Files
2025-01-25 12:35:59 +03:00

77853 lines
2.5 MiB
Plaintext
Executable File

diff -Nuar umbrello-kf6-15.08.1.orig/CMakeLists.txt umbrello-kf6-15.08.1/CMakeLists.txt
--- umbrello-kf6-15.08.1.orig/CMakeLists.txt 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/CMakeLists.txt 2015-10-08 11:48:59.471089026 +0300
@@ -6,8 +6,8 @@
set (KDE_APPLICATIONS_VERSION_MICRO "1")
set(umbrello-kf6_VERSION_MAJOR "2")
-set(umbrello-kf6_VERSION_MINOR "17")
-set(umbrello-kf6_VERSION_PATCH ${KDE_APPLICATIONS_VERSION_MICRO})
+set(umbrello-kf6_VERSION_MINOR "18")
+set(umbrello-kf6_VERSION_PATCH "99")
option(BUILD_KF5 "Build for KDE Frameworks 5" OFF)
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/actor.cpp umbrello-kf6-15.08.1/umbrello/actor.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/actor.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/actor.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,67 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "actor.h"
-
-/**
- * Constructs an Actor.
- *
- * @param name The name of the Actor.
- * @param id The unique id to assign to this Actor.
- */
-UMLActor::UMLActor(const QString & name, Uml::ID::Type id)
- : UMLCanvasObject(name, id)
-{
- init();
-}
-
-/**
- * Standard destructor.
- */
-UMLActor::~UMLActor()
-{
-}
-
-/**
- * Initializes key variables of the class.
- */
-void UMLActor::init()
-{
- m_BaseType = UMLObject::ot_Actor;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLActor::clone() const
-{
- UMLActor *clone = new UMLActor();
- UMLObject::copyInto(clone);
- return clone;
-}
-
-/**
- * Creates the <UML:Actor> XMI element.
- */
-void UMLActor::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement actorElement = UMLObject::save(QLatin1String("UML:Actor"), qDoc);
- qElement.appendChild(actorElement);
-}
-
-/**
- * Loads the <UML:Actor> XMI element (empty).
- */
-bool UMLActor::load(QDomElement& element)
-{
- Q_UNUSED(element);
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/actor.h umbrello-kf6-15.08.1/umbrello/actor.h
--- umbrello-kf6-15.08.1.orig/umbrello/actor.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/actor.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,44 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ACTOR_H
-#define ACTOR_H
-
-#include "umlcanvasobject.h"
-
-/**
- * This class contains the non-graphical information required for a UML Actor.
- * This class inherits from @ref UMLCanvasObject which contains most of the
- * information.
- * The @ref UMLDoc class creates instances of this type.
- *
- * @short Information for a non-graphical UML Actor.
- * @author Paul Hensgen <phensgen@techie.com>
- * @see UMLCanvasObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLActor : public UMLCanvasObject
-{
- Q_OBJECT
-public:
- explicit UMLActor(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLActor();
-
- virtual void init();
-
- virtual UMLObject* clone() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
-protected:
- bool load(QDomElement & element);
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/artifact.cpp umbrello-kf6-15.08.1/umbrello/artifact.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/artifact.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/artifact.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,90 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "artifact.h"
-#include "association.h"
-#include "clipboard/idchangelog.h"
-
-#include <KLocalizedString>
-
-/**
- * Sets up an Artifact.
- * @param name The name of the Concept.
- * @param id The unique id of the Concept.
- */
-UMLArtifact::UMLArtifact(const QString & name, Uml::ID::Type id)
- : UMLPackage(name, id),
- m_drawAsType(defaultDraw)
-{
- m_BaseType = UMLObject::ot_Artifact;
-}
-
-/**
- * Standard deconstructor.
- */
-UMLArtifact::~UMLArtifact()
-{
-}
-
-/**
- * Make a clone of this object.
- * @return the cloned object
- */
-UMLObject* UMLArtifact::clone() const
-{
- UMLArtifact *clone = new UMLArtifact();
- UMLObject::copyInto(clone);
- return clone;
-}
-
-/**
- * Creates the UML:Artifact element including its operations,
- * attributes and templates
- * @param qDoc the xml document
- * @param qElement the xml element
- */
-void UMLArtifact::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement artifactElement = UMLObject::save(QLatin1String("UML:Artifact"), qDoc);
- artifactElement.setAttribute(QLatin1String("drawas"), m_drawAsType);
- qElement.appendChild(artifactElement);
-}
-
-/**
- * Loads the UML:Artifact element including its operations,
- * attributes and templates.
- * @param element the xml element to load
- * @return the success status of the operation
- */
-bool UMLArtifact::load(QDomElement& element)
-{
- QString drawAs = element.attribute(QLatin1String("drawas"), QLatin1String("0"));
- m_drawAsType = (Draw_Type)drawAs.toInt();
- return true;
-}
-
-/**
- * Sets m_drawAsType for which method to draw the artifact as.
- * @param type the draw type
- */
-void UMLArtifact::setDrawAsType(Draw_Type type)
-{
- m_drawAsType = type;
-}
-
-/**
- * Returns the value of m_drawAsType.
- * @return the value of the draw type attribute
- */
-UMLArtifact::Draw_Type UMLArtifact::getDrawAsType()
-{
- return m_drawAsType;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/artifact.h umbrello-kf6-15.08.1/umbrello/artifact.h
--- umbrello-kf6-15.08.1.orig/umbrello/artifact.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/artifact.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,66 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ARTIFACT_H
-#define ARTIFACT_H
-
-#include "package.h"
-
-/**
- * This class contains the non-graphical information required for a UML
- * Artifact.
- * This class inherits from @ref UMLCanvasObject which contains most of the
- * information.
- *
- * @short Non-graphical information for a Artifact.
- * @author Jonathan Riddell
- * @see UMLCanvasObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLArtifact : public UMLPackage
-{
- Q_OBJECT
-public:
-
- /**
- * Artifacts can be drawn using one of several icons.
- */
- enum Draw_Type {
- defaultDraw,
- file,
- library,
- table
- };
-
- explicit UMLArtifact(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLArtifact();
-
- virtual UMLObject* clone() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- void setDrawAsType(Draw_Type type);
-
- Draw_Type getDrawAsType();
-
-protected:
-
- bool load(QDomElement & element);
-
-private:
-
- /**
- * Artifacts can be drawn as one of several different icons,
- * this value choosing how to draw them.
- */
- Draw_Type m_drawAsType;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/association.cpp umbrello-kf6-15.08.1/umbrello/association.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/association.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/association.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,742 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "association.h"
-
-// app includes
-#include "debug_utils.h"
-#include "classifier.h"
-#include "classpropertiesdialog.h"
-#include "folder.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlrole.h"
-#include "uniqueid.h"
-#include "model_utils.h"
-#include "cmds.h"
-
-// kde includes
-#include <KLocalizedString>
-
-// qt includes
-#include <QPointer>
-#include <QRegExp>
-
-using namespace Uml;
-
-DEBUG_REGISTER(UMLAssociation)
-
-/**
- * Sets up an association.
- * A new unique ID is assigned internally.
- * @param type The AssociationType::Enum to construct.
- * @param roleA Pointer to the UMLObject in role A.
- * @param roleB Pointer to the UMLObject in role B.
- */
-UMLAssociation::UMLAssociation(Uml::AssociationType::Enum type,
- UMLObject * roleA, UMLObject * roleB)
- : UMLObject(QString())
-{
- init(type, roleA, roleB);
-
- m_pRole[RoleType::A]->setID(UniqueID::gen());
- m_pRole[RoleType::B]->setID(UniqueID::gen());
-}
-
-/**
- * Constructs an association - for loading only.
- * This constructor should not normally be used as it constructs
- * an incomplete association (i.e. the role objects are missing.)
- * @param type The AssociationType::Enum to construct.
- * Default: Unknown.
- */
-UMLAssociation::UMLAssociation(Uml::AssociationType::Enum type)
- : UMLObject(QString(), Uml::ID::Reserved)
-{
- init(type, NULL, NULL);
-}
-
-/**
- * Standard destructor.
- */
-UMLAssociation::~UMLAssociation()
-{
- if (m_pRole[RoleType::A] == NULL) {
- uError() << "UMLAssociation destructor: m_pRole[A] is NULL already";
- } else {
- delete m_pRole[RoleType::A];
- m_pRole[RoleType::A] = NULL;
- }
- if (m_pRole[RoleType::B] == NULL) {
- uError() << "UMLAssociation destructor: m_pRole[B] is NULL already";
- } else {
- delete m_pRole[RoleType::B];
- m_pRole[RoleType::B] = NULL;
- }
-}
-
-/**
- * Overloaded '==' operator
- */
-bool UMLAssociation::operator==(const UMLAssociation &rhs) const
-{
- if (this == &rhs) {
- return true;
- }
- return (UMLObject::operator== (rhs) &&
- m_AssocType == rhs.m_AssocType &&
- m_Name == rhs.m_Name &&
- m_pRole[RoleType::A] == rhs.m_pRole[RoleType::A] &&
- m_pRole[RoleType::B] == rhs.m_pRole[RoleType::B]);
-}
-
-/**
- * Returns the AssociationType::Enum of the UMLAssociation.
- * @return The AssociationType::Enum of the UMLAssociation.
- */
-Uml::AssociationType::Enum UMLAssociation::getAssocType() const
-{
- return m_AssocType;
-}
-
-/**
- * Returns a String representation of this UMLAssociation.
- */
-QString UMLAssociation::toString() const
-{
- QString string;
- if(m_pRole[RoleType::A])
- {
- string += m_pRole[RoleType::A]->object()->name();
- string += QLatin1Char(':');
- string += m_pRole[RoleType::A]->name();
- }
- string += QLatin1Char(':') + Uml::AssociationType::toStringI18n(m_AssocType) + QLatin1Char(':');
- if(m_pRole[RoleType::B])
- {
- string += m_pRole[RoleType::B]->object()->name();
- string += QLatin1Char(':');
- string += m_pRole[RoleType::B]->name();
- }
- return string;
-}
-
-/**
- * Resolve types. Required when dealing with foreign XMI files.
- * Needs to be called after all UML objects are loaded from file.
- * Overrides the method from UMLObject.
- * Calls resolveRef() for each role.
- * @return True for success.
- */
-bool UMLAssociation::resolveRef()
-{
- bool successA = getUMLRole(RoleType::A)->resolveRef();
- bool successB = getUMLRole(RoleType::B)->resolveRef();
- if (successA && successB) {
- UMLObject *objA = getUMLRole(RoleType::A)->object();
- UMLObject *objB = getUMLRole(RoleType::B)->object();
- // Check if need to change the assoc type to Realization
- if (isRealization(objA, objB)) {
- m_AssocType = Uml::AssociationType::Realization;
- }
- m_pUMLPackage->addAssocToConcepts(this);
- return true;
- }
- return false;
-}
-
-/**
- * Creates the <UML:Generalization> or <UML:Association> XMI element
- * including its role objects.
- */
-void UMLAssociation::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- if (m_AssocType == Uml::AssociationType::Generalization) {
- QDomElement assocElement = UMLObject::save(QLatin1String("UML:Generalization"), qDoc);
- assocElement.setAttribute(QLatin1String("discriminator"), QString());
- assocElement.setAttribute(QLatin1String("child"), Uml::ID::toString(getObjectId(RoleType::A)));
- assocElement.setAttribute(QLatin1String("parent"), Uml::ID::toString(getObjectId(RoleType::B)));
- qElement.appendChild(assocElement);
- return;
- }
- if (m_AssocType == Uml::AssociationType::Realization) {
- QDomElement assocElement = UMLObject::save(QLatin1String("UML:Abstraction"), qDoc);
- assocElement.setAttribute(QLatin1String("client"), Uml::ID::toString(getObjectId(RoleType::A)));
- assocElement.setAttribute(QLatin1String("supplier"), Uml::ID::toString(getObjectId(RoleType::B)));
- qElement.appendChild(assocElement);
- return;
- }
- if (m_AssocType == Uml::AssociationType::Dependency) {
- QDomElement assocElement = UMLObject::save(QLatin1String("UML:Dependency"), qDoc);
- assocElement.setAttribute(QLatin1String("client"), Uml::ID::toString(getObjectId(RoleType::A)));
- assocElement.setAttribute(QLatin1String("supplier"), Uml::ID::toString(getObjectId(RoleType::B)));
- qElement.appendChild(assocElement);
- return;
- }
- if (m_AssocType == Uml::AssociationType::Child2Category) {
- QDomElement assocElement = UMLObject::save(QLatin1String("UML:Child2Category"), qDoc);
- assocElement.setAttribute(QLatin1String("client"), Uml::ID::toString(getObjectId(RoleType::A)));
- assocElement.setAttribute(QLatin1String("supplier"), Uml::ID::toString(getObjectId(RoleType::B)));
- qElement.appendChild(assocElement);
- return;
- }
- if (m_AssocType == Uml::AssociationType::Category2Parent) {
- QDomElement assocElement = UMLObject::save(QLatin1String("UML:Category2Parent"), qDoc);
- assocElement.setAttribute(QLatin1String("client"), Uml::ID::toString(getObjectId(RoleType::A)));
- assocElement.setAttribute(QLatin1String("supplier"), Uml::ID::toString(getObjectId(RoleType::B)));
- qElement.appendChild(assocElement);
- return;
- }
-
- QDomElement associationElement = UMLObject::save(QLatin1String("UML:Association"), qDoc);
- QDomElement connElement = qDoc.createElement(QLatin1String("UML:Association.connection"));
- getUMLRole(RoleType::A)->saveToXMI (qDoc, connElement);
- getUMLRole(RoleType::B)->saveToXMI (qDoc, connElement);
- associationElement.appendChild (connElement);
- qElement.appendChild(associationElement);
-}
-
-bool UMLAssociation::showPropertiesDialog(QWidget *parent)
-{
- QPointer<ClassPropertiesDialog> dlg = new ClassPropertiesDialog(parent, this, true);
- bool modified = false;
- if (dlg->exec()) {
- modified = true;
- }
- dlg->close();
- delete dlg;
- return modified;
-}
-
-/**
- * Creates the <UML:Generalization> or <UML:Association> XMI element
- * including its role objects.
- */
-bool UMLAssociation::load(QDomElement & element)
-{
- if (id() == Uml::ID::None)
- return false; // old style XMI file. No real info in this association.
-
- UMLDoc * doc = UMLApp::app()->document();
- UMLObject * obj[2] = { NULL, NULL };
- if (m_AssocType == Uml::AssociationType::Generalization ||
- m_AssocType == Uml::AssociationType::Realization ||
- m_AssocType == Uml::AssociationType::Dependency ||
- m_AssocType == Uml::AssociationType::Child2Category ||
- m_AssocType == Uml::AssociationType::Category2Parent) {
- QString general = element.attribute(QLatin1String("general"));
- if (!general.isEmpty()) {
- UMLClassifier *owningClassifier = dynamic_cast<UMLClassifier*>(m_pUMLPackage);
- if (owningClassifier == NULL){
- uWarning() << "Cannot load UML2 generalization: m_pUMLPackage is expected "
- << "to be the owning classifier (=client)";
- return false;
- }
- m_pRole[RoleType::A]->setObject(owningClassifier);
- m_pRole[RoleType::B]->setSecondaryId(general); // defer resolution to resolveRef()
- owningClassifier->addAssociationEnd(this);
- m_pUMLPackage = m_pUMLPackage->umlPackage(); // reparent
- m_pUMLPackage->addObject(this);
- return true;
- }
- for (unsigned r = RoleType::A; r <= RoleType::B; ++r) {
- const QString fetch = (m_AssocType == Uml::AssociationType::Generalization ?
- r == RoleType::A ? QLatin1String("child") : QLatin1String("parent")
- : r == RoleType::A ? QLatin1String("client") : QLatin1String("supplier"));
- QString roleIdStr = element.attribute(fetch);
- if (roleIdStr.isEmpty()) {
- // Might be given as a child node instead - see below.
- continue;
- }
-
- // set umlobject of role if possible (else defer resolution)
- obj[r] = doc->findObjectById(Uml::ID::fromString(roleIdStr));
- Uml::RoleType::Enum role = Uml::RoleType::fromInt(r);
- if (obj[r] == NULL) {
- m_pRole[role]->setSecondaryId(roleIdStr); // defer to resolveRef()
- } else {
- m_pRole[role]->setObject(obj[r]);
- if (m_pUMLPackage == NULL) {
- Uml::ModelType::Enum mt = Model_Utils::convert_OT_MT(obj[r]->baseType());
- m_pUMLPackage = doc->rootFolder(mt);
- DEBUG(DBG_SRC) << "assoctype " << m_AssocType
- << ": setting model type " << Uml::ModelType::toString(mt);
- }
- }
- }
- if (obj[RoleType::A] == NULL || obj[RoleType::B] == NULL) {
- for (QDomNode node = element.firstChild(); !node.isNull();
- node = node.nextSibling()) {
- if (node.isComment())
- continue;
- QDomElement tempElement = node.toElement();
- QString tag = tempElement.tagName();
- if (Model_Utils::isCommonXMIAttribute(tag))
- continue;
- // Permitted tag names:
- // roleA: "child" "subtype" "client"
- // roleB: "parent" "supertype" "supplier"
- QString idStr = tempElement.attribute(QLatin1String("xmi.id"));
- if (idStr.isEmpty())
- idStr = tempElement.attribute(QLatin1String("xmi.idref"));
- if (idStr.isEmpty()) {
- QDomNode inner = node.firstChild();
- QDomElement tmpElem = inner.toElement();
- idStr = tmpElem.attribute(QLatin1String("xmi.id"));
- if (idStr.isEmpty())
- idStr = tmpElem.attribute(QLatin1String("xmi.idref"));
- }
- if (idStr.isEmpty()) {
- uError() << "type " << m_AssocType
- << ", id " << Uml::ID::toString(id()) << ": "
- << "xmi id not given for " << tag;
- continue;
- }
- // Since we know for sure that we're dealing with a non
- // umbrello-kf6 file, use deferred resolution unconditionally.
- if (UMLDoc::tagEq(tag, QLatin1String("child")) ||
- UMLDoc::tagEq(tag, QLatin1String("subtype")) ||
- UMLDoc::tagEq(tag, QLatin1String("client"))) {
- getUMLRole(RoleType::A)->setSecondaryId(idStr);
- } else {
- getUMLRole(RoleType::B)->setSecondaryId(idStr);
- }
- }
- }
-
- // it is a realization if either endpoint is an interface
- if (isRealization(obj[RoleType::A], obj[RoleType::B])) {
- m_AssocType = Uml::AssociationType::Realization;
- }
- return true;
- }
-
- for (QDomNode node = element.firstChild(); !node.isNull();
- node = node.nextSibling()) {
- // uml13.dtd compliant format (new style)
- if (node.isComment())
- continue;
- QDomElement tempElement = node.toElement();
- QString tag = tempElement.tagName();
- if (Model_Utils::isCommonXMIAttribute(tag))
- continue;
- if (!UMLDoc::tagEq(tag, QLatin1String("Association.connection")) &&
- !UMLDoc::tagEq(tag, QLatin1String("Association.end")) && // Embarcadero's Describe
- !UMLDoc::tagEq(tag, QLatin1String("Namespace.ownedElement")) &&
- !UMLDoc::tagEq(tag, QLatin1String("Namespace.contents"))) {
- uWarning() << "unknown child node " << tag;
- continue;
- }
- // Load role A.
- QDomNode nodeA = tempElement.firstChild();
- while (nodeA.isComment())
- nodeA = nodeA.nextSibling();
- tempElement = nodeA.toElement();
- if (tempElement.isNull()) {
- uWarning() << "UML:Association : element (A) is Null";
- return false;
- }
- tag = tempElement.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("NavigableEnd"))) { // Embarcadero's Describe
- m_AssocType = Uml::AssociationType::UniAssociation;
- } else if (!UMLDoc::tagEq(tag, QLatin1String("AssociationEndRole")) &&
- !UMLDoc::tagEq(tag, QLatin1String("AssociationEnd"))) {
- uWarning() << "unknown child (A) tag " << tag;
- return false;
- }
- if (! getUMLRole(RoleType::A)->loadFromXMI(tempElement))
- return false;
- // Load role B.
- QDomNode nodeB = nodeA.nextSibling();
- while (nodeB.isComment())
- nodeB = nodeB.nextSibling();
- tempElement = nodeB.toElement();
- if (tempElement.isNull()) {
- uWarning() << "UML:Association : element (B) is Null";
- return false;
- }
- tag = tempElement.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("NavigableEnd"))) { // Embarcadero's Describe
- m_AssocType = Uml::AssociationType::UniAssociation;
- } else if (!UMLDoc::tagEq(tag, QLatin1String("AssociationEndRole")) &&
- !UMLDoc::tagEq(tag, QLatin1String("AssociationEnd"))) {
- uWarning() << "unknown child (B) tag " << tag;
- return false;
- }
- if (! getUMLRole(RoleType::B)->loadFromXMI(tempElement))
- return false;
-
- if (m_pUMLPackage == NULL) {
- Uml::ModelType::Enum mt = Model_Utils::convert_OT_MT(getObject(RoleType::B)->baseType());
- m_pUMLPackage = doc->rootFolder(mt);
- DEBUG(DBG_SRC) << "setting model type " << Uml::ModelType::toString(mt);
- }
-
- // setting the association type:
- //
- // In the old days, we could just record this on the association,
- // and be done with it. But thats not how the UML13.dtd does things.
- // As a result, we are checking roleA for information about the
- // parent association (!) which by this point in the parse, should
- // be set. However, the information that the roles are allowed to have
- // is not complete, so we need to finish the analysis here.
-
- // find self-associations
- if (m_AssocType == Uml::AssociationType::Association && getObjectId(RoleType::A) == getObjectId(RoleType::B))
- m_AssocType = Uml::AssociationType::Association_Self;
-
- // fall-back default type
- if (m_AssocType == Uml::AssociationType::Unknown) {
- m_AssocType = Uml::AssociationType::Association;
- }
-
- return true;
- }
-
- // From here on it's old-style stuff.
- QString assocTypeStr = element.attribute(QLatin1String("assoctype"), QLatin1String("-1"));
- Uml::AssociationType::Enum assocType = Uml::AssociationType::Unknown;
- if (assocTypeStr[0] >= QLatin1Char('a') && assocTypeStr[0] <= QLatin1Char('z')) {
- // In an earlier version, the natural assoctype names were saved.
- const char *assocTypeString[] = {
- "generalization", // Uml::AssociationType::Generalization
- "aggregation", // Uml::AssociationType::Aggregation
- "dependency", // Uml::AssociationType::Dependency
- "association", // Uml::AssociationType::Association
- "associationself", // Uml::AssociationType::Association_Self
- "collmessage", // Uml::AssociationType::Coll_Message
- "seqmessage", // Uml::AssociationType::Seq_Message
- "collmessageself", // Uml::AssociationType::Coll_Message_Self
- "seqmessageself", // Uml::AssociationType::Seq_Message_Self
- "implementation", // Uml::AssociationType::Implementation
- "composition", // Uml::AssociationType::Composition
- "realization", // Uml::AssociationType::Realization
- "uniassociation", // Uml::AssociationType::UniAssociation
- "anchor", // Uml::AssociationType::Anchor
- "state", // Uml::AssociationType::State
- "activity", // Uml::AssociationType::Activity
- "exception", // Uml::AssociationType::Exception
- "category2parent" // Uml::AssociationType::Category2Parent
- "child2category" // Uml::AssociationType::Child2Category
- "relationship" // Uml::AssociationType::Relationship
- };
- const int arraySize = sizeof(assocTypeString) / sizeof(char*);
- DEBUG(DBG_SRC) << "AssociationType string array size = " << arraySize;
-
- int index;
- for (index = 0; index < arraySize; ++index)
- if (assocTypeStr == QString::fromLatin1(assocTypeString[index]))
- break;
- if (index < arraySize)
- assocType = Uml::AssociationType::fromInt(index);
- } else {
- int assocTypeNum = assocTypeStr.toInt();
- if (assocTypeNum < (int)Uml::AssociationType::Generalization || // first enum
- assocTypeNum >= (int)Uml::AssociationType::Reserved) { // last enum
- uWarning() << "bad assoctype of UML:AssociationType::Enum " << Uml::ID::toString(id());
- return false;
- }
- assocType = Uml::AssociationType::fromInt(assocTypeNum);
- }
- setAssociationType(assocType);
-
- Uml::ID::Type roleAObjID = Uml::ID::fromString(element.attribute(QLatin1String("rolea"), QLatin1String("-1")));
- Uml::ID::Type roleBObjID = Uml::ID::fromString(element.attribute(QLatin1String("roleb"), QLatin1String("-1")));
- if (assocType == Uml::AssociationType::Aggregation ||
- assocType == Uml::AssociationType::Composition) {
- // Flip roles to compensate for changed diamond logic in AssociationLine.
- // For further explanations see AssociationWidget::loadFromXMI.
- Uml::ID::Type tmp = roleAObjID;
- roleAObjID = roleBObjID;
- roleBObjID = tmp;
- }
-
- UMLObject * objA = doc->findObjectById(roleAObjID);
- UMLObject * objB = doc->findObjectById(roleBObjID);
-
- if(objA)
- getUMLRole(RoleType::A)->setObject(objA);
- else
- return false;
-
- if(objB)
- getUMLRole(RoleType::B)->setObject(objB);
- else
- return false;
-
- setMultiplicity(element.attribute(QLatin1String("multia")), RoleType::A);
- setMultiplicity(element.attribute(QLatin1String("multib")), RoleType::B);
-
- setRoleName(element.attribute(QLatin1String("namea")), RoleType::A);
- setRoleName(element.attribute(QLatin1String("nameb")), RoleType::B);
-
- setRoleDoc(element.attribute(QLatin1String("doca")), RoleType::A);
- setRoleDoc(element.attribute(QLatin1String("docb")), RoleType::B);
-
- // Visibility defaults to Public if it cant set it here..
- QString visibilityA = element.attribute(QLatin1String("visibilitya"), QLatin1String("0"));
- QString visibilityB = element.attribute(QLatin1String("visibilityb"), QLatin1String("0"));
- int vis = visibilityA.toInt();
- if (vis >= 200) // bkwd compat.
- vis -= 200;
- setVisibility((Uml::Visibility::Enum)vis, RoleType::A);
- vis = visibilityB.toInt();
- if (vis >= 200) // bkwd compat.
- vis -= 200;
- setVisibility((Uml::Visibility::Enum)vis, RoleType::B);
-
- // Changeability defaults to Changeable if it cant set it here..
- QString changeabilityA = element.attribute(QLatin1String("changeabilitya"), QLatin1String("0"));
- QString changeabilityB = element.attribute(QLatin1String("changeabilityb"), QLatin1String("0"));
- if (changeabilityA.toInt() > 0)
- setChangeability(Uml::Changeability::fromInt(changeabilityA.toInt()), RoleType::A);
- if (changeabilityB.toInt() > 0)
- setChangeability(Uml::Changeability::fromInt(changeabilityB.toInt()), RoleType::B);
-
- return true;
-}
-
-/**
- * Returns the UMLObject assigned to the given role.
- * @return Pointer to the UMLObject in the given role.
- */
-UMLObject* UMLAssociation::getObject(Uml::RoleType::Enum role) const
-{
- if (m_pRole[role] == NULL)
- return NULL;
- return m_pRole[role]->object();
-}
-
-/**
- * Returns the ID of the UMLObject assigned to the given role.
- * Shorthand for getObject(role)->ID().
- * @return ID of the UMLObject in the given role.
- */
-Uml::ID::Type UMLAssociation::getObjectId(Uml::RoleType::Enum role) const
-{
- UMLRole *roleObj = m_pRole[role];
- if (roleObj == NULL)
- return Uml::ID::None;
- UMLObject *o = roleObj->object();
- if (o == NULL) {
- QString auxID = roleObj->secondaryId();
- if (auxID.isEmpty()) {
- uError() << "role " << role << ": getObject returns NULL";
- return Uml::ID::None;
- } else {
- DEBUG(DBG_SRC) << "role " << role << ": using secondary ID " << auxID;
- return Uml::ID::fromString(auxID);
- }
- }
- return o->id();
-}
-
-/**
- * Returns the ID of the UMLObject assigned to the given role.
- * CURRENTLY UNUSED.
- * @return ID of the UMLObject of the given role.
- */
-Uml::ID::Type UMLAssociation::getRoleId(RoleType::Enum role) const
-{
- return m_pRole[role]->id();
-}
-
-/**
- * Returns the changeability.
- */
-Uml::Changeability::Enum UMLAssociation::changeability(Uml::RoleType::Enum role) const
-{
- return m_pRole[role]->changeability();
-}
-
-/**
- * Returns the Visibility of the given role.
- * @return Visibility of the given role.
- */
-Uml::Visibility::Enum UMLAssociation::visibility(Uml::RoleType::Enum role) const
-{
- return m_pRole[role]->visibility();
-}
-
-/**
- * Returns the multiplicity assigned to the given role.
- * @return The multiplicity assigned to the given role.
- */
-QString UMLAssociation::getMultiplicity(Uml::RoleType::Enum role) const
-{
- return m_pRole[role]->multiplicity();
-}
-
-/**
- * Returns the name assigned to the role A.
- * @return The name assigned to the given role.
- */
-QString UMLAssociation::getRoleName(Uml::RoleType::Enum role) const
-{
- return m_pRole[role]->name();
-}
-
-/**
- * Returns the documentation assigned to the given role.
- * @return Documentation text of given role.
- */
-QString UMLAssociation::getRoleDoc(Uml::RoleType::Enum role) const
-{
- return m_pRole[role]->doc();
-}
-
-/**
- * Get the underlying UMLRole object for the given role.
- * @return Pointer to the UMLRole object for the given role.
- */
-UMLRole * UMLAssociation::getUMLRole(Uml::RoleType::Enum role) const
-{
- return m_pRole[role];
-}
-
-/**
- * Set the attribute m_bOldLoadMode.
- * @param value the new value to set
- */
-void UMLAssociation::setOldLoadMode(bool value /* = true */)
-{
- m_bOldLoadMode = value;
-}
-
-/**
- * Return the backward compatibility flag for loading files.
- */
-bool UMLAssociation::getOldLoadMode() const
-{
- return m_bOldLoadMode;
-}
-
-/**
- * Sets the assocType of the UMLAssociation.
- * @param assocType The AssociationType::Enum of the UMLAssociation.
- */
-void UMLAssociation::setAssociationType(Uml::AssociationType::Enum assocType)
-{
- m_AssocType = assocType;
- if (m_AssocType == Uml::AssociationType::UniAssociation)
- {
- // In this case we need to auto-set the multiplicity/rolenames
- // of the roles
-#ifdef VERBOSE_DEBUGGING
- DEBUG(DBG_SRC) << " A new uni-association has been created.";
-#endif
- }
- UMLObject::emitModified();
-}
-
-/**
- * Sets the UMLObject playing the given role in the association.
- * @param obj Pointer to the UMLObject of the given role.
- * @param role The Uml::RoleType::Enum played by the association
- */
-void UMLAssociation::setObject(UMLObject *obj, Uml::RoleType::Enum role)
-{
- m_pRole[role]->setObject(obj);
-}
-
-/**
- * Sets the visibility of the given role of the UMLAssociation.
- * @param value Visibility of role.
- * @param role The Uml::RoleType::Enum to which the visibility is being applied
- */
-void UMLAssociation::setVisibility(Visibility::Enum value, Uml::RoleType::Enum role)
-{
- m_pRole[role]->setVisibility(value);
-}
-
-/**
- * Sets the changeability of the given role of the UMLAssociation.
- * @param value Changeability_Type of the given role.
- * @param role The Uml::RoleType::Enum to which the changeability is being set
- */
-void UMLAssociation::setChangeability(Uml::Changeability::Enum value, Uml::RoleType::Enum role)
-{
- m_pRole[role]->setChangeability(value);
-}
-
-/**
- * Sets the multiplicity of the given role of the UMLAssociation.
- * @param multi The multiplicity of the given role.
- * @param role The Uml::RoleType::Enum to which the multiplicity is being applied
- */
-void UMLAssociation::setMultiplicity(const QString &multi, Uml::RoleType::Enum role)
-{
- if (m_pRole[role]->multiplicity() != multi) {
- UMLApp::app()->executeCommand(new CmdChangeMultiplicity(m_pRole[role], multi));
- }
-}
-
-/**
- * Sets the name of the given role of the UMLAssociation.
- * @param roleName The name to set for the given role.
- * @param role The Uml::RoleType::Enum for which to set the name.
- */
-void UMLAssociation::setRoleName(const QString &roleName, Uml::RoleType::Enum role)
-{
- m_pRole[role]->setName(roleName);
-}
-
-/**
- * Sets the documentation on the given role in the association.
- * @param doc The string with the documentation.
- * @param role The Uml::RoleType::Enum to which the documentation is being applied
- */
-void UMLAssociation::setRoleDoc(const QString &doc, Uml::RoleType::Enum role)
-{
- m_pRole[role]->setDoc(doc);
-}
-
-/**
- * When the association type is "Generalization" and at least one of the
- * given objects an interface, then it is a "Realization".
- * @param objA UML object as role A
- * @param objB UML object as role B
- * @return flag whether association is a realization
- */
-bool UMLAssociation::isRealization(UMLObject* objA, UMLObject* objB) const
-{
- bool aIsInterface = false;
- if (objA && (objA->baseType() == UMLObject::ot_Interface)) {
- aIsInterface = true;
- }
- bool bIsInterface = false;
- if (objB && (objB->baseType() == UMLObject::ot_Interface)) {
- bIsInterface = true;
- }
- return (m_AssocType == Uml::AssociationType::Generalization) &&
- (aIsInterface || bIsInterface);
-}
-
-/**
- * Common initializations at construction time.
- * @param type The AssociationType::Enum to represent.
- * @param roleAObj Pointer to the role A UMLObject.
- * @param roleBObj Pointer to the role B UMLObject.
- */
-void UMLAssociation::init(Uml::AssociationType::Enum type, UMLObject *roleAObj, UMLObject *roleBObj)
-{
- m_AssocType = type;
- m_BaseType = ot_Association;
- m_Name = QString();
- m_bOldLoadMode = false;
- nrof_parent_widgets = -1;
- if (!UMLApp::app()->document()->loading()) {
- m_pUMLPackage = UMLApp::app()->document()->currentRoot();
- }
- m_pRole[RoleType::A] = new UMLRole (this, roleAObj, RoleType::A);
- m_pRole[RoleType::B] = new UMLRole (this, roleBObj, RoleType::B);
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/association.h umbrello-kf6-15.08.1/umbrello/association.h
--- umbrello-kf6-15.08.1.orig/umbrello/association.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/association.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,102 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ASSOCIATION_H
-#define ASSOCIATION_H
-
-#include "basictypes.h"
-#include "umlobject.h"
-
-#include <QDomDocument>
-#include <QDomElement>
-
-class UMLRole;
-
-/**
- * This class contains the non-graphic representation of an association.
- * An association can be a generalization, realization, simple association,
- * directed association, aggregation, or composition.
- *
- * @short Sets up association information.
- * @author Oliver Kellogg <okellogg@users.sourceforge.net>
- * @see UMLObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLAssociation : public UMLObject
-{
- Q_OBJECT
- friend class AssociationWidget;
-
-public:
- UMLAssociation(Uml::AssociationType::Enum type, UMLObject *roleA, UMLObject *roleB);
- explicit UMLAssociation(Uml::AssociationType::Enum type = Uml::AssociationType::Unknown);
-
- virtual ~UMLAssociation();
-
- bool operator==(const UMLAssociation &rhs) const;
-
- QString toString() const;
-
- UMLRole * getUMLRole(Uml::RoleType::Enum role) const;
- Uml::ID::Type getObjectId(Uml::RoleType::Enum role) const;
- Uml::ID::Type getRoleId(Uml::RoleType::Enum role) const;
-
- void setAssociationType(Uml::AssociationType::Enum assocType);
- Uml::AssociationType::Enum getAssocType() const;
-
- void setObject(UMLObject *obj, Uml::RoleType::Enum role);
- UMLObject* getObject(Uml::RoleType::Enum role) const;
-
- void setVisibility(Uml::Visibility::Enum value, Uml::RoleType::Enum role);
- Uml::Visibility::Enum visibility(Uml::RoleType::Enum role) const;
-
- void setChangeability(Uml::Changeability::Enum value, Uml::RoleType::Enum role);
- Uml::Changeability::Enum changeability(Uml::RoleType::Enum role) const;
-
- void setMultiplicity(const QString &multi, Uml::RoleType::Enum role);
- QString getMultiplicity(Uml::RoleType::Enum role) const;
-
- void setRoleName(const QString &roleName, Uml::RoleType::Enum role);
- QString getRoleName(Uml::RoleType::Enum role) const;
-
- void setRoleDoc(const QString &doc, Uml::RoleType::Enum role);
- QString getRoleDoc(Uml::RoleType::Enum role) const;
-
- void setOldLoadMode(bool value = true);
- bool getOldLoadMode() const;
-
- virtual UMLObject* clone() const { return NULL; }
-
- virtual bool resolveRef();
-
- void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
- virtual bool showPropertiesDialog(QWidget *parent = 0);
-
-protected:
-
- bool load(QDomElement& element);
-
- // keep track of number of parent widgets
- int nrof_parent_widgets;
-
- void init(Uml::AssociationType::Enum type, UMLObject *roleAObj, UMLObject *roleBObj);
-
- UMLRole * m_pRole[2];
- Uml::AssociationType::Enum m_AssocType;
- QString m_Name;
- bool m_bOldLoadMode;
-
-private:
-
- bool isRealization(UMLObject* objA, UMLObject* objB) const;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/attribute.cpp umbrello-kf6-15.08.1/umbrello/attribute.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/attribute.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/attribute.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,424 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "attribute.h"
-
-// app includes
-#include "debug_utils.h"
-#include "classifier.h"
-#include "operation.h"
-#include "umlobject.h"
-#include "umldoc.h"
-#include "uml.h"
-#include "folder.h"
-#include "umlattributedialog.h"
-#include "object_factory.h"
-
-/**
- * Sets up an attribute.
- *
- * @param parent The parent of this UMLAttribute.
- * @param name The name of this UMLAttribute.
- * @param id The unique id given to this UMLAttribute.
- * @param s The visibility of the UMLAttribute.
- * @param type The type of this UMLAttribute.
- * @param iv The initial value of the attribute.
- */
-UMLAttribute::UMLAttribute(UMLObject *parent,
- const QString& name, Uml::ID::Type id,
- Uml::Visibility::Enum s,
- UMLObject *type, const QString& iv)
- : UMLClassifierListItem(parent, name, id)
-{
- m_InitialValue = iv;
- m_BaseType = UMLObject::ot_Attribute;
- m_visibility = s;
- m_ParmKind = Uml::ParameterDirection::In;
- /* CHECK: Do we need this:
- if (type == NULL) {
- type = Object_Factory::createUMLObject(Uml::ot_Datatype, "undef");
- }
- */
- m_pSecondary = type;
-}
-
-/**
- * Sets up an attribute.
- *
- * @param parent The parent of this UMLAttribute.
- */
-UMLAttribute::UMLAttribute(UMLObject *parent) : UMLClassifierListItem(parent)
-{
- m_BaseType = UMLObject::ot_Attribute;
- m_visibility = Uml::Visibility::Private;
- m_ParmKind = Uml::ParameterDirection::In;
-}
-
-/**
- * Destructor.
- */
-UMLAttribute::~UMLAttribute()
-{
-}
-
-/**
- * Reimplementation of method from UMLObject is required as
- * an extra signal, attributeChanged(), is emitted.
- */
-void UMLAttribute::setName(const QString &name)
-{
- m_name = name;
- emit attributeChanged();
- UMLObject::emitModified();
-}
-
-/**
- * Reimplementation of method from UMLObject is required as
- * an extra signal, attributeChanged(), is emitted.
- */
-void UMLAttribute::setVisibility(Uml::Visibility::Enum s)
-{
- m_visibility = s;
- emit attributeChanged();
- UMLObject::emitModified();
-}
-
-/**
- * Returns The initial value of the UMLAttribute.
- *
- * @return The initial value of the Atrtibute.
- */
-QString UMLAttribute::getInitialValue() const
-{
- return m_InitialValue;
-}
-
-/**
- * Sets the initial value of the UMLAttribute.
- *
- * @param iv The initial value of the UMLAttribute.
- */
-void UMLAttribute::setInitialValue(const QString &iv)
-{
- if(m_InitialValue != iv) {
- m_InitialValue = iv;
- UMLObject::emitModified();
- }
-}
-
-void UMLAttribute::setParmKind (Uml::ParameterDirection::Enum pk)
-{
- m_ParmKind = pk;
-}
-
-Uml::ParameterDirection::Enum UMLAttribute::getParmKind() const
-{
- return m_ParmKind;
-}
-
-/**
- * Returns a string representation of the UMLAttribute.
- *
- * @param sig If true will show the attribute type and initial value.
- * @return Returns a string representation of the UMLAttribute.
- */
-QString UMLAttribute::toString(Uml::SignatureType::Enum sig)
-{
- QString s;
-
- if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::NoSig) {
- s = Uml::Visibility::toString(m_visibility, true) + QLatin1Char(' ');
- }
-
- if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::SigNoVis) {
- // Determine whether the type name needs to be scoped.
- UMLObject *owningObject = static_cast<UMLObject*>(parent());
- if (owningObject->baseType() == UMLObject::ot_Operation) {
- // The immediate parent() is the UMLOperation but we want
- // the UMLClassifier:
- owningObject = static_cast<UMLObject*>(owningObject->parent());
- }
- UMLClassifier *ownParent = dynamic_cast<UMLClassifier*>(owningObject);
- if (ownParent == NULL) {
- uError() << "parent " << owningObject->name()
- << " is not a UMLClassifier";
- return QString();
- }
- QString typeName;
- UMLClassifier *type = UMLClassifierListItem::getType();
- if (type) {
- UMLPackage *typeScope = type->umlPackage();
- if (typeScope != ownParent && typeScope != ownParent->umlPackage())
- typeName = type->fullyQualifiedName();
- else
- typeName = type->name();
- }
- // The default direction, "in", is not mentioned.
- // Perhaps we should include a pd_Unspecified in
- // Uml::ParameterDirection::Enum to have better control over this.
- if (m_ParmKind == Uml::ParameterDirection::InOut)
- s += QLatin1String("inout ");
- else if (m_ParmKind == Uml::ParameterDirection::Out)
- s += QLatin1String("out ");
- // Construct the attribute text.
- QString string = s + name() + QLatin1String(" : ") + typeName;
- if (m_InitialValue.length() > 0)
- string += QLatin1String(" = ") + m_InitialValue;
- return string;
- }
- return s + name();
-}
-
-/**
- * Reimplement method from UMLObject.
- */
-QString UMLAttribute::getFullyQualifiedName(const QString& separator,
- bool includeRoot /* = false */) const
-{
- UMLOperation *op = NULL;
- UMLObject *owningObject = static_cast<UMLObject*>(parent());
- if (owningObject->baseType() == UMLObject::ot_Operation) {
- op = static_cast<UMLOperation*>(owningObject);
- owningObject = static_cast<UMLObject*>(owningObject->parent());
- }
- UMLClassifier *ownParent = dynamic_cast<UMLClassifier*>(owningObject);
- if (ownParent == NULL) {
- uError() << name() << ": parent " << owningObject->name()
- << " is not a UMLClassifier";
- return QString();
- }
- QString tempSeparator = separator;
- if (tempSeparator.isEmpty())
- tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
- QString fqn = ownParent->fullyQualifiedName(tempSeparator, includeRoot);
- if (op)
- fqn.append(tempSeparator + op->name());
- fqn.append(tempSeparator + name());
- return fqn;
-}
-
-/**
- * Overloaded '==' operator
- */
-bool UMLAttribute::operator==(const UMLAttribute &rhs) const
-{
- if(this == &rhs)
- return true;
-
- if(!UMLObject::operator==(rhs))
- return false;
-
- // The type name is the only distinguishing criterion.
- // (Some programming languages might support more, but others don't.)
- if (m_pSecondary != rhs.m_pSecondary)
- return false;
-
- return true;
-}
-
-/**
- * Copy the internal presentation of this object into the UMLAttribute
- * object.
- */
-void UMLAttribute::copyInto(UMLObject *lhs) const
-{
- UMLAttribute *target = static_cast<UMLAttribute*>(lhs);
- // call the parent first.
- UMLClassifierListItem::copyInto(target);
-
- // Copy all datamembers
- target->m_pSecondary = m_pSecondary;
- target->m_SecondaryId = m_SecondaryId;
- target->m_InitialValue = m_InitialValue;
- target->m_ParmKind = m_ParmKind;
-}
-
-/**
- * Make a clone of the UMLAttribute.
- */
-UMLObject* UMLAttribute::clone() const
-{
- //FIXME: The new attribute should be slaved to the NEW parent not the old.
- UMLAttribute *clone = new UMLAttribute(static_cast<UMLObject*>(parent()));
- copyInto(clone);
-
- return clone;
-}
-
-/**
- * Creates the <UML:Attribute> XMI element.
- */
-void UMLAttribute::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement attributeElement = UMLObject::save(QLatin1String("UML:Attribute"), qDoc);
- if (m_pSecondary == NULL) {
- uDebug() << name() << ": m_pSecondary is NULL, m_SecondaryId is '"
- << m_SecondaryId << "'";
- } else {
- attributeElement.setAttribute(QLatin1String("type"), Uml::ID::toString(m_pSecondary->id()));
- }
- if (! m_InitialValue.isEmpty())
- attributeElement.setAttribute(QLatin1String("initialValue"), m_InitialValue);
- qElement.appendChild(attributeElement);
-}
-
-/**
- * Loads the <UML:Attribute> XMI element.
- */
-bool UMLAttribute::load(QDomElement & element)
-{
- m_SecondaryId = element.attribute(QLatin1String("type"));
- // We use the m_SecondaryId as a temporary store for the xmi.id
- // of the attribute type model object.
- // It is resolved later on, when all classes have been loaded.
- // This deferred resolution is required because the xmi.id may
- // be a forward reference, i.e. it may identify a model object
- // that has not yet been loaded.
- if (m_SecondaryId.isEmpty()) {
- // Perhaps the type is stored in a child node:
- QDomNode node = element.firstChild();
- while (!node.isNull()) {
- if (node.isComment()) {
- node = node.nextSibling();
- continue;
- }
- QDomElement tempElement = node.toElement();
- QString tag = tempElement.tagName();
- if (!UMLDoc::tagEq(tag, QLatin1String("type"))) {
- node = node.nextSibling();
- continue;
- }
- m_SecondaryId = Model_Utils::getXmiId(tempElement);
- if (m_SecondaryId.isEmpty())
- m_SecondaryId = tempElement.attribute(QLatin1String("xmi.idref"));
- if (m_SecondaryId.isEmpty()) {
- QString href = tempElement.attribute(QLatin1String("href"));
- if (href.isEmpty()) {
- QDomNode inner = node.firstChild();
- QDomElement tmpElem = inner.toElement();
- m_SecondaryId = Model_Utils::getXmiId(tmpElem);
- if (m_SecondaryId.isEmpty())
- m_SecondaryId = tmpElem.attribute(QLatin1String("xmi.idref"));
- } else {
- int hashpos = href.lastIndexOf(QChar(QLatin1Char('#')));
- if (hashpos < 0) {
- uDebug() << name() << ": cannot find type " << href;
- } else {
- QString typeName = href.mid(hashpos + 1);
- UMLFolder *dtFolder = UMLApp::app()->document()->datatypeFolder();
- m_pSecondary = Model_Utils::findUMLObject(dtFolder->containedObjects(),
- typeName, UMLObject::ot_Datatype);
- if (!m_pSecondary) {
- m_pSecondary = Object_Factory::createUMLObject(UMLObject::ot_Datatype,
- typeName, dtFolder);
- }
- }
- }
- }
- break;
- }
- if (m_SecondaryId.isEmpty()) {
- uDebug() << name() << ": cannot find type.";
- }
- }
- m_InitialValue = element.attribute(QLatin1String("initialValue"));
- if (m_InitialValue.isEmpty()) {
- // for backward compatibility
- m_InitialValue = element.attribute(QLatin1String("value"));
- }
- return true;
-}
-
-/**
- * Display the properties configuration dialog for the attribute.
- */
-bool UMLAttribute::showPropertiesDialog(QWidget* parent)
-{
- UMLAttributeDialog dialog(parent, this);
- return dialog.exec();
-}
-
-/**
- * Puts in the param templateParamList all the template params that are in templateParam
- */
-void UMLAttribute::setTemplateParams(const QString& templateParam, UMLClassifierList &templateParamList)
-{
- if (templateParam.isEmpty())
- return;
- QString type = templateParam.simplified();
-
- int start = type.indexOf(QLatin1Char('<'));
- if (start >= 0) {
- int end = start;
- int count = 1;
- int len = type.length();
- while (count != 0 && ++end < len) {
- QChar c = type.at(end);
- if (c == QLatin1Char('<')) {
- count++;
- }
- if (c == QLatin1Char('>')) {
- count--;
- }
- }
- if (count != 0) {
- //The template is ill-formated, let's quit
- return;
- }
- setTemplateParams(type.mid(start + 1, end - start - 1), templateParamList);
- setTemplateParams(type.left(start) + type.right(len - end - 1), templateParamList);
- } else {
- QStringList paramsList = type.split(QLatin1Char(','));
- for (QStringList::Iterator it = paramsList.begin(); it != paramsList.end(); ++it) {
- QString param = *it;
- if (!param.isEmpty()) {
- UMLDoc *pDoc = UMLApp::app()->document();
- UMLObject* obj = pDoc->findUMLObject(param);
- if (obj == NULL) {
- obj = pDoc->findUMLObject(param.remove(QLatin1Char(' ')));
- }
- if (obj != NULL) {
- //We want to list only the params that already exist in this document
- //If the param doesnt't already exist, we couldn't draw an association anyway
- UMLClassifier* tmpClassifier = static_cast<UMLClassifier*>(obj);
- if (templateParamList.indexOf(tmpClassifier) == -1) {
- templateParamList.append(tmpClassifier);
- }
- }
- }
- }
- }
-}
-
-/**
- * Returns all the template params (if any) that are in the type of this attribute
- */
-UMLClassifierList UMLAttribute::getTemplateParams()
-{
- UMLClassifierList templateParamList;
- QString type = getType()->name();
- QString templateParam;
- // Handle C++/D/Java template/generic parameters
- const Uml::ProgrammingLanguage::Enum pl = UMLApp::app()->activeLanguage();
- if (pl == Uml::ProgrammingLanguage::Cpp ||
- pl == Uml::ProgrammingLanguage::Java || pl == Uml::ProgrammingLanguage::D) {
- int start = type.indexOf(QLatin1Char('<'));
- if (start >= 0) {
- int end = type.lastIndexOf(QLatin1Char('>'));
- if (end > start) {
- templateParam = type.mid(start + 1, end - start - 1);
- setTemplateParams(templateParam, templateParamList);
- }
- }
- }
- return templateParamList;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/attribute.h umbrello-kf6-15.08.1/umbrello/attribute.h
--- umbrello-kf6-15.08.1.orig/umbrello/attribute.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/attribute.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,84 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ATTRIBUTE_H
-#define ATTRIBUTE_H
-
-#include "basictypes.h"
-#include "classifierlistitem.h"
-#include "umlclassifierlist.h"
-
-/**
- * This class is used to set up information for an attribute. This is like
- * a programming attribute. It has a type, name, visibility and initial value.
- *
- * @short Sets up attribute information.
- * @author Paul Hensgen <phensgen@techie.com>
- * @see UMLObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLAttribute : public UMLClassifierListItem
-{
- Q_OBJECT
-public:
-
- UMLAttribute(UMLObject *parent, const QString& name,
- Uml::ID::Type id = Uml::ID::None,
- Uml::Visibility::Enum s = Uml::Visibility::Private,
- UMLObject *type = 0, const QString& iv = QString());
- explicit UMLAttribute(UMLObject *parent);
-
- bool operator==(const UMLAttribute &rhs) const;
-
- virtual ~UMLAttribute();
-
- virtual void copyInto(UMLObject *lhs) const;
-
- void setName(const QString &name);
-
- void setVisibility(Uml::Visibility::Enum s);
-
- virtual UMLObject* clone() const;
-
- QString getInitialValue() const;
- void setInitialValue(const QString &iv);
-
- QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
-
- QString getFullyQualifiedName(const QString& separator = QString(),
- bool includeRoot = false) const;
-
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- virtual bool showPropertiesDialog(QWidget* parent = 0);
-
- void setParmKind(Uml::ParameterDirection::Enum pk);
- Uml::ParameterDirection::Enum getParmKind() const;
-
- virtual UMLClassifierList getTemplateParams();
-
-signals:
-
- void attributeChanged();
-
-protected:
-
- bool load(QDomElement & element);
-
- QString m_InitialValue; ///< text for the attribute's initial value.
- Uml::ParameterDirection::Enum m_ParmKind;
-
-private:
-
- void setTemplateParams(const QString& templateParam, UMLClassifierList &templateParamList);
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/category.cpp umbrello-kf6-15.08.1/umbrello/category.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/category.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/category.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,101 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "category.h"
-
-/**
- * Constructs a Category.
- *
- * @param name The name of the Category.
- * @param id The unique id to assign to this Category.
- */
-UMLCategory::UMLCategory(const QString & name, Uml::ID::Type id)
- : UMLCanvasObject(name, id)
-{
- init();
-}
-
-/**
- * Standard destructor.
- */
-UMLCategory::~UMLCategory()
-{
-}
-
-/**
- * Initializes key variables of the class.
- */
-void UMLCategory::init()
-{
- m_BaseType = UMLObject::ot_Category;
- m_CategoryType = ct_Disjoint_Specialisation;
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLCategory::copyInto(UMLObject *lhs) const
-{
- UMLCategory *target = static_cast<UMLCategory*>(lhs);
-
- // call the parent first
- UMLCanvasObject::copyInto(target);
-
- target->m_CategoryType = m_CategoryType;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLCategory::clone() const
-{
- UMLCategory *clone = new UMLCategory();
- copyInto(clone);
- return clone;
-}
-
-/**
- * Creates the <UML:Category> XMI element.
- */
-void UMLCategory::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement categoryElement = UMLObject::save(QLatin1String("UML:Category"), qDoc);
- categoryElement.setAttribute(QLatin1String("categoryType"), (int)m_CategoryType);
- qElement.appendChild(categoryElement);
-}
-
-/**
- * Loads the <UML:Category> XMI element (empty.)
- */
-bool UMLCategory::load(QDomElement& element)
-{
- m_CategoryType = (Category_Type)element.attribute(QLatin1String("categoryType"),
- QLatin1String("0")).toInt();
- return true;
-}
-
-/**
- * Get the category type
- */
-UMLCategory::Category_Type UMLCategory::getType()
-{
- return m_CategoryType;
-}
-
-/**
- * Set the category type
- */
-void UMLCategory::setType(Category_Type type)
-{
- m_CategoryType = type;
- emitModified();
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/category.h umbrello-kf6-15.08.1/umbrello/category.h
--- umbrello-kf6-15.08.1.orig/umbrello/category.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/category.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,62 +0,0 @@
-/***************************************************************************
- * *
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef CATEGORY_H
-#define CATEGORY_H
-
-#include "umlcanvasobject.h"
-
-/**
- * This class contains the non-graphical information required for a UML Category.
- * This class inherits from @ref UMLCanvasObject which contains most of the
- * information.
- * The @ref UMLDoc class creates instances of this type.
- *
- * @short Information for a non-graphical UML Category.
- * @author Sharan Rao
- * @see UMLCanvasObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLCategory : public UMLCanvasObject {
- Q_OBJECT
-public:
-
- enum Category_Type {
- ct_Disjoint_Specialisation,
- ct_Overlapping_Specialisation,
- ct_Union
- };
-
- explicit UMLCategory(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- ~UMLCategory();
-
- virtual void init();
-
- void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- UMLCategory::Category_Type getType();
-
- void setType(Category_Type type);
-
-protected:
-
- bool load(QDomElement & element);
-
-private:
-
- Category_Type m_CategoryType;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/checkconstraint.cpp umbrello-kf6-15.08.1/umbrello/checkconstraint.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/checkconstraint.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/checkconstraint.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,160 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-//own header
-#include "checkconstraint.h"
-
-// app includes
-#include "debug_utils.h"
-#include "umlcheckconstraintdialog.h"
-
-/**
- * Sets up a constraint.
- *
- * @param parent The parent of this UMLCheckConstraint.
- * @param name The name of this UMLCheckConstraint.
- * @param id The unique id given to this UMLCheckConstraint.
- */
-UMLCheckConstraint::UMLCheckConstraint(UMLObject *parent,
- const QString& name, Uml::ID::Type id)
- : UMLEntityConstraint(parent, name, id)
-{
- init();
-}
-
-/**
- * Sets up a constraint.
- *
- * @param parent The parent of this UMLCheckConstraint.
- */
-UMLCheckConstraint::UMLCheckConstraint(UMLObject *parent)
- : UMLEntityConstraint(parent)
-{
- init();
-}
-
-/**
- * Overloaded '==' operator.
- */
-bool UMLCheckConstraint::operator==(const UMLCheckConstraint &rhs) const
-{
- if (this == &rhs)
- return true;
-
- if (!UMLObject::operator==(rhs))
- return false;
-
- return true;
-}
-
-/**
- * Destructor.
- */
-UMLCheckConstraint::~UMLCheckConstraint()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the UMLCheckConstraint
- * object.
- */
-void UMLCheckConstraint::copyInto(UMLObject *lhs) const
-{
- UMLCheckConstraint *target = static_cast<UMLCheckConstraint*>(lhs);
-
- // call the parent first.
- UMLEntityConstraint::copyInto(target);
-
- // Copy all datamembers
- target->m_CheckCondition = m_CheckCondition;
-}
-
-/**
- * Make a clone of the UMLCheckConstraint.
- */
-UMLObject* UMLCheckConstraint::clone() const
-{
- //FIXME: The new attribute should be slaved to the NEW parent not the old.
- UMLCheckConstraint *clone = new UMLCheckConstraint(static_cast<UMLObject*>(parent()));
- copyInto(clone);
- return clone;
-}
-
-/**
- * Returns a string representation of the UMLCheckConstraint.
- *
- * @param sig If true will show the attribute type and initial value.
- * @return Returns a string representation of the UMLAttribute.
- */
-QString UMLCheckConstraint::toString(Uml::SignatureType::Enum sig)
-{
- QString s;
-
- if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::SigNoVis) {
- s = name() ;
- }
-
- return s;
-}
-
-QString UMLCheckConstraint::getFullyQualifiedName(const QString& separator,
- bool includeRoot) const
-{
- Q_UNUSED(separator); Q_UNUSED(includeRoot);
- return this->name();
-}
-
-/**
- * Creates the <UML:UniqueConstraint> XMI element.
- */
-void UMLCheckConstraint::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement checkConstraintElement = UMLObject::save(QLatin1String("UML:CheckConstraint"), qDoc);
-
- QDomNode checkCondition = qDoc.createTextNode(m_CheckCondition);
- checkConstraintElement.appendChild(checkCondition);
-
- qElement.appendChild(checkConstraintElement);
-}
-
-/**
- * Display the properties configuration dialog for the attribute.
- */
-bool UMLCheckConstraint::showPropertiesDialog(QWidget* parent)
-{
- UMLCheckConstraintDialog dialog(parent, this);
- return dialog.exec();
-}
-
-/**
- * Loads the <UML:CheckConstraint> XMI element.
- */
-bool UMLCheckConstraint::load(QDomElement & element)
-{
- QDomNode node = element.firstChild();
-
- QDomText checkConstraintText = node.toText();
- if (checkConstraintText.isNull())
- m_CheckCondition = QString();
- else
- m_CheckCondition = checkConstraintText.data();
-
- return true;
-}
-
-/**
- * Initialises Check Constraint
- */
-void UMLCheckConstraint::init()
-{
- m_BaseType = UMLObject::ot_CheckConstraint;
- m_CheckCondition.clear();
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/checkconstraint.h umbrello-kf6-15.08.1/umbrello/checkconstraint.h
--- umbrello-kf6-15.08.1.orig/umbrello/checkconstraint.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/checkconstraint.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,71 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef CHECKCONSTRAINT_H
-#define CHECKCONSTRAINT_H
-
-#include "basictypes.h"
-#include "entityconstraint.h"
-
-/**
- * This class is used to set up information for a unique entity constraint.
- *
- * @short Sets up Check Constraint information for UMLEntities.
- * @author Sharan Rao
- * @see UMLObject UMLClassifierListItem UMLEntityConstraint
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLCheckConstraint : public UMLEntityConstraint
-{
- Q_OBJECT
-public:
-
- UMLCheckConstraint(UMLObject *parent, const QString& name,
- Uml::ID::Type id = Uml::ID::None);
- explicit UMLCheckConstraint(UMLObject *parent);
-
- bool operator==(const UMLCheckConstraint &rhs) const;
-
- virtual ~UMLCheckConstraint();
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
-
- QString getFullyQualifiedName(const QString& separator = QString(),
- bool includeRoot = false) const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- virtual bool showPropertiesDialog(QWidget* parent = 0);
-
- QString getCheckCondition() const {
- return m_CheckCondition;
- }
-
- void setCheckCondition(const QString& condition) {
- m_CheckCondition = condition.trimmed();
- }
-
-protected:
-
- bool load(QDomElement & element);
-
-private:
-
- void init();
-
- QString m_CheckCondition; ///< the check condition
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/classifier.cpp umbrello-kf6-15.08.1/umbrello/classifier.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/classifier.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/classifier.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,1631 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-#include "classifier.h"
-
-// app includes
-#include "association.h"
-#include "debug_utils.h"
-#include "umlassociationlist.h"
-#include "operation.h"
-#include "attribute.h"
-#include "template.h"
-#include "enumliteral.h"
-#include "entityattribute.h"
-#include "enum.h"
-#include "entity.h"
-#include "stereotype.h"
-#include "umldoc.h"
-#include "uml.h"
-#include "uniqueid.h"
-#include "object_factory.h"
-#include "model_utils.h"
-#include "idchangelog.h"
-#include "umloperationdialog.h"
-#include "umlattributedialog.h"
-#include "umltemplatedialog.h"
-#include "optionstate.h"
-#include "icon_utils.h"
-
-// kde includes
-#include <KLocalizedString>
-#include <KMessageBox>
-
-// qt includes
-#include <QPointer>
-
-using namespace Uml;
-
-/**
- * @brief holds set of classifiers for recursive loop detection
- */
-class UMLClassifierSet: public QSet<UMLClassifier *> {
-public:
- UMLClassifierSet() : level(0)
- {
- }
- int level;
-};
-
-/**
- * Sets up a Classifier.
- *
- * @param name The name of the Concept.
- * @param id The unique id of the Concept.
- */
-UMLClassifier::UMLClassifier(const QString & name, Uml::ID::Type id)
- : UMLPackage(name, id)
-{
- m_BaseType = UMLObject::ot_Class; // default value
- m_pClassAssoc = NULL;
- m_isRef = false;
-}
-
-/**
- * Standard deconstructor.
- */
-UMLClassifier::~UMLClassifier()
-{
-}
-
-/**
- * Reimplementation of method from class UMLObject for controlling the
- * exact type of this classifier: class, interface, or datatype.
- * @param ot the base type to set
- */
-void UMLClassifier::setBaseType(UMLObject::ObjectType ot)
-{
- m_BaseType = ot;
- Icon_Utils::IconType newIcon;
- switch (ot) {
- case ot_Interface:
- UMLObject::setStereotypeCmd(QLatin1String("interface"));
- UMLObject::m_bAbstract = true;
- newIcon = Icon_Utils::it_Interface;
- break;
- case ot_Class:
- UMLObject::setStereotypeCmd(QString());
- UMLObject::m_bAbstract = false;
- newIcon = Icon_Utils::it_Class;
- break;
- case ot_Datatype:
- UMLObject::setStereotypeCmd(QLatin1String("datatype"));
- UMLObject::m_bAbstract = false;
- newIcon = Icon_Utils::it_Datatype;
- break;
- case ot_Package:
- UMLObject::setStereotypeCmd(QLatin1String("package"));
- UMLObject::m_bAbstract = false;
- newIcon = Icon_Utils::it_Package;
- break;
- default:
- uError() << "cannot set to type " << ot;
- return;
- }
- Model_Utils::treeViewChangeIcon(this, newIcon);
-}
-
-/**
- * Returns true if this classifier represents an interface.
- */
-bool UMLClassifier::isInterface() const
-{
- return (m_BaseType == ot_Interface);
-}
-
-/**
- * Returns true if this classifier represents a datatype.
- */
-bool UMLClassifier::isDatatype() const
-{
- return (m_BaseType == ot_Datatype);
-}
-
-/**
- * Checks whether an operation is valid based on its signature -
- * An operation is "valid" if the operation's name and parameter list
- * are unique in the classifier.
- *
- * @param name Name of the operation to check.
- * @param opParams The operation's argument list.
- * @param exemptOp Pointer to the exempt method (optional.)
- * @return NULL if the signature is valid (ok), else return a pointer
- * to the existing UMLOperation that causes the conflict.
- */
-UMLOperation * UMLClassifier::checkOperationSignature(
- const QString& name,
- UMLAttributeList opParams,
- UMLOperation *exemptOp)
-{
- UMLOperationList list = findOperations(name);
- if (list.count() == 0) {
- return NULL;
- }
- const int inputParmCount = opParams.count();
-
- // there is at least one operation with the same name... compare the parameter list
- foreach (UMLOperation* test, list) {
- if (test == exemptOp) {
- continue;
- }
- UMLAttributeList testParams = test->getParmList();
- const int pCount = testParams.count();
- if (pCount != inputParmCount) {
- continue;
- }
- int i = 0;
- while (i < pCount) {
- // The only criterion for equivalence is the parameter types.
- // (Default values are not considered.)
- if(testParams.at(i)->getTypeName() != opParams.at(i)->getTypeName())
- break;
- i++;
- }
- if (i == pCount) { // all parameters matched->the signature is not unique
- return test;
- }
- }
- // we did not find an exact match, so the signature is unique (acceptable)
- return NULL;
-}
-
-/**
- * Find an operation of the given name and parameter signature.
- *
- * @param name The name of the operation to find.
- * @param params The parameter descriptors of the operation to find.
- *
- * @return The operation found. Will return 0 if none found.
- */
-UMLOperation* UMLClassifier::findOperation(const QString& name,
- Model_Utils::NameAndType_List params)
-{
- UMLOperationList list = findOperations(name);
- if (list.count() == 0) {
- return NULL;
- }
- // if there are operation(s) with the same name then compare the parameter list
- const int inputParmCount = params.count();
-
- foreach (UMLOperation* test, list) {
- UMLAttributeList testParams = test->getParmList();
- const int pCount = testParams.count();
- if (inputParmCount == 0 && pCount == 0)
- return test;
- if (inputParmCount != pCount)
- continue;
- int i = 0;
- for (; i < pCount; ++i) {
- Model_Utils::NameAndType_ListIt nt(params.begin() + i);
- UMLClassifier *type = dynamic_cast<UMLClassifier*>((*nt).m_type);
- UMLClassifier *testType = testParams.at(i)->getType();
- if (type == NULL && testType == NULL) { //no parameter type
- continue;
- } else if (type == NULL) { //template parameter
- if (testType->name() != QLatin1String("class"))
- break;
- } else if (type != testType)
- break;
- }
- if (i == pCount)
- return test; // all parameters matched
- }
- return 0;
-}
-
-/**
- * Creates an operation in the current document.
- * The new operation is initialized with name, id, etc.
- * If a method with the given profile already exists in the classifier,
- * no new method is created and the existing operation is returned.
- * If no name is provided, or if the params are NULL, an Operation
- * Dialog is shown to ask the user for a name and parameters.
- * The operation's signature is checked for validity within the parent
- * classifier.
- *
- * @param name The operation name (will be chosen internally if
- * none given.)
- * @param isExistingOp Optional pointer to bool. If supplied, the bool is
- * set to true if an existing operation is returned.
- * @param params Optional list of parameter names and types.
- * If supplied, new operation parameters are
- * constructed using this list.
- * @return The new operation, or NULL if the operation could not be
- * created because for example, the user canceled the dialog
- * or no appropriate name can be found.
- */
-UMLOperation* UMLClassifier::createOperation(
- const QString &name /*=QString()*/,
- bool *isExistingOp /*=NULL*/,
- Model_Utils::NameAndType_List *params /*=NULL*/)
-{
- bool nameNotSet = (name.isNull() || name.isEmpty());
- if (! nameNotSet) {
- Model_Utils::NameAndType_List parList;
- if (params)
- parList = *params;
- UMLOperation* existingOp = findOperation(name, parList);
- if (existingOp != NULL) {
- if (isExistingOp != NULL)
- *isExistingOp = true;
- return existingOp;
- }
- }
- // we did not find an exact match, so the signature is unique
- UMLOperation *op = new UMLOperation(this, name);
- if (params) {
- for (Model_Utils::NameAndType_ListIt it = params->begin(); it != params->end(); ++it) {
- const Model_Utils::NameAndType &nt = *it;
- UMLAttribute *par = new UMLAttribute(op, nt.m_name, Uml::ID::None, Uml::Visibility::Private,
- nt.m_type, nt.m_initialValue);
- par->setParmKind(nt.m_direction);
- op->addParm(par);
- }
- }
-
- // Only show the operation dialog if no name was provided (allows quick-create
- // from listview)
- if (nameNotSet) {
- op->setName(uniqChildName(UMLObject::ot_Operation));
-
- while (true) {
- QPointer<UMLOperationDialog> operationDialog = new UMLOperationDialog(0, op);
- if(operationDialog->exec() != QDialog::Accepted) {
- delete op;
- delete operationDialog;
- return NULL;
- } else if (checkOperationSignature(op->name(), op->getParmList())) {
- KMessageBox::information(0,
- i18n("An operation with the same name and signature already exists. You cannot add it again."));
- } else {
- break;
- }
- delete operationDialog;
- }
- }
-
- // operation name is ok, formally add it to the classifier
- if (! addOperation(op)) {
- delete op;
- return NULL;
- }
-
- UMLDoc *umldoc = UMLApp::app()->document();
- umldoc->signalUMLObjectCreated(op);
- return op;
-}
-
-/**
- * Appends an operation to the classifier.
- * This function is mainly intended for the clipboard.
- *
- * @param op Pointer to the UMLOperation to add.
- * @param position Inserted at the given position.
- * @return True if the operation was added successfully.
- */
-bool UMLClassifier::addOperation(UMLOperation* op, int position)
-{
- Q_ASSERT(op);
- if (m_List.indexOf(op) != -1) {
- uDebug() << "findRef(" << op->name() << ") finds op (bad)";
- return false;
- }
- if (checkOperationSignature(op->name(), op->getParmList())) {
- uDebug() << "checkOperationSignature(" << op->name() << ") op is non-unique";
- return false;
- }
-
- if (position >= 0 && position <= m_List.count()) {
- uDebug() << op->name() << ": inserting at position " << position;
- m_List.insert(position, op);
- UMLClassifierListItemList itemList = getFilteredList(UMLObject::ot_Operation);
- QString buf;
- foreach (UMLClassifierListItem* currentAtt, itemList) {
- buf.append(QLatin1Char(' ') + currentAtt->name());
- }
- uDebug() << " list after change: " << buf;
- }
- else {
- m_List.append(op);
- }
- emit operationAdded(op);
- UMLObject::emitModified();
- connect(op, SIGNAL(modified()), this, SIGNAL(modified()));
- return true;
-}
-
-/**
- * Appends an operation to the classifier.
- * @see bool addOperation(UMLOperation* Op, int position = -1)
- * This function is mainly intended for the clipboard.
- *
- * @param op Pointer to the UMLOperation to add.
- * @param log Pointer to the IDChangeLog.
- * @return True if the operation was added successfully.
- */
-bool UMLClassifier::addOperation(UMLOperation* op, IDChangeLog* log)
-{
- if (addOperation(op, -1)) {
- return true;
- }
- else if (log) {
- log->removeChangeByNewID(op->id());
- }
- return false;
-}
-
-/**
- * Remove an operation from the Classifier.
- * The operation is not deleted so the caller is responsible for what
- * happens to it after this.
- *
- * @param op The operation to remove.
- * @return Count of the remaining operations after removal, or
- * -1 if the given operation was not found.
- */
-int UMLClassifier::removeOperation(UMLOperation *op)
-{
- if (op == NULL) {
- uDebug() << "called on NULL op";
- return -1;
- }
- if (!m_List.removeAll(op)) {
- uDebug() << "cannot find op " << op->name() << " in list";
- return -1;
- }
- // disconnection needed.
- // note that we don't delete the operation, just remove it from the Classifier
- disconnect(op, SIGNAL(modified()), this, SIGNAL(modified()));
- emit operationRemoved(op);
- UMLObject::emitModified();
- return m_List.count();
-}
-
-/**
- * Create and add a just created template.
- * @param currentName the name of the template
- * @return the template or NULL
- */
-UMLObject* UMLClassifier::createTemplate(const QString& currentName /*= QString()*/)
-{
- QString name = currentName;
- bool goodName = !name.isEmpty();
- if (!goodName) {
- name = uniqChildName(UMLObject::ot_Template);
- }
- UMLTemplate* newTemplate = new UMLTemplate(this, name);
-
- int button = QDialog::Accepted;
-
- while (button == QDialog::Accepted && !goodName) {
- QPointer<UMLTemplateDialog> templateDialog = new UMLTemplateDialog(0, newTemplate);
- button = templateDialog->exec();
- name = newTemplate->name();
-
- if (name.length() == 0) {
- KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
- }
- else if (findChildObject(name) != NULL) {
- KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
- }
- else {
- goodName = true;
- }
- delete templateDialog;
- }
-
- if (button != QDialog::Accepted) {
- return NULL;
- }
-
- addTemplate(newTemplate);
-
- UMLDoc *umldoc = UMLApp::app()->document();
- umldoc->signalUMLObjectCreated(newTemplate);
- return newTemplate;
-}
-
-/**
- * Returns the number of attributes for the class.
- *
- * @return The number of attributes for the class.
- */
-int UMLClassifier::attributes()
-{
- UMLClassifierListItemList atts = getFilteredList(UMLObject::ot_Attribute);
- return atts.count();
-}
-
-/**
- * Returns the attributes for the specified scope.
- * @return List of true attributes for the class.
- */
-UMLAttributeList UMLClassifier::getAttributeList() const
-{
- UMLAttributeList attributeList;
- foreach (UMLObject* listItem, m_List) {
- uIgnoreZeroPointer(listItem);
- if (listItem->baseType() == UMLObject::ot_Attribute) {
- attributeList.append(static_cast<UMLAttribute*>(listItem));
- }
- }
- return attributeList;
-}
-
-/**
- * Returns the attributes for the specified scope.
- * @param scope The scope of the attribute.
- * @return List of true attributes for the class.
- */
-UMLAttributeList UMLClassifier::getAttributeList(Visibility::Enum scope) const
-{
- UMLAttributeList list;
- if (!isInterface())
- {
- UMLAttributeList atl = getAttributeList();
- foreach(UMLAttribute* at, atl)
- {
- uIgnoreZeroPointer(at);
- if (! at->isStatic())
- {
- if (scope == Uml::Visibility::Private)
- {
- if ((at->visibility() == Uml::Visibility::Private) ||
- (at->visibility() == Uml::Visibility::Implementation))
- {
- list.append(at);
- }
- }
- else if (scope == at->visibility())
- {
- list.append(at);
- }
- }
- }
- }
- return list;
-}
-
-/**
- * Returns the static attributes for the specified scope.
- *
- * @param scope The scope of the attribute.
- * @return List of true attributes for the class.
- */
-UMLAttributeList UMLClassifier::getAttributeListStatic(Visibility::Enum scope) const
-{
- UMLAttributeList list;
- if (!isInterface())
- {
- UMLAttributeList atl = getAttributeList();
- foreach(UMLAttribute* at, atl)
- {
- uIgnoreZeroPointer(at);
- if (at->isStatic())
- {
- if (scope == Uml::Visibility::Private)
- {
- if ((at->visibility() == Uml::Visibility::Private) ||
- (at->visibility() == Uml::Visibility::Implementation))
- {
- list.append(at);
- }
- }
- else if (scope == at->visibility())
- {
- list.append(at);
- }
- }
- }
- }
- return list;
-}
-
-/**
- * Find a list of operations with the given name.
- *
- * @param n The name of the operation to find.
- * @return The list of objects found; will be empty if none found.
- */
-UMLOperationList UMLClassifier::findOperations(const QString &n)
-{
- const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
- UMLOperationList list;
- foreach (UMLObject* obj, m_List) {
- uIgnoreZeroPointer(obj);
- if (obj->baseType() != UMLObject::ot_Operation)
- continue;
- UMLOperation *op = static_cast<UMLOperation*>(obj);
- if (caseSensitive) {
- if (obj->name() == n)
- list.append(op);
- } else if (obj->name().toLower() == n.toLower()) {
- list.append(op);
- }
- }
- return list;
-}
-
-/**
- * Find the child object by the given id.
- * @param id the id of the child object
- * @param considerAncestors flag whether the ancestors should be considered during search
- * @return the found child object or NULL
- */
-UMLObject* UMLClassifier::findChildObjectById(Uml::ID::Type id, bool considerAncestors /* =false */)
-{
- UMLObject *o = UMLCanvasObject::findChildObjectById(id);
- if (o) {
- return o;
- }
- if (considerAncestors) {
- UMLClassifierList ancestors = findSuperClassConcepts();
- foreach (UMLClassifier *anc, ancestors) {
- UMLObject *o = anc->findChildObjectById(id);
- if (o) {
- return o;
- }
- }
- }
- return NULL;
-}
-
-/**
- * Returns a list of concepts which inherit from this concept.
- *
- * @param type The ClassifierType to seek.
- * @return List of UMLClassifiers that inherit from us.
- */
-UMLClassifierList UMLClassifier::findSubClassConcepts (ClassifierType type)
-{
- UMLClassifierList list = getSubClasses();
- UMLAssociationList rlist = getRealizations();
-
- UMLClassifierList inheritingConcepts;
- Uml::ID::Type myID = id();
- foreach(UMLClassifier *c, list) {
- uIgnoreZeroPointer(c);
- if (type == ALL || (!c->isInterface() && type == CLASS)
- || (c->isInterface() && type == INTERFACE)) {
- inheritingConcepts.append(c);
- }
- }
-
- foreach (UMLAssociation *a, rlist) {
- uIgnoreZeroPointer(a);
- if (a->getObjectId(RoleType::A) != myID)
- {
- UMLObject* obj = a->getObject(RoleType::A);
- UMLClassifier *concept = dynamic_cast<UMLClassifier*>(obj);
- if (concept && (type == ALL || (!concept->isInterface() && type == CLASS)
- || (concept->isInterface() && type == INTERFACE))
- && (inheritingConcepts.indexOf(concept) == -1))
- {
- inheritingConcepts.append(concept);
- }
- }
- }
-
- return inheritingConcepts;
-}
-
-/**
- * Returns a list of concepts which this concept inherits from.
- *
- * @param type The ClassifierType to seek.
- * @return List of UMLClassifiers we inherit from.
- */
-UMLClassifierList UMLClassifier::findSuperClassConcepts (ClassifierType type)
-{
- UMLClassifierList list = getSuperClasses();
- UMLAssociationList rlist = getRealizations();
-
- UMLClassifierList parentConcepts;
- Uml::ID::Type myID = id();
- foreach (UMLClassifier *concept, list) {
- uIgnoreZeroPointer(concept);
- if (type == ALL || (!concept->isInterface() && type == CLASS)
- || (concept->isInterface() && type == INTERFACE))
- parentConcepts.append(concept);
- }
-
- foreach (UMLAssociation *a, rlist) {
- if (a->getObjectId(RoleType::A) == myID)
- {
- UMLObject* obj = a->getObject(RoleType::B);
- UMLClassifier *concept = dynamic_cast<UMLClassifier*>(obj);
- if (concept && (type == ALL || (!concept->isInterface() && type == CLASS)
- || (concept->isInterface() && type == INTERFACE))
- && (parentConcepts.indexOf(concept) == -1))
- parentConcepts.append(concept);
- }
- }
-
- return parentConcepts;
-}
-
-/**
- * Overloaded '==' operator.
- */
-bool UMLClassifier::operator==(const UMLClassifier & rhs) const
-{
- return UMLCanvasObject::operator==(rhs);
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLClassifier::copyInto(UMLObject *lhs) const
-{
- UMLClassifier *target = static_cast<UMLClassifier*>(lhs);
- UMLCanvasObject::copyInto(target);
- target->setBaseType(m_BaseType);
- // CHECK: association property m_pClassAssoc is not copied
- m_List.copyInto(&(target->m_List));
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLClassifier::clone() const
-{
- UMLClassifier *clone = new UMLClassifier();
- copyInto(clone);
- return clone;
-}
-
-/**
- * Needs to be called after all UML objects are loaded from file.
- * Calls the parent resolveRef(), and calls resolveRef() on all
- * UMLClassifierListItems.
- * Overrides the method from UMLObject.
- *
- * @return true for success.
- */
-bool UMLClassifier::resolveRef()
-{
- bool success = UMLPackage::resolveRef();
- // Using reentrant iteration is a bare necessity here:
- foreach (UMLObject* obj, m_List) {
- uIgnoreZeroPointer(obj);
- /**** For reference, here is the non-reentrant iteration scheme -
- DO NOT USE THIS !
- for (UMLObject *obj = m_List.first(); obj; obj = m_List.next())
- { .... }
- ****/
- if (obj->resolveRef()) {
- UMLClassifierListItem *cli = static_cast<UMLClassifierListItem*>(obj);
- switch (cli->baseType()) {
- case UMLObject::ot_Attribute:
- emit attributeAdded(cli);
- break;
- case UMLObject::ot_Operation:
- emit operationAdded(cli);
- break;
- case UMLObject::ot_Template:
- emit templateAdded(cli);
- break;
- default:
- break;
- }
- }
- }
- return success;
-}
-
-/**
- * Reimplemented from UMLObject.
- */
-bool UMLClassifier::acceptAssociationType(AssociationType::Enum type)
-{
- switch(type)
- {
- case AssociationType::Generalization:
- case AssociationType::Aggregation:
- case AssociationType::Relationship:
- case AssociationType::Dependency:
- case AssociationType::Association:
- case AssociationType::Association_Self:
- case AssociationType::Containment:
- case AssociationType::Composition:
- case AssociationType::Realization:
- case AssociationType::UniAssociation:
- return true;
- default:
- return false;
- }
- return false; //shutup compiler warning
-}
-
-/**
- * Creates an attribute for the class.
- *
- * @param name An optional name, used by when creating through UMLListView
- * @param type An optional type, used by when creating through UMLListView
- * @param vis An optional visibility, used by when creating through UMLListView
- * @param init An optional initial value, used by when creating through UMLListView
- * @return The UMLAttribute created
- */
-UMLAttribute* UMLClassifier::createAttribute(const QString &name,
- UMLObject *type,
- Visibility::Enum vis,
- const QString &init)
-{
- Uml::ID::Type id = UniqueID::gen();
- QString currentName;
- if (name.isNull()) {
- currentName = uniqChildName(UMLObject::ot_Attribute);
- } else {
- currentName = name;
- }
- UMLAttribute* newAttribute = new UMLAttribute(this, currentName, id, vis, type, init);
-
- int button = QDialog::Accepted;
- bool goodName = false;
-
- //check for name.isNull() stops dialog being shown
- //when creating attribute via list view
- while (button == QDialog::Accepted && !goodName && name.isNull()) {
- QPointer<UMLAttributeDialog> attributeDialog = new UMLAttributeDialog(0, newAttribute);
- button = attributeDialog->exec();
- QString name = newAttribute->name();
-
- if(name.length() == 0) {
- KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
- } else if (findChildObject(name) != NULL) {
- KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
- } else {
- goodName = true;
- }
- delete attributeDialog;
- }
-
- if (button != QDialog::Accepted) {
- delete newAttribute;
- return NULL;
- }
-
- addAttribute(newAttribute);
-
- UMLDoc *umldoc = UMLApp::app()->document();
- umldoc->signalUMLObjectCreated(newAttribute);
- return newAttribute;
-}
-
-/**
- * Creates and adds an attribute for the class.
- *
- * @param name an optional name, used by when creating through UMLListView
- * @param id an optional id
- * @return the UMLAttribute created and added
- */
-
-UMLAttribute* UMLClassifier::addAttribute(const QString &name, Uml::ID::Type id /* = Uml::id_None */)
-{
- foreach (UMLObject* obj, m_List) {
- uIgnoreZeroPointer(obj);
- if (obj->baseType() == UMLObject::ot_Attribute && obj->name() == name)
- return static_cast<UMLAttribute*>(obj);
- }
- Uml::Visibility::Enum scope = Settings::optionState().classState.defaultAttributeScope;
- UMLAttribute *a = new UMLAttribute(this, name, id, scope);
- m_List.append(a);
- emit attributeAdded(a);
- UMLObject::emitModified();
- connect(a, SIGNAL(modified()), this, SIGNAL(modified()));
- return a;
-}
-
-/**
- * Adds an already created attribute.
- * The attribute object must not belong to any other concept.
- *
- * @param name the name of the attribute
- * @param type the type of the attribute
- * @param scope the visibility of the attribute
- * @return the just created and added attribute
- */
-UMLAttribute* UMLClassifier::addAttribute(const QString &name, UMLObject *type, Visibility::Enum scope)
-{
- UMLAttribute *a = new UMLAttribute(this);
- a->setName(name);
- a->setVisibility(scope);
- a->setID(UniqueID::gen());
- if (type) {
- a->setType(type);
- }
- m_List.append(a);
- emit attributeAdded(a);
- UMLObject::emitModified();
- connect(a, SIGNAL(modified()), this, SIGNAL(modified()));
- return a;
-}
-
-/**
- * Adds an already created attribute.
- * The attribute object must not belong to any other concept.
- *
- * @param att Pointer to the UMLAttribute.
- * @param log Pointer to the IDChangeLog (optional.)
- * @param position Position index for the insertion (optional.)
- * If the position is omitted, or if it is
- * negative or too large, the attribute is added
- * to the end of the list.
- * @return True if the attribute was successfully added.
- */
-bool UMLClassifier::addAttribute(UMLAttribute* att, IDChangeLog* log /* = 0 */,
- int position /* = -1 */)
-{
- Q_ASSERT(att);
- if (findChildObject(att->name()) == NULL) {
- att->setParent(this);
- if (position >= 0 && position < (int)m_List.count()) {
- m_List.insert(position, att);
- }
- else {
- m_List.append(att);
- }
- emit attributeAdded(att);
- UMLObject::emitModified();
- connect(att, SIGNAL(modified()), this, SIGNAL(modified()));
- return true;
- } else if (log) {
- log->removeChangeByNewID(att->id());
- delete att;
- }
- return false;
-}
-
-/**
- * Removes an attribute from the class.
- *
- * @param att The attribute to remove.
- * @return Count of the remaining attributes after removal.
- * Returns -1 if the given attribute was not found.
- */
-int UMLClassifier::removeAttribute(UMLAttribute* att)
-{
- if (!m_List.removeAll(att)) {
- uDebug() << "cannot find att given in list";
- return -1;
- }
- emit attributeRemoved(att);
- UMLObject::emitModified();
- // If we are deleting the object, then we don't need to disconnect..this is done auto-magically
- // for us by QObject. -b.t.
- // disconnect(att, SIGNAL(modified()), this, SIGNAL(modified()));
- delete att;
- return m_List.count();
-}
-
-/**
- * Sets the UMLAssociation for which this class shall act as an
- * association class.
- */
-void UMLClassifier::setClassAssoc(UMLAssociation *assoc)
-{
- m_pClassAssoc = assoc;
-}
-
-/**
- * Returns the UMLAssociation for which this class acts as an
- * association class. Returns NULL if this class does not act
- * as an association class.
- */
-UMLAssociation *UMLClassifier::getClassAssoc() const
-{
- return m_pClassAssoc;
-}
-
-/**
- * Return true if this classifier has abstract operations.
- */
-bool UMLClassifier::hasAbstractOps ()
-{
- UMLOperationList opl(getOpList());
- foreach(UMLOperation *op, opl) {
- uIgnoreZeroPointer(op);
- if (op->isAbstract()) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Counts the number of operations in the Classifier.
- *
- * @return The number of operations for the Classifier.
- */
-int UMLClassifier::operations()
-{
- return getOpList().count();
-}
-
-
-/**
- * Return a list of operations for the Classifier.
- *
- * @param includeInherited Includes operations from superclasses.
- * @param alreadyTraversed internal used object to avoid recursive loops
- * @return The list of operations for the Classifier.
- */
-UMLOperationList UMLClassifier::getOpList(bool includeInherited, UMLClassifierSet *alreadyTraversed)
-{
- UMLOperationList ops;
- foreach (UMLObject* li, m_List) {
- uIgnoreZeroPointer(li);
- if (li->baseType() == ot_Operation) {
- ops.append(static_cast<UMLOperation*>(li));
- }
- }
- if (includeInherited) {
- if (!alreadyTraversed) {
- alreadyTraversed = new UMLClassifierSet;
- }
- else
- alreadyTraversed->level++;
-
- if (!alreadyTraversed->contains(this))
- *alreadyTraversed << this;
-
- // get a list of parents of this class
- UMLClassifierList parents = findSuperClassConcepts();
- foreach(UMLClassifier *c, parents) {
- if (alreadyTraversed->contains(c)) {
- uError() << "class " << c->name() << " is starting a dependency loop!";
- continue;
- }
- // get operations for each parent by recursive call
- UMLOperationList pops = c->getOpList(true, alreadyTraversed);
- // add these operations to operation list, but only if unique.
- foreach (UMLOperation *po, pops) {
- QString po_as_string(po->toString(Uml::SignatureType::SigNoVis));
- bool breakFlag = false;
- foreach (UMLOperation* o, ops) {
- if (o->toString(Uml::SignatureType::SigNoVis) == po_as_string) {
- breakFlag = true;
- break;
- }
- }
- if (breakFlag == false)
- ops.append(po);
- }
- // remember this node
- *alreadyTraversed << c;
- }
- if (alreadyTraversed->level-- == 0) {
- delete alreadyTraversed;
- alreadyTraversed = 0;
- }
- }
- return ops;
-}
-
-/**
- * Returns the entries in m_List that are of the requested type.
- * If the requested type is UMLObject::ot_UMLObject then all entries
- * are returned.
- * @param ot the requested object type
- * @return The list of true operations for the Concept.
- */
-UMLClassifierListItemList UMLClassifier::getFilteredList(UMLObject::ObjectType ot) const
-{
- UMLClassifierListItemList resultList;
- foreach (UMLObject* o, m_List) {
- uIgnoreZeroPointer(o);
- if (!o || o->baseType() == UMLObject::ot_Association) {
- continue;
- }
- UMLClassifierListItem *listItem = static_cast<UMLClassifierListItem*>(o);
- if (ot == UMLObject::ot_UMLObject || listItem->baseType() == ot) {
- resultList.append(listItem);
- }
- }
- return resultList;
-}
-
-/**
- * Adds an already created template.
- * The template object must not belong to any other concept.
- *
- * @param name the name of the template
- * @param id the id of the template
- * @return the added template
- */
-UMLTemplate* UMLClassifier::addTemplate(const QString &name, Uml::ID::Type id)
-{
- UMLTemplate *templt = findTemplate(name);
- if (templt) {
- return templt;
- }
- templt = new UMLTemplate(this, name, id);
- m_List.append(templt);
- emit templateAdded(templt);
- UMLObject::emitModified();
- connect(templt, SIGNAL(modified()), this, SIGNAL(modified()));
- return templt;
-}
-
-/**
- * Adds an already created template.
- * The template object must not belong to any other concept.
- *
- * @param newTemplate Pointer to the UMLTemplate object to add.
- * @param log Pointer to the IDChangeLog.
- * @return True if the template was successfully added.
- */
-bool UMLClassifier::addTemplate(UMLTemplate* newTemplate, IDChangeLog* log /* = 0*/)
-{
- QString name = newTemplate->name();
- if (findChildObject(name) == NULL) {
- newTemplate->setParent(this);
- m_List.append(newTemplate);
- emit templateAdded(newTemplate);
- UMLObject::emitModified();
- connect(newTemplate, SIGNAL(modified()), this, SIGNAL(modified()));
- return true;
- }
- else if (log) {
- log->removeChangeByNewID(newTemplate->id());
- delete newTemplate;
- }
- return false;
-}
-
-/**
- * Adds an template to the class.
- * The template object must not belong to any other class.
- * TODO: If the param IDChangeLog from the method above is not being used,
- * give position a default value of -1 and the method can replace the above one.
- * @param templt Pointer to the UMLTemplate to add.
- * @param position The position of the template in the list.
- * A value of -1 will add the template at the end.
- * @return True if the template was successfully added.
- */
-bool UMLClassifier::addTemplate(UMLTemplate* templt, int position)
-{
- Q_ASSERT(templt);
- QString name = templt->name();
- if (findChildObject(name) == NULL) {
- templt->setParent(this);
- if (position >= 0 && position <= (int)m_List.count()) {
- m_List.insert(position, templt);
- }
- else {
- m_List.append(templt);
- }
- emit templateAdded(templt);
- UMLObject::emitModified();
- connect(templt, SIGNAL(modified()), this, SIGNAL(modified()));
- return true;
- }
- //else
- return false;
-}
-
-/**
- * Removes a template from the class.
- *
- * @param umltemplate The template to remove.
- * @return Count of the remaining templates after removal.
- * Returns -1 if the given template was not found.
- */
-int UMLClassifier::removeTemplate(UMLTemplate* umltemplate)
-{
- if (!m_List.removeAll(umltemplate)) {
- uWarning() << "cannot find att given in list";
- return -1;
- }
- emit templateRemoved(umltemplate);
- UMLObject::emitModified();
- disconnect(umltemplate, SIGNAL(modified()), this, SIGNAL(modified()));
- return m_List.count();
-}
-
-/**
- * Seeks the template parameter of the given name.
- * @param name the template name
- * @return the found template or 0
- */
-UMLTemplate *UMLClassifier::findTemplate(const QString& name)
-{
- UMLTemplateList templParams = getTemplateList();
- foreach (UMLTemplate *templt, templParams) {
- if (templt->name() == name) {
- return templt;
- }
- }
- return 0;
-}
-
-/**
- * Returns the number of templates for the class.
- *
- * @return The number of templates for the class.
- */
-int UMLClassifier::templates()
-{
- UMLClassifierListItemList tempList = getFilteredList(UMLObject::ot_Template);
- return tempList.count();
-}
-
-/**
- * Returns the templates.
- * Same as UMLClassifier::getFilteredList(ot_Template) but
- * return type is a true UMLTemplateList.
- *
- * @return Pointer to the list of true templates for the class.
- */
-UMLTemplateList UMLClassifier::getTemplateList() const
-{
- UMLTemplateList templateList;
- foreach (UMLObject* listItem, m_List) {
- uIgnoreZeroPointer(listItem);
- if (listItem->baseType() == UMLObject::ot_Template) {
- templateList.append(static_cast<UMLTemplate*>(listItem));
- }
- }
- return templateList;
-}
-
-/**
- * Take and return a subordinate item from this classifier.
- * Ownership of the item is passed to the caller.
- *
- * @param item Subordinate item to take.
- * @return Index in m_List of the item taken.
- * Return -1 if the item is not found in m_List.
- */
-int UMLClassifier::takeItem(UMLClassifierListItem *item)
-{
- QString buf;
- foreach (UMLObject* currentAtt, m_List) {
- uIgnoreZeroPointer(currentAtt);
- QString txt = currentAtt->name();
- if (txt.isEmpty()) {
- txt = QLatin1String("Type-") + QString::number((int) currentAtt->baseType());
- }
- buf.append(QLatin1Char(' ') + currentAtt->name());
- }
- uDebug() << " UMLClassifier::takeItem (before): m_List is " << buf;
-
- int index = m_List.indexOf(item);
- if (index == -1) {
- return -1;
- }
- switch (item->baseType()) {
- case UMLObject::ot_Operation: {
- if (removeOperation(dynamic_cast<UMLOperation*>(item)) < 0) {
- index = -1;
- }
- break;
- }
- case UMLObject::ot_Attribute: {
- UMLAttribute *retval = dynamic_cast<UMLAttribute*>(m_List.takeAt(index).data());
- if (retval) {
- emit attributeRemoved(retval);
- UMLObject::emitModified();
- } else {
- index = -1;
- }
- break;
- }
- case UMLObject::ot_Template: {
- UMLTemplate *templt = dynamic_cast<UMLTemplate*>(m_List.takeAt(index).data());
- if (templt) {
- emit templateRemoved(templt);
- UMLObject::emitModified();
- } else {
- index = -1;
- }
- break;
- }
- case UMLObject::ot_EnumLiteral: {
- UMLEnumLiteral *el = dynamic_cast<UMLEnumLiteral*>(m_List.takeAt(index).data());
- if (el) {
- UMLEnum *e = static_cast<UMLEnum*>(this);
- e->signalEnumLiteralRemoved(el);
- UMLObject::emitModified();
- } else {
- index = -1;
- }
- break;
- }
- case UMLObject::ot_EntityAttribute: {
- UMLEntityAttribute* el = dynamic_cast<UMLEntityAttribute*>(m_List.takeAt(index).data());
- if (el) {
- UMLEntity *e = static_cast<UMLEntity*>(this);
- e->signalEntityAttributeRemoved(el);
- UMLObject::emitModified();
- } else {
- index = -1;
- }
- break;
- }
- default:
- index = -1;
- break;
- }
- return index;
-}
-
-/**
- * Set the origin type (in case of e.g. typedef)
- * @param origType the origin type to set
- */
-void UMLClassifier::setOriginType(UMLClassifier *origType)
-{
- m_pSecondary = origType;
-}
-
-/**
- * Get the origin type (in case of e.g. typedef)
- * @return the origin type
- */
-UMLClassifier * UMLClassifier::originType() const
-{
- return dynamic_cast<UMLClassifier*>(m_pSecondary.data());
-}
-
-/**
- * Set the m_isRef flag (true when dealing with a pointer type)
- * @param isRef the flag to set
- */
-void UMLClassifier::setIsReference(bool isRef)
-{
- m_isRef = isRef;
-}
-
-/**
- * Get the m_isRef flag.
- * @return true if is reference, otherwise false
- */
-bool UMLClassifier::isReference() const
-{
- return m_isRef;
-}
-
-/**
- * Return true if this classifier has associations.
- * @return true if classifier has associations
- */
-bool UMLClassifier::hasAssociations()
-{
- return getSpecificAssocs(AssociationType::Association).count() > 0
- || getAggregations().count() > 0
- || getCompositions().count() > 0
- || getUniAssociationToBeImplemented().count() > 0;
-}
-
-/**
- * Return true if this classifier has attributes.
- */
-bool UMLClassifier::hasAttributes()
-{
- return getAttributeList(Uml::Visibility::Public).count() > 0
- || getAttributeList(Uml::Visibility::Protected).count() > 0
- || getAttributeList(Uml::Visibility::Private).count() > 0
- || getAttributeListStatic(Uml::Visibility::Public).count() > 0
- || getAttributeListStatic(Uml::Visibility::Protected).count() > 0
- || getAttributeListStatic(Uml::Visibility::Private).count() > 0;
-}
-
-/**
- * Return true if this classifier has static attributes.
- */
-bool UMLClassifier::hasStaticAttributes()
-{
- return getAttributeListStatic(Uml::Visibility::Public).count() > 0
- || getAttributeListStatic(Uml::Visibility::Protected).count() > 0
- || getAttributeListStatic(Uml::Visibility::Private).count() > 0;
-}
-
-/**
- * Return true if this classifier has accessor methods.
- */
-bool UMLClassifier::hasAccessorMethods()
-{
- return hasAttributes() || hasAssociations();
-}
-
-/**
- * Return true if this classifier has operation methods.
- */
-bool UMLClassifier::hasOperationMethods()
-{
- return getOpList().last() ? true : false;
-}
-
-/**
- * Return true if this classifier has methods.
- */
-bool UMLClassifier::hasMethods()
-{
- return hasOperationMethods() || hasAccessorMethods();
-}
-
-// this is a bit too simplistic..some associations are for
-// SINGLE objects, and WONT be declared as Vectors, so this
-// is a bit overly inclusive (I guess that's better than the other way around)
-
-/**
- * Return true if this classifier has vector fields.
- */
-bool UMLClassifier::hasVectorFields()
-{
- return hasAssociations();
-}
-
-/**
- * Return the list of unidirectional association that should show up in the code
- */
-UMLAssociationList UMLClassifier::getUniAssociationToBeImplemented()
-{
- UMLAssociationList associations = getSpecificAssocs(AssociationType::UniAssociation);
- UMLAssociationList uniAssocListToBeImplemented;
-
- foreach (UMLAssociation *a, associations) {
- uIgnoreZeroPointer(a);
- if (a->getObjectId(RoleType::B) == id()) {
- continue; // we need to be at the A side
- }
- QString roleNameB = a->getRoleName(RoleType::B);
- if (!roleNameB.isEmpty()) {
- UMLAttributeList atl = getAttributeList();
- bool found = false;
- //make sure that an attribute with the same name doesn't already exist
- foreach (UMLAttribute *at, atl) {
- uIgnoreZeroPointer(a);
- if (at->name() == roleNameB) {
- found = true;
- break;
- }
- }
- if (!found) {
- uniAssocListToBeImplemented.append(a);
- }
- }
- }
- return uniAssocListToBeImplemented;
-}
-
-/**
- * Creates XML tag <UML:Class>, <UML:Interface>, or <UML:DataType>
- * depending on m_BaseType.
- * Saves possible template parameters, generalizations, attributes,
- * operations, and contained objects to the given QDomElement.
- */
-void UMLClassifier::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QString tag;
- switch (m_BaseType) {
- case UMLObject::ot_Class:
- tag = QLatin1String("UML:Class");
- break;
- case UMLObject::ot_Interface:
- tag = QLatin1String("UML:Interface");
- break;
- case UMLObject::ot_Datatype:
- tag = QLatin1String("UML:DataType");
- break;
- case UMLObject::ot_Package:
- UMLPackage::saveToXMI(qDoc, qElement);
- return;
- break;
- default:
- uError() << "internal error: basetype is " << m_BaseType;
- return;
- }
- QDomElement classifierElement = UMLObject::save(tag, qDoc);
- if (m_BaseType == UMLObject::ot_Datatype && m_pSecondary != NULL)
- classifierElement.setAttribute(QLatin1String("elementReference"),
- Uml::ID::toString(m_pSecondary->id()));
-
- //save templates
- UMLClassifierListItemList list = getFilteredList(UMLObject::ot_Template);
- if (list.count()) {
- QDomElement tmplElement = qDoc.createElement(QLatin1String("UML:ModelElement.templateParameter"));
- foreach (UMLClassifierListItem *tmpl, list) {
- tmpl->saveToXMI(qDoc, tmplElement);
- }
- classifierElement.appendChild(tmplElement);
- }
-
- //save generalizations (we are the subclass, the other end is the superclass)
- UMLAssociationList generalizations = getSpecificAssocs(AssociationType::Generalization);
- if (generalizations.count()) {
- QDomElement genElement = qDoc.createElement(QLatin1String("UML:GeneralizableElement.generalization"));
- foreach (UMLAssociation *a, generalizations) {
- // We are the subclass if we are at the role A end.
- if (m_nId != a->getObjectId(RoleType::A)) {
- continue;
- }
- QDomElement gElem = qDoc.createElement(QLatin1String("UML:Generalization"));
- gElem.setAttribute(QLatin1String("xmi.idref"), Uml::ID::toString(a->id()));
- genElement.appendChild(gElem);
- }
- if (genElement.hasChildNodes()) {
- classifierElement.appendChild(genElement);
- }
- }
-
- // save attributes
- QDomElement featureElement = qDoc.createElement(QLatin1String("UML:Classifier.feature"));
- UMLClassifierListItemList attList = getFilteredList(UMLObject::ot_Attribute);
- foreach (UMLClassifierListItem *pAtt, attList) {
- pAtt->saveToXMI(qDoc, featureElement);
- }
-
- // save operations
- UMLOperationList opList = getOpList();
- foreach (UMLOperation *pOp, opList) {
- pOp->saveToXMI(qDoc, featureElement);
- }
- if (featureElement.hasChildNodes()) {
- classifierElement.appendChild(featureElement);
- }
-
- // save contained objects
- if (m_objects.count()) {
- QDomElement ownedElement = qDoc.createElement(QLatin1String("UML:Namespace.ownedElement"));
- foreach (UMLObject* obj, m_objects) {
- uIgnoreZeroPointer(obj);
- obj->saveToXMI (qDoc, ownedElement);
- }
- classifierElement.appendChild(ownedElement);
- }
- qElement.appendChild(classifierElement);
-}
-
-/**
- * Create a new ClassifierListObject (attribute, operation, template)
- * according to the given XMI tag.
- * Returns NULL if the string given does not contain one of the tags
- * <UML:Attribute>, <UML:Operation>, or <UML:TemplateParameter>.
- * Used by the clipboard for paste operation.
- */
-UMLClassifierListItem* UMLClassifier::makeChildObject(const QString& xmiTag)
-{
- UMLClassifierListItem* pObject = NULL;
- if (UMLDoc::tagEq(xmiTag, QLatin1String("Operation")) ||
- UMLDoc::tagEq(xmiTag, QLatin1String("ownedOperation"))) {
- pObject = new UMLOperation(this);
- } else if (UMLDoc::tagEq(xmiTag, QLatin1String("Attribute")) ||
- UMLDoc::tagEq(xmiTag, QLatin1String("ownedAttribute"))) {
- if (baseType() != UMLObject::ot_Class)
- return NULL;
- pObject = new UMLAttribute(this);
- } else if (UMLDoc::tagEq(xmiTag, QLatin1String("TemplateParameter"))) {
- pObject = new UMLTemplate(this);
- }
- return pObject;
-}
-
-/**
- * Auxiliary to loadFromXMI:
- * The loading of operations is implemented here.
- * Calls loadSpecialized() for any other tag.
- * Child classes can override the loadSpecialized method
- * to load its additional tags.
- */
-bool UMLClassifier::load(QDomElement& element)
-{
- UMLClassifierListItem *child = NULL;
- m_SecondaryId = element.attribute(QLatin1String("elementReference"));
- if (!m_SecondaryId.isEmpty()) {
- // @todo We do not currently support composition.
- m_isRef = true;
- }
- bool totalSuccess = true;
- for (QDomNode node = element.firstChild(); !node.isNull();
- node = node.nextSibling()) {
- if (node.isComment())
- continue;
- element = node.toElement();
- QString tag = element.tagName();
- QString stereotype = element.attribute(QLatin1String("stereotype"));
- if (UMLDoc::tagEq(tag, QLatin1String("ModelElement.templateParameter")) ||
- UMLDoc::tagEq(tag, QLatin1String("Classifier.feature")) ||
- UMLDoc::tagEq(tag, QLatin1String("Namespace.ownedElement")) ||
- UMLDoc::tagEq(tag, QLatin1String("Element.ownedElement")) || // Embarcadero's Describe
- UMLDoc::tagEq(tag, QLatin1String("Namespace.contents"))) {
- load(element);
- // Not evaluating the return value from load()
- // because we want a best effort.
-
- } else if ((child = makeChildObject(tag)) != NULL) {
- if (child->loadFromXMI(element)) {
- switch (child->baseType()) {
- case UMLObject::ot_Template:
- addTemplate(static_cast<UMLTemplate*>(child));
- break;
- case UMLObject::ot_Operation:
- if (! addOperation(static_cast<UMLOperation*>(child))) {
- uError() << "error from addOperation(op)";
- delete child;
- totalSuccess = false;
- }
- break;
- case UMLObject::ot_Attribute:
- addAttribute(static_cast<UMLAttribute*>(child));
- break;
- default:
- break;
- }
- } else {
- uWarning() << "failed to load " << tag;
- delete child;
- totalSuccess = false;
- }
- } else if (!Model_Utils::isCommonXMIAttribute(tag)) {
- UMLObject *pObject = Object_Factory::makeObjectFromXMI(tag, stereotype);
- if (pObject == NULL) {
- // Not setting totalSuccess to false
- // because we want a best effort.
- continue;
- }
- pObject->setUMLPackage(this);
- if (! pObject->loadFromXMI(element)) {
- removeObject(pObject);
- delete pObject;
- totalSuccess = false;
- }
- }
- }
- return totalSuccess;
-}
-
-/*
-UMLClassifierList UMLClassifier::getPlainAssocChildClassifierList()
-{
- UMLAssociationList plainAssociations = getSpecificAssocs(Uml::AssociationType::Association);
- return findAssocClassifierObjsInRoles(&plainAssociations);
-}
-
-UMLClassifierList UMLClassifier::getAggregateChildClassifierList()
-{
- UMLAssociationList aggregations = getAggregations();
- return findAssocClassifierObjsInRoles(&aggregations);
-}
-
-UMLClassifierList UMLClassifier::getCompositionChildClassifierList()
-{
- UMLAssociationList compositions = getCompositions();
- return findAssocClassifierObjsInRoles(&compositions);
-}
-
-UMLClassifierList UMLClassifier::findAssocClassifierObjsInRoles (UMLAssociationList * list)
-{
- UMLClassifierList classifiers;
-
- for (UMLAssociationListIt alit(*list); alit.hasNext(); ) {
- UMLAssociation* a = alit.next();
- // DON'T accept a classifier IF the association role is empty, by
- // convention, that means to ignore the classifier on that end of
- // the association.
- // We also ignore classifiers which are the same as the current one
- // (e.g. id matches), we only want the "other" classifiers
- if (a->getObjectId(RoleType::A) == id() && !a->getRoleName(RoleType::B).isEmpty()) {
- UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(RoleType::B));
- if(c)
- classifiers.append(c);
- } else if (a->getObjectId(RoleType::B) == id() && !a->getRoleName(RoleType::A).isEmpty()) {
- UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(RoleType::A));
- if(c)
- classifiers.append(c);
- }
- }
-
- return classifiers;
-}
-*/
-
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/classifier.h umbrello-kf6-15.08.1/umbrello/classifier.h
--- umbrello-kf6-15.08.1.orig/umbrello/classifier.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/classifier.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,199 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-#ifndef CLASSIFIER_H
-#define CLASSIFIER_H
-
-#include "package.h"
-#include "umlattributelist.h"
-#include "umloperationlist.h"
-#include "umlclassifierlistitemlist.h"
-#include "classifierlistitem.h"
-#include "umltemplatelist.h"
-#include "model_utils.h"
-
-// forward declarations
-class UMLAssociation;
-class IDChangeLog;
-class UMLClassifierSet;
-
-/**
- * This class defines the non-graphical information required for a
- * UML Classifier (ie a class or interface).
- * This class inherits from @ref UMLPackage which allows classifiers
- * to also act as namespaces, i.e. it allows classifiers to nest.
- *
- * NOTE: There is a unit test available for this class.
- * Please, use and adapt it when necessary.
- *
- * @short Information for a non-graphical Concept/Class.
- * @author Paul Hensgen <phensgen@techie.com>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLClassifier : public UMLPackage
-{
- Q_OBJECT
-public:
-
- /**
- * Enumeration identifying the type of classifier.
- */
- enum ClassifierType { ALL = 0, CLASS, INTERFACE, DATATYPE };
-
- explicit UMLClassifier(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLClassifier();
-
- bool operator==(const UMLClassifier & rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- UMLObject* clone() const;
-
- virtual UMLAttribute* createAttribute(const QString &name = QString(),
- UMLObject *type = 0,
- Uml::Visibility::Enum vis = Uml::Visibility::Private,
- const QString &init = QString());
-
- UMLAttribute* addAttribute(const QString &name, Uml::ID::Type id = Uml::ID::None);
- UMLAttribute* addAttribute(const QString &name, UMLObject *type, Uml::Visibility::Enum scope);
-
- bool addAttribute(UMLAttribute* att, IDChangeLog* log = 0,
- int position = -1);
-
- int removeAttribute(UMLAttribute *att);
-
- int attributes() ;
-
- UMLAttributeList getAttributeList() const;
- UMLAttributeList getAttributeList(Uml::Visibility::Enum scope) const;
- UMLAttributeList getAttributeListStatic(Uml::Visibility::Enum scope) const;
-
- UMLOperation* createOperation(const QString &name = QString(),
- bool *isExistingOp = NULL,
- Model_Utils::NameAndType_List *params = NULL);
-
- bool addOperation(UMLOperation* op, int position = -1);
- bool addOperation(UMLOperation* op, IDChangeLog* log);
-
- UMLOperation * checkOperationSignature(const QString& name,
- UMLAttributeList opParams,
- UMLOperation *exemptOp = NULL);
-
- int removeOperation(UMLOperation *op);
-
- int operations();
-
- UMLOperationList getOpList(bool includeInherited = false, UMLClassifierSet *alreadyTraversed = 0);
-
- UMLObject* createTemplate(const QString& name = QString());
-
- UMLTemplate* addTemplate(const QString &name, Uml::ID::Type id = Uml::ID::None);
-
- bool addTemplate(UMLTemplate* newTemplate, IDChangeLog* log = 0);
- bool addTemplate(UMLTemplate* templt, int position);
-
- int removeTemplate(UMLTemplate* umltemplate);
-
- UMLTemplate *findTemplate(const QString& name);
-
- int templates();
-
- UMLTemplateList getTemplateList() const;
-
- int takeItem(UMLClassifierListItem* item);
-
- virtual UMLClassifierListItemList getFilteredList(UMLObject::ObjectType ot) const;
-
- virtual bool resolveRef();
-
- UMLOperationList findOperations(const QString &n);
-
- virtual UMLObject* findChildObjectById(Uml::ID::Type id, bool considerAncestors = false);
-
- UMLOperation* findOperation(const QString& name,
- Model_Utils::NameAndType_List params);
-
- UMLClassifierList findSuperClassConcepts(ClassifierType type = ALL);
-
- UMLClassifierList findSubClassConcepts(ClassifierType type = ALL);
-
- virtual bool acceptAssociationType(Uml::AssociationType::Enum type);
-
- void setClassAssoc(UMLAssociation *assoc);
- UMLAssociation *getClassAssoc() const;
-
- void setBaseType(UMLObject::ObjectType ot);
-
- bool isInterface() const;
-
- bool isDatatype() const;
-
- void setOriginType(UMLClassifier *origType);
- UMLClassifier * originType() const;
-
- void setIsReference(bool isRef = true);
- bool isReference() const;
-
- bool hasAbstractOps();
- bool hasAssociations();
- bool hasAttributes();
- bool hasStaticAttributes();
- bool hasMethods();
- bool hasAccessorMethods();
- bool hasOperationMethods();
- bool hasVectorFields();
-
- /**
- * utility functions to allow easy determination of what classifiers
- * are "owned" by the current one via named association type (e.g.
- * plain, aggregate or compositions).
- */
-// UMLClassifierList getPlainAssocChildClassifierList();
-// UMLClassifierList getAggregateChildClassifierList();
-// UMLClassifierList getCompositionChildClassifierList();
-
- virtual UMLClassifierListItem* makeChildObject(const QString& xmiTag);
-
- virtual UMLAssociationList getUniAssociationToBeImplemented();
-
-signals:
-
- void operationAdded(UMLClassifierListItem *);
- void operationRemoved(UMLClassifierListItem *);
-
- void templateAdded(UMLClassifierListItem*);
- void templateRemoved(UMLClassifierListItem*);
-
- // only applies when (m_Type == ot_Class)
- void attributeAdded(UMLClassifierListItem*);
- void attributeRemoved(UMLClassifierListItem*);
-
-private:
-
- UMLAssociation *m_pClassAssoc;
-
- bool m_isRef;
-
- /**
- * Utility method called by "get*ChildClassfierList()" methods. It basically
- * finds all the classifiers named in each association in the given association list
- * which aren't the current one. Useful for finding which classifiers are "owned" by the
- * current one via declared associations such as in aggregations/compositions.
- */
-// UMLClassifierList findAssocClassifierObjsInRoles (UMLAssociationList * list);
-
-protected:
-
- void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
- virtual bool load(QDomElement& element);
-
-};
-
-#endif // CLASSIFIER_H
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/classifierlistitem.cpp umbrello-kf6-15.08.1/umbrello/classifierlistitem.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/classifierlistitem.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/classifierlistitem.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,159 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "classifierlistitem.h"
-
-// local includes
-#include "debug_utils.h"
-#include "classifier.h"
-#include "model_utils.h"
-#include "object_factory.h"
-#include "uml.h"
-#include "umldoc.h"
-
-// kde includes
-#include <KLocalizedString>
-
-/**
- * Constructor.
- *
- * @param parent The parent to this operation.
- * At first sight it would appear that the type of the
- * parent should be UMLClassifier. However, the class
- * UMLAttribute is also used for the parameters of
- * operations, and in this case the UMLOperation is the
- * parent.
- * @param name The name of the operation.
- * @param id The id of the operation.
- */
-UMLClassifierListItem::UMLClassifierListItem(UMLObject *parent,
- const QString& name, Uml::ID::Type id)
- : UMLObject(parent, name, id)
-{
- UMLObject *parentObj = const_cast<UMLObject*>(parent);
- UMLClassifier *pc = dynamic_cast<UMLClassifier*>(parentObj);
- if (pc)
- UMLObject::setUMLPackage(pc);
-}
-
-/**
- * Constructor.
- *
- * @param parent The parent to this operation.
- * At first sight it would appear that the type of the
- * parent should be UMLClassifier. However, the class
- * UMLAttribute is also used for the parameters of
- * operations, and in this case the UMLOperation is the
- * parent.
- */
-UMLClassifierListItem::UMLClassifierListItem(UMLObject *parent)
- : UMLObject(parent)
-{
- UMLObject *parentObj = const_cast<UMLObject*>(parent);
- UMLClassifier *pc = dynamic_cast<UMLClassifier*>(parentObj);
- if (pc)
- UMLObject::setUMLPackage(pc);
-}
-
-/**
- * Destructor. Empty.
- */
-UMLClassifierListItem::~UMLClassifierListItem()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLClassifierListItem::copyInto(UMLObject *lhs) const
-{
- // Call the parent.
- UMLObject::copyInto(lhs);
-}
-
-/**
- * Returns a string representation of the list item.
- *
- * @param sig What type of operation string to show.
- * @return The string representation of the operation.
- */
-QString UMLClassifierListItem::toString(Uml::SignatureType::Enum sig)
-{
- Q_UNUSED(sig);
- return name();
-}
-
-/**
- * Returns the type of the UMLClassifierListItem.
- *
- * @return The type of the UMLClassifierListItem.
- */
-UMLClassifier * UMLClassifierListItem::getType() const
-{
- return dynamic_cast<UMLClassifier*>(m_pSecondary.data());
-}
-
-/**
- * Returns the type name of the UMLClassifierListItem.
- *
- * @return The type name of the UMLClassifierListItem.
- */
-QString UMLClassifierListItem::getTypeName() const
-{
- if (m_pSecondary == NULL)
- return m_SecondaryId;
- const UMLPackage *typePkg = m_pSecondary->umlPackage();
- if (typePkg != NULL && typePkg != m_pUMLPackage)
- return m_pSecondary->fullyQualifiedName();
- return m_pSecondary->name();
-}
-
-/**
- * Sets the type of the UMLAttribute.
- *
- * @param type Pointer to the UMLObject of the type.
- */
-void UMLClassifierListItem::setType(UMLObject *type)
-{
- if (m_pSecondary != type) {
- m_pSecondary = type;
- UMLObject::emitModified();
- }
-}
-
-/**
- * Sets the type name of the UMLClassifierListItem.
- * DEPRECATED - use setType() instead.
- *
- * @param type The type name of the UMLClassifierListItem.
- */
-void UMLClassifierListItem::setTypeName(const QString &type)
-{
- if (type.isEmpty() || type == QLatin1String("void")) {
- m_pSecondary = NULL;
- m_SecondaryId.clear();
- return;
- }
- UMLDoc *pDoc = UMLApp::app()->document();
- m_pSecondary = pDoc->findUMLObject(type);
- if (m_pSecondary == NULL) {
- // Make data type for easily identified cases
- if (Model_Utils::isCommonDataType(type) || type.contains(QLatin1Char('*'))) {
- m_pSecondary = Object_Factory::createUMLObject(UMLObject::ot_Datatype, type);
- uDebug() << "created datatype for " << type;
- } else {
- m_SecondaryId = type;
- }
- }
- UMLObject::emitModified();
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/classifierlistitem.h umbrello-kf6-15.08.1/umbrello/classifierlistitem.h
--- umbrello-kf6-15.08.1.orig/umbrello/classifierlistitem.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/classifierlistitem.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,58 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef CLASSIFIERLISTITEM_H
-#define CLASSIFIERLISTITEM_H
-
-#include "umlobject.h"
-
-// forward declaration
-class UMLClassifier;
-
-/**
- * Classifiers (classes, interfaces) have lists of operations,
- * attributes, templates and others. This is a base class for
- * the items in this list. This abstraction should remove
- * duplication of dialogs and allow for stereotypes in lists.
- *
- * @short A base class for classifier list items (e.g. attributes)
- * @author Jonathan Riddell
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLClassifierListItem : public UMLObject
-{
- Q_OBJECT
-public:
-
- UMLClassifierListItem(UMLObject *parent,
- const QString& name,
- Uml::ID::Type id = Uml::ID::None);
- explicit UMLClassifierListItem(UMLObject *parent);
- virtual ~UMLClassifierListItem();
-
- virtual void setType(UMLObject *type);
- UMLClassifier * getType() const;
-
- void setTypeName(const QString &type);
- virtual QString getTypeName() const;
-
- virtual QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
-
- virtual void copyInto(UMLObject *lhs) const;
-
- /**
- * The abstract method UMLObject::clone() must be implemented
- * by the classes inheriting from UMLClassifierListItem.
- */
- virtual UMLObject* clone() const = 0;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/CMakeLists.txt umbrello-kf6-15.08.1/umbrello/CMakeLists.txt
--- umbrello-kf6-15.08.1.orig/umbrello/CMakeLists.txt 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/CMakeLists.txt 2015-10-08 11:48:59.486089026 +0300
@@ -56,7 +56,8 @@
${CMAKE_CURRENT_SOURCE_DIR}/docgenerators/
${CMAKE_CURRENT_SOURCE_DIR}/finder/
${CMAKE_CURRENT_SOURCE_DIR}/refactoring/
- ${CMAKE_CURRENT_SOURCE_DIR}/widgets/
+ ${CMAKE_CURRENT_SOURCE_DIR}/umlmodel/
+ ${CMAKE_CURRENT_SOURCE_DIR}/umlwidgets/
${CMAKE_SOURCE_DIR}/lib/cppparser/
${CMAKE_SOURCE_DIR}/lib/interfaces/
)
@@ -343,47 +344,47 @@
cmds/widget/cmd_setTxt.cpp
)
-set(libwidgets_SRCS
- widgets/activitywidget.cpp
- widgets/actorwidget.cpp
- widgets/artifactwidget.cpp
- widgets/associationline.cpp
- widgets/associationwidget.cpp
- widgets/boxwidget.cpp
- widgets/categorywidget.cpp
- widgets/classifierwidget.cpp
- widgets/combinedfragmentwidget.cpp
- widgets/componentwidget.cpp
- widgets/datatypewidget.cpp
- widgets/entitywidget.cpp
- widgets/enumwidget.cpp
- widgets/floatingdashlinewidget.cpp
- widgets/floatingtextwidget.cpp
- widgets/forkjoinwidget.cpp
- widgets/layoutgrid.cpp
- widgets/linkwidget.cpp
- widgets/messagewidget.cpp
- widgets/nodewidget.cpp
- widgets/notewidget.cpp
- widgets/objectnodewidget.cpp
- widgets/objectwidget.cpp
- widgets/packagewidget.cpp
- widgets/pinportbase.cpp
- widgets/pinwidget.cpp
- widgets/portwidget.cpp
- widgets/preconditionwidget.cpp
- widgets/regionwidget.cpp
- widgets/seqlinewidget.cpp
- widgets/signalwidget.cpp
- widgets/statewidget.cpp
- widgets/toolbarstateonewidget.cpp
- widgets/umlwidget.cpp
- widgets/usecasewidget.cpp
- widgets/widget_factory.cpp
- widgets/widget_utils.cpp
- widgets/widgetbase.cpp
- widgets/widgetlist_utils.cpp
- widgets/statusbartoolbutton.cpp
+set(libumlwidgets_SRCS
+ umlwidgets/activitywidget.cpp
+ umlwidgets/actorwidget.cpp
+ umlwidgets/artifactwidget.cpp
+ umlwidgets/associationline.cpp
+ umlwidgets/associationwidget.cpp
+ umlwidgets/boxwidget.cpp
+ umlwidgets/categorywidget.cpp
+ umlwidgets/classifierwidget.cpp
+ umlwidgets/combinedfragmentwidget.cpp
+ umlwidgets/componentwidget.cpp
+ umlwidgets/datatypewidget.cpp
+ umlwidgets/entitywidget.cpp
+ umlwidgets/enumwidget.cpp
+ umlwidgets/floatingdashlinewidget.cpp
+ umlwidgets/floatingtextwidget.cpp
+ umlwidgets/forkjoinwidget.cpp
+ umlwidgets/layoutgrid.cpp
+ umlwidgets/linkwidget.cpp
+ umlwidgets/messagewidget.cpp
+ umlwidgets/nodewidget.cpp
+ umlwidgets/notewidget.cpp
+ umlwidgets/objectnodewidget.cpp
+ umlwidgets/objectwidget.cpp
+ umlwidgets/packagewidget.cpp
+ umlwidgets/pinportbase.cpp
+ umlwidgets/pinwidget.cpp
+ umlwidgets/portwidget.cpp
+ umlwidgets/preconditionwidget.cpp
+ umlwidgets/regionwidget.cpp
+ umlwidgets/seqlinewidget.cpp
+ umlwidgets/signalwidget.cpp
+ umlwidgets/statewidget.cpp
+ umlwidgets/toolbarstateonewidget.cpp
+ umlwidgets/umlwidget.cpp
+ umlwidgets/usecasewidget.cpp
+ umlwidgets/widget_factory.cpp
+ umlwidgets/widget_utils.cpp
+ umlwidgets/widgetbase.cpp
+ umlwidgets/widgetlist_utils.cpp
+ umlwidgets/statusbartoolbutton.cpp
)
set(libfinder_SRCS
@@ -394,47 +395,60 @@
finder/umlscenefinder.cpp
)
-########### next target ###############
+set(libuml_SRCS
+ umlmodel/actor.cpp
+ umlmodel/artifact.cpp
+ umlmodel/association.cpp
+ umlmodel/attribute.cpp
+ umlmodel/category.cpp
+ umlmodel/checkconstraint.cpp
+ umlmodel/classifier.cpp
+ umlmodel/classifierlistitem.cpp
+ umlmodel/component.cpp
+ umlmodel/entity.cpp
+ umlmodel/entityattribute.cpp
+ umlmodel/entityconstraint.cpp
+ umlmodel/enum.cpp
+ umlmodel/enumliteral.cpp
+ umlmodel/folder.cpp
+ umlmodel/foreignkeyconstraint.cpp
+ umlmodel/node.cpp
+ umlmodel/operation.cpp
+ umlmodel/package.cpp
+ umlmodel/port.cpp
+ umlmodel/stereotype.cpp
+ umlmodel/template.cpp
+ umlmodel/umlattributelist.cpp
+ umlmodel/umlcanvasobject.cpp
+ umlmodel/umlclassifierlistitemlist.cpp
+ umlmodel/umlentityattributelist.cpp
+ umlmodel/umlentityconstraintlist.cpp
+ umlmodel/umlobject.cpp
+ umlmodel/umlobjectlist.cpp
+ umlmodel/umlrole.cpp
+ umlmodel/usecase.cpp
+ umlmodel/uniqueconstraint.cpp
+)
set(umbrello-kf6base_SRCS
- actor.cpp
- artifact.cpp
- association.cpp
assocrules.cpp
- attribute.cpp
basictypes.cpp
birdview.cpp
- category.cpp
- checkconstraint.cpp
- classifier.cpp
- classifierlistitem.cpp
cmdlineexportallviewsevent.cpp
- component.cpp
docwindow.cpp
dotgenerator.cpp
- entity.cpp
- entityattribute.cpp
- entityconstraint.cpp
- enum.cpp
- enumliteral.cpp
- folder.cpp
- foreignkeyconstraint.cpp
icon_utils.cpp
import_argo.cpp
import_rose.cpp
layoutgenerator.cpp
listpopupmenu.cpp
model_utils.cpp
- node.cpp
object_factory.cpp
- operation.cpp
optionstate.cpp
- package.cpp
petalnode.cpp
petaltree2uml.cpp
- port.cpp
- stereotype.cpp
- template.cpp
+ stereotypeswindow.cpp
+ stereotypesmodel.cpp
toolbarstatearrow.cpp
toolbarstateassociation.cpp
toolbarstate.cpp
@@ -443,26 +457,16 @@
toolbarstateother.cpp
toolbarstatepool.cpp
umlappprivate.cpp
- umlattributelist.cpp
- umlcanvasobject.cpp
- umlclassifierlistitemlist.cpp
uml.cpp
umldoc.cpp
- umlentityattributelist.cpp
- umlentityconstraintlist.cpp
umllistview.cpp
umllistviewitem.cpp
- umlobject.cpp
- umlobjectlist.cpp
- umlrole.cpp
umlscene.cpp
umlview.cpp
umlviewimageexporterall.cpp
umlviewimageexporter.cpp
umlviewimageexportermodel.cpp
- uniqueconstraint.cpp
uniqueid.cpp
- usecase.cpp
worktoolbar.cpp
)
@@ -482,7 +486,8 @@
${libcodegenerator_SRCS}
${libdocgenerator_SRCS}
${libcmds_SRCS}
- ${libwidgets_SRCS}
+ ${libuml_SRCS}
+ ${libumlwidgets_SRCS}
${umbrello-kf6base_SRCS}
)
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/component.cpp umbrello-kf6-15.08.1/umbrello/component.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/component.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/component.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,127 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "component.h"
-// app includes
-#include "association.h"
-#include "debug_utils.h"
-#include "object_factory.h"
-#include "model_utils.h"
-#include "clipboard/idchangelog.h"
-#include "umldoc.h"
-// kde includes
-#include <KLocalizedString>
-
-/**
- * Sets up a Component.
- * @param name The name of the Concept.
- * @param id The unique id of the Concept.
- */
-UMLComponent::UMLComponent(const QString & name, Uml::ID::Type id)
- : UMLPackage(name, id),
- m_executable(false)
-{
- m_BaseType = UMLObject::ot_Component;
-}
-
-/**
- * Destructor.
- */
-UMLComponent::~UMLComponent()
-{
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLComponent::clone() const
-{
- UMLComponent *clone = new UMLComponent();
- UMLObject::copyInto(clone);
- return clone;
-}
-
-/**
- * Creates the UML:Component element including its operations,
- * attributes and templates
- */
-void UMLComponent::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement componentElement = UMLObject::save(QLatin1String("UML:Component"), qDoc);
- componentElement.setAttribute(QLatin1String("executable"), m_executable);
- // Save contained components if any.
- if (m_objects.count()) {
- QDomElement ownedElement = qDoc.createElement(QLatin1String("UML:Namespace.ownedElement"));
- for (UMLObjectListIt objectsIt(m_objects); objectsIt.hasNext();) {
- UMLObject* obj = objectsIt.next();
- uIgnoreZeroPointer(obj);
- obj->saveToXMI (qDoc, ownedElement);
- }
- componentElement.appendChild(ownedElement);
- }
- qElement.appendChild(componentElement);
-}
-
-/**
- * Loads the UML:Component element including its ports et al.
- */
-bool UMLComponent::load(QDomElement& element)
-{
- QString executable = element.attribute(QLatin1String("executable"), QLatin1String("0"));
- m_executable = (bool)executable.toInt();
- for (QDomNode node = element.firstChild(); !node.isNull();
- node = node.nextSibling()) {
- if (node.isComment())
- continue;
- QDomElement tempElement = node.toElement();
- QString type = tempElement.tagName();
- if (Model_Utils::isCommonXMIAttribute(type))
- continue;
- if (UMLDoc::tagEq(type, QLatin1String("Namespace.ownedElement")) ||
- UMLDoc::tagEq(type, QLatin1String("Namespace.contents"))) {
- //CHECK: umbrello-kf6 currently assumes that nested elements
- // are ownedElements anyway.
- // Therefore these tags are not further interpreted.
- if (! load(tempElement))
- return false;
- continue;
- }
- UMLObject *pObject = Object_Factory::makeObjectFromXMI(type);
- if (!pObject) {
- uWarning() << "Unknown type of umlobject to create: " << type;
- continue;
- }
- pObject->setUMLPackage(this);
- if (pObject->loadFromXMI(tempElement)) {
- addObject(pObject);
- } else {
- delete pObject;
- }
- }
- return true;
-}
-
-/**
- * Sets m_executable.
- */
-void UMLComponent::setExecutable(bool executable)
-{
- m_executable = executable;
-}
-
-/**
- * Returns the value of m_executable.
- */
-bool UMLComponent::getExecutable()
-{
- return m_executable;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/component.h umbrello-kf6-15.08.1/umbrello/component.h
--- umbrello-kf6-15.08.1.orig/umbrello/component.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/component.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,48 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef COMPONENT_H
-#define COMPONENT_H
-
-#include "package.h"
-
-/**
- * This class contains the non-graphical information required for a
- * UML Component.
- * This class inherits from @ref UMLPackage which contains most
- * of the information.
- *
- * @short Non-graphical information for a Component.
- * @author Jonathan Riddell
- * @see UMLCanvasObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLComponent : public UMLPackage
-{
- Q_OBJECT
-public:
- explicit UMLComponent(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLComponent();
-
- virtual UMLObject* clone() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- void setExecutable(bool executable);
- bool getExecutable();
-
-protected:
- bool load(QDomElement & element);
-
-private:
- bool m_executable; ///< holds whether this is an executable component or not
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/dialogs/notedialog.cpp umbrello-kf6-15.08.1/umbrello/dialogs/notedialog.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/dialogs/notedialog.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/dialogs/notedialog.cpp 2015-10-08 11:48:59.497089026 +0300
@@ -36,6 +36,7 @@
QVBoxLayout *layout = new QVBoxLayout(frame);
layout->addWidget(m_docWidget, 10);
setMinimumSize(600, 250);
+ m_docWidget->setFocus();
}
/**
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/dialogs/widgets/documentationwidget.cpp umbrello-kf6-15.08.1/umbrello/dialogs/widgets/documentationwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/dialogs/widgets/documentationwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/dialogs/widgets/documentationwidget.cpp 2015-10-08 11:48:59.499089026 +0300
@@ -67,6 +67,8 @@
m_editField->setLineWrapMode(QTextEdit::WidgetWidth);
m_editField->setWordWrapMode(QTextOption::WordWrap);
m_editField->setText(text);
+ setFocusProxy(m_editField);
+
QHBoxLayout *layout = new QHBoxLayout(m_box);
layout->addWidget(m_editField);
layout->setMargin(fontMetrics().height());
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/docwindow.cpp umbrello-kf6-15.08.1/umbrello/docwindow.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/docwindow.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/docwindow.cpp 2015-10-08 11:48:59.499089026 +0300
@@ -91,6 +91,7 @@
statusLayout->addWidget(m_modifiedWidget, 0, 5, 1, 1);
m_docTE = new KTextEdit(this);
m_docTE->setText(QString());
+ setFocusProxy(m_docTE);
//m_docTE->setWordWrapMode(QTextEdit::WidgetWidth);
QVBoxLayout* docLayout = new QVBoxLayout(this);
docLayout->addLayout(statusLayout);
@@ -461,5 +462,6 @@
tab->setCurrentIndex(i);
}
}
+ m_docTE->setFocus();
}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/entityattribute.cpp umbrello-kf6-15.08.1/umbrello/entityattribute.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/entityattribute.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/entityattribute.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,280 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "entityattribute.h"
-
-// app includes
-#include "debug_utils.h"
-//#include "umlcanvasobject.h"
-#include "umldoc.h"
-#include "uml.h"
-#include "umlentityattributedialog.h"
-#include "object_factory.h"
-
-// qt includes
-#include <QRegExp>
-
-/**
- * Sets up an entityattribute.
- * @param parent The parent of this UMLEntityAttribute.
- * @param name The name of this UMLEntityAttribute.
- * @param id The unique id given to this UMLEntityAttribute.
- * @param s The visibility of the UMLEntityAttribute.
- * @param type The type of this UMLEntityAttribute.
- * @param iv The initial value of the entityattribute.
- */
-UMLEntityAttribute::UMLEntityAttribute(UMLObject *parent, const QString& name,
- Uml::ID::Type id, Uml::Visibility::Enum s,
- UMLObject *type, const QString& iv)
- : UMLAttribute(parent, name, id, s, type, iv)
-{
- init();
- if (m_pSecondary) {
- m_pSecondary->setBaseType(UMLObject::ot_Entity);
- }
-}
-
-/**
- * Sets up an entityattribute.
- * @param parent The parent of this UMLEntityAttribute.
- */
-UMLEntityAttribute::UMLEntityAttribute(UMLObject *parent)
- : UMLAttribute(parent)
-{
- init();
-}
-
-/**
- * Destructor.
- */
-UMLEntityAttribute::~UMLEntityAttribute()
-{
-}
-
-/**
- * Initialize members of this class.
- * Auxiliary method used by constructors.
- */
-void UMLEntityAttribute::init()
-{
- m_BaseType = UMLObject::ot_EntityAttribute;
- m_indexType = UMLEntityAttribute::None;
- m_autoIncrement = false;
- m_null = false;
-}
-
-/**
- * Returns the value of the UMLEntityAttribute's attributes property.
- * @return The value of the UMLEntityAttribute's attributes property.
- */
-QString UMLEntityAttribute::getAttributes() const
-{
- return m_attributes;
-}
-
-/**
- * Sets the UMLEntityAttribute's attributes property.
- * @param attributes The new value for the attributes property.
- */
-void UMLEntityAttribute::setAttributes(const QString& attributes)
-{
- m_attributes = attributes;
-}
-
-/**
- * Returns the UMLEntityAttribute's length/values property.
- * @return The new value of the length/values property.
- */
-QString UMLEntityAttribute::getValues() const
-{
- return m_values;
-}
-
-/**
- * Sets the UMLEntityAttribute's length/values property.
- * @param values The new value of the length/values property.
- */
-void UMLEntityAttribute::setValues(const QString& values)
-{
- m_values = values;
-}
-
-/**
- * Returns the UMLEntityAttribute's auto_increment boolean
- * @return The UMLEntityAttribute's auto_increment boolean
- */
-bool UMLEntityAttribute::getAutoIncrement() const
-{
- return m_autoIncrement;
-}
-
-/**
- * Sets the UMLEntityAttribute's auto_increment boolean
- * @param autoIncrement The UMLEntityAttribute's auto_increment boolean
- */
-void UMLEntityAttribute::setAutoIncrement(const bool autoIncrement)
-{
- m_autoIncrement = autoIncrement;
-}
-
-/**
- * Returns the UMLEntityAttribute's index type property.
- * @return The value of the UMLEntityAttribute's index type property.
- */
-UMLEntityAttribute::DBIndex_Type UMLEntityAttribute::indexType() const
-{
- return m_indexType;
-}
-
-/**
- * Sets the initial value of the UMLEntityAttribute's index type property.
- * @param indexType The initial value of the UMLEntityAttribute's index type property.
- */
-void UMLEntityAttribute::setIndexType(const UMLEntityAttribute::DBIndex_Type indexType)
-{
- m_indexType = indexType;
-}
-
-/**
- * Returns the UMLEntityAttribute's allow null value.
- * @return The UMLEntityAttribute's allow null value.
- */
-bool UMLEntityAttribute::getNull() const
-{
- return m_null;
-}
-
-/**
- * Sets the initial value of the UMLEntityAttribute's allow null value.
- * @param nullIn The initial value of the UMLEntityAttribute's allow null value.
- */
-void UMLEntityAttribute::setNull(const bool nullIn)
-{
- m_null = nullIn;
-}
-
-/**
- * Returns a string representation of the UMLEntityAttribute.
- * @param sig If true will show the entityattribute type and initial value.
- * @return Returns a string representation of the UMLEntityAttribute.
- */
-QString UMLEntityAttribute::toString(Uml::SignatureType::Enum sig)
-{
- QString s;
- //FIXME
-
- if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::NoSig) {
- s = Uml::Visibility::toString(m_visibility, true) + QLatin1Char(' ');
- }
-
- if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::SigNoVis) {
- QString string = s + name() + QLatin1String(" : ") + getTypeName();
- if(m_InitialValue.length() > 0)
- string += QLatin1String(" = ") + m_InitialValue;
- return string;
- } else
- return s + name();
-}
-
-/**
- * Overloaded '==' operator
- */
-bool UMLEntityAttribute::operator==(const UMLEntityAttribute &rhs) const
-{
- if(this == &rhs)
- return true;
-
- if(!UMLObject::operator==(rhs))
- return false;
-
- // The type name is the only distinguishing criterion.
- // (Some programming languages might support more, but others don't.)
- if (m_pSecondary != rhs.m_pSecondary)
- return false;
-
- return true;
-}
-
-/**
- * Copy the internal presentation of this object into the UMLEntityAttribute
- * object.
- */
-void UMLEntityAttribute::copyInto(UMLObject *lhs) const
-{
- UMLEntityAttribute *target = static_cast<UMLEntityAttribute*>(lhs);
-
- // call the parent first.
- UMLClassifierListItem::copyInto(target);
-
- // Copy all datamembers
- target->m_pSecondary = m_pSecondary;
- target->m_SecondaryId = m_SecondaryId;
- target->m_InitialValue = m_InitialValue;
- target->m_ParmKind = m_ParmKind;
-}
-
-/**
- * Make a clone of the UMLEntityAttribute.
- */
-UMLObject* UMLEntityAttribute::clone() const
-{
- UMLEntityAttribute* clone = new UMLEntityAttribute((UMLEntityAttribute*)parent());
- copyInto(clone);
-
- return clone;
-}
-
-/**
- * Creates the <UML:EntityAttribute> XMI element.
- */
-void UMLEntityAttribute::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement entityattributeElement = UMLObject::save(QLatin1String("UML:EntityAttribute"), qDoc);
- if (m_pSecondary == NULL) {
- uDebug() << name() << ": m_pSecondary is NULL, using local name " << m_SecondaryId;
- entityattributeElement.setAttribute(QLatin1String("type"), m_SecondaryId);
- } else {
- entityattributeElement.setAttribute(QLatin1String("type"), Uml::ID::toString(m_pSecondary->id()));
- }
- entityattributeElement.setAttribute(QLatin1String("initialValue"), m_InitialValue);
- entityattributeElement.setAttribute(QLatin1String("dbindex_type"), m_indexType);
- entityattributeElement.setAttribute(QLatin1String("values"), m_values);
- entityattributeElement.setAttribute(QLatin1String("attributes"), m_attributes);
- entityattributeElement.setAttribute(QLatin1String("auto_increment"), m_autoIncrement);
- entityattributeElement.setAttribute(QLatin1String("allow_null"), m_null);
- qElement.appendChild(entityattributeElement);
-}
-
-/**
- * Loads the <UML:EntityAttribute> XMI element.
- */
-bool UMLEntityAttribute::load(QDomElement & element)
-{
- if (! UMLAttribute::load(element))
- return false;
- int indexType = element.attribute(QLatin1String("dbindex_type"), QLatin1String("1100")).toInt();
- m_indexType = (UMLEntityAttribute::DBIndex_Type)indexType;
- m_values = element.attribute(QLatin1String("values"));
- m_attributes = element.attribute(QLatin1String("attributes"));
- m_autoIncrement = (bool)element.attribute(QLatin1String("auto_increment")).toInt();
- m_null = (bool)element.attribute(QLatin1String("allow_null")).toInt();
- return true;
-}
-
-/**
- * Display the properties configuration dialog for the entityattribute.
- */
-bool UMLEntityAttribute::showPropertiesDialog(QWidget* parent)
-{
- UMLEntityAttributeDialog dialog(parent, this);
- return dialog.exec();
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/entityattribute.h umbrello-kf6-15.08.1/umbrello/entityattribute.h
--- umbrello-kf6-15.08.1.orig/umbrello/entityattribute.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/entityattribute.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,85 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ENTITYATTRIBUTE_H
-#define ENTITYATTRIBUTE_H
-
-#include "attribute.h"
-#include "basictypes.h"
-
-/**
- * This class is used to set up information for an entityattribute. This is a database field
- * It has a type, name, index type and default value.
- *
- * @short Sets up entityattribute information.
- * @author Jonathan Riddell <jr@jriddell.org>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLEntityAttribute : public UMLAttribute
-{
- Q_OBJECT
- Q_ENUMS(DBIndex_Type)
-public:
- enum DBIndex_Type
- {
- None = 1100,
- Primary,
- Index,
- Unique
- };
-
- UMLEntityAttribute(UMLObject* parent, const QString& name,
- Uml::ID::Type id = Uml::ID::None,
- Uml::Visibility::Enum s = Uml::Visibility::Private,
- UMLObject *type = 0, const QString& iv = QString());
- explicit UMLEntityAttribute(UMLObject* parent);
- virtual ~UMLEntityAttribute();
-
- bool operator==(const UMLEntityAttribute& rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- void setAttributes(const QString& attributes);
- QString getAttributes() const;
-
- void setIndexType(const DBIndex_Type indexType);
- DBIndex_Type indexType() const;
-
- void setValues(const QString& values);
- QString getValues() const;
-
- void setAutoIncrement(const bool autoIncrement);
- bool getAutoIncrement() const;
-
- void setNull(const bool null);
- bool getNull() const;
-
- QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
-
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
- virtual bool showPropertiesDialog(QWidget* parent = 0);
-
-protected:
- void init();
-
- bool load(QDomElement& element);
-
-private:
- DBIndex_Type m_indexType;
- QString m_values;
- QString m_attributes;
- bool m_autoIncrement;
- bool m_null;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/entityconstraint.cpp umbrello-kf6-15.08.1/umbrello/entityconstraint.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/entityconstraint.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/entityconstraint.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,76 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-//own header
-#include "entityconstraint.h"
-
-// app includes
-#include "umlobject.h"
-#include "umldoc.h"
-#include "uml.h"
-
-// qt includes
-#include <QRegExp>
-
-/**
- * Sets up a constraint.
- * @param parent The parent of this UMLEntityConstraint.
- * @param name The name of this UMLEntityConstraint.
- * @param id The unique id given to this UMLEntityConstraint.
- */
-UMLEntityConstraint::UMLEntityConstraint(UMLObject *parent,
- const QString& name, Uml::ID::Type id)
- : UMLClassifierListItem(parent, name, id)
-{
- m_BaseType = UMLObject::ot_EntityConstraint;
-}
-
-/**
- * Sets up a constraint.
- * @param parent The parent of this UMLEntityConstraint.
- */
-UMLEntityConstraint::UMLEntityConstraint(UMLObject *parent)
- : UMLClassifierListItem(parent)
-{
- m_BaseType = UMLObject::ot_EntityConstraint;
-}
-
-/**
- * Overloaded '==' operator
- */
-bool UMLEntityConstraint::operator==(const UMLEntityConstraint &rhs) const
-{
- if(this == &rhs)
- return true;
-
- if(!UMLObject::operator==(rhs))
- return false;
-
- return true;
-}
-
-/**
- * destructor.
- */
-UMLEntityConstraint::~UMLEntityConstraint()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the UMLEntityConstraint
- * object.
- */
-void UMLEntityConstraint::copyInto(UMLObject *lhs) const
-{
- // call the parent first.
- UMLClassifierListItem::copyInto(lhs);
-}
-
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/entityconstraint.h umbrello-kf6-15.08.1/umbrello/entityconstraint.h
--- umbrello-kf6-15.08.1.orig/umbrello/entityconstraint.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/entityconstraint.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,49 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ENTITYCONSTRAINT_H
-#define ENTITYCONSTRAINT_H
-
-#include "basictypes.h"
-#include "classifierlistitem.h"
-#include "umlclassifierlist.h"
-
-/**
- * This class is used to set up information for a entity constraint.
- *
- * @short Sets up entity constraint information.
- * @author Sharan Rao
- * @see UMLObject UMLClassifierListItem
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLEntityConstraint : public UMLClassifierListItem
-{
- Q_OBJECT
-
-public:
- UMLEntityConstraint(UMLObject *parent, const QString& name,
- Uml::ID::Type id = Uml::ID::None);
-
- explicit UMLEntityConstraint(UMLObject *parent);
-
- bool operator==(const UMLEntityConstraint &rhs) const;
-
- virtual ~UMLEntityConstraint();
-
- virtual void copyInto(UMLObject *lhs) const;
-
- /**
- * Make a clone of the UMLEntityConstraint.
- */
- virtual UMLObject* clone() const = 0;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/entity.cpp umbrello-kf6-15.08.1/umbrello/entity.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/entity.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/entity.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,719 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "entity.h"
-
-// app includes
-#include "debug_utils.h"
-#include "entityattribute.h"
-#include "uniqueconstraint.h"
-#include "foreignkeyconstraint.h"
-#include "checkconstraint.h"
-#include "umldoc.h"
-#include "uml.h"
-#include "uniqueid.h"
-#include "umlentityattributelist.h"
-#include "umlentityconstraintlist.h"
-#include "idchangelog.h"
-#include "umlentityattributedialog.h"
-#include "umluniqueconstraintdialog.h"
-#include "umlforeignkeyconstraintdialog.h"
-#include "umlcheckconstraintdialog.h"
-
-// kde includes
-#include <KLocalizedString>
-#include <KMessageBox>
-
-// qt includes
-#include <QPointer>
-
-/**
- * Constructor.
- */
-UMLEntity::UMLEntity(const QString& name, Uml::ID::Type id)
- : UMLClassifier(name, id),
- m_PrimaryKey(0)
-{
- m_BaseType = UMLObject::ot_Entity;
- connect(this, SIGNAL(entityAttributeRemoved(UMLClassifierListItem*)),
- this, SLOT(slotEntityAttributeRemoved(UMLClassifierListItem*)));
-}
-
-/**
- * Standard destructor.
- */
-UMLEntity::~UMLEntity()
-{
- m_List.clear();
-}
-
-/**
- * Overloaded '==' operator.
- */
-bool UMLEntity::operator==(const UMLEntity& rhs) const
-{
- return UMLClassifier::operator==(rhs);
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLEntity::copyInto(UMLObject *lhs) const
-{
- UMLEntity *target = static_cast<UMLEntity*>(lhs);
-
- // call base class copy function
- UMLClassifier::copyInto(target);
-
- // copy local data items
- target->m_PrimaryKey = m_PrimaryKey;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLEntity::clone() const
-{
- UMLEntity* clone = new UMLEntity();
- copyInto(clone);
-
- return clone;
-}
-
-/**
- * Create an UMLAttribute.
- * @param name an optional name for the attribute
- * @param type an optional type object for the attribute
- * @param vis the visibility of the attribute
- * @param iv the initial value for the attribute
- * @return the just created attribute or null
- */
-UMLAttribute* UMLEntity::createAttribute(const QString &name /*= QString()*/, UMLObject *type /*= 0*/,
- Uml::Visibility::Enum vis /* = Uml::Visibility::Private*/,
- const QString& iv /* = QString()*/)
-{
- Uml::ID::Type id = UniqueID::gen();
- QString currentName;
- if (name.isNull()) {
- currentName = uniqChildName(UMLObject::ot_EntityAttribute);
- } else {
- currentName = name;
- }
-
- UMLEntityAttribute* newAttribute = new UMLEntityAttribute(this, currentName, id, vis, type, iv);
-
- int button = QDialog::Accepted;
- bool goodName = false;
-
- //check for name.isNull() stops dialog being shown
- //when creating attribute via list view
- while (button == QDialog::Accepted && !goodName && name.isNull()) {
- QPointer<UMLEntityAttributeDialog> dialog = new UMLEntityAttributeDialog(0, newAttribute);
- button = dialog->exec();
- QString name = newAttribute->name();
-
- if (name.length() == 0) {
- KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
- } else if (findChildObject(name) != NULL) {
- KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
- } else {
- goodName = true;
- }
- delete dialog;
- }
-
- if (button != QDialog::Accepted) {
- delete newAttribute;
- return 0;
- }
-
- addEntityAttribute(newAttribute);
-
- UMLDoc *umldoc = UMLApp::app()->document();
- umldoc->signalUMLObjectCreated(newAttribute);
- return newAttribute;
-}
-
-/**
- * Creates a Unique Constraint for this Entity.
- * @param name an optional name
- * @return the UniqueConstraint created
- */
-UMLUniqueConstraint* UMLEntity::createUniqueConstraint(const QString &name)
-{
- Uml::ID::Type id = UniqueID::gen();
- QString currentName;
- if (name.isNull()) {
-
- /**
- * @todo check parameter
- */
- currentName = uniqChildName(UMLObject::ot_UniqueConstraint);
- } else {
- currentName = name;
- }
-
- UMLUniqueConstraint* newUniqueConstraint = new UMLUniqueConstraint(this, currentName, id);
-
- int button = QDialog::Accepted;
- bool goodName = false;
-
- //check for name.isNull() stops dialog being shown
- //when creating attribute via list view
- while (button == QDialog::Accepted && !goodName && name.isNull()) {
- QPointer<UMLUniqueConstraintDialog> dialog = new UMLUniqueConstraintDialog(0, newUniqueConstraint);
- button = dialog->exec();
- QString name = newUniqueConstraint->name();
-
- if (name.length() == 0) {
- KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
- } else if (findChildObject(name) != NULL) {
- KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
- } else {
- goodName = true;
- }
- delete dialog;
- }
-
- if (button != QDialog::Accepted) {
- delete newUniqueConstraint;
- return NULL;
- }
-
- addConstraint(newUniqueConstraint);
-
- UMLDoc *umldoc = UMLApp::app()->document();
- umldoc->signalUMLObjectCreated(newUniqueConstraint);
- emitModified();
- return newUniqueConstraint;
-}
-
-/**
- * Creates a Foreign Key Constraint for this Entity.
- * @param name an optional name
- * @return the ForeignKeyConstraint created
- */
-UMLForeignKeyConstraint* UMLEntity::createForeignKeyConstraint(const QString &name)
-{
- Uml::ID::Type id = UniqueID::gen();
- QString currentName;
- if (name.isNull()) {
- currentName = uniqChildName(UMLObject::ot_ForeignKeyConstraint);
- } else {
- currentName = name;
- }
-
- UMLForeignKeyConstraint* newForeignKeyConstraint = new UMLForeignKeyConstraint(this, currentName, id);
-
- int button = QDialog::Accepted;
- bool goodName = false;
-
- //check for name.isNull() stops dialog being shown
- //when creating attribute via list view
- while (button == QDialog::Accepted && !goodName && name.isNull()) {
- QPointer<UMLForeignKeyConstraintDialog> dialog = new UMLForeignKeyConstraintDialog(0, newForeignKeyConstraint);
- button = dialog->exec();
- QString name = newForeignKeyConstraint->name();
-
- if (name.length() == 0) {
- KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
- } else if (findChildObject(name) != NULL) {
- KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
- } else {
- goodName = true;
- }
- delete dialog;
- }
-
- if (button != QDialog::Accepted) {
- return NULL;
- }
-
- addConstraint(newForeignKeyConstraint);
-
- UMLDoc *umldoc = UMLApp::app()->document();
- umldoc->signalUMLObjectCreated(newForeignKeyConstraint);
- emitModified();
- return newForeignKeyConstraint;
-}
-
-/**
- * Creates a Check Constraint for this Entity.
- * @param name an optional name
- * @return the CheckConstraint created
- */
-UMLCheckConstraint* UMLEntity::createCheckConstraint(const QString &name)
-{
- Uml::ID::Type id = UniqueID::gen();
- QString currentName;
- if (name.isNull()) {
- currentName = uniqChildName(UMLObject::ot_CheckConstraint);
- } else {
- currentName = name;
- }
-
- UMLCheckConstraint* newCheckConstraint = new UMLCheckConstraint(this, currentName, id);
-
- int button = QDialog::Accepted;
- bool goodName = false;
-
- //check for name.isNull() stops dialog being shown
- //when creating attribute via list view
- while (button == QDialog::Accepted && !goodName && name.isNull()) {
- QPointer<UMLCheckConstraintDialog> dialog = new UMLCheckConstraintDialog(0, newCheckConstraint);
- button = dialog->exec();
- QString name = newCheckConstraint->name();
-
- if (name.length() == 0) {
- KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
- } else if (findChildObject(name) != NULL) {
- KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
- } else {
- goodName = true;
- }
- delete dialog;
- }
-
- if (button != QDialog::Accepted) {
- return NULL;
- }
-
- addConstraint(newCheckConstraint);
-
- UMLDoc *umldoc = UMLApp::app()->document();
- umldoc->signalUMLObjectCreated(newCheckConstraint);
- emitModified();
- return newCheckConstraint;
-}
-
-/**
- * Adds an entityAttribute.
- * The entityAttribute object must not belong to any other concept.
- * @param name name of the UMLEntityAttribute
- * @param id id of the UMLEntityAttribute
- * @return True if the entityAttribute was successfully added.
- */
-UMLObject* UMLEntity::addEntityAttribute(const QString& name, Uml::ID::Type id)
-{
- UMLEntityAttribute* literal = new UMLEntityAttribute(this, name, id);
- m_List.append(literal);
- emit entityAttributeAdded(literal);
- UMLObject::emitModified();
- connect(literal, SIGNAL(modified()), this, SIGNAL(modified()));
- return literal;
-}
-
-/**
- * Adds an already created entityAttribute.
- * The entityAttribute object must not belong to any other concept.
- * @param att Pointer to the UMLEntityAttribute.
- * @param log Pointer to the IDChangeLog.
- * @return True if the entityAttribute was successfully added.
- */
-bool UMLEntity::addEntityAttribute(UMLEntityAttribute* att, IDChangeLog* log /* = 0*/)
-{
- QString name = (QString)att->name();
- if (findChildObject(name) == NULL) {
- att->setParent(this);
- m_List.append(att);
- emit entityAttributeAdded(att);
- UMLObject::emitModified();
- connect(att, SIGNAL(modified()), this, SIGNAL(modified()));
- return true;
- } else if (log) {
- log->removeChangeByNewID(att->id());
- delete att;
- }
- return false;
-}
-
-/**
- * Adds an entityAttribute to the entity, at the given position.
- * If position is negative or too large, the entityAttribute is added
- * to the end of the list.
- * TODO: give default value -1 to position (append) - now it conflicts with the method above..
- * @param att Pointer to the UMLEntityAttribute.
- * @param position Position index for the insertion.
- * @return True if the entityAttribute was successfully added.
- */
-bool UMLEntity::addEntityAttribute(UMLEntityAttribute* att, int position)
-{
- Q_ASSERT(att);
- QString name = (QString)att->name();
- if (findChildObject(name) == NULL) {
- att->setParent(this);
- if (position >= 0 && position <= (int)m_List.count()) {
- m_List.insert(position, att);
- } else {
- m_List.append(att);
- }
- emit entityAttributeAdded(att);
- UMLObject::emitModified();
- connect(att, SIGNAL(modified()), this, SIGNAL(modified()));
- return true;
- }
- return false;
-}
-
-/**
- * Removes an entityAttribute from the class.
- * @param att The entityAttribute to remove.
- * @return Count of the remaining entityAttributes after removal.
- * Returns -1 if the given entityAttribute was not found.
- */
-int UMLEntity::removeEntityAttribute(UMLClassifierListItem* att)
-{
- if (!m_List.removeAll((UMLEntityAttribute*)att)) {
- uDebug() << "cannot find att given in list";
- return -1;
- }
- emit entityAttributeRemoved(att);
- UMLObject::emitModified();
- // If we are deleting the object, then we don't need to disconnect..this is done auto-magically
- // for us by QObject. -b.t.
- // disconnect(att, SIGNAL(modified()), this, SIGNAL(modified()));
- delete att;
- return m_List.count();
-}
-
-/**
- * Returns the number of entityAttributes for the class.
- * @return The number of entityAttributes for the class.
- */
-int UMLEntity::entityAttributes()
-{
- UMLClassifierListItemList entityAttributes = getFilteredList(UMLObject::ot_EntityAttribute);
- return entityAttributes.count();
-}
-
-/**
- * Emit the entityAttributeRemoved signal.
- */
-void UMLEntity::signalEntityAttributeRemoved(UMLClassifierListItem *eattr)
-{
- emit entityAttributeRemoved(eattr);
-}
-
-/**
- * Resolve the types referenced by our UMLEntityAttributes.
- * Reimplements the method from UMLClassifier.
- */
-bool UMLEntity::resolveRef()
-{
- bool success = UMLClassifier::resolveRef();
- for (UMLObjectListIt oit(m_List); oit.hasNext();) {
- UMLObject* obj = oit.next();
- if (obj->resolveRef()) {
- UMLClassifierListItem *cli = static_cast<UMLClassifierListItem*>(obj);
- switch (cli->baseType()) {
- case UMLObject::ot_EntityAttribute:
- emit entityAttributeAdded(cli);
- break;
- case UMLObject::ot_UniqueConstraint:
- case UMLObject::ot_ForeignKeyConstraint:
- emit entityConstraintAdded(cli);
- break;
- default:
- break;
- }
- }
- }
- return success;
-}
-
-/**
- * Creates the <UML:Entity> element including its entityliterals.
- */
-void UMLEntity::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement entityElement = UMLObject::save(QLatin1String("UML:Entity"), qDoc);
- //save operations
- UMLClassifierListItemList entityAttributes = getFilteredList(UMLObject::ot_EntityAttribute);
- UMLClassifierListItem* pEntityAttribute = 0;
- foreach (pEntityAttribute, entityAttributes) {
- pEntityAttribute->saveToXMI(qDoc, entityElement);
- }
-
- UMLClassifierListItemList entityConstraints = getFilteredList(UMLObject::ot_EntityConstraint);
- foreach(UMLClassifierListItem* cli, entityConstraints) {
- cli->saveToXMI(qDoc, entityElement);
- }
-
- qElement.appendChild(entityElement);
-}
-
-/**
- * Loads the <UML:Entity> element including its entityAttributes.
- */
-bool UMLEntity::load(QDomElement& element)
-{
- QDomNode node = element.firstChild();
- while(!node.isNull()) {
- if (node.isComment()) {
- node = node.nextSibling();
- continue;
- }
- QDomElement tempElement = node.toElement();
- QString tag = tempElement.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("EntityAttribute"))) { // for backward compatibility
- UMLEntityAttribute* pEntityAttribute = new UMLEntityAttribute(this);
- if(!pEntityAttribute->loadFromXMI(tempElement)) {
- return false;
- }
- m_List.append(pEntityAttribute);
- } else if (UMLDoc::tagEq(tag, QLatin1String("UniqueConstraint"))) {
- UMLUniqueConstraint* pUniqueConstraint = new UMLUniqueConstraint(this);
- if (!pUniqueConstraint->loadFromXMI(tempElement)) {
- return false;
- }
- addConstraint(pUniqueConstraint);
- } else if (UMLDoc::tagEq(tag, QLatin1String("ForeignKeyConstraint"))) {
- UMLForeignKeyConstraint* pForeignKeyConstraint = new UMLForeignKeyConstraint(this);
- if (!pForeignKeyConstraint->loadFromXMI(tempElement)) {
- return false;
- }
-
- addConstraint(pForeignKeyConstraint);
- } else if (UMLDoc::tagEq(tag, QLatin1String("CheckConstraint"))) {
-
- UMLCheckConstraint* pCheckConstraint = new UMLCheckConstraint(this);
- if (!pCheckConstraint->loadFromXMI(tempElement)) {
- return false;
- }
-
- addConstraint(pCheckConstraint);
- } else if (tag == QLatin1String("stereotype")) {
- uDebug() << name() << ": losing old-format stereotype.";
- } else {
- uWarning() << "unknown child type in UMLEntity::load";
- }
- node = node.nextSibling();
- }//end while
- return true;
-}
-
-/**
- * Sets the UniqueConstraint passed as the Primary Key of this Entity
- * If the UniqueConstraint exists, then it is made a primary key
- * Else the UniqueConstraint is added and set as PrimaryKey
- * @param uconstr The Unique Constraint that is to be set as Primary Key
- * @return true if Primary key could be set successfully
- */
-bool UMLEntity::setAsPrimaryKey(UMLUniqueConstraint* uconstr)
-{
- if (uconstr == NULL) {
- uDebug() << "NULL value passed. To unset a Primary Key use "
- << "unsetPrimaryKey()";
- return false;
- }
-
- if (static_cast<UMLEntity*>(uconstr->parent()) != this) {
-
- uDebug() << "Parent of " << uconstr->name()
- << " does not match with current entity";
- return false;
- }
-
- // check if this constraint already exists as a unique constraint for this entity
- UMLUniqueConstraint* uuc = static_cast<UMLUniqueConstraint*>(findChildObjectById(uconstr->id()));
- if (uuc == NULL) {
- addConstraint(uconstr);
- uuc = uconstr;
- }
-
- UMLUniqueConstraint* oldPrimaryKey = m_PrimaryKey;
-
- m_PrimaryKey = uuc;
-
- if (oldPrimaryKey != NULL)
- oldPrimaryKey->emitModified();
-
- uuc->emitModified();
- emitModified();
- return true;
-}
-
-/**
- * Unset a Primary Key Constraint if it exists, else does nothing
- * This function will make the primary key into just another UniqueConstraint
- * if it exists
- */
-void UMLEntity::unsetPrimaryKey()
-{
- m_PrimaryKey = 0;
-}
-
-/**
- * Checks if This UMLEntity has a primary key set.
- * @return true if a Primary Key Exists for this UMLEntity
- */
-bool UMLEntity::hasPrimaryKey() const
-{
- if (m_PrimaryKey) {
- return true;
- }
-
- return false;
-}
-
-/**
- * Adds a Constraint to this UMLEntity.
- * To set a UMLUniqueConstraint as Primary Key use setAsPrimaryKey.
- * @param constr The UMLEntityConstraint that is to be added
- * @return true if the constraint could be added successfully
- */
-bool UMLEntity::addConstraint(UMLEntityConstraint* constr)
-{
- if (findChildObjectById(constr->id()) != NULL) {
- uDebug() << "Constraint with id " << Uml::ID::toString(constr->id())
- << " already exists ";
- return false;
- }
-
- m_List.append(constr);
-
- emit entityConstraintAdded(constr);
- UMLObject::emitModified();
- connect(constr, SIGNAL(modified()), this, SIGNAL(modified()));
-
- return true;
-}
-
-/**
- * Removes an existing constraint from this UMLEntity.
- * If the Contraint is a Primary Key, this Entity will no longer have a PrimaryKey.
- * @param constr the constraint to be removed
- * @return true if the constraint could be removed successfully
- */
-bool UMLEntity::removeConstraint(UMLEntityConstraint* constr)
-{
- if (findChildObjectById(constr->id()) == NULL) {
- uDebug() << "Constraint with id " << Uml::ID::toString(constr->id())
- << " does not exist ";
- return false;
- }
-
- if (m_PrimaryKey == constr) {
- unsetPrimaryKey();
- }
-
- m_List.removeAll(constr);
-
- emit entityConstraintRemoved(constr);
- UMLObject::emitModified();
-
- delete constr;
- return true;
-}
-
-/**
- * Slot for entity attribute removed.
- */
-void UMLEntity::slotEntityAttributeRemoved(UMLClassifierListItem* cli)
-{
- // this function does some cleanjobs related to this entity when the attribute is
- // removed, like, removing the attribute from all constraints
-
- UMLEntityAttribute* entAtt = static_cast<UMLEntityAttribute*>(cli);
- if (cli) {
- UMLClassifierListItemList ual = this->getFilteredList(UMLObject::ot_UniqueConstraint);
-
- foreach(UMLClassifierListItem* ucli, ual) {
- UMLUniqueConstraint* uuc = static_cast<UMLUniqueConstraint*>(ucli);
- if (uuc->hasEntityAttribute(entAtt)) {
- uuc->removeEntityAttribute(entAtt);
- }
- }
- }
-
-}
-
-/**
- * Reimplementation of getFilteredList to support ot=UMLObject::ot_EntityConstraint.
- */
-UMLClassifierListItemList UMLEntity::getFilteredList(UMLObject::ObjectType ot) const
-{
- if (ot == UMLObject::ot_EntityConstraint) {
- UMLClassifierListItemList ucList, fcList, ccList, rcList;
- ucList = UMLClassifier::getFilteredList(UMLObject::ot_UniqueConstraint);
- fcList = UMLClassifier::getFilteredList(UMLObject::ot_ForeignKeyConstraint);
- ccList = UMLClassifier::getFilteredList(UMLObject::ot_CheckConstraint);
-
- // append the lists to rcList
- // first the Unique Constraints
- foreach(UMLClassifierListItem* ucli, ucList) {
- rcList.append(ucli);
- }
-
- // then the Foreign Key Constraints
- foreach(UMLClassifierListItem* ucli, fcList) {
- rcList.append(ucli);
- }
-
- foreach(UMLClassifierListItem* ucli, ccList) {
- rcList.append(ucli);
- }
-
- return rcList;
- } else {
- return UMLClassifier::getFilteredList(ot);
- }
-}
-
-/**
- * Checks if a given Unique Constraint is primary key of this entity
- * @param uConstr a Unique Constraint
- * @return bool true if passed parameter is a primary key of this entity
- */
-bool UMLEntity::isPrimaryKey(UMLUniqueConstraint* uConstr) const
-{
- if (uConstr == m_PrimaryKey) {
- return true;
- }
-
- return false;
-}
-
-/**
- * Returns the Entity Attributes.
- * Same as getFilteredList(UMLObject::ot_EntityAttribute).
- */
-UMLEntityAttributeList UMLEntity::getEntityAttributes() const
-{
- UMLEntityAttributeList entityAttributeList;
- for (UMLObjectListIt lit(m_List); lit.hasNext();) {
- UMLObject *listItem = lit.next();
- if (listItem->baseType() == UMLObject::ot_EntityAttribute) {
- entityAttributeList.append(static_cast<UMLEntityAttribute*>(listItem));
- }
- }
- return entityAttributeList;
-}
-
-
-/**
- * Create a new ClassifierListObject (entityattribute)
- * according to the given XMI tag.
- * Returns NULL if the string given does not contain one of the tags
- * <UML:EntityAttribute>
- * Used by the clipboard for paste operation.
- * Reimplemented from UMLClassifier for UMLEntity
- */
-UMLClassifierListItem* UMLEntity::makeChildObject(const QString& xmiTag)
-{
- UMLClassifierListItem* pObject = NULL;
- if (UMLDoc::tagEq(xmiTag, QLatin1String("EntityAttribute"))) {
- pObject = new UMLEntityAttribute(this);
- }
- return pObject;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/entity.h umbrello-kf6-15.08.1/umbrello/entity.h
--- umbrello-kf6-15.08.1.orig/umbrello/entity.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/entity.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,108 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ENTITY_H
-#define ENTITY_H
-
-#include "classifier.h"
-
-// forward declarations
-class UMLEntityAttribute;
-class UMLEntityConstraint;
-class UMLUniqueConstraint;
-class UMLForeignKeyConstraint;
-class UMLCheckConstraint;
-class UMLEntityAttributeList;
-
-/**
- * This class contains the non-graphical information required for a UML
- * Entity.
- * This class inherits from @ref UMLClassifier which contains most of the
- * information.
- *
- * @short Non-graphical Information for an Entity.
- * @author Jonathan Riddell
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLEntity : public UMLClassifier
-{
- Q_OBJECT
-public:
- explicit UMLEntity(const QString& name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLEntity();
-
- bool operator==(const UMLEntity& rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- virtual UMLAttribute* createAttribute(const QString &name = QString(),
- UMLObject *type = 0, Uml::Visibility::Enum vis = Uml::Visibility::Private,
- const QString &init = QString());
-
- UMLUniqueConstraint* createUniqueConstraint(const QString &name = QString());
- UMLForeignKeyConstraint* createForeignKeyConstraint(const QString &name = QString());
- UMLCheckConstraint* createCheckConstraint(const QString &name = QString());
-
- UMLObject* addEntityAttribute(const QString &name, Uml::ID::Type id = Uml::ID::None);
- bool addEntityAttribute(UMLEntityAttribute* att, IDChangeLog* log = 0);
- bool addEntityAttribute(UMLEntityAttribute* att, int position);
-
- int removeEntityAttribute(UMLClassifierListItem* att);
-
- void signalEntityAttributeRemoved(UMLClassifierListItem *eattr);
-
- int entityAttributes() ;
-
- bool setAsPrimaryKey(UMLUniqueConstraint* uconstr);
- void unsetPrimaryKey();
- bool hasPrimaryKey() const;
- bool isPrimaryKey(UMLUniqueConstraint* uConstr) const;
-
- bool addConstraint(UMLEntityConstraint* constr);
- bool removeConstraint(UMLEntityConstraint* constr);
-
- virtual bool resolveRef();
-
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
- UMLClassifierListItemList getFilteredList(UMLObject::ObjectType ot) const;
-
- UMLEntityAttributeList getEntityAttributes() const;
-
- virtual UMLClassifierListItem* makeChildObject(const QString& xmiTag);
-
-private slots:
- void slotEntityAttributeRemoved(UMLClassifierListItem*);
-
-signals:
- void entityAttributeAdded(UMLClassifierListItem*);
- void entityAttributeRemoved(UMLClassifierListItem*);
- void entityConstraintAdded(UMLClassifierListItem*);
- void entityConstraintRemoved(UMLClassifierListItem*);
-
-protected:
- bool load(QDomElement& element);
-
-private:
-
- /**
- * Primary Key of this Entity
- * This is a pointer kept for easy access to the primary key, and to distinguish it
- * from all other UniqueConstraints. It is also there in m_List (inherited from
- * UMLCanvasObject)
- */
- UMLUniqueConstraint* m_PrimaryKey;
-
-};
-
-#endif // ENTITY_H
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/enum.cpp umbrello-kf6-15.08.1/umbrello/enum.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/enum.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/enum.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,302 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "enum.h"
-
-// app includes
-#include "debug_utils.h"
-#include "enumliteral.h"
-#include "umldoc.h"
-#include "uml.h"
-#include "uniqueid.h"
-#include "idchangelog.h"
-
-// kde includes
-#include <KLocalizedString>
-#include <KMessageBox>
-
-/**
- * Sets up an enum.
- * @param name The name of the Enum.
- * @param id The unique id of the Enum.
- */
-UMLEnum::UMLEnum(const QString& name, Uml::ID::Type id) : UMLClassifier(name, id)
-{
- init();
-}
-
-/**
- * Standard destructor.
- */
-UMLEnum::~UMLEnum()
-{
- m_List.clear();
-}
-
-/**
- * Overloaded '==' operator.
- */
-bool UMLEnum::operator==(const UMLEnum & rhs) const
-{
- return UMLClassifier::operator==(rhs);
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLEnum::copyInto(UMLObject *lhs) const
-{
- UMLClassifier::copyInto(lhs);
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLEnum::clone() const
-{
- UMLEnum *clone = new UMLEnum();
- copyInto(clone);
-
- return clone;
-}
-
-/**
- * Initializes key variables of the class.
- */
-void UMLEnum::init()
-{
- m_BaseType = UMLObject::ot_Enum;
- setStereotypeCmd(QLatin1String("enum"));
-}
-
-/**
- * Creates a literal for the enum.
- * @return The UMLEnum created
- */
-UMLObject* UMLEnum::createEnumLiteral(const QString& name)
-{
- Uml::ID::Type id = UniqueID::gen();
- QString currentName;
- if (name.isNull()) {
- currentName = uniqChildName(UMLObject::ot_EnumLiteral);
- } else {
- currentName = name;
- }
-
- UMLEnumLiteral* newEnumLiteral = new UMLEnumLiteral(this, currentName);
-
- bool ok = true;
- bool goodName = false;
-
- //check for name.isNull() stops dialog being shown
- //when creating enum literal via list view
- while (ok && !goodName && name.isNull()) {
- ok = newEnumLiteral->showPropertiesDialog(UMLApp::app());
- QString name = newEnumLiteral->name();
-
- if(name.length() == 0) {
- KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
- } else {
- goodName = true;
- }
- }
-
- if (!ok) {
- delete newEnumLiteral;
- return NULL;
- }
-
- addEnumLiteral(newEnumLiteral);
-
- UMLDoc *umldoc = UMLApp::app()->document();
- umldoc->signalUMLObjectCreated(newEnumLiteral);
- return newEnumLiteral;
-}
-
-/**
- * Adds an enumliteral to the enum.
- * @param name The name of the enumliteral.
- * @param id The id of the enumliteral (optional.)
- * If omitted a new ID is assigned internally.
- * @return Pointer to the UMLEnumliteral created.
- */
-UMLObject* UMLEnum::addEnumLiteral(const QString &name, Uml::ID::Type id)
-{
- UMLObject *el = UMLCanvasObject::findChildObject(name);
- if (el != NULL) {
- uDebug() << name << " is already present";
- return el;
- }
- UMLEnumLiteral* literal = new UMLEnumLiteral(this, name, id);
- m_List.append(literal);
- UMLObject::emitModified();
- emit enumLiteralAdded(literal);
- connect(literal, SIGNAL(modified()), this, SIGNAL(modified()));
- return literal;
-}
-
-/**
- * Adds an already created enumliteral.
- * The enumliteral object must not belong to any other concept.
- * @param literal Pointer to the UMLEnumLiteral.
- * @param Log Pointer to the IDChangeLog.
- * @return True if the enumliteral was successfully added.
- */
-bool UMLEnum::addEnumLiteral(UMLEnumLiteral* literal, IDChangeLog* Log /* = 0*/)
-{
- QString name = (QString)literal->name();
- if (findChildObject(name) == NULL) {
- literal->setParent(this);
- m_List.append(literal);
- UMLObject::emitModified();
- emit enumLiteralAdded(literal);
- connect(literal, SIGNAL(modified()), this, SIGNAL(modified()));
- return true;
- } else if (Log) {
- Log->removeChangeByNewID(literal->id());
- delete literal;
- }
- return false;
-}
-
-/**
- * Adds an enumliteral to the enum, at the given position.
- * If position is negative or too large, the enumliteral is added
- * to the end of the list.
- * TODO: give default value -1 to position (append) - now it conflicts with the method above..
- * @param literal Pointer to the UMLEnumLiteral.
- * @param position Position index for the insertion.
- * @return True if the enumliteral was successfully added.
- */
-bool UMLEnum::addEnumLiteral(UMLEnumLiteral* literal, int position)
-{
- Q_ASSERT(literal);
- QString name = (QString)literal->name();
- if (findChildObject(name) == NULL) {
- literal->setParent(this);
- if (position >= 0 && position <= (int)m_List.count()) {
- m_List.insert(position, literal);
- } else {
- m_List.append(literal);
- }
- UMLObject::emitModified();
- emit enumLiteralAdded(literal);
- connect(literal, SIGNAL(modified()), this, SIGNAL(modified()));
- return true;
- }
- return false;
-}
-
-/**
- * Removes an enumliteral from the class.
- * @param literal The enumliteral to remove.
- * @return Count of the remaining enumliterals after removal.
- * Returns -1 if the given enumliteral was not found.
- */
-int UMLEnum::removeEnumLiteral(UMLEnumLiteral* literal)
-{
- if (!m_List.removeAll(literal)) {
- uDebug() << "cannot find att given in list";
- return -1;
- }
- emit enumLiteralRemoved(literal);
- UMLObject::emitModified();
- // If we are deleting the object, then we don't need to disconnect..this is done auto-magically
- // for us by QObject. -b.t.
- // disconnect(a, SIGNAL(modified()), this, SIGNAL(modified()));
- delete literal;
- return m_List.count();
-}
-
-/**
- * Returns the number of enumliterals for the class.
- * @return The number of enumliterals for the class.
- */
-int UMLEnum::enumLiterals()
-{
- return m_List.count();
-}
-
-/**
- * Emit the enumLiteralRemoved signal.
- */
-void UMLEnum::signalEnumLiteralRemoved(UMLClassifierListItem *elit)
-{
- emit enumLiteralRemoved(elit);
-}
-
-/**
- * Creates the <UML:Enum> element including its enumliterals.
- */
-void UMLEnum::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement enumElement = UMLObject::save(QLatin1String("UML:Enumeration"), qDoc);
- // save enum literals
- UMLClassifierListItemList enumLiterals = getFilteredList(UMLObject::ot_EnumLiteral);
- foreach (UMLClassifierListItem* pEnumLiteral, enumLiterals) {
- pEnumLiteral->saveToXMI(qDoc, enumElement);
- }
- qElement.appendChild(enumElement);
-}
-
-/**
- * Loads the <UML:Enum> element including its enumliterals.
- */
-bool UMLEnum::load(QDomElement& element)
-{
- QDomNode node = element.firstChild();
- while(!node.isNull()) {
- if (node.isComment()) {
- node = node.nextSibling();
- continue;
- }
- QDomElement tempElement = node.toElement();
- QString tag = tempElement.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("EnumerationLiteral")) ||
- UMLDoc::tagEq(tag, QLatin1String("ownedLiteral")) ||
- UMLDoc::tagEq(tag, QLatin1String("EnumLiteral"))) { // for backward compatibility
- UMLEnumLiteral* pEnumLiteral = new UMLEnumLiteral(this);
- if(!pEnumLiteral->loadFromXMI(tempElement)) {
- return false;
- }
- m_List.append(pEnumLiteral);
- } else if (UMLDoc::tagEq(tag, QLatin1String("Enumeration.literal"))) { // Embarcadero's Describe
- if (! load(tempElement))
- return false;
- } else if (tag == QLatin1String("stereotype")) {
- uDebug() << name() << ": losing old-format stereotype.";
- } else {
- uWarning() << "unknown child type: " << tag;
- }
- node = node.nextSibling();
- }//end while
- return true;
-}
-
-/**
- * Create a new ClassifierListObject (enumLiteral)
- * according to the given XMI tag.
- * Returns NULL if the string given does not contain one of the tags
- * <UML:EnumLiteral>
- * Used by the clipboard for paste operation.
- * Reimplemented from UMLClassifier for UMLEnum
- */
-UMLClassifierListItem* UMLEnum::makeChildObject(const QString& xmiTag)
-{
- UMLClassifierListItem* pObject = NULL;
- if (UMLDoc::tagEq(xmiTag, QLatin1String("EnumerationLiteral")) ||
- UMLDoc::tagEq(xmiTag, QLatin1String("EnumLiteral"))) {
- pObject = new UMLEnumLiteral(this);
- }
- return pObject;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/enum.h umbrello-kf6-15.08.1/umbrello/enum.h
--- umbrello-kf6-15.08.1.orig/umbrello/enum.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/enum.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,72 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ENUM_H
-#define ENUM_H
-
-#include "classifier.h"
-
-class UMLEnumLiteral;
-
-/**
- * This class contains the non-graphical information required for a UML
- * Enum.
- * This class inherits from @ref UMLClassifier which contains most of the
- * information.
- *
- * @short Non-graphical Information for an Enum.
- * @author Jonathan Riddell
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLEnum : public UMLClassifier
-{
- Q_OBJECT
-public:
- explicit UMLEnum(const QString& name = QString(), Uml::ID::Type id = Uml::ID::None);
-
- virtual ~UMLEnum();
-
- bool operator==(const UMLEnum& rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- UMLObject* createEnumLiteral(const QString& name = QString());
-
- UMLObject* addEnumLiteral(const QString &name, Uml::ID::Type id = Uml::ID::None);
-
- bool addEnumLiteral(UMLEnumLiteral* literal, IDChangeLog* Log = 0);
- bool addEnumLiteral(UMLEnumLiteral* literal, int position);
-
- int removeEnumLiteral(UMLEnumLiteral* literal);
-
- int enumLiterals();
-
- void signalEnumLiteralRemoved(UMLClassifierListItem *elit);
-
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- virtual UMLClassifierListItem* makeChildObject(const QString& xmiTag);
-
-signals:
- void enumLiteralAdded(UMLClassifierListItem*);
- void enumLiteralRemoved(UMLClassifierListItem*);
-
-protected:
- bool load(QDomElement & element);
-
-private:
- void init();
-
-};
-
-#endif // ENUM_H
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/enumliteral.cpp umbrello-kf6-15.08.1/umbrello/enumliteral.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/enumliteral.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/enumliteral.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,126 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "enumliteral.h"
-
-// kde includes
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-#include <KLocalizedString>
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-
-/**
- * Sets up an enum literal.
- * @param parent The parent of this UMLEnumLiteral.
- * @param name The name of this UMLEnumLiteral.
- * @param id The unique id given to this UMLEnumLiteral.
- */
-UMLEnumLiteral::UMLEnumLiteral(UMLObject *parent,
- const QString& name, Uml::ID::Type id)
- : UMLClassifierListItem(parent, name, id)
-{
- m_BaseType = UMLObject::ot_EnumLiteral;
-}
-
-/**
- * Sets up an enum literal.
- * @param parent The parent of this UMLEnumLiteral.
- */
-UMLEnumLiteral::UMLEnumLiteral(UMLObject *parent)
- : UMLClassifierListItem(parent)
-{
- m_BaseType = UMLObject::ot_EnumLiteral;
-}
-
-/**
- * Destructor.
- */
-UMLEnumLiteral::~UMLEnumLiteral()
-{
-}
-
-/**
- * Overloaded '==' operator
- */
-bool UMLEnumLiteral::operator==(const UMLEnumLiteral& rhs) const
-{
- if (this == &rhs) {
- return true;
- }
- if (!UMLObject::operator==(rhs)) {
- return false;
- }
- return true;
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLEnumLiteral::copyInto(UMLObject *lhs) const
-{
- UMLClassifierListItem::copyInto(lhs);
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLEnumLiteral::clone() const
-{
- UMLEnumLiteral *clone = new UMLEnumLiteral((UMLObject *) parent());
- copyInto(clone);
-
- return clone;
-}
-
-/**
- * Creates the <UML:EnumLiteral> XMI element.
- */
-void UMLEnumLiteral::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement attributeElement = UMLObject::save(QLatin1String("UML:EnumerationLiteral"), qDoc);
- qElement.appendChild(attributeElement);
-}
-
-/**
- * Loads the <UML:EnumLiteral> XMI element (empty.)
- */
-bool UMLEnumLiteral::load(QDomElement& element)
-{
- Q_UNUSED(element);
- return true;
-}
-
-/**
- * Display the properties configuration dialog for the enum literal.
- */
-bool UMLEnumLiteral::showPropertiesDialog(QWidget* parent)
-{
- bool ok;
-#if QT_VERSION >= 0x050000
- QString enumName = QInputDialog::getText(parent,
- i18nc("enum name", "Name"), i18n("Enter name:"),
- QLineEdit::Normal,
- name(), &ok);
-#else
- QString enumName = KInputDialog::getText(i18nc("enum name", "Name"), i18n("Enter name:"), name(), &ok, parent);
-#endif
- if (ok && !enumName.isEmpty()) {
- setName(enumName);
- return true;
- } else {
- return false;
- }
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/enumliteral.h umbrello-kf6-15.08.1/umbrello/enumliteral.h
--- umbrello-kf6-15.08.1.orig/umbrello/enumliteral.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/enumliteral.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,49 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ENUMLITERAL_H
-#define ENUMLITERAL_H
-
-#include "classifierlistitem.h"
-
-/**
- * This class is used to set up information for an enum literal. Enum
- * literals are the values that enums can be set to.
- *
- * @short Sets up attribute information.
- * @author Paul Hensgen <phensgen@techie.com>
- * @see UMLObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLEnumLiteral : public UMLClassifierListItem
-{
-public:
- UMLEnumLiteral(UMLObject* parent,
- const QString& name, Uml::ID::Type id = Uml::ID::None);
- explicit UMLEnumLiteral(UMLObject* parent);
-
- bool operator==(const UMLEnumLiteral &rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- virtual ~UMLEnumLiteral();
-
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
- virtual bool showPropertiesDialog(QWidget* parent = 0);
-
-protected:
- bool load(QDomElement& element);
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/folder.cpp umbrello-kf6-15.08.1/umbrello/folder.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/folder.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/folder.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,558 +0,0 @@
-/***************************************************************************
- * 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) 2006-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "folder.h"
-
-// app includes
-#include "debug_utils.h"
-#include "model_utils.h"
-#include "object_factory.h"
-#include "optionstate.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-// kde includes
-#include <KLocalizedString>
-#include <KMessageBox>
-
-// qt includes
-#include <QFile>
-
-/**
- * Sets up a Folder.
- * @param name The name of the Folder.
- * @param id The unique id of the Folder. A new ID will be generated
- * if this argument is left away.
- */
-UMLFolder::UMLFolder(const QString & name, Uml::ID::Type id)
- : UMLPackage(name, id)
-{
- m_BaseType = UMLObject::ot_Folder;
- UMLObject::setStereotypeCmd(QLatin1String("folder"));
-}
-
-/**
- * Empty destructor.
- */
-UMLFolder::~UMLFolder()
-{
- qDeleteAll(m_diagrams);
- m_diagrams.clear();
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLFolder::clone() const
-{
- UMLFolder *clone = new UMLFolder();
- UMLObject::copyInto(clone);
- return clone;
-}
-
-/**
- * Set the localized name of this folder.
- * This is set for the predefined root views (Logical,
- * UseCase, Component, Deployment, EntityRelationship,
- * and the Datatypes folder inside the Logical View.)
- */
-void UMLFolder::setLocalName(const QString& localName)
-{
- m_localName = localName;
-}
-
-/**
- * Return the localized name of this folder.
- * Only useful for the predefined root folders.
- */
-QString UMLFolder::localName() const
-{
- return m_localName;
-}
-
-/**
- * Add a view to the diagram list.
- */
-void UMLFolder::addView(UMLView *view)
-{
- m_diagrams.append(view);
-}
-
-/**
- * Remove a view from the diagram list.
- */
-void UMLFolder::removeView(UMLView *view)
-{
- m_diagrams.removeAll(view);
- delete view;
-}
-
-/**
- * Append the views in this folder to the given diagram list.
- * @param viewList The UMLViewList to which to append the diagrams.
- * @param includeNested Whether to include diagrams from nested folders
- * (default: true.)
- */
-void UMLFolder::appendViews(UMLViewList& viewList, bool includeNested)
-{
- if (includeNested) {
- foreach (UMLObject* o, m_objects) {
- uIgnoreZeroPointer(o);
- if (o->baseType() == UMLObject::ot_Folder) {
- UMLFolder *f = static_cast<UMLFolder*>(o);
- f->appendViews(viewList);
- }
- }
- }
- foreach (UMLView* v, m_diagrams) {
- viewList.append(v);
- }
-}
-
-/**
- * Acivate the views in this folder.
- * "Activation": Some widgets require adjustments after loading from file,
- * those are done here.
- */
-void UMLFolder::activateViews()
-{
- foreach (UMLObject* o, m_objects) {
- uIgnoreZeroPointer(o);
- if (o->baseType() == UMLObject::ot_Folder) {
- UMLFolder *f = static_cast<UMLFolder*>(o);
- f->activateViews();
- }
- }
-
- foreach (UMLView* v, m_diagrams) {
- v->umlScene()->activateAfterLoad();
- }
- // Make sure we have a treeview item for each diagram.
- // It may happen that we are missing them after switching off tabbed widgets.
- Settings::OptionState optionState = Settings::optionState();
- if (optionState.generalState.tabdiagrams) {
- return;
- }
- Model_Utils::treeViewAddViews(m_diagrams);
-}
-
-/**
- * Seek a view of the given ID in this folder.
- * @param id ID of the view to find.
- * @return Pointer to the view if found, NULL if no view found.
- */
-UMLView *UMLFolder::findView(Uml::ID::Type id)
-{
- foreach (UMLView* v, m_diagrams) {
- if (v->umlScene()->ID() == id) {
- return v;
- }
- }
-
- UMLView* v = 0;
- UMLPackageList packages;
- appendPackages(packages);
- foreach (UMLPackage *o, packages) {
- if (o->baseType() != UMLObject::ot_Folder) {
- continue;
- }
- UMLFolder *f = static_cast<UMLFolder*>(o);
- v = f->findView(id);
- if (v) {
- break;
- }
- }
- return v;
-}
-
-/**
- * Seek a view by the type and name given.
- * @param type The type of view to find.
- * @param name The name of the view to find.
- * @param searchAllScopes Search in all subfolders (default: true.)
- * @return Pointer to the view found, or NULL if not found.
- */
-UMLView *UMLFolder::findView(Uml::DiagramType::Enum type, const QString &name, bool searchAllScopes)
-{
- foreach (UMLView* v, m_diagrams) {
- if (v->umlScene()->type() == type && v->umlScene()->name() == name) {
- return v;
- }
- }
-
- UMLView* v = 0;
- if (searchAllScopes) {
- foreach (UMLObject* o, m_objects) {
- uIgnoreZeroPointer(o);
- if (o->baseType() != UMLObject::ot_Folder) {
- continue;
- }
- UMLFolder *f = static_cast<UMLFolder*>(o);
- v = f->findView(type, name, searchAllScopes);
- if (v) {
- break;
- }
- }
- }
- return v;
-}
-
-/**
- * Set the options for the views in this folder.
- */
-void UMLFolder::setViewOptions(const Settings::OptionState& optionState)
-{
- // for each view update settings
- foreach (UMLView* v, m_diagrams) {
- v->umlScene()->setOptionState(optionState);
- }
-}
-
-/**
- * Remove all views in this folder.
- */
-void UMLFolder::removeAllViews()
-{
- foreach (UMLObject* o, m_objects) {
- uIgnoreZeroPointer(o);
- if (o->baseType() != UMLObject::ot_Folder)
- continue;
- UMLFolder *f = static_cast<UMLFolder*>(o);
- f->removeAllViews();
- }
-
- foreach (UMLView* v, m_diagrams) {
- // TODO ------------------ check this code - bad: calling back to UMLDoc::removeView()
- v->umlScene()->removeAllAssociations(); // note : It may not be apparent, but when we remove all associations
- // from a view, it also causes any UMLAssociations that lack parent
- // association widgets (but once had them) to remove themselves from
- // this document.
- uDebug() << "removing " << v->umlScene()->name();
- UMLApp::app()->document()->removeView(v, false);
- }
-
- qDeleteAll(m_diagrams);
- m_diagrams.clear();
-}
-
-/**
- * Set the folder file name for a separate submodel.
- */
-void UMLFolder::setFolderFile(const QString& fileName)
-{
- m_folderFile = fileName;
-}
-
-/**
- * Get the folder file name for a separate submodel.
- */
-QString UMLFolder::folderFile() const
-{
- return m_folderFile;
-}
-
-/**
- * Auxiliary to saveToXMI(): Save the contained objects and diagrams.
- * Can be used regardless of whether saving to the main model file
- * or to an external folder file (see m_folderFile.)
- */
-void UMLFolder::saveContents(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement ownedElement = qDoc.createElement(QLatin1String("UML:Namespace.ownedElement"));
- UMLObject *obj = 0;
- // Save contained objects if any.
- for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
- obj = oit.next();
- uIgnoreZeroPointer(obj);
- obj->saveToXMI (qDoc, ownedElement);
- }
- // Save asscociations if any.
- for (UMLObjectListIt ait(m_List); ait.hasNext();) {
- obj = ait.next();
- obj->saveToXMI (qDoc, ownedElement);
- }
- qElement.appendChild(ownedElement);
- // Save diagrams to `extension'.
- if (m_diagrams.count()) {
- QDomElement diagramsElement = qDoc.createElement(QLatin1String("diagrams"));
-
- foreach (UMLView* pView, m_diagrams) {
- pView->umlScene()->saveToXMI(qDoc, diagramsElement);
- }
- QDomElement extension = qDoc.createElement(QLatin1String("XMI.extension"));
- extension.setAttribute(QLatin1String("xmi.extender"), QLatin1String("umbrello-kf6"));
- extension.appendChild(diagramsElement);
- qElement.appendChild(extension);
- }
-}
-
-/**
- * Auxiliary to saveToXMI(): Creates a <UML:Model> element when saving
- * a predefined modelview, or a <UML:Package> element when saving a
- * user created folder. Invokes saveContents() with the newly created
- * element.
- */
-void UMLFolder::save(QDomDocument& qDoc, QDomElement& qElement)
-{
- UMLDoc *umldoc = UMLApp::app()->document();
- QString elementName(QLatin1String("UML:Package"));
- const Uml::ModelType::Enum mt = umldoc->rootFolderType(this);
- if (mt != Uml::ModelType::N_MODELTYPES) {
- elementName = QLatin1String("UML:Model");
- }
- QDomElement folderElement = UMLObject::save(elementName, qDoc);
- saveContents(qDoc, folderElement);
- qElement.appendChild(folderElement);
-}
-
-/**
- * Creates a UML:Model or UML:Package element:
- * UML:Model is created for the predefined fixed folders,
- * UML:Package with stereotype "folder" is created for all else.
- */
-void UMLFolder::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- if (m_folderFile.isEmpty()) {
- save(qDoc, qElement);
- return;
- }
- // See if we can create the external file.
- // If not then internalize the folder.
- UMLDoc *umldoc = UMLApp::app()->document();
-#if QT_VERSION >= 0x050000
- QString fileName = umldoc->url().adjusted(QUrl::RemoveFilename).path() + m_folderFile;
-#else
- QString fileName = umldoc->url().directory() + QLatin1Char('/') + m_folderFile;
-#endif
- QFile file(fileName);
- if (!file.open(QIODevice::WriteOnly)) {
- uError() << m_folderFile << QLatin1String(": ")
- << "cannot create file, contents will be saved in main model file";
- m_folderFile.clear();
- save(qDoc, qElement);
- return;
- }
- // Okay, external file is writable. Wrap up main file.
- QDomElement folderElement = UMLObject::save(QLatin1String("UML:Package"), qDoc);
- QDomElement extension = qDoc.createElement(QLatin1String("XMI.extension"));
- extension.setAttribute(QLatin1String("xmi.extender"), QLatin1String("umbrello-kf6"));
- QDomElement fileElement = qDoc.createElement(QLatin1String("external_file"));
- fileElement.setAttribute(QLatin1String("name"), m_folderFile);
- extension.appendChild(fileElement);
- folderElement.appendChild(extension);
- qElement.appendChild(folderElement);
-
- // Save folder to external file.
- QDomDocument folderDoc;
- QDomElement folderRoot;
- QDomProcessingInstruction xmlHeading =
- folderDoc.createProcessingInstruction(QLatin1String("xml"),
- QString::fromLatin1("version=\"1.0\" encoding=\"UTF-8\""));
- folderDoc.appendChild(xmlHeading);
- folderRoot = folderDoc.createElement(QLatin1String("external_file"));
- folderRoot.setAttribute(QLatin1String("name"), name());
- folderRoot.setAttribute(QLatin1String("filename"), m_folderFile);
- folderRoot.setAttribute(QLatin1String("mainModel"), umldoc->url().fileName());
- folderRoot.setAttribute(QLatin1String("parentId"), Uml::ID::toString(m_pUMLPackage->id()));
- folderRoot.setAttribute(QLatin1String("parent"), m_pUMLPackage->fullyQualifiedName(QLatin1String("::"), true));
- saveContents(folderDoc, folderRoot);
- folderDoc.appendChild(folderRoot);
- QTextStream stream(&file);
- stream.setCodec("UTF-8");
- stream << folderDoc.toString();
- file.close();
-}
-
-/**
- * Auxiliary to load():
- * Load the diagrams from the "diagrams" in the <XMI.extension>
- */
-bool UMLFolder::loadDiagramsFromXMI(QDomNode& diagrams)
-{
- const Settings::OptionState optionState = Settings::optionState();
- UMLDoc *umldoc = UMLApp::app()->document();
- bool totalSuccess = true;
- for (QDomElement diagram = diagrams.toElement(); !diagram.isNull();
- diagrams = diagrams.nextSibling(), diagram = diagrams.toElement()) {
- QString tag = diagram.tagName();
- if (tag != QLatin1String("diagram")) {
- uDebug() << "ignoring " << tag << " in <diagrams>";
- continue;
- }
- UMLView * pView = new UMLView(this);
- pView->umlScene()->setOptionState(optionState);
- if (pView->umlScene()->loadFromXMI(diagram)) {
- pView->hide();
- umldoc->addView(pView);
- } else {
- delete pView;
- totalSuccess = false;
- }
- }
- return totalSuccess;
-}
-
-/**
- * Folders in the listview can be marked such that their contents
- * are saved to a separate file.
- * This method loads the separate folder file.
- * CAVEAT: This is not XMI standard compliant.
- * If standard compliance is an issue then avoid folder files.
- * @param path Fully qualified file name, i.e. absolute directory
- * plus file name.
- * @return True for success.
- */
-bool UMLFolder::loadFolderFile(const QString& path)
-{
- QFile file(path);
- if (!file.exists()) {
- KMessageBox::error(0, i18n("The folderfile %1 does not exist.", path), i18n("Load Error"));
- return false;
- }
- if (!file.open(QIODevice::ReadOnly)) {
- KMessageBox::error(0, i18n("The folderfile %1 cannot be opened.", path), i18n("Load Error"));
- return false;
- }
- QTextStream stream(&file);
- QString data = stream.readAll();
- file.close();
- QDomDocument doc;
- QString error;
- int line;
- if (!doc.setContent(data, false, &error, &line)) {
- uError() << "Cannot set content:" << error << " line:" << line;
- return false;
- }
- QDomNode rootNode = doc.firstChild();
- while (rootNode.isComment() || rootNode.isProcessingInstruction()) {
- rootNode = rootNode.nextSibling();
- }
- if (rootNode.isNull()) {
- uError() << "Root node is Null";
- return false;
- }
- QDomElement element = rootNode.toElement();
- QString type = element.tagName();
- if (type != QLatin1String("external_file")) {
- uError() << "Root node has unknown type " << type;
- return false;
- }
- return load(element);
-}
-
-/**
- * Loads the owned elements of the <UML:Model>.
- */
-bool UMLFolder::load(QDomElement& element)
-{
- UMLDoc *umldoc = UMLApp::app()->document();
- bool totalSuccess = true;
- for (QDomNode node = element.firstChild(); !node.isNull();
- node = node.nextSibling()) {
- if (node.isComment())
- continue;
- QDomElement tempElement = node.toElement();
- QString type = tempElement.tagName();
- if (Model_Utils::isCommonXMIAttribute(type))
- continue;
- if (UMLDoc::tagEq(type, QLatin1String("Namespace.ownedElement")) ||
- UMLDoc::tagEq(type, QLatin1String("Namespace.contents"))) {
- //CHECK: umbrello-kf6 currently assumes that nested elements
- // are ownedElements anyway.
- // Therefore these tags are not further interpreted.
- if (! load(tempElement)) {
- uDebug() << "An error happened while loading the " << type
- << " of the " << name();
- totalSuccess = false;
- }
- continue;
- } else if (UMLDoc::tagEq(type, QLatin1String("packagedElement")) ||
- UMLDoc::tagEq(type, QLatin1String("ownedElement"))) {
- type = tempElement.attribute(QLatin1String("xmi:type"));
- } else if (type == QLatin1String("XMI.extension")) {
- for (QDomNode xtnode = node.firstChild(); !xtnode.isNull();
- xtnode = xtnode.nextSibling()) {
- QDomElement el = xtnode.toElement();
- const QString xtag = el.tagName();
- if (xtag == QLatin1String("diagrams")) {
- QDomNode diagramNode = xtnode.firstChild();
- if (!loadDiagramsFromXMI(diagramNode))
- totalSuccess = false;
- } else if (xtag == QLatin1String("external_file")) {
-#if QT_VERSION >= 0x050000
- const QString rootDir(umldoc->url().adjusted(QUrl::RemoveFilename).path());
-#else
- const QString rootDir(umldoc->url().directory());
-#endif
- QString fileName = el.attribute(QLatin1String("name"));
- const QString path(rootDir + QLatin1Char('/') + fileName);
- if (loadFolderFile(path))
- m_folderFile = fileName;
- } else {
- uDebug() << name() << ": ignoring XMI.extension " << xtag;
- continue;
- }
- }
- continue;
- }
- // Do not re-create the predefined Datatypes folder in the Logical View,
- // it already exists.
- UMLFolder *logicalView = umldoc->rootFolder(Uml::ModelType::Logical);
- if (this == logicalView && UMLDoc::tagEq(type, QLatin1String("Package"))) {
- QString thisName = tempElement.attribute(QLatin1String("name"));
- if (thisName == QLatin1String("Datatypes")) {
- UMLFolder *datatypeFolder = umldoc->datatypeFolder();
- if (!datatypeFolder->loadFromXMI(tempElement))
- totalSuccess = false;
- continue;
- }
- }
- UMLObject *pObject = 0;
- // Avoid duplicate creation of forward declared object
- QString idStr = Model_Utils::getXmiId(tempElement);
- if (!idStr.isEmpty()) {
- Uml::ID::Type id = Uml::ID::fromString(idStr);
- pObject = umldoc->findObjectById(id);
- if (pObject) {
- uDebug() << "object " << idStr << "already exists";
- }
- }
- if (pObject == 0) {
- QString stereoID = tempElement.attribute(QLatin1String("stereotype"));
- pObject = Object_Factory::makeObjectFromXMI(type, stereoID);
- if (!pObject) {
- uWarning() << "Unknown type of umlobject to create: " << type;
- continue;
- }
- }
- pObject->setUMLPackage(this);
- if (!pObject->loadFromXMI(tempElement)) {
- removeObject(pObject);
- delete pObject;
- totalSuccess = false;
- }
- }
- return totalSuccess;
-}
-
-/**
- * Overloading operator for debugging output.
- */
-QDebug operator<<(QDebug out, const UMLFolder& item)
-{
- out.nospace() << "UMLFolder: localName=" << item.m_localName
- << ", folderFile=" << item.m_folderFile
- << ", diagrams=" << item.m_diagrams.count();
- return out.space();
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/folder.h umbrello-kf6-15.08.1/umbrello/folder.h
--- umbrello-kf6-15.08.1.orig/umbrello/folder.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/folder.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,92 +0,0 @@
-/***************************************************************************
- * 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) 2006-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLFOLDER_H
-#define UMLFOLDER_H
-
-#include "package.h"
-#include "umlviewlist.h"
-#include "optionstate.h"
-
-/**
- * This class manages the UMLObjects and UMLViews of a Folder.
- * This class inherits from UMLPackage which contains most
- * of the information.
- *
- * The UMLDoc class allocates a fixed instance of this class for
- * each of the predefined Logical, UseCase, Component, Deployment, and
- * Entity-Relationship folders. Further instances are created on demand
- * for user folders.
- *
- * @short Non-graphical management of objects and diagrams of a Folder
- * @author Oliver Kellogg
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- *
- * TODO: This whole class needs a relook regarding view/scene.
- */
-class UMLFolder : public UMLPackage
-{
- Q_OBJECT
-public:
- explicit UMLFolder(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLFolder();
-
- virtual UMLObject* clone() const;
-
- void setLocalName(const QString& localName);
- QString localName() const;
-
- void addView(UMLView *view);
-
- void removeView(UMLView *view);
-
- void appendViews(UMLViewList& viewList, bool includeNested = true);
-
- void activateViews();
-
- UMLView* findView(Uml::ID::Type id);
- UMLView* findView(Uml::DiagramType::Enum type, const QString &name, bool searchAllScopes = true);
-
- void setViewOptions(const Settings::OptionState& optionState);
-
- void removeAllViews();
-
- void setFolderFile(const QString& fileName);
- QString folderFile() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- friend QDebug operator<<(QDebug out, const UMLFolder& item);
-
-protected:
- void saveContents(QDomDocument& qDoc, QDomElement& qElement);
-
- void save(QDomDocument& qDoc, QDomElement& qElement);
-
- bool loadDiagramsFromXMI(QDomNode& diagrams);
-
- bool loadFolderFile(const QString& path);
-
- bool load(QDomElement & element);
-
-private:
- QString m_localName; ///< i18n name, only used for predefined root folders
- /**
- * If m_folderFile is not empty then it contains a file name to which
- * this folder is saved.
- * In this case the folder file acts as a physically separate submodel.
- * What is saved in the main model is not the folder contents but a
- * reference to the folder file.
- */
- QString m_folderFile;
- UMLViewList m_diagrams;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/foreignkeyconstraint.cpp umbrello-kf6-15.08.1/umbrello/foreignkeyconstraint.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/foreignkeyconstraint.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/foreignkeyconstraint.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,444 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-//own header
-#include "foreignkeyconstraint.h"
-
-// app includes
-#include "debug_utils.h"
-#include "entity.h"
-#include "entityattribute.h"
-#include "umlobject.h"
-#include "umldoc.h"
-#include "uml.h"
-#include "umlforeignkeyconstraintdialog.h"
-#include "object_factory.h"
-
-/**
- * Sets up a constraint.
- * @param parent The parent of this UMLForeignKeyConstraint.
- * @param name The name of this UMLForeignKeyConstraint.
- * @param id The unique id given to this UMLForeignKeyConstraint.
- */
-UMLForeignKeyConstraint::UMLForeignKeyConstraint(UMLObject *parent,
- const QString& name, Uml::ID::Type id)
- : UMLEntityConstraint(parent, name, id)
-{
- init();
-}
-
-/**
- * Sets up a constraint.
- * @param parent The parent of this UMLForeignKeyConstraint.
- */
-UMLForeignKeyConstraint::UMLForeignKeyConstraint(UMLObject *parent)
- : UMLEntityConstraint(parent)
-{
- init();
-}
-
-/**
- * Initialisation of common variables
- */
-void UMLForeignKeyConstraint::init()
-{
- // initialise attributes
- m_BaseType = UMLObject::ot_ForeignKeyConstraint;
-
- // should be NULL actually
- // self referencing assigned to protect default behaviour
- m_ReferencedEntity = static_cast<UMLEntity*>(parent());
-
- m_UpdateAction = uda_NoAction;
- m_DeleteAction = uda_NoAction;
-
- // connecte signals and slots
- connect(this, SIGNAL(sigReferencedEntityChanged()), this, SLOT(slotReferencedEntityChanged()));
-}
-
-/**
- * Overloaded '==' operator
- */
-bool UMLForeignKeyConstraint::operator==(const UMLForeignKeyConstraint &rhs) const
-{
- if(this == &rhs)
- return true;
-
- if(!UMLObject::operator==(rhs))
- return false;
-
- return true;
-}
-
-/**
- * Destructor.
- */
-UMLForeignKeyConstraint::~UMLForeignKeyConstraint()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the UMLForeignKeyConstraint
- * object.
- */
-void UMLForeignKeyConstraint::copyInto(UMLObject *lhs) const
-{
- UMLForeignKeyConstraint *target = static_cast<UMLForeignKeyConstraint*>(lhs);
-
- // call the parent first.
- UMLEntityConstraint::copyInto(target);
-
- // Copy all datamembers
- target->m_ReferencedEntity = m_ReferencedEntity;
- target->m_AttributeMap = m_AttributeMap;
- target->m_DeleteAction = m_DeleteAction;
- target->m_UpdateAction = m_UpdateAction;
-}
-
-/**
- * Make a clone of the UMLForeignKeyConstraint.
- */
-UMLObject* UMLForeignKeyConstraint::clone() const
-{
- //FIXME: The new attribute should be slaved to the NEW parent not the old.
- UMLForeignKeyConstraint *clone = new UMLForeignKeyConstraint(static_cast<UMLObject*>(parent()));
- copyInto(clone);
- return clone;
-}
-
-/**
- * Returns a string representation of the UMLForeignKeyConstraint.
- * @param sig If true will show the attribute type and initial value.
- * @return Returns a string representation of the UMLAttribute.
- */
-QString UMLForeignKeyConstraint::toString(Uml::SignatureType::Enum sig)
-{
- QString s;
-
- if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::SigNoVis) {
- s = name() + QLatin1Char(':');
- s += QLatin1String(" Foreign Key (");
- QList<UMLEntityAttribute*> keys = m_AttributeMap.keys();
- bool first = true;
- foreach(UMLEntityAttribute* key, keys) {
- if (first) {
- first = false;
- } else
- s += QLatin1Char(',');
- s += key->name();
- }
- s += QLatin1Char(')');
- }
-
- return s;
-}
-
-/**
- * Creates the <UML:ForeignKeyConstraint> XMI element.
- */
-void UMLForeignKeyConstraint::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement foreignKeyConstraintElement = UMLObject::save(QLatin1String("UML:ForeignKeyConstraint"), qDoc);
-
- foreignKeyConstraintElement.setAttribute(QLatin1String("referencedEntity"), Uml::ID::toString(m_ReferencedEntity->id()));
-
- int updateAction = (int)m_UpdateAction;
- int deleteAction = (int)m_DeleteAction;
-
- foreignKeyConstraintElement.setAttribute(QLatin1String("updateAction"), updateAction);
- foreignKeyConstraintElement.setAttribute(QLatin1String("deleteAction"), deleteAction);
-
- QMap<UMLEntityAttribute*, UMLEntityAttribute*>::iterator i;
- for (i = m_AttributeMap.begin(); i!= m_AttributeMap.end() ; ++i) {
- QDomElement mapElement = qDoc.createElement(QLatin1String("AttributeMap"));
- mapElement.setAttribute(QLatin1String("key"), Uml::ID::toString((i.key())->id()));
- mapElement.setAttribute(QLatin1String("value"), Uml::ID::toString((i.value())->id()));
- foreignKeyConstraintElement.appendChild(mapElement);
- }
-
- qElement.appendChild(foreignKeyConstraintElement);
-}
-
-/**
- * Display the properties configuration dialog for the attribute.
- */
-bool UMLForeignKeyConstraint::showPropertiesDialog(QWidget* parent)
-{
- UMLForeignKeyConstraintDialog dialog(parent, this);
- return dialog.exec();
-}
-
-/**
- * Adds the attribute pair to the attributeMap
- * @param pAttr The Attribute of the Parent Entity
- * @param rAttr The Attribute of the Referenced Entity
- * @return true if the attribute pair could be added successfully
- */
-bool UMLForeignKeyConstraint::addEntityAttributePair(UMLEntityAttribute* pAttr, UMLEntityAttribute* rAttr)
-{
- UMLEntity *owningParent = dynamic_cast<UMLEntity*>(parent());
-
- if (pAttr == NULL || rAttr == NULL) {
- uError() << "null values passed to function";
- return false;
- }
- // check for sanity of pAttr (parent entity attribute)
- if (owningParent == NULL) {
- uError() << name() << ": parent is not a UMLEntity";
- return false;
- }
-
- if (owningParent->findChildObjectById(pAttr->id()) == NULL) {
- uError() << " parent " << owningParent->name()
- << " does not contain attribute " << pAttr->name();
- return false;
- }
-
- //check for sanity of rAttr (referenced entity attribute)
- if (m_ReferencedEntity != NULL) {
- if (m_ReferencedEntity->findChildObjectById(rAttr->id()) == NULL) {
- uError() << " parent " << m_ReferencedEntity->name()
- << " does not contain attribute " << rAttr->name();
- return false;
- }
- } else {
- uError() << "Referenced Table Not set. Not Adding Pair ";
- return false;
- }
-
- // check if key takes part in some mapping
- if (m_AttributeMap.contains(pAttr) == true)
- return false;
-
- // check if value takes part in some mapping (no direct function)
- foreach(UMLEntityAttribute* attr, m_AttributeMap.values()) {
- if (rAttr == attr)
- return false;
- }
-
- // passed all checks, insert now
- m_AttributeMap.insert(pAttr, rAttr);
-
- QMap<UMLEntityAttribute*, UMLEntityAttribute*>::iterator i;
- for (i = m_AttributeMap.begin(); i != m_AttributeMap.end(); ++i)
- uDebug() << i.key()->name() << QLatin1String(" ") << i.key()->baseType()
- << QLatin1String(" ") << i.value()->name() << QLatin1String(" ") << i.value()->baseType();
-
- return true;
-}
-
-/**
- * Removes an Attribute pair
- * @param pAttr The Attribute of the Parent Entity in the map. This attribute is the
- key of the map.
- * @return true of the attribute pair could be removed successfully
- */
-bool UMLForeignKeyConstraint::removeEntityAttributePair(UMLEntityAttribute* /*key*/ pAttr)
-{
- bool state = m_AttributeMap.remove(pAttr);
-
- return state;
-}
-
-/**
- * Check if a attribute pair already exists
- * @param pAttr The Attribute of the Parent Entity
- * @param rAttr The Attribute of the Referenced Entity
- * @return true if the attribute pair could be found.
- */
-bool UMLForeignKeyConstraint::hasEntityAttributePair(UMLEntityAttribute* pAttr, UMLEntityAttribute* rAttr) const
-{
- if (m_AttributeMap.contains(pAttr)) {
- if (m_AttributeMap.value(pAttr) == rAttr) {
- return true;
- }
- }
-
- return false;
-}
-
-/**
- * Loads the <UML:ForeignKeyConstraint> XMI element.
- */
-bool UMLForeignKeyConstraint::load(QDomElement & element)
-{
- UMLDoc* doc = UMLApp::app()->document();
-
- Uml::ID::Type referencedEntityId = Uml::ID::fromString(element.attribute(QLatin1String("referencedEntity")));
-
- UMLObject* obj = doc->findObjectById(referencedEntityId);
- m_ReferencedEntity = static_cast<UMLEntity*>(obj);
-
- if (m_ReferencedEntity == NULL) {
- // save for resolving later
- m_pReferencedEntityID = referencedEntityId;
- }
-
- m_UpdateAction = (UpdateDeleteAction)element.attribute(QLatin1String("updateAction")).toInt();
- m_DeleteAction = (UpdateDeleteAction)element.attribute(QLatin1String("deleteAction")).toInt();
-
- QDomNode node = element.firstChild();
- while (!node.isNull()) {
- if (node.isComment()) {
- node = node.nextSibling();
- continue;
- }
- QDomElement tempElement = node.toElement();
- QString tag = tempElement.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("AttributeMap"))) {
-
- QString xmiKey = tempElement.attribute(QLatin1String("key"));
- QString xmiValue = tempElement.attribute(QLatin1String("value"));
- Uml::ID::Type keyId = Uml::ID::fromString(xmiKey);
- Uml::ID::Type valueId = Uml::ID::fromString(xmiValue);
-
- UMLEntity* parentEntity = static_cast<UMLEntity*>(parent());
- UMLObject* keyObj = parentEntity->findChildObjectById(keyId);
- UMLEntityAttribute* key = static_cast<UMLEntityAttribute*>(keyObj);
-
- if (keyObj == NULL) {
- uWarning() << "unable to resolve foreign key referencing attribute " << xmiKey;
- } else if (m_ReferencedEntity == NULL) {
- // if referenced entity is null, then we won't find its attributes even
- // save for resolving later
- m_pEntityAttributeIDMap.insert(key, valueId);
- } else {
- UMLObject* valueObj = m_ReferencedEntity->findChildObjectById(valueId);
- if (valueObj == NULL) {
- uWarning() << "unable to resolve foreign key referenced attribute" << xmiValue;
- } else {
- m_AttributeMap[key] = static_cast<UMLEntityAttribute*>(valueObj);
- }
- }
-
- } else {
- uWarning() << "unknown child type in UMLForeignKeyConstraint::load";
- }
-
- node = node.nextSibling();
- }
-
- return true;
-}
-
-/**
- * Set the Referenced Entity.
- * @param ent The Entity to Reference
- */
-void UMLForeignKeyConstraint::setReferencedEntity(UMLEntity* ent)
-{
- if (ent == m_ReferencedEntity)
- return;
-
- m_ReferencedEntity = ent;
-
- emit sigReferencedEntityChanged();
-}
-
-/**
- * Get the Referenced Entity.
- * @return the UML entity object
- */
-UMLEntity* UMLForeignKeyConstraint::getReferencedEntity() const
-{
- return m_ReferencedEntity;
-}
-
-/**
- * Slot for referenced entity changed.
- */
-void UMLForeignKeyConstraint::slotReferencedEntityChanged()
-{
- // clear all mappings
- m_AttributeMap.clear();
-}
-
-/**
- * Clears all mappings between local and referenced attributes
- */
-void UMLForeignKeyConstraint::clearMappings()
-{
- m_AttributeMap.clear();
-}
-
-/**
- * Remimplementation from base classes
- * Used to resolve forward references to referenced entities in xmi
- */
-bool UMLForeignKeyConstraint::resolveRef()
-{
- // resolve referenced entity first
- UMLDoc* doc = UMLApp::app()->document();
-
- bool success = true;
-
- //resolve the referenced entity
- if (!Uml::ID::toString(m_pReferencedEntityID).isEmpty()) {
- UMLObject* obj = doc->findObjectById(m_pReferencedEntityID);
- m_ReferencedEntity = static_cast<UMLEntity*>(obj);
- if (m_ReferencedEntity == NULL) {
- success = false;
- }
- }
-
- QMap<UMLEntityAttribute*, Uml::ID::Type>::iterator i;
- for (i = m_pEntityAttributeIDMap.begin(); i!= m_pEntityAttributeIDMap.end() ; ++i) {
- if (!Uml::ID::toString(i.value()).isEmpty()) {
- UMLObject* obj = doc->findObjectById(i.value());
- m_AttributeMap[i.key()] = static_cast<UMLEntityAttribute*>(obj);
- if (m_AttributeMap[i.key()] == NULL) {
- success = false;
- }
- }
- }
-
- return success;
-}
-
-/**
- * Retrieve all Pairs of Attributes.
- */
-QMap<UMLEntityAttribute*, UMLEntityAttribute*> UMLForeignKeyConstraint::getEntityAttributePairs()
-{
- return m_AttributeMap;
-}
-
-/**
- * Get the Delete Action.
- */
-UMLForeignKeyConstraint::UpdateDeleteAction UMLForeignKeyConstraint::getDeleteAction() const
-{
- return m_DeleteAction;
-}
-
-/**
- * Get the Update Action.
- */
-UMLForeignKeyConstraint::UpdateDeleteAction UMLForeignKeyConstraint::getUpdateAction() const
-{
- return m_UpdateAction;
-}
-
-/**
- * Set the Delete Action to the specified UpdateDeleteAction.
- */
-void UMLForeignKeyConstraint::setDeleteAction(UpdateDeleteAction uda)
-{
- m_DeleteAction = uda;
-}
-
-/**
- * Set the Update Action to the specified UpdateDeleteAction
- */
-void UMLForeignKeyConstraint::setUpdateAction(UpdateDeleteAction uda)
-{
- m_UpdateAction = uda;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/foreignkeyconstraint.h umbrello-kf6-15.08.1/umbrello/foreignkeyconstraint.h
--- umbrello-kf6-15.08.1.orig/umbrello/foreignkeyconstraint.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/foreignkeyconstraint.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,120 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef FOREIGNKEYCONSTRAINT_H
-#define FOREIGNKEYCONSTRAINT_H
-
-// appl includes
-#include "basictypes.h"
-#include "entityconstraint.h"
-
-// qt includes
-#include <QMap>
-
-//forward declarations
-class UMLEntityAttribute;
-class UMLEntity;
-
-/**
- * This class is used to set up information for a foreign key entity constraint.
- * @short Sets up Foreign Key entity constraint information.
- * @author Sharan Rao
- * @see UMLObject UMLClassifierListItem UMLEntityConstraint
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLForeignKeyConstraint : public UMLEntityConstraint
-{
- Q_OBJECT
-
-public:
-
- /**
- * Update/Delete Action: Action to be taken on Update or Delete of a referenced attribute
- * is either, No Action, Restrict, Cascade, Set NULL, Set Default.
- */
- enum UpdateDeleteAction { uda_NoAction = 0,
- uda_Restrict,
- uda_Cascade,
- uda_SetNull,
- uda_SetDefault };
-
- UMLForeignKeyConstraint(UMLObject *parent, const QString& name,
- Uml::ID::Type id = Uml::ID::None);
- explicit UMLForeignKeyConstraint(UMLObject *parent);
-
- bool operator==(const UMLForeignKeyConstraint &rhs) const;
-
- virtual ~UMLForeignKeyConstraint();
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
-
- void setReferencedEntity(UMLEntity* ent);
- UMLEntity* getReferencedEntity() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- virtual bool showPropertiesDialog(QWidget* parent = 0);
-
- bool addEntityAttributePair(UMLEntityAttribute* pAttr, UMLEntityAttribute* rAttr);
-
- bool removeEntityAttributePair(UMLEntityAttribute* /*key*/ pAttr);
-
- bool hasEntityAttributePair(UMLEntityAttribute* pAttr, UMLEntityAttribute* rAttr) const;
-
- QMap<UMLEntityAttribute*, UMLEntityAttribute*> getEntityAttributePairs();
-
- void setDeleteAction(UpdateDeleteAction uda);
- UpdateDeleteAction getDeleteAction() const;
-
- void setUpdateAction(UpdateDeleteAction uda);
- UpdateDeleteAction getUpdateAction() const;
-
- void clearMappings();
-
- bool resolveRef();
-
-signals:
- void sigReferencedEntityChanged();
-
-private slots:
- void slotReferencedEntityChanged();
-
-protected:
- bool load(QDomElement & element);
-
-private:
-
- Uml::ID::Type m_pReferencedEntityID; ///< Used to resolve forward references to UMLEntity.
-
- /**
- * Used to resolve forward references to UMLEntityAttributes
- * Key -> The local attribute
- * Value -> Id of the attribute it is mapping to
- */
- QMap<UMLEntityAttribute*, Uml::ID::Type> m_pEntityAttributeIDMap;
-
- void init();
-
- UMLEntity* m_ReferencedEntity; ///< The UMLEntity that this foreign key references.
-
- /**
- * Stores the Mapping of attributes between parent table and referenced table
- */
- QMap<UMLEntityAttribute*, UMLEntityAttribute*> m_AttributeMap;
-
- UpdateDeleteAction m_UpdateAction; ///< What to do on Update of referenced attributes.
- UpdateDeleteAction m_DeleteAction; ///< What to do on Deletion of referenced attributes.
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/listpopupmenu.cpp umbrello-kf6-15.08.1/umbrello/listpopupmenu.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/listpopupmenu.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/listpopupmenu.cpp 2015-10-08 11:48:59.500089026 +0300
@@ -1195,7 +1195,6 @@
void ListPopupMenu::makeClassifierShowPopup(ClassifierWidget *c)
{
WidgetBase::WidgetType type = c->baseType();
- ClassifierWidget *cls = NULL;
#if QT_VERSION >= 0x050000
QMenu* show = new QMenu(i18n("Show"), this);
@@ -1208,9 +1207,8 @@
setActionChecked(mt_Show_Documentation, c->visualProperty(ClassifierWidget::ShowDocumentation));
#endif
if (type == WidgetBase::wt_Class) {
- cls = static_cast<ClassifierWidget*>(c);
insert(mt_Show_Attributes, show, i18n("Attributes"), CHECKABLE);
- setActionChecked(mt_Show_Attributes, cls->visualProperty(ClassifierWidget::ShowAttributes));
+ setActionChecked(mt_Show_Attributes, c->visualProperty(ClassifierWidget::ShowAttributes));
}
insert(mt_Show_Operations, show, i18n("Operations"), CHECKABLE);
setActionChecked(mt_Show_Operations, c->visualProperty(ClassifierWidget::ShowOperations));
@@ -1224,16 +1222,14 @@
setActionChecked(mt_Show_Operation_Signature, sig);
if (type == WidgetBase::wt_Class) {
insert(mt_Show_Attribute_Signature, show, i18n("Attribute Signature"), CHECKABLE);
- sig = (cls->attributeSignature() == Uml::SignatureType::SigNoVis ||
- cls->attributeSignature() == Uml::SignatureType::ShowSig);
+ sig = (c->attributeSignature() == Uml::SignatureType::SigNoVis ||
+ c->attributeSignature() == Uml::SignatureType::ShowSig);
setActionChecked(mt_Show_Attribute_Signature, sig);
}
insert(mt_Show_Packages, show, i18n("Package"), CHECKABLE);
setActionChecked(mt_Show_Packages, c->visualProperty(ClassifierWidget::ShowPackage));
- if (type == WidgetBase::wt_Class) {
- insert(mt_Show_Stereotypes, show, i18n("Stereotype"), CHECKABLE);
- setActionChecked(mt_Show_Stereotypes, cls->visualProperty(ClassifierWidget::ShowStereotype));
- }
+ insert(mt_Show_Stereotypes, show, i18n("Stereotype"), CHECKABLE);
+ setActionChecked(mt_Show_Stereotypes, c->visualProperty(ClassifierWidget::ShowStereotype));
addMenu(show);
}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/node.cpp umbrello-kf6-15.08.1/umbrello/node.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/node.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/node.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,68 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "node.h"
-
-#include <KLocalizedString>
-
-/**
- * Sets up a Node.
- *
- * @param name The name of the Concept.
- * @param id The unique id of the Concept.
- */
-UMLNode::UMLNode(const QString & name, Uml::ID::Type id)
- : UMLCanvasObject(name, id)
-{
- init();
-}
-
-/**
- * Destructor.
- */
-UMLNode::~UMLNode()
-{
-}
-
-/**
- * Initializes key variables of the class.
- */
-void UMLNode::init()
-{
- m_BaseType = UMLObject::ot_Node;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLNode::clone() const
-{
- UMLNode *clone = new UMLNode();
- UMLObject::copyInto(clone);
- return clone;
-}
-
-/**
- * Creates the <UML:Node> XMI element.
- */
-void UMLNode::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement nodeElement = UMLObject::save(QLatin1String("UML:Node"), qDoc);
- qElement.appendChild(nodeElement);
-}
-
-/**
- * Loads the <UML:Node> XMI element (empty.)
- */
-bool UMLNode::load(QDomElement&)
-{
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/node.h umbrello-kf6-15.08.1/umbrello/node.h
--- umbrello-kf6-15.08.1.orig/umbrello/node.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/node.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,46 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef NODE_H
-#define NODE_H
-
-#include "umlcanvasobject.h"
-
-/**
- * This class contains the non-graphical information required for a UML Node.
- * This class inherits from @ref UMLCanvasObject which contains most of the
- * information.
- *
- * @short Non-graphical information for a Node.
- * @author Jonathan Riddell
- * @see UMLCanvasObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLNode : public UMLCanvasObject
-{
- Q_OBJECT
-public:
-
- explicit UMLNode(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLNode();
-
- virtual void init();
-
- virtual UMLObject* clone() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
-protected:
-
- bool load(QDomElement & element);
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/operation.cpp umbrello-kf6-15.08.1/umbrello/operation.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/operation.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/operation.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,611 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "operation.h"
-
-// app includes
-#include "attribute.h"
-#include "classifier.h"
-#include "model_utils.h"
-#include "debug_utils.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "uniqueid.h"
-#include "umloperationdialog.h"
-#include "codegenerator.h"
-#include "codedocument.h"
-#include "codeblock.h"
-
-// kde includes
-#include <KLocalizedString>
-
-// qt includes
-#include <QRegExp>
-
-/**
- * Constructs an UMLOperation.
- * Not intended for general use: The operation is not tied in with
- * umbrello-kf6's Qt signalling for object creation.
- * If you want to create an Operation use the method in UMLDoc instead.
- *
- * @param parent the parent to this operation
- * @param name the name of the operation
- * @param id the id of the operation
- * @param s the visibility of the operation
- * @param rt the return type of the operation
- */
-UMLOperation::UMLOperation(UMLClassifier *parent, const QString& name,
- Uml::ID::Type id, Uml::Visibility::Enum s, UMLObject *rt)
- : UMLClassifierListItem(parent, name, id)
-{
- if (rt)
- m_returnId = UniqueID::gen();
- else
- m_returnId = Uml::ID::None;
- m_pSecondary = rt;
- m_visibility = s;
- m_BaseType = UMLObject::ot_Operation;
- m_bConst = false;
- m_Code.clear();
-}
-
-/**
- * Constructs an UMLOperation.
- * Not intended for general use: The operation is not tied in with
- * umbrello-kf6's Qt signalling for object creation.
- * If you want to create an Operation use the method in UMLDoc instead.
- *
- * @param parent the parent to this operation
- */
-UMLOperation::UMLOperation(UMLClassifier * parent)
- : UMLClassifierListItem (parent)
-{
- m_BaseType = UMLObject::ot_Operation;
- m_bConst = false;
- m_Code.clear();
-}
-
-/**
- * Destructor.
- */
-UMLOperation::~UMLOperation()
-{
-}
-
-/**
- * Reimplement method from UMLClassifierListItem.
- *
- * @param type pointer to the type object
- */
-void UMLOperation::setType(UMLObject* type)
-{
- UMLClassifierListItem::setType(type);
- if (m_returnId == Uml::ID::None)
- m_returnId = UniqueID::gen();
-}
-
-/**
- * Move a parameter one position to the left.
- *
- * @param a the parameter to move
- */
-void UMLOperation::moveParmLeft(UMLAttribute * a)
-{
- if (a == NULL) {
- uDebug() << "called on NULL attribute";
- return;
- }
- uDebug() << "called for " << a->name();
- disconnect(a, SIGNAL(modified()), this, SIGNAL(modified()));
- int idx;
- if ((idx=m_List.indexOf(a)) == -1) {
- uDebug() << "Error move parm left " << a->name();
- return;
- }
- if (idx == 0)
- return;
- m_List.removeAll(a);
- m_List.insert(idx-1, a);
-}
-
-/**
- * Move a parameter one position to the right.
- *
- * @param a the parameter to move
- */
-void UMLOperation::moveParmRight(UMLAttribute * a)
-{
- if (a == NULL) {
- uDebug() << "called on NULL attribute";
- return;
- }
- uDebug() << "called for " << a->name();
- disconnect(a, SIGNAL(modified()), this, SIGNAL(modified()));
- int idx;
- if ((idx=m_List.indexOf(a)) == -1) {
- uDebug() << "Error move parm right " << a->name();
- return;
- }
- int count = m_List.count();
- if (idx == count-1)
- return;
- m_List.removeAll(a);
- m_List.insert(idx+1, a);
-}
-
-/**
- * Remove a parameter from the operation.
- *
- * @param a the parameter to remove
- * @param emitModifiedSignal whether to emit the "modified" signal
- * which creates an entry in the Undo stack for the
- * removal, default: true
- */
-void UMLOperation::removeParm(UMLAttribute * a, bool emitModifiedSignal /* =true */)
-{
- if (a == NULL) {
- uDebug() << "called on NULL attribute";
- return;
- }
- uDebug() << "called for " << a->name();
- disconnect(a, SIGNAL(modified()), this, SIGNAL(modified()));
- if(!m_List.removeAll(a))
- uDebug() << "Error removing parm " << a->name();
-
- if (emitModifiedSignal)
- emit modified();
-}
-
-/**
- * Returns a list of parameters.
- *
- * @return a list of the parameters in the operation
- */
-UMLAttributeList UMLOperation::getParmList() const
-{
- return m_List;
-}
-
-/**
- * Finds a parameter of the operation.
- *
- * @param name the parameter name to search for
- * @return the found parameter, 0 if not found
- */
-UMLAttribute* UMLOperation::findParm(const QString &name)
-{
- UMLAttribute * obj=0;
- foreach (obj, m_List) {
- if (obj->name() == name)
- return obj;
- }
- return 0;
-}
-
-/**
- * Returns a string representation of the operation.
- *
- * @param sig what type of operation string to show
- * @return the string representation of the operation
- */
-QString UMLOperation::toString(Uml::SignatureType::Enum sig)
-{
- QString s;
-
- if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::NoSig)
- s = Uml::Visibility::toString(m_visibility, true) + QLatin1Char(' ');
-
- s += name();
- Uml::ProgrammingLanguage::Enum pl = UMLApp::app()->activeLanguage();
- bool parameterlessOpNeedsParentheses =
- (pl != Uml::ProgrammingLanguage::Pascal && pl != Uml::ProgrammingLanguage::Ada);
-
- if (sig == Uml::SignatureType::NoSig || sig == Uml::SignatureType::NoSigNoVis) {
- if (parameterlessOpNeedsParentheses)
- s.append(QLatin1String("()"));
- return s;
- }
- int last = m_List.count();
- if (last) {
- s.append(QLatin1String("("));
- int i = 0;
- foreach (UMLAttribute *param, m_List) {
- i++;
- s.append(param->toString(Uml::SignatureType::SigNoVis));
- if (i < last)
- s.append(QLatin1String(", "));
- }
- s.append(QLatin1String(")"));
- } else if (parameterlessOpNeedsParentheses) {
- s.append(QLatin1String("()"));
- }
- UMLClassifier *ownParent = static_cast<UMLClassifier*>(parent());
- QString returnType;
- UMLClassifier *retType = UMLClassifierListItem::getType();
- if (retType) {
- UMLPackage *retVisibility = retType->umlPackage();
- if (retVisibility != ownParent && retVisibility != ownParent->umlPackage())
- returnType = retType->fullyQualifiedName();
- else
- returnType = retType->name();
- }
- if (returnType.length() > 0 && returnType != QLatin1String("void")) {
- s.append(QLatin1String(" : "));
-
- if (returnType.startsWith(QLatin1String(QLatin1String("virtual ")))) {
- s += returnType.mid(8);
- } else {
- s += returnType;
- }
- }
- return s;
-}
-
-/**
- * Add a parameter to the operation.
- *
- * @param parameter the parameter to add
- * @param position the position in the parameter list.
- * If position = -1 the parameter will be
- * appended to the list.
- */
-void UMLOperation::addParm(UMLAttribute *parameter, int position)
-{
- if(position >= 0 && position <= (int)m_List.count())
- m_List.insert(position, parameter);
- else
- m_List.append(parameter);
- UMLObject::emitModified();
- connect(parameter, SIGNAL(modified()), this, SIGNAL(modified()));
-}
-
-/**
- * Returns an unused parameter name for a new parameter.
- */
-QString UMLOperation::getUniqueParameterName()
-{
- QString currentName = i18n("new_parameter");
- QString name = currentName;
- for (int number = 1; findParm(name); ++number) {
- name = currentName + QLatin1Char('_') + QString::number(number);
- }
- return name;
-}
-
-/**
- * Overloaded '==' operator.
- */
-bool UMLOperation::operator==(const UMLOperation & rhs) const
-{
- if (this == &rhs)
- return true;
-
- if (!UMLObject::operator==(rhs))
- return false;
-
- if (getTypeName() != rhs.getTypeName())
- return false;
-
- if (m_List.count() != rhs.m_List.count())
- return false;
-
- if (!(m_List == rhs.m_List))
- return false;
-
- return true;
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLOperation::copyInto(UMLObject *lhs) const
-{
- UMLOperation *target = static_cast<UMLOperation*>(lhs);
-
- UMLClassifierListItem::copyInto(target);
-
- m_List.copyInto(&(target->m_List));
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLOperation::clone() const
-{
- //FIXME: The new operation should be slaved to the NEW parent not the old.
- UMLOperation *clone = new UMLOperation(static_cast<UMLClassifier*>(parent()));
- copyInto(clone);
-
- return clone;
-}
-
-/**
- * Calls resolveRef() on all parameters.
- * Needs to be called after all UML objects are loaded from file.
- *
- * @return true for success
- */
-bool UMLOperation::resolveRef()
-{
- bool overallSuccess = UMLObject::resolveRef();
- // See remark on iteration style in UMLClassifier::resolveRef()
- foreach (UMLAttribute* pAtt, m_List) {
- if (! pAtt->resolveRef())
- overallSuccess = false;
- }
- return overallSuccess;
-}
-
-/**
- * Returns whether this operation is a constructor.
- *
- * @return true if this operation is a constructor
- */
-bool UMLOperation::isConstructorOperation()
-{
- // if an operation has the stereotype constructor
- // return true
- if (stereotype() == QLatin1String("constructor"))
- return true;
-
- UMLClassifier * c = static_cast<UMLClassifier*>(this->parent());
- QString cName = c->name();
- QString opName = name();
- // It's a constructor operation if the operation name
- // matches that of the parent classifier.
- return (cName == opName);
-}
-
-/**
- * Returns whether this operation is a destructor.
- *
- * @return true if this operation is a destructor
- */
-bool UMLOperation::isDestructorOperation()
-{
- if (stereotype() == QLatin1String("destructor"))
- return true;
- UMLClassifier * c = static_cast<UMLClassifier*>(this->parent());
-
- QString cName = c->name();
- QString opName = name();
- // Special support for C++ syntax:
- // It's a destructor operation if the operation name begins
- // with "~" followed by the name of the parent classifier.
- if (! opName.startsWith(QLatin1Char('~')))
- return false;
- opName.remove(QRegExp(QLatin1String("^~\\s*")));
- return (cName == opName);
-}
-
-/**
- * Shortcut for (isConstructorOperation() || isDestructorOperation()).
- *
- * @return true if this operation is a constructor or destructor
- */
-bool UMLOperation::isLifeOperation()
-{
- return (isConstructorOperation() || isDestructorOperation());
-}
-
-/**
- * Sets whether this operation is a query (C++ "const").
- */
-void UMLOperation::setConst(bool b)
-{
- m_bConst = b;
-}
-
-/**
- * Returns whether this operation is a query (C++ "const").
- */
-bool UMLOperation::getConst() const
-{
- return m_bConst;
-}
-
-/**
- * Display the properties configuration dialog for the template.
- *
- * @param parent the parent for the dialog
- */
-bool UMLOperation::showPropertiesDialog(QWidget* parent)
-{
- UMLOperationDialog dialog(parent, this);
- return dialog.exec();
-}
-
-/**
- * Sets the source code for this operation.
- *
- * @param code the body of this operation
- */
-void UMLOperation::setSourceCode(const QString& code)
-{
- m_Code = code;
-}
-
-/**
- * Returns the source code for this operation.
- */
-QString UMLOperation::getSourceCode() const
-{
- return m_Code;
-}
-
-/**
- * Saves to the <UML:Operation> XMI element.
- */
-void UMLOperation::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement operationElement = UMLObject::save(QLatin1String("UML:Operation"), qDoc);
- operationElement.setAttribute(QLatin1String("isQuery"), m_bConst ? QLatin1String("true") : QLatin1String("false"));
- QDomElement featureElement = qDoc.createElement(QLatin1String("UML:BehavioralFeature.parameter"));
- if (m_pSecondary) {
- QDomElement retElement = qDoc.createElement(QLatin1String("UML:Parameter"));
- if (m_returnId == Uml::ID::None) {
- uDebug() << name() << ": m_returnId is not set, setting it now.";
- m_returnId = UniqueID::gen();
- }
- retElement.setAttribute(QLatin1String("xmi.id"), Uml::ID::toString(m_returnId));
- retElement.setAttribute(QLatin1String("type"), Uml::ID::toString(m_pSecondary->id()));
- retElement.setAttribute(QLatin1String("kind"), QLatin1String("return"));
- featureElement.appendChild(retElement);
- } else {
- uDebug() << "m_SecondaryId is " << m_SecondaryId;
- }
-
- //save each attribute here, type different
- foreach(UMLAttribute* pAtt, m_List) {
- QDomElement attElement = pAtt->UMLObject::save(QLatin1String("UML:Parameter"), qDoc);
- UMLClassifier *attrType = pAtt->getType();
- if (attrType) {
- attElement.setAttribute(QLatin1String("type"), Uml::ID::toString(attrType->id()));
- } else {
- attElement.setAttribute(QLatin1String("type"), pAtt->getTypeName());
- }
- attElement.setAttribute(QLatin1String("value"), pAtt->getInitialValue());
-
- Uml::ParameterDirection::Enum kind = pAtt->getParmKind();
- if (kind == Uml::ParameterDirection::Out)
- attElement.setAttribute(QLatin1String("kind"), QLatin1String("out"));
- else if (kind == Uml::ParameterDirection::InOut)
- attElement.setAttribute(QLatin1String("kind"), QLatin1String("inout"));
- // The default for the parameter kind is "in".
-
- featureElement.appendChild(attElement);
- }
- if (featureElement.hasChildNodes()) {
- operationElement.appendChild(featureElement);
- }
- qElement.appendChild(operationElement);
-}
-
-/**
- * Loads a <UML:Operation> XMI element.
- */
-bool UMLOperation::load(QDomElement & element)
-{
- m_SecondaryId = element.attribute(QLatin1String("type"));
- QString isQuery = element.attribute(QLatin1String("isQuery"));
- if (!isQuery.isEmpty()) {
- // We need this extra test for isEmpty() because load() might have been
- // called again by the processing for BehavioralFeature.parameter (see below)
- m_bConst = (isQuery == QLatin1String("true"));
- }
- QDomNode node = element.firstChild();
- if (node.isComment())
- node = node.nextSibling();
- QDomElement attElement = node.toElement();
- while (!attElement.isNull()) {
- QString tag = attElement.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("BehavioralFeature.parameter")) ||
- UMLDoc::tagEq(tag, QLatin1String("Element.ownedElement"))) { // Embarcadero's Describe
- if (! load(attElement))
- return false;
- } else if (UMLDoc::tagEq(tag, QLatin1String("Parameter"))) {
- QString kind = attElement.attribute(QLatin1String("kind"));
- if (kind.isEmpty()) {
- kind = attElement.attribute(QLatin1String("direction")); // Embarcadero's Describe
- if (kind.isEmpty()) {
- // Perhaps the kind is stored in a child node:
- for (QDomNode n = attElement.firstChild(); !n.isNull(); n = n.nextSibling()) {
- if (n.isComment())
- continue;
- QDomElement tempElement = n.toElement();
- QString tag = tempElement.tagName();
- if (!UMLDoc::tagEq(tag, QLatin1String("kind")))
- continue;
- kind = tempElement.attribute(QLatin1String("xmi.value"));
- break;
- }
- }
- if (kind.isEmpty()) {
- kind = QLatin1String("in");
- }
- }
- if (kind == QLatin1String("return") ||
- kind == QLatin1String("result")) { // Embarcadero's Describe
- QString returnId = Model_Utils::getXmiId(attElement);
- if (!returnId.isEmpty())
- m_returnId = Uml::ID::fromString(returnId);
- m_SecondaryId = attElement.attribute(QLatin1String("type"));
- if (m_SecondaryId.isEmpty()) {
- // Perhaps the type is stored in a child node:
- QDomNode node = attElement.firstChild();
- while (!node.isNull()) {
- if (node.isComment()) {
- node = node.nextSibling();
- continue;
- }
- QDomElement tempElement = node.toElement();
- QString tag = tempElement.tagName();
- if (!UMLDoc::tagEq(tag, QLatin1String("type"))) {
- node = node.nextSibling();
- continue;
- }
- m_SecondaryId = Model_Utils::getXmiId(tempElement);
- if (m_SecondaryId.isEmpty())
- m_SecondaryId = tempElement.attribute(QLatin1String("xmi.idref"));
- if (m_SecondaryId.isEmpty()) {
- QDomNode inner = node.firstChild();
- QDomElement tmpElem = inner.toElement();
- m_SecondaryId = Model_Utils::getXmiId(tmpElem);
- if (m_SecondaryId.isEmpty())
- m_SecondaryId = tmpElem.attribute(QLatin1String("xmi.idref"));
- }
- break;
- }
- if (m_SecondaryId.isEmpty()) {
- uError() << name() << ": cannot find return type.";
- }
- }
- // Use deferred xmi.id resolution.
- m_pSecondary = NULL;
- } else {
- UMLAttribute * pAtt = new UMLAttribute(this);
- if(!pAtt->loadFromXMI(attElement)) {
- delete pAtt;
- return false;
- }
- if (kind == QLatin1String("out"))
- pAtt->setParmKind(Uml::ParameterDirection::Out);
- else if (kind == QLatin1String("inout"))
- pAtt->setParmKind(Uml::ParameterDirection::InOut);
- else
- pAtt->setParmKind(Uml::ParameterDirection::In);
- m_List.append(pAtt);
- }
- }
- node = node.nextSibling();
- if (node.isComment())
- node = node.nextSibling();
- attElement = node.toElement();
-
- // loading the source code which was entered in the 'classpropdlg' dialog is not done
- // with the following code, because there is no CodeDocument.
- /*
- CodeGenerator* codegen = UMLApp::app()->getGenerator();
- if (codegen) {
- uDebug() << "CodeDocument searching with id=" << Uml::ID::toString(UMLObject::ID());
- CodeDocument* codeDoc = codegen->findCodeDocumentByID(Uml::ID::toString(UMLObject::ID()));
- if (codeDoc) {
- uDebug() << "CodeDocument found:\n" << codeDoc;
- }
- }
- */
- // it is done in the code generators by calling CodeGenerator::loadFromXMI(...).
-
- }//end while
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/operation.h umbrello-kf6-15.08.1/umbrello/operation.h
--- umbrello-kf6-15.08.1.orig/umbrello/operation.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/operation.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,84 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef OPERATION_H
-#define OPERATION_H
-
-#include "umlattributelist.h"
-#include "classifierlistitem.h"
-
-class UMLClassifier;
-
-/**
- * This class represents an operation in the UML model.
- *
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLOperation : public UMLClassifierListItem
-{
- Q_OBJECT
-public:
- UMLOperation(UMLClassifier * parent, const QString& name,
- Uml::ID::Type id = Uml::ID::None,
- Uml::Visibility::Enum s = Uml::Visibility::Public,
- UMLObject *rt = 0);
- explicit UMLOperation(UMLClassifier * parent);
- virtual ~UMLOperation();
-
- bool operator==(const UMLOperation & rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- void setType(UMLObject* type);
-
- void moveParmLeft(UMLAttribute *a);
- void moveParmRight(UMLAttribute *a);
-
- void removeParm(UMLAttribute *a, bool emitModifiedSignal = true);
-
- UMLAttributeList getParmList() const;
-
- UMLAttribute * findParm(const QString &name);
-
- QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
-
- void addParm(UMLAttribute *parameter, int position = -1);
-
- bool resolveRef();
-
- QString getUniqueParameterName();
-
- virtual bool showPropertiesDialog(QWidget* parent = 0);
-
- bool isConstructorOperation();
- bool isDestructorOperation();
- bool isLifeOperation();
-
- void setConst(bool b);
- bool getConst() const;
-
- void setSourceCode(const QString& code);
- QString getSourceCode() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
-protected:
- bool load(QDomElement & element);
-
-private:
- Uml::ID::Type m_returnId; ///< Holds the xmi.id of the <UML:Parameter kind="return">
- UMLAttributeList m_List; ///< Parameter list
- bool m_bConst; ///< Holds the isQuery attribute of the <UML:Operation>
- QString m_Code; ///< Holds the entered source code
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/org.kde.umbrello-kf6.appdata.xml umbrello-kf6-15.08.1/umbrello/org.kde.umbrello-kf6.appdata.xml
--- umbrello-kf6-15.08.1.orig/umbrello/org.kde.umbrello-kf6.appdata.xml 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/org.kde.umbrello-kf6.appdata.xml 2015-10-08 11:48:59.501089026 +0300
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<component type="desktop">
+ <id>org.kde.umbrello-kf6.desktop</id>
+ <metadata_license>CC0-1.0</metadata_license>
+ <project_license>GPL-2.0+</project_license>
+ <name>umbrello-kf6</name>
+ <name xml:lang="ca">umbrello-kf6</name>
+ <name xml:lang="cs">umbrello-kf6</name>
+ <name xml:lang="de">umbrello-kf6</name>
+ <name xml:lang="en-GB">umbrello-kf6</name>
+ <name xml:lang="es">umbrello-kf6</name>
+ <name xml:lang="et">umbrello-kf6</name>
+ <name xml:lang="fi">umbrello-kf6</name>
+ <name xml:lang="gl">umbrello-kf6</name>
+ <name xml:lang="it">umbrello-kf6</name>
+ <name xml:lang="nl">umbrello-kf6</name>
+ <name xml:lang="pl">umbrello-kf6</name>
+ <name xml:lang="pt">umbrello-kf6</name>
+ <name xml:lang="pt-BR">umbrello-kf6</name>
+ <name xml:lang="sk">umbrello-kf6</name>
+ <name xml:lang="sl">umbrello-kf6</name>
+ <name xml:lang="sv">umbrello-kf6</name>
+ <name xml:lang="uk">umbrello-kf6</name>
+ <name xml:lang="x-test">xxumbrello-kf6xx</name>
+ <summary>UML Modeller</summary>
+ <summary xml:lang="ca">Modelador UML</summary>
+ <summary xml:lang="cs">UML modelář</summary>
+ <summary xml:lang="de">UML-Modeller</summary>
+ <summary xml:lang="en-GB">UML Modeller</summary>
+ <summary xml:lang="es">Modelador UML</summary>
+ <summary xml:lang="et">UML-i modelleerimise rakendus</summary>
+ <summary xml:lang="fi">UML-mallinnusohjelma</summary>
+ <summary xml:lang="gl">Modelador de UML</summary>
+ <summary xml:lang="it">Modellatore UML</summary>
+ <summary xml:lang="nl">UML-modeller</summary>
+ <summary xml:lang="pl">Program do modelowania UML</summary>
+ <summary xml:lang="pt">Modelador de UML</summary>
+ <summary xml:lang="pt-BR">Modelador de UML</summary>
+ <summary xml:lang="sk">Modelár UML</summary>
+ <summary xml:lang="sl">Modelirnik UML</summary>
+ <summary xml:lang="sv">UML-modellering</summary>
+ <summary xml:lang="uk">Засіб моделювання UML</summary>
+ <summary xml:lang="x-test">xxUML Modellerxx</summary>
+ <description>
+ <p>
+ umbrello-kf6 is a Unified Modelling Language (UML) modelling tool and code generator.
+ It can create diagrams of software and other systems in the industry-standard UML format, and can also generate code from UML diagrams
+ in a variety of programming languages.
+ </p>
+ <p xml:lang="ca">L'umbrello-kf6 és una eina de modelatge de Llenguatge Unificat de Modelatge (UML) i generador de codi. Pot crear diagrames de programari i altres sistemes en el format UML estàndard de la indústria, i també pot generar codi des de diagrames UML en diversos llenguatges de programació.</p>
+ <p xml:lang="en-GB">umbrello-kf6 is a Unified Modelling Language (UML) modelling tool and code generator. It can create diagrams of software and other systems in the industry-standard UML format, and can also generate code from UML diagrams in a variety of programming languages.</p>
+ <p xml:lang="es">umbrello-kf6 es una herramienta de modelado y de generación de código para el lenguaje unificado de modelado (UML). Puede crear diagramas de software y de otros sistemas en el formato estándar de la industria UML, además de generar código a partir de diagramas UML en diversos lenguajes de programación.</p>
+ <p xml:lang="et">umbrello-kf6 on unifitseeritud modelleerimiskeele UML modelleerimistööriist ja koodi genereerija. See võib luua tarkvara ja muude süsteemide skeeme standardses UML-vormingus, samuti genereerida UML-skeemide põhjal koodi mitmes programmeerimiskeeles.</p>
+ <p xml:lang="fi">umbrello-kf6 on UML-mallinnusohjelma. umbrello-kf6lla voi luoda kaavioita ohjelmistoista ja muista järjestelmistä käyttäen standardia UML-muotoa. Sillä voi myös luoda koodin UML-kaavioiden perusteella useille ohjelmointikielille.</p>
+ <p xml:lang="gl">umbrello-kf6 é unha ferramenta de modelaxe e xerador de código baseado na linguaxe de modelaxe UML. Pode crear diagramas de software e doutros sistemas usando o formato estándar da industria, UML, e pode tamén xerar código a partir de diagramas UML en varios linguaxes de programación.</p>
+ <p xml:lang="it">umbrello-kf6 è uno strumento per diagrammi UML e un generatore di codice. Può creare diagrammi di software e altri sistemi nello standard industriale UML, e può anche generare codice partendo dai diagrammi UML in diversi linguaggi di programmazione.</p>
+ <p xml:lang="nl">umbrello-kf6 is een Unified Modelling Language (UML) hulpmiddel voor modellering en generator van code. Het kan diagrammen van software en andere systemen maken in het industrie-standaard UML-formaat en kan ook code genereren uit UML diagrammen in een verscheidenheid van programmeertalen.</p>
+ <p xml:lang="pl">umbrello-kf6 jest Unified Modelling Language (UML) (z ang. Językiem do Jednolitego Modelowania) i generatorem kodu. Może tworzyć diagramy oprogramowania i innych systemów w formacie standardu przemysłowego UML, a także generować kod z diagramów UML w wielu językach programowania.</p>
+ <p xml:lang="pt">O umbrello-kf6 é uma ferramenta de modelação em UML (Unified Modelling Language) e gerador de código. Poderá criar diagramas de aplicações e outros sistemas, usando o formato-padrão da indústria UML, podendo também gerar código a partir de diagramas UML, numa grande variedade de linguagens de programação.</p>
+ <p xml:lang="pt-BR">umbrello-kf6 é uma ferramenta de modelação de UML (Unified Modelling Language) e gerador de código. Ele pode criar diagramas de softwares e outros sistemas, usando o formato de UML padrão da indústria, assim como gerar código a partir de diagramas UML, em uma grande variedade de linguagens de programação.</p>
+ <p xml:lang="sk">umbrello-kf6 je nástroj na modelovania v UML a generátor kódu. Dokáže vytvárať diagramy softvéru a iných systémov v priemyselnom štandarde UML a tiež generovať kód z UML diagramov v množstve programovacích jazykov.</p>
+ <p xml:lang="sl">umbrello-kf6 je orodje za modeliranje v poenotenem jeziku za modeliranje (UML) in ustvarjalnik kode. Ustvari lahko diagrame programov in drugih sistemov v industrijski standardizirani obliki UML, iz diagramov UML pa lahko ustvari tudi kodo v različnih programskih jezikih.</p>
+ <p xml:lang="sv">umbrello-kf6 är ett modelleringsverktyg för Unified Modelling Language och kodgenerator. Det kan skapa diagram av programvara och andra system med industristandardformatet UML, och kan också skapa kod från UML-diagram på ett antal olika programspråk.</p>
+ <p xml:lang="uk">umbrello-kf6 — засіб моделювання уніфікованою мовою моделювання (UML) та інструмент для створення шаблонів коду. Програма здатна створювати діаграми систем програмного забезпечення та інших систем у стандартному форматі UML та реалізовувати діаграми UML у програмному коді багатьма мовами програмування.</p>
+ <p xml:lang="x-test">xxumbrello-kf6 is a Unified Modelling Language (UML) modelling tool and code generator. It can create diagrams of software and other systems in the industry-standard UML format, and can also generate code from UML diagrams in a variety of programming languages.xx</p>
+ <p>Features:</p>
+ <p xml:lang="ca">Característiques:</p>
+ <p xml:lang="cs">Vlastnosti:</p>
+ <p xml:lang="de">Funktionen:</p>
+ <p xml:lang="en-GB">Features:</p>
+ <p xml:lang="es">Funciones:</p>
+ <p xml:lang="et">Omadused:</p>
+ <p xml:lang="fi">Ominaisuuksia:</p>
+ <p xml:lang="gl">Funcionalidades:</p>
+ <p xml:lang="it">Funzionalità:</p>
+ <p xml:lang="nl">Kenmerken:</p>
+ <p xml:lang="pl">Możliwości:</p>
+ <p xml:lang="pt">Funcionalidades:</p>
+ <p xml:lang="pt-BR">Funcionalidades:</p>
+ <p xml:lang="sk">Funkcie:</p>
+ <p xml:lang="sl">Zmožnosti:</p>
+ <p xml:lang="sv">Funktioner:</p>
+ <p xml:lang="uk">Можливості:</p>
+ <p xml:lang="x-test">xxFeatures:xx</p>
+ <ul>
+ <li>Supported formats: XMI</li>
+ <li xml:lang="ca">Formats acceptats: XMI</li>
+ <li xml:lang="cs">Podporované formáty: XMI</li>
+ <li xml:lang="de">Unterstützte Formate: XMI</li>
+ <li xml:lang="en-GB">Supported formats: XMI</li>
+ <li xml:lang="es">Formatos permitidos: XMI</li>
+ <li xml:lang="et">Toetatud vormingud: XMI</li>
+ <li xml:lang="fi">Tukee XMI-tiedostomuotoa</li>
+ <li xml:lang="gl">Formatos compatíbeis: XMI.</li>
+ <li xml:lang="it">Formati supportati: XMI</li>
+ <li xml:lang="nl">Ondersteunde formaten: XMI</li>
+ <li xml:lang="pl">Obsługiwane formaty: XMI</li>
+ <li xml:lang="pt">Formatos suportados: XMI</li>
+ <li xml:lang="pt-BR">Formatos suportados: XMI</li>
+ <li xml:lang="sk">Podporované formáty: XMI</li>
+ <li xml:lang="sl">Podprte oblike: XMI</li>
+ <li xml:lang="sv">Format som stöds: XMI</li>
+ <li xml:lang="uk">Підтримувані формати: XMI</li>
+ <li xml:lang="x-test">xxSupported formats: XMIxx</li>
+ <li>Several type of diagrams supported: use case, class, sequence, collaboration, state, activity, component, deployment, entity relationship</li>
+ <li xml:lang="ca">Es permeten diversos tipus de diagrames: cas d'ús, classe, seqüència, col·laboració, estat, activitat, component, desplegament, entitat relació</li>
+ <li xml:lang="en-GB">Several type of diagrams supported: use case, class, sequence, collaboration, state, activity, component, deployment, entity relationship</li>
+ <li xml:lang="es">Permite usar varios tipos de diagramas: casos de uso, clase, secuencia, colaboración, estado, actividad, componente, despliegue y relación de entidades</li>
+ <li xml:lang="et">Toetatud on mitut tüüpi skeemid: kasutus, klass, järgnevus, koostöö, olek, tegevus, komponent, evitus, olem-seos</li>
+ <li xml:lang="fi">Tukee monenlaisia kaavioita: käyttötapauskaavio, luokkakaavio, sekvenssikaavio, yhteistyökaavio, tilakaavio, aktiviteettikaavio, komponenttikaavio, sijoittelukaavio, käsitekaavio</li>
+ <li xml:lang="gl">Permite traballar con varios tipos de diagramas: caso de uso, clase, secuencia, colaboración, estado, actividade, compoñente, distribución, e entidade-relación.</li>
+ <li xml:lang="it">Diversi tipi di diagrammi supportati: casi d'uso, classe, sequenza, collaborazione, stato, attività, componente, dispiegamento, relazione tra entità</li>
+ <li xml:lang="nl">Verschillende typen diagrammen worden ondersteund: use case, klassen, volgorde, samenwerking, status, activiteit, component, deployment, relaties tussen eenheden</li>
+ <li xml:lang="pl">Kilka obsługiwanych rodzajów diagramów: przypadki użycia, klasy, sekwencje, kolaboracje, stany, aktywności, składniki, zastosowanie, współzależności obiektów</li>
+ <li xml:lang="pt">Diversos tipos de diagramas suportados: casos de uso, classe, sequência, colaboração, estado, actividade, componente, entrada em produção, entidade-associação</li>
+ <li xml:lang="pt-BR">Há suporte para diversos tipos de diagramas: casos de uso, classe, sequência, colaboração, estado, atividade, componente, distribuição, relacionamento de entidade</li>
+ <li xml:lang="sk">Podporovaných je niekoľko typov diagramov: prípady použitia, triedy, sekvencie, stavy, aktivity, nasadenie, vzžahy entít</li>
+ <li xml:lang="sl">Podprte so številne vrste diagramov: primer uporabe, razred, zaporedje, sodelovanje, stanje, dejavnost, sestavni del, namestitev, odvisnost entitete</li>
+ <li xml:lang="sv">Flera diagramtyper stöds: användningsfall, klass, sekvens, samarbete, tillstånd, aktivitet, komponent, utplacering, objektsamband</li>
+ <li xml:lang="uk">Підтримка декількох типів діаграм: випадків використання, класів, послідовності, співпраці, станів, компонент, розміщення та взаємозв’язку компонентів.</li>
+ <li xml:lang="x-test">xxSeveral type of diagrams supported: use case, class, sequence, collaboration, state, activity, component, deployment, entity relationshipxx</li>
+ </ul>
+ </description>
+ <url type="homepage">http://umbrello-kf6.kde.org</url>
+ <url type="bugtracker">https://bugs.kde.org/enter_bug.cgi?format=guided&amp;product=umbrello-kf6</url>
+ <url type="help">http://docs.kde.org/stable/en/kdesdk/umbrello/index.html</url>
+ <screenshots>
+ <screenshot type="default">
+ <image>http://kde.org/images/screenshots/umbrello-kf6.png</image>
+ </screenshot>
+ </screenshots>
+ <project_group>KDE</project_group>
+ <provides>
+ <binary>umbrello-kf6</binary>
+ </provides>
+</component>
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/package.cpp umbrello-kf6-15.08.1/umbrello/package.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/package.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/package.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,461 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header file
-#include "package.h"
-
-// local includes
-#include "debug_utils.h"
-#include "dialog_utils.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "classifier.h"
-#include "association.h"
-#include "entity.h"
-#include "object_factory.h"
-#include "model_utils.h"
-
-// kde includes
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-#include <KLocalizedString>
-#include <KMessageBox>
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-
-using namespace Uml;
-
-/**
- * Sets up a Package.
- * @param name The name of the Concept.
- * @param id The unique id of the Concept.
- */
-UMLPackage::UMLPackage(const QString & name, Uml::ID::Type id)
- : UMLCanvasObject(name, id)
-{
- m_BaseType = ot_Package;
-}
-
-/**
- * Destructor.
- */
-UMLPackage::~UMLPackage()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the new object.
- */
-void UMLPackage::copyInto(UMLObject *lhs) const
-{
- UMLPackage *target = static_cast<UMLPackage*>(lhs);
-
- UMLCanvasObject::copyInto(target);
-
- m_objects.copyInto(&(target->m_objects));
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLPackage::clone() const
-{
- UMLPackage *clone = new UMLPackage();
- copyInto(clone);
-
- return clone;
-}
-
-/**
- * Adds an existing association to the matching concept in the list of concepts.
- * The selection of the matching concept depends on the association type:
- * For generalizations, the assoc is added to the concept that matches role A.
- * For aggregations and compositions, the assoc is added to the concept
- * that matches role B.
- * @param assoc the association to add
- */
-void UMLPackage::addAssocToConcepts(UMLAssociation* assoc)
-{
- if (! AssociationType::hasUMLRepresentation(assoc->getAssocType()))
- return;
- Uml::ID::Type AId = assoc->getObjectId(Uml::RoleType::A);
- Uml::ID::Type BId = assoc->getObjectId(Uml::RoleType::B);
- UMLObject *o = NULL;
- for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
- o = oit.next();
- UMLCanvasObject *c = dynamic_cast<UMLCanvasObject*>(o);
- if (c == NULL)
- continue;
- if (AId == c->id() || (BId == c->id())) {
- if (c->hasAssociation(assoc))
- uDebug() << c->name() << " already has association id=" << Uml::ID::toString(assoc->id());
- else
- c->addAssociationEnd(assoc);
- }
- UMLPackage *pkg = dynamic_cast<UMLPackage*>(c);
- if (pkg)
- pkg->addAssocToConcepts(assoc);
- }
-}
-
-/**
- * Remove the association from the participating concepts.
- * @param assoc the association to remove
- */
-void UMLPackage::removeAssocFromConcepts(UMLAssociation *assoc)
-{
- UMLObject *o = 0;
- for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
- o = oit.next();
- UMLCanvasObject *c = dynamic_cast<UMLCanvasObject*>(o);
- if (c) {
- if (c->hasAssociation(assoc))
- c->removeAssociationEnd(assoc);
- UMLPackage *pkg = dynamic_cast<UMLPackage*>(c);
- if (pkg)
- pkg->removeAssocFromConcepts(assoc);
- }
- }
-}
-
-/**
- * Adds an object in this package.
- *
- * @param pObject Pointer to the UMLObject to add.
- * @return True if the object was actually added.
- */
-bool UMLPackage::addObject(UMLObject *pObject)
-{
- if (pObject == NULL) {
- uError() << "is called with a NULL object";
- return false;
- }
- if (pObject == this) {
- uError() << "adding myself as child is not allowed";
- return false;
- }
-
- if (m_objects.indexOf(pObject) != -1) {
- uDebug() << pObject->name() << " is already there";
- return false;
- }
- if (pObject->baseType() == UMLObject::ot_Association) {
- UMLAssociation *assoc = static_cast<UMLAssociation*>(pObject);
- // Adding the UMLAssociation at the participating concepts is done
- // again later (in UMLAssociation::resolveRef()) if they are not yet
- // known right here.
- if (assoc->getObject(Uml::RoleType::A) && assoc->getObject(Uml::RoleType::B)) {
- UMLPackage *pkg = pObject->umlPackage();
- if (pkg != this) {
- uError() << "UMLPackage " << name() << " addObject: "
- << "assoc's UMLPackage is " << pkg->name();
- }
- addAssocToConcepts(assoc);
- }
- }
- else {
- QString name = pObject->name();
- QString oldName = name;
- while (findObject(name) != NULL) {
- QString prevName = name;
- name = Model_Utils::uniqObjectName(pObject->baseType(), this);
- bool ok = Dialog_Utils::askName(i18nc("object name", "Name"),
- i18n("An object with the name %1\nalready exists in the package %2.\nPlease enter a new name:", prevName, this->name()),
- name);
- if (!ok) {
- name = oldName;
- continue;
- }
- if (name.length() == 0) {
- KMessageBox::error(0, i18n("That is an invalid name."),
- i18n("Invalid Name"));
- continue;
- }
- }
- if (oldName != name) {
- pObject->setName(name);
- }
- }
- m_objects.append(pObject);
- return true;
-}
-
-/**
- * Removes an object from this package.
- * Does not physically delete the object.
- *
- * @param pObject Pointer to the UMLObject to be removed.
- */
-void UMLPackage::removeObject(UMLObject *pObject)
-{
- if (pObject->baseType() == UMLObject::ot_Association) {
- UMLObject *o = const_cast<UMLObject*>(pObject);
- UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
- removeAssocFromConcepts(assoc);
- }
- if (m_objects.indexOf(pObject) == -1)
- uDebug() << name() << " removeObject: object with id="
- << Uml::ID::toString(pObject->id()) << "not found.";
- else
- m_objects.removeAll(pObject);
-}
-
-/**
- * Removes all objects from this package.
- * Inner containers (e.g. nested packages) are removed recursively.
- */
-void UMLPackage::removeAllObjects()
-{
- UMLCanvasObject::removeAllChildObjects();
- UMLObject *o = NULL;
-
- while (!m_objects.isEmpty() && (o = m_objects.first()) != NULL) {
- UMLPackage *pkg = dynamic_cast<UMLPackage*>(o);
- if (pkg)
- pkg->removeAllObjects();
- removeObject(o);
- delete o;
- }
-}
-
-/**
- * Returns the list of objects contained in this package.
- */
-UMLObjectList UMLPackage::containedObjects()
-{
- return m_objects;
-}
-
-/**
- * Find the object of the given name in the list of contained objects.
- *
- * @param name The name to seek.
- * @return Pointer to the UMLObject found or NULL if not found.
- */
-UMLObject * UMLPackage::findObject(const QString &name)
-{
- const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
- for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
- UMLObject *obj = oit.next();
- if (!obj)
- continue;
- if (caseSensitive) {
- if (obj->name() == name)
- return obj;
- } else if (obj->name().toLower() == name.toLower()) {
- return obj;
- }
- }
- return NULL;
-}
-
-/**
- * Find the object of the given ID in the list of contained objects.
- *
- * @param id The ID to seek.
- * @return Pointer to the UMLObject found or NULL if not found.
- */
-UMLObject * UMLPackage::findObjectById(Uml::ID::Type id)
-{
- return Model_Utils::findObjectInList(id, m_objects);
-}
-
-/**
- * Append all packages from this package (and those from nested packages)
- * to the given UMLPackageList.
- *
- * @param packages The list to append to
- * @param includeNested Whether to include the packages from nested packages
- * (default:true)
- */
-void UMLPackage::appendPackages(UMLPackageList& packages, bool includeNested)
-{
- for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
- UMLObject *o = oit.next();
- uIgnoreZeroPointer(o);
- ObjectType ot = o->baseType();
- if (ot == ot_Package || ot == ot_Folder) {
- packages.append(static_cast<UMLPackage*>(o));
- if (includeNested) {
- UMLPackage *inner = static_cast<UMLPackage*>(o);
- inner->appendPackages(packages);
- }
- }
- }
-}
-
-/**
- * Append all classifiers from this package (and those from
- * nested packages) to the given UMLClassifierList.
- *
- * @param classifiers The list to append to.
- * @param includeNested Whether to include the classifiers from
- * nested packages (default: true.)
- */
-void UMLPackage::appendClassifiers(UMLClassifierList& classifiers,
- bool includeNested /* = true */)
-{
- for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
- UMLObject *o = oit.next();
- uIgnoreZeroPointer(o);
- ObjectType ot = o->baseType();
- if (ot == ot_Class || ot == ot_Interface ||
- ot == ot_Datatype || ot == ot_Enum || ot == ot_Entity) {
- classifiers.append((UMLClassifier *)o);
- } else if (includeNested && (ot == ot_Package || ot == ot_Folder)) {
- UMLPackage *inner = static_cast<UMLPackage *>(o);
- inner->appendClassifiers(classifiers);
- }
- }
-}
-
-/**
- * Append all entities from this package (and those
- * from nested packages) to the given UMLEntityList.
- *
- * @param entities The list to append to.
- * @param includeNested Whether to include the entities from
- * nested packages (default: true.)
- */
-void UMLPackage::appendEntities(UMLEntityList& entities,
- bool includeNested /* = true */)
-{
- for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
- UMLObject *o = oit.next();
- uIgnoreZeroPointer(o);
- ObjectType ot = o->baseType();
- if (ot == ot_Entity) {
- UMLEntity *c = static_cast<UMLEntity*>(o);
- entities.append(c);
- } else if (includeNested && (ot == ot_Package || ot == ot_Folder)) {
- UMLPackage *inner = static_cast<UMLPackage *>(o);
- inner->appendEntities(entities);
- }
- }
-}
-
-/**
- * Append all classes and interfaces from this package (and those
- * from nested packages) to the given UMLClassifierList.
- *
- * @param classifiers The list to append to.
- * @param includeNested Whether to include the classifiers from
- * nested packages (default: true.)
- */
-void UMLPackage::appendClassesAndInterfaces(UMLClassifierList& classifiers,
- bool includeNested /* = true */)
-{
- for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
- UMLObject *o = oit.next();
- uIgnoreZeroPointer(o);
- ObjectType ot = o->baseType();
- if (ot == ot_Class || ot == ot_Interface) {
- UMLClassifier *c = static_cast<UMLClassifier*>(o);
- classifiers.append(c);
- } else if (includeNested && (ot == ot_Package || ot == ot_Folder)) {
- UMLPackage *inner = static_cast<UMLPackage *>(o);
- inner->appendClassesAndInterfaces(classifiers);
- }
- }
-}
-
-/**
- * Resolve types. Required when dealing with foreign XMI files.
- * Needs to be called after all UML objects are loaded from file.
- * Overrides the method from UMLObject.
- * Calls resolveRef() on each contained object.
- *
- * @return True for overall success.
- */
-bool UMLPackage::resolveRef()
-{
- bool overallSuccess = UMLCanvasObject::resolveRef();
- for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
- UMLObject *obj = oit.next();
- uIgnoreZeroPointer(obj);
- if (! obj->resolveRef()) {
- UMLObject::ObjectType ot = obj->baseType();
- if (ot != UMLObject::ot_Package && ot != UMLObject::ot_Folder)
- m_objects.removeAll(obj);
- overallSuccess = false;
- }
- }
- return overallSuccess;
-}
-
-/**
- * Creates the <UML:Package> XMI element.
- */
-void UMLPackage::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement packageElement = UMLObject::save(QLatin1String("UML:Package"), qDoc);
- QDomElement ownedElement = qDoc.createElement(QLatin1String("UML:Namespace.ownedElement"));
- UMLObject *obj = NULL;
- // save classifiers etc.
- for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
- obj = oit.next();
- uIgnoreZeroPointer(obj);
- obj->saveToXMI (qDoc, ownedElement);
- }
- // save associations
- for (UMLObjectListIt ait(m_List); ait.hasNext();) {
- obj = ait.next();
- obj->saveToXMI (qDoc, ownedElement);
- }
-
- packageElement.appendChild(ownedElement);
- qElement.appendChild(packageElement);
-}
-
-/**
- * Loads the <UML:Package> XMI element.
- * Auxiliary to UMLObject::loadFromXMI.
- */
-bool UMLPackage::load(QDomElement& element)
-{
- for (QDomNode node = element.firstChild(); !node.isNull();
- node = node.nextSibling()) {
- if (node.isComment())
- continue;
- QDomElement tempElement = node.toElement();
- QString type = tempElement.tagName();
- if (Model_Utils::isCommonXMIAttribute(type))
- continue;
- if (UMLDoc::tagEq(type, QLatin1String("Namespace.ownedElement")) ||
- UMLDoc::tagEq(type, QLatin1String("Element.ownedElement")) || // Embarcadero's Describe
- UMLDoc::tagEq(type, QLatin1String("Namespace.contents"))) {
- //CHECK: umbrello-kf6 currently assumes that nested elements
- // are ownedElements anyway.
- // Therefore these tags are not further interpreted.
- if (! load(tempElement))
- return false;
- continue;
- } else if (UMLDoc::tagEq(type, QLatin1String("packagedElement")) ||
- UMLDoc::tagEq(type, QLatin1String("ownedElement"))) {
- type = tempElement.attribute(QLatin1String("xmi:type"));
- }
- UMLObject *pObject = Object_Factory::makeObjectFromXMI(type);
- if(!pObject) {
- uWarning() << "Unknown type of umlobject to create: " << type;
- continue;
- }
- pObject->setUMLPackage(this);
- if (!pObject->loadFromXMI(tempElement)) {
- removeObject(pObject);
- delete pObject;
- }
- }
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/package.h umbrello-kf6-15.08.1/umbrello/package.h
--- umbrello-kf6-15.08.1.orig/umbrello/package.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/package.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,79 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef PACKAGE_H
-#define PACKAGE_H
-
-#include "umlcanvasobject.h"
-#include "umlclassifierlist.h"
-#include "umlentitylist.h"
-
-// forward declarations
-class UMLAssociation;
-
-/**
- * This class contains the non-graphical information required for a UML
- * Package.
- * This class inherits from @ref UMLCanvasObject which contains most of the
- * information.
- *
- * @short Non-graphical information for a Package.
- * @author Jonathan Riddell
- * @see UMLCanvasObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLPackage : public UMLCanvasObject
-{
- Q_OBJECT
-public:
- explicit UMLPackage(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLPackage();
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- bool addObject(UMLObject *pObject);
- void removeObject(UMLObject *pObject);
-
- virtual void removeAllObjects();
-
- UMLObjectList containedObjects();
-
- void addAssocToConcepts(UMLAssociation* assoc);
- void removeAssocFromConcepts(UMLAssociation *assoc);
-
- UMLObject * findObject(const QString &name);
- UMLObject * findObjectById(Uml::ID::Type id);
-
- void appendPackages(UMLPackageList& packages, bool includeNested = true);
- void appendClassifiers(UMLClassifierList& classifiers,
- bool includeNested = true);
- void appendClassesAndInterfaces(UMLClassifierList& classifiers,
- bool includeNested = true);
- void appendEntities(UMLEntityList& entities,
- bool includeNested = true);
-
- virtual bool resolveRef();
-
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
-protected:
- virtual bool load(QDomElement& element);
-
- /**
- * References to the objects contained in this package.
- * The UMLPackage is the owner of the objects.
- */
- UMLObjectList m_objects;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/port.cpp umbrello-kf6-15.08.1/umbrello/port.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/port.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/port.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,68 +0,0 @@
-/***************************************************************************
- * 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) 2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "port.h"
-
-#include <KLocalizedString>
-
-/**
- * Sets up a Port.
- *
- * @param name The name of the Concept.
- * @param id The unique id of the Concept.
- */
-UMLPort::UMLPort(const QString & name, Uml::ID::Type id)
- : UMLCanvasObject(name, id)
-{
- init();
-}
-
-/**
- * Destructor.
- */
-UMLPort::~UMLPort()
-{
-}
-
-/**
- * Initializes key variables of the class.
- */
-void UMLPort::init()
-{
- m_BaseType = UMLObject::ot_Port;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLPort::clone() const
-{
- UMLPort *clone = new UMLPort();
- UMLObject::copyInto(clone);
- return clone;
-}
-
-/**
- * Creates the <UML:Port> XMI element.
- */
-void UMLPort::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement portElement = UMLObject::save(QLatin1String("UML:Port"), qDoc);
- qElement.appendChild(portElement);
-}
-
-/**
- * Loads the <UML:Port> XMI element (empty.)
- */
-bool UMLPort::load(QDomElement&)
-{
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/port.h umbrello-kf6-15.08.1/umbrello/port.h
--- umbrello-kf6-15.08.1.orig/umbrello/port.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/port.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,46 +0,0 @@
-/***************************************************************************
- * 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) 2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef PORT_H
-#define PORT_H
-
-#include "umlcanvasobject.h"
-
-/**
- * This class contains the non-graphical information required for a UML Port.
- * This class inherits from @ref UMLCanvasObject which contains most of the
- * information.
- *
- * @short Non-graphical information for a Port.
- * @author Oliver Kellogg
- * @see UMLCanvasObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLPort : public UMLCanvasObject
-{
- Q_OBJECT
-public:
-
- explicit UMLPort(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLPort();
-
- virtual void init();
-
- virtual UMLObject* clone() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
-protected:
-
- bool load(QDomElement & element);
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/stereotype.cpp umbrello-kf6-15.08.1/umbrello/stereotype.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/stereotype.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/stereotype.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,164 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "stereotype.h"
-
-// local includes
-#include "debug_utils.h"
-#include "umldoc.h"
-#include "uml.h"
-
-// kde includes
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-#include <KLocalizedString>
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-
-/**
- * Sets up a stereotype.
- *
- * @param name The name of this UMLStereotype.
- * @param id The unique id given to this UMLStereotype.
- */
-UMLStereotype::UMLStereotype(const QString &name, Uml::ID::Type id /* = Uml::id_None */)
- : UMLObject(name, id)
-{
- m_BaseType = UMLObject::ot_Stereotype;
- UMLStereotype * existing = UMLApp::app()->document()->findStereotype(name);
- if (existing) {
- uError() << "UMLStereotype constructor: " << name << " already exists";
- }
- m_refCount = 0;
-}
-
-/**
- * Sets up a stereotype.
- */
-UMLStereotype::UMLStereotype()
- : UMLObject()
-{
- m_BaseType = UMLObject::ot_Stereotype;
- m_refCount = 0;
-}
-
-/**
- * Destructor.
- */
-UMLStereotype::~UMLStereotype()
-{
-}
-
-/**
- * Overloaded '==' operator.
- */
-bool UMLStereotype::operator==(const UMLStereotype &rhs) const
-{
- if (this == &rhs) {
- return true;
- }
-
- if (!UMLObject::operator==(rhs)) {
- return false;
- }
-
- return true;
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLStereotype::copyInto(UMLObject *lhs) const
-{
- UMLObject::copyInto(lhs);
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLStereotype::clone() const
-{
- UMLStereotype *clone = new UMLStereotype();
- copyInto(clone);
-
- return clone;
-}
-
-/**
- * Saves to the <UML:StereoType> XMI element.
- */
-void UMLStereotype::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- //FIXME: uml13.dtd compliance
- QDomElement stereotypeElement = UMLObject::save(QLatin1String("UML:Stereotype"), qDoc);
- qElement.appendChild(stereotypeElement);
-}
-
-/**
- * Display the properties configuration dialog for the stereotype
- * (just a line edit).
- */
-bool UMLStereotype::showPropertiesDialog(QWidget* parent)
-{
- bool ok;
-#if QT_VERSION >= 0x050000
- QString stereoTypeName = QInputDialog::getText(parent,
- i18n("Stereotype"), i18n("Enter name:"),
- QLineEdit::Normal,
- name(), &ok);
-#else
- QString stereoTypeName = KInputDialog::getText(i18n("Stereotype"), i18n("Enter name:"), name(), &ok, parent);
-#endif
- if (ok) {
- setName(stereoTypeName);
- }
- return ok;
-}
-
-/**
- * Increments the reference count for this stereotype.
- */
-void UMLStereotype::incrRefCount()
-{
- m_refCount++;
-}
-
-/**
- * Decrements the reference count for this stereotype.
- */
-void UMLStereotype::decrRefCount()
-{
- m_refCount--;
-}
-
-/**
- * Returns the reference count for this stereotype.
- */
-int UMLStereotype::refCount() const
-{
- return m_refCount;
-}
-
-/**
- * Returns the name as string
- */
-QString UMLStereotype::name(bool includeAdornments) const
-{
- if (includeAdornments)
- return QString::fromUtf8("«") + UMLObject::name() + QString::fromUtf8("»");
- else
- return UMLObject::name();
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/stereotype.h umbrello-kf6-15.08.1/umbrello/stereotype.h
--- umbrello-kf6-15.08.1.orig/umbrello/stereotype.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/stereotype.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,71 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef STEREOTYPE_H
-#define STEREOTYPE_H
-
-#include "umlobject.h"
-
-/**
- * This class is used to set up information for a stereotype.
- * Stereotypes are used essentially as properties of
- * attributes and operations etc.
- *
- * Each stereotype object is reference counted, i.e. client code
- * manages it such that it comes into existence as soon as there is
- * at least one user, and ceases existing when the number of users
- * drops to 0.
- * m_refCount reflects the number of users. It is externally managed,
- * i.e. client code must take care to call incrRefCount() and
- * decrRefCount() as appropriate.
- *
- * The one and only owner of all stereotypes is the UMLDoc, and the
- * ownership is specially managed (umlPackage() returns NULL for a
- * UMLStereotype.) The reason for this special treatment is that
- * class UMLDoc does not inherit from class UMLPackage, and therefore
- * setUMLPackage() cannot be used for stereotypes.
- *
- * @short Sets up stereotype information.
- * @author Jonathan Riddell
- * @author Oliver Kellogg
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLStereotype : public UMLObject
-{
- Q_OBJECT
-public:
- explicit UMLStereotype(const QString &name, Uml::ID::Type id = Uml::ID::None);
- UMLStereotype();
-
- virtual ~UMLStereotype();
-
- bool operator==(const UMLStereotype &rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- void incrRefCount();
- void decrRefCount();
-
- int refCount() const;
-
- QString name(bool includeAdornments=false) const;
-
- void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
- virtual bool showPropertiesDialog(QWidget* parent);
-
-protected:
- int m_refCount;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/stereotypesmodel.cpp umbrello-kf6-15.08.1/umbrello/stereotypesmodel.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/stereotypesmodel.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/stereotypesmodel.cpp 2015-10-08 11:48:59.505089026 +0300
@@ -0,0 +1,121 @@
+/***************************************************************************
+ * 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) 2015 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "stereotypesmodel.h"
+
+// app includes
+#include "stereotype.h"
+#include "uml.h"
+#include "umldoc.h"
+
+// kde includes
+#include <KLocalizedString>
+
+// qt includes
+#include <QtDebug>
+
+StereotypesModel::StereotypesModel(UMLStereotypeList *stereotypes)
+ : m_count(0),
+ m_stereotypes(stereotypes)
+{
+}
+
+int StereotypesModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ int count = m_stereotypes->count();
+ return count;
+}
+
+int StereotypesModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return 2;
+}
+
+QVariant StereotypesModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (section < 0)
+ return QVariant();
+
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (orientation == Qt::Vertical)
+ return section + 1;
+ if (section == 0)
+ return QVariant(i18n("Name"));
+ else if (section == 1)
+ return QVariant(i18n("Usage"));
+ else return QVariant();
+}
+
+QVariant StereotypesModel::data(const QModelIndex & index, int role) const
+{
+ if (role == Qt::UserRole && index.column() == 0) {
+ QVariant v;
+ v.setValue(m_stereotypes->at(index.row()));
+ return v;
+ }
+
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ int cCount = columnCount(index);
+ if (index.column() >= cCount)
+ return QVariant();
+
+ UMLStereotype *s = m_stereotypes->at(index.row());
+ if (cCount == 1) {
+ QString a = s->name() + QString(QLatin1String(" (%1)")).arg(s->refCount());
+ return a;
+ }
+
+ // table view
+ if (index.column() == 0)
+ return s->name();
+ else
+ return s->refCount();
+}
+
+bool StereotypesModel::addStereotype(UMLStereotype *stereotype)
+{
+ if (m_stereotypes->contains(stereotype))
+ return false;
+ int index = m_stereotypes->count();
+ beginInsertRows(QModelIndex(), index, index);
+ m_stereotypes->append(stereotype);
+ endInsertRows();
+ return true;
+}
+
+bool StereotypesModel::removeStereotype(UMLStereotype *stereotype)
+{
+ if (!m_stereotypes->contains(stereotype))
+ return false;
+ int index = m_stereotypes->indexOf(stereotype);
+ beginRemoveRows(QModelIndex(), index, index);
+ m_stereotypes->removeAll(stereotype);
+ endRemoveRows();
+ return true;
+}
+
+void StereotypesModel::emitDataChanged(const QModelIndex &index)
+{
+ emit dataChanged(index, index);
+}
+
+void StereotypesModel::emitDataChanged(int index)
+{
+ QModelIndex mi = createIndex(index,0);
+ emit dataChanged(mi, mi);
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/stereotypesmodel.h umbrello-kf6-15.08.1/umbrello/stereotypesmodel.h
--- umbrello-kf6-15.08.1.orig/umbrello/stereotypesmodel.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/stereotypesmodel.h 2015-10-08 11:48:59.505089026 +0300
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * 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) 2015 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef STEREOTYPESMODEL_H
+#define STEREOTYPESMODEL_H
+
+// app includes
+#include "umlstereotypelist.h"
+
+// qt includes
+#include <QAbstractTableModel>
+
+class UMLStereotype;
+
+Q_DECLARE_METATYPE(UMLStereotype*);
+
+class StereotypesModel : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ StereotypesModel(UMLStereotypeList *stereotypes);
+
+ int rowCount(const QModelIndex &parent) const;
+ int columnCount(const QModelIndex &parent) const;
+
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
+
+ bool addStereotype(UMLStereotype *stereotype);
+ bool removeStereotype(UMLStereotype *stereotype);
+
+ void emitDataChanged(const QModelIndex &index);
+ void emitDataChanged(int index);
+
+protected:
+ int m_count;
+ UMLStereotypeList *m_stereotypes;
+};
+
+#endif // STEREOTYPESMODEL_H
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/stereotypeswindow.cpp umbrello-kf6-15.08.1/umbrello/stereotypeswindow.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/stereotypeswindow.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/stereotypeswindow.cpp 2015-10-08 11:48:59.506089026 +0300
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * 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) 2015 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "stereotypeswindow.h"
+
+// app includes
+#include "stereotype.h"
+#include "stereotypesmodel.h"
+#include "uml.h"
+#include "umldoc.h"
+
+// kde includes
+#include <KLocalizedString>
+
+// qt includes
+#include <QHeaderView>
+#include <QTableView>
+#include <QSortFilterProxyModel>
+#include <QtDebug>
+
+StereotypesWindow::StereotypesWindow(QWidget *parent)
+ : QDockWidget(i18n("&Stereotypes"), parent)
+{
+ setObjectName(QLatin1String("StereotypesWindow"));
+
+ QSortFilterProxyModel *proxy = new QSortFilterProxyModel;
+ proxy->setSourceModel(UMLApp::app()->document()->stereotypesModel());
+ proxy->setSortCaseSensitivity(Qt::CaseInsensitive);
+ m_stereotypesTree = new QTableView;
+ m_stereotypesTree->setModel(proxy);
+ m_stereotypesTree->setSortingEnabled(true);
+ m_stereotypesTree->verticalHeader()->setDefaultSectionSize(20);
+ m_stereotypesTree->verticalHeader()->setVisible(false);
+#if QT_VERSION >= 0x050000
+ m_stereotypesTree->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+#else
+ m_stereotypesTree->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
+#endif
+ setWidget(m_stereotypesTree);
+
+ connect(m_stereotypesTree, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(slotStereotypesDoubleClicked(QModelIndex)));
+}
+
+StereotypesWindow::~StereotypesWindow()
+{
+ delete m_stereotypesTree;
+}
+
+void StereotypesWindow::modified()
+{
+ UMLStereotype *o = static_cast<UMLStereotype*>(QObject::sender());
+ if (!o)
+ return;
+ int index = UMLApp::app()->document()->stereotypes().indexOf(o);
+ UMLApp::app()->document()->stereotypesModel()->emitDataChanged(index);
+}
+
+void StereotypesWindow::slotStereotypesDoubleClicked(QModelIndex index)
+{
+ QVariant v = UMLApp::app()->document()->stereotypesModel()->data(index, Qt::UserRole);
+ if (v.canConvert<UMLStereotype*>()) {
+ UMLStereotype *s = v.value<UMLStereotype*>();
+ s->showPropertiesDialog(this);
+ }
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/stereotypeswindow.h umbrello-kf6-15.08.1/umbrello/stereotypeswindow.h
--- umbrello-kf6-15.08.1.orig/umbrello/stereotypeswindow.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/stereotypeswindow.h 2015-10-08 11:48:59.506089026 +0300
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * 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) 2015 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef STEREOTYPESWINDOW_H
+#define STEREOTYPESWINDOW_H
+
+#include <QDockWidget>
+#include <QModelIndex>
+
+class QTableView;
+
+class StereotypesWindow : public QDockWidget
+{
+ Q_OBJECT
+public:
+ explicit StereotypesWindow(QWidget *parent = 0);
+ ~StereotypesWindow();
+
+signals:
+
+public slots:
+ void modified();
+
+protected slots:
+ void slotStereotypesDoubleClicked(QModelIndex index);
+
+protected:
+ QTableView *m_stereotypesTree;
+};
+
+#endif // STEREOTYPESWINDOW_H
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/template.cpp umbrello-kf6-15.08.1/umbrello/template.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/template.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/template.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,146 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "template.h"
-
-// app includes
-#include "debug_utils.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umltemplatedialog.h"
-
-/**
- * Sets up a template.
- *
- * @param parent The parent of this UMLTemplate (i.e. its concept).
- * @param name The name of this UMLTemplate.
- * @param id The unique id given to this UMLTemplate.
- * @param type The type of this UMLTemplate.
- */
-UMLTemplate::UMLTemplate(UMLObject *parent, const QString& name,
- Uml::ID::Type id, const QString& type)
- : UMLClassifierListItem(parent, name, id)
-{
- setTypeName(type);
- m_BaseType = UMLObject::ot_Template;
-}
-
-/**
- * Sets up a template.
- *
- * @param parent The parent of this UMLTemplate (i.e. its concept).
- */
-UMLTemplate::UMLTemplate(UMLObject *parent)
- : UMLClassifierListItem(parent)
-{
- m_BaseType = UMLObject::ot_Template;
-}
-
-/**
- * Destructor.
- */
-UMLTemplate::~UMLTemplate()
-{
-}
-
-QString UMLTemplate::toString(Uml::SignatureType::Enum sig)
-{
- Q_UNUSED(sig);
- if (m_pSecondary == NULL || m_pSecondary->name() == QLatin1String("class")) {
- return name();
- } else {
- return name() + QLatin1String(" : ") + m_pSecondary->name();
- }
-}
-
-/**
- * Overrides method from UMLClassifierListItem.
- * Returns the type name of the UMLTemplate.
- * If the template parameter is a class, there is no separate
- * type object. In this case, getTypeName() returns "class".
- *
- * @return The type name of the UMLClassifierListItem.
- */
-QString UMLTemplate::getTypeName() const
-{
- if (m_pSecondary == NULL)
- return QLatin1String("class");
- return m_pSecondary->name();
-}
-
-/**
- * Overloaded '==' operator.
- */
-bool UMLTemplate::operator==(const UMLTemplate &rhs) const
-{
- if (this == &rhs) {
- return true;
- }
- if (!UMLObject::operator==(rhs)) {
- return false;
- }
- if (m_pSecondary != rhs.m_pSecondary) {
- return false;
- }
- return true;
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLTemplate::copyInto(UMLObject *lhs) const
-{
- UMLClassifierListItem::copyInto(lhs);
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLTemplate::clone() const
-{
- UMLTemplate *clone = new UMLTemplate((UMLTemplate*) parent());
- copyInto(clone);
-
- return clone;
-}
-
-/**
- * Writes the <UML:TemplateParameter> XMI element.
- */
-void UMLTemplate::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- //FIXME: uml13.dtd compliance
- QDomElement attributeElement = UMLObject::save(QLatin1String("UML:TemplateParameter"), qDoc);
- if (m_pSecondary)
- attributeElement.setAttribute(QLatin1String("type"), Uml::ID::toString(m_pSecondary->id()));
- qElement.appendChild(attributeElement);
-}
-
-/**
- * Loads the <UML:TemplateParameter> XMI element.
- */
-bool UMLTemplate::load(QDomElement& element)
-{
- m_SecondaryId = element.attribute(QLatin1String("type"));
- return true;
-}
-
-/**
- * Display the properties configuration dialog for the template.
- *
- * @return Success status.
- */
-bool UMLTemplate::showPropertiesDialog(QWidget* parent)
-{
- UMLTemplateDialog dialog(parent, this);
- return dialog.exec();
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/template.h umbrello-kf6-15.08.1/umbrello/template.h
--- umbrello-kf6-15.08.1.orig/umbrello/template.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/template.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,57 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef TEMPLATE_H
-#define TEMPLATE_H
-
-#include "classifierlistitem.h"
-
-/**
- * This class holds information used by template classes, called
- * paramaterised class in UML and a generic in Java. It has a
- * type (usually just "class") and name.
- *
- * @short Sets up template information.
- * @author Jonathan Riddell
- * @see UMLObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLTemplate : public UMLClassifierListItem
-{
-public:
-
- UMLTemplate(UMLObject *parent, const QString& name,
- Uml::ID::Type id = Uml::ID::None, const QString& type = QLatin1String("class"));
-
- explicit UMLTemplate(UMLObject *parent);
-
- bool operator==(const UMLTemplate &rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- virtual ~UMLTemplate();
-
- QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
-
- virtual QString getTypeName() const;
-
- virtual bool showPropertiesDialog(QWidget* parent);
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
-protected:
-
- bool load(QDomElement & element);
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umbrello-kf6ui.rc umbrello-kf6-15.08.1/umbrello/umbrello-kf6ui.rc
--- umbrello-kf6-15.08.1.orig/umbrello/umbrello-kf6ui.rc 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umbrello-kf6ui.rc 2015-10-08 11:48:59.506089026 +0300
@@ -85,6 +85,7 @@
<Action name="view_show_doc"/>
<Action name="view_show_undo"/>
<Action name="view_show_bird"/>
+ <Action name="view_show_stereotypes"/>
</Menu>
</MenuBar>
<ToolBar name="mainToolBar" fullWidth="true" newline="true">
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlappprivate.h umbrello-kf6-15.08.1/umbrello/umlappprivate.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlappprivate.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlappprivate.h 2015-10-08 11:48:59.506089026 +0300
@@ -15,8 +15,11 @@
#include "finddialog.h"
#include "findresults.h"
#include "uml.h"
+#include "stereotypeswindow.h"
// kde includes
+#include <KActionCollection>
+#include <KToggleAction>
#include <ktexteditor-kf6/configinterface.h>
#include <ktexteditor-kf6/document.h>
#include <ktexteditor-kf6/editor.h>
@@ -43,16 +46,18 @@
{
Q_OBJECT
public:
- QWidget *parent;
+ UMLApp *parent;
FindDialog findDialog;
FindResults findResults;
QListWidget *logWindow; ///< Logging window.
+ KToggleAction *viewStereotypesWindow;
+ StereotypesWindow *stereotypesWindow;
ktexteditor-kf6::Editor *editor;
ktexteditor-kf6::View *view;
ktexteditor-kf6::Document *document;
- explicit UMLAppPrivate(QWidget *_parent)
+ explicit UMLAppPrivate(UMLApp *_parent)
: parent(_parent),
findDialog(_parent),
view(0),
@@ -101,6 +106,18 @@
delete dialog;
delete document;
}
+
+ void createStereotypesWindow()
+ {
+ // create the tree viewer
+ stereotypesWindow = new StereotypesWindow(parent);
+ parent->addDockWidget(Qt::LeftDockWidgetArea, stereotypesWindow);
+
+ viewStereotypesWindow = parent->actionCollection()->add<KToggleAction>(QLatin1String("view_stereotypes_window"));
+ viewStereotypesWindow->setText(i18n("Stereotypes"));
+ connect(viewStereotypesWindow, SIGNAL(triggered(bool)), stereotypesWindow, SLOT(setVisible(bool)));
+ }
+
};
#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlassociationlist.h umbrello-kf6-15.08.1/umbrello/umlassociationlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlassociationlist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlassociationlist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,23 +0,0 @@
-/***************************************************************************
- * *
- * 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-2007 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLASSOCIATIONLIST_H
-#define UMLASSOCIATIONLIST_H
-
-#include <qlist.h>
-
-// forward declaration
-class UMLAssociation;
-
-typedef QList<UMLAssociation*> UMLAssociationList;
-typedef QListIterator<UMLAssociation*> UMLAssociationListIt;
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlattributelist.cpp umbrello-kf6-15.08.1/umbrello/umlattributelist.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlattributelist.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlattributelist.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,61 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "umlattributelist.h"
-
-#include "attribute.h"
-
-#include <KLocalizedString>
-
-UMLAttributeList::UMLAttributeList()
-{
-}
-
-UMLAttributeList::UMLAttributeList(const UMLAttributeList& other)
- : QList<UMLAttribute*>(other)
-{
-}
-
-UMLAttributeList::~UMLAttributeList()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLAttributeList::copyInto(UMLAttributeList *rhs) const
-{
- // Don't copy yourself.
- if (rhs == this) return;
-
- rhs->clear();
-
- // Suffering from const; we shall not modify our object.
- UMLAttributeList *tmp = new UMLAttributeList(*this);
-
- UMLAttribute *item;
- for (UMLAttributeListIt ait(*tmp); ait.hasNext() ;)
- {
- item = ait.next();
- rhs->append((UMLAttribute*)item->clone());
- }
- delete tmp;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLAttributeList* UMLAttributeList::clone() const
-{
- UMLAttributeList *clone = new UMLAttributeList();
- copyInto(clone);
- return clone;
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlattributelist.h umbrello-kf6-15.08.1/umbrello/umlattributelist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlattributelist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlattributelist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,42 +0,0 @@
-/***************************************************************************
- * *
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLATTRIBUTELIST_H
-#define UMLATTRIBUTELIST_H
-
-#include <QList>
-
-#include "attribute.h"
-
-//typedef QPtrList<UMLAttribute> UMLAttributeList;
-typedef QListIterator<UMLAttribute*> UMLAttributeListIt;
-
-/**
- * This sub-class adds copyInto and clone to the QPtrList<UMLAttribute>
- * base class.
- */
-class UMLAttributeList : public QList<UMLAttribute*>
-{
-public:
-
- UMLAttributeList();
-
- UMLAttributeList(const UMLAttributeList&);
-
- virtual ~UMLAttributeList();
-
- virtual void copyInto(UMLAttributeList *rhs) const;
-
- virtual UMLAttributeList* clone() const;
-};
-
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlcanvasobject.cpp umbrello-kf6-15.08.1/umbrello/umlcanvasobject.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlcanvasobject.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlcanvasobject.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,464 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "umlcanvasobject.h"
-
-// local includes
-#include "debug_utils.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "classifier.h"
-#include "association.h"
-#include "attribute.h"
-#include "operation.h"
-#include "template.h"
-#include "stereotype.h"
-#include "idchangelog.h"
-
-// kde includes
-#include <KLocalizedString>
-
-DEBUG_REGISTER_DISABLED(UMLCanvasObject)
-
-/**
- * Sets up a UMLCanvasObject.
- *
- * @param name The name of the Concept.
- * @param id The unique id of the Concept.
- */
-UMLCanvasObject::UMLCanvasObject(const QString & name, Uml::ID::Type id)
- : UMLObject(name, id)
-{
-}
-
-/**
- * Standard deconstructor.
- */
-UMLCanvasObject::~UMLCanvasObject()
-{
- //removeAllAssociations();
- // No! This is way too late to do that.
- // It should have been called explicitly before destructing the
- // UMLCanvasObject.
- if (associations())
- DEBUG(DBG_SRC) << "UMLCanvasObject destructor: FIXME: there are still associations()";
-}
-
-/**
- * Return the subset of m_List that matches the given type.
- *
- * @param assocType The AssociationType::Enum to match.
- * @return The list of associations that match assocType.
- */
-UMLAssociationList UMLCanvasObject::getSpecificAssocs(Uml::AssociationType::Enum assocType)
-{
- UMLAssociationList list;
- UMLObject *o = NULL;
- for (UMLObjectListIt oit(m_List); oit.hasNext();) {
- o = oit.next();
- uIgnoreZeroPointer(o);
- if (o->baseType() != UMLObject::ot_Association)
- continue;
- UMLAssociation *a = static_cast<UMLAssociation*>(o);
- if (a->getAssocType() == assocType)
- list.append(a);
- }
- return list;
-}
-
-/**
- * Adds an association end to m_List.
- *
- * @param assoc The association to add.
- * @todo change param type to UMLRole
- */
-bool UMLCanvasObject::addAssociationEnd(UMLAssociation* assoc)
-{
- Q_ASSERT(assoc);
- // add association only if not already present in list
- if (!hasAssociation(assoc))
- {
- m_List.append(assoc);
-
- // Don't emit signals during load from XMI
- UMLObject::emitModified();
- emit sigAssociationEndAdded(assoc);
- return true;
- }
- return false;
-}
-
-/**
- * Determine if this canvasobject has the given association.
- *
- * @param assoc The association to check.
- */
-bool UMLCanvasObject::hasAssociation(UMLAssociation* assoc)
-{
- uint cnt = m_List.count(assoc);
- DEBUG(DBG_SRC) << "count is " << cnt;
- return (cnt > 0);
-}
-
-/**
- * Remove an association end from the CanvasObject.
- *
- * @param assoc The association to remove.
- * @todo change param type to UMLRole
- */
-int UMLCanvasObject::removeAssociationEnd(UMLAssociation * assoc)
-{
- if (!hasAssociation(assoc) || !m_List.removeAll(assoc)) {
- DEBUG(DBG_SRC) << "cannot find given assoc " << assoc << " in list";
- return -1;
- }
- UMLApp::app()->document()->removeAssociation(assoc, false);
- UMLObject::emitModified();
- emit sigAssociationEndRemoved(assoc);
- return m_List.count();
-}
-
-/**
- * Remove all association ends from the CanvasObject.
- */
-void UMLCanvasObject::removeAllAssociationEnds()
-{
- for (int i = 0; i < m_List.count(); i++) {
- UMLObject *o = m_List.at(i);
- uIgnoreZeroPointer(o);
- if (o->baseType() != UMLObject::ot_Association) {
- continue;
- }
- UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
- //umldoc->slotRemoveUMLObject(assoc);
- UMLObject* objA = assoc->getObject(Uml::RoleType::A);
- UMLObject* objB = assoc->getObject(Uml::RoleType::B);
- UMLCanvasObject *roleAObj = dynamic_cast<UMLCanvasObject*>(objA);
- if (roleAObj) {
- roleAObj->removeAssociationEnd(assoc);
- } else if (objA) {
- DEBUG(DBG_SRC) << name() << ": objA " << objA->name() << " is not a UMLCanvasObject";
- } else
- DEBUG(DBG_SRC) << name() << "): objA is NULL";
- UMLCanvasObject *roleBObj = dynamic_cast<UMLCanvasObject*>(objB);
- if (roleBObj) {
- roleBObj->removeAssociationEnd(assoc);
- } else if (objB) {
- DEBUG(DBG_SRC) << name() << "): objB " << objB->name() << " is not a UMLCanvasObject";
- } else
- DEBUG(DBG_SRC) << name() << "): objB is NULL";
- }
-}
-
-/**
- * Remove all child objects.
- * Just clear list, objects must be deleted where they were created
- * (or we have bad crashes).
- */
-void UMLCanvasObject::removeAllChildObjects()
-{
- if (!m_List.isEmpty()) {
- removeAllAssociationEnds();
- m_List.clear();
- }
-}
-
-/**
- * Returns a name for the new association, operation, template
- * or attribute appended with a number if the default name is
- * taken e.g. new_association, new_association_1 etc.
- *
- * @param type The object type for which to make a name.
- * @param prefix Optional prefix to use for the name.
- * If not given then uniqChildName() will choose the prefix
- * internally based on the object type.
- * @return Unique name string for the ObjectType given.
- */
-QString UMLCanvasObject::uniqChildName(const UMLObject::ObjectType type,
- const QString &prefix /* = QString() */)
-{
- QString currentName;
- currentName = prefix;
- if (currentName.isEmpty()) {
- switch (type) {
- case UMLObject::ot_Association:
- currentName = i18n("new_association");
- break;
- case UMLObject::ot_Attribute:
- currentName = i18n("new_attribute");
- break;
- case UMLObject::ot_Template:
- currentName = i18n("new_template");
- break;
- case UMLObject::ot_Operation:
- currentName = i18n("new_operation");
- break;
- case UMLObject::ot_EnumLiteral:
- currentName = i18n("new_literal");
- break;
- case UMLObject::ot_EntityAttribute:
- currentName = i18n("new_field");
- break;
- case UMLObject::ot_UniqueConstraint:
- currentName = i18n("new_unique_constraint");
- break;
- case UMLObject::ot_ForeignKeyConstraint:
- currentName = i18n("new_fkey_constraint");
- break;
- case UMLObject::ot_CheckConstraint:
- currentName = i18n("new_check_constraint");
- break;
- default:
- uWarning() << "uniqChildName() called for unknown child type " << UMLObject::toString(type);
- return QLatin1String("ERROR_in_UMLCanvasObject_uniqChildName");
- }
- }
-
- QString name = currentName;
- for (int number = 1; findChildObject(name); ++number) {
- name = currentName + QLatin1Char('_') + QString::number(number);
- }
- return name;
-}
-
-/**
- * Find a child object with the given name.
- *
- * @param n The name of the object to find.
- * @param t The type to find (optional.) If not given then
- * any object type will match.
- * @return Pointer to the object found; NULL if none found.
- */
-UMLObject * UMLCanvasObject::findChildObject(const QString &n, UMLObject::ObjectType t)
-{
- const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
- UMLObject *obj = NULL;
- for (UMLObjectListIt oit(m_List); oit.hasNext();) {
- obj = oit.next();
- uIgnoreZeroPointer(obj);
- if (t != UMLObject::ot_UMLObject && obj->baseType() != t)
- continue;
- if (caseSensitive) {
- if (obj->name() == n)
- return obj;
- } else if (obj->name().toLower() == n.toLower()) {
- return obj;
- }
- }
- return NULL;
-}
-
-/**
- * Find an association.
- *
- * @param id The id of the object to find.
- * @param considerAncestors boolean switch to consider ancestors while searching
- * @return Pointer to the object found (NULL if not found.)
- */
-UMLObject* UMLCanvasObject::findChildObjectById(Uml::ID::Type id, bool considerAncestors)
-{
- Q_UNUSED(considerAncestors);
- UMLObject *o = NULL;
- for (UMLObjectListIt oit(m_List); oit.hasNext();) {
- o = oit.next();
- uIgnoreZeroPointer(o);
- if (o->id() == id)
- return o;
- }
- return 0;
-}
-
-/**
- * Overloaded '==' operator
- */
-bool UMLCanvasObject::operator==(const UMLCanvasObject& rhs) const
-{
- if (this == &rhs) {
- return true;
- }
- if (!UMLObject::operator==(rhs)) {
- return false;
- }
- if (m_List.count() != rhs.m_List.count()) {
- return false;
- }
- if (&m_List != &(rhs.m_List)) {
- return false;
- }
- return true;
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLCanvasObject::copyInto(UMLObject *lhs) const
-{
- UMLObject::copyInto(lhs);
-
- // TODO Associations are not copied at the moment. This because
- // the duplicate function (on umlwidgets) do not copy the associations.
- //
- //target->m_List = m_List;
-}
-
-/**
- * Returns the number of associations for the CanvasObject.
- * This is the sum of the aggregations and compositions.
- *
- * @return The number of associations for the Concept.
- */
-int UMLCanvasObject::associations()
-{
- int count = 0;
- UMLObject *obj = NULL;
- for (UMLObjectListIt oit(m_List); oit.hasNext();) {
- obj = oit.next();
- uIgnoreZeroPointer(obj);
- if (obj->baseType() == UMLObject::ot_Association)
- count++;
- }
- return count;
-}
-
-/**
- * Return the list of associations for the CanvasObject.
- *
- * @return The list of associations for the CanvasObject.
- */
-UMLAssociationList UMLCanvasObject::getAssociations()
-{
- UMLAssociationList assocs;
- UMLObject *o = NULL;
- for (UMLObjectListIt oit(m_List); oit.hasNext() ;) {
- o = oit.next();
- uIgnoreZeroPointer(o);
- if (o->baseType() != UMLObject::ot_Association)
- continue;
- UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
- assocs.append(assoc);
- }
- return assocs;
-}
-
-/**
- * Return a list of the superclasses of this concept.
- * TODO: This overlaps with UMLClassifier::findSuperClassConcepts(),
- * see if we can merge the two.
- *
- * @param withRealizations include realizations in the returned list (default=yes)
- * @return The list of superclasses for the concept.
- */
-UMLClassifierList UMLCanvasObject::getSuperClasses(bool withRealizations)
-{
- UMLClassifierList list;
- UMLAssociationList assocs = getAssociations();
- foreach (UMLAssociation* a, assocs) {
- uIgnoreZeroPointer(a);
- if ((a->getAssocType() != Uml::AssociationType::Generalization &&
- a->getAssocType() != Uml::AssociationType::Realization) ||
- (!withRealizations && a->getAssocType() == Uml::AssociationType::Realization) ||
- a->getObjectId(Uml::RoleType::A) != id())
- continue;
- UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::RoleType::B));
- if (c)
- list.append(c);
- else
- DEBUG(DBG_SRC) << name() << ": generalization's other end is not a "
- << "UMLClassifier (id= " << Uml::ID::toString(a->getObjectId(Uml::RoleType::B)) << ")";
- }
- return list;
-}
-
-/**
- * Return a list of the classes that inherit from this concept.
- * TODO: This overlaps with UMLClassifier::findSubClassConcepts(),
- * see if we can merge the two.
- *
- * @return The list of classes inheriting from the concept.
- */
-UMLClassifierList UMLCanvasObject::getSubClasses()
-{
- UMLClassifierList list;
- UMLAssociationList assocs = getAssociations();
- foreach (UMLAssociation* a, assocs) {
- uIgnoreZeroPointer(a);
- if ((a->getAssocType() != Uml::AssociationType::Generalization &&
- a->getAssocType() != Uml::AssociationType::Realization) ||
- a->getObjectId(Uml::RoleType::B) != id())
- continue;
- UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::RoleType::A));
- if (c)
- list.append(c);
- else
- DEBUG(DBG_SRC) << "specialization's other end is not a UMLClassifier"
- << " (id=" << Uml::ID::toString(a->getObjectId(Uml::RoleType::A)) << ")";
- }
- return list;
-}
-
-/**
- * Shorthand for getSpecificAssocs(Uml::at_Realization)
- *
- * @return The list of realizations for the Concept.
- */
-UMLAssociationList UMLCanvasObject::getRealizations()
-{
- return getSpecificAssocs(Uml::AssociationType::Realization);
-}
-
-/**
- * Shorthand for getSpecificAssocs(Uml::at_Aggregation)
- *
- * @return The list of aggregations for the Concept.
- */
-UMLAssociationList UMLCanvasObject::getAggregations()
-{
- return getSpecificAssocs(Uml::AssociationType::Aggregation);
-}
-
-/**
- * Shorthand for getSpecificAssocs(Uml::at_Composition)
- *
- * @return The list of compositions for the Concept.
- */
-UMLAssociationList UMLCanvasObject::getCompositions()
-{
- return getSpecificAssocs(Uml::AssociationType::Composition);
-}
-
-/**
- * Shorthand for getSpecificAssocs(Uml::at_Relationship)
- *
- * @return The list of relationships for the entity.
- */
-UMLAssociationList UMLCanvasObject::getRelationships()
-{
- return getSpecificAssocs(Uml::AssociationType::Relationship);
-}
-
-/**
- * Reimplementation of UMLObject method.
- */
-bool UMLCanvasObject::resolveRef()
-{
- bool overallSuccess = UMLObject::resolveRef();
- for (UMLObjectListIt ait(m_List); ait.hasNext();) {
- UMLObject *obj = ait.next();
- uIgnoreZeroPointer(obj);
- if (! obj->resolveRef()) {
- m_List.removeAll(obj);
- overallSuccess = false;
- }
- }
- return overallSuccess;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlcanvasobject.h umbrello-kf6-15.08.1/umbrello/umlcanvasobject.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlcanvasobject.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlcanvasobject.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,108 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef CANVASOBJECT_H
-#define CANVASOBJECT_H
-
-#include "umlobject.h"
-#include "umlobjectlist.h"
-#include "umlclassifierlist.h"
-#include "umlassociationlist.h"
-
-/**
- * This class contains the non-graphical information required for UMLObjects
- * which appear as moveable widgets on the scene.
- *
- * This class inherits from @ref UMLObject which contains most of the
- * information.
- * It is not instantiated itself, it's just used as a super class for
- * actual model objects.
- *
- * @short Non-graphical information for a UMLCanvasObject.
- * @author Jonathan Riddell
- * @see UMLObject
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLCanvasObject : public UMLObject
-{
- Q_OBJECT
-
-public:
- explicit UMLCanvasObject(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLCanvasObject();
-
- bool operator==(const UMLCanvasObject& rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- // The abstract method UMLObject::clone() is implemented
- // in the classes inheriting from UMLCanvasObject.
-
- bool addAssociationEnd(UMLAssociation* assoc);
-
- bool hasAssociation(UMLAssociation* assoc);
-
- int removeAssociationEnd(UMLAssociation *assoc);
-
- void removeAllAssociationEnds();
-
- int associations();
-
- UMLAssociationList getAssociations();
-
- UMLAssociationList getSpecificAssocs(Uml::AssociationType::Enum assocType);
-
- UMLClassifierList getSuperClasses(bool withRealizations = true);
- UMLClassifierList getSubClasses();
-
- virtual UMLAssociationList getRealizations();
-
- UMLAssociationList getAggregations();
- UMLAssociationList getCompositions();
- UMLAssociationList getRelationships();
-
- virtual UMLObject *findChildObject(const QString &n,
- UMLObject::ObjectType t = UMLObject::ot_UMLObject);
- virtual UMLObject *findChildObjectById(Uml::ID::Type id, bool considerAncestors = false);
-
- virtual QString uniqChildName(const UMLObject::ObjectType type,
- const QString &prefix = QString());
-
- virtual void removeAllChildObjects();
-
- UMLObjectList subordinates() const {
- return m_List;
- }
-
- virtual bool resolveRef();
-
- // The abstract method UMLObject::saveToXMI() is implemented
- // in the classes inheriting from UMLCanvasObject.
-
-protected:
-
- /**
- * List of all the associations in this object.
- * Inheriting classes add more types of objects that are possible in this list;
- * for example, UMLClassifier adds operations, attributes, and templates.
- *
- * @todo Only a pointer to the appropriate assocation end object
- * (UMLRole) should be saved here, not the entire UMLAssociation.
- */
- UMLObjectList m_List;
-
-signals:
-
- void sigAssociationEndAdded(UMLAssociation * assoc);
- void sigAssociationEndRemoved(UMLAssociation * assoc);
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlclassifierlist.h umbrello-kf6-15.08.1/umbrello/umlclassifierlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlclassifierlist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlclassifierlist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,22 +0,0 @@
-/***************************************************************************
- * 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) 2003-2010 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLCLASSIFIERLIST_H
-#define UMLCLASSIFIERLIST_H
-
-#include <QList>
-
-// forward declaration
-class UMLClassifier;
-
-typedef QList<UMLClassifier*> UMLClassifierList;
-typedef QListIterator<UMLClassifier*> UMLClassifierListIt;
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlclassifierlistitemlist.cpp umbrello-kf6-15.08.1/umbrello/umlclassifierlistitemlist.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlclassifierlistitemlist.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlclassifierlistitemlist.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,60 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "umlclassifierlistitemlist.h"
-
-#include "classifierlistitem.h"
-
-#include <KLocalizedString>
-
-UMLClassifierListItemList::UMLClassifierListItemList()
-{
-}
-
-UMLClassifierListItemList::UMLClassifierListItemList(const UMLClassifierListItemList& other)
- : QList<UMLClassifierListItem*>(other)
-{
-}
-
-UMLClassifierListItemList::~UMLClassifierListItemList()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLClassifierListItemList::copyInto(UMLClassifierListItemList *rhs) const
-{
- // Prevent copying to yourself. (Can cause serious injuries)
- if (rhs == this) return;
-
- rhs->clear();
-
- // Suffering from const; we shall not modify our object.
- UMLClassifierListItemList *tmp = new UMLClassifierListItemList(*this);
-
- UMLClassifierListItem *item;
- for (UMLClassifierListItemListIt clit(*tmp); clit.hasNext() ;) {
- item = clit.next();
- rhs->append((UMLClassifierListItem*)item->clone());
- }
- delete tmp;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLClassifierListItemList* UMLClassifierListItemList::clone() const
-{
- UMLClassifierListItemList *clone = new UMLClassifierListItemList();
- copyInto(clone);
- return clone;
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlclassifierlistitemlist.h umbrello-kf6-15.08.1/umbrello/umlclassifierlistitemlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlclassifierlistitemlist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlclassifierlistitemlist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,41 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLCLASSIFIERLISTITEMLIST_H
-#define UMLCLASSIFIERLISTITEMLIST_H
-
-#include <QList>
-
-// forward declaration
-class UMLClassifierListItem;
-
-//typedef QPtrList<UMLClassifierListItem> UMLClassifierListItemList;
-typedef QListIterator<UMLClassifierListItem*> UMLClassifierListItemListIt;
-
-/**
- * This sub-class adds copyInto and clone to the QPtrList<UMLClassifierListItem>
- * base class.
- */
-class UMLClassifierListItemList : public QList<UMLClassifierListItem*>
-{
-public:
-
- UMLClassifierListItemList();
- UMLClassifierListItemList(const UMLClassifierListItemList& other);
-
- virtual ~UMLClassifierListItemList();
-
- virtual void copyInto (UMLClassifierListItemList *rhs) const;
-
- virtual UMLClassifierListItemList* clone() const;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/uml.cpp umbrello-kf6-15.08.1/umbrello/uml.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/uml.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/uml.cpp 2015-10-08 11:48:59.506089026 +0300
@@ -240,15 +240,15 @@
delete m_clipTimer;
delete m_copyTimer;
delete m_commoncodegenpolicy;
- delete m_d;
- delete m_doc;
delete m_imageExporterAll;
- delete m_listView;
delete m_printer;
delete m_policyext;
delete m_pUndoStack;
delete m_refactoringAssist;
delete m_xhtmlGenerator;
+ delete m_listView;
+ delete m_doc;
+ delete m_d;
}
/**
@@ -918,6 +918,8 @@
widget->setLayout(m_layout);
setCentralWidget(widget);
+ m_d->createStereotypesWindow();
+
// create the tree viewer
m_listDock = new QDockWidget(i18n("&Tree View"), this);
m_listDock->setObjectName(QLatin1String("TreeViewDock"));
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umldoc.cpp umbrello-kf6-15.08.1/umbrello/umldoc.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umldoc.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umldoc.cpp 2015-10-08 11:48:59.506089026 +0300
@@ -44,6 +44,7 @@
#include "umlscene.h"
#include "version.h"
#include "worktoolbar.h"
+#include "stereotypesmodel.h"
// kde includes
#include <kio-kf6/job.h>
@@ -113,7 +114,8 @@
m_nViewID(Uml::ID::None),
m_bTypesAreResolved(true),
m_pCurrentRoot(0),
- m_bClosing(false)
+ m_bClosing(false),
+ m_stereotypesModel(new StereotypesModel(&m_stereoList))
{
for (int i = 0; i < Uml::ModelType::N_MODELTYPES; ++i)
m_root[i] = 0;
@@ -190,6 +192,7 @@
}
delete m_pChangeLog;
qDeleteAll(m_stereoList);
+ delete m_stereotypesModel;
}
/**
@@ -402,18 +405,19 @@
// @fixme With advanced code generation enabled, this crashes.
removeAllObjects();
+ // Remove any stereotypes.
+ if (stereotypes().count() > 0) {
+ foreach(UMLStereotype *s, stereotypes()) {
+ m_stereotypesModel->removeStereotype(s);
+ delete s;
+ }
+ m_stereoList.clear();
+ }
+
// Restore the datatype folder, it has been deleted above.
createDatatypeFolder();
// this creates to much items only Logical View should be created
listView->init();
- /* Remove any stereotypes.
- if (m_stereoList.count() > 0) {
- UMLStereotype *s;
- for (UMLStereotypeListIt sit(m_stereoList); (s = sit.current()) != 0; ++sit)
- delete s;
- m_stereoList.clear();
- }
- */
}
m_bClosing = false;
}
@@ -1268,9 +1272,8 @@
*/
void UMLDoc::addStereotype(UMLStereotype *s)
{
- if (! m_stereoList.contains(s)) {
- m_stereoList.append(s);
- }
+ if (m_stereotypesModel->addStereotype(s))
+ emit sigObjectCreated(s);
}
/**
@@ -1279,9 +1282,8 @@
*/
void UMLDoc::removeStereotype(UMLStereotype *s)
{
- if (m_stereoList.contains(s)) {
- m_stereoList.removeAll(s);
- }
+ if (m_stereotypesModel->removeStereotype(s))
+ emit sigObjectRemoved(s);
}
/**
@@ -2444,6 +2446,11 @@
qApp->processEvents(); // give UI events a chance
}
+StereotypesModel *UMLDoc::stereotypesModel()
+{
+ return m_stereotypesModel;
+}
+
/**
* Ensures the XMI file is a valid UML file.
* Currently only checks for metamodel=UML.
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umldoc.h umbrello-kf6-15.08.1/umbrello/umldoc.h
--- umbrello-kf6-15.08.1.orig/umbrello/umldoc.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umldoc.h 2015-10-08 11:48:59.506089026 +0300
@@ -48,6 +48,7 @@
class QPrinter;
class IDChangeLog;
+class StereotypesModel;
class UMLPackage;
class UMLFolder;
class DiagramPrintPage;
@@ -233,6 +234,8 @@
void resolveTypes();
+ StereotypesModel *stereotypesModel();
+
private:
void initSaveTimer();
void createDatatypeFolder();
@@ -308,6 +311,8 @@
*/
bool m_bClosing;
+ StereotypesModel *m_stereotypesModel;
+
public slots:
void slotRemoveUMLObject(UMLObject*o);
void slotAutoSave();
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlentityattributelist.cpp umbrello-kf6-15.08.1/umbrello/umlentityattributelist.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlentityattributelist.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlentityattributelist.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,60 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "umlentityattributelist.h"
-
-#include "entityattribute.h"
-
-#include <KLocalizedString>
-
-UMLEntityAttributeList::UMLEntityAttributeList()
-{
-}
-
-UMLEntityAttributeList::UMLEntityAttributeList(const UMLEntityAttributeList& other)
- : QList<UMLEntityAttribute*>(other)
-{
-}
-
-UMLEntityAttributeList::~UMLEntityAttributeList()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLEntityAttributeList::copyInto(UMLEntityAttributeList* rhs) const
-{
- // Don't copy yourself.
- if (rhs == this) return;
-
- rhs->clear();
-
- // Suffering from const; we shall not modify our object.
- UMLEntityAttributeList* tmp = new UMLEntityAttributeList(*this);
-
- UMLEntityAttribute* item;
- for (UMLEntityAttributeListIt eait(*tmp); eait.hasNext() ;) {
- item = eait.next();
- rhs->append((UMLEntityAttribute*)item->clone());
- }
- delete tmp;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLEntityAttributeList* UMLEntityAttributeList::clone() const
-{
- UMLEntityAttributeList *clone = new UMLEntityAttributeList();
- copyInto(clone);
- return clone;
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlentityattributelist.h umbrello-kf6-15.08.1/umbrello/umlentityattributelist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlentityattributelist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlentityattributelist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,41 +0,0 @@
-/***************************************************************************
- * *
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLENTITYATTRIBUTELIST_H
-#define UMLENTITYATTRIBUTELIST_H
-
-#include <qlist.h>
-#include "entityattribute.h"
-
-//typedef QPtrList<UMLEntityAttribute> UMLEntityAttributeList;
-typedef QListIterator<UMLEntityAttribute*> UMLEntityAttributeListIt;
-
-/**
- * This sub-class adds copyInto and clone to the QPtrList<UMLEntityAttribute>
- * base class.
- */
-class UMLEntityAttributeList : public QList<UMLEntityAttribute*>
-{
-public:
-
- UMLEntityAttributeList();
-
- UMLEntityAttributeList(const UMLEntityAttributeList&);
-
- virtual ~UMLEntityAttributeList();
-
- virtual void copyInto (UMLEntityAttributeList* rhs) const;
-
- virtual UMLEntityAttributeList* clone() const;
-};
-
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlentityconstraintlist.cpp umbrello-kf6-15.08.1/umbrello/umlentityconstraintlist.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlentityconstraintlist.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlentityconstraintlist.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,60 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "umlentityconstraintlist.h"
-
-#include "entityconstraint.h"
-
-#include <KLocalizedString>
-
-UMLEntityConstraintList::UMLEntityConstraintList()
-{
-}
-
-UMLEntityConstraintList::UMLEntityConstraintList(const UMLEntityConstraintList& other)
- : QList<UMLEntityConstraint*>(other)
-{
-}
-
-UMLEntityConstraintList::~UMLEntityConstraintList()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLEntityConstraintList::copyInto(UMLEntityConstraintList* rhs) const
-{
- // Don't copy yourself.
- if (rhs == this) return;
-
- rhs->clear();
-
- // Suffering from const; we shall not modify our object.
- UMLEntityConstraintList* tmp = new UMLEntityConstraintList(*this);
-
- UMLEntityConstraint* item;
- for (UMLEntityConstraintListIt ecit(*tmp); ecit.hasNext() ;) {
- item = ecit.next();
- rhs->append((UMLEntityConstraint*)item->clone());
- }
- delete tmp;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLEntityConstraintList* UMLEntityConstraintList::clone() const
-{
- UMLEntityConstraintList *clone = new UMLEntityConstraintList();
- copyInto(clone);
- return clone;
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlentityconstraintlist.h umbrello-kf6-15.08.1/umbrello/umlentityconstraintlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlentityconstraintlist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlentityconstraintlist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,43 +0,0 @@
-/***************************************************************************
- * *
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLENTITYCONSTRAINTLIST_H
-#define UMLENTITYCONSTRAINTLIST_H
-
-#include <qlist.h>
-
-// forward declaration
-class UMLEntityConstraint;
-
-
-typedef QListIterator<UMLEntityConstraint*> UMLEntityConstraintListIt;
-
-/**
- * This sub-class adds copyInto and clone to the QPtrList<UMLEntityConstraint>
- * base class.
- */
-class UMLEntityConstraintList : public QList<UMLEntityConstraint*>
-{
-public:
-
- UMLEntityConstraintList();
-
- UMLEntityConstraintList(const UMLEntityConstraintList&);
-
- virtual ~UMLEntityConstraintList();
-
- virtual void copyInto (UMLEntityConstraintList* rhs) const;
-
- virtual UMLEntityConstraintList* clone() const;
-};
-
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlentitylist.h umbrello-kf6-15.08.1/umbrello/umlentitylist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlentitylist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlentitylist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,22 +0,0 @@
-/***************************************************************************
- * 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) 2003-2010 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLENTITYLIST_H
-#define UMLENTITYLIST_H
-
-#include <QList>
-
-// forward declaration
-class UMLEntity;
-
-typedef QList<UMLEntity*> UMLEntityList;
-typedef QListIterator<UMLEntity*> UMLEntityListIt;
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlenumliterallist.h umbrello-kf6-15.08.1/umbrello/umlenumliterallist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlenumliterallist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlenumliterallist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,23 +0,0 @@
-/***************************************************************************
- * *
- * 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-2007 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLENUMLITERALLIST_H
-#define UMLENUMLITERALLIST_H
-
-#include <QList>
-
-// forward declaration
-class UMLEnumLiteral;
-
-typedef QList<UMLEnumLiteral*> UMLEnumLiteralList;
-typedef QListIterator<UMLEnumLiteral*> UMLEnumLiteralListIt;
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umllistview.cpp umbrello-kf6-15.08.1/umbrello/umllistview.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umllistview.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umllistview.cpp 2015-10-08 11:48:59.506089026 +0300
@@ -2161,6 +2161,11 @@
QString name = classifier->uniqChildName(objectType);
UMLObject* object = Object_Factory::createChildObject(classifier, objectType, name);
+ if (object == 0) {
+ // creation was cancelled by the user
+ return;
+ }
+
// Handle primary key constraints (mark the unique constraint as PK on
// the parent entity)
if (type == UMLListViewItem::lvt_PrimaryKeyConstraint) {
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/actor.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/actor.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/actor.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/actor.cpp 2015-10-08 11:48:59.506089026 +0300
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "actor.h"
+
+/**
+ * Constructs an Actor.
+ *
+ * @param name The name of the Actor.
+ * @param id The unique id to assign to this Actor.
+ */
+UMLActor::UMLActor(const QString & name, Uml::ID::Type id)
+ : UMLCanvasObject(name, id)
+{
+ init();
+}
+
+/**
+ * Standard destructor.
+ */
+UMLActor::~UMLActor()
+{
+}
+
+/**
+ * Initializes key variables of the class.
+ */
+void UMLActor::init()
+{
+ m_BaseType = UMLObject::ot_Actor;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLActor::clone() const
+{
+ UMLActor *clone = new UMLActor();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+/**
+ * Creates the <UML:Actor> XMI element.
+ */
+void UMLActor::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement actorElement = UMLObject::save(QLatin1String("UML:Actor"), qDoc);
+ qElement.appendChild(actorElement);
+}
+
+/**
+ * Loads the <UML:Actor> XMI element (empty).
+ */
+bool UMLActor::load(QDomElement& element)
+{
+ Q_UNUSED(element);
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/actor.h umbrello-kf6-15.08.1/umbrello/umlmodel/actor.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/actor.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/actor.h 2015-10-08 11:48:59.506089026 +0300
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ACTOR_H
+#define ACTOR_H
+
+#include "umlcanvasobject.h"
+
+/**
+ * This class contains the non-graphical information required for a UML Actor.
+ * This class inherits from @ref UMLCanvasObject which contains most of the
+ * information.
+ * The @ref UMLDoc class creates instances of this type.
+ *
+ * @short Information for a non-graphical UML Actor.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLCanvasObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLActor : public UMLCanvasObject
+{
+ Q_OBJECT
+public:
+ explicit UMLActor(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLActor();
+
+ virtual void init();
+
+ virtual UMLObject* clone() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+protected:
+ bool load(QDomElement & element);
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/artifact.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/artifact.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/artifact.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/artifact.cpp 2015-10-08 11:48:59.506089026 +0300
@@ -0,0 +1,90 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "artifact.h"
+#include "association.h"
+#include "clipboard/idchangelog.h"
+
+#include <KLocalizedString>
+
+/**
+ * Sets up an Artifact.
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+UMLArtifact::UMLArtifact(const QString & name, Uml::ID::Type id)
+ : UMLPackage(name, id),
+ m_drawAsType(defaultDraw)
+{
+ m_BaseType = UMLObject::ot_Artifact;
+}
+
+/**
+ * Standard deconstructor.
+ */
+UMLArtifact::~UMLArtifact()
+{
+}
+
+/**
+ * Make a clone of this object.
+ * @return the cloned object
+ */
+UMLObject* UMLArtifact::clone() const
+{
+ UMLArtifact *clone = new UMLArtifact();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+/**
+ * Creates the UML:Artifact element including its operations,
+ * attributes and templates
+ * @param qDoc the xml document
+ * @param qElement the xml element
+ */
+void UMLArtifact::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement artifactElement = UMLObject::save(QLatin1String("UML:Artifact"), qDoc);
+ artifactElement.setAttribute(QLatin1String("drawas"), m_drawAsType);
+ qElement.appendChild(artifactElement);
+}
+
+/**
+ * Loads the UML:Artifact element including its operations,
+ * attributes and templates.
+ * @param element the xml element to load
+ * @return the success status of the operation
+ */
+bool UMLArtifact::load(QDomElement& element)
+{
+ QString drawAs = element.attribute(QLatin1String("drawas"), QLatin1String("0"));
+ m_drawAsType = (Draw_Type)drawAs.toInt();
+ return true;
+}
+
+/**
+ * Sets m_drawAsType for which method to draw the artifact as.
+ * @param type the draw type
+ */
+void UMLArtifact::setDrawAsType(Draw_Type type)
+{
+ m_drawAsType = type;
+}
+
+/**
+ * Returns the value of m_drawAsType.
+ * @return the value of the draw type attribute
+ */
+UMLArtifact::Draw_Type UMLArtifact::getDrawAsType()
+{
+ return m_drawAsType;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/artifact.h umbrello-kf6-15.08.1/umbrello/umlmodel/artifact.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/artifact.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/artifact.h 2015-10-08 11:48:59.506089026 +0300
@@ -0,0 +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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ARTIFACT_H
+#define ARTIFACT_H
+
+#include "package.h"
+
+/**
+ * This class contains the non-graphical information required for a UML
+ * Artifact.
+ * This class inherits from @ref UMLCanvasObject which contains most of the
+ * information.
+ *
+ * @short Non-graphical information for a Artifact.
+ * @author Jonathan Riddell
+ * @see UMLCanvasObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLArtifact : public UMLPackage
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Artifacts can be drawn using one of several icons.
+ */
+ enum Draw_Type {
+ defaultDraw,
+ file,
+ library,
+ table
+ };
+
+ explicit UMLArtifact(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLArtifact();
+
+ virtual UMLObject* clone() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ void setDrawAsType(Draw_Type type);
+
+ Draw_Type getDrawAsType();
+
+protected:
+
+ bool load(QDomElement & element);
+
+private:
+
+ /**
+ * Artifacts can be drawn as one of several different icons,
+ * this value choosing how to draw them.
+ */
+ Draw_Type m_drawAsType;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/association.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/association.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/association.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/association.cpp 2015-10-08 11:48:59.506089026 +0300
@@ -0,0 +1,742 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "association.h"
+
+// app includes
+#include "debug_utils.h"
+#include "classifier.h"
+#include "classpropertiesdialog.h"
+#include "folder.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlrole.h"
+#include "uniqueid.h"
+#include "model_utils.h"
+#include "cmds.h"
+
+// kde includes
+#include <KLocalizedString>
+
+// qt includes
+#include <QPointer>
+#include <QRegExp>
+
+using namespace Uml;
+
+DEBUG_REGISTER(UMLAssociation)
+
+/**
+ * Sets up an association.
+ * A new unique ID is assigned internally.
+ * @param type The AssociationType::Enum to construct.
+ * @param roleA Pointer to the UMLObject in role A.
+ * @param roleB Pointer to the UMLObject in role B.
+ */
+UMLAssociation::UMLAssociation(Uml::AssociationType::Enum type,
+ UMLObject * roleA, UMLObject * roleB)
+ : UMLObject(QString())
+{
+ init(type, roleA, roleB);
+
+ m_pRole[RoleType::A]->setID(UniqueID::gen());
+ m_pRole[RoleType::B]->setID(UniqueID::gen());
+}
+
+/**
+ * Constructs an association - for loading only.
+ * This constructor should not normally be used as it constructs
+ * an incomplete association (i.e. the role objects are missing.)
+ * @param type The AssociationType::Enum to construct.
+ * Default: Unknown.
+ */
+UMLAssociation::UMLAssociation(Uml::AssociationType::Enum type)
+ : UMLObject(QString(), Uml::ID::Reserved)
+{
+ init(type, NULL, NULL);
+}
+
+/**
+ * Standard destructor.
+ */
+UMLAssociation::~UMLAssociation()
+{
+ if (m_pRole[RoleType::A] == NULL) {
+ uError() << "UMLAssociation destructor: m_pRole[A] is NULL already";
+ } else {
+ delete m_pRole[RoleType::A];
+ m_pRole[RoleType::A] = NULL;
+ }
+ if (m_pRole[RoleType::B] == NULL) {
+ uError() << "UMLAssociation destructor: m_pRole[B] is NULL already";
+ } else {
+ delete m_pRole[RoleType::B];
+ m_pRole[RoleType::B] = NULL;
+ }
+}
+
+/**
+ * Overloaded '==' operator
+ */
+bool UMLAssociation::operator==(const UMLAssociation &rhs) const
+{
+ if (this == &rhs) {
+ return true;
+ }
+ return (UMLObject::operator== (rhs) &&
+ m_AssocType == rhs.m_AssocType &&
+ m_Name == rhs.m_Name &&
+ m_pRole[RoleType::A] == rhs.m_pRole[RoleType::A] &&
+ m_pRole[RoleType::B] == rhs.m_pRole[RoleType::B]);
+}
+
+/**
+ * Returns the AssociationType::Enum of the UMLAssociation.
+ * @return The AssociationType::Enum of the UMLAssociation.
+ */
+Uml::AssociationType::Enum UMLAssociation::getAssocType() const
+{
+ return m_AssocType;
+}
+
+/**
+ * Returns a String representation of this UMLAssociation.
+ */
+QString UMLAssociation::toString() const
+{
+ QString string;
+ if(m_pRole[RoleType::A])
+ {
+ string += m_pRole[RoleType::A]->object()->name();
+ string += QLatin1Char(':');
+ string += m_pRole[RoleType::A]->name();
+ }
+ string += QLatin1Char(':') + Uml::AssociationType::toStringI18n(m_AssocType) + QLatin1Char(':');
+ if(m_pRole[RoleType::B])
+ {
+ string += m_pRole[RoleType::B]->object()->name();
+ string += QLatin1Char(':');
+ string += m_pRole[RoleType::B]->name();
+ }
+ return string;
+}
+
+/**
+ * Resolve types. Required when dealing with foreign XMI files.
+ * Needs to be called after all UML objects are loaded from file.
+ * Overrides the method from UMLObject.
+ * Calls resolveRef() for each role.
+ * @return True for success.
+ */
+bool UMLAssociation::resolveRef()
+{
+ bool successA = getUMLRole(RoleType::A)->resolveRef();
+ bool successB = getUMLRole(RoleType::B)->resolveRef();
+ if (successA && successB) {
+ UMLObject *objA = getUMLRole(RoleType::A)->object();
+ UMLObject *objB = getUMLRole(RoleType::B)->object();
+ // Check if need to change the assoc type to Realization
+ if (isRealization(objA, objB)) {
+ m_AssocType = Uml::AssociationType::Realization;
+ }
+ m_pUMLPackage->addAssocToConcepts(this);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Creates the <UML:Generalization> or <UML:Association> XMI element
+ * including its role objects.
+ */
+void UMLAssociation::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ if (m_AssocType == Uml::AssociationType::Generalization) {
+ QDomElement assocElement = UMLObject::save(QLatin1String("UML:Generalization"), qDoc);
+ assocElement.setAttribute(QLatin1String("discriminator"), QString());
+ assocElement.setAttribute(QLatin1String("child"), Uml::ID::toString(getObjectId(RoleType::A)));
+ assocElement.setAttribute(QLatin1String("parent"), Uml::ID::toString(getObjectId(RoleType::B)));
+ qElement.appendChild(assocElement);
+ return;
+ }
+ if (m_AssocType == Uml::AssociationType::Realization) {
+ QDomElement assocElement = UMLObject::save(QLatin1String("UML:Abstraction"), qDoc);
+ assocElement.setAttribute(QLatin1String("client"), Uml::ID::toString(getObjectId(RoleType::A)));
+ assocElement.setAttribute(QLatin1String("supplier"), Uml::ID::toString(getObjectId(RoleType::B)));
+ qElement.appendChild(assocElement);
+ return;
+ }
+ if (m_AssocType == Uml::AssociationType::Dependency) {
+ QDomElement assocElement = UMLObject::save(QLatin1String("UML:Dependency"), qDoc);
+ assocElement.setAttribute(QLatin1String("client"), Uml::ID::toString(getObjectId(RoleType::A)));
+ assocElement.setAttribute(QLatin1String("supplier"), Uml::ID::toString(getObjectId(RoleType::B)));
+ qElement.appendChild(assocElement);
+ return;
+ }
+ if (m_AssocType == Uml::AssociationType::Child2Category) {
+ QDomElement assocElement = UMLObject::save(QLatin1String("UML:Child2Category"), qDoc);
+ assocElement.setAttribute(QLatin1String("client"), Uml::ID::toString(getObjectId(RoleType::A)));
+ assocElement.setAttribute(QLatin1String("supplier"), Uml::ID::toString(getObjectId(RoleType::B)));
+ qElement.appendChild(assocElement);
+ return;
+ }
+ if (m_AssocType == Uml::AssociationType::Category2Parent) {
+ QDomElement assocElement = UMLObject::save(QLatin1String("UML:Category2Parent"), qDoc);
+ assocElement.setAttribute(QLatin1String("client"), Uml::ID::toString(getObjectId(RoleType::A)));
+ assocElement.setAttribute(QLatin1String("supplier"), Uml::ID::toString(getObjectId(RoleType::B)));
+ qElement.appendChild(assocElement);
+ return;
+ }
+
+ QDomElement associationElement = UMLObject::save(QLatin1String("UML:Association"), qDoc);
+ QDomElement connElement = qDoc.createElement(QLatin1String("UML:Association.connection"));
+ getUMLRole(RoleType::A)->saveToXMI (qDoc, connElement);
+ getUMLRole(RoleType::B)->saveToXMI (qDoc, connElement);
+ associationElement.appendChild (connElement);
+ qElement.appendChild(associationElement);
+}
+
+bool UMLAssociation::showPropertiesDialog(QWidget *parent)
+{
+ QPointer<ClassPropertiesDialog> dlg = new ClassPropertiesDialog(parent, this, true);
+ bool modified = false;
+ if (dlg->exec()) {
+ modified = true;
+ }
+ dlg->close();
+ delete dlg;
+ return modified;
+}
+
+/**
+ * Creates the <UML:Generalization> or <UML:Association> XMI element
+ * including its role objects.
+ */
+bool UMLAssociation::load(QDomElement & element)
+{
+ if (id() == Uml::ID::None)
+ return false; // old style XMI file. No real info in this association.
+
+ UMLDoc * doc = UMLApp::app()->document();
+ UMLObject * obj[2] = { NULL, NULL };
+ if (m_AssocType == Uml::AssociationType::Generalization ||
+ m_AssocType == Uml::AssociationType::Realization ||
+ m_AssocType == Uml::AssociationType::Dependency ||
+ m_AssocType == Uml::AssociationType::Child2Category ||
+ m_AssocType == Uml::AssociationType::Category2Parent) {
+ QString general = element.attribute(QLatin1String("general"));
+ if (!general.isEmpty()) {
+ UMLClassifier *owningClassifier = dynamic_cast<UMLClassifier*>(m_pUMLPackage);
+ if (owningClassifier == NULL){
+ uWarning() << "Cannot load UML2 generalization: m_pUMLPackage is expected "
+ << "to be the owning classifier (=client)";
+ return false;
+ }
+ m_pRole[RoleType::A]->setObject(owningClassifier);
+ m_pRole[RoleType::B]->setSecondaryId(general); // defer resolution to resolveRef()
+ owningClassifier->addAssociationEnd(this);
+ m_pUMLPackage = m_pUMLPackage->umlPackage(); // reparent
+ m_pUMLPackage->addObject(this);
+ return true;
+ }
+ for (unsigned r = RoleType::A; r <= RoleType::B; ++r) {
+ const QString fetch = (m_AssocType == Uml::AssociationType::Generalization ?
+ r == RoleType::A ? QLatin1String("child") : QLatin1String("parent")
+ : r == RoleType::A ? QLatin1String("client") : QLatin1String("supplier"));
+ QString roleIdStr = element.attribute(fetch);
+ if (roleIdStr.isEmpty()) {
+ // Might be given as a child node instead - see below.
+ continue;
+ }
+
+ // set umlobject of role if possible (else defer resolution)
+ obj[r] = doc->findObjectById(Uml::ID::fromString(roleIdStr));
+ Uml::RoleType::Enum role = Uml::RoleType::fromInt(r);
+ if (obj[r] == NULL) {
+ m_pRole[role]->setSecondaryId(roleIdStr); // defer to resolveRef()
+ } else {
+ m_pRole[role]->setObject(obj[r]);
+ if (m_pUMLPackage == NULL) {
+ Uml::ModelType::Enum mt = Model_Utils::convert_OT_MT(obj[r]->baseType());
+ m_pUMLPackage = doc->rootFolder(mt);
+ DEBUG(DBG_SRC) << "assoctype " << m_AssocType
+ << ": setting model type " << Uml::ModelType::toString(mt);
+ }
+ }
+ }
+ if (obj[RoleType::A] == NULL || obj[RoleType::B] == NULL) {
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (Model_Utils::isCommonXMIAttribute(tag))
+ continue;
+ // Permitted tag names:
+ // roleA: "child" "subtype" "client"
+ // roleB: "parent" "supertype" "supplier"
+ QString idStr = tempElement.attribute(QLatin1String("xmi.id"));
+ if (idStr.isEmpty())
+ idStr = tempElement.attribute(QLatin1String("xmi.idref"));
+ if (idStr.isEmpty()) {
+ QDomNode inner = node.firstChild();
+ QDomElement tmpElem = inner.toElement();
+ idStr = tmpElem.attribute(QLatin1String("xmi.id"));
+ if (idStr.isEmpty())
+ idStr = tmpElem.attribute(QLatin1String("xmi.idref"));
+ }
+ if (idStr.isEmpty()) {
+ uError() << "type " << m_AssocType
+ << ", id " << Uml::ID::toString(id()) << ": "
+ << "xmi id not given for " << tag;
+ continue;
+ }
+ // Since we know for sure that we're dealing with a non
+ // umbrello-kf6 file, use deferred resolution unconditionally.
+ if (UMLDoc::tagEq(tag, QLatin1String("child")) ||
+ UMLDoc::tagEq(tag, QLatin1String("subtype")) ||
+ UMLDoc::tagEq(tag, QLatin1String("client"))) {
+ getUMLRole(RoleType::A)->setSecondaryId(idStr);
+ } else {
+ getUMLRole(RoleType::B)->setSecondaryId(idStr);
+ }
+ }
+ }
+
+ // it is a realization if either endpoint is an interface
+ if (isRealization(obj[RoleType::A], obj[RoleType::B])) {
+ m_AssocType = Uml::AssociationType::Realization;
+ }
+ return true;
+ }
+
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ // uml13.dtd compliant format (new style)
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (Model_Utils::isCommonXMIAttribute(tag))
+ continue;
+ if (!UMLDoc::tagEq(tag, QLatin1String("Association.connection")) &&
+ !UMLDoc::tagEq(tag, QLatin1String("Association.end")) && // Embarcadero's Describe
+ !UMLDoc::tagEq(tag, QLatin1String("Namespace.ownedElement")) &&
+ !UMLDoc::tagEq(tag, QLatin1String("Namespace.contents"))) {
+ uWarning() << "unknown child node " << tag;
+ continue;
+ }
+ // Load role A.
+ QDomNode nodeA = tempElement.firstChild();
+ while (nodeA.isComment())
+ nodeA = nodeA.nextSibling();
+ tempElement = nodeA.toElement();
+ if (tempElement.isNull()) {
+ uWarning() << "UML:Association : element (A) is Null";
+ return false;
+ }
+ tag = tempElement.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("NavigableEnd"))) { // Embarcadero's Describe
+ m_AssocType = Uml::AssociationType::UniAssociation;
+ } else if (!UMLDoc::tagEq(tag, QLatin1String("AssociationEndRole")) &&
+ !UMLDoc::tagEq(tag, QLatin1String("AssociationEnd"))) {
+ uWarning() << "unknown child (A) tag " << tag;
+ return false;
+ }
+ if (! getUMLRole(RoleType::A)->loadFromXMI(tempElement))
+ return false;
+ // Load role B.
+ QDomNode nodeB = nodeA.nextSibling();
+ while (nodeB.isComment())
+ nodeB = nodeB.nextSibling();
+ tempElement = nodeB.toElement();
+ if (tempElement.isNull()) {
+ uWarning() << "UML:Association : element (B) is Null";
+ return false;
+ }
+ tag = tempElement.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("NavigableEnd"))) { // Embarcadero's Describe
+ m_AssocType = Uml::AssociationType::UniAssociation;
+ } else if (!UMLDoc::tagEq(tag, QLatin1String("AssociationEndRole")) &&
+ !UMLDoc::tagEq(tag, QLatin1String("AssociationEnd"))) {
+ uWarning() << "unknown child (B) tag " << tag;
+ return false;
+ }
+ if (! getUMLRole(RoleType::B)->loadFromXMI(tempElement))
+ return false;
+
+ if (m_pUMLPackage == NULL) {
+ Uml::ModelType::Enum mt = Model_Utils::convert_OT_MT(getObject(RoleType::B)->baseType());
+ m_pUMLPackage = doc->rootFolder(mt);
+ DEBUG(DBG_SRC) << "setting model type " << Uml::ModelType::toString(mt);
+ }
+
+ // setting the association type:
+ //
+ // In the old days, we could just record this on the association,
+ // and be done with it. But thats not how the UML13.dtd does things.
+ // As a result, we are checking roleA for information about the
+ // parent association (!) which by this point in the parse, should
+ // be set. However, the information that the roles are allowed to have
+ // is not complete, so we need to finish the analysis here.
+
+ // find self-associations
+ if (m_AssocType == Uml::AssociationType::Association && getObjectId(RoleType::A) == getObjectId(RoleType::B))
+ m_AssocType = Uml::AssociationType::Association_Self;
+
+ // fall-back default type
+ if (m_AssocType == Uml::AssociationType::Unknown) {
+ m_AssocType = Uml::AssociationType::Association;
+ }
+
+ return true;
+ }
+
+ // From here on it's old-style stuff.
+ QString assocTypeStr = element.attribute(QLatin1String("assoctype"), QLatin1String("-1"));
+ Uml::AssociationType::Enum assocType = Uml::AssociationType::Unknown;
+ if (assocTypeStr[0] >= QLatin1Char('a') && assocTypeStr[0] <= QLatin1Char('z')) {
+ // In an earlier version, the natural assoctype names were saved.
+ const char *assocTypeString[] = {
+ "generalization", // Uml::AssociationType::Generalization
+ "aggregation", // Uml::AssociationType::Aggregation
+ "dependency", // Uml::AssociationType::Dependency
+ "association", // Uml::AssociationType::Association
+ "associationself", // Uml::AssociationType::Association_Self
+ "collmessage", // Uml::AssociationType::Coll_Message
+ "seqmessage", // Uml::AssociationType::Seq_Message
+ "collmessageself", // Uml::AssociationType::Coll_Message_Self
+ "seqmessageself", // Uml::AssociationType::Seq_Message_Self
+ "implementation", // Uml::AssociationType::Implementation
+ "composition", // Uml::AssociationType::Composition
+ "realization", // Uml::AssociationType::Realization
+ "uniassociation", // Uml::AssociationType::UniAssociation
+ "anchor", // Uml::AssociationType::Anchor
+ "state", // Uml::AssociationType::State
+ "activity", // Uml::AssociationType::Activity
+ "exception", // Uml::AssociationType::Exception
+ "category2parent" // Uml::AssociationType::Category2Parent
+ "child2category" // Uml::AssociationType::Child2Category
+ "relationship" // Uml::AssociationType::Relationship
+ };
+ const int arraySize = sizeof(assocTypeString) / sizeof(char*);
+ DEBUG(DBG_SRC) << "AssociationType string array size = " << arraySize;
+
+ int index;
+ for (index = 0; index < arraySize; ++index)
+ if (assocTypeStr == QString::fromLatin1(assocTypeString[index]))
+ break;
+ if (index < arraySize)
+ assocType = Uml::AssociationType::fromInt(index);
+ } else {
+ int assocTypeNum = assocTypeStr.toInt();
+ if (assocTypeNum < (int)Uml::AssociationType::Generalization || // first enum
+ assocTypeNum >= (int)Uml::AssociationType::Reserved) { // last enum
+ uWarning() << "bad assoctype of UML:AssociationType::Enum " << Uml::ID::toString(id());
+ return false;
+ }
+ assocType = Uml::AssociationType::fromInt(assocTypeNum);
+ }
+ setAssociationType(assocType);
+
+ Uml::ID::Type roleAObjID = Uml::ID::fromString(element.attribute(QLatin1String("rolea"), QLatin1String("-1")));
+ Uml::ID::Type roleBObjID = Uml::ID::fromString(element.attribute(QLatin1String("roleb"), QLatin1String("-1")));
+ if (assocType == Uml::AssociationType::Aggregation ||
+ assocType == Uml::AssociationType::Composition) {
+ // Flip roles to compensate for changed diamond logic in AssociationLine.
+ // For further explanations see AssociationWidget::loadFromXMI.
+ Uml::ID::Type tmp = roleAObjID;
+ roleAObjID = roleBObjID;
+ roleBObjID = tmp;
+ }
+
+ UMLObject * objA = doc->findObjectById(roleAObjID);
+ UMLObject * objB = doc->findObjectById(roleBObjID);
+
+ if(objA)
+ getUMLRole(RoleType::A)->setObject(objA);
+ else
+ return false;
+
+ if(objB)
+ getUMLRole(RoleType::B)->setObject(objB);
+ else
+ return false;
+
+ setMultiplicity(element.attribute(QLatin1String("multia")), RoleType::A);
+ setMultiplicity(element.attribute(QLatin1String("multib")), RoleType::B);
+
+ setRoleName(element.attribute(QLatin1String("namea")), RoleType::A);
+ setRoleName(element.attribute(QLatin1String("nameb")), RoleType::B);
+
+ setRoleDoc(element.attribute(QLatin1String("doca")), RoleType::A);
+ setRoleDoc(element.attribute(QLatin1String("docb")), RoleType::B);
+
+ // Visibility defaults to Public if it cant set it here..
+ QString visibilityA = element.attribute(QLatin1String("visibilitya"), QLatin1String("0"));
+ QString visibilityB = element.attribute(QLatin1String("visibilityb"), QLatin1String("0"));
+ int vis = visibilityA.toInt();
+ if (vis >= 200) // bkwd compat.
+ vis -= 200;
+ setVisibility((Uml::Visibility::Enum)vis, RoleType::A);
+ vis = visibilityB.toInt();
+ if (vis >= 200) // bkwd compat.
+ vis -= 200;
+ setVisibility((Uml::Visibility::Enum)vis, RoleType::B);
+
+ // Changeability defaults to Changeable if it cant set it here..
+ QString changeabilityA = element.attribute(QLatin1String("changeabilitya"), QLatin1String("0"));
+ QString changeabilityB = element.attribute(QLatin1String("changeabilityb"), QLatin1String("0"));
+ if (changeabilityA.toInt() > 0)
+ setChangeability(Uml::Changeability::fromInt(changeabilityA.toInt()), RoleType::A);
+ if (changeabilityB.toInt() > 0)
+ setChangeability(Uml::Changeability::fromInt(changeabilityB.toInt()), RoleType::B);
+
+ return true;
+}
+
+/**
+ * Returns the UMLObject assigned to the given role.
+ * @return Pointer to the UMLObject in the given role.
+ */
+UMLObject* UMLAssociation::getObject(Uml::RoleType::Enum role) const
+{
+ if (m_pRole[role] == NULL)
+ return NULL;
+ return m_pRole[role]->object();
+}
+
+/**
+ * Returns the ID of the UMLObject assigned to the given role.
+ * Shorthand for getObject(role)->ID().
+ * @return ID of the UMLObject in the given role.
+ */
+Uml::ID::Type UMLAssociation::getObjectId(Uml::RoleType::Enum role) const
+{
+ UMLRole *roleObj = m_pRole[role];
+ if (roleObj == NULL)
+ return Uml::ID::None;
+ UMLObject *o = roleObj->object();
+ if (o == NULL) {
+ QString auxID = roleObj->secondaryId();
+ if (auxID.isEmpty()) {
+ uError() << "role " << role << ": getObject returns NULL";
+ return Uml::ID::None;
+ } else {
+ DEBUG(DBG_SRC) << "role " << role << ": using secondary ID " << auxID;
+ return Uml::ID::fromString(auxID);
+ }
+ }
+ return o->id();
+}
+
+/**
+ * Returns the ID of the UMLObject assigned to the given role.
+ * CURRENTLY UNUSED.
+ * @return ID of the UMLObject of the given role.
+ */
+Uml::ID::Type UMLAssociation::getRoleId(RoleType::Enum role) const
+{
+ return m_pRole[role]->id();
+}
+
+/**
+ * Returns the changeability.
+ */
+Uml::Changeability::Enum UMLAssociation::changeability(Uml::RoleType::Enum role) const
+{
+ return m_pRole[role]->changeability();
+}
+
+/**
+ * Returns the Visibility of the given role.
+ * @return Visibility of the given role.
+ */
+Uml::Visibility::Enum UMLAssociation::visibility(Uml::RoleType::Enum role) const
+{
+ return m_pRole[role]->visibility();
+}
+
+/**
+ * Returns the multiplicity assigned to the given role.
+ * @return The multiplicity assigned to the given role.
+ */
+QString UMLAssociation::getMultiplicity(Uml::RoleType::Enum role) const
+{
+ return m_pRole[role]->multiplicity();
+}
+
+/**
+ * Returns the name assigned to the role A.
+ * @return The name assigned to the given role.
+ */
+QString UMLAssociation::getRoleName(Uml::RoleType::Enum role) const
+{
+ return m_pRole[role]->name();
+}
+
+/**
+ * Returns the documentation assigned to the given role.
+ * @return Documentation text of given role.
+ */
+QString UMLAssociation::getRoleDoc(Uml::RoleType::Enum role) const
+{
+ return m_pRole[role]->doc();
+}
+
+/**
+ * Get the underlying UMLRole object for the given role.
+ * @return Pointer to the UMLRole object for the given role.
+ */
+UMLRole * UMLAssociation::getUMLRole(Uml::RoleType::Enum role) const
+{
+ return m_pRole[role];
+}
+
+/**
+ * Set the attribute m_bOldLoadMode.
+ * @param value the new value to set
+ */
+void UMLAssociation::setOldLoadMode(bool value /* = true */)
+{
+ m_bOldLoadMode = value;
+}
+
+/**
+ * Return the backward compatibility flag for loading files.
+ */
+bool UMLAssociation::getOldLoadMode() const
+{
+ return m_bOldLoadMode;
+}
+
+/**
+ * Sets the assocType of the UMLAssociation.
+ * @param assocType The AssociationType::Enum of the UMLAssociation.
+ */
+void UMLAssociation::setAssociationType(Uml::AssociationType::Enum assocType)
+{
+ m_AssocType = assocType;
+ if (m_AssocType == Uml::AssociationType::UniAssociation)
+ {
+ // In this case we need to auto-set the multiplicity/rolenames
+ // of the roles
+#ifdef VERBOSE_DEBUGGING
+ DEBUG(DBG_SRC) << " A new uni-association has been created.";
+#endif
+ }
+ UMLObject::emitModified();
+}
+
+/**
+ * Sets the UMLObject playing the given role in the association.
+ * @param obj Pointer to the UMLObject of the given role.
+ * @param role The Uml::RoleType::Enum played by the association
+ */
+void UMLAssociation::setObject(UMLObject *obj, Uml::RoleType::Enum role)
+{
+ m_pRole[role]->setObject(obj);
+}
+
+/**
+ * Sets the visibility of the given role of the UMLAssociation.
+ * @param value Visibility of role.
+ * @param role The Uml::RoleType::Enum to which the visibility is being applied
+ */
+void UMLAssociation::setVisibility(Visibility::Enum value, Uml::RoleType::Enum role)
+{
+ m_pRole[role]->setVisibility(value);
+}
+
+/**
+ * Sets the changeability of the given role of the UMLAssociation.
+ * @param value Changeability_Type of the given role.
+ * @param role The Uml::RoleType::Enum to which the changeability is being set
+ */
+void UMLAssociation::setChangeability(Uml::Changeability::Enum value, Uml::RoleType::Enum role)
+{
+ m_pRole[role]->setChangeability(value);
+}
+
+/**
+ * Sets the multiplicity of the given role of the UMLAssociation.
+ * @param multi The multiplicity of the given role.
+ * @param role The Uml::RoleType::Enum to which the multiplicity is being applied
+ */
+void UMLAssociation::setMultiplicity(const QString &multi, Uml::RoleType::Enum role)
+{
+ if (m_pRole[role]->multiplicity() != multi) {
+ UMLApp::app()->executeCommand(new CmdChangeMultiplicity(m_pRole[role], multi));
+ }
+}
+
+/**
+ * Sets the name of the given role of the UMLAssociation.
+ * @param roleName The name to set for the given role.
+ * @param role The Uml::RoleType::Enum for which to set the name.
+ */
+void UMLAssociation::setRoleName(const QString &roleName, Uml::RoleType::Enum role)
+{
+ m_pRole[role]->setName(roleName);
+}
+
+/**
+ * Sets the documentation on the given role in the association.
+ * @param doc The string with the documentation.
+ * @param role The Uml::RoleType::Enum to which the documentation is being applied
+ */
+void UMLAssociation::setRoleDoc(const QString &doc, Uml::RoleType::Enum role)
+{
+ m_pRole[role]->setDoc(doc);
+}
+
+/**
+ * When the association type is "Generalization" and at least one of the
+ * given objects an interface, then it is a "Realization".
+ * @param objA UML object as role A
+ * @param objB UML object as role B
+ * @return flag whether association is a realization
+ */
+bool UMLAssociation::isRealization(UMLObject* objA, UMLObject* objB) const
+{
+ bool aIsInterface = false;
+ if (objA && (objA->baseType() == UMLObject::ot_Interface)) {
+ aIsInterface = true;
+ }
+ bool bIsInterface = false;
+ if (objB && (objB->baseType() == UMLObject::ot_Interface)) {
+ bIsInterface = true;
+ }
+ return (m_AssocType == Uml::AssociationType::Generalization) &&
+ (aIsInterface || bIsInterface);
+}
+
+/**
+ * Common initializations at construction time.
+ * @param type The AssociationType::Enum to represent.
+ * @param roleAObj Pointer to the role A UMLObject.
+ * @param roleBObj Pointer to the role B UMLObject.
+ */
+void UMLAssociation::init(Uml::AssociationType::Enum type, UMLObject *roleAObj, UMLObject *roleBObj)
+{
+ m_AssocType = type;
+ m_BaseType = ot_Association;
+ m_Name = QString();
+ m_bOldLoadMode = false;
+ nrof_parent_widgets = -1;
+ if (!UMLApp::app()->document()->loading()) {
+ m_pUMLPackage = UMLApp::app()->document()->currentRoot();
+ }
+ m_pRole[RoleType::A] = new UMLRole (this, roleAObj, RoleType::A);
+ m_pRole[RoleType::B] = new UMLRole (this, roleBObj, RoleType::B);
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/association.h umbrello-kf6-15.08.1/umbrello/umlmodel/association.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/association.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/association.h 2015-10-08 11:48:59.506089026 +0300
@@ -0,0 +1,102 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ASSOCIATION_H
+#define ASSOCIATION_H
+
+#include "basictypes.h"
+#include "umlobject.h"
+
+#include <QDomDocument>
+#include <QDomElement>
+
+class UMLRole;
+
+/**
+ * This class contains the non-graphic representation of an association.
+ * An association can be a generalization, realization, simple association,
+ * directed association, aggregation, or composition.
+ *
+ * @short Sets up association information.
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * @see UMLObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLAssociation : public UMLObject
+{
+ Q_OBJECT
+ friend class AssociationWidget;
+
+public:
+ UMLAssociation(Uml::AssociationType::Enum type, UMLObject *roleA, UMLObject *roleB);
+ explicit UMLAssociation(Uml::AssociationType::Enum type = Uml::AssociationType::Unknown);
+
+ virtual ~UMLAssociation();
+
+ bool operator==(const UMLAssociation &rhs) const;
+
+ QString toString() const;
+
+ UMLRole * getUMLRole(Uml::RoleType::Enum role) const;
+ Uml::ID::Type getObjectId(Uml::RoleType::Enum role) const;
+ Uml::ID::Type getRoleId(Uml::RoleType::Enum role) const;
+
+ void setAssociationType(Uml::AssociationType::Enum assocType);
+ Uml::AssociationType::Enum getAssocType() const;
+
+ void setObject(UMLObject *obj, Uml::RoleType::Enum role);
+ UMLObject* getObject(Uml::RoleType::Enum role) const;
+
+ void setVisibility(Uml::Visibility::Enum value, Uml::RoleType::Enum role);
+ Uml::Visibility::Enum visibility(Uml::RoleType::Enum role) const;
+
+ void setChangeability(Uml::Changeability::Enum value, Uml::RoleType::Enum role);
+ Uml::Changeability::Enum changeability(Uml::RoleType::Enum role) const;
+
+ void setMultiplicity(const QString &multi, Uml::RoleType::Enum role);
+ QString getMultiplicity(Uml::RoleType::Enum role) const;
+
+ void setRoleName(const QString &roleName, Uml::RoleType::Enum role);
+ QString getRoleName(Uml::RoleType::Enum role) const;
+
+ void setRoleDoc(const QString &doc, Uml::RoleType::Enum role);
+ QString getRoleDoc(Uml::RoleType::Enum role) const;
+
+ void setOldLoadMode(bool value = true);
+ bool getOldLoadMode() const;
+
+ virtual UMLObject* clone() const { return NULL; }
+
+ virtual bool resolveRef();
+
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ virtual bool showPropertiesDialog(QWidget *parent = 0);
+
+protected:
+
+ bool load(QDomElement& element);
+
+ // keep track of number of parent widgets
+ int nrof_parent_widgets;
+
+ void init(Uml::AssociationType::Enum type, UMLObject *roleAObj, UMLObject *roleBObj);
+
+ UMLRole * m_pRole[2];
+ Uml::AssociationType::Enum m_AssocType;
+ QString m_Name;
+ bool m_bOldLoadMode;
+
+private:
+
+ bool isRealization(UMLObject* objA, UMLObject* objB) const;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/attribute.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/attribute.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/attribute.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/attribute.cpp 2015-10-08 11:48:59.506089026 +0300
@@ -0,0 +1,424 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "attribute.h"
+
+// app includes
+#include "debug_utils.h"
+#include "classifier.h"
+#include "operation.h"
+#include "umlobject.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "folder.h"
+#include "umlattributedialog.h"
+#include "object_factory.h"
+
+/**
+ * Sets up an attribute.
+ *
+ * @param parent The parent of this UMLAttribute.
+ * @param name The name of this UMLAttribute.
+ * @param id The unique id given to this UMLAttribute.
+ * @param s The visibility of the UMLAttribute.
+ * @param type The type of this UMLAttribute.
+ * @param iv The initial value of the attribute.
+ */
+UMLAttribute::UMLAttribute(UMLObject *parent,
+ const QString& name, Uml::ID::Type id,
+ Uml::Visibility::Enum s,
+ UMLObject *type, const QString& iv)
+ : UMLClassifierListItem(parent, name, id)
+{
+ m_InitialValue = iv;
+ m_BaseType = UMLObject::ot_Attribute;
+ m_visibility = s;
+ m_ParmKind = Uml::ParameterDirection::In;
+ /* CHECK: Do we need this:
+ if (type == NULL) {
+ type = Object_Factory::createUMLObject(Uml::ot_Datatype, "undef");
+ }
+ */
+ m_pSecondary = type;
+}
+
+/**
+ * Sets up an attribute.
+ *
+ * @param parent The parent of this UMLAttribute.
+ */
+UMLAttribute::UMLAttribute(UMLObject *parent) : UMLClassifierListItem(parent)
+{
+ m_BaseType = UMLObject::ot_Attribute;
+ m_visibility = Uml::Visibility::Private;
+ m_ParmKind = Uml::ParameterDirection::In;
+}
+
+/**
+ * Destructor.
+ */
+UMLAttribute::~UMLAttribute()
+{
+}
+
+/**
+ * Reimplementation of method from UMLObject is required as
+ * an extra signal, attributeChanged(), is emitted.
+ */
+void UMLAttribute::setName(const QString &name)
+{
+ m_name = name;
+ emit attributeChanged();
+ UMLObject::emitModified();
+}
+
+/**
+ * Reimplementation of method from UMLObject is required as
+ * an extra signal, attributeChanged(), is emitted.
+ */
+void UMLAttribute::setVisibility(Uml::Visibility::Enum s)
+{
+ m_visibility = s;
+ emit attributeChanged();
+ UMLObject::emitModified();
+}
+
+/**
+ * Returns The initial value of the UMLAttribute.
+ *
+ * @return The initial value of the Atrtibute.
+ */
+QString UMLAttribute::getInitialValue() const
+{
+ return m_InitialValue;
+}
+
+/**
+ * Sets the initial value of the UMLAttribute.
+ *
+ * @param iv The initial value of the UMLAttribute.
+ */
+void UMLAttribute::setInitialValue(const QString &iv)
+{
+ if(m_InitialValue != iv) {
+ m_InitialValue = iv;
+ UMLObject::emitModified();
+ }
+}
+
+void UMLAttribute::setParmKind (Uml::ParameterDirection::Enum pk)
+{
+ m_ParmKind = pk;
+}
+
+Uml::ParameterDirection::Enum UMLAttribute::getParmKind() const
+{
+ return m_ParmKind;
+}
+
+/**
+ * Returns a string representation of the UMLAttribute.
+ *
+ * @param sig If true will show the attribute type and initial value.
+ * @return Returns a string representation of the UMLAttribute.
+ */
+QString UMLAttribute::toString(Uml::SignatureType::Enum sig)
+{
+ QString s;
+
+ if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::NoSig) {
+ s = Uml::Visibility::toString(m_visibility, true) + QLatin1Char(' ');
+ }
+
+ if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::SigNoVis) {
+ // Determine whether the type name needs to be scoped.
+ UMLObject *owningObject = static_cast<UMLObject*>(parent());
+ if (owningObject->baseType() == UMLObject::ot_Operation) {
+ // The immediate parent() is the UMLOperation but we want
+ // the UMLClassifier:
+ owningObject = static_cast<UMLObject*>(owningObject->parent());
+ }
+ UMLClassifier *ownParent = dynamic_cast<UMLClassifier*>(owningObject);
+ if (ownParent == NULL) {
+ uError() << "parent " << owningObject->name()
+ << " is not a UMLClassifier";
+ return QString();
+ }
+ QString typeName;
+ UMLClassifier *type = UMLClassifierListItem::getType();
+ if (type) {
+ UMLPackage *typeScope = type->umlPackage();
+ if (typeScope != ownParent && typeScope != ownParent->umlPackage())
+ typeName = type->fullyQualifiedName();
+ else
+ typeName = type->name();
+ }
+ // The default direction, "in", is not mentioned.
+ // Perhaps we should include a pd_Unspecified in
+ // Uml::ParameterDirection::Enum to have better control over this.
+ if (m_ParmKind == Uml::ParameterDirection::InOut)
+ s += QLatin1String("inout ");
+ else if (m_ParmKind == Uml::ParameterDirection::Out)
+ s += QLatin1String("out ");
+ // Construct the attribute text.
+ QString string = s + name() + QLatin1String(" : ") + typeName;
+ if (m_InitialValue.length() > 0)
+ string += QLatin1String(" = ") + m_InitialValue;
+ return string;
+ }
+ return s + name();
+}
+
+/**
+ * Reimplement method from UMLObject.
+ */
+QString UMLAttribute::getFullyQualifiedName(const QString& separator,
+ bool includeRoot /* = false */) const
+{
+ UMLOperation *op = NULL;
+ UMLObject *owningObject = static_cast<UMLObject*>(parent());
+ if (owningObject->baseType() == UMLObject::ot_Operation) {
+ op = static_cast<UMLOperation*>(owningObject);
+ owningObject = static_cast<UMLObject*>(owningObject->parent());
+ }
+ UMLClassifier *ownParent = dynamic_cast<UMLClassifier*>(owningObject);
+ if (ownParent == NULL) {
+ uError() << name() << ": parent " << owningObject->name()
+ << " is not a UMLClassifier";
+ return QString();
+ }
+ QString tempSeparator = separator;
+ if (tempSeparator.isEmpty())
+ tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
+ QString fqn = ownParent->fullyQualifiedName(tempSeparator, includeRoot);
+ if (op)
+ fqn.append(tempSeparator + op->name());
+ fqn.append(tempSeparator + name());
+ return fqn;
+}
+
+/**
+ * Overloaded '==' operator
+ */
+bool UMLAttribute::operator==(const UMLAttribute &rhs) const
+{
+ if(this == &rhs)
+ return true;
+
+ if(!UMLObject::operator==(rhs))
+ return false;
+
+ // The type name is the only distinguishing criterion.
+ // (Some programming languages might support more, but others don't.)
+ if (m_pSecondary != rhs.m_pSecondary)
+ return false;
+
+ return true;
+}
+
+/**
+ * Copy the internal presentation of this object into the UMLAttribute
+ * object.
+ */
+void UMLAttribute::copyInto(UMLObject *lhs) const
+{
+ UMLAttribute *target = static_cast<UMLAttribute*>(lhs);
+ // call the parent first.
+ UMLClassifierListItem::copyInto(target);
+
+ // Copy all datamembers
+ target->m_pSecondary = m_pSecondary;
+ target->m_SecondaryId = m_SecondaryId;
+ target->m_InitialValue = m_InitialValue;
+ target->m_ParmKind = m_ParmKind;
+}
+
+/**
+ * Make a clone of the UMLAttribute.
+ */
+UMLObject* UMLAttribute::clone() const
+{
+ //FIXME: The new attribute should be slaved to the NEW parent not the old.
+ UMLAttribute *clone = new UMLAttribute(static_cast<UMLObject*>(parent()));
+ copyInto(clone);
+
+ return clone;
+}
+
+/**
+ * Creates the <UML:Attribute> XMI element.
+ */
+void UMLAttribute::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement attributeElement = UMLObject::save(QLatin1String("UML:Attribute"), qDoc);
+ if (m_pSecondary == NULL) {
+ uDebug() << name() << ": m_pSecondary is NULL, m_SecondaryId is '"
+ << m_SecondaryId << "'";
+ } else {
+ attributeElement.setAttribute(QLatin1String("type"), Uml::ID::toString(m_pSecondary->id()));
+ }
+ if (! m_InitialValue.isEmpty())
+ attributeElement.setAttribute(QLatin1String("initialValue"), m_InitialValue);
+ qElement.appendChild(attributeElement);
+}
+
+/**
+ * Loads the <UML:Attribute> XMI element.
+ */
+bool UMLAttribute::load(QDomElement & element)
+{
+ m_SecondaryId = element.attribute(QLatin1String("type"));
+ // We use the m_SecondaryId as a temporary store for the xmi.id
+ // of the attribute type model object.
+ // It is resolved later on, when all classes have been loaded.
+ // This deferred resolution is required because the xmi.id may
+ // be a forward reference, i.e. it may identify a model object
+ // that has not yet been loaded.
+ if (m_SecondaryId.isEmpty()) {
+ // Perhaps the type is stored in a child node:
+ QDomNode node = element.firstChild();
+ while (!node.isNull()) {
+ if (node.isComment()) {
+ node = node.nextSibling();
+ continue;
+ }
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (!UMLDoc::tagEq(tag, QLatin1String("type"))) {
+ node = node.nextSibling();
+ continue;
+ }
+ m_SecondaryId = Model_Utils::getXmiId(tempElement);
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = tempElement.attribute(QLatin1String("xmi.idref"));
+ if (m_SecondaryId.isEmpty()) {
+ QString href = tempElement.attribute(QLatin1String("href"));
+ if (href.isEmpty()) {
+ QDomNode inner = node.firstChild();
+ QDomElement tmpElem = inner.toElement();
+ m_SecondaryId = Model_Utils::getXmiId(tmpElem);
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = tmpElem.attribute(QLatin1String("xmi.idref"));
+ } else {
+ int hashpos = href.lastIndexOf(QChar(QLatin1Char('#')));
+ if (hashpos < 0) {
+ uDebug() << name() << ": cannot find type " << href;
+ } else {
+ QString typeName = href.mid(hashpos + 1);
+ UMLFolder *dtFolder = UMLApp::app()->document()->datatypeFolder();
+ m_pSecondary = Model_Utils::findUMLObject(dtFolder->containedObjects(),
+ typeName, UMLObject::ot_Datatype);
+ if (!m_pSecondary) {
+ m_pSecondary = Object_Factory::createUMLObject(UMLObject::ot_Datatype,
+ typeName, dtFolder);
+ }
+ }
+ }
+ }
+ break;
+ }
+ if (m_SecondaryId.isEmpty()) {
+ uDebug() << name() << ": cannot find type.";
+ }
+ }
+ m_InitialValue = element.attribute(QLatin1String("initialValue"));
+ if (m_InitialValue.isEmpty()) {
+ // for backward compatibility
+ m_InitialValue = element.attribute(QLatin1String("value"));
+ }
+ return true;
+}
+
+/**
+ * Display the properties configuration dialog for the attribute.
+ */
+bool UMLAttribute::showPropertiesDialog(QWidget* parent)
+{
+ UMLAttributeDialog dialog(parent, this);
+ return dialog.exec();
+}
+
+/**
+ * Puts in the param templateParamList all the template params that are in templateParam
+ */
+void UMLAttribute::setTemplateParams(const QString& templateParam, UMLClassifierList &templateParamList)
+{
+ if (templateParam.isEmpty())
+ return;
+ QString type = templateParam.simplified();
+
+ int start = type.indexOf(QLatin1Char('<'));
+ if (start >= 0) {
+ int end = start;
+ int count = 1;
+ int len = type.length();
+ while (count != 0 && ++end < len) {
+ QChar c = type.at(end);
+ if (c == QLatin1Char('<')) {
+ count++;
+ }
+ if (c == QLatin1Char('>')) {
+ count--;
+ }
+ }
+ if (count != 0) {
+ //The template is ill-formated, let's quit
+ return;
+ }
+ setTemplateParams(type.mid(start + 1, end - start - 1), templateParamList);
+ setTemplateParams(type.left(start) + type.right(len - end - 1), templateParamList);
+ } else {
+ QStringList paramsList = type.split(QLatin1Char(','));
+ for (QStringList::Iterator it = paramsList.begin(); it != paramsList.end(); ++it) {
+ QString param = *it;
+ if (!param.isEmpty()) {
+ UMLDoc *pDoc = UMLApp::app()->document();
+ UMLObject* obj = pDoc->findUMLObject(param);
+ if (obj == NULL) {
+ obj = pDoc->findUMLObject(param.remove(QLatin1Char(' ')));
+ }
+ if (obj != NULL) {
+ //We want to list only the params that already exist in this document
+ //If the param doesnt't already exist, we couldn't draw an association anyway
+ UMLClassifier* tmpClassifier = static_cast<UMLClassifier*>(obj);
+ if (templateParamList.indexOf(tmpClassifier) == -1) {
+ templateParamList.append(tmpClassifier);
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Returns all the template params (if any) that are in the type of this attribute
+ */
+UMLClassifierList UMLAttribute::getTemplateParams()
+{
+ UMLClassifierList templateParamList;
+ QString type = getType()->name();
+ QString templateParam;
+ // Handle C++/D/Java template/generic parameters
+ const Uml::ProgrammingLanguage::Enum pl = UMLApp::app()->activeLanguage();
+ if (pl == Uml::ProgrammingLanguage::Cpp ||
+ pl == Uml::ProgrammingLanguage::Java || pl == Uml::ProgrammingLanguage::D) {
+ int start = type.indexOf(QLatin1Char('<'));
+ if (start >= 0) {
+ int end = type.lastIndexOf(QLatin1Char('>'));
+ if (end > start) {
+ templateParam = type.mid(start + 1, end - start - 1);
+ setTemplateParams(templateParam, templateParamList);
+ }
+ }
+ }
+ return templateParamList;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/attribute.h umbrello-kf6-15.08.1/umbrello/umlmodel/attribute.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/attribute.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/attribute.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ATTRIBUTE_H
+#define ATTRIBUTE_H
+
+#include "basictypes.h"
+#include "classifierlistitem.h"
+#include "umlclassifierlist.h"
+
+/**
+ * This class is used to set up information for an attribute. This is like
+ * a programming attribute. It has a type, name, visibility and initial value.
+ *
+ * @short Sets up attribute information.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLAttribute : public UMLClassifierListItem
+{
+ Q_OBJECT
+public:
+
+ UMLAttribute(UMLObject *parent, const QString& name,
+ Uml::ID::Type id = Uml::ID::None,
+ Uml::Visibility::Enum s = Uml::Visibility::Private,
+ UMLObject *type = 0, const QString& iv = QString());
+ explicit UMLAttribute(UMLObject *parent);
+
+ bool operator==(const UMLAttribute &rhs) const;
+
+ virtual ~UMLAttribute();
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ void setName(const QString &name);
+
+ void setVisibility(Uml::Visibility::Enum s);
+
+ virtual UMLObject* clone() const;
+
+ QString getInitialValue() const;
+ void setInitialValue(const QString &iv);
+
+ QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
+
+ QString getFullyQualifiedName(const QString& separator = QString(),
+ bool includeRoot = false) const;
+
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ virtual bool showPropertiesDialog(QWidget* parent = 0);
+
+ void setParmKind(Uml::ParameterDirection::Enum pk);
+ Uml::ParameterDirection::Enum getParmKind() const;
+
+ virtual UMLClassifierList getTemplateParams();
+
+signals:
+
+ void attributeChanged();
+
+protected:
+
+ bool load(QDomElement & element);
+
+ QString m_InitialValue; ///< text for the attribute's initial value.
+ Uml::ParameterDirection::Enum m_ParmKind;
+
+private:
+
+ void setTemplateParams(const QString& templateParam, UMLClassifierList &templateParamList);
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/category.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/category.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/category.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/category.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,101 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "category.h"
+
+/**
+ * Constructs a Category.
+ *
+ * @param name The name of the Category.
+ * @param id The unique id to assign to this Category.
+ */
+UMLCategory::UMLCategory(const QString & name, Uml::ID::Type id)
+ : UMLCanvasObject(name, id)
+{
+ init();
+}
+
+/**
+ * Standard destructor.
+ */
+UMLCategory::~UMLCategory()
+{
+}
+
+/**
+ * Initializes key variables of the class.
+ */
+void UMLCategory::init()
+{
+ m_BaseType = UMLObject::ot_Category;
+ m_CategoryType = ct_Disjoint_Specialisation;
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLCategory::copyInto(UMLObject *lhs) const
+{
+ UMLCategory *target = static_cast<UMLCategory*>(lhs);
+
+ // call the parent first
+ UMLCanvasObject::copyInto(target);
+
+ target->m_CategoryType = m_CategoryType;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLCategory::clone() const
+{
+ UMLCategory *clone = new UMLCategory();
+ copyInto(clone);
+ return clone;
+}
+
+/**
+ * Creates the <UML:Category> XMI element.
+ */
+void UMLCategory::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement categoryElement = UMLObject::save(QLatin1String("UML:Category"), qDoc);
+ categoryElement.setAttribute(QLatin1String("categoryType"), (int)m_CategoryType);
+ qElement.appendChild(categoryElement);
+}
+
+/**
+ * Loads the <UML:Category> XMI element (empty.)
+ */
+bool UMLCategory::load(QDomElement& element)
+{
+ m_CategoryType = (Category_Type)element.attribute(QLatin1String("categoryType"),
+ QLatin1String("0")).toInt();
+ return true;
+}
+
+/**
+ * Get the category type
+ */
+UMLCategory::Category_Type UMLCategory::getType()
+{
+ return m_CategoryType;
+}
+
+/**
+ * Set the category type
+ */
+void UMLCategory::setType(Category_Type type)
+{
+ m_CategoryType = type;
+ emitModified();
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/category.h umbrello-kf6-15.08.1/umbrello/umlmodel/category.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/category.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/category.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * *
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef CATEGORY_H
+#define CATEGORY_H
+
+#include "umlcanvasobject.h"
+
+/**
+ * This class contains the non-graphical information required for a UML Category.
+ * This class inherits from @ref UMLCanvasObject which contains most of the
+ * information.
+ * The @ref UMLDoc class creates instances of this type.
+ *
+ * @short Information for a non-graphical UML Category.
+ * @author Sharan Rao
+ * @see UMLCanvasObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLCategory : public UMLCanvasObject {
+ Q_OBJECT
+public:
+
+ enum Category_Type {
+ ct_Disjoint_Specialisation,
+ ct_Overlapping_Specialisation,
+ ct_Union
+ };
+
+ explicit UMLCategory(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ ~UMLCategory();
+
+ virtual void init();
+
+ void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ UMLCategory::Category_Type getType();
+
+ void setType(Category_Type type);
+
+protected:
+
+ bool load(QDomElement & element);
+
+private:
+
+ Category_Type m_CategoryType;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/checkconstraint.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/checkconstraint.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/checkconstraint.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/checkconstraint.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,160 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+//own header
+#include "checkconstraint.h"
+
+// app includes
+#include "debug_utils.h"
+#include "umlcheckconstraintdialog.h"
+
+/**
+ * Sets up a constraint.
+ *
+ * @param parent The parent of this UMLCheckConstraint.
+ * @param name The name of this UMLCheckConstraint.
+ * @param id The unique id given to this UMLCheckConstraint.
+ */
+UMLCheckConstraint::UMLCheckConstraint(UMLObject *parent,
+ const QString& name, Uml::ID::Type id)
+ : UMLEntityConstraint(parent, name, id)
+{
+ init();
+}
+
+/**
+ * Sets up a constraint.
+ *
+ * @param parent The parent of this UMLCheckConstraint.
+ */
+UMLCheckConstraint::UMLCheckConstraint(UMLObject *parent)
+ : UMLEntityConstraint(parent)
+{
+ init();
+}
+
+/**
+ * Overloaded '==' operator.
+ */
+bool UMLCheckConstraint::operator==(const UMLCheckConstraint &rhs) const
+{
+ if (this == &rhs)
+ return true;
+
+ if (!UMLObject::operator==(rhs))
+ return false;
+
+ return true;
+}
+
+/**
+ * Destructor.
+ */
+UMLCheckConstraint::~UMLCheckConstraint()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the UMLCheckConstraint
+ * object.
+ */
+void UMLCheckConstraint::copyInto(UMLObject *lhs) const
+{
+ UMLCheckConstraint *target = static_cast<UMLCheckConstraint*>(lhs);
+
+ // call the parent first.
+ UMLEntityConstraint::copyInto(target);
+
+ // Copy all datamembers
+ target->m_CheckCondition = m_CheckCondition;
+}
+
+/**
+ * Make a clone of the UMLCheckConstraint.
+ */
+UMLObject* UMLCheckConstraint::clone() const
+{
+ //FIXME: The new attribute should be slaved to the NEW parent not the old.
+ UMLCheckConstraint *clone = new UMLCheckConstraint(static_cast<UMLObject*>(parent()));
+ copyInto(clone);
+ return clone;
+}
+
+/**
+ * Returns a string representation of the UMLCheckConstraint.
+ *
+ * @param sig If true will show the attribute type and initial value.
+ * @return Returns a string representation of the UMLAttribute.
+ */
+QString UMLCheckConstraint::toString(Uml::SignatureType::Enum sig)
+{
+ QString s;
+
+ if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::SigNoVis) {
+ s = name() ;
+ }
+
+ return s;
+}
+
+QString UMLCheckConstraint::getFullyQualifiedName(const QString& separator,
+ bool includeRoot) const
+{
+ Q_UNUSED(separator); Q_UNUSED(includeRoot);
+ return this->name();
+}
+
+/**
+ * Creates the <UML:UniqueConstraint> XMI element.
+ */
+void UMLCheckConstraint::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement checkConstraintElement = UMLObject::save(QLatin1String("UML:CheckConstraint"), qDoc);
+
+ QDomNode checkCondition = qDoc.createTextNode(m_CheckCondition);
+ checkConstraintElement.appendChild(checkCondition);
+
+ qElement.appendChild(checkConstraintElement);
+}
+
+/**
+ * Display the properties configuration dialog for the attribute.
+ */
+bool UMLCheckConstraint::showPropertiesDialog(QWidget* parent)
+{
+ UMLCheckConstraintDialog dialog(parent, this);
+ return dialog.exec();
+}
+
+/**
+ * Loads the <UML:CheckConstraint> XMI element.
+ */
+bool UMLCheckConstraint::load(QDomElement & element)
+{
+ QDomNode node = element.firstChild();
+
+ QDomText checkConstraintText = node.toText();
+ if (checkConstraintText.isNull())
+ m_CheckCondition = QString();
+ else
+ m_CheckCondition = checkConstraintText.data();
+
+ return true;
+}
+
+/**
+ * Initialises Check Constraint
+ */
+void UMLCheckConstraint::init()
+{
+ m_BaseType = UMLObject::ot_CheckConstraint;
+ m_CheckCondition.clear();
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/checkconstraint.h umbrello-kf6-15.08.1/umbrello/umlmodel/checkconstraint.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/checkconstraint.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/checkconstraint.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef CHECKCONSTRAINT_H
+#define CHECKCONSTRAINT_H
+
+#include "basictypes.h"
+#include "entityconstraint.h"
+
+/**
+ * This class is used to set up information for a unique entity constraint.
+ *
+ * @short Sets up Check Constraint information for UMLEntities.
+ * @author Sharan Rao
+ * @see UMLObject UMLClassifierListItem UMLEntityConstraint
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLCheckConstraint : public UMLEntityConstraint
+{
+ Q_OBJECT
+public:
+
+ UMLCheckConstraint(UMLObject *parent, const QString& name,
+ Uml::ID::Type id = Uml::ID::None);
+ explicit UMLCheckConstraint(UMLObject *parent);
+
+ bool operator==(const UMLCheckConstraint &rhs) const;
+
+ virtual ~UMLCheckConstraint();
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
+
+ QString getFullyQualifiedName(const QString& separator = QString(),
+ bool includeRoot = false) const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ virtual bool showPropertiesDialog(QWidget* parent = 0);
+
+ QString getCheckCondition() const {
+ return m_CheckCondition;
+ }
+
+ void setCheckCondition(const QString& condition) {
+ m_CheckCondition = condition.trimmed();
+ }
+
+protected:
+
+ bool load(QDomElement & element);
+
+private:
+
+ void init();
+
+ QString m_CheckCondition; ///< the check condition
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/classifier.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/classifier.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/classifier.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/classifier.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,1631 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+#include "classifier.h"
+
+// app includes
+#include "association.h"
+#include "debug_utils.h"
+#include "umlassociationlist.h"
+#include "operation.h"
+#include "attribute.h"
+#include "template.h"
+#include "enumliteral.h"
+#include "entityattribute.h"
+#include "enum.h"
+#include "entity.h"
+#include "stereotype.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "uniqueid.h"
+#include "object_factory.h"
+#include "model_utils.h"
+#include "idchangelog.h"
+#include "umloperationdialog.h"
+#include "umlattributedialog.h"
+#include "umltemplatedialog.h"
+#include "optionstate.h"
+#include "icon_utils.h"
+
+// kde includes
+#include <KLocalizedString>
+#include <KMessageBox>
+
+// qt includes
+#include <QPointer>
+
+using namespace Uml;
+
+/**
+ * @brief holds set of classifiers for recursive loop detection
+ */
+class UMLClassifierSet: public QSet<UMLClassifier *> {
+public:
+ UMLClassifierSet() : level(0)
+ {
+ }
+ int level;
+};
+
+/**
+ * Sets up a Classifier.
+ *
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+UMLClassifier::UMLClassifier(const QString & name, Uml::ID::Type id)
+ : UMLPackage(name, id)
+{
+ m_BaseType = UMLObject::ot_Class; // default value
+ m_pClassAssoc = NULL;
+ m_isRef = false;
+}
+
+/**
+ * Standard deconstructor.
+ */
+UMLClassifier::~UMLClassifier()
+{
+}
+
+/**
+ * Reimplementation of method from class UMLObject for controlling the
+ * exact type of this classifier: class, interface, or datatype.
+ * @param ot the base type to set
+ */
+void UMLClassifier::setBaseType(UMLObject::ObjectType ot)
+{
+ m_BaseType = ot;
+ Icon_Utils::IconType newIcon;
+ switch (ot) {
+ case ot_Interface:
+ UMLObject::setStereotypeCmd(QLatin1String("interface"));
+ UMLObject::m_bAbstract = true;
+ newIcon = Icon_Utils::it_Interface;
+ break;
+ case ot_Class:
+ UMLObject::setStereotypeCmd(QString());
+ UMLObject::m_bAbstract = false;
+ newIcon = Icon_Utils::it_Class;
+ break;
+ case ot_Datatype:
+ UMLObject::setStereotypeCmd(QLatin1String("datatype"));
+ UMLObject::m_bAbstract = false;
+ newIcon = Icon_Utils::it_Datatype;
+ break;
+ case ot_Package:
+ UMLObject::setStereotypeCmd(QString());
+ UMLObject::m_bAbstract = false;
+ newIcon = Icon_Utils::it_Package;
+ break;
+ default:
+ uError() << "cannot set to type " << ot;
+ return;
+ }
+ Model_Utils::treeViewChangeIcon(this, newIcon);
+}
+
+/**
+ * Returns true if this classifier represents an interface.
+ */
+bool UMLClassifier::isInterface() const
+{
+ return (m_BaseType == ot_Interface);
+}
+
+/**
+ * Returns true if this classifier represents a datatype.
+ */
+bool UMLClassifier::isDatatype() const
+{
+ return (m_BaseType == ot_Datatype);
+}
+
+/**
+ * Checks whether an operation is valid based on its signature -
+ * An operation is "valid" if the operation's name and parameter list
+ * are unique in the classifier.
+ *
+ * @param name Name of the operation to check.
+ * @param opParams The operation's argument list.
+ * @param exemptOp Pointer to the exempt method (optional.)
+ * @return NULL if the signature is valid (ok), else return a pointer
+ * to the existing UMLOperation that causes the conflict.
+ */
+UMLOperation * UMLClassifier::checkOperationSignature(
+ const QString& name,
+ UMLAttributeList opParams,
+ UMLOperation *exemptOp)
+{
+ UMLOperationList list = findOperations(name);
+ if (list.count() == 0) {
+ return NULL;
+ }
+ const int inputParmCount = opParams.count();
+
+ // there is at least one operation with the same name... compare the parameter list
+ foreach (UMLOperation* test, list) {
+ if (test == exemptOp) {
+ continue;
+ }
+ UMLAttributeList testParams = test->getParmList();
+ const int pCount = testParams.count();
+ if (pCount != inputParmCount) {
+ continue;
+ }
+ int i = 0;
+ while (i < pCount) {
+ // The only criterion for equivalence is the parameter types.
+ // (Default values are not considered.)
+ if(testParams.at(i)->getTypeName() != opParams.at(i)->getTypeName())
+ break;
+ i++;
+ }
+ if (i == pCount) { // all parameters matched->the signature is not unique
+ return test;
+ }
+ }
+ // we did not find an exact match, so the signature is unique (acceptable)
+ return NULL;
+}
+
+/**
+ * Find an operation of the given name and parameter signature.
+ *
+ * @param name The name of the operation to find.
+ * @param params The parameter descriptors of the operation to find.
+ *
+ * @return The operation found. Will return 0 if none found.
+ */
+UMLOperation* UMLClassifier::findOperation(const QString& name,
+ Model_Utils::NameAndType_List params)
+{
+ UMLOperationList list = findOperations(name);
+ if (list.count() == 0) {
+ return NULL;
+ }
+ // if there are operation(s) with the same name then compare the parameter list
+ const int inputParmCount = params.count();
+
+ foreach (UMLOperation* test, list) {
+ UMLAttributeList testParams = test->getParmList();
+ const int pCount = testParams.count();
+ if (inputParmCount == 0 && pCount == 0)
+ return test;
+ if (inputParmCount != pCount)
+ continue;
+ int i = 0;
+ for (; i < pCount; ++i) {
+ Model_Utils::NameAndType_ListIt nt(params.begin() + i);
+ UMLClassifier *type = dynamic_cast<UMLClassifier*>((*nt).m_type);
+ UMLClassifier *testType = testParams.at(i)->getType();
+ if (type == NULL && testType == NULL) { //no parameter type
+ continue;
+ } else if (type == NULL) { //template parameter
+ if (testType->name() != QLatin1String("class"))
+ break;
+ } else if (type != testType)
+ break;
+ }
+ if (i == pCount)
+ return test; // all parameters matched
+ }
+ return 0;
+}
+
+/**
+ * Creates an operation in the current document.
+ * The new operation is initialized with name, id, etc.
+ * If a method with the given profile already exists in the classifier,
+ * no new method is created and the existing operation is returned.
+ * If no name is provided, or if the params are NULL, an Operation
+ * Dialog is shown to ask the user for a name and parameters.
+ * The operation's signature is checked for validity within the parent
+ * classifier.
+ *
+ * @param name The operation name (will be chosen internally if
+ * none given.)
+ * @param isExistingOp Optional pointer to bool. If supplied, the bool is
+ * set to true if an existing operation is returned.
+ * @param params Optional list of parameter names and types.
+ * If supplied, new operation parameters are
+ * constructed using this list.
+ * @return The new operation, or NULL if the operation could not be
+ * created because for example, the user canceled the dialog
+ * or no appropriate name can be found.
+ */
+UMLOperation* UMLClassifier::createOperation(
+ const QString &name /*=QString()*/,
+ bool *isExistingOp /*=NULL*/,
+ Model_Utils::NameAndType_List *params /*=NULL*/)
+{
+ bool nameNotSet = (name.isNull() || name.isEmpty());
+ if (! nameNotSet) {
+ Model_Utils::NameAndType_List parList;
+ if (params)
+ parList = *params;
+ UMLOperation* existingOp = findOperation(name, parList);
+ if (existingOp != NULL) {
+ if (isExistingOp != NULL)
+ *isExistingOp = true;
+ return existingOp;
+ }
+ }
+ // we did not find an exact match, so the signature is unique
+ UMLOperation *op = new UMLOperation(this, name);
+ if (params) {
+ for (Model_Utils::NameAndType_ListIt it = params->begin(); it != params->end(); ++it) {
+ const Model_Utils::NameAndType &nt = *it;
+ UMLAttribute *par = new UMLAttribute(op, nt.m_name, Uml::ID::None, Uml::Visibility::Private,
+ nt.m_type, nt.m_initialValue);
+ par->setParmKind(nt.m_direction);
+ op->addParm(par);
+ }
+ }
+
+ // Only show the operation dialog if no name was provided (allows quick-create
+ // from listview)
+ if (nameNotSet) {
+ op->setName(uniqChildName(UMLObject::ot_Operation));
+
+ while (true) {
+ QPointer<UMLOperationDialog> operationDialog = new UMLOperationDialog(0, op);
+ if(operationDialog->exec() != QDialog::Accepted) {
+ delete op;
+ delete operationDialog;
+ return NULL;
+ } else if (checkOperationSignature(op->name(), op->getParmList())) {
+ KMessageBox::information(0,
+ i18n("An operation with the same name and signature already exists. You cannot add it again."));
+ } else {
+ break;
+ }
+ delete operationDialog;
+ }
+ }
+
+ // operation name is ok, formally add it to the classifier
+ if (! addOperation(op)) {
+ delete op;
+ return NULL;
+ }
+
+ UMLDoc *umldoc = UMLApp::app()->document();
+ umldoc->signalUMLObjectCreated(op);
+ return op;
+}
+
+/**
+ * Appends an operation to the classifier.
+ * This function is mainly intended for the clipboard.
+ *
+ * @param op Pointer to the UMLOperation to add.
+ * @param position Inserted at the given position.
+ * @return True if the operation was added successfully.
+ */
+bool UMLClassifier::addOperation(UMLOperation* op, int position)
+{
+ Q_ASSERT(op);
+ if (m_List.indexOf(op) != -1) {
+ uDebug() << "findRef(" << op->name() << ") finds op (bad)";
+ return false;
+ }
+ if (checkOperationSignature(op->name(), op->getParmList())) {
+ uDebug() << "checkOperationSignature(" << op->name() << ") op is non-unique";
+ return false;
+ }
+
+ if (position >= 0 && position <= m_List.count()) {
+ uDebug() << op->name() << ": inserting at position " << position;
+ m_List.insert(position, op);
+ UMLClassifierListItemList itemList = getFilteredList(UMLObject::ot_Operation);
+ QString buf;
+ foreach (UMLClassifierListItem* currentAtt, itemList) {
+ buf.append(QLatin1Char(' ') + currentAtt->name());
+ }
+ uDebug() << " list after change: " << buf;
+ }
+ else {
+ m_List.append(op);
+ }
+ emit operationAdded(op);
+ UMLObject::emitModified();
+ connect(op, SIGNAL(modified()), this, SIGNAL(modified()));
+ return true;
+}
+
+/**
+ * Appends an operation to the classifier.
+ * @see bool addOperation(UMLOperation* Op, int position = -1)
+ * This function is mainly intended for the clipboard.
+ *
+ * @param op Pointer to the UMLOperation to add.
+ * @param log Pointer to the IDChangeLog.
+ * @return True if the operation was added successfully.
+ */
+bool UMLClassifier::addOperation(UMLOperation* op, IDChangeLog* log)
+{
+ if (addOperation(op, -1)) {
+ return true;
+ }
+ else if (log) {
+ log->removeChangeByNewID(op->id());
+ }
+ return false;
+}
+
+/**
+ * Remove an operation from the Classifier.
+ * The operation is not deleted so the caller is responsible for what
+ * happens to it after this.
+ *
+ * @param op The operation to remove.
+ * @return Count of the remaining operations after removal, or
+ * -1 if the given operation was not found.
+ */
+int UMLClassifier::removeOperation(UMLOperation *op)
+{
+ if (op == NULL) {
+ uDebug() << "called on NULL op";
+ return -1;
+ }
+ if (!m_List.removeAll(op)) {
+ uDebug() << "cannot find op " << op->name() << " in list";
+ return -1;
+ }
+ // disconnection needed.
+ // note that we don't delete the operation, just remove it from the Classifier
+ disconnect(op, SIGNAL(modified()), this, SIGNAL(modified()));
+ emit operationRemoved(op);
+ UMLObject::emitModified();
+ return m_List.count();
+}
+
+/**
+ * Create and add a just created template.
+ * @param currentName the name of the template
+ * @return the template or NULL
+ */
+UMLObject* UMLClassifier::createTemplate(const QString& currentName /*= QString()*/)
+{
+ QString name = currentName;
+ bool goodName = !name.isEmpty();
+ if (!goodName) {
+ name = uniqChildName(UMLObject::ot_Template);
+ }
+ UMLTemplate* newTemplate = new UMLTemplate(this, name);
+
+ int button = QDialog::Accepted;
+
+ while (button == QDialog::Accepted && !goodName) {
+ QPointer<UMLTemplateDialog> templateDialog = new UMLTemplateDialog(0, newTemplate);
+ button = templateDialog->exec();
+ name = newTemplate->name();
+
+ if (name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ }
+ else if (findChildObject(name) != NULL) {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ }
+ else {
+ goodName = true;
+ }
+ delete templateDialog;
+ }
+
+ if (button != QDialog::Accepted) {
+ return NULL;
+ }
+
+ addTemplate(newTemplate);
+
+ UMLDoc *umldoc = UMLApp::app()->document();
+ umldoc->signalUMLObjectCreated(newTemplate);
+ return newTemplate;
+}
+
+/**
+ * Returns the number of attributes for the class.
+ *
+ * @return The number of attributes for the class.
+ */
+int UMLClassifier::attributes()
+{
+ UMLClassifierListItemList atts = getFilteredList(UMLObject::ot_Attribute);
+ return atts.count();
+}
+
+/**
+ * Returns the attributes for the specified scope.
+ * @return List of true attributes for the class.
+ */
+UMLAttributeList UMLClassifier::getAttributeList() const
+{
+ UMLAttributeList attributeList;
+ foreach (UMLObject* listItem, m_List) {
+ uIgnoreZeroPointer(listItem);
+ if (listItem->baseType() == UMLObject::ot_Attribute) {
+ attributeList.append(static_cast<UMLAttribute*>(listItem));
+ }
+ }
+ return attributeList;
+}
+
+/**
+ * Returns the attributes for the specified scope.
+ * @param scope The scope of the attribute.
+ * @return List of true attributes for the class.
+ */
+UMLAttributeList UMLClassifier::getAttributeList(Visibility::Enum scope) const
+{
+ UMLAttributeList list;
+ if (!isInterface())
+ {
+ UMLAttributeList atl = getAttributeList();
+ foreach(UMLAttribute* at, atl)
+ {
+ uIgnoreZeroPointer(at);
+ if (! at->isStatic())
+ {
+ if (scope == Uml::Visibility::Private)
+ {
+ if ((at->visibility() == Uml::Visibility::Private) ||
+ (at->visibility() == Uml::Visibility::Implementation))
+ {
+ list.append(at);
+ }
+ }
+ else if (scope == at->visibility())
+ {
+ list.append(at);
+ }
+ }
+ }
+ }
+ return list;
+}
+
+/**
+ * Returns the static attributes for the specified scope.
+ *
+ * @param scope The scope of the attribute.
+ * @return List of true attributes for the class.
+ */
+UMLAttributeList UMLClassifier::getAttributeListStatic(Visibility::Enum scope) const
+{
+ UMLAttributeList list;
+ if (!isInterface())
+ {
+ UMLAttributeList atl = getAttributeList();
+ foreach(UMLAttribute* at, atl)
+ {
+ uIgnoreZeroPointer(at);
+ if (at->isStatic())
+ {
+ if (scope == Uml::Visibility::Private)
+ {
+ if ((at->visibility() == Uml::Visibility::Private) ||
+ (at->visibility() == Uml::Visibility::Implementation))
+ {
+ list.append(at);
+ }
+ }
+ else if (scope == at->visibility())
+ {
+ list.append(at);
+ }
+ }
+ }
+ }
+ return list;
+}
+
+/**
+ * Find a list of operations with the given name.
+ *
+ * @param n The name of the operation to find.
+ * @return The list of objects found; will be empty if none found.
+ */
+UMLOperationList UMLClassifier::findOperations(const QString &n)
+{
+ const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
+ UMLOperationList list;
+ foreach (UMLObject* obj, m_List) {
+ uIgnoreZeroPointer(obj);
+ if (obj->baseType() != UMLObject::ot_Operation)
+ continue;
+ UMLOperation *op = static_cast<UMLOperation*>(obj);
+ if (caseSensitive) {
+ if (obj->name() == n)
+ list.append(op);
+ } else if (obj->name().toLower() == n.toLower()) {
+ list.append(op);
+ }
+ }
+ return list;
+}
+
+/**
+ * Find the child object by the given id.
+ * @param id the id of the child object
+ * @param considerAncestors flag whether the ancestors should be considered during search
+ * @return the found child object or NULL
+ */
+UMLObject* UMLClassifier::findChildObjectById(Uml::ID::Type id, bool considerAncestors /* =false */)
+{
+ UMLObject *o = UMLCanvasObject::findChildObjectById(id);
+ if (o) {
+ return o;
+ }
+ if (considerAncestors) {
+ UMLClassifierList ancestors = findSuperClassConcepts();
+ foreach (UMLClassifier *anc, ancestors) {
+ UMLObject *o = anc->findChildObjectById(id);
+ if (o) {
+ return o;
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Returns a list of concepts which inherit from this concept.
+ *
+ * @param type The ClassifierType to seek.
+ * @return List of UMLClassifiers that inherit from us.
+ */
+UMLClassifierList UMLClassifier::findSubClassConcepts (ClassifierType type)
+{
+ UMLClassifierList list = getSubClasses();
+ UMLAssociationList rlist = getRealizations();
+
+ UMLClassifierList inheritingConcepts;
+ Uml::ID::Type myID = id();
+ foreach(UMLClassifier *c, list) {
+ uIgnoreZeroPointer(c);
+ if (type == ALL || (!c->isInterface() && type == CLASS)
+ || (c->isInterface() && type == INTERFACE)) {
+ inheritingConcepts.append(c);
+ }
+ }
+
+ foreach (UMLAssociation *a, rlist) {
+ uIgnoreZeroPointer(a);
+ if (a->getObjectId(RoleType::A) != myID)
+ {
+ UMLObject* obj = a->getObject(RoleType::A);
+ UMLClassifier *concept = dynamic_cast<UMLClassifier*>(obj);
+ if (concept && (type == ALL || (!concept->isInterface() && type == CLASS)
+ || (concept->isInterface() && type == INTERFACE))
+ && (inheritingConcepts.indexOf(concept) == -1))
+ {
+ inheritingConcepts.append(concept);
+ }
+ }
+ }
+
+ return inheritingConcepts;
+}
+
+/**
+ * Returns a list of concepts which this concept inherits from.
+ *
+ * @param type The ClassifierType to seek.
+ * @return List of UMLClassifiers we inherit from.
+ */
+UMLClassifierList UMLClassifier::findSuperClassConcepts (ClassifierType type)
+{
+ UMLClassifierList list = getSuperClasses();
+ UMLAssociationList rlist = getRealizations();
+
+ UMLClassifierList parentConcepts;
+ Uml::ID::Type myID = id();
+ foreach (UMLClassifier *concept, list) {
+ uIgnoreZeroPointer(concept);
+ if (type == ALL || (!concept->isInterface() && type == CLASS)
+ || (concept->isInterface() && type == INTERFACE))
+ parentConcepts.append(concept);
+ }
+
+ foreach (UMLAssociation *a, rlist) {
+ if (a->getObjectId(RoleType::A) == myID)
+ {
+ UMLObject* obj = a->getObject(RoleType::B);
+ UMLClassifier *concept = dynamic_cast<UMLClassifier*>(obj);
+ if (concept && (type == ALL || (!concept->isInterface() && type == CLASS)
+ || (concept->isInterface() && type == INTERFACE))
+ && (parentConcepts.indexOf(concept) == -1))
+ parentConcepts.append(concept);
+ }
+ }
+
+ return parentConcepts;
+}
+
+/**
+ * Overloaded '==' operator.
+ */
+bool UMLClassifier::operator==(const UMLClassifier & rhs) const
+{
+ return UMLCanvasObject::operator==(rhs);
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLClassifier::copyInto(UMLObject *lhs) const
+{
+ UMLClassifier *target = static_cast<UMLClassifier*>(lhs);
+ UMLCanvasObject::copyInto(target);
+ target->setBaseType(m_BaseType);
+ // CHECK: association property m_pClassAssoc is not copied
+ m_List.copyInto(&(target->m_List));
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLClassifier::clone() const
+{
+ UMLClassifier *clone = new UMLClassifier();
+ copyInto(clone);
+ return clone;
+}
+
+/**
+ * Needs to be called after all UML objects are loaded from file.
+ * Calls the parent resolveRef(), and calls resolveRef() on all
+ * UMLClassifierListItems.
+ * Overrides the method from UMLObject.
+ *
+ * @return true for success.
+ */
+bool UMLClassifier::resolveRef()
+{
+ bool success = UMLPackage::resolveRef();
+ // Using reentrant iteration is a bare necessity here:
+ foreach (UMLObject* obj, m_List) {
+ uIgnoreZeroPointer(obj);
+ /**** For reference, here is the non-reentrant iteration scheme -
+ DO NOT USE THIS !
+ for (UMLObject *obj = m_List.first(); obj; obj = m_List.next())
+ { .... }
+ ****/
+ if (obj->resolveRef()) {
+ UMLClassifierListItem *cli = static_cast<UMLClassifierListItem*>(obj);
+ switch (cli->baseType()) {
+ case UMLObject::ot_Attribute:
+ emit attributeAdded(cli);
+ break;
+ case UMLObject::ot_Operation:
+ emit operationAdded(cli);
+ break;
+ case UMLObject::ot_Template:
+ emit templateAdded(cli);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return success;
+}
+
+/**
+ * Reimplemented from UMLObject.
+ */
+bool UMLClassifier::acceptAssociationType(AssociationType::Enum type)
+{
+ switch(type)
+ {
+ case AssociationType::Generalization:
+ case AssociationType::Aggregation:
+ case AssociationType::Relationship:
+ case AssociationType::Dependency:
+ case AssociationType::Association:
+ case AssociationType::Association_Self:
+ case AssociationType::Containment:
+ case AssociationType::Composition:
+ case AssociationType::Realization:
+ case AssociationType::UniAssociation:
+ return true;
+ default:
+ return false;
+ }
+ return false; //shutup compiler warning
+}
+
+/**
+ * Creates an attribute for the class.
+ *
+ * @param name An optional name, used by when creating through UMLListView
+ * @param type An optional type, used by when creating through UMLListView
+ * @param vis An optional visibility, used by when creating through UMLListView
+ * @param init An optional initial value, used by when creating through UMLListView
+ * @return The UMLAttribute created
+ */
+UMLAttribute* UMLClassifier::createAttribute(const QString &name,
+ UMLObject *type,
+ Visibility::Enum vis,
+ const QString &init)
+{
+ Uml::ID::Type id = UniqueID::gen();
+ QString currentName;
+ if (name.isNull()) {
+ currentName = uniqChildName(UMLObject::ot_Attribute);
+ } else {
+ currentName = name;
+ }
+ UMLAttribute* newAttribute = new UMLAttribute(this, currentName, id, vis, type, init);
+
+ int button = QDialog::Accepted;
+ bool goodName = false;
+
+ //check for name.isNull() stops dialog being shown
+ //when creating attribute via list view
+ while (button == QDialog::Accepted && !goodName && name.isNull()) {
+ QPointer<UMLAttributeDialog> attributeDialog = new UMLAttributeDialog(0, newAttribute);
+ button = attributeDialog->exec();
+ QString name = newAttribute->name();
+
+ if(name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ } else if (findChildObject(name) != NULL) {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ } else {
+ goodName = true;
+ }
+ delete attributeDialog;
+ }
+
+ if (button != QDialog::Accepted) {
+ delete newAttribute;
+ return NULL;
+ }
+
+ addAttribute(newAttribute);
+
+ UMLDoc *umldoc = UMLApp::app()->document();
+ umldoc->signalUMLObjectCreated(newAttribute);
+ return newAttribute;
+}
+
+/**
+ * Creates and adds an attribute for the class.
+ *
+ * @param name an optional name, used by when creating through UMLListView
+ * @param id an optional id
+ * @return the UMLAttribute created and added
+ */
+
+UMLAttribute* UMLClassifier::addAttribute(const QString &name, Uml::ID::Type id /* = Uml::id_None */)
+{
+ foreach (UMLObject* obj, m_List) {
+ uIgnoreZeroPointer(obj);
+ if (obj->baseType() == UMLObject::ot_Attribute && obj->name() == name)
+ return static_cast<UMLAttribute*>(obj);
+ }
+ Uml::Visibility::Enum scope = Settings::optionState().classState.defaultAttributeScope;
+ UMLAttribute *a = new UMLAttribute(this, name, id, scope);
+ m_List.append(a);
+ emit attributeAdded(a);
+ UMLObject::emitModified();
+ connect(a, SIGNAL(modified()), this, SIGNAL(modified()));
+ return a;
+}
+
+/**
+ * Adds an already created attribute.
+ * The attribute object must not belong to any other concept.
+ *
+ * @param name the name of the attribute
+ * @param type the type of the attribute
+ * @param scope the visibility of the attribute
+ * @return the just created and added attribute
+ */
+UMLAttribute* UMLClassifier::addAttribute(const QString &name, UMLObject *type, Visibility::Enum scope)
+{
+ UMLAttribute *a = new UMLAttribute(this);
+ a->setName(name);
+ a->setVisibility(scope);
+ a->setID(UniqueID::gen());
+ if (type) {
+ a->setType(type);
+ }
+ m_List.append(a);
+ emit attributeAdded(a);
+ UMLObject::emitModified();
+ connect(a, SIGNAL(modified()), this, SIGNAL(modified()));
+ return a;
+}
+
+/**
+ * Adds an already created attribute.
+ * The attribute object must not belong to any other concept.
+ *
+ * @param att Pointer to the UMLAttribute.
+ * @param log Pointer to the IDChangeLog (optional.)
+ * @param position Position index for the insertion (optional.)
+ * If the position is omitted, or if it is
+ * negative or too large, the attribute is added
+ * to the end of the list.
+ * @return True if the attribute was successfully added.
+ */
+bool UMLClassifier::addAttribute(UMLAttribute* att, IDChangeLog* log /* = 0 */,
+ int position /* = -1 */)
+{
+ Q_ASSERT(att);
+ if (findChildObject(att->name()) == NULL) {
+ att->setParent(this);
+ if (position >= 0 && position < (int)m_List.count()) {
+ m_List.insert(position, att);
+ }
+ else {
+ m_List.append(att);
+ }
+ emit attributeAdded(att);
+ UMLObject::emitModified();
+ connect(att, SIGNAL(modified()), this, SIGNAL(modified()));
+ return true;
+ } else if (log) {
+ log->removeChangeByNewID(att->id());
+ delete att;
+ }
+ return false;
+}
+
+/**
+ * Removes an attribute from the class.
+ *
+ * @param att The attribute to remove.
+ * @return Count of the remaining attributes after removal.
+ * Returns -1 if the given attribute was not found.
+ */
+int UMLClassifier::removeAttribute(UMLAttribute* att)
+{
+ if (!m_List.removeAll(att)) {
+ uDebug() << "cannot find att given in list";
+ return -1;
+ }
+ emit attributeRemoved(att);
+ UMLObject::emitModified();
+ // If we are deleting the object, then we don't need to disconnect..this is done auto-magically
+ // for us by QObject. -b.t.
+ // disconnect(att, SIGNAL(modified()), this, SIGNAL(modified()));
+ delete att;
+ return m_List.count();
+}
+
+/**
+ * Sets the UMLAssociation for which this class shall act as an
+ * association class.
+ */
+void UMLClassifier::setClassAssoc(UMLAssociation *assoc)
+{
+ m_pClassAssoc = assoc;
+}
+
+/**
+ * Returns the UMLAssociation for which this class acts as an
+ * association class. Returns NULL if this class does not act
+ * as an association class.
+ */
+UMLAssociation *UMLClassifier::getClassAssoc() const
+{
+ return m_pClassAssoc;
+}
+
+/**
+ * Return true if this classifier has abstract operations.
+ */
+bool UMLClassifier::hasAbstractOps ()
+{
+ UMLOperationList opl(getOpList());
+ foreach(UMLOperation *op, opl) {
+ uIgnoreZeroPointer(op);
+ if (op->isAbstract()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Counts the number of operations in the Classifier.
+ *
+ * @return The number of operations for the Classifier.
+ */
+int UMLClassifier::operations()
+{
+ return getOpList().count();
+}
+
+
+/**
+ * Return a list of operations for the Classifier.
+ *
+ * @param includeInherited Includes operations from superclasses.
+ * @param alreadyTraversed internal used object to avoid recursive loops
+ * @return The list of operations for the Classifier.
+ */
+UMLOperationList UMLClassifier::getOpList(bool includeInherited, UMLClassifierSet *alreadyTraversed)
+{
+ UMLOperationList ops;
+ foreach (UMLObject* li, m_List) {
+ uIgnoreZeroPointer(li);
+ if (li->baseType() == ot_Operation) {
+ ops.append(static_cast<UMLOperation*>(li));
+ }
+ }
+ if (includeInherited) {
+ if (!alreadyTraversed) {
+ alreadyTraversed = new UMLClassifierSet;
+ }
+ else
+ alreadyTraversed->level++;
+
+ if (!alreadyTraversed->contains(this))
+ *alreadyTraversed << this;
+
+ // get a list of parents of this class
+ UMLClassifierList parents = findSuperClassConcepts();
+ foreach(UMLClassifier *c, parents) {
+ if (alreadyTraversed->contains(c)) {
+ uError() << "class " << c->name() << " is starting a dependency loop!";
+ continue;
+ }
+ // get operations for each parent by recursive call
+ UMLOperationList pops = c->getOpList(true, alreadyTraversed);
+ // add these operations to operation list, but only if unique.
+ foreach (UMLOperation *po, pops) {
+ QString po_as_string(po->toString(Uml::SignatureType::SigNoVis));
+ bool breakFlag = false;
+ foreach (UMLOperation* o, ops) {
+ if (o->toString(Uml::SignatureType::SigNoVis) == po_as_string) {
+ breakFlag = true;
+ break;
+ }
+ }
+ if (breakFlag == false)
+ ops.append(po);
+ }
+ // remember this node
+ *alreadyTraversed << c;
+ }
+ if (alreadyTraversed->level-- == 0) {
+ delete alreadyTraversed;
+ alreadyTraversed = 0;
+ }
+ }
+ return ops;
+}
+
+/**
+ * Returns the entries in m_List that are of the requested type.
+ * If the requested type is UMLObject::ot_UMLObject then all entries
+ * are returned.
+ * @param ot the requested object type
+ * @return The list of true operations for the Concept.
+ */
+UMLClassifierListItemList UMLClassifier::getFilteredList(UMLObject::ObjectType ot) const
+{
+ UMLClassifierListItemList resultList;
+ foreach (UMLObject* o, m_List) {
+ uIgnoreZeroPointer(o);
+ if (!o || o->baseType() == UMLObject::ot_Association) {
+ continue;
+ }
+ UMLClassifierListItem *listItem = static_cast<UMLClassifierListItem*>(o);
+ if (ot == UMLObject::ot_UMLObject || listItem->baseType() == ot) {
+ resultList.append(listItem);
+ }
+ }
+ return resultList;
+}
+
+/**
+ * Adds an already created template.
+ * The template object must not belong to any other concept.
+ *
+ * @param name the name of the template
+ * @param id the id of the template
+ * @return the added template
+ */
+UMLTemplate* UMLClassifier::addTemplate(const QString &name, Uml::ID::Type id)
+{
+ UMLTemplate *templt = findTemplate(name);
+ if (templt) {
+ return templt;
+ }
+ templt = new UMLTemplate(this, name, id);
+ m_List.append(templt);
+ emit templateAdded(templt);
+ UMLObject::emitModified();
+ connect(templt, SIGNAL(modified()), this, SIGNAL(modified()));
+ return templt;
+}
+
+/**
+ * Adds an already created template.
+ * The template object must not belong to any other concept.
+ *
+ * @param newTemplate Pointer to the UMLTemplate object to add.
+ * @param log Pointer to the IDChangeLog.
+ * @return True if the template was successfully added.
+ */
+bool UMLClassifier::addTemplate(UMLTemplate* newTemplate, IDChangeLog* log /* = 0*/)
+{
+ QString name = newTemplate->name();
+ if (findChildObject(name) == NULL) {
+ newTemplate->setParent(this);
+ m_List.append(newTemplate);
+ emit templateAdded(newTemplate);
+ UMLObject::emitModified();
+ connect(newTemplate, SIGNAL(modified()), this, SIGNAL(modified()));
+ return true;
+ }
+ else if (log) {
+ log->removeChangeByNewID(newTemplate->id());
+ delete newTemplate;
+ }
+ return false;
+}
+
+/**
+ * Adds an template to the class.
+ * The template object must not belong to any other class.
+ * TODO: If the param IDChangeLog from the method above is not being used,
+ * give position a default value of -1 and the method can replace the above one.
+ * @param templt Pointer to the UMLTemplate to add.
+ * @param position The position of the template in the list.
+ * A value of -1 will add the template at the end.
+ * @return True if the template was successfully added.
+ */
+bool UMLClassifier::addTemplate(UMLTemplate* templt, int position)
+{
+ Q_ASSERT(templt);
+ QString name = templt->name();
+ if (findChildObject(name) == NULL) {
+ templt->setParent(this);
+ if (position >= 0 && position <= (int)m_List.count()) {
+ m_List.insert(position, templt);
+ }
+ else {
+ m_List.append(templt);
+ }
+ emit templateAdded(templt);
+ UMLObject::emitModified();
+ connect(templt, SIGNAL(modified()), this, SIGNAL(modified()));
+ return true;
+ }
+ //else
+ return false;
+}
+
+/**
+ * Removes a template from the class.
+ *
+ * @param umltemplate The template to remove.
+ * @return Count of the remaining templates after removal.
+ * Returns -1 if the given template was not found.
+ */
+int UMLClassifier::removeTemplate(UMLTemplate* umltemplate)
+{
+ if (!m_List.removeAll(umltemplate)) {
+ uWarning() << "cannot find att given in list";
+ return -1;
+ }
+ emit templateRemoved(umltemplate);
+ UMLObject::emitModified();
+ disconnect(umltemplate, SIGNAL(modified()), this, SIGNAL(modified()));
+ return m_List.count();
+}
+
+/**
+ * Seeks the template parameter of the given name.
+ * @param name the template name
+ * @return the found template or 0
+ */
+UMLTemplate *UMLClassifier::findTemplate(const QString& name)
+{
+ UMLTemplateList templParams = getTemplateList();
+ foreach (UMLTemplate *templt, templParams) {
+ if (templt->name() == name) {
+ return templt;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Returns the number of templates for the class.
+ *
+ * @return The number of templates for the class.
+ */
+int UMLClassifier::templates()
+{
+ UMLClassifierListItemList tempList = getFilteredList(UMLObject::ot_Template);
+ return tempList.count();
+}
+
+/**
+ * Returns the templates.
+ * Same as UMLClassifier::getFilteredList(ot_Template) but
+ * return type is a true UMLTemplateList.
+ *
+ * @return Pointer to the list of true templates for the class.
+ */
+UMLTemplateList UMLClassifier::getTemplateList() const
+{
+ UMLTemplateList templateList;
+ foreach (UMLObject* listItem, m_List) {
+ uIgnoreZeroPointer(listItem);
+ if (listItem->baseType() == UMLObject::ot_Template) {
+ templateList.append(static_cast<UMLTemplate*>(listItem));
+ }
+ }
+ return templateList;
+}
+
+/**
+ * Take and return a subordinate item from this classifier.
+ * Ownership of the item is passed to the caller.
+ *
+ * @param item Subordinate item to take.
+ * @return Index in m_List of the item taken.
+ * Return -1 if the item is not found in m_List.
+ */
+int UMLClassifier::takeItem(UMLClassifierListItem *item)
+{
+ QString buf;
+ foreach (UMLObject* currentAtt, m_List) {
+ uIgnoreZeroPointer(currentAtt);
+ QString txt = currentAtt->name();
+ if (txt.isEmpty()) {
+ txt = QLatin1String("Type-") + QString::number((int) currentAtt->baseType());
+ }
+ buf.append(QLatin1Char(' ') + currentAtt->name());
+ }
+ uDebug() << " UMLClassifier::takeItem (before): m_List is " << buf;
+
+ int index = m_List.indexOf(item);
+ if (index == -1) {
+ return -1;
+ }
+ switch (item->baseType()) {
+ case UMLObject::ot_Operation: {
+ if (removeOperation(dynamic_cast<UMLOperation*>(item)) < 0) {
+ index = -1;
+ }
+ break;
+ }
+ case UMLObject::ot_Attribute: {
+ UMLAttribute *retval = dynamic_cast<UMLAttribute*>(m_List.takeAt(index).data());
+ if (retval) {
+ emit attributeRemoved(retval);
+ UMLObject::emitModified();
+ } else {
+ index = -1;
+ }
+ break;
+ }
+ case UMLObject::ot_Template: {
+ UMLTemplate *templt = dynamic_cast<UMLTemplate*>(m_List.takeAt(index).data());
+ if (templt) {
+ emit templateRemoved(templt);
+ UMLObject::emitModified();
+ } else {
+ index = -1;
+ }
+ break;
+ }
+ case UMLObject::ot_EnumLiteral: {
+ UMLEnumLiteral *el = dynamic_cast<UMLEnumLiteral*>(m_List.takeAt(index).data());
+ if (el) {
+ UMLEnum *e = static_cast<UMLEnum*>(this);
+ e->signalEnumLiteralRemoved(el);
+ UMLObject::emitModified();
+ } else {
+ index = -1;
+ }
+ break;
+ }
+ case UMLObject::ot_EntityAttribute: {
+ UMLEntityAttribute* el = dynamic_cast<UMLEntityAttribute*>(m_List.takeAt(index).data());
+ if (el) {
+ UMLEntity *e = static_cast<UMLEntity*>(this);
+ e->signalEntityAttributeRemoved(el);
+ UMLObject::emitModified();
+ } else {
+ index = -1;
+ }
+ break;
+ }
+ default:
+ index = -1;
+ break;
+ }
+ return index;
+}
+
+/**
+ * Set the origin type (in case of e.g. typedef)
+ * @param origType the origin type to set
+ */
+void UMLClassifier::setOriginType(UMLClassifier *origType)
+{
+ m_pSecondary = origType;
+}
+
+/**
+ * Get the origin type (in case of e.g. typedef)
+ * @return the origin type
+ */
+UMLClassifier * UMLClassifier::originType() const
+{
+ return dynamic_cast<UMLClassifier*>(m_pSecondary.data());
+}
+
+/**
+ * Set the m_isRef flag (true when dealing with a pointer type)
+ * @param isRef the flag to set
+ */
+void UMLClassifier::setIsReference(bool isRef)
+{
+ m_isRef = isRef;
+}
+
+/**
+ * Get the m_isRef flag.
+ * @return true if is reference, otherwise false
+ */
+bool UMLClassifier::isReference() const
+{
+ return m_isRef;
+}
+
+/**
+ * Return true if this classifier has associations.
+ * @return true if classifier has associations
+ */
+bool UMLClassifier::hasAssociations()
+{
+ return getSpecificAssocs(AssociationType::Association).count() > 0
+ || getAggregations().count() > 0
+ || getCompositions().count() > 0
+ || getUniAssociationToBeImplemented().count() > 0;
+}
+
+/**
+ * Return true if this classifier has attributes.
+ */
+bool UMLClassifier::hasAttributes()
+{
+ return getAttributeList(Uml::Visibility::Public).count() > 0
+ || getAttributeList(Uml::Visibility::Protected).count() > 0
+ || getAttributeList(Uml::Visibility::Private).count() > 0
+ || getAttributeListStatic(Uml::Visibility::Public).count() > 0
+ || getAttributeListStatic(Uml::Visibility::Protected).count() > 0
+ || getAttributeListStatic(Uml::Visibility::Private).count() > 0;
+}
+
+/**
+ * Return true if this classifier has static attributes.
+ */
+bool UMLClassifier::hasStaticAttributes()
+{
+ return getAttributeListStatic(Uml::Visibility::Public).count() > 0
+ || getAttributeListStatic(Uml::Visibility::Protected).count() > 0
+ || getAttributeListStatic(Uml::Visibility::Private).count() > 0;
+}
+
+/**
+ * Return true if this classifier has accessor methods.
+ */
+bool UMLClassifier::hasAccessorMethods()
+{
+ return hasAttributes() || hasAssociations();
+}
+
+/**
+ * Return true if this classifier has operation methods.
+ */
+bool UMLClassifier::hasOperationMethods()
+{
+ return getOpList().last() ? true : false;
+}
+
+/**
+ * Return true if this classifier has methods.
+ */
+bool UMLClassifier::hasMethods()
+{
+ return hasOperationMethods() || hasAccessorMethods();
+}
+
+// this is a bit too simplistic..some associations are for
+// SINGLE objects, and WONT be declared as Vectors, so this
+// is a bit overly inclusive (I guess that's better than the other way around)
+
+/**
+ * Return true if this classifier has vector fields.
+ */
+bool UMLClassifier::hasVectorFields()
+{
+ return hasAssociations();
+}
+
+/**
+ * Return the list of unidirectional association that should show up in the code
+ */
+UMLAssociationList UMLClassifier::getUniAssociationToBeImplemented()
+{
+ UMLAssociationList associations = getSpecificAssocs(AssociationType::UniAssociation);
+ UMLAssociationList uniAssocListToBeImplemented;
+
+ foreach (UMLAssociation *a, associations) {
+ uIgnoreZeroPointer(a);
+ if (a->getObjectId(RoleType::B) == id()) {
+ continue; // we need to be at the A side
+ }
+ QString roleNameB = a->getRoleName(RoleType::B);
+ if (!roleNameB.isEmpty()) {
+ UMLAttributeList atl = getAttributeList();
+ bool found = false;
+ //make sure that an attribute with the same name doesn't already exist
+ foreach (UMLAttribute *at, atl) {
+ uIgnoreZeroPointer(a);
+ if (at->name() == roleNameB) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ uniAssocListToBeImplemented.append(a);
+ }
+ }
+ }
+ return uniAssocListToBeImplemented;
+}
+
+/**
+ * Creates XML tag <UML:Class>, <UML:Interface>, or <UML:DataType>
+ * depending on m_BaseType.
+ * Saves possible template parameters, generalizations, attributes,
+ * operations, and contained objects to the given QDomElement.
+ */
+void UMLClassifier::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QString tag;
+ switch (m_BaseType) {
+ case UMLObject::ot_Class:
+ tag = QLatin1String("UML:Class");
+ break;
+ case UMLObject::ot_Interface:
+ tag = QLatin1String("UML:Interface");
+ break;
+ case UMLObject::ot_Datatype:
+ tag = QLatin1String("UML:DataType");
+ break;
+ case UMLObject::ot_Package:
+ UMLPackage::saveToXMI(qDoc, qElement);
+ return;
+ break;
+ default:
+ uError() << "internal error: basetype is " << m_BaseType;
+ return;
+ }
+ QDomElement classifierElement = UMLObject::save(tag, qDoc);
+ if (m_BaseType == UMLObject::ot_Datatype && m_pSecondary != NULL)
+ classifierElement.setAttribute(QLatin1String("elementReference"),
+ Uml::ID::toString(m_pSecondary->id()));
+
+ //save templates
+ UMLClassifierListItemList list = getFilteredList(UMLObject::ot_Template);
+ if (list.count()) {
+ QDomElement tmplElement = qDoc.createElement(QLatin1String("UML:ModelElement.templateParameter"));
+ foreach (UMLClassifierListItem *tmpl, list) {
+ tmpl->saveToXMI(qDoc, tmplElement);
+ }
+ classifierElement.appendChild(tmplElement);
+ }
+
+ //save generalizations (we are the subclass, the other end is the superclass)
+ UMLAssociationList generalizations = getSpecificAssocs(AssociationType::Generalization);
+ if (generalizations.count()) {
+ QDomElement genElement = qDoc.createElement(QLatin1String("UML:GeneralizableElement.generalization"));
+ foreach (UMLAssociation *a, generalizations) {
+ // We are the subclass if we are at the role A end.
+ if (m_nId != a->getObjectId(RoleType::A)) {
+ continue;
+ }
+ QDomElement gElem = qDoc.createElement(QLatin1String("UML:Generalization"));
+ gElem.setAttribute(QLatin1String("xmi.idref"), Uml::ID::toString(a->id()));
+ genElement.appendChild(gElem);
+ }
+ if (genElement.hasChildNodes()) {
+ classifierElement.appendChild(genElement);
+ }
+ }
+
+ // save attributes
+ QDomElement featureElement = qDoc.createElement(QLatin1String("UML:Classifier.feature"));
+ UMLClassifierListItemList attList = getFilteredList(UMLObject::ot_Attribute);
+ foreach (UMLClassifierListItem *pAtt, attList) {
+ pAtt->saveToXMI(qDoc, featureElement);
+ }
+
+ // save operations
+ UMLOperationList opList = getOpList();
+ foreach (UMLOperation *pOp, opList) {
+ pOp->saveToXMI(qDoc, featureElement);
+ }
+ if (featureElement.hasChildNodes()) {
+ classifierElement.appendChild(featureElement);
+ }
+
+ // save contained objects
+ if (m_objects.count()) {
+ QDomElement ownedElement = qDoc.createElement(QLatin1String("UML:Namespace.ownedElement"));
+ foreach (UMLObject* obj, m_objects) {
+ uIgnoreZeroPointer(obj);
+ obj->saveToXMI (qDoc, ownedElement);
+ }
+ classifierElement.appendChild(ownedElement);
+ }
+ qElement.appendChild(classifierElement);
+}
+
+/**
+ * Create a new ClassifierListObject (attribute, operation, template)
+ * according to the given XMI tag.
+ * Returns NULL if the string given does not contain one of the tags
+ * <UML:Attribute>, <UML:Operation>, or <UML:TemplateParameter>.
+ * Used by the clipboard for paste operation.
+ */
+UMLClassifierListItem* UMLClassifier::makeChildObject(const QString& xmiTag)
+{
+ UMLClassifierListItem* pObject = NULL;
+ if (UMLDoc::tagEq(xmiTag, QLatin1String("Operation")) ||
+ UMLDoc::tagEq(xmiTag, QLatin1String("ownedOperation"))) {
+ pObject = new UMLOperation(this);
+ } else if (UMLDoc::tagEq(xmiTag, QLatin1String("Attribute")) ||
+ UMLDoc::tagEq(xmiTag, QLatin1String("ownedAttribute"))) {
+ if (baseType() != UMLObject::ot_Class)
+ return NULL;
+ pObject = new UMLAttribute(this);
+ } else if (UMLDoc::tagEq(xmiTag, QLatin1String("TemplateParameter"))) {
+ pObject = new UMLTemplate(this);
+ }
+ return pObject;
+}
+
+/**
+ * Auxiliary to loadFromXMI:
+ * The loading of operations is implemented here.
+ * Calls loadSpecialized() for any other tag.
+ * Child classes can override the loadSpecialized method
+ * to load its additional tags.
+ */
+bool UMLClassifier::load(QDomElement& element)
+{
+ UMLClassifierListItem *child = NULL;
+ m_SecondaryId = element.attribute(QLatin1String("elementReference"));
+ if (!m_SecondaryId.isEmpty()) {
+ // @todo We do not currently support composition.
+ m_isRef = true;
+ }
+ bool totalSuccess = true;
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ element = node.toElement();
+ QString tag = element.tagName();
+ QString stereotype = element.attribute(QLatin1String("stereotype"));
+ if (UMLDoc::tagEq(tag, QLatin1String("ModelElement.templateParameter")) ||
+ UMLDoc::tagEq(tag, QLatin1String("Classifier.feature")) ||
+ UMLDoc::tagEq(tag, QLatin1String("Namespace.ownedElement")) ||
+ UMLDoc::tagEq(tag, QLatin1String("Element.ownedElement")) || // Embarcadero's Describe
+ UMLDoc::tagEq(tag, QLatin1String("Namespace.contents"))) {
+ load(element);
+ // Not evaluating the return value from load()
+ // because we want a best effort.
+
+ } else if ((child = makeChildObject(tag)) != NULL) {
+ if (child->loadFromXMI(element)) {
+ switch (child->baseType()) {
+ case UMLObject::ot_Template:
+ addTemplate(static_cast<UMLTemplate*>(child));
+ break;
+ case UMLObject::ot_Operation:
+ if (! addOperation(static_cast<UMLOperation*>(child))) {
+ uError() << "error from addOperation(op)";
+ delete child;
+ totalSuccess = false;
+ }
+ break;
+ case UMLObject::ot_Attribute:
+ addAttribute(static_cast<UMLAttribute*>(child));
+ break;
+ default:
+ break;
+ }
+ } else {
+ uWarning() << "failed to load " << tag;
+ delete child;
+ totalSuccess = false;
+ }
+ } else if (!Model_Utils::isCommonXMIAttribute(tag)) {
+ UMLObject *pObject = Object_Factory::makeObjectFromXMI(tag, stereotype);
+ if (pObject == NULL) {
+ // Not setting totalSuccess to false
+ // because we want a best effort.
+ continue;
+ }
+ pObject->setUMLPackage(this);
+ if (! pObject->loadFromXMI(element)) {
+ removeObject(pObject);
+ delete pObject;
+ totalSuccess = false;
+ }
+ }
+ }
+ return totalSuccess;
+}
+
+/*
+UMLClassifierList UMLClassifier::getPlainAssocChildClassifierList()
+{
+ UMLAssociationList plainAssociations = getSpecificAssocs(Uml::AssociationType::Association);
+ return findAssocClassifierObjsInRoles(&plainAssociations);
+}
+
+UMLClassifierList UMLClassifier::getAggregateChildClassifierList()
+{
+ UMLAssociationList aggregations = getAggregations();
+ return findAssocClassifierObjsInRoles(&aggregations);
+}
+
+UMLClassifierList UMLClassifier::getCompositionChildClassifierList()
+{
+ UMLAssociationList compositions = getCompositions();
+ return findAssocClassifierObjsInRoles(&compositions);
+}
+
+UMLClassifierList UMLClassifier::findAssocClassifierObjsInRoles (UMLAssociationList * list)
+{
+ UMLClassifierList classifiers;
+
+ for (UMLAssociationListIt alit(*list); alit.hasNext(); ) {
+ UMLAssociation* a = alit.next();
+ // DON'T accept a classifier IF the association role is empty, by
+ // convention, that means to ignore the classifier on that end of
+ // the association.
+ // We also ignore classifiers which are the same as the current one
+ // (e.g. id matches), we only want the "other" classifiers
+ if (a->getObjectId(RoleType::A) == id() && !a->getRoleName(RoleType::B).isEmpty()) {
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(RoleType::B));
+ if(c)
+ classifiers.append(c);
+ } else if (a->getObjectId(RoleType::B) == id() && !a->getRoleName(RoleType::A).isEmpty()) {
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(RoleType::A));
+ if(c)
+ classifiers.append(c);
+ }
+ }
+
+ return classifiers;
+}
+*/
+
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/classifier.h umbrello-kf6-15.08.1/umbrello/umlmodel/classifier.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/classifier.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/classifier.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,199 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+#ifndef CLASSIFIER_H
+#define CLASSIFIER_H
+
+#include "package.h"
+#include "umlattributelist.h"
+#include "umloperationlist.h"
+#include "umlclassifierlistitemlist.h"
+#include "classifierlistitem.h"
+#include "umltemplatelist.h"
+#include "model_utils.h"
+
+// forward declarations
+class UMLAssociation;
+class IDChangeLog;
+class UMLClassifierSet;
+
+/**
+ * This class defines the non-graphical information required for a
+ * UML Classifier (ie a class or interface).
+ * This class inherits from @ref UMLPackage which allows classifiers
+ * to also act as namespaces, i.e. it allows classifiers to nest.
+ *
+ * NOTE: There is a unit test available for this class.
+ * Please, use and adapt it when necessary.
+ *
+ * @short Information for a non-graphical Concept/Class.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLClassifier : public UMLPackage
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Enumeration identifying the type of classifier.
+ */
+ enum ClassifierType { ALL = 0, CLASS, INTERFACE, DATATYPE };
+
+ explicit UMLClassifier(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLClassifier();
+
+ bool operator==(const UMLClassifier & rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ UMLObject* clone() const;
+
+ virtual UMLAttribute* createAttribute(const QString &name = QString(),
+ UMLObject *type = 0,
+ Uml::Visibility::Enum vis = Uml::Visibility::Private,
+ const QString &init = QString());
+
+ UMLAttribute* addAttribute(const QString &name, Uml::ID::Type id = Uml::ID::None);
+ UMLAttribute* addAttribute(const QString &name, UMLObject *type, Uml::Visibility::Enum scope);
+
+ bool addAttribute(UMLAttribute* att, IDChangeLog* log = 0,
+ int position = -1);
+
+ int removeAttribute(UMLAttribute *att);
+
+ int attributes() ;
+
+ UMLAttributeList getAttributeList() const;
+ UMLAttributeList getAttributeList(Uml::Visibility::Enum scope) const;
+ UMLAttributeList getAttributeListStatic(Uml::Visibility::Enum scope) const;
+
+ UMLOperation* createOperation(const QString &name = QString(),
+ bool *isExistingOp = NULL,
+ Model_Utils::NameAndType_List *params = NULL);
+
+ bool addOperation(UMLOperation* op, int position = -1);
+ bool addOperation(UMLOperation* op, IDChangeLog* log);
+
+ UMLOperation * checkOperationSignature(const QString& name,
+ UMLAttributeList opParams,
+ UMLOperation *exemptOp = NULL);
+
+ int removeOperation(UMLOperation *op);
+
+ int operations();
+
+ UMLOperationList getOpList(bool includeInherited = false, UMLClassifierSet *alreadyTraversed = 0);
+
+ UMLObject* createTemplate(const QString& name = QString());
+
+ UMLTemplate* addTemplate(const QString &name, Uml::ID::Type id = Uml::ID::None);
+
+ bool addTemplate(UMLTemplate* newTemplate, IDChangeLog* log = 0);
+ bool addTemplate(UMLTemplate* templt, int position);
+
+ int removeTemplate(UMLTemplate* umltemplate);
+
+ UMLTemplate *findTemplate(const QString& name);
+
+ int templates();
+
+ UMLTemplateList getTemplateList() const;
+
+ int takeItem(UMLClassifierListItem* item);
+
+ virtual UMLClassifierListItemList getFilteredList(UMLObject::ObjectType ot) const;
+
+ virtual bool resolveRef();
+
+ UMLOperationList findOperations(const QString &n);
+
+ virtual UMLObject* findChildObjectById(Uml::ID::Type id, bool considerAncestors = false);
+
+ UMLOperation* findOperation(const QString& name,
+ Model_Utils::NameAndType_List params);
+
+ UMLClassifierList findSuperClassConcepts(ClassifierType type = ALL);
+
+ UMLClassifierList findSubClassConcepts(ClassifierType type = ALL);
+
+ virtual bool acceptAssociationType(Uml::AssociationType::Enum type);
+
+ void setClassAssoc(UMLAssociation *assoc);
+ UMLAssociation *getClassAssoc() const;
+
+ void setBaseType(UMLObject::ObjectType ot);
+
+ bool isInterface() const;
+
+ bool isDatatype() const;
+
+ void setOriginType(UMLClassifier *origType);
+ UMLClassifier * originType() const;
+
+ void setIsReference(bool isRef = true);
+ bool isReference() const;
+
+ bool hasAbstractOps();
+ bool hasAssociations();
+ bool hasAttributes();
+ bool hasStaticAttributes();
+ bool hasMethods();
+ bool hasAccessorMethods();
+ bool hasOperationMethods();
+ bool hasVectorFields();
+
+ /**
+ * utility functions to allow easy determination of what classifiers
+ * are "owned" by the current one via named association type (e.g.
+ * plain, aggregate or compositions).
+ */
+// UMLClassifierList getPlainAssocChildClassifierList();
+// UMLClassifierList getAggregateChildClassifierList();
+// UMLClassifierList getCompositionChildClassifierList();
+
+ virtual UMLClassifierListItem* makeChildObject(const QString& xmiTag);
+
+ virtual UMLAssociationList getUniAssociationToBeImplemented();
+
+signals:
+
+ void operationAdded(UMLClassifierListItem *);
+ void operationRemoved(UMLClassifierListItem *);
+
+ void templateAdded(UMLClassifierListItem*);
+ void templateRemoved(UMLClassifierListItem*);
+
+ // only applies when (m_Type == ot_Class)
+ void attributeAdded(UMLClassifierListItem*);
+ void attributeRemoved(UMLClassifierListItem*);
+
+private:
+
+ UMLAssociation *m_pClassAssoc;
+
+ bool m_isRef;
+
+ /**
+ * Utility method called by "get*ChildClassfierList()" methods. It basically
+ * finds all the classifiers named in each association in the given association list
+ * which aren't the current one. Useful for finding which classifiers are "owned" by the
+ * current one via declared associations such as in aggregations/compositions.
+ */
+// UMLClassifierList findAssocClassifierObjsInRoles (UMLAssociationList * list);
+
+protected:
+
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ virtual bool load(QDomElement& element);
+
+};
+
+#endif // CLASSIFIER_H
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/classifierlistitem.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/classifierlistitem.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/classifierlistitem.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/classifierlistitem.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,159 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "classifierlistitem.h"
+
+// local includes
+#include "debug_utils.h"
+#include "classifier.h"
+#include "model_utils.h"
+#include "object_factory.h"
+#include "uml.h"
+#include "umldoc.h"
+
+// kde includes
+#include <KLocalizedString>
+
+/**
+ * Constructor.
+ *
+ * @param parent The parent to this operation.
+ * At first sight it would appear that the type of the
+ * parent should be UMLClassifier. However, the class
+ * UMLAttribute is also used for the parameters of
+ * operations, and in this case the UMLOperation is the
+ * parent.
+ * @param name The name of the operation.
+ * @param id The id of the operation.
+ */
+UMLClassifierListItem::UMLClassifierListItem(UMLObject *parent,
+ const QString& name, Uml::ID::Type id)
+ : UMLObject(parent, name, id)
+{
+ UMLObject *parentObj = const_cast<UMLObject*>(parent);
+ UMLClassifier *pc = dynamic_cast<UMLClassifier*>(parentObj);
+ if (pc)
+ UMLObject::setUMLPackage(pc);
+}
+
+/**
+ * Constructor.
+ *
+ * @param parent The parent to this operation.
+ * At first sight it would appear that the type of the
+ * parent should be UMLClassifier. However, the class
+ * UMLAttribute is also used for the parameters of
+ * operations, and in this case the UMLOperation is the
+ * parent.
+ */
+UMLClassifierListItem::UMLClassifierListItem(UMLObject *parent)
+ : UMLObject(parent)
+{
+ UMLObject *parentObj = const_cast<UMLObject*>(parent);
+ UMLClassifier *pc = dynamic_cast<UMLClassifier*>(parentObj);
+ if (pc)
+ UMLObject::setUMLPackage(pc);
+}
+
+/**
+ * Destructor. Empty.
+ */
+UMLClassifierListItem::~UMLClassifierListItem()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLClassifierListItem::copyInto(UMLObject *lhs) const
+{
+ // Call the parent.
+ UMLObject::copyInto(lhs);
+}
+
+/**
+ * Returns a string representation of the list item.
+ *
+ * @param sig What type of operation string to show.
+ * @return The string representation of the operation.
+ */
+QString UMLClassifierListItem::toString(Uml::SignatureType::Enum sig)
+{
+ Q_UNUSED(sig);
+ return name();
+}
+
+/**
+ * Returns the type of the UMLClassifierListItem.
+ *
+ * @return The type of the UMLClassifierListItem.
+ */
+UMLClassifier * UMLClassifierListItem::getType() const
+{
+ return dynamic_cast<UMLClassifier*>(m_pSecondary.data());
+}
+
+/**
+ * Returns the type name of the UMLClassifierListItem.
+ *
+ * @return The type name of the UMLClassifierListItem.
+ */
+QString UMLClassifierListItem::getTypeName() const
+{
+ if (m_pSecondary == NULL)
+ return m_SecondaryId;
+ const UMLPackage *typePkg = m_pSecondary->umlPackage();
+ if (typePkg != NULL && typePkg != m_pUMLPackage)
+ return m_pSecondary->fullyQualifiedName();
+ return m_pSecondary->name();
+}
+
+/**
+ * Sets the type of the UMLAttribute.
+ *
+ * @param type Pointer to the UMLObject of the type.
+ */
+void UMLClassifierListItem::setType(UMLObject *type)
+{
+ if (m_pSecondary != type) {
+ m_pSecondary = type;
+ UMLObject::emitModified();
+ }
+}
+
+/**
+ * Sets the type name of the UMLClassifierListItem.
+ * DEPRECATED - use setType() instead.
+ *
+ * @param type The type name of the UMLClassifierListItem.
+ */
+void UMLClassifierListItem::setTypeName(const QString &type)
+{
+ if (type.isEmpty() || type == QLatin1String("void")) {
+ m_pSecondary = NULL;
+ m_SecondaryId.clear();
+ return;
+ }
+ UMLDoc *pDoc = UMLApp::app()->document();
+ m_pSecondary = pDoc->findUMLObject(type);
+ if (m_pSecondary == NULL) {
+ // Make data type for easily identified cases
+ if (Model_Utils::isCommonDataType(type) || type.contains(QLatin1Char('*'))) {
+ m_pSecondary = Object_Factory::createUMLObject(UMLObject::ot_Datatype, type);
+ uDebug() << "created datatype for " << type;
+ } else {
+ m_SecondaryId = type;
+ }
+ }
+ UMLObject::emitModified();
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/classifierlistitem.h umbrello-kf6-15.08.1/umbrello/umlmodel/classifierlistitem.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/classifierlistitem.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/classifierlistitem.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef CLASSIFIERLISTITEM_H
+#define CLASSIFIERLISTITEM_H
+
+#include "umlobject.h"
+
+// forward declaration
+class UMLClassifier;
+
+/**
+ * Classifiers (classes, interfaces) have lists of operations,
+ * attributes, templates and others. This is a base class for
+ * the items in this list. This abstraction should remove
+ * duplication of dialogs and allow for stereotypes in lists.
+ *
+ * @short A base class for classifier list items (e.g. attributes)
+ * @author Jonathan Riddell
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLClassifierListItem : public UMLObject
+{
+ Q_OBJECT
+public:
+
+ UMLClassifierListItem(UMLObject *parent,
+ const QString& name,
+ Uml::ID::Type id = Uml::ID::None);
+ explicit UMLClassifierListItem(UMLObject *parent);
+ virtual ~UMLClassifierListItem();
+
+ virtual void setType(UMLObject *type);
+ UMLClassifier * getType() const;
+
+ void setTypeName(const QString &type);
+ virtual QString getTypeName() const;
+
+ virtual QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ /**
+ * The abstract method UMLObject::clone() must be implemented
+ * by the classes inheriting from UMLClassifierListItem.
+ */
+ virtual UMLObject* clone() const = 0;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/component.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/component.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/component.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/component.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "component.h"
+// app includes
+#include "association.h"
+#include "debug_utils.h"
+#include "object_factory.h"
+#include "model_utils.h"
+#include "clipboard/idchangelog.h"
+#include "umldoc.h"
+// kde includes
+#include <KLocalizedString>
+
+/**
+ * Sets up a Component.
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+UMLComponent::UMLComponent(const QString & name, Uml::ID::Type id)
+ : UMLPackage(name, id),
+ m_executable(false)
+{
+ m_BaseType = UMLObject::ot_Component;
+}
+
+/**
+ * Destructor.
+ */
+UMLComponent::~UMLComponent()
+{
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLComponent::clone() const
+{
+ UMLComponent *clone = new UMLComponent();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+/**
+ * Creates the UML:Component element including its operations,
+ * attributes and templates
+ */
+void UMLComponent::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement componentElement = UMLObject::save(QLatin1String("UML:Component"), qDoc);
+ componentElement.setAttribute(QLatin1String("executable"), m_executable);
+ // Save contained components if any.
+ if (m_objects.count()) {
+ QDomElement ownedElement = qDoc.createElement(QLatin1String("UML:Namespace.ownedElement"));
+ for (UMLObjectListIt objectsIt(m_objects); objectsIt.hasNext();) {
+ UMLObject* obj = objectsIt.next();
+ uIgnoreZeroPointer(obj);
+ obj->saveToXMI (qDoc, ownedElement);
+ }
+ componentElement.appendChild(ownedElement);
+ }
+ qElement.appendChild(componentElement);
+}
+
+/**
+ * Loads the UML:Component element including its ports et al.
+ */
+bool UMLComponent::load(QDomElement& element)
+{
+ QString executable = element.attribute(QLatin1String("executable"), QLatin1String("0"));
+ m_executable = (bool)executable.toInt();
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString type = tempElement.tagName();
+ if (Model_Utils::isCommonXMIAttribute(type))
+ continue;
+ if (UMLDoc::tagEq(type, QLatin1String("Namespace.ownedElement")) ||
+ UMLDoc::tagEq(type, QLatin1String("Namespace.contents"))) {
+ //CHECK: umbrello-kf6 currently assumes that nested elements
+ // are ownedElements anyway.
+ // Therefore these tags are not further interpreted.
+ if (! load(tempElement))
+ return false;
+ continue;
+ }
+ UMLObject *pObject = Object_Factory::makeObjectFromXMI(type);
+ if (!pObject) {
+ uWarning() << "Unknown type of umlobject to create: " << type;
+ continue;
+ }
+ pObject->setUMLPackage(this);
+ if (pObject->loadFromXMI(tempElement)) {
+ addObject(pObject);
+ } else {
+ delete pObject;
+ }
+ }
+ return true;
+}
+
+/**
+ * Sets m_executable.
+ */
+void UMLComponent::setExecutable(bool executable)
+{
+ m_executable = executable;
+}
+
+/**
+ * Returns the value of m_executable.
+ */
+bool UMLComponent::getExecutable()
+{
+ return m_executable;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/component.h umbrello-kf6-15.08.1/umbrello/umlmodel/component.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/component.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/component.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef COMPONENT_H
+#define COMPONENT_H
+
+#include "package.h"
+
+/**
+ * This class contains the non-graphical information required for a
+ * UML Component.
+ * This class inherits from @ref UMLPackage which contains most
+ * of the information.
+ *
+ * @short Non-graphical information for a Component.
+ * @author Jonathan Riddell
+ * @see UMLCanvasObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLComponent : public UMLPackage
+{
+ Q_OBJECT
+public:
+ explicit UMLComponent(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLComponent();
+
+ virtual UMLObject* clone() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ void setExecutable(bool executable);
+ bool getExecutable();
+
+protected:
+ bool load(QDomElement & element);
+
+private:
+ bool m_executable; ///< holds whether this is an executable component or not
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entityattribute.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/entityattribute.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entityattribute.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/entityattribute.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,280 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "entityattribute.h"
+
+// app includes
+#include "debug_utils.h"
+//#include "umlcanvasobject.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "umlentityattributedialog.h"
+#include "object_factory.h"
+
+// qt includes
+#include <QRegExp>
+
+/**
+ * Sets up an entityattribute.
+ * @param parent The parent of this UMLEntityAttribute.
+ * @param name The name of this UMLEntityAttribute.
+ * @param id The unique id given to this UMLEntityAttribute.
+ * @param s The visibility of the UMLEntityAttribute.
+ * @param type The type of this UMLEntityAttribute.
+ * @param iv The initial value of the entityattribute.
+ */
+UMLEntityAttribute::UMLEntityAttribute(UMLObject *parent, const QString& name,
+ Uml::ID::Type id, Uml::Visibility::Enum s,
+ UMLObject *type, const QString& iv)
+ : UMLAttribute(parent, name, id, s, type, iv)
+{
+ init();
+ if (m_pSecondary) {
+ m_pSecondary->setBaseType(UMLObject::ot_Entity);
+ }
+}
+
+/**
+ * Sets up an entityattribute.
+ * @param parent The parent of this UMLEntityAttribute.
+ */
+UMLEntityAttribute::UMLEntityAttribute(UMLObject *parent)
+ : UMLAttribute(parent)
+{
+ init();
+}
+
+/**
+ * Destructor.
+ */
+UMLEntityAttribute::~UMLEntityAttribute()
+{
+}
+
+/**
+ * Initialize members of this class.
+ * Auxiliary method used by constructors.
+ */
+void UMLEntityAttribute::init()
+{
+ m_BaseType = UMLObject::ot_EntityAttribute;
+ m_indexType = UMLEntityAttribute::None;
+ m_autoIncrement = false;
+ m_null = false;
+}
+
+/**
+ * Returns the value of the UMLEntityAttribute's attributes property.
+ * @return The value of the UMLEntityAttribute's attributes property.
+ */
+QString UMLEntityAttribute::getAttributes() const
+{
+ return m_attributes;
+}
+
+/**
+ * Sets the UMLEntityAttribute's attributes property.
+ * @param attributes The new value for the attributes property.
+ */
+void UMLEntityAttribute::setAttributes(const QString& attributes)
+{
+ m_attributes = attributes;
+}
+
+/**
+ * Returns the UMLEntityAttribute's length/values property.
+ * @return The new value of the length/values property.
+ */
+QString UMLEntityAttribute::getValues() const
+{
+ return m_values;
+}
+
+/**
+ * Sets the UMLEntityAttribute's length/values property.
+ * @param values The new value of the length/values property.
+ */
+void UMLEntityAttribute::setValues(const QString& values)
+{
+ m_values = values;
+}
+
+/**
+ * Returns the UMLEntityAttribute's auto_increment boolean
+ * @return The UMLEntityAttribute's auto_increment boolean
+ */
+bool UMLEntityAttribute::getAutoIncrement() const
+{
+ return m_autoIncrement;
+}
+
+/**
+ * Sets the UMLEntityAttribute's auto_increment boolean
+ * @param autoIncrement The UMLEntityAttribute's auto_increment boolean
+ */
+void UMLEntityAttribute::setAutoIncrement(const bool autoIncrement)
+{
+ m_autoIncrement = autoIncrement;
+}
+
+/**
+ * Returns the UMLEntityAttribute's index type property.
+ * @return The value of the UMLEntityAttribute's index type property.
+ */
+UMLEntityAttribute::DBIndex_Type UMLEntityAttribute::indexType() const
+{
+ return m_indexType;
+}
+
+/**
+ * Sets the initial value of the UMLEntityAttribute's index type property.
+ * @param indexType The initial value of the UMLEntityAttribute's index type property.
+ */
+void UMLEntityAttribute::setIndexType(const UMLEntityAttribute::DBIndex_Type indexType)
+{
+ m_indexType = indexType;
+}
+
+/**
+ * Returns the UMLEntityAttribute's allow null value.
+ * @return The UMLEntityAttribute's allow null value.
+ */
+bool UMLEntityAttribute::getNull() const
+{
+ return m_null;
+}
+
+/**
+ * Sets the initial value of the UMLEntityAttribute's allow null value.
+ * @param nullIn The initial value of the UMLEntityAttribute's allow null value.
+ */
+void UMLEntityAttribute::setNull(const bool nullIn)
+{
+ m_null = nullIn;
+}
+
+/**
+ * Returns a string representation of the UMLEntityAttribute.
+ * @param sig If true will show the entityattribute type and initial value.
+ * @return Returns a string representation of the UMLEntityAttribute.
+ */
+QString UMLEntityAttribute::toString(Uml::SignatureType::Enum sig)
+{
+ QString s;
+ //FIXME
+
+ if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::NoSig) {
+ s = Uml::Visibility::toString(m_visibility, true) + QLatin1Char(' ');
+ }
+
+ if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::SigNoVis) {
+ QString string = s + name() + QLatin1String(" : ") + getTypeName();
+ if(m_InitialValue.length() > 0)
+ string += QLatin1String(" = ") + m_InitialValue;
+ return string;
+ } else
+ return s + name();
+}
+
+/**
+ * Overloaded '==' operator
+ */
+bool UMLEntityAttribute::operator==(const UMLEntityAttribute &rhs) const
+{
+ if(this == &rhs)
+ return true;
+
+ if(!UMLObject::operator==(rhs))
+ return false;
+
+ // The type name is the only distinguishing criterion.
+ // (Some programming languages might support more, but others don't.)
+ if (m_pSecondary != rhs.m_pSecondary)
+ return false;
+
+ return true;
+}
+
+/**
+ * Copy the internal presentation of this object into the UMLEntityAttribute
+ * object.
+ */
+void UMLEntityAttribute::copyInto(UMLObject *lhs) const
+{
+ UMLEntityAttribute *target = static_cast<UMLEntityAttribute*>(lhs);
+
+ // call the parent first.
+ UMLClassifierListItem::copyInto(target);
+
+ // Copy all datamembers
+ target->m_pSecondary = m_pSecondary;
+ target->m_SecondaryId = m_SecondaryId;
+ target->m_InitialValue = m_InitialValue;
+ target->m_ParmKind = m_ParmKind;
+}
+
+/**
+ * Make a clone of the UMLEntityAttribute.
+ */
+UMLObject* UMLEntityAttribute::clone() const
+{
+ UMLEntityAttribute* clone = new UMLEntityAttribute((UMLEntityAttribute*)parent());
+ copyInto(clone);
+
+ return clone;
+}
+
+/**
+ * Creates the <UML:EntityAttribute> XMI element.
+ */
+void UMLEntityAttribute::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement entityattributeElement = UMLObject::save(QLatin1String("UML:EntityAttribute"), qDoc);
+ if (m_pSecondary == NULL) {
+ uDebug() << name() << ": m_pSecondary is NULL, using local name " << m_SecondaryId;
+ entityattributeElement.setAttribute(QLatin1String("type"), m_SecondaryId);
+ } else {
+ entityattributeElement.setAttribute(QLatin1String("type"), Uml::ID::toString(m_pSecondary->id()));
+ }
+ entityattributeElement.setAttribute(QLatin1String("initialValue"), m_InitialValue);
+ entityattributeElement.setAttribute(QLatin1String("dbindex_type"), m_indexType);
+ entityattributeElement.setAttribute(QLatin1String("values"), m_values);
+ entityattributeElement.setAttribute(QLatin1String("attributes"), m_attributes);
+ entityattributeElement.setAttribute(QLatin1String("auto_increment"), m_autoIncrement);
+ entityattributeElement.setAttribute(QLatin1String("allow_null"), m_null);
+ qElement.appendChild(entityattributeElement);
+}
+
+/**
+ * Loads the <UML:EntityAttribute> XMI element.
+ */
+bool UMLEntityAttribute::load(QDomElement & element)
+{
+ if (! UMLAttribute::load(element))
+ return false;
+ int indexType = element.attribute(QLatin1String("dbindex_type"), QLatin1String("1100")).toInt();
+ m_indexType = (UMLEntityAttribute::DBIndex_Type)indexType;
+ m_values = element.attribute(QLatin1String("values"));
+ m_attributes = element.attribute(QLatin1String("attributes"));
+ m_autoIncrement = (bool)element.attribute(QLatin1String("auto_increment")).toInt();
+ m_null = (bool)element.attribute(QLatin1String("allow_null")).toInt();
+ return true;
+}
+
+/**
+ * Display the properties configuration dialog for the entityattribute.
+ */
+bool UMLEntityAttribute::showPropertiesDialog(QWidget* parent)
+{
+ UMLEntityAttributeDialog dialog(parent, this);
+ return dialog.exec();
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entityattribute.h umbrello-kf6-15.08.1/umbrello/umlmodel/entityattribute.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entityattribute.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/entityattribute.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ENTITYATTRIBUTE_H
+#define ENTITYATTRIBUTE_H
+
+#include "attribute.h"
+#include "basictypes.h"
+
+/**
+ * This class is used to set up information for an entityattribute. This is a database field
+ * It has a type, name, index type and default value.
+ *
+ * @short Sets up entityattribute information.
+ * @author Jonathan Riddell <jr@jriddell.org>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLEntityAttribute : public UMLAttribute
+{
+ Q_OBJECT
+ Q_ENUMS(DBIndex_Type)
+public:
+ enum DBIndex_Type
+ {
+ None = 1100,
+ Primary,
+ Index,
+ Unique
+ };
+
+ UMLEntityAttribute(UMLObject* parent, const QString& name,
+ Uml::ID::Type id = Uml::ID::None,
+ Uml::Visibility::Enum s = Uml::Visibility::Private,
+ UMLObject *type = 0, const QString& iv = QString());
+ explicit UMLEntityAttribute(UMLObject* parent);
+ virtual ~UMLEntityAttribute();
+
+ bool operator==(const UMLEntityAttribute& rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ void setAttributes(const QString& attributes);
+ QString getAttributes() const;
+
+ void setIndexType(const DBIndex_Type indexType);
+ DBIndex_Type indexType() const;
+
+ void setValues(const QString& values);
+ QString getValues() const;
+
+ void setAutoIncrement(const bool autoIncrement);
+ bool getAutoIncrement() const;
+
+ void setNull(const bool null);
+ bool getNull() const;
+
+ QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
+
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ virtual bool showPropertiesDialog(QWidget* parent = 0);
+
+protected:
+ void init();
+
+ bool load(QDomElement& element);
+
+private:
+ DBIndex_Type m_indexType;
+ QString m_values;
+ QString m_attributes;
+ bool m_autoIncrement;
+ bool m_null;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entityconstraint.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/entityconstraint.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entityconstraint.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/entityconstraint.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+//own header
+#include "entityconstraint.h"
+
+// app includes
+#include "umlobject.h"
+#include "umldoc.h"
+#include "uml.h"
+
+// qt includes
+#include <QRegExp>
+
+/**
+ * Sets up a constraint.
+ * @param parent The parent of this UMLEntityConstraint.
+ * @param name The name of this UMLEntityConstraint.
+ * @param id The unique id given to this UMLEntityConstraint.
+ */
+UMLEntityConstraint::UMLEntityConstraint(UMLObject *parent,
+ const QString& name, Uml::ID::Type id)
+ : UMLClassifierListItem(parent, name, id)
+{
+ m_BaseType = UMLObject::ot_EntityConstraint;
+}
+
+/**
+ * Sets up a constraint.
+ * @param parent The parent of this UMLEntityConstraint.
+ */
+UMLEntityConstraint::UMLEntityConstraint(UMLObject *parent)
+ : UMLClassifierListItem(parent)
+{
+ m_BaseType = UMLObject::ot_EntityConstraint;
+}
+
+/**
+ * Overloaded '==' operator
+ */
+bool UMLEntityConstraint::operator==(const UMLEntityConstraint &rhs) const
+{
+ if(this == &rhs)
+ return true;
+
+ if(!UMLObject::operator==(rhs))
+ return false;
+
+ return true;
+}
+
+/**
+ * destructor.
+ */
+UMLEntityConstraint::~UMLEntityConstraint()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the UMLEntityConstraint
+ * object.
+ */
+void UMLEntityConstraint::copyInto(UMLObject *lhs) const
+{
+ // call the parent first.
+ UMLClassifierListItem::copyInto(lhs);
+}
+
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entityconstraint.h umbrello-kf6-15.08.1/umbrello/umlmodel/entityconstraint.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entityconstraint.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/entityconstraint.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ENTITYCONSTRAINT_H
+#define ENTITYCONSTRAINT_H
+
+#include "basictypes.h"
+#include "classifierlistitem.h"
+#include "umlclassifierlist.h"
+
+/**
+ * This class is used to set up information for a entity constraint.
+ *
+ * @short Sets up entity constraint information.
+ * @author Sharan Rao
+ * @see UMLObject UMLClassifierListItem
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLEntityConstraint : public UMLClassifierListItem
+{
+ Q_OBJECT
+
+public:
+ UMLEntityConstraint(UMLObject *parent, const QString& name,
+ Uml::ID::Type id = Uml::ID::None);
+
+ explicit UMLEntityConstraint(UMLObject *parent);
+
+ bool operator==(const UMLEntityConstraint &rhs) const;
+
+ virtual ~UMLEntityConstraint();
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ /**
+ * Make a clone of the UMLEntityConstraint.
+ */
+ virtual UMLObject* clone() const = 0;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entity.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/entity.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entity.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/entity.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,719 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "entity.h"
+
+// app includes
+#include "debug_utils.h"
+#include "entityattribute.h"
+#include "uniqueconstraint.h"
+#include "foreignkeyconstraint.h"
+#include "checkconstraint.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "uniqueid.h"
+#include "umlentityattributelist.h"
+#include "umlentityconstraintlist.h"
+#include "idchangelog.h"
+#include "umlentityattributedialog.h"
+#include "umluniqueconstraintdialog.h"
+#include "umlforeignkeyconstraintdialog.h"
+#include "umlcheckconstraintdialog.h"
+
+// kde includes
+#include <KLocalizedString>
+#include <KMessageBox>
+
+// qt includes
+#include <QPointer>
+
+/**
+ * Constructor.
+ */
+UMLEntity::UMLEntity(const QString& name, Uml::ID::Type id)
+ : UMLClassifier(name, id),
+ m_PrimaryKey(0)
+{
+ m_BaseType = UMLObject::ot_Entity;
+ connect(this, SIGNAL(entityAttributeRemoved(UMLClassifierListItem*)),
+ this, SLOT(slotEntityAttributeRemoved(UMLClassifierListItem*)));
+}
+
+/**
+ * Standard destructor.
+ */
+UMLEntity::~UMLEntity()
+{
+ m_List.clear();
+}
+
+/**
+ * Overloaded '==' operator.
+ */
+bool UMLEntity::operator==(const UMLEntity& rhs) const
+{
+ return UMLClassifier::operator==(rhs);
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLEntity::copyInto(UMLObject *lhs) const
+{
+ UMLEntity *target = static_cast<UMLEntity*>(lhs);
+
+ // call base class copy function
+ UMLClassifier::copyInto(target);
+
+ // copy local data items
+ target->m_PrimaryKey = m_PrimaryKey;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLEntity::clone() const
+{
+ UMLEntity* clone = new UMLEntity();
+ copyInto(clone);
+
+ return clone;
+}
+
+/**
+ * Create an UMLAttribute.
+ * @param name an optional name for the attribute
+ * @param type an optional type object for the attribute
+ * @param vis the visibility of the attribute
+ * @param iv the initial value for the attribute
+ * @return the just created attribute or null
+ */
+UMLAttribute* UMLEntity::createAttribute(const QString &name /*= QString()*/, UMLObject *type /*= 0*/,
+ Uml::Visibility::Enum vis /* = Uml::Visibility::Private*/,
+ const QString& iv /* = QString()*/)
+{
+ Uml::ID::Type id = UniqueID::gen();
+ QString currentName;
+ if (name.isNull()) {
+ currentName = uniqChildName(UMLObject::ot_EntityAttribute);
+ } else {
+ currentName = name;
+ }
+
+ UMLEntityAttribute* newAttribute = new UMLEntityAttribute(this, currentName, id, vis, type, iv);
+
+ int button = QDialog::Accepted;
+ bool goodName = false;
+
+ //check for name.isNull() stops dialog being shown
+ //when creating attribute via list view
+ while (button == QDialog::Accepted && !goodName && name.isNull()) {
+ QPointer<UMLEntityAttributeDialog> dialog = new UMLEntityAttributeDialog(0, newAttribute);
+ button = dialog->exec();
+ QString name = newAttribute->name();
+
+ if (name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ } else if (findChildObject(name) != NULL) {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ } else {
+ goodName = true;
+ }
+ delete dialog;
+ }
+
+ if (button != QDialog::Accepted) {
+ delete newAttribute;
+ return 0;
+ }
+
+ addEntityAttribute(newAttribute);
+
+ UMLDoc *umldoc = UMLApp::app()->document();
+ umldoc->signalUMLObjectCreated(newAttribute);
+ return newAttribute;
+}
+
+/**
+ * Creates a Unique Constraint for this Entity.
+ * @param name an optional name
+ * @return the UniqueConstraint created
+ */
+UMLUniqueConstraint* UMLEntity::createUniqueConstraint(const QString &name)
+{
+ Uml::ID::Type id = UniqueID::gen();
+ QString currentName;
+ if (name.isNull()) {
+
+ /**
+ * @todo check parameter
+ */
+ currentName = uniqChildName(UMLObject::ot_UniqueConstraint);
+ } else {
+ currentName = name;
+ }
+
+ UMLUniqueConstraint* newUniqueConstraint = new UMLUniqueConstraint(this, currentName, id);
+
+ int button = QDialog::Accepted;
+ bool goodName = false;
+
+ //check for name.isNull() stops dialog being shown
+ //when creating attribute via list view
+ while (button == QDialog::Accepted && !goodName && name.isNull()) {
+ QPointer<UMLUniqueConstraintDialog> dialog = new UMLUniqueConstraintDialog(0, newUniqueConstraint);
+ button = dialog->exec();
+ QString name = newUniqueConstraint->name();
+
+ if (name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ } else if (findChildObject(name) != NULL) {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ } else {
+ goodName = true;
+ }
+ delete dialog;
+ }
+
+ if (button != QDialog::Accepted) {
+ delete newUniqueConstraint;
+ return NULL;
+ }
+
+ addConstraint(newUniqueConstraint);
+
+ UMLDoc *umldoc = UMLApp::app()->document();
+ umldoc->signalUMLObjectCreated(newUniqueConstraint);
+ emitModified();
+ return newUniqueConstraint;
+}
+
+/**
+ * Creates a Foreign Key Constraint for this Entity.
+ * @param name an optional name
+ * @return the ForeignKeyConstraint created
+ */
+UMLForeignKeyConstraint* UMLEntity::createForeignKeyConstraint(const QString &name)
+{
+ Uml::ID::Type id = UniqueID::gen();
+ QString currentName;
+ if (name.isNull()) {
+ currentName = uniqChildName(UMLObject::ot_ForeignKeyConstraint);
+ } else {
+ currentName = name;
+ }
+
+ UMLForeignKeyConstraint* newForeignKeyConstraint = new UMLForeignKeyConstraint(this, currentName, id);
+
+ int button = QDialog::Accepted;
+ bool goodName = false;
+
+ //check for name.isNull() stops dialog being shown
+ //when creating attribute via list view
+ while (button == QDialog::Accepted && !goodName && name.isNull()) {
+ QPointer<UMLForeignKeyConstraintDialog> dialog = new UMLForeignKeyConstraintDialog(0, newForeignKeyConstraint);
+ button = dialog->exec();
+ QString name = newForeignKeyConstraint->name();
+
+ if (name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ } else if (findChildObject(name) != NULL) {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ } else {
+ goodName = true;
+ }
+ delete dialog;
+ }
+
+ if (button != QDialog::Accepted) {
+ return NULL;
+ }
+
+ addConstraint(newForeignKeyConstraint);
+
+ UMLDoc *umldoc = UMLApp::app()->document();
+ umldoc->signalUMLObjectCreated(newForeignKeyConstraint);
+ emitModified();
+ return newForeignKeyConstraint;
+}
+
+/**
+ * Creates a Check Constraint for this Entity.
+ * @param name an optional name
+ * @return the CheckConstraint created
+ */
+UMLCheckConstraint* UMLEntity::createCheckConstraint(const QString &name)
+{
+ Uml::ID::Type id = UniqueID::gen();
+ QString currentName;
+ if (name.isNull()) {
+ currentName = uniqChildName(UMLObject::ot_CheckConstraint);
+ } else {
+ currentName = name;
+ }
+
+ UMLCheckConstraint* newCheckConstraint = new UMLCheckConstraint(this, currentName, id);
+
+ int button = QDialog::Accepted;
+ bool goodName = false;
+
+ //check for name.isNull() stops dialog being shown
+ //when creating attribute via list view
+ while (button == QDialog::Accepted && !goodName && name.isNull()) {
+ QPointer<UMLCheckConstraintDialog> dialog = new UMLCheckConstraintDialog(0, newCheckConstraint);
+ button = dialog->exec();
+ QString name = newCheckConstraint->name();
+
+ if (name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ } else if (findChildObject(name) != NULL) {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ } else {
+ goodName = true;
+ }
+ delete dialog;
+ }
+
+ if (button != QDialog::Accepted) {
+ return NULL;
+ }
+
+ addConstraint(newCheckConstraint);
+
+ UMLDoc *umldoc = UMLApp::app()->document();
+ umldoc->signalUMLObjectCreated(newCheckConstraint);
+ emitModified();
+ return newCheckConstraint;
+}
+
+/**
+ * Adds an entityAttribute.
+ * The entityAttribute object must not belong to any other concept.
+ * @param name name of the UMLEntityAttribute
+ * @param id id of the UMLEntityAttribute
+ * @return True if the entityAttribute was successfully added.
+ */
+UMLObject* UMLEntity::addEntityAttribute(const QString& name, Uml::ID::Type id)
+{
+ UMLEntityAttribute* literal = new UMLEntityAttribute(this, name, id);
+ m_List.append(literal);
+ emit entityAttributeAdded(literal);
+ UMLObject::emitModified();
+ connect(literal, SIGNAL(modified()), this, SIGNAL(modified()));
+ return literal;
+}
+
+/**
+ * Adds an already created entityAttribute.
+ * The entityAttribute object must not belong to any other concept.
+ * @param att Pointer to the UMLEntityAttribute.
+ * @param log Pointer to the IDChangeLog.
+ * @return True if the entityAttribute was successfully added.
+ */
+bool UMLEntity::addEntityAttribute(UMLEntityAttribute* att, IDChangeLog* log /* = 0*/)
+{
+ QString name = (QString)att->name();
+ if (findChildObject(name) == NULL) {
+ att->setParent(this);
+ m_List.append(att);
+ emit entityAttributeAdded(att);
+ UMLObject::emitModified();
+ connect(att, SIGNAL(modified()), this, SIGNAL(modified()));
+ return true;
+ } else if (log) {
+ log->removeChangeByNewID(att->id());
+ delete att;
+ }
+ return false;
+}
+
+/**
+ * Adds an entityAttribute to the entity, at the given position.
+ * If position is negative or too large, the entityAttribute is added
+ * to the end of the list.
+ * TODO: give default value -1 to position (append) - now it conflicts with the method above..
+ * @param att Pointer to the UMLEntityAttribute.
+ * @param position Position index for the insertion.
+ * @return True if the entityAttribute was successfully added.
+ */
+bool UMLEntity::addEntityAttribute(UMLEntityAttribute* att, int position)
+{
+ Q_ASSERT(att);
+ QString name = (QString)att->name();
+ if (findChildObject(name) == NULL) {
+ att->setParent(this);
+ if (position >= 0 && position <= (int)m_List.count()) {
+ m_List.insert(position, att);
+ } else {
+ m_List.append(att);
+ }
+ emit entityAttributeAdded(att);
+ UMLObject::emitModified();
+ connect(att, SIGNAL(modified()), this, SIGNAL(modified()));
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Removes an entityAttribute from the class.
+ * @param att The entityAttribute to remove.
+ * @return Count of the remaining entityAttributes after removal.
+ * Returns -1 if the given entityAttribute was not found.
+ */
+int UMLEntity::removeEntityAttribute(UMLClassifierListItem* att)
+{
+ if (!m_List.removeAll((UMLEntityAttribute*)att)) {
+ uDebug() << "cannot find att given in list";
+ return -1;
+ }
+ emit entityAttributeRemoved(att);
+ UMLObject::emitModified();
+ // If we are deleting the object, then we don't need to disconnect..this is done auto-magically
+ // for us by QObject. -b.t.
+ // disconnect(att, SIGNAL(modified()), this, SIGNAL(modified()));
+ delete att;
+ return m_List.count();
+}
+
+/**
+ * Returns the number of entityAttributes for the class.
+ * @return The number of entityAttributes for the class.
+ */
+int UMLEntity::entityAttributes()
+{
+ UMLClassifierListItemList entityAttributes = getFilteredList(UMLObject::ot_EntityAttribute);
+ return entityAttributes.count();
+}
+
+/**
+ * Emit the entityAttributeRemoved signal.
+ */
+void UMLEntity::signalEntityAttributeRemoved(UMLClassifierListItem *eattr)
+{
+ emit entityAttributeRemoved(eattr);
+}
+
+/**
+ * Resolve the types referenced by our UMLEntityAttributes.
+ * Reimplements the method from UMLClassifier.
+ */
+bool UMLEntity::resolveRef()
+{
+ bool success = UMLClassifier::resolveRef();
+ for (UMLObjectListIt oit(m_List); oit.hasNext();) {
+ UMLObject* obj = oit.next();
+ if (obj->resolveRef()) {
+ UMLClassifierListItem *cli = static_cast<UMLClassifierListItem*>(obj);
+ switch (cli->baseType()) {
+ case UMLObject::ot_EntityAttribute:
+ emit entityAttributeAdded(cli);
+ break;
+ case UMLObject::ot_UniqueConstraint:
+ case UMLObject::ot_ForeignKeyConstraint:
+ emit entityConstraintAdded(cli);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return success;
+}
+
+/**
+ * Creates the <UML:Entity> element including its entityliterals.
+ */
+void UMLEntity::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement entityElement = UMLObject::save(QLatin1String("UML:Entity"), qDoc);
+ //save operations
+ UMLClassifierListItemList entityAttributes = getFilteredList(UMLObject::ot_EntityAttribute);
+ UMLClassifierListItem* pEntityAttribute = 0;
+ foreach (pEntityAttribute, entityAttributes) {
+ pEntityAttribute->saveToXMI(qDoc, entityElement);
+ }
+
+ UMLClassifierListItemList entityConstraints = getFilteredList(UMLObject::ot_EntityConstraint);
+ foreach(UMLClassifierListItem* cli, entityConstraints) {
+ cli->saveToXMI(qDoc, entityElement);
+ }
+
+ qElement.appendChild(entityElement);
+}
+
+/**
+ * Loads the <UML:Entity> element including its entityAttributes.
+ */
+bool UMLEntity::load(QDomElement& element)
+{
+ QDomNode node = element.firstChild();
+ while(!node.isNull()) {
+ if (node.isComment()) {
+ node = node.nextSibling();
+ continue;
+ }
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("EntityAttribute"))) { // for backward compatibility
+ UMLEntityAttribute* pEntityAttribute = new UMLEntityAttribute(this);
+ if(!pEntityAttribute->loadFromXMI(tempElement)) {
+ return false;
+ }
+ m_List.append(pEntityAttribute);
+ } else if (UMLDoc::tagEq(tag, QLatin1String("UniqueConstraint"))) {
+ UMLUniqueConstraint* pUniqueConstraint = new UMLUniqueConstraint(this);
+ if (!pUniqueConstraint->loadFromXMI(tempElement)) {
+ return false;
+ }
+ addConstraint(pUniqueConstraint);
+ } else if (UMLDoc::tagEq(tag, QLatin1String("ForeignKeyConstraint"))) {
+ UMLForeignKeyConstraint* pForeignKeyConstraint = new UMLForeignKeyConstraint(this);
+ if (!pForeignKeyConstraint->loadFromXMI(tempElement)) {
+ return false;
+ }
+
+ addConstraint(pForeignKeyConstraint);
+ } else if (UMLDoc::tagEq(tag, QLatin1String("CheckConstraint"))) {
+
+ UMLCheckConstraint* pCheckConstraint = new UMLCheckConstraint(this);
+ if (!pCheckConstraint->loadFromXMI(tempElement)) {
+ return false;
+ }
+
+ addConstraint(pCheckConstraint);
+ } else if (tag == QLatin1String("stereotype")) {
+ uDebug() << name() << ": losing old-format stereotype.";
+ } else {
+ uWarning() << "unknown child type in UMLEntity::load";
+ }
+ node = node.nextSibling();
+ }//end while
+ return true;
+}
+
+/**
+ * Sets the UniqueConstraint passed as the Primary Key of this Entity
+ * If the UniqueConstraint exists, then it is made a primary key
+ * Else the UniqueConstraint is added and set as PrimaryKey
+ * @param uconstr The Unique Constraint that is to be set as Primary Key
+ * @return true if Primary key could be set successfully
+ */
+bool UMLEntity::setAsPrimaryKey(UMLUniqueConstraint* uconstr)
+{
+ if (uconstr == NULL) {
+ uDebug() << "NULL value passed. To unset a Primary Key use "
+ << "unsetPrimaryKey()";
+ return false;
+ }
+
+ if (static_cast<UMLEntity*>(uconstr->parent()) != this) {
+
+ uDebug() << "Parent of " << uconstr->name()
+ << " does not match with current entity";
+ return false;
+ }
+
+ // check if this constraint already exists as a unique constraint for this entity
+ UMLUniqueConstraint* uuc = static_cast<UMLUniqueConstraint*>(findChildObjectById(uconstr->id()));
+ if (uuc == NULL) {
+ addConstraint(uconstr);
+ uuc = uconstr;
+ }
+
+ UMLUniqueConstraint* oldPrimaryKey = m_PrimaryKey;
+
+ m_PrimaryKey = uuc;
+
+ if (oldPrimaryKey != NULL)
+ oldPrimaryKey->emitModified();
+
+ uuc->emitModified();
+ emitModified();
+ return true;
+}
+
+/**
+ * Unset a Primary Key Constraint if it exists, else does nothing
+ * This function will make the primary key into just another UniqueConstraint
+ * if it exists
+ */
+void UMLEntity::unsetPrimaryKey()
+{
+ m_PrimaryKey = 0;
+}
+
+/**
+ * Checks if This UMLEntity has a primary key set.
+ * @return true if a Primary Key Exists for this UMLEntity
+ */
+bool UMLEntity::hasPrimaryKey() const
+{
+ if (m_PrimaryKey) {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Adds a Constraint to this UMLEntity.
+ * To set a UMLUniqueConstraint as Primary Key use setAsPrimaryKey.
+ * @param constr The UMLEntityConstraint that is to be added
+ * @return true if the constraint could be added successfully
+ */
+bool UMLEntity::addConstraint(UMLEntityConstraint* constr)
+{
+ if (findChildObjectById(constr->id()) != NULL) {
+ uDebug() << "Constraint with id " << Uml::ID::toString(constr->id())
+ << " already exists ";
+ return false;
+ }
+
+ m_List.append(constr);
+
+ emit entityConstraintAdded(constr);
+ UMLObject::emitModified();
+ connect(constr, SIGNAL(modified()), this, SIGNAL(modified()));
+
+ return true;
+}
+
+/**
+ * Removes an existing constraint from this UMLEntity.
+ * If the Contraint is a Primary Key, this Entity will no longer have a PrimaryKey.
+ * @param constr the constraint to be removed
+ * @return true if the constraint could be removed successfully
+ */
+bool UMLEntity::removeConstraint(UMLEntityConstraint* constr)
+{
+ if (findChildObjectById(constr->id()) == NULL) {
+ uDebug() << "Constraint with id " << Uml::ID::toString(constr->id())
+ << " does not exist ";
+ return false;
+ }
+
+ if (m_PrimaryKey == constr) {
+ unsetPrimaryKey();
+ }
+
+ m_List.removeAll(constr);
+
+ emit entityConstraintRemoved(constr);
+ UMLObject::emitModified();
+
+ delete constr;
+ return true;
+}
+
+/**
+ * Slot for entity attribute removed.
+ */
+void UMLEntity::slotEntityAttributeRemoved(UMLClassifierListItem* cli)
+{
+ // this function does some cleanjobs related to this entity when the attribute is
+ // removed, like, removing the attribute from all constraints
+
+ UMLEntityAttribute* entAtt = static_cast<UMLEntityAttribute*>(cli);
+ if (cli) {
+ UMLClassifierListItemList ual = this->getFilteredList(UMLObject::ot_UniqueConstraint);
+
+ foreach(UMLClassifierListItem* ucli, ual) {
+ UMLUniqueConstraint* uuc = static_cast<UMLUniqueConstraint*>(ucli);
+ if (uuc->hasEntityAttribute(entAtt)) {
+ uuc->removeEntityAttribute(entAtt);
+ }
+ }
+ }
+
+}
+
+/**
+ * Reimplementation of getFilteredList to support ot=UMLObject::ot_EntityConstraint.
+ */
+UMLClassifierListItemList UMLEntity::getFilteredList(UMLObject::ObjectType ot) const
+{
+ if (ot == UMLObject::ot_EntityConstraint) {
+ UMLClassifierListItemList ucList, fcList, ccList, rcList;
+ ucList = UMLClassifier::getFilteredList(UMLObject::ot_UniqueConstraint);
+ fcList = UMLClassifier::getFilteredList(UMLObject::ot_ForeignKeyConstraint);
+ ccList = UMLClassifier::getFilteredList(UMLObject::ot_CheckConstraint);
+
+ // append the lists to rcList
+ // first the Unique Constraints
+ foreach(UMLClassifierListItem* ucli, ucList) {
+ rcList.append(ucli);
+ }
+
+ // then the Foreign Key Constraints
+ foreach(UMLClassifierListItem* ucli, fcList) {
+ rcList.append(ucli);
+ }
+
+ foreach(UMLClassifierListItem* ucli, ccList) {
+ rcList.append(ucli);
+ }
+
+ return rcList;
+ } else {
+ return UMLClassifier::getFilteredList(ot);
+ }
+}
+
+/**
+ * Checks if a given Unique Constraint is primary key of this entity
+ * @param uConstr a Unique Constraint
+ * @return bool true if passed parameter is a primary key of this entity
+ */
+bool UMLEntity::isPrimaryKey(UMLUniqueConstraint* uConstr) const
+{
+ if (uConstr == m_PrimaryKey) {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Returns the Entity Attributes.
+ * Same as getFilteredList(UMLObject::ot_EntityAttribute).
+ */
+UMLEntityAttributeList UMLEntity::getEntityAttributes() const
+{
+ UMLEntityAttributeList entityAttributeList;
+ for (UMLObjectListIt lit(m_List); lit.hasNext();) {
+ UMLObject *listItem = lit.next();
+ if (listItem->baseType() == UMLObject::ot_EntityAttribute) {
+ entityAttributeList.append(static_cast<UMLEntityAttribute*>(listItem));
+ }
+ }
+ return entityAttributeList;
+}
+
+
+/**
+ * Create a new ClassifierListObject (entityattribute)
+ * according to the given XMI tag.
+ * Returns NULL if the string given does not contain one of the tags
+ * <UML:EntityAttribute>
+ * Used by the clipboard for paste operation.
+ * Reimplemented from UMLClassifier for UMLEntity
+ */
+UMLClassifierListItem* UMLEntity::makeChildObject(const QString& xmiTag)
+{
+ UMLClassifierListItem* pObject = NULL;
+ if (UMLDoc::tagEq(xmiTag, QLatin1String("EntityAttribute"))) {
+ pObject = new UMLEntityAttribute(this);
+ }
+ return pObject;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entity.h umbrello-kf6-15.08.1/umbrello/umlmodel/entity.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/entity.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/entity.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,108 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ENTITY_H
+#define ENTITY_H
+
+#include "classifier.h"
+
+// forward declarations
+class UMLEntityAttribute;
+class UMLEntityConstraint;
+class UMLUniqueConstraint;
+class UMLForeignKeyConstraint;
+class UMLCheckConstraint;
+class UMLEntityAttributeList;
+
+/**
+ * This class contains the non-graphical information required for a UML
+ * Entity.
+ * This class inherits from @ref UMLClassifier which contains most of the
+ * information.
+ *
+ * @short Non-graphical Information for an Entity.
+ * @author Jonathan Riddell
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLEntity : public UMLClassifier
+{
+ Q_OBJECT
+public:
+ explicit UMLEntity(const QString& name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLEntity();
+
+ bool operator==(const UMLEntity& rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ virtual UMLAttribute* createAttribute(const QString &name = QString(),
+ UMLObject *type = 0, Uml::Visibility::Enum vis = Uml::Visibility::Private,
+ const QString &init = QString());
+
+ UMLUniqueConstraint* createUniqueConstraint(const QString &name = QString());
+ UMLForeignKeyConstraint* createForeignKeyConstraint(const QString &name = QString());
+ UMLCheckConstraint* createCheckConstraint(const QString &name = QString());
+
+ UMLObject* addEntityAttribute(const QString &name, Uml::ID::Type id = Uml::ID::None);
+ bool addEntityAttribute(UMLEntityAttribute* att, IDChangeLog* log = 0);
+ bool addEntityAttribute(UMLEntityAttribute* att, int position);
+
+ int removeEntityAttribute(UMLClassifierListItem* att);
+
+ void signalEntityAttributeRemoved(UMLClassifierListItem *eattr);
+
+ int entityAttributes() ;
+
+ bool setAsPrimaryKey(UMLUniqueConstraint* uconstr);
+ void unsetPrimaryKey();
+ bool hasPrimaryKey() const;
+ bool isPrimaryKey(UMLUniqueConstraint* uConstr) const;
+
+ bool addConstraint(UMLEntityConstraint* constr);
+ bool removeConstraint(UMLEntityConstraint* constr);
+
+ virtual bool resolveRef();
+
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ UMLClassifierListItemList getFilteredList(UMLObject::ObjectType ot) const;
+
+ UMLEntityAttributeList getEntityAttributes() const;
+
+ virtual UMLClassifierListItem* makeChildObject(const QString& xmiTag);
+
+private slots:
+ void slotEntityAttributeRemoved(UMLClassifierListItem*);
+
+signals:
+ void entityAttributeAdded(UMLClassifierListItem*);
+ void entityAttributeRemoved(UMLClassifierListItem*);
+ void entityConstraintAdded(UMLClassifierListItem*);
+ void entityConstraintRemoved(UMLClassifierListItem*);
+
+protected:
+ bool load(QDomElement& element);
+
+private:
+
+ /**
+ * Primary Key of this Entity
+ * This is a pointer kept for easy access to the primary key, and to distinguish it
+ * from all other UniqueConstraints. It is also there in m_List (inherited from
+ * UMLCanvasObject)
+ */
+ UMLUniqueConstraint* m_PrimaryKey;
+
+};
+
+#endif // ENTITY_H
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/enum.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/enum.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/enum.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/enum.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,302 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "enum.h"
+
+// app includes
+#include "debug_utils.h"
+#include "enumliteral.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "uniqueid.h"
+#include "idchangelog.h"
+
+// kde includes
+#include <KLocalizedString>
+#include <KMessageBox>
+
+/**
+ * Sets up an enum.
+ * @param name The name of the Enum.
+ * @param id The unique id of the Enum.
+ */
+UMLEnum::UMLEnum(const QString& name, Uml::ID::Type id) : UMLClassifier(name, id)
+{
+ init();
+}
+
+/**
+ * Standard destructor.
+ */
+UMLEnum::~UMLEnum()
+{
+ m_List.clear();
+}
+
+/**
+ * Overloaded '==' operator.
+ */
+bool UMLEnum::operator==(const UMLEnum & rhs) const
+{
+ return UMLClassifier::operator==(rhs);
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLEnum::copyInto(UMLObject *lhs) const
+{
+ UMLClassifier::copyInto(lhs);
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLEnum::clone() const
+{
+ UMLEnum *clone = new UMLEnum();
+ copyInto(clone);
+
+ return clone;
+}
+
+/**
+ * Initializes key variables of the class.
+ */
+void UMLEnum::init()
+{
+ m_BaseType = UMLObject::ot_Enum;
+ setStereotypeCmd(QLatin1String("enum"));
+}
+
+/**
+ * Creates a literal for the enum.
+ * @return The UMLEnum created
+ */
+UMLObject* UMLEnum::createEnumLiteral(const QString& name)
+{
+ Uml::ID::Type id = UniqueID::gen();
+ QString currentName;
+ if (name.isNull()) {
+ currentName = uniqChildName(UMLObject::ot_EnumLiteral);
+ } else {
+ currentName = name;
+ }
+
+ UMLEnumLiteral* newEnumLiteral = new UMLEnumLiteral(this, currentName);
+
+ bool ok = true;
+ bool goodName = false;
+
+ //check for name.isNull() stops dialog being shown
+ //when creating enum literal via list view
+ while (ok && !goodName && name.isNull()) {
+ ok = newEnumLiteral->showPropertiesDialog(UMLApp::app());
+ QString name = newEnumLiteral->name();
+
+ if(name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ } else {
+ goodName = true;
+ }
+ }
+
+ if (!ok) {
+ delete newEnumLiteral;
+ return NULL;
+ }
+
+ addEnumLiteral(newEnumLiteral);
+
+ UMLDoc *umldoc = UMLApp::app()->document();
+ umldoc->signalUMLObjectCreated(newEnumLiteral);
+ return newEnumLiteral;
+}
+
+/**
+ * Adds an enumliteral to the enum.
+ * @param name The name of the enumliteral.
+ * @param id The id of the enumliteral (optional.)
+ * If omitted a new ID is assigned internally.
+ * @return Pointer to the UMLEnumliteral created.
+ */
+UMLObject* UMLEnum::addEnumLiteral(const QString &name, Uml::ID::Type id)
+{
+ UMLObject *el = UMLCanvasObject::findChildObject(name);
+ if (el != NULL) {
+ uDebug() << name << " is already present";
+ return el;
+ }
+ UMLEnumLiteral* literal = new UMLEnumLiteral(this, name, id);
+ m_List.append(literal);
+ UMLObject::emitModified();
+ emit enumLiteralAdded(literal);
+ connect(literal, SIGNAL(modified()), this, SIGNAL(modified()));
+ return literal;
+}
+
+/**
+ * Adds an already created enumliteral.
+ * The enumliteral object must not belong to any other concept.
+ * @param literal Pointer to the UMLEnumLiteral.
+ * @param Log Pointer to the IDChangeLog.
+ * @return True if the enumliteral was successfully added.
+ */
+bool UMLEnum::addEnumLiteral(UMLEnumLiteral* literal, IDChangeLog* Log /* = 0*/)
+{
+ QString name = (QString)literal->name();
+ if (findChildObject(name) == NULL) {
+ literal->setParent(this);
+ m_List.append(literal);
+ UMLObject::emitModified();
+ emit enumLiteralAdded(literal);
+ connect(literal, SIGNAL(modified()), this, SIGNAL(modified()));
+ return true;
+ } else if (Log) {
+ Log->removeChangeByNewID(literal->id());
+ delete literal;
+ }
+ return false;
+}
+
+/**
+ * Adds an enumliteral to the enum, at the given position.
+ * If position is negative or too large, the enumliteral is added
+ * to the end of the list.
+ * TODO: give default value -1 to position (append) - now it conflicts with the method above..
+ * @param literal Pointer to the UMLEnumLiteral.
+ * @param position Position index for the insertion.
+ * @return True if the enumliteral was successfully added.
+ */
+bool UMLEnum::addEnumLiteral(UMLEnumLiteral* literal, int position)
+{
+ Q_ASSERT(literal);
+ QString name = (QString)literal->name();
+ if (findChildObject(name) == NULL) {
+ literal->setParent(this);
+ if (position >= 0 && position <= (int)m_List.count()) {
+ m_List.insert(position, literal);
+ } else {
+ m_List.append(literal);
+ }
+ UMLObject::emitModified();
+ emit enumLiteralAdded(literal);
+ connect(literal, SIGNAL(modified()), this, SIGNAL(modified()));
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Removes an enumliteral from the class.
+ * @param literal The enumliteral to remove.
+ * @return Count of the remaining enumliterals after removal.
+ * Returns -1 if the given enumliteral was not found.
+ */
+int UMLEnum::removeEnumLiteral(UMLEnumLiteral* literal)
+{
+ if (!m_List.removeAll(literal)) {
+ uDebug() << "cannot find att given in list";
+ return -1;
+ }
+ emit enumLiteralRemoved(literal);
+ UMLObject::emitModified();
+ // If we are deleting the object, then we don't need to disconnect..this is done auto-magically
+ // for us by QObject. -b.t.
+ // disconnect(a, SIGNAL(modified()), this, SIGNAL(modified()));
+ delete literal;
+ return m_List.count();
+}
+
+/**
+ * Returns the number of enumliterals for the class.
+ * @return The number of enumliterals for the class.
+ */
+int UMLEnum::enumLiterals()
+{
+ return m_List.count();
+}
+
+/**
+ * Emit the enumLiteralRemoved signal.
+ */
+void UMLEnum::signalEnumLiteralRemoved(UMLClassifierListItem *elit)
+{
+ emit enumLiteralRemoved(elit);
+}
+
+/**
+ * Creates the <UML:Enum> element including its enumliterals.
+ */
+void UMLEnum::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement enumElement = UMLObject::save(QLatin1String("UML:Enumeration"), qDoc);
+ // save enum literals
+ UMLClassifierListItemList enumLiterals = getFilteredList(UMLObject::ot_EnumLiteral);
+ foreach (UMLClassifierListItem* pEnumLiteral, enumLiterals) {
+ pEnumLiteral->saveToXMI(qDoc, enumElement);
+ }
+ qElement.appendChild(enumElement);
+}
+
+/**
+ * Loads the <UML:Enum> element including its enumliterals.
+ */
+bool UMLEnum::load(QDomElement& element)
+{
+ QDomNode node = element.firstChild();
+ while(!node.isNull()) {
+ if (node.isComment()) {
+ node = node.nextSibling();
+ continue;
+ }
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("EnumerationLiteral")) ||
+ UMLDoc::tagEq(tag, QLatin1String("ownedLiteral")) ||
+ UMLDoc::tagEq(tag, QLatin1String("EnumLiteral"))) { // for backward compatibility
+ UMLEnumLiteral* pEnumLiteral = new UMLEnumLiteral(this);
+ if(!pEnumLiteral->loadFromXMI(tempElement)) {
+ return false;
+ }
+ m_List.append(pEnumLiteral);
+ } else if (UMLDoc::tagEq(tag, QLatin1String("Enumeration.literal"))) { // Embarcadero's Describe
+ if (! load(tempElement))
+ return false;
+ } else if (tag == QLatin1String("stereotype")) {
+ uDebug() << name() << ": losing old-format stereotype.";
+ } else {
+ uWarning() << "unknown child type: " << tag;
+ }
+ node = node.nextSibling();
+ }//end while
+ return true;
+}
+
+/**
+ * Create a new ClassifierListObject (enumLiteral)
+ * according to the given XMI tag.
+ * Returns NULL if the string given does not contain one of the tags
+ * <UML:EnumLiteral>
+ * Used by the clipboard for paste operation.
+ * Reimplemented from UMLClassifier for UMLEnum
+ */
+UMLClassifierListItem* UMLEnum::makeChildObject(const QString& xmiTag)
+{
+ UMLClassifierListItem* pObject = NULL;
+ if (UMLDoc::tagEq(xmiTag, QLatin1String("EnumerationLiteral")) ||
+ UMLDoc::tagEq(xmiTag, QLatin1String("EnumLiteral"))) {
+ pObject = new UMLEnumLiteral(this);
+ }
+ return pObject;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/enum.h umbrello-kf6-15.08.1/umbrello/umlmodel/enum.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/enum.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/enum.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ENUM_H
+#define ENUM_H
+
+#include "classifier.h"
+
+class UMLEnumLiteral;
+
+/**
+ * This class contains the non-graphical information required for a UML
+ * Enum.
+ * This class inherits from @ref UMLClassifier which contains most of the
+ * information.
+ *
+ * @short Non-graphical Information for an Enum.
+ * @author Jonathan Riddell
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLEnum : public UMLClassifier
+{
+ Q_OBJECT
+public:
+ explicit UMLEnum(const QString& name = QString(), Uml::ID::Type id = Uml::ID::None);
+
+ virtual ~UMLEnum();
+
+ bool operator==(const UMLEnum& rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ UMLObject* createEnumLiteral(const QString& name = QString());
+
+ UMLObject* addEnumLiteral(const QString &name, Uml::ID::Type id = Uml::ID::None);
+
+ bool addEnumLiteral(UMLEnumLiteral* literal, IDChangeLog* Log = 0);
+ bool addEnumLiteral(UMLEnumLiteral* literal, int position);
+
+ int removeEnumLiteral(UMLEnumLiteral* literal);
+
+ int enumLiterals();
+
+ void signalEnumLiteralRemoved(UMLClassifierListItem *elit);
+
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ virtual UMLClassifierListItem* makeChildObject(const QString& xmiTag);
+
+signals:
+ void enumLiteralAdded(UMLClassifierListItem*);
+ void enumLiteralRemoved(UMLClassifierListItem*);
+
+protected:
+ bool load(QDomElement & element);
+
+private:
+ void init();
+
+};
+
+#endif // ENUM_H
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/enumliteral.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/enumliteral.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/enumliteral.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/enumliteral.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,126 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "enumliteral.h"
+
+// kde includes
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+#include <KLocalizedString>
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+
+/**
+ * Sets up an enum literal.
+ * @param parent The parent of this UMLEnumLiteral.
+ * @param name The name of this UMLEnumLiteral.
+ * @param id The unique id given to this UMLEnumLiteral.
+ */
+UMLEnumLiteral::UMLEnumLiteral(UMLObject *parent,
+ const QString& name, Uml::ID::Type id)
+ : UMLClassifierListItem(parent, name, id)
+{
+ m_BaseType = UMLObject::ot_EnumLiteral;
+}
+
+/**
+ * Sets up an enum literal.
+ * @param parent The parent of this UMLEnumLiteral.
+ */
+UMLEnumLiteral::UMLEnumLiteral(UMLObject *parent)
+ : UMLClassifierListItem(parent)
+{
+ m_BaseType = UMLObject::ot_EnumLiteral;
+}
+
+/**
+ * Destructor.
+ */
+UMLEnumLiteral::~UMLEnumLiteral()
+{
+}
+
+/**
+ * Overloaded '==' operator
+ */
+bool UMLEnumLiteral::operator==(const UMLEnumLiteral& rhs) const
+{
+ if (this == &rhs) {
+ return true;
+ }
+ if (!UMLObject::operator==(rhs)) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLEnumLiteral::copyInto(UMLObject *lhs) const
+{
+ UMLClassifierListItem::copyInto(lhs);
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLEnumLiteral::clone() const
+{
+ UMLEnumLiteral *clone = new UMLEnumLiteral((UMLObject *) parent());
+ copyInto(clone);
+
+ return clone;
+}
+
+/**
+ * Creates the <UML:EnumLiteral> XMI element.
+ */
+void UMLEnumLiteral::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement attributeElement = UMLObject::save(QLatin1String("UML:EnumerationLiteral"), qDoc);
+ qElement.appendChild(attributeElement);
+}
+
+/**
+ * Loads the <UML:EnumLiteral> XMI element (empty.)
+ */
+bool UMLEnumLiteral::load(QDomElement& element)
+{
+ Q_UNUSED(element);
+ return true;
+}
+
+/**
+ * Display the properties configuration dialog for the enum literal.
+ */
+bool UMLEnumLiteral::showPropertiesDialog(QWidget* parent)
+{
+ bool ok;
+#if QT_VERSION >= 0x050000
+ QString enumName = QInputDialog::getText(parent,
+ i18nc("enum name", "Name"), i18n("Enter name:"),
+ QLineEdit::Normal,
+ name(), &ok);
+#else
+ QString enumName = KInputDialog::getText(i18nc("enum name", "Name"), i18n("Enter name:"), name(), &ok, parent);
+#endif
+ if (ok && !enumName.isEmpty()) {
+ setName(enumName);
+ return true;
+ } else {
+ return false;
+ }
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/enumliteral.h umbrello-kf6-15.08.1/umbrello/umlmodel/enumliteral.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/enumliteral.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/enumliteral.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ENUMLITERAL_H
+#define ENUMLITERAL_H
+
+#include "classifierlistitem.h"
+
+/**
+ * This class is used to set up information for an enum literal. Enum
+ * literals are the values that enums can be set to.
+ *
+ * @short Sets up attribute information.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLEnumLiteral : public UMLClassifierListItem
+{
+public:
+ UMLEnumLiteral(UMLObject* parent,
+ const QString& name, Uml::ID::Type id = Uml::ID::None);
+ explicit UMLEnumLiteral(UMLObject* parent);
+
+ bool operator==(const UMLEnumLiteral &rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ virtual ~UMLEnumLiteral();
+
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ virtual bool showPropertiesDialog(QWidget* parent = 0);
+
+protected:
+ bool load(QDomElement& element);
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/folder.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/folder.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/folder.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/folder.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,558 @@
+/***************************************************************************
+ * 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) 2006-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "folder.h"
+
+// app includes
+#include "debug_utils.h"
+#include "model_utils.h"
+#include "object_factory.h"
+#include "optionstate.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+// kde includes
+#include <KLocalizedString>
+#include <KMessageBox>
+
+// qt includes
+#include <QFile>
+
+/**
+ * Sets up a Folder.
+ * @param name The name of the Folder.
+ * @param id The unique id of the Folder. A new ID will be generated
+ * if this argument is left away.
+ */
+UMLFolder::UMLFolder(const QString & name, Uml::ID::Type id)
+ : UMLPackage(name, id)
+{
+ m_BaseType = UMLObject::ot_Folder;
+ UMLObject::setStereotypeCmd(QLatin1String("folder"));
+}
+
+/**
+ * Empty destructor.
+ */
+UMLFolder::~UMLFolder()
+{
+ qDeleteAll(m_diagrams);
+ m_diagrams.clear();
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLFolder::clone() const
+{
+ UMLFolder *clone = new UMLFolder();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+/**
+ * Set the localized name of this folder.
+ * This is set for the predefined root views (Logical,
+ * UseCase, Component, Deployment, EntityRelationship,
+ * and the Datatypes folder inside the Logical View.)
+ */
+void UMLFolder::setLocalName(const QString& localName)
+{
+ m_localName = localName;
+}
+
+/**
+ * Return the localized name of this folder.
+ * Only useful for the predefined root folders.
+ */
+QString UMLFolder::localName() const
+{
+ return m_localName;
+}
+
+/**
+ * Add a view to the diagram list.
+ */
+void UMLFolder::addView(UMLView *view)
+{
+ m_diagrams.append(view);
+}
+
+/**
+ * Remove a view from the diagram list.
+ */
+void UMLFolder::removeView(UMLView *view)
+{
+ m_diagrams.removeAll(view);
+ delete view;
+}
+
+/**
+ * Append the views in this folder to the given diagram list.
+ * @param viewList The UMLViewList to which to append the diagrams.
+ * @param includeNested Whether to include diagrams from nested folders
+ * (default: true.)
+ */
+void UMLFolder::appendViews(UMLViewList& viewList, bool includeNested)
+{
+ if (includeNested) {
+ foreach (UMLObject* o, m_objects) {
+ uIgnoreZeroPointer(o);
+ if (o->baseType() == UMLObject::ot_Folder) {
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ f->appendViews(viewList);
+ }
+ }
+ }
+ foreach (UMLView* v, m_diagrams) {
+ viewList.append(v);
+ }
+}
+
+/**
+ * Acivate the views in this folder.
+ * "Activation": Some widgets require adjustments after loading from file,
+ * those are done here.
+ */
+void UMLFolder::activateViews()
+{
+ foreach (UMLObject* o, m_objects) {
+ uIgnoreZeroPointer(o);
+ if (o->baseType() == UMLObject::ot_Folder) {
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ f->activateViews();
+ }
+ }
+
+ foreach (UMLView* v, m_diagrams) {
+ v->umlScene()->activateAfterLoad();
+ }
+ // Make sure we have a treeview item for each diagram.
+ // It may happen that we are missing them after switching off tabbed widgets.
+ Settings::OptionState optionState = Settings::optionState();
+ if (optionState.generalState.tabdiagrams) {
+ return;
+ }
+ Model_Utils::treeViewAddViews(m_diagrams);
+}
+
+/**
+ * Seek a view of the given ID in this folder.
+ * @param id ID of the view to find.
+ * @return Pointer to the view if found, NULL if no view found.
+ */
+UMLView *UMLFolder::findView(Uml::ID::Type id)
+{
+ foreach (UMLView* v, m_diagrams) {
+ if (v->umlScene()->ID() == id) {
+ return v;
+ }
+ }
+
+ UMLView* v = 0;
+ UMLPackageList packages;
+ appendPackages(packages);
+ foreach (UMLPackage *o, packages) {
+ if (o->baseType() != UMLObject::ot_Folder) {
+ continue;
+ }
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ v = f->findView(id);
+ if (v) {
+ break;
+ }
+ }
+ return v;
+}
+
+/**
+ * Seek a view by the type and name given.
+ * @param type The type of view to find.
+ * @param name The name of the view to find.
+ * @param searchAllScopes Search in all subfolders (default: true.)
+ * @return Pointer to the view found, or NULL if not found.
+ */
+UMLView *UMLFolder::findView(Uml::DiagramType::Enum type, const QString &name, bool searchAllScopes)
+{
+ foreach (UMLView* v, m_diagrams) {
+ if (v->umlScene()->type() == type && v->umlScene()->name() == name) {
+ return v;
+ }
+ }
+
+ UMLView* v = 0;
+ if (searchAllScopes) {
+ foreach (UMLObject* o, m_objects) {
+ uIgnoreZeroPointer(o);
+ if (o->baseType() != UMLObject::ot_Folder) {
+ continue;
+ }
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ v = f->findView(type, name, searchAllScopes);
+ if (v) {
+ break;
+ }
+ }
+ }
+ return v;
+}
+
+/**
+ * Set the options for the views in this folder.
+ */
+void UMLFolder::setViewOptions(const Settings::OptionState& optionState)
+{
+ // for each view update settings
+ foreach (UMLView* v, m_diagrams) {
+ v->umlScene()->setOptionState(optionState);
+ }
+}
+
+/**
+ * Remove all views in this folder.
+ */
+void UMLFolder::removeAllViews()
+{
+ foreach (UMLObject* o, m_objects) {
+ uIgnoreZeroPointer(o);
+ if (o->baseType() != UMLObject::ot_Folder)
+ continue;
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ f->removeAllViews();
+ }
+
+ foreach (UMLView* v, m_diagrams) {
+ // TODO ------------------ check this code - bad: calling back to UMLDoc::removeView()
+ v->umlScene()->removeAllAssociations(); // note : It may not be apparent, but when we remove all associations
+ // from a view, it also causes any UMLAssociations that lack parent
+ // association widgets (but once had them) to remove themselves from
+ // this document.
+ uDebug() << "removing " << v->umlScene()->name();
+ UMLApp::app()->document()->removeView(v, false);
+ }
+
+ qDeleteAll(m_diagrams);
+ m_diagrams.clear();
+}
+
+/**
+ * Set the folder file name for a separate submodel.
+ */
+void UMLFolder::setFolderFile(const QString& fileName)
+{
+ m_folderFile = fileName;
+}
+
+/**
+ * Get the folder file name for a separate submodel.
+ */
+QString UMLFolder::folderFile() const
+{
+ return m_folderFile;
+}
+
+/**
+ * Auxiliary to saveToXMI(): Save the contained objects and diagrams.
+ * Can be used regardless of whether saving to the main model file
+ * or to an external folder file (see m_folderFile.)
+ */
+void UMLFolder::saveContents(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement ownedElement = qDoc.createElement(QLatin1String("UML:Namespace.ownedElement"));
+ UMLObject *obj = 0;
+ // Save contained objects if any.
+ for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
+ obj = oit.next();
+ uIgnoreZeroPointer(obj);
+ obj->saveToXMI (qDoc, ownedElement);
+ }
+ // Save asscociations if any.
+ for (UMLObjectListIt ait(m_List); ait.hasNext();) {
+ obj = ait.next();
+ obj->saveToXMI (qDoc, ownedElement);
+ }
+ qElement.appendChild(ownedElement);
+ // Save diagrams to `extension'.
+ if (m_diagrams.count()) {
+ QDomElement diagramsElement = qDoc.createElement(QLatin1String("diagrams"));
+
+ foreach (UMLView* pView, m_diagrams) {
+ pView->umlScene()->saveToXMI(qDoc, diagramsElement);
+ }
+ QDomElement extension = qDoc.createElement(QLatin1String("XMI.extension"));
+ extension.setAttribute(QLatin1String("xmi.extender"), QLatin1String("umbrello-kf6"));
+ extension.appendChild(diagramsElement);
+ qElement.appendChild(extension);
+ }
+}
+
+/**
+ * Auxiliary to saveToXMI(): Creates a <UML:Model> element when saving
+ * a predefined modelview, or a <UML:Package> element when saving a
+ * user created folder. Invokes saveContents() with the newly created
+ * element.
+ */
+void UMLFolder::save(QDomDocument& qDoc, QDomElement& qElement)
+{
+ UMLDoc *umldoc = UMLApp::app()->document();
+ QString elementName(QLatin1String("UML:Package"));
+ const Uml::ModelType::Enum mt = umldoc->rootFolderType(this);
+ if (mt != Uml::ModelType::N_MODELTYPES) {
+ elementName = QLatin1String("UML:Model");
+ }
+ QDomElement folderElement = UMLObject::save(elementName, qDoc);
+ saveContents(qDoc, folderElement);
+ qElement.appendChild(folderElement);
+}
+
+/**
+ * Creates a UML:Model or UML:Package element:
+ * UML:Model is created for the predefined fixed folders,
+ * UML:Package with stereotype "folder" is created for all else.
+ */
+void UMLFolder::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ if (m_folderFile.isEmpty()) {
+ save(qDoc, qElement);
+ return;
+ }
+ // See if we can create the external file.
+ // If not then internalize the folder.
+ UMLDoc *umldoc = UMLApp::app()->document();
+#if QT_VERSION >= 0x050000
+ QString fileName = umldoc->url().adjusted(QUrl::RemoveFilename).path() + m_folderFile;
+#else
+ QString fileName = umldoc->url().directory() + QLatin1Char('/') + m_folderFile;
+#endif
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly)) {
+ uError() << m_folderFile << QLatin1String(": ")
+ << "cannot create file, contents will be saved in main model file";
+ m_folderFile.clear();
+ save(qDoc, qElement);
+ return;
+ }
+ // Okay, external file is writable. Wrap up main file.
+ QDomElement folderElement = UMLObject::save(QLatin1String("UML:Package"), qDoc);
+ QDomElement extension = qDoc.createElement(QLatin1String("XMI.extension"));
+ extension.setAttribute(QLatin1String("xmi.extender"), QLatin1String("umbrello-kf6"));
+ QDomElement fileElement = qDoc.createElement(QLatin1String("external_file"));
+ fileElement.setAttribute(QLatin1String("name"), m_folderFile);
+ extension.appendChild(fileElement);
+ folderElement.appendChild(extension);
+ qElement.appendChild(folderElement);
+
+ // Save folder to external file.
+ QDomDocument folderDoc;
+ QDomElement folderRoot;
+ QDomProcessingInstruction xmlHeading =
+ folderDoc.createProcessingInstruction(QLatin1String("xml"),
+ QString::fromLatin1("version=\"1.0\" encoding=\"UTF-8\""));
+ folderDoc.appendChild(xmlHeading);
+ folderRoot = folderDoc.createElement(QLatin1String("external_file"));
+ folderRoot.setAttribute(QLatin1String("name"), name());
+ folderRoot.setAttribute(QLatin1String("filename"), m_folderFile);
+ folderRoot.setAttribute(QLatin1String("mainModel"), umldoc->url().fileName());
+ folderRoot.setAttribute(QLatin1String("parentId"), Uml::ID::toString(m_pUMLPackage->id()));
+ folderRoot.setAttribute(QLatin1String("parent"), m_pUMLPackage->fullyQualifiedName(QLatin1String("::"), true));
+ saveContents(folderDoc, folderRoot);
+ folderDoc.appendChild(folderRoot);
+ QTextStream stream(&file);
+ stream.setCodec("UTF-8");
+ stream << folderDoc.toString();
+ file.close();
+}
+
+/**
+ * Auxiliary to load():
+ * Load the diagrams from the "diagrams" in the <XMI.extension>
+ */
+bool UMLFolder::loadDiagramsFromXMI(QDomNode& diagrams)
+{
+ const Settings::OptionState optionState = Settings::optionState();
+ UMLDoc *umldoc = UMLApp::app()->document();
+ bool totalSuccess = true;
+ for (QDomElement diagram = diagrams.toElement(); !diagram.isNull();
+ diagrams = diagrams.nextSibling(), diagram = diagrams.toElement()) {
+ QString tag = diagram.tagName();
+ if (tag != QLatin1String("diagram")) {
+ uDebug() << "ignoring " << tag << " in <diagrams>";
+ continue;
+ }
+ UMLView * pView = new UMLView(this);
+ pView->umlScene()->setOptionState(optionState);
+ if (pView->umlScene()->loadFromXMI(diagram)) {
+ pView->hide();
+ umldoc->addView(pView);
+ } else {
+ delete pView;
+ totalSuccess = false;
+ }
+ }
+ return totalSuccess;
+}
+
+/**
+ * Folders in the listview can be marked such that their contents
+ * are saved to a separate file.
+ * This method loads the separate folder file.
+ * CAVEAT: This is not XMI standard compliant.
+ * If standard compliance is an issue then avoid folder files.
+ * @param path Fully qualified file name, i.e. absolute directory
+ * plus file name.
+ * @return True for success.
+ */
+bool UMLFolder::loadFolderFile(const QString& path)
+{
+ QFile file(path);
+ if (!file.exists()) {
+ KMessageBox::error(0, i18n("The folderfile %1 does not exist.", path), i18n("Load Error"));
+ return false;
+ }
+ if (!file.open(QIODevice::ReadOnly)) {
+ KMessageBox::error(0, i18n("The folderfile %1 cannot be opened.", path), i18n("Load Error"));
+ return false;
+ }
+ QTextStream stream(&file);
+ QString data = stream.readAll();
+ file.close();
+ QDomDocument doc;
+ QString error;
+ int line;
+ if (!doc.setContent(data, false, &error, &line)) {
+ uError() << "Cannot set content:" << error << " line:" << line;
+ return false;
+ }
+ QDomNode rootNode = doc.firstChild();
+ while (rootNode.isComment() || rootNode.isProcessingInstruction()) {
+ rootNode = rootNode.nextSibling();
+ }
+ if (rootNode.isNull()) {
+ uError() << "Root node is Null";
+ return false;
+ }
+ QDomElement element = rootNode.toElement();
+ QString type = element.tagName();
+ if (type != QLatin1String("external_file")) {
+ uError() << "Root node has unknown type " << type;
+ return false;
+ }
+ return load(element);
+}
+
+/**
+ * Loads the owned elements of the <UML:Model>.
+ */
+bool UMLFolder::load(QDomElement& element)
+{
+ UMLDoc *umldoc = UMLApp::app()->document();
+ bool totalSuccess = true;
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString type = tempElement.tagName();
+ if (Model_Utils::isCommonXMIAttribute(type))
+ continue;
+ if (UMLDoc::tagEq(type, QLatin1String("Namespace.ownedElement")) ||
+ UMLDoc::tagEq(type, QLatin1String("Namespace.contents"))) {
+ //CHECK: umbrello-kf6 currently assumes that nested elements
+ // are ownedElements anyway.
+ // Therefore these tags are not further interpreted.
+ if (! load(tempElement)) {
+ uDebug() << "An error happened while loading the " << type
+ << " of the " << name();
+ totalSuccess = false;
+ }
+ continue;
+ } else if (UMLDoc::tagEq(type, QLatin1String("packagedElement")) ||
+ UMLDoc::tagEq(type, QLatin1String("ownedElement"))) {
+ type = tempElement.attribute(QLatin1String("xmi:type"));
+ } else if (type == QLatin1String("XMI.extension")) {
+ for (QDomNode xtnode = node.firstChild(); !xtnode.isNull();
+ xtnode = xtnode.nextSibling()) {
+ QDomElement el = xtnode.toElement();
+ const QString xtag = el.tagName();
+ if (xtag == QLatin1String("diagrams")) {
+ QDomNode diagramNode = xtnode.firstChild();
+ if (!loadDiagramsFromXMI(diagramNode))
+ totalSuccess = false;
+ } else if (xtag == QLatin1String("external_file")) {
+#if QT_VERSION >= 0x050000
+ const QString rootDir(umldoc->url().adjusted(QUrl::RemoveFilename).path());
+#else
+ const QString rootDir(umldoc->url().directory());
+#endif
+ QString fileName = el.attribute(QLatin1String("name"));
+ const QString path(rootDir + QLatin1Char('/') + fileName);
+ if (loadFolderFile(path))
+ m_folderFile = fileName;
+ } else {
+ uDebug() << name() << ": ignoring XMI.extension " << xtag;
+ continue;
+ }
+ }
+ continue;
+ }
+ // Do not re-create the predefined Datatypes folder in the Logical View,
+ // it already exists.
+ UMLFolder *logicalView = umldoc->rootFolder(Uml::ModelType::Logical);
+ if (this == logicalView && UMLDoc::tagEq(type, QLatin1String("Package"))) {
+ QString thisName = tempElement.attribute(QLatin1String("name"));
+ if (thisName == QLatin1String("Datatypes")) {
+ UMLFolder *datatypeFolder = umldoc->datatypeFolder();
+ if (!datatypeFolder->loadFromXMI(tempElement))
+ totalSuccess = false;
+ continue;
+ }
+ }
+ UMLObject *pObject = 0;
+ // Avoid duplicate creation of forward declared object
+ QString idStr = Model_Utils::getXmiId(tempElement);
+ if (!idStr.isEmpty()) {
+ Uml::ID::Type id = Uml::ID::fromString(idStr);
+ pObject = umldoc->findObjectById(id);
+ if (pObject) {
+ uDebug() << "object " << idStr << "already exists";
+ }
+ }
+ if (pObject == 0) {
+ QString stereoID = tempElement.attribute(QLatin1String("stereotype"));
+ pObject = Object_Factory::makeObjectFromXMI(type, stereoID);
+ if (!pObject) {
+ uWarning() << "Unknown type of umlobject to create: " << type;
+ continue;
+ }
+ }
+ pObject->setUMLPackage(this);
+ if (!pObject->loadFromXMI(tempElement)) {
+ removeObject(pObject);
+ delete pObject;
+ totalSuccess = false;
+ }
+ }
+ return totalSuccess;
+}
+
+/**
+ * Overloading operator for debugging output.
+ */
+QDebug operator<<(QDebug out, const UMLFolder& item)
+{
+ out.nospace() << "UMLFolder: localName=" << item.m_localName
+ << ", folderFile=" << item.m_folderFile
+ << ", diagrams=" << item.m_diagrams.count();
+ return out.space();
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/folder.h umbrello-kf6-15.08.1/umbrello/umlmodel/folder.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/folder.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/folder.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,92 @@
+/***************************************************************************
+ * 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) 2006-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLFOLDER_H
+#define UMLFOLDER_H
+
+#include "package.h"
+#include "umlviewlist.h"
+#include "optionstate.h"
+
+/**
+ * This class manages the UMLObjects and UMLViews of a Folder.
+ * This class inherits from UMLPackage which contains most
+ * of the information.
+ *
+ * The UMLDoc class allocates a fixed instance of this class for
+ * each of the predefined Logical, UseCase, Component, Deployment, and
+ * Entity-Relationship folders. Further instances are created on demand
+ * for user folders.
+ *
+ * @short Non-graphical management of objects and diagrams of a Folder
+ * @author Oliver Kellogg
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ *
+ * TODO: This whole class needs a relook regarding view/scene.
+ */
+class UMLFolder : public UMLPackage
+{
+ Q_OBJECT
+public:
+ explicit UMLFolder(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLFolder();
+
+ virtual UMLObject* clone() const;
+
+ void setLocalName(const QString& localName);
+ QString localName() const;
+
+ void addView(UMLView *view);
+
+ void removeView(UMLView *view);
+
+ void appendViews(UMLViewList& viewList, bool includeNested = true);
+
+ void activateViews();
+
+ UMLView* findView(Uml::ID::Type id);
+ UMLView* findView(Uml::DiagramType::Enum type, const QString &name, bool searchAllScopes = true);
+
+ void setViewOptions(const Settings::OptionState& optionState);
+
+ void removeAllViews();
+
+ void setFolderFile(const QString& fileName);
+ QString folderFile() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ friend QDebug operator<<(QDebug out, const UMLFolder& item);
+
+protected:
+ void saveContents(QDomDocument& qDoc, QDomElement& qElement);
+
+ void save(QDomDocument& qDoc, QDomElement& qElement);
+
+ bool loadDiagramsFromXMI(QDomNode& diagrams);
+
+ bool loadFolderFile(const QString& path);
+
+ bool load(QDomElement & element);
+
+private:
+ QString m_localName; ///< i18n name, only used for predefined root folders
+ /**
+ * If m_folderFile is not empty then it contains a file name to which
+ * this folder is saved.
+ * In this case the folder file acts as a physically separate submodel.
+ * What is saved in the main model is not the folder contents but a
+ * reference to the folder file.
+ */
+ QString m_folderFile;
+ UMLViewList m_diagrams;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/foreignkeyconstraint.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/foreignkeyconstraint.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/foreignkeyconstraint.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/foreignkeyconstraint.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,444 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+//own header
+#include "foreignkeyconstraint.h"
+
+// app includes
+#include "debug_utils.h"
+#include "entity.h"
+#include "entityattribute.h"
+#include "umlobject.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "umlforeignkeyconstraintdialog.h"
+#include "object_factory.h"
+
+/**
+ * Sets up a constraint.
+ * @param parent The parent of this UMLForeignKeyConstraint.
+ * @param name The name of this UMLForeignKeyConstraint.
+ * @param id The unique id given to this UMLForeignKeyConstraint.
+ */
+UMLForeignKeyConstraint::UMLForeignKeyConstraint(UMLObject *parent,
+ const QString& name, Uml::ID::Type id)
+ : UMLEntityConstraint(parent, name, id)
+{
+ init();
+}
+
+/**
+ * Sets up a constraint.
+ * @param parent The parent of this UMLForeignKeyConstraint.
+ */
+UMLForeignKeyConstraint::UMLForeignKeyConstraint(UMLObject *parent)
+ : UMLEntityConstraint(parent)
+{
+ init();
+}
+
+/**
+ * Initialisation of common variables
+ */
+void UMLForeignKeyConstraint::init()
+{
+ // initialise attributes
+ m_BaseType = UMLObject::ot_ForeignKeyConstraint;
+
+ // should be NULL actually
+ // self referencing assigned to protect default behaviour
+ m_ReferencedEntity = static_cast<UMLEntity*>(parent());
+
+ m_UpdateAction = uda_NoAction;
+ m_DeleteAction = uda_NoAction;
+
+ // connecte signals and slots
+ connect(this, SIGNAL(sigReferencedEntityChanged()), this, SLOT(slotReferencedEntityChanged()));
+}
+
+/**
+ * Overloaded '==' operator
+ */
+bool UMLForeignKeyConstraint::operator==(const UMLForeignKeyConstraint &rhs) const
+{
+ if(this == &rhs)
+ return true;
+
+ if(!UMLObject::operator==(rhs))
+ return false;
+
+ return true;
+}
+
+/**
+ * Destructor.
+ */
+UMLForeignKeyConstraint::~UMLForeignKeyConstraint()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the UMLForeignKeyConstraint
+ * object.
+ */
+void UMLForeignKeyConstraint::copyInto(UMLObject *lhs) const
+{
+ UMLForeignKeyConstraint *target = static_cast<UMLForeignKeyConstraint*>(lhs);
+
+ // call the parent first.
+ UMLEntityConstraint::copyInto(target);
+
+ // Copy all datamembers
+ target->m_ReferencedEntity = m_ReferencedEntity;
+ target->m_AttributeMap = m_AttributeMap;
+ target->m_DeleteAction = m_DeleteAction;
+ target->m_UpdateAction = m_UpdateAction;
+}
+
+/**
+ * Make a clone of the UMLForeignKeyConstraint.
+ */
+UMLObject* UMLForeignKeyConstraint::clone() const
+{
+ //FIXME: The new attribute should be slaved to the NEW parent not the old.
+ UMLForeignKeyConstraint *clone = new UMLForeignKeyConstraint(static_cast<UMLObject*>(parent()));
+ copyInto(clone);
+ return clone;
+}
+
+/**
+ * Returns a string representation of the UMLForeignKeyConstraint.
+ * @param sig If true will show the attribute type and initial value.
+ * @return Returns a string representation of the UMLAttribute.
+ */
+QString UMLForeignKeyConstraint::toString(Uml::SignatureType::Enum sig)
+{
+ QString s;
+
+ if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::SigNoVis) {
+ s = name() + QLatin1Char(':');
+ s += QLatin1String(" Foreign Key (");
+ QList<UMLEntityAttribute*> keys = m_AttributeMap.keys();
+ bool first = true;
+ foreach(UMLEntityAttribute* key, keys) {
+ if (first) {
+ first = false;
+ } else
+ s += QLatin1Char(',');
+ s += key->name();
+ }
+ s += QLatin1Char(')');
+ }
+
+ return s;
+}
+
+/**
+ * Creates the <UML:ForeignKeyConstraint> XMI element.
+ */
+void UMLForeignKeyConstraint::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement foreignKeyConstraintElement = UMLObject::save(QLatin1String("UML:ForeignKeyConstraint"), qDoc);
+
+ foreignKeyConstraintElement.setAttribute(QLatin1String("referencedEntity"), Uml::ID::toString(m_ReferencedEntity->id()));
+
+ int updateAction = (int)m_UpdateAction;
+ int deleteAction = (int)m_DeleteAction;
+
+ foreignKeyConstraintElement.setAttribute(QLatin1String("updateAction"), updateAction);
+ foreignKeyConstraintElement.setAttribute(QLatin1String("deleteAction"), deleteAction);
+
+ QMap<UMLEntityAttribute*, UMLEntityAttribute*>::iterator i;
+ for (i = m_AttributeMap.begin(); i!= m_AttributeMap.end() ; ++i) {
+ QDomElement mapElement = qDoc.createElement(QLatin1String("AttributeMap"));
+ mapElement.setAttribute(QLatin1String("key"), Uml::ID::toString((i.key())->id()));
+ mapElement.setAttribute(QLatin1String("value"), Uml::ID::toString((i.value())->id()));
+ foreignKeyConstraintElement.appendChild(mapElement);
+ }
+
+ qElement.appendChild(foreignKeyConstraintElement);
+}
+
+/**
+ * Display the properties configuration dialog for the attribute.
+ */
+bool UMLForeignKeyConstraint::showPropertiesDialog(QWidget* parent)
+{
+ UMLForeignKeyConstraintDialog dialog(parent, this);
+ return dialog.exec();
+}
+
+/**
+ * Adds the attribute pair to the attributeMap
+ * @param pAttr The Attribute of the Parent Entity
+ * @param rAttr The Attribute of the Referenced Entity
+ * @return true if the attribute pair could be added successfully
+ */
+bool UMLForeignKeyConstraint::addEntityAttributePair(UMLEntityAttribute* pAttr, UMLEntityAttribute* rAttr)
+{
+ UMLEntity *owningParent = dynamic_cast<UMLEntity*>(parent());
+
+ if (pAttr == NULL || rAttr == NULL) {
+ uError() << "null values passed to function";
+ return false;
+ }
+ // check for sanity of pAttr (parent entity attribute)
+ if (owningParent == NULL) {
+ uError() << name() << ": parent is not a UMLEntity";
+ return false;
+ }
+
+ if (owningParent->findChildObjectById(pAttr->id()) == NULL) {
+ uError() << " parent " << owningParent->name()
+ << " does not contain attribute " << pAttr->name();
+ return false;
+ }
+
+ //check for sanity of rAttr (referenced entity attribute)
+ if (m_ReferencedEntity != NULL) {
+ if (m_ReferencedEntity->findChildObjectById(rAttr->id()) == NULL) {
+ uError() << " parent " << m_ReferencedEntity->name()
+ << " does not contain attribute " << rAttr->name();
+ return false;
+ }
+ } else {
+ uError() << "Referenced Table Not set. Not Adding Pair ";
+ return false;
+ }
+
+ // check if key takes part in some mapping
+ if (m_AttributeMap.contains(pAttr) == true)
+ return false;
+
+ // check if value takes part in some mapping (no direct function)
+ foreach(UMLEntityAttribute* attr, m_AttributeMap.values()) {
+ if (rAttr == attr)
+ return false;
+ }
+
+ // passed all checks, insert now
+ m_AttributeMap.insert(pAttr, rAttr);
+
+ QMap<UMLEntityAttribute*, UMLEntityAttribute*>::iterator i;
+ for (i = m_AttributeMap.begin(); i != m_AttributeMap.end(); ++i)
+ uDebug() << i.key()->name() << QLatin1String(" ") << i.key()->baseType()
+ << QLatin1String(" ") << i.value()->name() << QLatin1String(" ") << i.value()->baseType();
+
+ return true;
+}
+
+/**
+ * Removes an Attribute pair
+ * @param pAttr The Attribute of the Parent Entity in the map. This attribute is the
+ key of the map.
+ * @return true of the attribute pair could be removed successfully
+ */
+bool UMLForeignKeyConstraint::removeEntityAttributePair(UMLEntityAttribute* /*key*/ pAttr)
+{
+ bool state = m_AttributeMap.remove(pAttr);
+
+ return state;
+}
+
+/**
+ * Check if a attribute pair already exists
+ * @param pAttr The Attribute of the Parent Entity
+ * @param rAttr The Attribute of the Referenced Entity
+ * @return true if the attribute pair could be found.
+ */
+bool UMLForeignKeyConstraint::hasEntityAttributePair(UMLEntityAttribute* pAttr, UMLEntityAttribute* rAttr) const
+{
+ if (m_AttributeMap.contains(pAttr)) {
+ if (m_AttributeMap.value(pAttr) == rAttr) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Loads the <UML:ForeignKeyConstraint> XMI element.
+ */
+bool UMLForeignKeyConstraint::load(QDomElement & element)
+{
+ UMLDoc* doc = UMLApp::app()->document();
+
+ Uml::ID::Type referencedEntityId = Uml::ID::fromString(element.attribute(QLatin1String("referencedEntity")));
+
+ UMLObject* obj = doc->findObjectById(referencedEntityId);
+ m_ReferencedEntity = static_cast<UMLEntity*>(obj);
+
+ if (m_ReferencedEntity == NULL) {
+ // save for resolving later
+ m_pReferencedEntityID = referencedEntityId;
+ }
+
+ m_UpdateAction = (UpdateDeleteAction)element.attribute(QLatin1String("updateAction")).toInt();
+ m_DeleteAction = (UpdateDeleteAction)element.attribute(QLatin1String("deleteAction")).toInt();
+
+ QDomNode node = element.firstChild();
+ while (!node.isNull()) {
+ if (node.isComment()) {
+ node = node.nextSibling();
+ continue;
+ }
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("AttributeMap"))) {
+
+ QString xmiKey = tempElement.attribute(QLatin1String("key"));
+ QString xmiValue = tempElement.attribute(QLatin1String("value"));
+ Uml::ID::Type keyId = Uml::ID::fromString(xmiKey);
+ Uml::ID::Type valueId = Uml::ID::fromString(xmiValue);
+
+ UMLEntity* parentEntity = static_cast<UMLEntity*>(parent());
+ UMLObject* keyObj = parentEntity->findChildObjectById(keyId);
+ UMLEntityAttribute* key = static_cast<UMLEntityAttribute*>(keyObj);
+
+ if (keyObj == NULL) {
+ uWarning() << "unable to resolve foreign key referencing attribute " << xmiKey;
+ } else if (m_ReferencedEntity == NULL) {
+ // if referenced entity is null, then we won't find its attributes even
+ // save for resolving later
+ m_pEntityAttributeIDMap.insert(key, valueId);
+ } else {
+ UMLObject* valueObj = m_ReferencedEntity->findChildObjectById(valueId);
+ if (valueObj == NULL) {
+ uWarning() << "unable to resolve foreign key referenced attribute" << xmiValue;
+ } else {
+ m_AttributeMap[key] = static_cast<UMLEntityAttribute*>(valueObj);
+ }
+ }
+
+ } else {
+ uWarning() << "unknown child type in UMLForeignKeyConstraint::load";
+ }
+
+ node = node.nextSibling();
+ }
+
+ return true;
+}
+
+/**
+ * Set the Referenced Entity.
+ * @param ent The Entity to Reference
+ */
+void UMLForeignKeyConstraint::setReferencedEntity(UMLEntity* ent)
+{
+ if (ent == m_ReferencedEntity)
+ return;
+
+ m_ReferencedEntity = ent;
+
+ emit sigReferencedEntityChanged();
+}
+
+/**
+ * Get the Referenced Entity.
+ * @return the UML entity object
+ */
+UMLEntity* UMLForeignKeyConstraint::getReferencedEntity() const
+{
+ return m_ReferencedEntity;
+}
+
+/**
+ * Slot for referenced entity changed.
+ */
+void UMLForeignKeyConstraint::slotReferencedEntityChanged()
+{
+ // clear all mappings
+ m_AttributeMap.clear();
+}
+
+/**
+ * Clears all mappings between local and referenced attributes
+ */
+void UMLForeignKeyConstraint::clearMappings()
+{
+ m_AttributeMap.clear();
+}
+
+/**
+ * Remimplementation from base classes
+ * Used to resolve forward references to referenced entities in xmi
+ */
+bool UMLForeignKeyConstraint::resolveRef()
+{
+ // resolve referenced entity first
+ UMLDoc* doc = UMLApp::app()->document();
+
+ bool success = true;
+
+ //resolve the referenced entity
+ if (!Uml::ID::toString(m_pReferencedEntityID).isEmpty()) {
+ UMLObject* obj = doc->findObjectById(m_pReferencedEntityID);
+ m_ReferencedEntity = static_cast<UMLEntity*>(obj);
+ if (m_ReferencedEntity == NULL) {
+ success = false;
+ }
+ }
+
+ QMap<UMLEntityAttribute*, Uml::ID::Type>::iterator i;
+ for (i = m_pEntityAttributeIDMap.begin(); i!= m_pEntityAttributeIDMap.end() ; ++i) {
+ if (!Uml::ID::toString(i.value()).isEmpty()) {
+ UMLObject* obj = doc->findObjectById(i.value());
+ m_AttributeMap[i.key()] = static_cast<UMLEntityAttribute*>(obj);
+ if (m_AttributeMap[i.key()] == NULL) {
+ success = false;
+ }
+ }
+ }
+
+ return success;
+}
+
+/**
+ * Retrieve all Pairs of Attributes.
+ */
+QMap<UMLEntityAttribute*, UMLEntityAttribute*> UMLForeignKeyConstraint::getEntityAttributePairs()
+{
+ return m_AttributeMap;
+}
+
+/**
+ * Get the Delete Action.
+ */
+UMLForeignKeyConstraint::UpdateDeleteAction UMLForeignKeyConstraint::getDeleteAction() const
+{
+ return m_DeleteAction;
+}
+
+/**
+ * Get the Update Action.
+ */
+UMLForeignKeyConstraint::UpdateDeleteAction UMLForeignKeyConstraint::getUpdateAction() const
+{
+ return m_UpdateAction;
+}
+
+/**
+ * Set the Delete Action to the specified UpdateDeleteAction.
+ */
+void UMLForeignKeyConstraint::setDeleteAction(UpdateDeleteAction uda)
+{
+ m_DeleteAction = uda;
+}
+
+/**
+ * Set the Update Action to the specified UpdateDeleteAction
+ */
+void UMLForeignKeyConstraint::setUpdateAction(UpdateDeleteAction uda)
+{
+ m_UpdateAction = uda;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/foreignkeyconstraint.h umbrello-kf6-15.08.1/umbrello/umlmodel/foreignkeyconstraint.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/foreignkeyconstraint.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/foreignkeyconstraint.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,120 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef FOREIGNKEYCONSTRAINT_H
+#define FOREIGNKEYCONSTRAINT_H
+
+// appl includes
+#include "basictypes.h"
+#include "entityconstraint.h"
+
+// qt includes
+#include <QMap>
+
+//forward declarations
+class UMLEntityAttribute;
+class UMLEntity;
+
+/**
+ * This class is used to set up information for a foreign key entity constraint.
+ * @short Sets up Foreign Key entity constraint information.
+ * @author Sharan Rao
+ * @see UMLObject UMLClassifierListItem UMLEntityConstraint
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLForeignKeyConstraint : public UMLEntityConstraint
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Update/Delete Action: Action to be taken on Update or Delete of a referenced attribute
+ * is either, No Action, Restrict, Cascade, Set NULL, Set Default.
+ */
+ enum UpdateDeleteAction { uda_NoAction = 0,
+ uda_Restrict,
+ uda_Cascade,
+ uda_SetNull,
+ uda_SetDefault };
+
+ UMLForeignKeyConstraint(UMLObject *parent, const QString& name,
+ Uml::ID::Type id = Uml::ID::None);
+ explicit UMLForeignKeyConstraint(UMLObject *parent);
+
+ bool operator==(const UMLForeignKeyConstraint &rhs) const;
+
+ virtual ~UMLForeignKeyConstraint();
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
+
+ void setReferencedEntity(UMLEntity* ent);
+ UMLEntity* getReferencedEntity() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ virtual bool showPropertiesDialog(QWidget* parent = 0);
+
+ bool addEntityAttributePair(UMLEntityAttribute* pAttr, UMLEntityAttribute* rAttr);
+
+ bool removeEntityAttributePair(UMLEntityAttribute* /*key*/ pAttr);
+
+ bool hasEntityAttributePair(UMLEntityAttribute* pAttr, UMLEntityAttribute* rAttr) const;
+
+ QMap<UMLEntityAttribute*, UMLEntityAttribute*> getEntityAttributePairs();
+
+ void setDeleteAction(UpdateDeleteAction uda);
+ UpdateDeleteAction getDeleteAction() const;
+
+ void setUpdateAction(UpdateDeleteAction uda);
+ UpdateDeleteAction getUpdateAction() const;
+
+ void clearMappings();
+
+ bool resolveRef();
+
+signals:
+ void sigReferencedEntityChanged();
+
+private slots:
+ void slotReferencedEntityChanged();
+
+protected:
+ bool load(QDomElement & element);
+
+private:
+
+ Uml::ID::Type m_pReferencedEntityID; ///< Used to resolve forward references to UMLEntity.
+
+ /**
+ * Used to resolve forward references to UMLEntityAttributes
+ * Key -> The local attribute
+ * Value -> Id of the attribute it is mapping to
+ */
+ QMap<UMLEntityAttribute*, Uml::ID::Type> m_pEntityAttributeIDMap;
+
+ void init();
+
+ UMLEntity* m_ReferencedEntity; ///< The UMLEntity that this foreign key references.
+
+ /**
+ * Stores the Mapping of attributes between parent table and referenced table
+ */
+ QMap<UMLEntityAttribute*, UMLEntityAttribute*> m_AttributeMap;
+
+ UpdateDeleteAction m_UpdateAction; ///< What to do on Update of referenced attributes.
+ UpdateDeleteAction m_DeleteAction; ///< What to do on Deletion of referenced attributes.
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/node.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/node.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/node.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/node.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "node.h"
+
+#include <KLocalizedString>
+
+/**
+ * Sets up a Node.
+ *
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+UMLNode::UMLNode(const QString & name, Uml::ID::Type id)
+ : UMLCanvasObject(name, id)
+{
+ init();
+}
+
+/**
+ * Destructor.
+ */
+UMLNode::~UMLNode()
+{
+}
+
+/**
+ * Initializes key variables of the class.
+ */
+void UMLNode::init()
+{
+ m_BaseType = UMLObject::ot_Node;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLNode::clone() const
+{
+ UMLNode *clone = new UMLNode();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+/**
+ * Creates the <UML:Node> XMI element.
+ */
+void UMLNode::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement nodeElement = UMLObject::save(QLatin1String("UML:Node"), qDoc);
+ qElement.appendChild(nodeElement);
+}
+
+/**
+ * Loads the <UML:Node> XMI element (empty.)
+ */
+bool UMLNode::load(QDomElement&)
+{
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/node.h umbrello-kf6-15.08.1/umbrello/umlmodel/node.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/node.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/node.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef NODE_H
+#define NODE_H
+
+#include "umlcanvasobject.h"
+
+/**
+ * This class contains the non-graphical information required for a UML Node.
+ * This class inherits from @ref UMLCanvasObject which contains most of the
+ * information.
+ *
+ * @short Non-graphical information for a Node.
+ * @author Jonathan Riddell
+ * @see UMLCanvasObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLNode : public UMLCanvasObject
+{
+ Q_OBJECT
+public:
+
+ explicit UMLNode(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLNode();
+
+ virtual void init();
+
+ virtual UMLObject* clone() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+protected:
+
+ bool load(QDomElement & element);
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/operation.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/operation.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/operation.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/operation.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,611 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "operation.h"
+
+// app includes
+#include "attribute.h"
+#include "classifier.h"
+#include "model_utils.h"
+#include "debug_utils.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "uniqueid.h"
+#include "umloperationdialog.h"
+#include "codegenerator.h"
+#include "codedocument.h"
+#include "codeblock.h"
+
+// kde includes
+#include <KLocalizedString>
+
+// qt includes
+#include <QRegExp>
+
+/**
+ * Constructs an UMLOperation.
+ * Not intended for general use: The operation is not tied in with
+ * umbrello-kf6's Qt signalling for object creation.
+ * If you want to create an Operation use the method in UMLDoc instead.
+ *
+ * @param parent the parent to this operation
+ * @param name the name of the operation
+ * @param id the id of the operation
+ * @param s the visibility of the operation
+ * @param rt the return type of the operation
+ */
+UMLOperation::UMLOperation(UMLClassifier *parent, const QString& name,
+ Uml::ID::Type id, Uml::Visibility::Enum s, UMLObject *rt)
+ : UMLClassifierListItem(parent, name, id)
+{
+ if (rt)
+ m_returnId = UniqueID::gen();
+ else
+ m_returnId = Uml::ID::None;
+ m_pSecondary = rt;
+ m_visibility = s;
+ m_BaseType = UMLObject::ot_Operation;
+ m_bConst = false;
+ m_Code.clear();
+}
+
+/**
+ * Constructs an UMLOperation.
+ * Not intended for general use: The operation is not tied in with
+ * umbrello-kf6's Qt signalling for object creation.
+ * If you want to create an Operation use the method in UMLDoc instead.
+ *
+ * @param parent the parent to this operation
+ */
+UMLOperation::UMLOperation(UMLClassifier * parent)
+ : UMLClassifierListItem (parent)
+{
+ m_BaseType = UMLObject::ot_Operation;
+ m_bConst = false;
+ m_Code.clear();
+}
+
+/**
+ * Destructor.
+ */
+UMLOperation::~UMLOperation()
+{
+}
+
+/**
+ * Reimplement method from UMLClassifierListItem.
+ *
+ * @param type pointer to the type object
+ */
+void UMLOperation::setType(UMLObject* type)
+{
+ UMLClassifierListItem::setType(type);
+ if (m_returnId == Uml::ID::None)
+ m_returnId = UniqueID::gen();
+}
+
+/**
+ * Move a parameter one position to the left.
+ *
+ * @param a the parameter to move
+ */
+void UMLOperation::moveParmLeft(UMLAttribute * a)
+{
+ if (a == NULL) {
+ uDebug() << "called on NULL attribute";
+ return;
+ }
+ uDebug() << "called for " << a->name();
+ disconnect(a, SIGNAL(modified()), this, SIGNAL(modified()));
+ int idx;
+ if ((idx=m_List.indexOf(a)) == -1) {
+ uDebug() << "Error move parm left " << a->name();
+ return;
+ }
+ if (idx == 0)
+ return;
+ m_List.removeAll(a);
+ m_List.insert(idx-1, a);
+}
+
+/**
+ * Move a parameter one position to the right.
+ *
+ * @param a the parameter to move
+ */
+void UMLOperation::moveParmRight(UMLAttribute * a)
+{
+ if (a == NULL) {
+ uDebug() << "called on NULL attribute";
+ return;
+ }
+ uDebug() << "called for " << a->name();
+ disconnect(a, SIGNAL(modified()), this, SIGNAL(modified()));
+ int idx;
+ if ((idx=m_List.indexOf(a)) == -1) {
+ uDebug() << "Error move parm right " << a->name();
+ return;
+ }
+ int count = m_List.count();
+ if (idx == count-1)
+ return;
+ m_List.removeAll(a);
+ m_List.insert(idx+1, a);
+}
+
+/**
+ * Remove a parameter from the operation.
+ *
+ * @param a the parameter to remove
+ * @param emitModifiedSignal whether to emit the "modified" signal
+ * which creates an entry in the Undo stack for the
+ * removal, default: true
+ */
+void UMLOperation::removeParm(UMLAttribute * a, bool emitModifiedSignal /* =true */)
+{
+ if (a == NULL) {
+ uDebug() << "called on NULL attribute";
+ return;
+ }
+ uDebug() << "called for " << a->name();
+ disconnect(a, SIGNAL(modified()), this, SIGNAL(modified()));
+ if(!m_List.removeAll(a))
+ uDebug() << "Error removing parm " << a->name();
+
+ if (emitModifiedSignal)
+ emit modified();
+}
+
+/**
+ * Returns a list of parameters.
+ *
+ * @return a list of the parameters in the operation
+ */
+UMLAttributeList UMLOperation::getParmList() const
+{
+ return m_List;
+}
+
+/**
+ * Finds a parameter of the operation.
+ *
+ * @param name the parameter name to search for
+ * @return the found parameter, 0 if not found
+ */
+UMLAttribute* UMLOperation::findParm(const QString &name)
+{
+ UMLAttribute * obj=0;
+ foreach (obj, m_List) {
+ if (obj->name() == name)
+ return obj;
+ }
+ return 0;
+}
+
+/**
+ * Returns a string representation of the operation.
+ *
+ * @param sig what type of operation string to show
+ * @return the string representation of the operation
+ */
+QString UMLOperation::toString(Uml::SignatureType::Enum sig)
+{
+ QString s;
+
+ if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::NoSig)
+ s = Uml::Visibility::toString(m_visibility, true) + QLatin1Char(' ');
+
+ s += name();
+ Uml::ProgrammingLanguage::Enum pl = UMLApp::app()->activeLanguage();
+ bool parameterlessOpNeedsParentheses =
+ (pl != Uml::ProgrammingLanguage::Pascal && pl != Uml::ProgrammingLanguage::Ada);
+
+ if (sig == Uml::SignatureType::NoSig || sig == Uml::SignatureType::NoSigNoVis) {
+ if (parameterlessOpNeedsParentheses)
+ s.append(QLatin1String("()"));
+ return s;
+ }
+ int last = m_List.count();
+ if (last) {
+ s.append(QLatin1String("("));
+ int i = 0;
+ foreach (UMLAttribute *param, m_List) {
+ i++;
+ s.append(param->toString(Uml::SignatureType::SigNoVis));
+ if (i < last)
+ s.append(QLatin1String(", "));
+ }
+ s.append(QLatin1String(")"));
+ } else if (parameterlessOpNeedsParentheses) {
+ s.append(QLatin1String("()"));
+ }
+ UMLClassifier *ownParent = static_cast<UMLClassifier*>(parent());
+ QString returnType;
+ UMLClassifier *retType = UMLClassifierListItem::getType();
+ if (retType) {
+ UMLPackage *retVisibility = retType->umlPackage();
+ if (retVisibility != ownParent && retVisibility != ownParent->umlPackage())
+ returnType = retType->fullyQualifiedName();
+ else
+ returnType = retType->name();
+ }
+ if (returnType.length() > 0 && returnType != QLatin1String("void")) {
+ s.append(QLatin1String(" : "));
+
+ if (returnType.startsWith(QLatin1String(QLatin1String("virtual ")))) {
+ s += returnType.mid(8);
+ } else {
+ s += returnType;
+ }
+ }
+ return s;
+}
+
+/**
+ * Add a parameter to the operation.
+ *
+ * @param parameter the parameter to add
+ * @param position the position in the parameter list.
+ * If position = -1 the parameter will be
+ * appended to the list.
+ */
+void UMLOperation::addParm(UMLAttribute *parameter, int position)
+{
+ if(position >= 0 && position <= (int)m_List.count())
+ m_List.insert(position, parameter);
+ else
+ m_List.append(parameter);
+ UMLObject::emitModified();
+ connect(parameter, SIGNAL(modified()), this, SIGNAL(modified()));
+}
+
+/**
+ * Returns an unused parameter name for a new parameter.
+ */
+QString UMLOperation::getUniqueParameterName()
+{
+ QString currentName = i18n("new_parameter");
+ QString name = currentName;
+ for (int number = 1; findParm(name); ++number) {
+ name = currentName + QLatin1Char('_') + QString::number(number);
+ }
+ return name;
+}
+
+/**
+ * Overloaded '==' operator.
+ */
+bool UMLOperation::operator==(const UMLOperation & rhs) const
+{
+ if (this == &rhs)
+ return true;
+
+ if (!UMLObject::operator==(rhs))
+ return false;
+
+ if (getTypeName() != rhs.getTypeName())
+ return false;
+
+ if (m_List.count() != rhs.m_List.count())
+ return false;
+
+ if (!(m_List == rhs.m_List))
+ return false;
+
+ return true;
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLOperation::copyInto(UMLObject *lhs) const
+{
+ UMLOperation *target = static_cast<UMLOperation*>(lhs);
+
+ UMLClassifierListItem::copyInto(target);
+
+ m_List.copyInto(&(target->m_List));
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLOperation::clone() const
+{
+ //FIXME: The new operation should be slaved to the NEW parent not the old.
+ UMLOperation *clone = new UMLOperation(static_cast<UMLClassifier*>(parent()));
+ copyInto(clone);
+
+ return clone;
+}
+
+/**
+ * Calls resolveRef() on all parameters.
+ * Needs to be called after all UML objects are loaded from file.
+ *
+ * @return true for success
+ */
+bool UMLOperation::resolveRef()
+{
+ bool overallSuccess = UMLObject::resolveRef();
+ // See remark on iteration style in UMLClassifier::resolveRef()
+ foreach (UMLAttribute* pAtt, m_List) {
+ if (! pAtt->resolveRef())
+ overallSuccess = false;
+ }
+ return overallSuccess;
+}
+
+/**
+ * Returns whether this operation is a constructor.
+ *
+ * @return true if this operation is a constructor
+ */
+bool UMLOperation::isConstructorOperation()
+{
+ // if an operation has the stereotype constructor
+ // return true
+ if (stereotype() == QLatin1String("constructor"))
+ return true;
+
+ UMLClassifier * c = static_cast<UMLClassifier*>(this->parent());
+ QString cName = c->name();
+ QString opName = name();
+ // It's a constructor operation if the operation name
+ // matches that of the parent classifier.
+ return (cName == opName);
+}
+
+/**
+ * Returns whether this operation is a destructor.
+ *
+ * @return true if this operation is a destructor
+ */
+bool UMLOperation::isDestructorOperation()
+{
+ if (stereotype() == QLatin1String("destructor"))
+ return true;
+ UMLClassifier * c = static_cast<UMLClassifier*>(this->parent());
+
+ QString cName = c->name();
+ QString opName = name();
+ // Special support for C++ syntax:
+ // It's a destructor operation if the operation name begins
+ // with "~" followed by the name of the parent classifier.
+ if (! opName.startsWith(QLatin1Char('~')))
+ return false;
+ opName.remove(QRegExp(QLatin1String("^~\\s*")));
+ return (cName == opName);
+}
+
+/**
+ * Shortcut for (isConstructorOperation() || isDestructorOperation()).
+ *
+ * @return true if this operation is a constructor or destructor
+ */
+bool UMLOperation::isLifeOperation()
+{
+ return (isConstructorOperation() || isDestructorOperation());
+}
+
+/**
+ * Sets whether this operation is a query (C++ "const").
+ */
+void UMLOperation::setConst(bool b)
+{
+ m_bConst = b;
+}
+
+/**
+ * Returns whether this operation is a query (C++ "const").
+ */
+bool UMLOperation::getConst() const
+{
+ return m_bConst;
+}
+
+/**
+ * Display the properties configuration dialog for the template.
+ *
+ * @param parent the parent for the dialog
+ */
+bool UMLOperation::showPropertiesDialog(QWidget* parent)
+{
+ UMLOperationDialog dialog(parent, this);
+ return dialog.exec();
+}
+
+/**
+ * Sets the source code for this operation.
+ *
+ * @param code the body of this operation
+ */
+void UMLOperation::setSourceCode(const QString& code)
+{
+ m_Code = code;
+}
+
+/**
+ * Returns the source code for this operation.
+ */
+QString UMLOperation::getSourceCode() const
+{
+ return m_Code;
+}
+
+/**
+ * Saves to the <UML:Operation> XMI element.
+ */
+void UMLOperation::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement operationElement = UMLObject::save(QLatin1String("UML:Operation"), qDoc);
+ operationElement.setAttribute(QLatin1String("isQuery"), m_bConst ? QLatin1String("true") : QLatin1String("false"));
+ QDomElement featureElement = qDoc.createElement(QLatin1String("UML:BehavioralFeature.parameter"));
+ if (m_pSecondary) {
+ QDomElement retElement = qDoc.createElement(QLatin1String("UML:Parameter"));
+ if (m_returnId == Uml::ID::None) {
+ uDebug() << name() << ": m_returnId is not set, setting it now.";
+ m_returnId = UniqueID::gen();
+ }
+ retElement.setAttribute(QLatin1String("xmi.id"), Uml::ID::toString(m_returnId));
+ retElement.setAttribute(QLatin1String("type"), Uml::ID::toString(m_pSecondary->id()));
+ retElement.setAttribute(QLatin1String("kind"), QLatin1String("return"));
+ featureElement.appendChild(retElement);
+ } else {
+ uDebug() << "m_SecondaryId is " << m_SecondaryId;
+ }
+
+ //save each attribute here, type different
+ foreach(UMLAttribute* pAtt, m_List) {
+ QDomElement attElement = pAtt->UMLObject::save(QLatin1String("UML:Parameter"), qDoc);
+ UMLClassifier *attrType = pAtt->getType();
+ if (attrType) {
+ attElement.setAttribute(QLatin1String("type"), Uml::ID::toString(attrType->id()));
+ } else {
+ attElement.setAttribute(QLatin1String("type"), pAtt->getTypeName());
+ }
+ attElement.setAttribute(QLatin1String("value"), pAtt->getInitialValue());
+
+ Uml::ParameterDirection::Enum kind = pAtt->getParmKind();
+ if (kind == Uml::ParameterDirection::Out)
+ attElement.setAttribute(QLatin1String("kind"), QLatin1String("out"));
+ else if (kind == Uml::ParameterDirection::InOut)
+ attElement.setAttribute(QLatin1String("kind"), QLatin1String("inout"));
+ // The default for the parameter kind is "in".
+
+ featureElement.appendChild(attElement);
+ }
+ if (featureElement.hasChildNodes()) {
+ operationElement.appendChild(featureElement);
+ }
+ qElement.appendChild(operationElement);
+}
+
+/**
+ * Loads a <UML:Operation> XMI element.
+ */
+bool UMLOperation::load(QDomElement & element)
+{
+ m_SecondaryId = element.attribute(QLatin1String("type"));
+ QString isQuery = element.attribute(QLatin1String("isQuery"));
+ if (!isQuery.isEmpty()) {
+ // We need this extra test for isEmpty() because load() might have been
+ // called again by the processing for BehavioralFeature.parameter (see below)
+ m_bConst = (isQuery == QLatin1String("true"));
+ }
+ QDomNode node = element.firstChild();
+ if (node.isComment())
+ node = node.nextSibling();
+ QDomElement attElement = node.toElement();
+ while (!attElement.isNull()) {
+ QString tag = attElement.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("BehavioralFeature.parameter")) ||
+ UMLDoc::tagEq(tag, QLatin1String("Element.ownedElement"))) { // Embarcadero's Describe
+ if (! load(attElement))
+ return false;
+ } else if (UMLDoc::tagEq(tag, QLatin1String("Parameter"))) {
+ QString kind = attElement.attribute(QLatin1String("kind"));
+ if (kind.isEmpty()) {
+ kind = attElement.attribute(QLatin1String("direction")); // Embarcadero's Describe
+ if (kind.isEmpty()) {
+ // Perhaps the kind is stored in a child node:
+ for (QDomNode n = attElement.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (n.isComment())
+ continue;
+ QDomElement tempElement = n.toElement();
+ QString tag = tempElement.tagName();
+ if (!UMLDoc::tagEq(tag, QLatin1String("kind")))
+ continue;
+ kind = tempElement.attribute(QLatin1String("xmi.value"));
+ break;
+ }
+ }
+ if (kind.isEmpty()) {
+ kind = QLatin1String("in");
+ }
+ }
+ if (kind == QLatin1String("return") ||
+ kind == QLatin1String("result")) { // Embarcadero's Describe
+ QString returnId = Model_Utils::getXmiId(attElement);
+ if (!returnId.isEmpty())
+ m_returnId = Uml::ID::fromString(returnId);
+ m_SecondaryId = attElement.attribute(QLatin1String("type"));
+ if (m_SecondaryId.isEmpty()) {
+ // Perhaps the type is stored in a child node:
+ QDomNode node = attElement.firstChild();
+ while (!node.isNull()) {
+ if (node.isComment()) {
+ node = node.nextSibling();
+ continue;
+ }
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (!UMLDoc::tagEq(tag, QLatin1String("type"))) {
+ node = node.nextSibling();
+ continue;
+ }
+ m_SecondaryId = Model_Utils::getXmiId(tempElement);
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = tempElement.attribute(QLatin1String("xmi.idref"));
+ if (m_SecondaryId.isEmpty()) {
+ QDomNode inner = node.firstChild();
+ QDomElement tmpElem = inner.toElement();
+ m_SecondaryId = Model_Utils::getXmiId(tmpElem);
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = tmpElem.attribute(QLatin1String("xmi.idref"));
+ }
+ break;
+ }
+ if (m_SecondaryId.isEmpty()) {
+ uError() << name() << ": cannot find return type.";
+ }
+ }
+ // Use deferred xmi.id resolution.
+ m_pSecondary = NULL;
+ } else {
+ UMLAttribute * pAtt = new UMLAttribute(this);
+ if(!pAtt->loadFromXMI(attElement)) {
+ delete pAtt;
+ return false;
+ }
+ if (kind == QLatin1String("out"))
+ pAtt->setParmKind(Uml::ParameterDirection::Out);
+ else if (kind == QLatin1String("inout"))
+ pAtt->setParmKind(Uml::ParameterDirection::InOut);
+ else
+ pAtt->setParmKind(Uml::ParameterDirection::In);
+ m_List.append(pAtt);
+ }
+ }
+ node = node.nextSibling();
+ if (node.isComment())
+ node = node.nextSibling();
+ attElement = node.toElement();
+
+ // loading the source code which was entered in the 'classpropdlg' dialog is not done
+ // with the following code, because there is no CodeDocument.
+ /*
+ CodeGenerator* codegen = UMLApp::app()->getGenerator();
+ if (codegen) {
+ uDebug() << "CodeDocument searching with id=" << Uml::ID::toString(UMLObject::ID());
+ CodeDocument* codeDoc = codegen->findCodeDocumentByID(Uml::ID::toString(UMLObject::ID()));
+ if (codeDoc) {
+ uDebug() << "CodeDocument found:\n" << codeDoc;
+ }
+ }
+ */
+ // it is done in the code generators by calling CodeGenerator::loadFromXMI(...).
+
+ }//end while
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/operation.h umbrello-kf6-15.08.1/umbrello/umlmodel/operation.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/operation.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/operation.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef OPERATION_H
+#define OPERATION_H
+
+#include "umlattributelist.h"
+#include "classifierlistitem.h"
+
+class UMLClassifier;
+
+/**
+ * This class represents an operation in the UML model.
+ *
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLOperation : public UMLClassifierListItem
+{
+ Q_OBJECT
+public:
+ UMLOperation(UMLClassifier * parent, const QString& name,
+ Uml::ID::Type id = Uml::ID::None,
+ Uml::Visibility::Enum s = Uml::Visibility::Public,
+ UMLObject *rt = 0);
+ explicit UMLOperation(UMLClassifier * parent);
+ virtual ~UMLOperation();
+
+ bool operator==(const UMLOperation & rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ void setType(UMLObject* type);
+
+ void moveParmLeft(UMLAttribute *a);
+ void moveParmRight(UMLAttribute *a);
+
+ void removeParm(UMLAttribute *a, bool emitModifiedSignal = true);
+
+ UMLAttributeList getParmList() const;
+
+ UMLAttribute * findParm(const QString &name);
+
+ QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
+
+ void addParm(UMLAttribute *parameter, int position = -1);
+
+ bool resolveRef();
+
+ QString getUniqueParameterName();
+
+ virtual bool showPropertiesDialog(QWidget* parent = 0);
+
+ bool isConstructorOperation();
+ bool isDestructorOperation();
+ bool isLifeOperation();
+
+ void setConst(bool b);
+ bool getConst() const;
+
+ void setSourceCode(const QString& code);
+ QString getSourceCode() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+protected:
+ bool load(QDomElement & element);
+
+private:
+ Uml::ID::Type m_returnId; ///< Holds the xmi.id of the <UML:Parameter kind="return">
+ UMLAttributeList m_List; ///< Parameter list
+ bool m_bConst; ///< Holds the isQuery attribute of the <UML:Operation>
+ QString m_Code; ///< Holds the entered source code
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/package.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/package.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/package.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/package.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,461 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header file
+#include "package.h"
+
+// local includes
+#include "debug_utils.h"
+#include "dialog_utils.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "classifier.h"
+#include "association.h"
+#include "entity.h"
+#include "object_factory.h"
+#include "model_utils.h"
+
+// kde includes
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+#include <KLocalizedString>
+#include <KMessageBox>
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+
+using namespace Uml;
+
+/**
+ * Sets up a Package.
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+UMLPackage::UMLPackage(const QString & name, Uml::ID::Type id)
+ : UMLCanvasObject(name, id)
+{
+ m_BaseType = ot_Package;
+}
+
+/**
+ * Destructor.
+ */
+UMLPackage::~UMLPackage()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the new object.
+ */
+void UMLPackage::copyInto(UMLObject *lhs) const
+{
+ UMLPackage *target = static_cast<UMLPackage*>(lhs);
+
+ UMLCanvasObject::copyInto(target);
+
+ m_objects.copyInto(&(target->m_objects));
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLPackage::clone() const
+{
+ UMLPackage *clone = new UMLPackage();
+ copyInto(clone);
+
+ return clone;
+}
+
+/**
+ * Adds an existing association to the matching concept in the list of concepts.
+ * The selection of the matching concept depends on the association type:
+ * For generalizations, the assoc is added to the concept that matches role A.
+ * For aggregations and compositions, the assoc is added to the concept
+ * that matches role B.
+ * @param assoc the association to add
+ */
+void UMLPackage::addAssocToConcepts(UMLAssociation* assoc)
+{
+ if (! AssociationType::hasUMLRepresentation(assoc->getAssocType()))
+ return;
+ Uml::ID::Type AId = assoc->getObjectId(Uml::RoleType::A);
+ Uml::ID::Type BId = assoc->getObjectId(Uml::RoleType::B);
+ UMLObject *o = NULL;
+ for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
+ o = oit.next();
+ UMLCanvasObject *c = dynamic_cast<UMLCanvasObject*>(o);
+ if (c == NULL)
+ continue;
+ if (AId == c->id() || (BId == c->id())) {
+ if (c->hasAssociation(assoc))
+ uDebug() << c->name() << " already has association id=" << Uml::ID::toString(assoc->id());
+ else
+ c->addAssociationEnd(assoc);
+ }
+ UMLPackage *pkg = dynamic_cast<UMLPackage*>(c);
+ if (pkg)
+ pkg->addAssocToConcepts(assoc);
+ }
+}
+
+/**
+ * Remove the association from the participating concepts.
+ * @param assoc the association to remove
+ */
+void UMLPackage::removeAssocFromConcepts(UMLAssociation *assoc)
+{
+ UMLObject *o = 0;
+ for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
+ o = oit.next();
+ UMLCanvasObject *c = dynamic_cast<UMLCanvasObject*>(o);
+ if (c) {
+ if (c->hasAssociation(assoc))
+ c->removeAssociationEnd(assoc);
+ UMLPackage *pkg = dynamic_cast<UMLPackage*>(c);
+ if (pkg)
+ pkg->removeAssocFromConcepts(assoc);
+ }
+ }
+}
+
+/**
+ * Adds an object in this package.
+ *
+ * @param pObject Pointer to the UMLObject to add.
+ * @return True if the object was actually added.
+ */
+bool UMLPackage::addObject(UMLObject *pObject)
+{
+ if (pObject == NULL) {
+ uError() << "is called with a NULL object";
+ return false;
+ }
+ if (pObject == this) {
+ uError() << "adding myself as child is not allowed";
+ return false;
+ }
+
+ if (m_objects.indexOf(pObject) != -1) {
+ uDebug() << pObject->name() << " is already there";
+ return false;
+ }
+ if (pObject->baseType() == UMLObject::ot_Association) {
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(pObject);
+ // Adding the UMLAssociation at the participating concepts is done
+ // again later (in UMLAssociation::resolveRef()) if they are not yet
+ // known right here.
+ if (assoc->getObject(Uml::RoleType::A) && assoc->getObject(Uml::RoleType::B)) {
+ UMLPackage *pkg = pObject->umlPackage();
+ if (pkg != this) {
+ uError() << "UMLPackage " << name() << " addObject: "
+ << "assoc's UMLPackage is " << pkg->name();
+ }
+ addAssocToConcepts(assoc);
+ }
+ }
+ else {
+ QString name = pObject->name();
+ QString oldName = name;
+ while (findObject(name) != NULL) {
+ QString prevName = name;
+ name = Model_Utils::uniqObjectName(pObject->baseType(), this);
+ bool ok = Dialog_Utils::askName(i18nc("object name", "Name"),
+ i18n("An object with the name %1\nalready exists in the package %2.\nPlease enter a new name:", prevName, this->name()),
+ name);
+ if (!ok) {
+ name = oldName;
+ continue;
+ }
+ if (name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."),
+ i18n("Invalid Name"));
+ continue;
+ }
+ }
+ if (oldName != name) {
+ pObject->setName(name);
+ }
+ }
+ m_objects.append(pObject);
+ return true;
+}
+
+/**
+ * Removes an object from this package.
+ * Does not physically delete the object.
+ *
+ * @param pObject Pointer to the UMLObject to be removed.
+ */
+void UMLPackage::removeObject(UMLObject *pObject)
+{
+ if (pObject->baseType() == UMLObject::ot_Association) {
+ UMLObject *o = const_cast<UMLObject*>(pObject);
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
+ removeAssocFromConcepts(assoc);
+ }
+ if (m_objects.indexOf(pObject) == -1)
+ uDebug() << name() << " removeObject: object with id="
+ << Uml::ID::toString(pObject->id()) << "not found.";
+ else
+ m_objects.removeAll(pObject);
+}
+
+/**
+ * Removes all objects from this package.
+ * Inner containers (e.g. nested packages) are removed recursively.
+ */
+void UMLPackage::removeAllObjects()
+{
+ UMLCanvasObject::removeAllChildObjects();
+ UMLObject *o = NULL;
+
+ while (!m_objects.isEmpty() && (o = m_objects.first()) != NULL) {
+ UMLPackage *pkg = dynamic_cast<UMLPackage*>(o);
+ if (pkg)
+ pkg->removeAllObjects();
+ removeObject(o);
+ delete o;
+ }
+}
+
+/**
+ * Returns the list of objects contained in this package.
+ */
+UMLObjectList UMLPackage::containedObjects()
+{
+ return m_objects;
+}
+
+/**
+ * Find the object of the given name in the list of contained objects.
+ *
+ * @param name The name to seek.
+ * @return Pointer to the UMLObject found or NULL if not found.
+ */
+UMLObject * UMLPackage::findObject(const QString &name)
+{
+ const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
+ for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
+ UMLObject *obj = oit.next();
+ if (!obj)
+ continue;
+ if (caseSensitive) {
+ if (obj->name() == name)
+ return obj;
+ } else if (obj->name().toLower() == name.toLower()) {
+ return obj;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Find the object of the given ID in the list of contained objects.
+ *
+ * @param id The ID to seek.
+ * @return Pointer to the UMLObject found or NULL if not found.
+ */
+UMLObject * UMLPackage::findObjectById(Uml::ID::Type id)
+{
+ return Model_Utils::findObjectInList(id, m_objects);
+}
+
+/**
+ * Append all packages from this package (and those from nested packages)
+ * to the given UMLPackageList.
+ *
+ * @param packages The list to append to
+ * @param includeNested Whether to include the packages from nested packages
+ * (default:true)
+ */
+void UMLPackage::appendPackages(UMLPackageList& packages, bool includeNested)
+{
+ for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
+ UMLObject *o = oit.next();
+ uIgnoreZeroPointer(o);
+ ObjectType ot = o->baseType();
+ if (ot == ot_Package || ot == ot_Folder) {
+ packages.append(static_cast<UMLPackage*>(o));
+ if (includeNested) {
+ UMLPackage *inner = static_cast<UMLPackage*>(o);
+ inner->appendPackages(packages);
+ }
+ }
+ }
+}
+
+/**
+ * Append all classifiers from this package (and those from
+ * nested packages) to the given UMLClassifierList.
+ *
+ * @param classifiers The list to append to.
+ * @param includeNested Whether to include the classifiers from
+ * nested packages (default: true.)
+ */
+void UMLPackage::appendClassifiers(UMLClassifierList& classifiers,
+ bool includeNested /* = true */)
+{
+ for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
+ UMLObject *o = oit.next();
+ uIgnoreZeroPointer(o);
+ ObjectType ot = o->baseType();
+ if (ot == ot_Class || ot == ot_Interface ||
+ ot == ot_Datatype || ot == ot_Enum || ot == ot_Entity) {
+ classifiers.append((UMLClassifier *)o);
+ } else if (includeNested && (ot == ot_Package || ot == ot_Folder)) {
+ UMLPackage *inner = static_cast<UMLPackage *>(o);
+ inner->appendClassifiers(classifiers);
+ }
+ }
+}
+
+/**
+ * Append all entities from this package (and those
+ * from nested packages) to the given UMLEntityList.
+ *
+ * @param entities The list to append to.
+ * @param includeNested Whether to include the entities from
+ * nested packages (default: true.)
+ */
+void UMLPackage::appendEntities(UMLEntityList& entities,
+ bool includeNested /* = true */)
+{
+ for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
+ UMLObject *o = oit.next();
+ uIgnoreZeroPointer(o);
+ ObjectType ot = o->baseType();
+ if (ot == ot_Entity) {
+ UMLEntity *c = static_cast<UMLEntity*>(o);
+ entities.append(c);
+ } else if (includeNested && (ot == ot_Package || ot == ot_Folder)) {
+ UMLPackage *inner = static_cast<UMLPackage *>(o);
+ inner->appendEntities(entities);
+ }
+ }
+}
+
+/**
+ * Append all classes and interfaces from this package (and those
+ * from nested packages) to the given UMLClassifierList.
+ *
+ * @param classifiers The list to append to.
+ * @param includeNested Whether to include the classifiers from
+ * nested packages (default: true.)
+ */
+void UMLPackage::appendClassesAndInterfaces(UMLClassifierList& classifiers,
+ bool includeNested /* = true */)
+{
+ for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
+ UMLObject *o = oit.next();
+ uIgnoreZeroPointer(o);
+ ObjectType ot = o->baseType();
+ if (ot == ot_Class || ot == ot_Interface) {
+ UMLClassifier *c = static_cast<UMLClassifier*>(o);
+ classifiers.append(c);
+ } else if (includeNested && (ot == ot_Package || ot == ot_Folder)) {
+ UMLPackage *inner = static_cast<UMLPackage *>(o);
+ inner->appendClassesAndInterfaces(classifiers);
+ }
+ }
+}
+
+/**
+ * Resolve types. Required when dealing with foreign XMI files.
+ * Needs to be called after all UML objects are loaded from file.
+ * Overrides the method from UMLObject.
+ * Calls resolveRef() on each contained object.
+ *
+ * @return True for overall success.
+ */
+bool UMLPackage::resolveRef()
+{
+ bool overallSuccess = UMLCanvasObject::resolveRef();
+ for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
+ UMLObject *obj = oit.next();
+ uIgnoreZeroPointer(obj);
+ if (! obj->resolveRef()) {
+ UMLObject::ObjectType ot = obj->baseType();
+ if (ot != UMLObject::ot_Package && ot != UMLObject::ot_Folder)
+ m_objects.removeAll(obj);
+ overallSuccess = false;
+ }
+ }
+ return overallSuccess;
+}
+
+/**
+ * Creates the <UML:Package> XMI element.
+ */
+void UMLPackage::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement packageElement = UMLObject::save(QLatin1String("UML:Package"), qDoc);
+ QDomElement ownedElement = qDoc.createElement(QLatin1String("UML:Namespace.ownedElement"));
+ UMLObject *obj = NULL;
+ // save classifiers etc.
+ for (UMLObjectListIt oit(m_objects); oit.hasNext();) {
+ obj = oit.next();
+ uIgnoreZeroPointer(obj);
+ obj->saveToXMI (qDoc, ownedElement);
+ }
+ // save associations
+ for (UMLObjectListIt ait(m_List); ait.hasNext();) {
+ obj = ait.next();
+ obj->saveToXMI (qDoc, ownedElement);
+ }
+
+ packageElement.appendChild(ownedElement);
+ qElement.appendChild(packageElement);
+}
+
+/**
+ * Loads the <UML:Package> XMI element.
+ * Auxiliary to UMLObject::loadFromXMI.
+ */
+bool UMLPackage::load(QDomElement& element)
+{
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString type = tempElement.tagName();
+ if (Model_Utils::isCommonXMIAttribute(type))
+ continue;
+ if (UMLDoc::tagEq(type, QLatin1String("Namespace.ownedElement")) ||
+ UMLDoc::tagEq(type, QLatin1String("Element.ownedElement")) || // Embarcadero's Describe
+ UMLDoc::tagEq(type, QLatin1String("Namespace.contents"))) {
+ //CHECK: umbrello-kf6 currently assumes that nested elements
+ // are ownedElements anyway.
+ // Therefore these tags are not further interpreted.
+ if (! load(tempElement))
+ return false;
+ continue;
+ } else if (UMLDoc::tagEq(type, QLatin1String("packagedElement")) ||
+ UMLDoc::tagEq(type, QLatin1String("ownedElement"))) {
+ type = tempElement.attribute(QLatin1String("xmi:type"));
+ }
+ UMLObject *pObject = Object_Factory::makeObjectFromXMI(type);
+ if(!pObject) {
+ uWarning() << "Unknown type of umlobject to create: " << type;
+ continue;
+ }
+ pObject->setUMLPackage(this);
+ if (!pObject->loadFromXMI(tempElement)) {
+ removeObject(pObject);
+ delete pObject;
+ }
+ }
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/package.h umbrello-kf6-15.08.1/umbrello/umlmodel/package.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/package.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/package.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef PACKAGE_H
+#define PACKAGE_H
+
+#include "umlcanvasobject.h"
+#include "umlclassifierlist.h"
+#include "umlentitylist.h"
+
+// forward declarations
+class UMLAssociation;
+
+/**
+ * This class contains the non-graphical information required for a UML
+ * Package.
+ * This class inherits from @ref UMLCanvasObject which contains most of the
+ * information.
+ *
+ * @short Non-graphical information for a Package.
+ * @author Jonathan Riddell
+ * @see UMLCanvasObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLPackage : public UMLCanvasObject
+{
+ Q_OBJECT
+public:
+ explicit UMLPackage(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLPackage();
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ bool addObject(UMLObject *pObject);
+ void removeObject(UMLObject *pObject);
+
+ virtual void removeAllObjects();
+
+ UMLObjectList containedObjects();
+
+ void addAssocToConcepts(UMLAssociation* assoc);
+ void removeAssocFromConcepts(UMLAssociation *assoc);
+
+ UMLObject * findObject(const QString &name);
+ UMLObject * findObjectById(Uml::ID::Type id);
+
+ void appendPackages(UMLPackageList& packages, bool includeNested = true);
+ void appendClassifiers(UMLClassifierList& classifiers,
+ bool includeNested = true);
+ void appendClassesAndInterfaces(UMLClassifierList& classifiers,
+ bool includeNested = true);
+ void appendEntities(UMLEntityList& entities,
+ bool includeNested = true);
+
+ virtual bool resolveRef();
+
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ virtual bool load(QDomElement& element);
+
+ /**
+ * References to the objects contained in this package.
+ * The UMLPackage is the owner of the objects.
+ */
+ UMLObjectList m_objects;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/port.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/port.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/port.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/port.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * 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) 2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "port.h"
+
+#include <KLocalizedString>
+
+/**
+ * Sets up a Port.
+ *
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+UMLPort::UMLPort(const QString & name, Uml::ID::Type id)
+ : UMLCanvasObject(name, id)
+{
+ init();
+}
+
+/**
+ * Destructor.
+ */
+UMLPort::~UMLPort()
+{
+}
+
+/**
+ * Initializes key variables of the class.
+ */
+void UMLPort::init()
+{
+ m_BaseType = UMLObject::ot_Port;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLPort::clone() const
+{
+ UMLPort *clone = new UMLPort();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+/**
+ * Creates the <UML:Port> XMI element.
+ */
+void UMLPort::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement portElement = UMLObject::save(QLatin1String("UML:Port"), qDoc);
+ qElement.appendChild(portElement);
+}
+
+/**
+ * Loads the <UML:Port> XMI element (empty.)
+ */
+bool UMLPort::load(QDomElement&)
+{
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/port.h umbrello-kf6-15.08.1/umbrello/umlmodel/port.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/port.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/port.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * 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) 2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef PORT_H
+#define PORT_H
+
+#include "umlcanvasobject.h"
+
+/**
+ * This class contains the non-graphical information required for a UML Port.
+ * This class inherits from @ref UMLCanvasObject which contains most of the
+ * information.
+ *
+ * @short Non-graphical information for a Port.
+ * @author Oliver Kellogg
+ * @see UMLCanvasObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLPort : public UMLCanvasObject
+{
+ Q_OBJECT
+public:
+
+ explicit UMLPort(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLPort();
+
+ virtual void init();
+
+ virtual UMLObject* clone() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+protected:
+
+ bool load(QDomElement & element);
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/stereotype.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/stereotype.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/stereotype.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/stereotype.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,165 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "stereotype.h"
+
+// local includes
+#include "debug_utils.h"
+#include "umldoc.h"
+#include "uml.h"
+
+// kde includes
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+#include <KLocalizedString>
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+
+/**
+ * Sets up a stereotype.
+ *
+ * @param name The name of this UMLStereotype.
+ * @param id The unique id given to this UMLStereotype.
+ */
+UMLStereotype::UMLStereotype(const QString &name, Uml::ID::Type id /* = Uml::id_None */)
+ : UMLObject(name, id)
+{
+ m_BaseType = UMLObject::ot_Stereotype;
+ UMLStereotype * existing = UMLApp::app()->document()->findStereotype(name);
+ if (existing) {
+ uError() << "UMLStereotype constructor: " << name << " already exists";
+ }
+ m_refCount = 0;
+}
+
+/**
+ * Sets up a stereotype.
+ */
+UMLStereotype::UMLStereotype()
+ : UMLObject()
+{
+ m_BaseType = UMLObject::ot_Stereotype;
+ m_refCount = 0;
+}
+
+/**
+ * Destructor.
+ */
+UMLStereotype::~UMLStereotype()
+{
+ //Q_ASSERT(m_refCount == 0);
+}
+
+/**
+ * Overloaded '==' operator.
+ */
+bool UMLStereotype::operator==(const UMLStereotype &rhs) const
+{
+ if (this == &rhs) {
+ return true;
+ }
+
+ if (!UMLObject::operator==(rhs)) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLStereotype::copyInto(UMLObject *lhs) const
+{
+ UMLObject::copyInto(lhs);
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLStereotype::clone() const
+{
+ UMLStereotype *clone = new UMLStereotype();
+ copyInto(clone);
+
+ return clone;
+}
+
+/**
+ * Saves to the <UML:StereoType> XMI element.
+ */
+void UMLStereotype::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ //FIXME: uml13.dtd compliance
+ QDomElement stereotypeElement = UMLObject::save(QLatin1String("UML:Stereotype"), qDoc);
+ qElement.appendChild(stereotypeElement);
+}
+
+/**
+ * Display the properties configuration dialog for the stereotype
+ * (just a line edit).
+ */
+bool UMLStereotype::showPropertiesDialog(QWidget* parent)
+{
+ bool ok;
+#if QT_VERSION >= 0x050000
+ QString stereoTypeName = QInputDialog::getText(parent,
+ i18n("Stereotype"), i18n("Enter name:"),
+ QLineEdit::Normal,
+ name(), &ok);
+#else
+ QString stereoTypeName = KInputDialog::getText(i18n("Stereotype"), i18n("Enter name:"), name(), &ok, parent);
+#endif
+ if (ok) {
+ setName(stereoTypeName);
+ }
+ return ok;
+}
+
+/**
+ * Increments the reference count for this stereotype.
+ */
+void UMLStereotype::incrRefCount()
+{
+ m_refCount++;
+}
+
+/**
+ * Decrements the reference count for this stereotype.
+ */
+void UMLStereotype::decrRefCount()
+{
+ m_refCount--;
+}
+
+/**
+ * Returns the reference count for this stereotype.
+ */
+int UMLStereotype::refCount() const
+{
+ return m_refCount;
+}
+
+/**
+ * Returns the name as string
+ */
+QString UMLStereotype::name(bool includeAdornments) const
+{
+ if (includeAdornments)
+ return QString::fromUtf8("«") + UMLObject::name() + QString::fromUtf8("»");
+ else
+ return UMLObject::name();
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/stereotype.h umbrello-kf6-15.08.1/umbrello/umlmodel/stereotype.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/stereotype.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/stereotype.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef STEREOTYPE_H
+#define STEREOTYPE_H
+
+#include "umlobject.h"
+
+/**
+ * This class is used to set up information for a stereotype.
+ * Stereotypes are used essentially as properties of
+ * attributes and operations etc.
+ *
+ * Each stereotype object is reference counted, i.e. client code
+ * manages it such that it comes into existence as soon as there is
+ * at least one user, and ceases existing when the number of users
+ * drops to 0.
+ * m_refCount reflects the number of users. It is externally managed,
+ * i.e. client code must take care to call incrRefCount() and
+ * decrRefCount() as appropriate.
+ *
+ * The one and only owner of all stereotypes is the UMLDoc, and the
+ * ownership is specially managed (umlPackage() returns NULL for a
+ * UMLStereotype.) The reason for this special treatment is that
+ * class UMLDoc does not inherit from class UMLPackage, and therefore
+ * setUMLPackage() cannot be used for stereotypes.
+ *
+ * @short Sets up stereotype information.
+ * @author Jonathan Riddell
+ * @author Oliver Kellogg
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLStereotype : public UMLObject
+{
+ Q_OBJECT
+public:
+ explicit UMLStereotype(const QString &name, Uml::ID::Type id = Uml::ID::None);
+ UMLStereotype();
+
+ virtual ~UMLStereotype();
+
+ bool operator==(const UMLStereotype &rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ void incrRefCount();
+ void decrRefCount();
+
+ int refCount() const;
+
+ QString name(bool includeAdornments=false) const;
+
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ virtual bool showPropertiesDialog(QWidget* parent);
+
+protected:
+ int m_refCount;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/template.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/template.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/template.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/template.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,146 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "template.h"
+
+// app includes
+#include "debug_utils.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umltemplatedialog.h"
+
+/**
+ * Sets up a template.
+ *
+ * @param parent The parent of this UMLTemplate (i.e. its concept).
+ * @param name The name of this UMLTemplate.
+ * @param id The unique id given to this UMLTemplate.
+ * @param type The type of this UMLTemplate.
+ */
+UMLTemplate::UMLTemplate(UMLObject *parent, const QString& name,
+ Uml::ID::Type id, const QString& type)
+ : UMLClassifierListItem(parent, name, id)
+{
+ setTypeName(type);
+ m_BaseType = UMLObject::ot_Template;
+}
+
+/**
+ * Sets up a template.
+ *
+ * @param parent The parent of this UMLTemplate (i.e. its concept).
+ */
+UMLTemplate::UMLTemplate(UMLObject *parent)
+ : UMLClassifierListItem(parent)
+{
+ m_BaseType = UMLObject::ot_Template;
+}
+
+/**
+ * Destructor.
+ */
+UMLTemplate::~UMLTemplate()
+{
+}
+
+QString UMLTemplate::toString(Uml::SignatureType::Enum sig)
+{
+ Q_UNUSED(sig);
+ if (m_pSecondary == NULL || m_pSecondary->name() == QLatin1String("class")) {
+ return name();
+ } else {
+ return name() + QLatin1String(" : ") + m_pSecondary->name();
+ }
+}
+
+/**
+ * Overrides method from UMLClassifierListItem.
+ * Returns the type name of the UMLTemplate.
+ * If the template parameter is a class, there is no separate
+ * type object. In this case, getTypeName() returns "class".
+ *
+ * @return The type name of the UMLClassifierListItem.
+ */
+QString UMLTemplate::getTypeName() const
+{
+ if (m_pSecondary == NULL)
+ return QLatin1String("class");
+ return m_pSecondary->name();
+}
+
+/**
+ * Overloaded '==' operator.
+ */
+bool UMLTemplate::operator==(const UMLTemplate &rhs) const
+{
+ if (this == &rhs) {
+ return true;
+ }
+ if (!UMLObject::operator==(rhs)) {
+ return false;
+ }
+ if (m_pSecondary != rhs.m_pSecondary) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLTemplate::copyInto(UMLObject *lhs) const
+{
+ UMLClassifierListItem::copyInto(lhs);
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLTemplate::clone() const
+{
+ UMLTemplate *clone = new UMLTemplate((UMLTemplate*) parent());
+ copyInto(clone);
+
+ return clone;
+}
+
+/**
+ * Writes the <UML:TemplateParameter> XMI element.
+ */
+void UMLTemplate::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ //FIXME: uml13.dtd compliance
+ QDomElement attributeElement = UMLObject::save(QLatin1String("UML:TemplateParameter"), qDoc);
+ if (m_pSecondary)
+ attributeElement.setAttribute(QLatin1String("type"), Uml::ID::toString(m_pSecondary->id()));
+ qElement.appendChild(attributeElement);
+}
+
+/**
+ * Loads the <UML:TemplateParameter> XMI element.
+ */
+bool UMLTemplate::load(QDomElement& element)
+{
+ m_SecondaryId = element.attribute(QLatin1String("type"));
+ return true;
+}
+
+/**
+ * Display the properties configuration dialog for the template.
+ *
+ * @return Success status.
+ */
+bool UMLTemplate::showPropertiesDialog(QWidget* parent)
+{
+ UMLTemplateDialog dialog(parent, this);
+ return dialog.exec();
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/template.h umbrello-kf6-15.08.1/umbrello/umlmodel/template.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/template.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/template.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef TEMPLATE_H
+#define TEMPLATE_H
+
+#include "classifierlistitem.h"
+
+/**
+ * This class holds information used by template classes, called
+ * paramaterised class in UML and a generic in Java. It has a
+ * type (usually just "class") and name.
+ *
+ * @short Sets up template information.
+ * @author Jonathan Riddell
+ * @see UMLObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLTemplate : public UMLClassifierListItem
+{
+public:
+
+ UMLTemplate(UMLObject *parent, const QString& name,
+ Uml::ID::Type id = Uml::ID::None, const QString& type = QLatin1String("class"));
+
+ explicit UMLTemplate(UMLObject *parent);
+
+ bool operator==(const UMLTemplate &rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ virtual ~UMLTemplate();
+
+ QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
+
+ virtual QString getTypeName() const;
+
+ virtual bool showPropertiesDialog(QWidget* parent);
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+protected:
+
+ bool load(QDomElement & element);
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlassociationlist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlassociationlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlassociationlist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlassociationlist.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,23 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLASSOCIATIONLIST_H
+#define UMLASSOCIATIONLIST_H
+
+#include <qlist.h>
+
+// forward declaration
+class UMLAssociation;
+
+typedef QList<UMLAssociation*> UMLAssociationList;
+typedef QListIterator<UMLAssociation*> UMLAssociationListIt;
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlattributelist.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/umlattributelist.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlattributelist.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlattributelist.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "umlattributelist.h"
+
+#include "attribute.h"
+
+#include <KLocalizedString>
+
+UMLAttributeList::UMLAttributeList()
+{
+}
+
+UMLAttributeList::UMLAttributeList(const UMLAttributeList& other)
+ : QList<UMLAttribute*>(other)
+{
+}
+
+UMLAttributeList::~UMLAttributeList()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLAttributeList::copyInto(UMLAttributeList *rhs) const
+{
+ // Don't copy yourself.
+ if (rhs == this) return;
+
+ rhs->clear();
+
+ // Suffering from const; we shall not modify our object.
+ UMLAttributeList *tmp = new UMLAttributeList(*this);
+
+ UMLAttribute *item;
+ for (UMLAttributeListIt ait(*tmp); ait.hasNext() ;)
+ {
+ item = ait.next();
+ rhs->append((UMLAttribute*)item->clone());
+ }
+ delete tmp;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLAttributeList* UMLAttributeList::clone() const
+{
+ UMLAttributeList *clone = new UMLAttributeList();
+ copyInto(clone);
+ return clone;
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlattributelist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlattributelist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlattributelist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlattributelist.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * *
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLATTRIBUTELIST_H
+#define UMLATTRIBUTELIST_H
+
+#include <QList>
+
+#include "attribute.h"
+
+//typedef QPtrList<UMLAttribute> UMLAttributeList;
+typedef QListIterator<UMLAttribute*> UMLAttributeListIt;
+
+/**
+ * This sub-class adds copyInto and clone to the QPtrList<UMLAttribute>
+ * base class.
+ */
+class UMLAttributeList : public QList<UMLAttribute*>
+{
+public:
+
+ UMLAttributeList();
+
+ UMLAttributeList(const UMLAttributeList&);
+
+ virtual ~UMLAttributeList();
+
+ virtual void copyInto(UMLAttributeList *rhs) const;
+
+ virtual UMLAttributeList* clone() const;
+};
+
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlcanvasobject.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/umlcanvasobject.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlcanvasobject.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlcanvasobject.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,464 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "umlcanvasobject.h"
+
+// local includes
+#include "debug_utils.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "classifier.h"
+#include "association.h"
+#include "attribute.h"
+#include "operation.h"
+#include "template.h"
+#include "stereotype.h"
+#include "idchangelog.h"
+
+// kde includes
+#include <KLocalizedString>
+
+DEBUG_REGISTER_DISABLED(UMLCanvasObject)
+
+/**
+ * Sets up a UMLCanvasObject.
+ *
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+UMLCanvasObject::UMLCanvasObject(const QString & name, Uml::ID::Type id)
+ : UMLObject(name, id)
+{
+}
+
+/**
+ * Standard deconstructor.
+ */
+UMLCanvasObject::~UMLCanvasObject()
+{
+ //removeAllAssociations();
+ // No! This is way too late to do that.
+ // It should have been called explicitly before destructing the
+ // UMLCanvasObject.
+ if (associations())
+ DEBUG(DBG_SRC) << "UMLCanvasObject destructor: FIXME: there are still associations()";
+}
+
+/**
+ * Return the subset of m_List that matches the given type.
+ *
+ * @param assocType The AssociationType::Enum to match.
+ * @return The list of associations that match assocType.
+ */
+UMLAssociationList UMLCanvasObject::getSpecificAssocs(Uml::AssociationType::Enum assocType)
+{
+ UMLAssociationList list;
+ UMLObject *o = NULL;
+ for (UMLObjectListIt oit(m_List); oit.hasNext();) {
+ o = oit.next();
+ uIgnoreZeroPointer(o);
+ if (o->baseType() != UMLObject::ot_Association)
+ continue;
+ UMLAssociation *a = static_cast<UMLAssociation*>(o);
+ if (a->getAssocType() == assocType)
+ list.append(a);
+ }
+ return list;
+}
+
+/**
+ * Adds an association end to m_List.
+ *
+ * @param assoc The association to add.
+ * @todo change param type to UMLRole
+ */
+bool UMLCanvasObject::addAssociationEnd(UMLAssociation* assoc)
+{
+ Q_ASSERT(assoc);
+ // add association only if not already present in list
+ if (!hasAssociation(assoc))
+ {
+ m_List.append(assoc);
+
+ // Don't emit signals during load from XMI
+ UMLObject::emitModified();
+ emit sigAssociationEndAdded(assoc);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Determine if this canvasobject has the given association.
+ *
+ * @param assoc The association to check.
+ */
+bool UMLCanvasObject::hasAssociation(UMLAssociation* assoc)
+{
+ uint cnt = m_List.count(assoc);
+ DEBUG(DBG_SRC) << "count is " << cnt;
+ return (cnt > 0);
+}
+
+/**
+ * Remove an association end from the CanvasObject.
+ *
+ * @param assoc The association to remove.
+ * @todo change param type to UMLRole
+ */
+int UMLCanvasObject::removeAssociationEnd(UMLAssociation * assoc)
+{
+ if (!hasAssociation(assoc) || !m_List.removeAll(assoc)) {
+ DEBUG(DBG_SRC) << "cannot find given assoc " << assoc << " in list";
+ return -1;
+ }
+ UMLApp::app()->document()->removeAssociation(assoc, false);
+ UMLObject::emitModified();
+ emit sigAssociationEndRemoved(assoc);
+ return m_List.count();
+}
+
+/**
+ * Remove all association ends from the CanvasObject.
+ */
+void UMLCanvasObject::removeAllAssociationEnds()
+{
+ for (int i = 0; i < m_List.count(); i++) {
+ UMLObject *o = m_List.at(i);
+ uIgnoreZeroPointer(o);
+ if (o->baseType() != UMLObject::ot_Association) {
+ continue;
+ }
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
+ //umldoc->slotRemoveUMLObject(assoc);
+ UMLObject* objA = assoc->getObject(Uml::RoleType::A);
+ UMLObject* objB = assoc->getObject(Uml::RoleType::B);
+ UMLCanvasObject *roleAObj = dynamic_cast<UMLCanvasObject*>(objA);
+ if (roleAObj) {
+ roleAObj->removeAssociationEnd(assoc);
+ } else if (objA) {
+ DEBUG(DBG_SRC) << name() << ": objA " << objA->name() << " is not a UMLCanvasObject";
+ } else
+ DEBUG(DBG_SRC) << name() << "): objA is NULL";
+ UMLCanvasObject *roleBObj = dynamic_cast<UMLCanvasObject*>(objB);
+ if (roleBObj) {
+ roleBObj->removeAssociationEnd(assoc);
+ } else if (objB) {
+ DEBUG(DBG_SRC) << name() << "): objB " << objB->name() << " is not a UMLCanvasObject";
+ } else
+ DEBUG(DBG_SRC) << name() << "): objB is NULL";
+ }
+}
+
+/**
+ * Remove all child objects.
+ * Just clear list, objects must be deleted where they were created
+ * (or we have bad crashes).
+ */
+void UMLCanvasObject::removeAllChildObjects()
+{
+ if (!m_List.isEmpty()) {
+ removeAllAssociationEnds();
+ m_List.clear();
+ }
+}
+
+/**
+ * Returns a name for the new association, operation, template
+ * or attribute appended with a number if the default name is
+ * taken e.g. new_association, new_association_1 etc.
+ *
+ * @param type The object type for which to make a name.
+ * @param prefix Optional prefix to use for the name.
+ * If not given then uniqChildName() will choose the prefix
+ * internally based on the object type.
+ * @return Unique name string for the ObjectType given.
+ */
+QString UMLCanvasObject::uniqChildName(const UMLObject::ObjectType type,
+ const QString &prefix /* = QString() */)
+{
+ QString currentName;
+ currentName = prefix;
+ if (currentName.isEmpty()) {
+ switch (type) {
+ case UMLObject::ot_Association:
+ currentName = i18n("new_association");
+ break;
+ case UMLObject::ot_Attribute:
+ currentName = i18n("new_attribute");
+ break;
+ case UMLObject::ot_Template:
+ currentName = i18n("new_template");
+ break;
+ case UMLObject::ot_Operation:
+ currentName = i18n("new_operation");
+ break;
+ case UMLObject::ot_EnumLiteral:
+ currentName = i18n("new_literal");
+ break;
+ case UMLObject::ot_EntityAttribute:
+ currentName = i18n("new_field");
+ break;
+ case UMLObject::ot_UniqueConstraint:
+ currentName = i18n("new_unique_constraint");
+ break;
+ case UMLObject::ot_ForeignKeyConstraint:
+ currentName = i18n("new_fkey_constraint");
+ break;
+ case UMLObject::ot_CheckConstraint:
+ currentName = i18n("new_check_constraint");
+ break;
+ default:
+ uWarning() << "uniqChildName() called for unknown child type " << UMLObject::toString(type);
+ return QLatin1String("ERROR_in_UMLCanvasObject_uniqChildName");
+ }
+ }
+
+ QString name = currentName;
+ for (int number = 1; findChildObject(name); ++number) {
+ name = currentName + QLatin1Char('_') + QString::number(number);
+ }
+ return name;
+}
+
+/**
+ * Find a child object with the given name.
+ *
+ * @param n The name of the object to find.
+ * @param t The type to find (optional.) If not given then
+ * any object type will match.
+ * @return Pointer to the object found; NULL if none found.
+ */
+UMLObject * UMLCanvasObject::findChildObject(const QString &n, UMLObject::ObjectType t)
+{
+ const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
+ UMLObject *obj = NULL;
+ for (UMLObjectListIt oit(m_List); oit.hasNext();) {
+ obj = oit.next();
+ uIgnoreZeroPointer(obj);
+ if (t != UMLObject::ot_UMLObject && obj->baseType() != t)
+ continue;
+ if (caseSensitive) {
+ if (obj->name() == n)
+ return obj;
+ } else if (obj->name().toLower() == n.toLower()) {
+ return obj;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Find an association.
+ *
+ * @param id The id of the object to find.
+ * @param considerAncestors boolean switch to consider ancestors while searching
+ * @return Pointer to the object found (NULL if not found.)
+ */
+UMLObject* UMLCanvasObject::findChildObjectById(Uml::ID::Type id, bool considerAncestors)
+{
+ Q_UNUSED(considerAncestors);
+ UMLObject *o = NULL;
+ for (UMLObjectListIt oit(m_List); oit.hasNext();) {
+ o = oit.next();
+ uIgnoreZeroPointer(o);
+ if (o->id() == id)
+ return o;
+ }
+ return 0;
+}
+
+/**
+ * Overloaded '==' operator
+ */
+bool UMLCanvasObject::operator==(const UMLCanvasObject& rhs) const
+{
+ if (this == &rhs) {
+ return true;
+ }
+ if (!UMLObject::operator==(rhs)) {
+ return false;
+ }
+ if (m_List.count() != rhs.m_List.count()) {
+ return false;
+ }
+ if (&m_List != &(rhs.m_List)) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLCanvasObject::copyInto(UMLObject *lhs) const
+{
+ UMLObject::copyInto(lhs);
+
+ // TODO Associations are not copied at the moment. This because
+ // the duplicate function (on umlwidgets) do not copy the associations.
+ //
+ //target->m_List = m_List;
+}
+
+/**
+ * Returns the number of associations for the CanvasObject.
+ * This is the sum of the aggregations and compositions.
+ *
+ * @return The number of associations for the Concept.
+ */
+int UMLCanvasObject::associations()
+{
+ int count = 0;
+ UMLObject *obj = NULL;
+ for (UMLObjectListIt oit(m_List); oit.hasNext();) {
+ obj = oit.next();
+ uIgnoreZeroPointer(obj);
+ if (obj->baseType() == UMLObject::ot_Association)
+ count++;
+ }
+ return count;
+}
+
+/**
+ * Return the list of associations for the CanvasObject.
+ *
+ * @return The list of associations for the CanvasObject.
+ */
+UMLAssociationList UMLCanvasObject::getAssociations()
+{
+ UMLAssociationList assocs;
+ UMLObject *o = NULL;
+ for (UMLObjectListIt oit(m_List); oit.hasNext() ;) {
+ o = oit.next();
+ uIgnoreZeroPointer(o);
+ if (o->baseType() != UMLObject::ot_Association)
+ continue;
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
+ assocs.append(assoc);
+ }
+ return assocs;
+}
+
+/**
+ * Return a list of the superclasses of this concept.
+ * TODO: This overlaps with UMLClassifier::findSuperClassConcepts(),
+ * see if we can merge the two.
+ *
+ * @param withRealizations include realizations in the returned list (default=yes)
+ * @return The list of superclasses for the concept.
+ */
+UMLClassifierList UMLCanvasObject::getSuperClasses(bool withRealizations)
+{
+ UMLClassifierList list;
+ UMLAssociationList assocs = getAssociations();
+ foreach (UMLAssociation* a, assocs) {
+ uIgnoreZeroPointer(a);
+ if ((a->getAssocType() != Uml::AssociationType::Generalization &&
+ a->getAssocType() != Uml::AssociationType::Realization) ||
+ (!withRealizations && a->getAssocType() == Uml::AssociationType::Realization) ||
+ a->getObjectId(Uml::RoleType::A) != id())
+ continue;
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::RoleType::B));
+ if (c)
+ list.append(c);
+ else
+ DEBUG(DBG_SRC) << name() << ": generalization's other end is not a "
+ << "UMLClassifier (id= " << Uml::ID::toString(a->getObjectId(Uml::RoleType::B)) << ")";
+ }
+ return list;
+}
+
+/**
+ * Return a list of the classes that inherit from this concept.
+ * TODO: This overlaps with UMLClassifier::findSubClassConcepts(),
+ * see if we can merge the two.
+ *
+ * @return The list of classes inheriting from the concept.
+ */
+UMLClassifierList UMLCanvasObject::getSubClasses()
+{
+ UMLClassifierList list;
+ UMLAssociationList assocs = getAssociations();
+ foreach (UMLAssociation* a, assocs) {
+ uIgnoreZeroPointer(a);
+ if ((a->getAssocType() != Uml::AssociationType::Generalization &&
+ a->getAssocType() != Uml::AssociationType::Realization) ||
+ a->getObjectId(Uml::RoleType::B) != id())
+ continue;
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::RoleType::A));
+ if (c)
+ list.append(c);
+ else
+ DEBUG(DBG_SRC) << "specialization's other end is not a UMLClassifier"
+ << " (id=" << Uml::ID::toString(a->getObjectId(Uml::RoleType::A)) << ")";
+ }
+ return list;
+}
+
+/**
+ * Shorthand for getSpecificAssocs(Uml::at_Realization)
+ *
+ * @return The list of realizations for the Concept.
+ */
+UMLAssociationList UMLCanvasObject::getRealizations()
+{
+ return getSpecificAssocs(Uml::AssociationType::Realization);
+}
+
+/**
+ * Shorthand for getSpecificAssocs(Uml::at_Aggregation)
+ *
+ * @return The list of aggregations for the Concept.
+ */
+UMLAssociationList UMLCanvasObject::getAggregations()
+{
+ return getSpecificAssocs(Uml::AssociationType::Aggregation);
+}
+
+/**
+ * Shorthand for getSpecificAssocs(Uml::at_Composition)
+ *
+ * @return The list of compositions for the Concept.
+ */
+UMLAssociationList UMLCanvasObject::getCompositions()
+{
+ return getSpecificAssocs(Uml::AssociationType::Composition);
+}
+
+/**
+ * Shorthand for getSpecificAssocs(Uml::at_Relationship)
+ *
+ * @return The list of relationships for the entity.
+ */
+UMLAssociationList UMLCanvasObject::getRelationships()
+{
+ return getSpecificAssocs(Uml::AssociationType::Relationship);
+}
+
+/**
+ * Reimplementation of UMLObject method.
+ */
+bool UMLCanvasObject::resolveRef()
+{
+ bool overallSuccess = UMLObject::resolveRef();
+ for (UMLObjectListIt ait(m_List); ait.hasNext();) {
+ UMLObject *obj = ait.next();
+ uIgnoreZeroPointer(obj);
+ if (! obj->resolveRef()) {
+ m_List.removeAll(obj);
+ overallSuccess = false;
+ }
+ }
+ return overallSuccess;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlcanvasobject.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlcanvasobject.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlcanvasobject.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlcanvasobject.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,108 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef CANVASOBJECT_H
+#define CANVASOBJECT_H
+
+#include "umlobject.h"
+#include "umlobjectlist.h"
+#include "umlclassifierlist.h"
+#include "umlassociationlist.h"
+
+/**
+ * This class contains the non-graphical information required for UMLObjects
+ * which appear as moveable widgets on the scene.
+ *
+ * This class inherits from @ref UMLObject which contains most of the
+ * information.
+ * It is not instantiated itself, it's just used as a super class for
+ * actual model objects.
+ *
+ * @short Non-graphical information for a UMLCanvasObject.
+ * @author Jonathan Riddell
+ * @see UMLObject
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLCanvasObject : public UMLObject
+{
+ Q_OBJECT
+
+public:
+ explicit UMLCanvasObject(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLCanvasObject();
+
+ bool operator==(const UMLCanvasObject& rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ // The abstract method UMLObject::clone() is implemented
+ // in the classes inheriting from UMLCanvasObject.
+
+ bool addAssociationEnd(UMLAssociation* assoc);
+
+ bool hasAssociation(UMLAssociation* assoc);
+
+ int removeAssociationEnd(UMLAssociation *assoc);
+
+ void removeAllAssociationEnds();
+
+ int associations();
+
+ UMLAssociationList getAssociations();
+
+ UMLAssociationList getSpecificAssocs(Uml::AssociationType::Enum assocType);
+
+ UMLClassifierList getSuperClasses(bool withRealizations = true);
+ UMLClassifierList getSubClasses();
+
+ virtual UMLAssociationList getRealizations();
+
+ UMLAssociationList getAggregations();
+ UMLAssociationList getCompositions();
+ UMLAssociationList getRelationships();
+
+ virtual UMLObject *findChildObject(const QString &n,
+ UMLObject::ObjectType t = UMLObject::ot_UMLObject);
+ virtual UMLObject *findChildObjectById(Uml::ID::Type id, bool considerAncestors = false);
+
+ virtual QString uniqChildName(const UMLObject::ObjectType type,
+ const QString &prefix = QString());
+
+ virtual void removeAllChildObjects();
+
+ UMLObjectList subordinates() const {
+ return m_List;
+ }
+
+ virtual bool resolveRef();
+
+ // The abstract method UMLObject::saveToXMI() is implemented
+ // in the classes inheriting from UMLCanvasObject.
+
+protected:
+
+ /**
+ * List of all the associations in this object.
+ * Inheriting classes add more types of objects that are possible in this list;
+ * for example, UMLClassifier adds operations, attributes, and templates.
+ *
+ * @todo Only a pointer to the appropriate assocation end object
+ * (UMLRole) should be saved here, not the entire UMLAssociation.
+ */
+ UMLObjectList m_List;
+
+signals:
+
+ void sigAssociationEndAdded(UMLAssociation * assoc);
+ void sigAssociationEndRemoved(UMLAssociation * assoc);
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlclassifierlist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlclassifierlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlclassifierlist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlclassifierlist.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * 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) 2003-2010 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLCLASSIFIERLIST_H
+#define UMLCLASSIFIERLIST_H
+
+#include <QList>
+
+// forward declaration
+class UMLClassifier;
+
+typedef QList<UMLClassifier*> UMLClassifierList;
+typedef QListIterator<UMLClassifier*> UMLClassifierListIt;
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlclassifierlistitemlist.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/umlclassifierlistitemlist.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlclassifierlistitemlist.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlclassifierlistitemlist.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "umlclassifierlistitemlist.h"
+
+#include "classifierlistitem.h"
+
+#include <KLocalizedString>
+
+UMLClassifierListItemList::UMLClassifierListItemList()
+{
+}
+
+UMLClassifierListItemList::UMLClassifierListItemList(const UMLClassifierListItemList& other)
+ : QList<UMLClassifierListItem*>(other)
+{
+}
+
+UMLClassifierListItemList::~UMLClassifierListItemList()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLClassifierListItemList::copyInto(UMLClassifierListItemList *rhs) const
+{
+ // Prevent copying to yourself. (Can cause serious injuries)
+ if (rhs == this) return;
+
+ rhs->clear();
+
+ // Suffering from const; we shall not modify our object.
+ UMLClassifierListItemList *tmp = new UMLClassifierListItemList(*this);
+
+ UMLClassifierListItem *item;
+ for (UMLClassifierListItemListIt clit(*tmp); clit.hasNext() ;) {
+ item = clit.next();
+ rhs->append((UMLClassifierListItem*)item->clone());
+ }
+ delete tmp;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLClassifierListItemList* UMLClassifierListItemList::clone() const
+{
+ UMLClassifierListItemList *clone = new UMLClassifierListItemList();
+ copyInto(clone);
+ return clone;
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlclassifierlistitemlist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlclassifierlistitemlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlclassifierlistitemlist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlclassifierlistitemlist.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,41 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLCLASSIFIERLISTITEMLIST_H
+#define UMLCLASSIFIERLISTITEMLIST_H
+
+#include <QList>
+
+// forward declaration
+class UMLClassifierListItem;
+
+//typedef QPtrList<UMLClassifierListItem> UMLClassifierListItemList;
+typedef QListIterator<UMLClassifierListItem*> UMLClassifierListItemListIt;
+
+/**
+ * This sub-class adds copyInto and clone to the QPtrList<UMLClassifierListItem>
+ * base class.
+ */
+class UMLClassifierListItemList : public QList<UMLClassifierListItem*>
+{
+public:
+
+ UMLClassifierListItemList();
+ UMLClassifierListItemList(const UMLClassifierListItemList& other);
+
+ virtual ~UMLClassifierListItemList();
+
+ virtual void copyInto (UMLClassifierListItemList *rhs) const;
+
+ virtual UMLClassifierListItemList* clone() const;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlentityattributelist.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/umlentityattributelist.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlentityattributelist.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlentityattributelist.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "umlentityattributelist.h"
+
+#include "entityattribute.h"
+
+#include <KLocalizedString>
+
+UMLEntityAttributeList::UMLEntityAttributeList()
+{
+}
+
+UMLEntityAttributeList::UMLEntityAttributeList(const UMLEntityAttributeList& other)
+ : QList<UMLEntityAttribute*>(other)
+{
+}
+
+UMLEntityAttributeList::~UMLEntityAttributeList()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLEntityAttributeList::copyInto(UMLEntityAttributeList* rhs) const
+{
+ // Don't copy yourself.
+ if (rhs == this) return;
+
+ rhs->clear();
+
+ // Suffering from const; we shall not modify our object.
+ UMLEntityAttributeList* tmp = new UMLEntityAttributeList(*this);
+
+ UMLEntityAttribute* item;
+ for (UMLEntityAttributeListIt eait(*tmp); eait.hasNext() ;) {
+ item = eait.next();
+ rhs->append((UMLEntityAttribute*)item->clone());
+ }
+ delete tmp;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLEntityAttributeList* UMLEntityAttributeList::clone() const
+{
+ UMLEntityAttributeList *clone = new UMLEntityAttributeList();
+ copyInto(clone);
+ return clone;
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlentityattributelist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlentityattributelist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlentityattributelist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlentityattributelist.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,41 @@
+/***************************************************************************
+ * *
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLENTITYATTRIBUTELIST_H
+#define UMLENTITYATTRIBUTELIST_H
+
+#include <qlist.h>
+#include "entityattribute.h"
+
+//typedef QPtrList<UMLEntityAttribute> UMLEntityAttributeList;
+typedef QListIterator<UMLEntityAttribute*> UMLEntityAttributeListIt;
+
+/**
+ * This sub-class adds copyInto and clone to the QPtrList<UMLEntityAttribute>
+ * base class.
+ */
+class UMLEntityAttributeList : public QList<UMLEntityAttribute*>
+{
+public:
+
+ UMLEntityAttributeList();
+
+ UMLEntityAttributeList(const UMLEntityAttributeList&);
+
+ virtual ~UMLEntityAttributeList();
+
+ virtual void copyInto (UMLEntityAttributeList* rhs) const;
+
+ virtual UMLEntityAttributeList* clone() const;
+};
+
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlentityconstraintlist.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/umlentityconstraintlist.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlentityconstraintlist.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlentityconstraintlist.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "umlentityconstraintlist.h"
+
+#include "entityconstraint.h"
+
+#include <KLocalizedString>
+
+UMLEntityConstraintList::UMLEntityConstraintList()
+{
+}
+
+UMLEntityConstraintList::UMLEntityConstraintList(const UMLEntityConstraintList& other)
+ : QList<UMLEntityConstraint*>(other)
+{
+}
+
+UMLEntityConstraintList::~UMLEntityConstraintList()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLEntityConstraintList::copyInto(UMLEntityConstraintList* rhs) const
+{
+ // Don't copy yourself.
+ if (rhs == this) return;
+
+ rhs->clear();
+
+ // Suffering from const; we shall not modify our object.
+ UMLEntityConstraintList* tmp = new UMLEntityConstraintList(*this);
+
+ UMLEntityConstraint* item;
+ for (UMLEntityConstraintListIt ecit(*tmp); ecit.hasNext() ;) {
+ item = ecit.next();
+ rhs->append((UMLEntityConstraint*)item->clone());
+ }
+ delete tmp;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLEntityConstraintList* UMLEntityConstraintList::clone() const
+{
+ UMLEntityConstraintList *clone = new UMLEntityConstraintList();
+ copyInto(clone);
+ return clone;
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlentityconstraintlist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlentityconstraintlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlentityconstraintlist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlentityconstraintlist.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * *
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLENTITYCONSTRAINTLIST_H
+#define UMLENTITYCONSTRAINTLIST_H
+
+#include <qlist.h>
+
+// forward declaration
+class UMLEntityConstraint;
+
+
+typedef QListIterator<UMLEntityConstraint*> UMLEntityConstraintListIt;
+
+/**
+ * This sub-class adds copyInto and clone to the QPtrList<UMLEntityConstraint>
+ * base class.
+ */
+class UMLEntityConstraintList : public QList<UMLEntityConstraint*>
+{
+public:
+
+ UMLEntityConstraintList();
+
+ UMLEntityConstraintList(const UMLEntityConstraintList&);
+
+ virtual ~UMLEntityConstraintList();
+
+ virtual void copyInto (UMLEntityConstraintList* rhs) const;
+
+ virtual UMLEntityConstraintList* clone() const;
+};
+
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlentitylist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlentitylist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlentitylist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlentitylist.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * 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) 2003-2010 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLENTITYLIST_H
+#define UMLENTITYLIST_H
+
+#include <QList>
+
+// forward declaration
+class UMLEntity;
+
+typedef QList<UMLEntity*> UMLEntityList;
+typedef QListIterator<UMLEntity*> UMLEntityListIt;
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlenumliterallist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlenumliterallist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlenumliterallist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlenumliterallist.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,23 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLENUMLITERALLIST_H
+#define UMLENUMLITERALLIST_H
+
+#include <QList>
+
+// forward declaration
+class UMLEnumLiteral;
+
+typedef QList<UMLEnumLiteral*> UMLEnumLiteralList;
+typedef QListIterator<UMLEnumLiteral*> UMLEnumLiteralListIt;
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlobject.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/umlobject.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlobject.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlobject.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,1157 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "umlobject.h"
+
+// app includes
+#include "classpropertiesdialog.h"
+#include "debug_utils.h"
+#include "enumliteral.h"
+#include "uniqueid.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umllistview.h"
+#include "package.h"
+#include "folder.h"
+#include "stereotype.h"
+#include "object_factory.h"
+#include "model_utils.h"
+#include "import_utils.h"
+#include "docwindow.h"
+#include "cmds.h"
+
+// kde includes
+#include <KLocalizedString>
+
+// qt includes
+#include <QApplication>
+#include <QPointer>
+
+using namespace Uml;
+
+DEBUG_REGISTER_DISABLED(UMLObject)
+
+/**
+ * Creates a UMLObject.
+ * @param other object to created from
+ */
+UMLObject::UMLObject(const UMLObject &other)
+ : QObject(other.parent())
+{
+ other.copyInto(this);
+}
+
+/**
+ * Creates a UMLObject.
+ * @param parent The parent of the object.
+ * @param name The name of the object.
+ * @param id The ID of the object (optional.) If omitted
+ * then a new ID will be assigned internally.
+ */
+UMLObject::UMLObject(UMLObject* parent, const QString& name, ID::Type id)
+ : QObject(parent),
+ m_nId(id),
+ m_name(name)
+{
+ init();
+ if (id == Uml::ID::None)
+ m_nId = UniqueID::gen();
+}
+
+/**
+ * Creates a UMLObject.
+ * @param name The name of the object.
+ * @param id The ID of the object (optional.) If omitted
+ * then a new ID will be assigned internally.
+ */
+UMLObject::UMLObject(const QString& name, ID::Type id)
+ : QObject(UMLApp::app()->document()),
+ m_nId(id),
+ m_name(name)
+{
+ init();
+ if (id == Uml::ID::None)
+ m_nId = UniqueID::gen();
+}
+
+/**
+ * Creates a UMLObject.
+ * @param parent The parent of the object.
+ */
+UMLObject::UMLObject(UMLObject * parent)
+ : QObject(parent),
+ m_nId(Uml::ID::None),
+ m_name(QString())
+{
+ init();
+}
+
+/**
+ * Standard destructor.
+ */
+UMLObject::~UMLObject()
+{
+ // unref stereotype
+ setUMLStereotype(0);
+ if (m_pSecondary && m_pSecondary->baseType() == ot_Stereotype) {
+ UMLStereotype* stereotype = dynamic_cast<UMLStereotype*>(m_pSecondary.data());
+ if (stereotype)
+ stereotype->decrRefCount();
+ }
+}
+
+/**
+ * Initializes key variables of the class.
+ */
+void UMLObject::init()
+{
+ setObjectName(QLatin1String("UMLObject"));
+ m_BaseType = ot_UMLObject;
+ m_pUMLPackage = 0;
+ m_visibility = Uml::Visibility::Public;
+ m_pStereotype = 0;
+ m_Doc.clear();
+ m_bAbstract = false;
+ m_bStatic = false;
+ m_bCreationWasSignalled = false;
+ m_pSecondary = 0;
+}
+
+/**
+ * Display the properties configuration dialog for the object.
+ *
+ * @param parent The parent widget.
+ * @return True for success of this operation.
+ */
+bool UMLObject::showPropertiesDialog(QWidget *parent)
+{
+ DocWindow *docwindow = UMLApp::app()->docWindow();
+ docwindow->updateDocumentation(false);
+ QPointer<ClassPropertiesDialog> dlg = new ClassPropertiesDialog(parent, this, false);
+ bool modified = false;
+ if (dlg->exec()) {
+ docwindow->showDocumentation(this, true);
+ UMLApp::app()->document()->setModified(true);
+ modified = true;
+ }
+ dlg->close();
+ delete dlg;
+ return modified;
+}
+
+/**
+ * This should be reimplemented by subclasses if they wish to
+ * accept certain types of associations. Note that this only
+ * tells if this UMLObject can accept the association
+ * type. When creating an association another check is made to
+ * see if the association is valid. For example a UMLClass
+ * (UMLClassifier) can accept generalizations and should
+ * return true. If while creating a generalization the
+ * superclass is already subclassed from this, the association
+ * is not valid and will not be created. The default accepts
+ * nothing (returns false)
+ */
+bool UMLObject::acceptAssociationType(Uml::AssociationType::Enum type)
+{
+ Q_UNUSED(type);
+ // A UMLObject accepts nothing. This should be reimplemented by the subclasses
+ return false;
+}
+
+/**
+ * Assigns a new Id to the object
+ */
+void UMLObject::setID(ID::Type NewID)
+{
+ m_nId = NewID;
+ emitModified();
+}
+
+/**
+ * Set the UMLObject's name
+ */
+void UMLObject::setName(const QString &strName)
+{
+ if (name() != strName) {
+ UMLApp::app()->executeCommand(new Uml::CmdRenameUMLObject(this, strName));
+ }
+}
+
+/**
+ * Method used by setName: it is called by cmdSetName, Don't use it!
+ */
+void UMLObject::setNameCmd(const QString &strName)
+{
+ m_name = strName;
+ emitModified();
+}
+
+/**
+ * Returns a copy of m_name
+ */
+QString UMLObject::name() const
+{
+ return m_name;
+}
+
+/**
+ * Returns the fully qualified name, i.e. all package prefixes and then m_name.
+ *
+ * @param separator The separator string to use (optional.)
+ * If not given then the separator is chosen according
+ * to the currently selected active programming language
+ * of import and code generation.
+ * @param includeRoot Whether to prefix the root folder name to the FQN.
+ * See UMLDoc::getRootFolder(). Default: false.
+ * @return The fully qualified name of this UMLObject.
+ */
+QString UMLObject::fullyQualifiedName(const QString& separator,
+ bool includeRoot /* = false */) const
+{
+ QString fqn;
+ if (m_pUMLPackage && m_pUMLPackage != this) {
+ bool skipPackage = false;
+ if (!includeRoot) {
+ UMLDoc *umldoc = UMLApp::app()->document();
+ if (umldoc->rootFolderType(m_pUMLPackage) != Uml::ModelType::N_MODELTYPES ||
+ m_pUMLPackage == umldoc->datatypeFolder())
+ skipPackage = true;
+ }
+ if (!skipPackage) {
+ QString tempSeparator = separator;
+ if (tempSeparator.isEmpty())
+ tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
+ fqn = m_pUMLPackage->fullyQualifiedName(tempSeparator, includeRoot);
+ fqn.append(tempSeparator);
+ }
+ }
+ fqn.append(m_name);
+ return fqn;
+}
+
+/**
+ * Overloaded '==' operator
+ */
+bool UMLObject::operator==(const UMLObject & rhs) const
+{
+ if (this == &rhs)
+ return true;
+
+ //don't compare IDs, these are program specific and
+ //don't mean the objects are the same
+ //***** CHECK: Who put in this comment? What was the reason?
+ //***** Currently some operator== in umbrello-kf6 compare the IDs
+ //***** while others don't.
+
+ if (m_name != rhs.m_name)
+ return false;
+
+ // Packages create different namespaces, therefore they should be
+ // part of the equality test.
+ if (m_pUMLPackage != rhs.m_pUMLPackage)
+ return false;
+
+ // Making the type part of an object's identity has its problems:
+ // Not all programming languages support declarations of the same
+ // name but different type.
+ // In such cases, the code generator is responsible for generating
+ // the appropriate error message.
+ if (m_BaseType != rhs.m_BaseType)
+ return false;
+
+ // The documentation should not be part of the equality test.
+ // If two objects are the same but differ only in their documentation,
+ // what does that mean?
+ //if(m_Doc != rhs.m_Doc)
+ // return false;
+
+ // The visibility should not be part of the equality test.
+ // What does it mean if two objects are the same but differ in their
+ // visibility? - I'm not aware of any programming language that would
+ // support that.
+ //if(m_visibility != rhs.m_visibility)
+ // return false;
+
+ // See comments above
+ //if(m_pStereotype != rhs.m_pStereotype)
+ // return false;
+
+ // See comments above
+ //if(m_bAbstract != rhs.m_bAbstract)
+ // return false;
+
+ // See comments above
+ //if(m_bStatic != rhs.m_bStatic)
+ // return false;
+
+ return true;
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLObject::copyInto(UMLObject *lhs) const
+{
+ // Data members with copy constructor
+ lhs->m_Doc = m_Doc;
+ lhs->m_pStereotype = m_pStereotype;
+ if (lhs->m_pStereotype)
+ lhs->m_pStereotype->incrRefCount();
+ lhs->m_bAbstract = m_bAbstract;
+ lhs->m_bStatic = m_bStatic;
+ lhs->m_BaseType = m_BaseType;
+ lhs->m_visibility = m_visibility;
+ lhs->m_pUMLPackage = m_pUMLPackage;
+
+ // We don't want the same name existing twice.
+ lhs->m_name = Model_Utils::uniqObjectName(m_BaseType, m_pUMLPackage, m_name);
+
+ // Create a new ID.
+ lhs->m_nId = UniqueID::gen();
+
+ // Hope that the parent from QObject is okay.
+ if (lhs->parent() != parent())
+ uDebug() << "copyInto has a wrong parent";
+}
+
+UMLObject *UMLObject::clone() const
+{
+ UMLObject *clone = new UMLObject;
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+/**
+ * Returns the abstract state of the object.
+ */
+bool UMLObject::isAbstract() const
+{
+ return m_bAbstract;
+}
+
+/**
+ * Sets the paste state of the object.
+ */
+void UMLObject::setAbstract(bool bAbstract)
+{
+ m_bAbstract = bAbstract;
+ emitModified();
+}
+
+/**
+ * Returns true if this UMLObject has classifier scope,
+ * otherwise false (the default).
+ */
+bool UMLObject::isStatic() const
+{
+ return m_bStatic;
+}
+
+/**
+ * Sets the value for m_bStatic.
+ */
+void UMLObject::setStatic(bool bStatic)
+{
+ m_bStatic = bStatic;
+ emitModified();
+}
+
+/**
+ * Forces the emission of the modified signal. Useful when
+ * updating several attributes at a time: you can block the
+ * signals, update all atts, and then force the signal.
+ */
+void UMLObject::emitModified()
+{
+ UMLDoc *umldoc = UMLApp::app()->document();
+ if (!umldoc->loading() && !umldoc->closing())
+ emit modified();
+}
+
+/**
+ * Returns the type of the object.
+ *
+ * @return Returns the type of the object.
+ */
+UMLObject::ObjectType UMLObject::baseType() const
+{
+ return m_BaseType;
+}
+
+/**
+ * @return The type used for rtti as string.
+ */
+QLatin1String UMLObject::baseTypeStr() const
+{
+ return QLatin1String(ENUM_NAME(UMLObject, ObjectType, m_BaseType));
+}
+
+/**
+ * Set the type of the object.
+ *
+ * @param ot The ObjectType to set.
+ */
+void UMLObject::setBaseType(ObjectType ot)
+{
+ m_BaseType = ot;
+}
+
+/**
+ * Returns the ID of the object.
+ *
+ * @return Returns the ID of the object.
+ */
+ID::Type UMLObject::id() const
+{
+ return m_nId;
+}
+
+/**
+ * Returns the documentation for the object.
+ *
+ * @return Returns the documentation for the object.
+ */
+QString UMLObject::doc() const
+{
+ return m_Doc;
+}
+
+/**
+ * Returns state of documentation for the object.
+ *
+ * @return false if documentation is empty
+ */
+bool UMLObject::hasDoc() const
+{
+ return !m_Doc.isEmpty();
+}
+
+/**
+ * Sets the documentation for the object.
+ *
+ * @param d The documentation for the object.
+ */
+void UMLObject::setDoc(const QString &d)
+{
+ m_Doc = d;
+ //emit modified(); No, this is done centrally at DocWindow::updateDocumentation()
+}
+
+/**
+ * Returns the visibility of the object.
+ *
+ * @return Returns the visibility of the object.
+ */
+Visibility::Enum UMLObject::visibility() const
+{
+ return m_visibility;
+}
+
+/**
+ * Sets the visibility of the object.
+ *
+ * @param visibility The visibility of the object.
+ */
+void UMLObject::setVisibility(Visibility::Enum visibility)
+{
+ if (m_visibility != visibility) {
+ UMLApp::app()->executeCommand(new CmdSetVisibility(this, visibility));
+ }
+}
+
+/**
+ * Method used by setVisibility: it is called by cmdSetVisibility, Don't use it!
+ */
+void UMLObject::setVisibilityCmd(Visibility::Enum visibility)
+{
+ m_visibility = visibility;
+ emitModified();
+}
+
+/**
+ * Sets the class' UMLStereotype. Adjusts the reference counts
+ * at the previously set stereotype and at the new stereotype.
+ * If the previously set UMLStereotype's reference count drops
+ * to zero then the UMLStereotype is removed at the UMLDoc and
+ * it is then physically deleted.
+ *
+ * @param stereo Sets the classes UMLStereotype.
+ */
+void UMLObject::setUMLStereotype(UMLStereotype *stereo)
+{
+ if (stereo == m_pStereotype)
+ return;
+ if (stereo) {
+ stereo->incrRefCount();
+ }
+ if (m_pStereotype) {
+ m_pStereotype->decrRefCount();
+ if (m_pStereotype->refCount() == 0) {
+ UMLDoc *pDoc = UMLApp::app()->document();
+ pDoc->removeStereotype(m_pStereotype);
+ delete m_pStereotype;
+ }
+ }
+ m_pStereotype = stereo;
+ // TODO: don't emit modified() if predefined folder
+ emitModified();
+}
+
+/**
+ * Sets the classes stereotype name.
+ * Internally uses setUMLStereotype().
+ *
+ * @param name Sets the classes stereotype name.
+ */
+void UMLObject::setStereotype(const QString &name)
+{
+ if (name != stereotype()) {
+ UMLApp::app()->executeCommand(new CmdSetStereotype(this, name));
+ }
+}
+
+void UMLObject::setStereotypeCmd(const QString& name)
+{
+ if (name.isEmpty()) {
+ setUMLStereotype(NULL);
+ return;
+ }
+ UMLDoc *pDoc = UMLApp::app()->document();
+ UMLStereotype *s = pDoc->findOrCreateStereotype(name);
+ setUMLStereotype(s);
+}
+
+/**
+ * Sets the UMLPackage in which this class is located.
+ *
+ * @param pPkg Pointer to the class' UMLPackage.
+ */
+bool UMLObject::setUMLPackage(UMLPackage* pPkg)
+{
+ if (pPkg == this) {
+ uDebug() << "setting parent to myself is not allowed";
+ return false;
+ }
+
+ if (pPkg == NULL) {
+ // Allow setting to NULL for stereotypes
+ m_pUMLPackage = pPkg;
+ return true;
+ }
+
+ if (pPkg->umlPackage() == this) {
+ uDebug() << "setting parent to an object of which I'm already the parent is not allowed";
+ return false;
+ }
+
+ m_pUMLPackage = pPkg;
+ emitModified();
+ return true;
+}
+
+/**
+ * Returns the classes UMLStereotype object.
+ *
+ * @return Returns the classes UMLStereotype object.
+ */
+UMLStereotype * UMLObject::umlStereotype()
+{
+ return m_pStereotype;
+}
+
+/**
+ * Returns the stereotype.
+ */
+QString UMLObject::stereotype(bool includeAdornments /* = false */) const
+{
+ if (m_pStereotype == NULL)
+ return QString();
+ return m_pStereotype->name(includeAdornments);
+}
+
+/**
+ * Return the package(s) in which this UMLObject is contained
+ * as a text.
+ *
+ * @param separator Separator string for joining together the
+ * individual package prefixes (optional.)
+ * If no separator is given then the separator
+ * of the currently selected language is used.
+ * @param includeRoot Whether to prefix the root folder name.
+ * Default: false.
+ * @return The UMLObject's enclosing package(s) as a text.
+ */
+QString UMLObject::package(const QString& separator, bool includeRoot)
+{
+ QString tempSeparator = separator;
+ if (tempSeparator.isEmpty())
+ tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
+ QString fqn = fullyQualifiedName(tempSeparator, includeRoot);
+ if (!fqn.contains(tempSeparator))
+ return QString();
+ QString scope = fqn.left(fqn.length() - tempSeparator.length() - m_name.length());
+ return scope;
+}
+
+/**
+ * Return a list of the packages in which this class is embedded.
+ * The outermost package is first in the list.
+ *
+ * @param includeRoot Whether to prefix the root folder name.
+ * Default: false.
+ * @return UMLPackageList of the containing packages.
+ */
+UMLPackageList UMLObject::packages(bool includeRoot) const
+{
+ UMLPackageList pkgList;
+ UMLPackage* pkg = m_pUMLPackage;
+ while (pkg != NULL) {
+ pkgList.prepend(pkg);
+ pkg = pkg->umlPackage();
+ }
+ if (!includeRoot)
+ pkgList.removeFirst();
+ return pkgList;
+}
+
+/**
+ * Returns the UMLPackage that this class is located in.
+ *
+ * @return Pointer to the UMLPackage of this class.
+ */
+UMLPackage* UMLObject::umlPackage()
+{
+ return m_pUMLPackage;
+}
+
+/**
+ * Return secondary ID. Required by resolveRef().
+ */
+QString UMLObject::secondaryId() const
+{
+ return m_SecondaryId;
+}
+
+/**
+ * Set the secondary ID.
+ * Currently only required by petalTree2Uml(); all other setting of the
+ * m_SecondaryID is internal to the UMLObject class hierarchy.
+ */
+void UMLObject::setSecondaryId(const QString& id)
+{
+ m_SecondaryId = id;
+}
+
+/**
+ * Return secondary ID fallback.
+ * Required by resolveRef() for imported model files.
+ */
+QString UMLObject::secondaryFallback() const
+{
+ return m_SecondaryFallback;
+}
+
+/**
+ * Set the secondary ID fallback.
+ * Currently only used by petalTree2Uml().
+ */
+void UMLObject::setSecondaryFallback(const QString& id)
+{
+ m_SecondaryFallback = id;
+}
+
+/**
+ * Calls UMLDoc::signalUMLObjectCreated() if m_BaseType affords
+ * doing so.
+ */
+void UMLObject::maybeSignalObjectCreated()
+{
+ if (!m_bCreationWasSignalled &&
+ m_BaseType != ot_Stereotype &&
+ m_BaseType != ot_Association &&
+ m_BaseType != ot_Role) {
+ m_bCreationWasSignalled = true;
+ UMLDoc* umldoc = UMLApp::app()->document();
+ umldoc->signalUMLObjectCreated(this);
+ }
+}
+
+/**
+ * Resolve referenced objects (if any.)
+ * Needs to be called after all UML objects are loaded from file.
+ * This needs to be done after all model objects are loaded because
+ * some of the xmi.id's might be forward references, i.e. they may
+ * identify model objects which were not yet loaded at the point of
+ * reference.
+ * The default implementation attempts resolution of the m_SecondaryId.
+ *
+ * @return True for success.
+ */
+bool UMLObject::resolveRef()
+{
+ if (m_pSecondary || (m_SecondaryId.isEmpty() && m_SecondaryFallback.isEmpty())) {
+ maybeSignalObjectCreated();
+ return true;
+ }
+#ifdef VERBOSE_DEBUGGING
+ uDebug() << m_name << ": m_SecondaryId is " << m_SecondaryId;
+#endif
+ UMLDoc *pDoc = UMLApp::app()->document();
+ // In the new, XMI standard compliant save format,
+ // the type is the xmi.id of a UMLClassifier.
+ if (! m_SecondaryId.isEmpty()) {
+ m_pSecondary = pDoc->findObjectById(Uml::ID::fromString(m_SecondaryId));
+ if (m_pSecondary != NULL) {
+ if (m_pSecondary->baseType() == ot_Stereotype) {
+ if (m_pStereotype)
+ m_pStereotype->decrRefCount();
+ m_pStereotype = dynamic_cast<UMLStereotype*>(m_pSecondary.data());
+ m_pStereotype->incrRefCount();
+ m_pSecondary = NULL;
+ }
+ m_SecondaryId = QString();
+ maybeSignalObjectCreated();
+ return true;
+ }
+ if (m_SecondaryFallback.isEmpty()) {
+ uDebug() << "object with xmi.id=" << m_SecondaryId << " not found, setting to undef";
+ UMLFolder *datatypes = pDoc->datatypeFolder();
+ m_pSecondary = Object_Factory::createUMLObject(ot_Datatype, QLatin1String("undef"), datatypes, false);
+ return true;
+ }
+ }
+ if (m_SecondaryFallback.isEmpty()) {
+ uError() << m_name << ": cannot find type with id " << m_SecondaryId;
+ return false;
+ }
+#ifdef VERBOSE_DEBUGGING
+ uDebug() << m_name << ": could not resolve secondary ID " << m_SecondaryId
+ << ", using secondary fallback " << m_SecondaryFallback;
+#endif
+ m_SecondaryId = m_SecondaryFallback;
+ // Assume we're dealing with the older umbrello-kf6 format where
+ // the type name was saved in the "type" attribute rather
+ // than the xmi.id of the model object of the attribute type.
+ m_pSecondary = pDoc->findUMLObject(m_SecondaryId, ot_UMLObject, this);
+ if (m_pSecondary) {
+ m_SecondaryId = QString();
+ maybeSignalObjectCreated();
+ return true;
+ }
+ // Work around Object_Factory::createUMLObject()'s incapability
+ // of on-the-fly scope creation:
+ if (m_SecondaryId.contains(QLatin1String("::"))) {
+ // TODO: Merge Import_Utils::createUMLObject() into Object_Factory::createUMLObject()
+ m_pSecondary = Import_Utils::createUMLObject(ot_UMLObject, m_SecondaryId, m_pUMLPackage);
+ if (m_pSecondary) {
+ if (Import_Utils::newUMLObjectWasCreated()) {
+ maybeSignalObjectCreated();
+ qApp->processEvents();
+ uDebug() << "Import_Utils::createUMLObject() created a new type for "
+ << m_SecondaryId;
+ } else {
+ uDebug() << "Import_Utils::createUMLObject() returned an existing type for "
+ << m_SecondaryId;
+ }
+ m_SecondaryId = QString();
+ return true;
+ }
+ uError() << "Import_Utils::createUMLObject() failed to create a new type for "
+ << m_SecondaryId;
+ return false;
+ }
+ uDebug() << "Creating new type for " << m_SecondaryId;
+ // This is very C++ specific - we rely on some '*' or
+ // '&' to decide it's a ref type. Plus, we don't recognize
+ // typedefs of ref types.
+ bool isReferenceType = (m_SecondaryId.contains(QLatin1Char('*')) ||
+ m_SecondaryId.contains(QLatin1Char('&')));
+ ObjectType ot = ot_Class;
+ if (isReferenceType) {
+ ot = ot_Datatype;
+ } else {
+ if (Model_Utils::isCommonDataType(m_SecondaryId))
+ ot = ot_Datatype;
+ }
+ m_pSecondary = Object_Factory::createUMLObject(ot, m_SecondaryId, NULL);
+ if (m_pSecondary == NULL)
+ return false;
+ m_SecondaryId = QString();
+ maybeSignalObjectCreated();
+ //qApp->processEvents();
+ return true;
+}
+
+void UMLObject::saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
+{
+ Q_UNUSED(qDoc); Q_UNUSED(qElement);
+}
+
+/**
+ * Auxiliary to saveToXMI.
+ * Create a QDomElement with the given tag, and save the XMI attributes
+ * that are common to all child classes to the newly created element.
+ * This method does not need to be overridden by child classes.
+ */
+QDomElement UMLObject::save(const QString &tag, QDomDocument & qDoc)
+{
+ /*
+ Call as the first action of saveToXMI() in child class:
+ This creates the QDomElement with which to work.
+ */
+ QDomElement qElement = qDoc.createElement(tag);
+ qElement.setAttribute(QLatin1String("isSpecification"), QLatin1String("false"));
+ if (m_BaseType != ot_Association &&
+ m_BaseType != ot_Role &&
+ m_BaseType != ot_Attribute) {
+ qElement.setAttribute(QLatin1String("isLeaf"), QLatin1String("false"));
+ qElement.setAttribute(QLatin1String("isRoot"), QLatin1String("false"));
+ if (m_bAbstract)
+ qElement.setAttribute(QLatin1String("isAbstract"), QLatin1String("true"));
+ else
+ qElement.setAttribute(QLatin1String("isAbstract"), QLatin1String("false"));
+ }
+ qElement.setAttribute(QLatin1String("xmi.id"), Uml::ID::toString(m_nId));
+ qElement.setAttribute(QLatin1String("name"), m_name);
+ if (m_BaseType != ot_Operation &&
+ m_BaseType != ot_Role &&
+ m_BaseType != ot_Attribute) {
+ Uml::ID::Type nmSpc;
+ if (m_pUMLPackage)
+ nmSpc = m_pUMLPackage->id();
+ else
+ nmSpc = UMLApp::app()->document()->modelID();
+ qElement.setAttribute(QLatin1String("namespace"), Uml::ID::toString(nmSpc));
+ }
+ if (! m_Doc.isEmpty())
+ qElement.setAttribute(QLatin1String("comment"), m_Doc); //CHECK: uml13.dtd compliance
+#ifdef XMI_FLAT_PACKAGES
+ if (m_pUMLPackage) //FIXME: uml13.dtd compliance
+ qElement.setAttribute(QLatin1String("package"), m_pUMLPackage->ID());
+#endif
+ QString visibility = Uml::Visibility::toString(m_visibility, false);
+ qElement.setAttribute(QLatin1String("visibility"), visibility);
+ if (m_pStereotype != NULL)
+ qElement.setAttribute(QLatin1String("stereotype"), Uml::ID::toString(m_pStereotype->id()));
+ if (m_bStatic)
+ qElement.setAttribute(QLatin1String("ownerScope"), QLatin1String("classifier"));
+ /* else
+ qElement.setAttribute("ownerScope", "instance");
+ *** ownerScope defaults to instance if not set **********/
+ return qElement;
+}
+
+/**
+ * Auxiliary to loadFromXMI.
+ * This method is usually overridden by child classes.
+ * It is responsible for loading the specific XMI structure
+ * of the child class.
+ */
+bool UMLObject::load(QDomElement&)
+{
+ // This body is not usually executed because child classes
+ // overwrite the load method.
+ return true;
+}
+
+/**
+ * Analyzes the given QDomElement for a reference to a stereotype.
+ *
+ * @param element QDomElement to analyze.
+ * @return True if a stereotype reference was found, else false.
+ */
+bool UMLObject::loadStereotype(QDomElement & element)
+{
+ QString tag = element.tagName();
+ if (!UMLDoc::tagEq(tag, QLatin1String("stereotype")))
+ return false;
+ QString stereo = element.attribute(QLatin1String("xmi.value"));
+ if (stereo.isEmpty() && element.hasChildNodes()) {
+ /* like so:
+ <UML:ModelElement.stereotype>
+ <UML:Stereotype xmi.idref = '07CD'/>
+ </UML:ModelElement.stereotype>
+ */
+ QDomNode stereoNode = element.firstChild();
+ QDomElement stereoElem = stereoNode.toElement();
+ tag = stereoElem.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("Stereotype"))) {
+ stereo = stereoElem.attribute(QLatin1String("xmi.idref"));
+ }
+ }
+ if (stereo.isEmpty())
+ return false;
+ Uml::ID::Type stereoID = Uml::ID::fromString(stereo);
+ UMLDoc *pDoc = UMLApp::app()->document();
+ if (m_pStereotype)
+ m_pStereotype->decrRefCount();
+ m_pStereotype = pDoc->findStereotypeById(stereoID);
+ if (m_pStereotype)
+ m_pStereotype->incrRefCount();
+ else
+ m_SecondaryId = stereo; // leave it to resolveRef()
+ return true;
+}
+
+/**
+ * This method loads the generic parts of the XMI common to most model
+ * classes. It is not usually reimplemented by child classes.
+ * Instead, it invokes the load() method which implements the loading
+ * of the specifics of each child class.
+ *
+ * @param element The QDomElement from which to load.
+ */
+bool UMLObject::loadFromXMI(QDomElement & element)
+{
+ UMLDoc* umldoc = UMLApp::app()->document();
+ if (umldoc == 0) {
+ uError() << "umldoc is NULL";
+ return false;
+ }
+ // Read the name first so that if we encounter a problem, the error
+ // message can say the name.
+ m_name = element.attribute(QLatin1String("name"));
+ QString id = Model_Utils::getXmiId(element);
+ if (id.isEmpty() || id == QLatin1String("-1")) {
+ // Before version 1.4, umbrello-kf6 did not save the xmi.id of UMLRole objects.
+ // Some tools (such as Embarcadero's) do not have an xmi.id on all attributes.
+ m_nId = UniqueID::gen();
+ uWarning() << m_name << ": xmi.id not present, generating a new one";
+ } else {
+ Uml::ID::Type nId = Uml::ID::fromString(id);
+ if (m_BaseType == ot_Role) {
+ // Some older umbrello-kf6 versions had a problem with xmi.id's
+ // of other objects being reused for the UMLRole, see e.g.
+ // attachment 21179 at http://bugs.kde.org/147988 .
+ // If the xmi.id is already being used then we generate a new one.
+ UMLObject *o = umldoc->findObjectById(nId);
+ if (o) {
+ uError() << "loadFromXMI(UMLRole): id " << id
+ << " is already in use!!! Please fix your XMI file.";
+ }
+ }
+ m_nId = nId;
+ }
+
+ if (element.hasAttribute(QLatin1String("documentation"))) // for bkwd compat.
+ m_Doc = element.attribute(QLatin1String("documentation"));
+ else
+ m_Doc = element.attribute(QLatin1String("comment")); //CHECK: need a UML:Comment?
+
+ m_visibility = Uml::Visibility::Public;
+ if (element.hasAttribute(QLatin1String("scope"))) { // for bkwd compat.
+ QString scope = element.attribute(QLatin1String("scope"));
+ if (scope == QLatin1String("instance_level")) // nsuml compat.
+ m_bStatic = false;
+ else if (scope == QLatin1String("classifier_level")) // nsuml compat.
+ m_bStatic = true;
+ else {
+ int nScope = scope.toInt();
+ switch (nScope) {
+ case 200:
+ m_visibility = Uml::Visibility::Public;
+ break;
+ case 201:
+ m_visibility = Uml::Visibility::Private;
+ break;
+ case 202:
+ m_visibility = Uml::Visibility::Protected;
+ break;
+ default:
+ uError() << m_name << ": illegal scope " << nScope;
+ }
+ }
+ } else {
+ QString visibility = element.attribute(QLatin1String("visibility"), QLatin1String("public"));
+ if (visibility == QLatin1String("private")
+ || visibility == QLatin1String("private_vis")) // for compatibility with other programs
+ m_visibility = Uml::Visibility::Private;
+ else if (visibility == QLatin1String("protected")
+ || visibility == QLatin1String("protected_vis")) // for compatibility with other programs
+ m_visibility = Uml::Visibility::Protected;
+ else if (visibility == QLatin1String("implementation"))
+ m_visibility = Uml::Visibility::Implementation;
+ }
+
+ QString stereo = element.attribute(QLatin1String("stereotype"));
+ if (!stereo.isEmpty()) {
+ Uml::ID::Type stereoID = Uml::ID::fromString(stereo);
+ if (m_pStereotype)
+ m_pStereotype->decrRefCount();
+ m_pStereotype = umldoc->findStereotypeById(stereoID);
+ if (m_pStereotype) {
+ m_pStereotype->incrRefCount();
+ } else {
+ uDebug() << m_name << ": UMLStereotype " << Uml::ID::toString(stereoID)
+ << " not found, creating now.";
+ setStereotypeCmd(stereo);
+ }
+ }
+
+ if (element.hasAttribute(QLatin1String("abstract"))) { // for bkwd compat.
+ QString abstract = element.attribute(QLatin1String("abstract"), QLatin1String("0"));
+ m_bAbstract = (bool)abstract.toInt();
+ } else {
+ QString isAbstract = element.attribute(QLatin1String("isAbstract"), QLatin1String("false"));
+ m_bAbstract = (isAbstract == QLatin1String("true"));
+ }
+
+ if (element.hasAttribute(QLatin1String("static"))) { // for bkwd compat.
+ QString staticScope = element.attribute(QLatin1String("static"), QLatin1String("0"));
+ m_bStatic = (bool)staticScope.toInt();
+ } else {
+ QString ownerScope = element.attribute(QLatin1String("ownerScope"), QLatin1String("instance"));
+ m_bStatic = (ownerScope == QLatin1String("classifier"));
+ }
+
+ // If the node has child nodes, check whether attributes can be
+ // extracted from them.
+ if (element.hasChildNodes()) {
+ QDomNode node = element.firstChild();
+ if (node.isComment())
+ node = node.nextSibling();
+ QDomElement elem = node.toElement();
+ while (!elem.isNull()) {
+ QString tag = elem.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("name"))) {
+ m_name = elem.attribute(QLatin1String("xmi.value"));
+ if (m_name.isEmpty())
+ m_name = elem.text();
+ } else if (UMLDoc::tagEq(tag, QLatin1String("visibility"))) {
+ QString vis = elem.attribute(QLatin1String("xmi.value"));
+ if (vis.isEmpty())
+ vis = elem.text();
+ if (vis == QLatin1String("private") || vis == QLatin1String("private_vis"))
+ m_visibility = Uml::Visibility::Private;
+ else if (vis == QLatin1String("protected") || vis == QLatin1String("protected_vis"))
+ m_visibility = Uml::Visibility::Protected;
+ else if (vis == QLatin1String("implementation"))
+ m_visibility = Uml::Visibility::Implementation;
+ } else if (UMLDoc::tagEq(tag, QLatin1String("isAbstract"))) {
+ QString isAbstract = elem.attribute(QLatin1String("xmi.value"));
+ if (isAbstract.isEmpty())
+ isAbstract = elem.text();
+ m_bAbstract = (isAbstract == QLatin1String("true"));
+ } else if (UMLDoc::tagEq(tag, QLatin1String("ownerScope"))) {
+ QString ownerScope = elem.attribute(QLatin1String("xmi.value"));
+ if (ownerScope.isEmpty())
+ ownerScope = elem.text();
+ m_bStatic = (ownerScope == QLatin1String("classifier"));
+ } else {
+ loadStereotype(elem);
+ }
+ node = node.nextSibling();
+ if (node.isComment())
+ node = node.nextSibling();
+ elem = node.toElement();
+ }
+ }
+
+ // Operations, attributes, enum literals, templates, stereotypes,
+ // and association role objects get added and signaled elsewhere.
+ if (m_BaseType != ot_Operation && m_BaseType != ot_Attribute &&
+ m_BaseType != ot_EnumLiteral && m_BaseType != ot_EntityAttribute &&
+ m_BaseType != ot_Template && m_BaseType != ot_Stereotype &&
+ m_BaseType != ot_Role && m_BaseType != ot_UniqueConstraint &&
+ m_BaseType != ot_ForeignKeyConstraint && m_BaseType != ot_CheckConstraint) {
+ if (m_pUMLPackage) {
+ m_pUMLPackage->addObject(this);
+ } else if (umldoc->rootFolderType(this) == Uml::ModelType::N_MODELTYPES) {
+ // m_pUMLPackage is not set on the root folders.
+ uDebug() << m_name << ": m_pUMLPackage is not set";
+ }
+ }
+ return load(element);
+}
+
+/**
+ * Helper function for debug output.
+ * Returns the given enum value as string.
+ * @param ot ObjectType of which a string representation is wanted
+ * @return the ObjectType as string
+ */
+QString UMLObject::toString(ObjectType ot)
+{
+ return QLatin1String(ENUM_NAME(UMLObject, ObjectType, ot));
+}
+
+/**
+ * Returns the given object type value as localized string.
+ * @param ot ObjectType of which a string representation is wanted
+ * @return the ObjectType as localized string
+ */
+QString UMLObject::toI18nString(ObjectType t)
+{
+ QString name;
+
+ switch (t) {
+ case UMLObject::ot_Actor:
+ name = i18n("Actor &name:");
+ break;
+ case UMLObject::ot_Artifact:
+ name = i18n("Artifact &name:");
+ break;
+ case UMLObject::ot_Class:
+ name = i18n("Class &name:");
+ break;
+ case UMLObject::ot_Component:
+ name = i18n("Component &name:");
+ break;
+ case UMLObject::ot_Datatype:
+ name = i18n("Datatype &name:");
+ break;
+ case UMLObject::ot_Entity:
+ name = i18n("Entity &name:");
+ break;
+ case UMLObject::ot_Enum:
+ name = i18n("Enum &name:");
+ break;
+ case UMLObject::ot_Folder:
+ name = i18n("Folder &name:");
+ break;
+ case UMLObject::ot_Interface:
+ name = i18n("Interface &name:");
+ break;
+ case UMLObject::ot_Node:
+ name = i18n("Node &name:");
+ break;
+ case UMLObject::ot_Package:
+ name = i18n("Package &name:");
+ break;
+ case UMLObject::ot_Port:
+ name = i18n("Port &name:");
+ break;
+ case UMLObject::ot_Stereotype:
+ name = i18n("Stereotype &name:");
+ break;
+ case UMLObject::ot_UseCase:
+ name = i18n("Use case &name:");
+ break;
+ default:
+ name = QLatin1String("<unknown> &name:");
+ uWarning() << "unknown object type";
+ break;
+ }
+ return name;
+}
+
+/**
+ * Print UML Object to debug output stream, so it can be used like
+ * uDebug() << "This object shouldn't be here: " << illegalObject;
+ */
+QDebug operator<<(QDebug out, const UMLObject& obj)
+{
+ out.nospace() << "UMLObject: name= " << obj.name()
+ << ", type= " << UMLObject::toString(obj.m_BaseType);
+ return out.space();
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlobject.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlobject.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlobject.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlobject.h 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,198 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLOBJECT_H
+#define UMLOBJECT_H
+
+#include "basictypes.h"
+#include "umlpackagelist.h"
+
+//qt includes
+#include <QDomDocument>
+#include <QDomElement>
+#include <QObject>
+#include <QPointer>
+#include <QString>
+
+class UMLStereotype;
+
+/**
+ * This class is the non-graphical version of @ref UMLWidget. These are
+ * created and maintained in the class @ref UMLDoc. This class holds all
+ * the generic information needed for all UML objects.
+ *
+ * @ref clone needs to be implemented by each child class.
+ *
+ * @ref saveToXMI saves the XMI attributes of each specific model class.
+ * It needs to be implemented by each child class.
+ * For creating the QDomElement and saving the common XMI parts,
+ * it can use the save() method.
+ *
+ * @short The base class for UML objects.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLObject : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(ObjectType)
+
+public:
+ enum ObjectType
+ {
+ ot_Unknown = -1,
+ ot_UMLObject = 100,
+ ot_Actor,
+ ot_UseCase,
+ ot_Package,
+ ot_Interface,
+ ot_Datatype,
+ ot_Enum,
+ ot_Class,
+ ot_Association,
+ ot_Attribute,
+ ot_Operation,
+ ot_EnumLiteral,
+ ot_Template,
+ ot_Component,
+ ot_Artifact,
+ ot_Node,
+ ot_Stereotype,
+ ot_Role,
+ ot_Entity,
+ ot_EntityAttribute,
+ ot_Folder,
+ ot_EntityConstraint,
+ ot_UniqueConstraint,
+ ot_ForeignKeyConstraint,
+ ot_CheckConstraint,
+ ot_Category,
+ ot_Port
+ };
+
+ static QString toString(ObjectType ot);
+ static QString toI18nString(ObjectType t);
+
+ explicit UMLObject(const UMLObject& other);
+ explicit UMLObject(UMLObject* parent, const QString& name, Uml::ID::Type id = Uml::ID::None);
+ explicit UMLObject(UMLObject* parent);
+ explicit UMLObject(const QString& name = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLObject();
+
+ bool operator==(const UMLObject & rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ virtual void setBaseType(ObjectType ot);
+ ObjectType baseType() const;
+ QLatin1String baseTypeStr() const;
+
+ virtual void setID(Uml::ID::Type NewID);
+ virtual Uml::ID::Type id() const;
+
+ QString doc() const;
+ bool hasDoc() const;
+ void setDoc(const QString &d);
+
+ void setVisibility(Uml::Visibility::Enum visibility);
+ void setVisibilityCmd(Uml::Visibility::Enum visibility);
+ Uml::Visibility::Enum visibility() const;
+
+ void setStereotype(const QString &_name);
+ void setStereotypeCmd(const QString &_name);
+ QString stereotype(bool includeAdornments = false) const;
+
+ void setUMLStereotype(UMLStereotype *stereo);
+ UMLStereotype *umlStereotype();
+
+ QString package(const QString& separator = QString(),
+ bool includeRoot = false);
+
+ bool setUMLPackage(UMLPackage* pPkg);
+ UMLPackage* umlPackage();
+
+ UMLPackageList packages(bool includeRoot = false) const;
+
+ virtual void setName(const QString &strName);
+ void setNameCmd(const QString &strName) ;
+ QString name() const;
+
+ virtual QString fullyQualifiedName(const QString& separator = QString(),
+ bool includeRoot = false) const;
+
+ void setAbstract(bool bAbstract);
+ bool isAbstract() const;
+
+ virtual bool showPropertiesDialog(QWidget* parent = 0);
+
+ virtual bool resolveRef();
+
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+ virtual bool loadFromXMI(QDomElement & element);
+
+ bool loadStereotype(QDomElement & element);
+
+ void setStatic(bool bStatic);
+ bool isStatic() const;
+
+ virtual bool acceptAssociationType(Uml::AssociationType::Enum); //:TODO: check if this is really needed here
+
+ void setSecondaryId(const QString& id);
+ QString secondaryId() const;
+
+ void setSecondaryFallback(const QString& id);
+ QString secondaryFallback() const;
+
+ QDomElement save(const QString &tag, QDomDocument & qDoc);
+
+ friend QDebug operator<< (QDebug out, const UMLObject& obj);
+
+public slots:
+ void emitModified();
+
+signals:
+ void modified();
+
+protected:
+ void init();
+
+ void maybeSignalObjectCreated();
+
+ virtual bool load(QDomElement& element);
+
+ Uml::ID::Type m_nId; ///< object's id
+ QString m_Doc; ///< object's documentation
+ UMLPackage* m_pUMLPackage; ///< package the object belongs to if applicable
+ QPointer<UMLStereotype> m_pStereotype; ///< stereotype of the object if applicable
+ QString m_name; ///< objects name
+ ObjectType m_BaseType; ///< objects type
+ Uml::Visibility::Enum m_visibility; ///< objects visibility
+ bool m_bAbstract; ///< state of whether the object is abstract or not
+ bool m_bStatic; ///< flag for instance scope
+ bool m_bInPaste; ///< caller sets this true when in paste operation
+ bool m_bCreationWasSignalled; ///< auxiliary to maybeSignalObjectCreated()
+ QPointer<UMLObject> m_pSecondary; ///< pointer to an associated object
+ ///< Only a few of the classes inheriting from UMLObject use this.
+ ///< However, it needs to be here because of inheritance graph
+ ///< disjunctness.
+ QString m_SecondaryId; ///< xmi.id of the secondary object for intermediate use during
+ ///< loading. The secondary ID is resolved to the m_pSecondary
+ ///< in the course of resolveRef() at the end of loading.
+ QString m_SecondaryFallback; ///< Last-chance backup for when m_SecondaryId is not found.
+ ///< Used by Rose import: MDL files specify both a "quidu"
+ ///< (which corresponds to m_SecondaryId) and the human readable
+ ///< fully qualified target name of a reference.
+ ///< In case the quidu is not found, the human readable name is
+ ///< used which we store in m_SecondaryFallback.
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlobjectlist.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/umlobjectlist.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlobjectlist.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlobjectlist.cpp 2015-10-08 11:48:59.507089026 +0300
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "umlobjectlist.h"
+#include "umlobject.h"
+
+UMLObjectList::UMLObjectList()
+{
+}
+
+UMLObjectList::~UMLObjectList()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+void UMLObjectList::copyInto(UMLObjectList *rhs) const
+{
+ // Don't copy yourself.
+ if (rhs == this) return;
+
+ rhs->clear();
+
+ // Suffering from const; we shall not modify our object.
+ UMLObjectList *tmp = new UMLObjectList(*this);
+
+ UMLObject *item = NULL;
+ for (UMLObjectListIt oit(*tmp); oit.hasNext() ;)
+ {
+ item = oit.next();
+ rhs->append(item->clone());
+ }
+ delete tmp;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObjectList* UMLObjectList::clone() const
+{
+ UMLObjectList *clone = new UMLObjectList();
+ copyInto(clone);
+ return clone;
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlobjectlist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlobjectlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlobjectlist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlobjectlist.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * 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) 2001 Gustavo Madrigal gmadrigal@nextphere.com *
+ * copyright (C) 2002-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLOBJECTLIST_H
+#define UMLOBJECTLIST_H
+
+#include <QList>
+#include <QPointer>
+
+// forward declarations
+class UMLObject;
+
+typedef QListIterator<QPointer<UMLObject> >
+UMLObjectListIt;
+
+/**
+ * This sub-class adds copyInto and clone to the QList<UMLObject*>
+ * base class.
+ */
+class UMLObjectList : public QList<QPointer<UMLObject> >
+{
+public:
+
+ UMLObjectList();
+ virtual ~UMLObjectList();
+
+ virtual void copyInto(UMLObjectList *rhs) const;
+
+ virtual UMLObjectList* clone() const;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umloperationlist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umloperationlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umloperationlist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umloperationlist.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,23 @@
+/***************************************************************************
+ * *
+ * 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) 2003-2007 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLOPERATIONLIST_H
+#define UMLOPERATIONLIST_H
+
+#include <qlist.h>
+
+// forward declaration
+class UMLOperation;
+
+typedef QList<UMLOperation*> UMLOperationList;
+typedef QListIterator<UMLOperation*> UMLOperationListIt;
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlpackagelist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlpackagelist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlpackagelist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlpackagelist.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * *
+ * 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) 2003-2007 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLPACKAGELIST_H
+#define UMLPACKAGELIST_H
+
+#include <qlist.h>
+
+class UMLPackage;
+
+typedef QList<UMLPackage*> UMLPackageList;
+typedef QListIterator<UMLPackage*> UMLPackageListIt;
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlrole.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/umlrole.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlrole.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlrole.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,415 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "umlrole.h"
+
+// local includes
+#include "association.h"
+#include "debug_utils.h"
+#include "umldoc.h"
+#include "umlroledialog.h"
+#include "uml.h"
+
+// qt includes
+#include <QPointer>
+#include <QRegExp>
+
+/**
+ * Sets up an association.
+ *
+ * @param parent The parent (association) of this UMLRole.
+ * @param parentObj The Parent UML Object of this UMLRole
+ * @param role The Uml::RoleType::Enum of this UMLRole
+ */
+UMLRole::UMLRole(UMLAssociation * parent, UMLObject * parentObj, Uml::RoleType::Enum role)
+ : UMLObject(const_cast<UMLAssociation*>(parent)),
+ m_pAssoc(parent),
+ m_role(role),
+ m_Multi(QString()),
+ m_Changeability(Uml::Changeability::Changeable)
+{
+ m_BaseType = UMLObject::ot_Role;
+ m_name.clear();
+ m_pSecondary = parentObj;
+
+ // connect this up to parent
+ connect(this, SIGNAL(modified()), parent, SIGNAL(modified()));
+}
+
+/**
+ * Standard destructor.
+ */
+UMLRole::~UMLRole()
+{
+}
+
+/**
+ * Overloaded '==' operator.
+ */
+bool UMLRole::operator==(const UMLRole &rhs) const
+{
+ if (this == &rhs) {
+ return true;
+ }
+ return (UMLObject::operator==(rhs) &&
+ m_Changeability == rhs.m_Changeability &&
+ m_Multi == rhs.m_Multi &&
+ m_name == rhs.m_name
+ );
+}
+
+UMLAssociation * UMLRole::parentAssociation() const
+{
+ return m_pAssoc;
+}
+
+/**
+ * Returns the UMLObject assigned to the role.
+ * @return Pointer to the UMLObject in role.
+ */
+UMLObject* UMLRole::object() const
+{
+ return m_pSecondary;
+}
+
+/**
+ * Returns the Changeablity of the role.
+ *
+ * @return Changeability of role.
+ */
+Uml::Changeability::Enum UMLRole::changeability() const
+{
+ return m_Changeability;
+}
+
+/**
+ * Returns the multiplicity assigned to the role.
+ *
+ * @return The multiplicity assigned to the role.
+ */
+QString UMLRole::multiplicity() const
+{
+ return m_Multi;
+}
+
+/**
+ * Sets the UMLObject playing the role in the association.
+ *
+ * @param obj Pointer to the UMLObject of role.
+ */
+void UMLRole::setObject(UMLObject *obj)
+{
+ // because we will get the id of this role from the parent
+ // object, we CANT allow UMLRoles to take other UMLRoles as
+ // parent objects. In fact, there is probably good reason
+ // to only take UMLClassifiers here, but I'll leave it more open
+ // for the time being. -b.t.
+ if (obj && dynamic_cast<UMLRole*>(obj)) {
+ uError() << "UMLRole(" << Uml::ID::toString(m_nId) << ") cannot setObject() to another UMLRole("
+ << Uml::ID::toString(obj->id()) << ")";
+ return;
+ }
+
+ m_pSecondary = obj;
+ UMLObject::emitModified();
+}
+
+/**
+ * Sets the changeability of the role.
+ *
+ * @param value Changeability::Enum of role.
+ */
+void UMLRole::setChangeability(Uml::Changeability::Enum value)
+{
+ m_Changeability = value;
+ UMLObject::emitModified();
+}
+
+/**
+ * Sets the multiplicity of the role.
+ *
+ * @param multi The multiplicity of role.
+ */
+void UMLRole::setMultiplicity(const QString &multi)
+{
+ m_Multi = multi;
+ UMLObject::emitModified();
+}
+
+/**
+ * Get the 'id' of the role (NOT the parent object). This could be
+ * either Uml::RoleType::A or Uml::RoleType::B. Yes, it would be better if we
+ * could get along without this, but we need it to distinguish saved
+ * umlrole objects in the XMI for 'self' associations where both roles
+ * will point to the same underlying UMLObject.
+ */
+Uml::RoleType::Enum UMLRole::role() const
+{
+ return m_role;
+}
+
+/**
+ * Creates the <UML:AssociationEnd> XMI element.
+ */
+void UMLRole::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement roleElement = UMLObject::save(QLatin1String("UML:AssociationEnd"), qDoc);
+ if (m_pSecondary)
+ roleElement.setAttribute(QLatin1String("type"), Uml::ID::toString(m_pSecondary->id()));
+ else
+ uError() << "id " << Uml::ID::toString(m_nId) << ": m_pSecondary is NULL";
+ if (!m_Multi.isEmpty())
+ roleElement.setAttribute(QLatin1String("multiplicity"), m_Multi);
+ if (m_role == Uml::RoleType::A) { // role aggregation based on parent type
+ // role A
+ switch (m_pAssoc->getAssocType()) {
+ case Uml::AssociationType::Composition:
+ roleElement.setAttribute(QLatin1String("aggregation"), QLatin1String("composite"));
+ break;
+ case Uml::AssociationType::Aggregation:
+ roleElement.setAttribute(QLatin1String("aggregation"), QLatin1String("aggregate"));
+ break;
+ default:
+ roleElement.setAttribute(QLatin1String("aggregation"), QLatin1String("none"));
+ break;
+ }
+ if (m_pAssoc->getAssocType() == Uml::AssociationType::UniAssociation) {
+ // Normally the isNavigable attribute is "true".
+ // We set it to false on role A to indicate that
+ // role B gets an explicit arrowhead.
+ roleElement.setAttribute(QLatin1String("isNavigable"), QLatin1String("false"));
+ } else {
+ roleElement.setAttribute(QLatin1String("isNavigable"), QLatin1String("true"));
+ }
+ } else {
+ roleElement.setAttribute(QLatin1String("aggregation"), QLatin1String("none"));
+ roleElement.setAttribute(QLatin1String("isNavigable"), QLatin1String("true"));
+ //FIXME obviously this isn't standard XMI
+ if (m_pAssoc->getAssocType() == Uml::AssociationType::Relationship) {
+ roleElement.setAttribute(QLatin1String("relationship"), QLatin1String("true"));
+ }
+ }
+
+ roleElement.setAttribute(QLatin1String("visibility"), Uml::Visibility::toString(visibility(), false));
+
+ switch (m_Changeability) {
+ case Uml::Changeability::Frozen:
+ roleElement.setAttribute(QLatin1String("changeability"), QLatin1String("frozen"));
+ break;
+ case Uml::Changeability::AddOnly:
+ roleElement.setAttribute(QLatin1String("changeability"), QLatin1String("addOnly"));
+ break;
+ case Uml::Changeability::Changeable:
+ roleElement.setAttribute(QLatin1String("changeability"), QLatin1String("changeable"));
+ break;
+ }
+ qElement.appendChild(roleElement);
+}
+
+/**
+ * Display the properties configuration dialog for the object.
+ *
+ * @param parent The parent widget.
+ * @return True for success of this operation.
+ */
+bool UMLRole::showPropertiesDialog(QWidget *parent)
+{
+ QPointer<UMLRoleDialog> dlg = new UMLRoleDialog(parent, this);
+ bool modified = false;
+ if (dlg->exec() == QDialog::Accepted) {
+ modified = true;
+ }
+ delete dlg;
+ return modified;
+}
+
+/**
+ * Loads the <UML:AssociationEnd> XMI element.
+ * Auxiliary to UMLObject::loadFromXMI.
+ */
+bool UMLRole::load(QDomElement & element)
+{
+ UMLDoc * doc = UMLApp::app()->document();
+ QString type = element.attribute(QLatin1String("type"));
+ if (!type.isEmpty()) {
+ if (!m_SecondaryId.isEmpty())
+ uWarning() << "overwriting old m_SecondaryId \"" << m_SecondaryId
+ << " with new value \"" << type << "\"";
+ m_SecondaryId = type;
+ }
+ // Inspect child nodes - for multiplicity (and type if not set above.)
+ for (QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("name"))) {
+ m_name = tempElement.text();
+ } else if (UMLDoc::tagEq(tag, QLatin1String("AssociationEnd.multiplicity"))) {
+ /*
+ * There are different ways in which the multiplicity might be given:
+ * - direct value in the <AssociationEnd.multiplicity> tag,
+ * - attributes "lower" and "upper" of a subordinate <MultiplicityRange>,
+ * - direct value in subordinate <MultiplicityRange.lower> and
+ * <MultiplicityRange.upper> tags
+ */
+ QDomNode n = tempElement.firstChild();
+ if (node.isNull() || tempElement.isNull() || n.isNull() ||
+ n.toElement().isNull()) {
+ m_Multi = tempElement.text().trimmed();
+ continue;
+ }
+ tempElement = n.toElement();
+ tag = tempElement.tagName();
+ if (!UMLDoc::tagEq(tag, QLatin1String("Multiplicity"))) {
+ m_Multi = tempElement.text().trimmed();
+ continue;
+ }
+ n = tempElement.firstChild();
+ tempElement = n.toElement();
+ tag = tempElement.tagName();
+ if (!UMLDoc::tagEq(tag, QLatin1String("Multiplicity.range"))) {
+ m_Multi = tempElement.text().trimmed();
+ continue;
+ }
+ n = tempElement.firstChild();
+ tempElement = n.toElement();
+ tag = tempElement.tagName();
+ if (!UMLDoc::tagEq(tag, QLatin1String("MultiplicityRange"))) {
+ m_Multi = tempElement.text().trimmed();
+ continue;
+ }
+ QString multiUpper;
+ if (tempElement.hasAttribute(QLatin1String("lower"))) {
+ m_Multi = tempElement.attribute(QLatin1String("lower"));
+ multiUpper = tempElement.attribute(QLatin1String("upper"));
+ if (!multiUpper.isEmpty()) {
+ if (!m_Multi.isEmpty())
+ m_Multi.append(QLatin1String(".."));
+ m_Multi.append(multiUpper);
+ }
+ continue;
+ }
+ n = tempElement.firstChild();
+ while (!n.isNull()) {
+ tempElement = n.toElement();
+ tag = tempElement.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("MultiplicityRange.lower"))) {
+ m_Multi = tempElement.text();
+ } else if (UMLDoc::tagEq(tag, QLatin1String("MultiplicityRange.upper"))) {
+ multiUpper = tempElement.text();
+ }
+ n = n.nextSibling();
+ }
+ if (!multiUpper.isEmpty()) {
+ if (!m_Multi.isEmpty())
+ m_Multi.append(QLatin1String(".."));
+ m_Multi.append(multiUpper);
+ }
+ } else if (m_SecondaryId.isEmpty() &&
+ (UMLDoc::tagEq(tag, QLatin1String("type")) ||
+ UMLDoc::tagEq(tag, QLatin1String("participant")))) {
+ m_SecondaryId = tempElement.attribute(QLatin1String("xmi.id"));
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = tempElement.attribute(QLatin1String("xmi.idref"));
+ if (m_SecondaryId.isEmpty()) {
+ QDomNode inner = tempElement.firstChild();
+ QDomElement innerElem = inner.toElement();
+ m_SecondaryId = innerElem.attribute(QLatin1String("xmi.id"));
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = innerElem.attribute(QLatin1String("xmi.idref"));
+ }
+ }
+ }
+ if (!m_Multi.isEmpty())
+ uDebug() << name() << ": m_Multi is " << m_Multi;
+ if (m_SecondaryId.isEmpty()) {
+ uError() << name() << ": type not given or illegal";
+ return false;
+ }
+ UMLObject * obj;
+ obj = doc->findObjectById(Uml::ID::fromString(m_SecondaryId));
+ if (obj) {
+ m_pSecondary = obj;
+ m_SecondaryId = QString();
+ }
+
+ // block signals to prevent needless updating
+ blockSignals(true);
+ // Here comes the handling of the association type.
+ // This is open for discussion - I'm pretty sure there are better ways..
+
+ // Yeah, for one, setting the *parent* object parameters from here is sucky
+ // as hell. Why are we using roleA to store what is essentially a parent (association)
+ // parameter, eh? The UML13.dtd is pretty silly, but since that is what
+ // is driving us to that point, we have to go with it. Some analysis of
+ // the component roles/linked items needs to be done in order to get things
+ // right. *sigh* -b.t.
+
+ // Setting association type from the role (A)
+ // Determination of the "aggregation" attribute used to be done only
+ // when (m_role == Uml::RoleType::A) but some XMI writers (e.g. StarUML) place
+ // the aggregation attribute at role B.
+ // The role end with the aggregation unequal to "none" wins.
+ QString aggregation = element.attribute(QLatin1String("aggregation"), QLatin1String("none"));
+ if (aggregation == QLatin1String("composite"))
+ m_pAssoc->setAssociationType(Uml::AssociationType::Composition);
+ else if (aggregation == QLatin1String("shared") // UML1.3
+ || aggregation == QLatin1String("aggregate")) // UML1.4
+ m_pAssoc->setAssociationType(Uml::AssociationType::Aggregation);
+
+ if (!element.hasAttribute(QLatin1String("isNavigable"))) {
+ // Backward compatibility mode: In umbrello-kf6 version 1.3.x the
+ // logic for saving the isNavigable flag was wrong.
+ // May happen on loading role A.
+ m_pAssoc->setOldLoadMode(true);
+ } else if (m_pAssoc->getOldLoadMode() == true) {
+ // Here is the original logic:
+ // "Role B:
+ // If isNavigable is not given, we make no change to the
+ // association type.
+ // If isNavigable is given, and is "true", then we assume that
+ // the association's other end (role A) is not navigable, and
+ // therefore we change the association type to UniAssociation.
+ // The case that isNavigable is given as "false" is ignored.
+ // Combined with the association type logic for role A, this
+ // allows us to support at_Association and at_UniAssociation."
+ if (element.attribute(QLatin1String("isNavigable")) == QLatin1String("true"))
+ m_pAssoc->setAssociationType(Uml::AssociationType::UniAssociation);
+ } else if (element.attribute(QLatin1String("isNavigable")) == QLatin1String("false")) {
+ m_pAssoc->setAssociationType(Uml::AssociationType::UniAssociation);
+ }
+
+ //FIXME not standard XMI
+ if (element.hasAttribute(QLatin1String("relationship"))) {
+ if (element.attribute(QLatin1String("relationship")) == QLatin1String("true")) {
+ m_pAssoc->setAssociationType(Uml::AssociationType::Relationship);
+ }
+ }
+
+ if (m_Multi.isEmpty())
+ m_Multi = element.attribute(QLatin1String("multiplicity"));
+
+ // Changeability defaults to Changeable if it cant set it here..
+ m_Changeability = Uml::Changeability::Changeable;
+ QString changeability = element.attribute(QLatin1String("changeability"));
+ if (changeability.isEmpty())
+ element.attribute(QLatin1String("changeable")); // for backward compatibility
+ if (changeability == QLatin1String("frozen"))
+ m_Changeability = Uml::Changeability::Frozen;
+ else if (changeability == QLatin1String("addOnly"))
+ m_Changeability = Uml::Changeability::AddOnly;
+
+ // finished config, now unblock
+ blockSignals(false);
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlrole.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlrole.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlrole.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlrole.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,65 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLROLE_H
+#define UMLROLE_H
+
+#include "umlobject.h"
+
+class UMLAssociation;
+
+/**
+ * This class contains the non-graphic representation of an association role.
+ *
+ * @author Brian Thomas <brian.thomas@gsfc.nasa.gov>
+ * @see UMLObject
+ */
+class UMLRole : public UMLObject
+{
+ Q_OBJECT
+public:
+
+ UMLRole(UMLAssociation * parent, UMLObject * parentUMLObject, Uml::RoleType::Enum role);
+ virtual ~UMLRole();
+
+ bool operator==(const UMLRole & rhs) const;
+
+ void setObject(UMLObject *obj);
+ UMLObject* object() const;
+
+ void setChangeability(Uml::Changeability::Enum value);
+ Uml::Changeability::Enum changeability() const;
+
+ void setMultiplicity(const QString &multi);
+ QString multiplicity() const;
+
+ UMLAssociation * parentAssociation() const;
+
+ Uml::RoleType::Enum role() const;
+
+ UMLObject* clone() const { return NULL; }
+
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ virtual bool showPropertiesDialog(QWidget *parent = 0);
+
+protected:
+
+ bool load(QDomElement& element);
+
+private:
+
+ UMLAssociation * m_pAssoc;
+ Uml::RoleType::Enum m_role;
+ QString m_Multi;
+ Uml::Changeability::Enum m_Changeability;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlstereotypelist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umlstereotypelist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umlstereotypelist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umlstereotypelist.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * 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) 2003-2012 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLSTEREOTYPELIST_H
+#define UMLSTEREOTYPELIST_H
+
+#include <QList>
+
+// forward declaration
+class UMLStereotype;
+
+typedef QList<UMLStereotype*> UMLStereotypeList;
+typedef QListIterator<UMLStereotype*> UMLStereotypeListIt;
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umltemplatelist.h umbrello-kf6-15.08.1/umbrello/umlmodel/umltemplatelist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/umltemplatelist.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/umltemplatelist.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,23 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLTEMPLATELIST_H
+#define UMLTEMPLATELIST_H
+
+#include <qlist.h>
+
+// forward declaration
+class UMLTemplate;
+
+typedef QList<UMLTemplate*> UMLTemplateList;
+typedef QListIterator<UMLTemplate*> UMLTemplateListIt;
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/uniqueconstraint.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/uniqueconstraint.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/uniqueconstraint.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/uniqueconstraint.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,325 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+//own header
+#include "uniqueconstraint.h"
+
+// app includes
+#include "debug_utils.h"
+#include "entity.h"
+#include "entityattribute.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "umlattributedialog.h"
+#include "umluniqueconstraintdialog.h"
+#include "object_factory.h"
+
+/**
+ * Sets up a constraint.
+ *
+ * @param parent The parent of this UMLUniqueConstraint.
+ * @param name The name of this UMLUniqueConstraint.
+ * @param id The unique id given to this UMLUniqueConstraint.
+ */
+UMLUniqueConstraint::UMLUniqueConstraint(UMLObject *parent, const QString& name, Uml::ID::Type id)
+ : UMLEntityConstraint(parent, name, id)
+{
+ init();
+}
+
+/**
+ * Sets up a constraint.
+ *
+ * @param parent The parent of this UMLUniqueConstraint.
+ */
+UMLUniqueConstraint::UMLUniqueConstraint(UMLObject *parent)
+ : UMLEntityConstraint(parent)
+{
+ init();
+}
+
+/**
+ * Overloaded '==' operator
+ */
+bool UMLUniqueConstraint::operator==(const UMLUniqueConstraint &rhs) const
+{
+ if(this == &rhs)
+ return true;
+
+ if(!UMLObject::operator==(rhs))
+ return false;
+
+ return true;
+}
+
+/**
+ * Destructor.
+ */
+UMLUniqueConstraint::~UMLUniqueConstraint()
+{
+}
+
+/**
+ * Copy the internal presentation of this object into the UMLUniqueConstraint
+ * object.
+ */
+void UMLUniqueConstraint::copyInto(UMLObject *lhs) const
+{
+ UMLUniqueConstraint *target = static_cast<UMLUniqueConstraint*>(lhs);
+
+ // call the parent first.
+ UMLEntityConstraint::copyInto(target);
+
+ // Copy all datamembers
+ target->m_EntityAttributeList.clear();
+ bool valid = true;
+ foreach(UMLEntityAttribute* attr, m_EntityAttributeList) {
+ if (!valid)
+ break;
+ valid = target->addEntityAttribute(attr);
+ }
+
+ if (!valid) {
+ target->m_EntityAttributeList.clear();
+ uDebug() <<"Copying Attributes Failed : Target list cleared instead";
+ }
+}
+
+/**
+ * Make a clone of the UMLUniqueConstraint.
+ */
+UMLObject* UMLUniqueConstraint::clone() const
+{
+ //FIXME: The new attribute should be slaved to the NEW parent not the old.
+ UMLUniqueConstraint *clone = new UMLUniqueConstraint(static_cast<UMLObject*>(parent()));
+ copyInto(clone);
+ return clone;
+}
+
+/**
+ * Returns a string representation of the UMLUniqueConstraint.
+ *
+ * @param sig If true will show the attribute type and initial value.
+ * @return Returns a string representation of the UMLAttribute.
+ */
+QString UMLUniqueConstraint::toString(Uml::SignatureType::Enum sig)
+{
+ QString s;
+
+ if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::SigNoVis) {
+ s = name() + QLatin1Char(':');
+
+ if (static_cast<UMLEntity*>(parent())->isPrimaryKey(this)) {
+ s += QLatin1String("Primary Key (");
+ } else {
+ s += QLatin1String("Unique (");
+ }
+
+ bool first = true;
+ foreach(UMLEntityAttribute* att, m_EntityAttributeList) {
+ if (first) {
+ first = false;
+ } else
+ s += QLatin1Char(',');
+ s += att->name();
+ }
+ s += QLatin1Char(')') ;
+ }
+
+ return s;
+}
+
+QString UMLUniqueConstraint::getFullyQualifiedName(const QString& separator,
+ bool includeRoot) const
+{
+ Q_UNUSED(separator); Q_UNUSED(includeRoot);
+ return this->name();
+}
+
+/**
+ * Creates the <UML:UniqueConstraint> XMI element.
+ */
+void UMLUniqueConstraint::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement uniqueConstraintElement = UMLObject::save(QLatin1String("UML:UniqueConstraint"), qDoc);
+
+ UMLEntity* parentEnt = static_cast<UMLEntity*>(parent());
+ if (parentEnt->isPrimaryKey(this)) {
+ uniqueConstraintElement.setAttribute(QLatin1String("isPrimary"), QLatin1String("1"));
+ } else {
+ uniqueConstraintElement.setAttribute(QLatin1String("isPrimary"), QLatin1String("0"));
+ }
+
+ foreach(UMLEntityAttribute* att, m_EntityAttributeList) {
+ att->saveToXMI(qDoc, uniqueConstraintElement);
+ }
+
+ qElement.appendChild(uniqueConstraintElement);
+}
+
+/**
+ * Display the properties configuration dialog for the attribute.
+ */
+bool UMLUniqueConstraint::showPropertiesDialog(QWidget* parent)
+{
+ UMLUniqueConstraintDialog dialog(parent, this);
+ return dialog.exec();
+}
+
+/**
+ * Loads the <UML:UniqueConstraint> XMI element.
+ */
+bool UMLUniqueConstraint::load(QDomElement & element)
+{
+ int isPrimary = element.attribute(QLatin1String("isPrimary"), QLatin1String("0")).toInt();
+ UMLEntity* parentEnt = static_cast<UMLEntity*>(parent());
+
+ if (isPrimary == 1) {
+ parentEnt->setAsPrimaryKey(this);
+ }
+
+ QDomNode node = element.firstChild();
+ while (!node.isNull()) {
+ if (node.isComment()) {
+ node = node.nextSibling();
+ continue;
+ }
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (UMLDoc::tagEq(tag, QLatin1String("EntityAttribute"))) {
+
+ QString attName = tempElement.attribute(QLatin1String("name"));
+ UMLObject* obj = parentEnt->findChildObject(attName);
+
+ UMLEntityAttribute* entAtt = static_cast<UMLEntityAttribute*>(obj);
+ if (entAtt == NULL)
+ continue;
+
+ m_EntityAttributeList.append(entAtt);
+
+ } else {
+ uWarning() << "unknown child type in UMLUniqueConstraint::load";
+ }
+
+ node = node.nextSibling();
+ }
+
+ return true;
+}
+
+
+/**
+ * Check if a entity attribute is present in m_entityAttributeList
+ *
+ * @param attr The Entity Attribute to check for existence in list
+ * @return true if it exists in the list, else false
+ */
+bool UMLUniqueConstraint::hasEntityAttribute(UMLEntityAttribute* attr)
+{
+ if (m_EntityAttributeList.indexOf(attr) == -1) {
+ //not present
+ return false;
+ }
+
+ // else present
+ return true;
+}
+
+/**
+ * Adds a UMLEntityAttribute to the list.
+ * The UMLEntityAttribute should already exist and should
+ * belong to the parent UMLEntity.
+ *
+ * @param attr The UMLEntityAttribute to add
+ * @return false if it failed to add, else true
+ */
+bool UMLUniqueConstraint::addEntityAttribute(UMLEntityAttribute* attr)
+{
+ UMLEntity *owningParent = dynamic_cast<UMLEntity*>(parent());
+
+ if (hasEntityAttribute(attr)) {
+ uDebug() << "Unique Constraint already contains" << attr->name();
+ return false;
+
+ }
+ if (owningParent == NULL) {
+ uError() << name() << ": parent is not a UMLEntity";
+ return false;
+ }
+
+ if (owningParent->findChildObjectById(attr->id()) == NULL) {
+ uError()
+ << " parent " << owningParent->name()
+ << " does not contain attribute " << attr->name();
+ return false;
+ }
+
+ //else add the attribute to the Entity Attribute List
+ m_EntityAttributeList.append(attr);
+
+ return true;
+}
+
+/**
+ * Removes a UMLEntityAttribute from the list
+ *
+ * @param attr The UMLEntityAttribute to remove from list
+ * @return false if it failed to remove the attribute from the list
+ */
+bool UMLUniqueConstraint::removeEntityAttribute(UMLEntityAttribute* attr)
+{
+ UMLEntity *owningParent = dynamic_cast<UMLEntity*>(parent());
+
+ if (owningParent == NULL) {
+ uError() << name() << ": parent is not a UMLEntity";
+ return false;
+ }
+
+ /*
+ * The attribute may already be removed from the Entity when this function
+ * is called. So checking this is not right
+ *
+ * if (owningParent->findChildObjectById(attr->ID()) == NULL) {
+ * uError()
+ * << " parent " << owningParent->getName()
+ * << " does not contain attribute " << attr->getName();
+ * return false;
+ * }
+ */
+
+ //else remove the attribute from the Entity Attribute List
+ if (m_EntityAttributeList.removeAll(attr)) {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Get the Entity Attributes List.
+ */
+UMLEntityAttributeList UMLUniqueConstraint::getEntityAttributeList() const
+{
+ return m_EntityAttributeList;
+}
+
+void UMLUniqueConstraint::init()
+{
+ m_BaseType = UMLObject::ot_UniqueConstraint;
+}
+
+/**
+ * Clear the list of attributes contained in this UniqueConstraint
+ */
+void UMLUniqueConstraint::clearAttributeList()
+{
+ m_EntityAttributeList.clear();
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/uniqueconstraint.h umbrello-kf6-15.08.1/umbrello/umlmodel/uniqueconstraint.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/uniqueconstraint.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/uniqueconstraint.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,77 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UNIQUECONSTRAINT_H
+#define UNIQUECONSTRAINT_H
+
+#include "basictypes.h"
+#include "classifierlistitem.h"
+#include "entityconstraint.h"
+#include "umlclassifierlist.h"
+#include "umlentityattributelist.h"
+
+/**
+ * This class is used to set up information for a unique entity constraint.
+ *
+ * @short Sets up Unique entity constraint information.
+ * @author Sharan Rao
+ * @see UMLObject UMLClassifierListItem UMLEntityConstraint
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLUniqueConstraint : public UMLEntityConstraint
+{
+public:
+
+ UMLUniqueConstraint(UMLObject *parent, const QString& name,
+ Uml::ID::Type id = Uml::ID::None);
+ explicit UMLUniqueConstraint(UMLObject *parent);
+ virtual ~UMLUniqueConstraint();
+
+ bool operator==(const UMLUniqueConstraint &rhs) const;
+
+ virtual void copyInto(UMLObject *lhs) const;
+
+ virtual UMLObject* clone() const;
+
+ QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
+
+ QString getFullyQualifiedName(const QString& separator = QString(),
+ bool includeRoot = false) const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ virtual bool showPropertiesDialog(QWidget* parent = 0);
+
+ bool hasEntityAttribute(UMLEntityAttribute* attr);
+
+ bool addEntityAttribute(UMLEntityAttribute* attr);
+
+ bool removeEntityAttribute(UMLEntityAttribute* attr);
+
+ UMLEntityAttributeList getEntityAttributeList() const;
+
+ void clearAttributeList();
+
+protected:
+
+ bool load(QDomElement & element);
+
+private:
+
+ void init();
+
+ /**
+ * The list of entity attributes that together make up the unique constraint.
+ */
+ UMLEntityAttributeList m_EntityAttributeList;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/usecase.cpp umbrello-kf6-15.08.1/umbrello/umlmodel/usecase.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/usecase.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/usecase.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "usecase.h"
+
+/**
+ * Creates a UseCase object
+ *
+ * @param name The name of the object.
+ * @param id The id of the object.
+ */
+UMLUseCase::UMLUseCase(const QString & name, Uml::ID::Type id)
+ : UMLCanvasObject(name, id)
+{
+ init();
+}
+
+/**
+ * Standard decstructor.
+ */
+UMLUseCase::~UMLUseCase()
+{
+}
+
+/**
+ * Initializes key variables of the class.
+ */
+void UMLUseCase::init()
+{
+ m_BaseType = UMLObject::ot_UseCase;
+}
+
+/**
+ * Make a clone of this object.
+ */
+UMLObject* UMLUseCase::clone() const
+{
+ UMLUseCase *clone = new UMLUseCase();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+/**
+ * Creates the <UML:UseCase> element.
+ */
+void UMLUseCase::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement usecaseElement = UMLObject::save(QLatin1String("UML:UseCase"), qDoc);
+ qElement.appendChild(usecaseElement);
+}
+
+/**
+ * Loads the <UML:UseCase> element (TODO).
+ */
+bool UMLUseCase::load(QDomElement&)
+{
+ return true;
+}
+
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlmodel/usecase.h umbrello-kf6-15.08.1/umbrello/umlmodel/usecase.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlmodel/usecase.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlmodel/usecase.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef USECASE_H
+#define USECASE_H
+
+#include "umlcanvasobject.h"
+
+/**
+ * This class contains the non-graphical information required for a UML UseCase.
+ * This class inherits from @ref UMLCanvasObject which contains most of the information.
+ *
+ * @short Information for a non-graphical UML UseCase.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLUseCase : public UMLCanvasObject
+{
+public:
+ explicit UMLUseCase(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
+ ~UMLUseCase();
+
+ virtual void init();
+
+ virtual UMLObject* clone() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+protected:
+ bool load(QDomElement & element);
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlobject.cpp umbrello-kf6-15.08.1/umbrello/umlobject.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlobject.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlobject.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,1142 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "umlobject.h"
-
-// app includes
-#include "classpropertiesdialog.h"
-#include "debug_utils.h"
-#include "enumliteral.h"
-#include "uniqueid.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umllistview.h"
-#include "package.h"
-#include "folder.h"
-#include "stereotype.h"
-#include "object_factory.h"
-#include "model_utils.h"
-#include "import_utils.h"
-#include "docwindow.h"
-#include "cmds.h"
-
-// kde includes
-#include <KLocalizedString>
-
-// qt includes
-#include <QApplication>
-#include <QPointer>
-
-using namespace Uml;
-
-DEBUG_REGISTER_DISABLED(UMLObject)
-
-/**
- * Creates a UMLObject.
- * @param other object to created from
- */
-UMLObject::UMLObject(const UMLObject &other)
- : QObject(other.parent())
-{
- other.copyInto(this);
-}
-
-/**
- * Creates a UMLObject.
- * @param parent The parent of the object.
- * @param name The name of the object.
- * @param id The ID of the object (optional.) If omitted
- * then a new ID will be assigned internally.
- */
-UMLObject::UMLObject(UMLObject* parent, const QString& name, ID::Type id)
- : QObject(parent),
- m_nId(id),
- m_name(name)
-{
- init();
- if (id == Uml::ID::None)
- m_nId = UniqueID::gen();
-}
-
-/**
- * Creates a UMLObject.
- * @param name The name of the object.
- * @param id The ID of the object (optional.) If omitted
- * then a new ID will be assigned internally.
- */
-UMLObject::UMLObject(const QString& name, ID::Type id)
- : QObject(UMLApp::app()->document()),
- m_nId(id),
- m_name(name)
-{
- init();
- if (id == Uml::ID::None)
- m_nId = UniqueID::gen();
-}
-
-/**
- * Creates a UMLObject.
- * @param parent The parent of the object.
- */
-UMLObject::UMLObject(UMLObject * parent)
- : QObject(parent),
- m_nId(Uml::ID::None),
- m_name(QString())
-{
- init();
-}
-
-/**
- * Standard destructor.
- */
-UMLObject::~UMLObject()
-{
-}
-
-/**
- * Initializes key variables of the class.
- */
-void UMLObject::init()
-{
- setObjectName(QLatin1String("UMLObject"));
- m_BaseType = ot_UMLObject;
- m_pUMLPackage = 0;
- m_visibility = Uml::Visibility::Public;
- m_pStereotype = 0;
- m_Doc.clear();
- m_bAbstract = false;
- m_bStatic = false;
- m_bCreationWasSignalled = false;
- m_pSecondary = 0;
-}
-
-/**
- * Display the properties configuration dialog for the object.
- *
- * @param parent The parent widget.
- * @return True for success of this operation.
- */
-bool UMLObject::showPropertiesDialog(QWidget *parent)
-{
- DocWindow *docwindow = UMLApp::app()->docWindow();
- docwindow->updateDocumentation(false);
- QPointer<ClassPropertiesDialog> dlg = new ClassPropertiesDialog(parent, this, false);
- bool modified = false;
- if (dlg->exec()) {
- docwindow->showDocumentation(this, true);
- UMLApp::app()->document()->setModified(true);
- modified = true;
- }
- dlg->close();
- delete dlg;
- return modified;
-}
-
-/**
- * This should be reimplemented by subclasses if they wish to
- * accept certain types of associations. Note that this only
- * tells if this UMLObject can accept the association
- * type. When creating an association another check is made to
- * see if the association is valid. For example a UMLClass
- * (UMLClassifier) can accept generalizations and should
- * return true. If while creating a generalization the
- * superclass is already subclassed from this, the association
- * is not valid and will not be created. The default accepts
- * nothing (returns false)
- */
-bool UMLObject::acceptAssociationType(Uml::AssociationType::Enum type)
-{
- Q_UNUSED(type);
- // A UMLObject accepts nothing. This should be reimplemented by the subclasses
- return false;
-}
-
-/**
- * Assigns a new Id to the object
- */
-void UMLObject::setID(ID::Type NewID)
-{
- m_nId = NewID;
- emitModified();
-}
-
-/**
- * Set the UMLObject's name
- */
-void UMLObject::setName(const QString &strName)
-{
- if (name() != strName) {
- UMLApp::app()->executeCommand(new Uml::CmdRenameUMLObject(this, strName));
- }
-}
-
-/**
- * Method used by setName: it is called by cmdSetName, Don't use it!
- */
-void UMLObject::setNameCmd(const QString &strName)
-{
- m_name = strName;
- emitModified();
-}
-
-/**
- * Returns a copy of m_name
- */
-QString UMLObject::name() const
-{
- return m_name;
-}
-
-/**
- * Returns the fully qualified name, i.e. all package prefixes and then m_name.
- *
- * @param separator The separator string to use (optional.)
- * If not given then the separator is chosen according
- * to the currently selected active programming language
- * of import and code generation.
- * @param includeRoot Whether to prefix the root folder name to the FQN.
- * See UMLDoc::getRootFolder(). Default: false.
- * @return The fully qualified name of this UMLObject.
- */
-QString UMLObject::fullyQualifiedName(const QString& separator,
- bool includeRoot /* = false */) const
-{
- QString fqn;
- if (m_pUMLPackage && m_pUMLPackage != this) {
- bool skipPackage = false;
- if (!includeRoot) {
- UMLDoc *umldoc = UMLApp::app()->document();
- if (umldoc->rootFolderType(m_pUMLPackage) != Uml::ModelType::N_MODELTYPES ||
- m_pUMLPackage == umldoc->datatypeFolder())
- skipPackage = true;
- }
- if (!skipPackage) {
- QString tempSeparator = separator;
- if (tempSeparator.isEmpty())
- tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
- fqn = m_pUMLPackage->fullyQualifiedName(tempSeparator, includeRoot);
- fqn.append(tempSeparator);
- }
- }
- fqn.append(m_name);
- return fqn;
-}
-
-/**
- * Overloaded '==' operator
- */
-bool UMLObject::operator==(const UMLObject & rhs) const
-{
- if (this == &rhs)
- return true;
-
- //don't compare IDs, these are program specific and
- //don't mean the objects are the same
- //***** CHECK: Who put in this comment? What was the reason?
- //***** Currently some operator== in umbrello-kf6 compare the IDs
- //***** while others don't.
-
- if (m_name != rhs.m_name)
- return false;
-
- // Packages create different namespaces, therefore they should be
- // part of the equality test.
- if (m_pUMLPackage != rhs.m_pUMLPackage)
- return false;
-
- // Making the type part of an object's identity has its problems:
- // Not all programming languages support declarations of the same
- // name but different type.
- // In such cases, the code generator is responsible for generating
- // the appropriate error message.
- if (m_BaseType != rhs.m_BaseType)
- return false;
-
- // The documentation should not be part of the equality test.
- // If two objects are the same but differ only in their documentation,
- // what does that mean?
- //if(m_Doc != rhs.m_Doc)
- // return false;
-
- // The visibility should not be part of the equality test.
- // What does it mean if two objects are the same but differ in their
- // visibility? - I'm not aware of any programming language that would
- // support that.
- //if(m_visibility != rhs.m_visibility)
- // return false;
-
- // See comments above
- //if(m_pStereotype != rhs.m_pStereotype)
- // return false;
-
- // See comments above
- //if(m_bAbstract != rhs.m_bAbstract)
- // return false;
-
- // See comments above
- //if(m_bStatic != rhs.m_bStatic)
- // return false;
-
- return true;
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLObject::copyInto(UMLObject *lhs) const
-{
- // Data members with copy constructor
- lhs->m_Doc = m_Doc;
- lhs->m_pStereotype = m_pStereotype;
- lhs->m_bAbstract = m_bAbstract;
- lhs->m_bStatic = m_bStatic;
- lhs->m_BaseType = m_BaseType;
- lhs->m_visibility = m_visibility;
- lhs->m_pUMLPackage = m_pUMLPackage;
-
- // We don't want the same name existing twice.
- lhs->m_name = Model_Utils::uniqObjectName(m_BaseType, m_pUMLPackage, m_name);
-
- // Create a new ID.
- lhs->m_nId = UniqueID::gen();
-
- // Hope that the parent from QObject is okay.
- if (lhs->parent() != parent())
- uDebug() << "copyInto has a wrong parent";
-}
-
-UMLObject *UMLObject::clone() const
-{
- UMLObject *clone = new UMLObject;
- UMLObject::copyInto(clone);
- return clone;
-}
-
-/**
- * Returns the abstract state of the object.
- */
-bool UMLObject::isAbstract() const
-{
- return m_bAbstract;
-}
-
-/**
- * Sets the paste state of the object.
- */
-void UMLObject::setAbstract(bool bAbstract)
-{
- m_bAbstract = bAbstract;
- emitModified();
-}
-
-/**
- * Returns true if this UMLObject has classifier scope,
- * otherwise false (the default).
- */
-bool UMLObject::isStatic() const
-{
- return m_bStatic;
-}
-
-/**
- * Sets the value for m_bStatic.
- */
-void UMLObject::setStatic(bool bStatic)
-{
- m_bStatic = bStatic;
- emitModified();
-}
-
-/**
- * Forces the emission of the modified signal. Useful when
- * updating several attributes at a time: you can block the
- * signals, update all atts, and then force the signal.
- */
-void UMLObject::emitModified()
-{
- UMLDoc *umldoc = UMLApp::app()->document();
- if (!umldoc->loading() && !umldoc->closing())
- emit modified();
-}
-
-/**
- * Returns the type of the object.
- *
- * @return Returns the type of the object.
- */
-UMLObject::ObjectType UMLObject::baseType() const
-{
- return m_BaseType;
-}
-
-/**
- * @return The type used for rtti as string.
- */
-QLatin1String UMLObject::baseTypeStr() const
-{
- return QLatin1String(ENUM_NAME(UMLObject, ObjectType, m_BaseType));
-}
-
-/**
- * Set the type of the object.
- *
- * @param ot The ObjectType to set.
- */
-void UMLObject::setBaseType(ObjectType ot)
-{
- m_BaseType = ot;
-}
-
-/**
- * Returns the ID of the object.
- *
- * @return Returns the ID of the object.
- */
-ID::Type UMLObject::id() const
-{
- return m_nId;
-}
-
-/**
- * Returns the documentation for the object.
- *
- * @return Returns the documentation for the object.
- */
-QString UMLObject::doc() const
-{
- return m_Doc;
-}
-
-/**
- * Returns state of documentation for the object.
- *
- * @return false if documentation is empty
- */
-bool UMLObject::hasDoc() const
-{
- return !m_Doc.isEmpty();
-}
-
-/**
- * Sets the documentation for the object.
- *
- * @param d The documentation for the object.
- */
-void UMLObject::setDoc(const QString &d)
-{
- m_Doc = d;
- //emit modified(); No, this is done centrally at DocWindow::updateDocumentation()
-}
-
-/**
- * Returns the visibility of the object.
- *
- * @return Returns the visibility of the object.
- */
-Visibility::Enum UMLObject::visibility() const
-{
- return m_visibility;
-}
-
-/**
- * Sets the visibility of the object.
- *
- * @param visibility The visibility of the object.
- */
-void UMLObject::setVisibility(Visibility::Enum visibility)
-{
- if (m_visibility != visibility) {
- UMLApp::app()->executeCommand(new CmdSetVisibility(this, visibility));
- }
-}
-
-/**
- * Method used by setVisibility: it is called by cmdSetVisibility, Don't use it!
- */
-void UMLObject::setVisibilityCmd(Visibility::Enum visibility)
-{
- m_visibility = visibility;
- emitModified();
-}
-
-/**
- * Sets the class' UMLStereotype. Adjusts the reference counts
- * at the previously set stereotype and at the new stereotype.
- * If the previously set UMLStereotype's reference count drops
- * to zero then the UMLStereotype is removed at the UMLDoc and
- * it is then physically deleted.
- *
- * @param stereo Sets the classes UMLStereotype.
- */
-void UMLObject::setUMLStereotype(UMLStereotype *stereo)
-{
- if (stereo == m_pStereotype)
- return;
- if (stereo) {
- stereo->incrRefCount();
- }
- if (m_pStereotype) {
- m_pStereotype->decrRefCount();
- if (m_pStereotype->refCount() == 0) {
- UMLDoc *pDoc = UMLApp::app()->document();
- pDoc->removeStereotype(m_pStereotype);
- delete m_pStereotype;
- }
- }
- m_pStereotype = stereo;
- // TODO: don't emit modified() if predefined folder
- emitModified();
-}
-
-/**
- * Sets the classes stereotype name.
- * Internally uses setUMLStereotype().
- *
- * @param name Sets the classes stereotype name.
- */
-void UMLObject::setStereotype(const QString &name)
-{
- if (name != stereotype()) {
- UMLApp::app()->executeCommand(new CmdSetStereotype(this, name));
- }
-}
-
-void UMLObject::setStereotypeCmd(const QString& name)
-{
- if (name.isEmpty()) {
- setUMLStereotype(NULL);
- return;
- }
- UMLDoc *pDoc = UMLApp::app()->document();
- UMLStereotype *s = pDoc->findOrCreateStereotype(name);
- setUMLStereotype(s);
-}
-
-/**
- * Sets the UMLPackage in which this class is located.
- *
- * @param pPkg Pointer to the class' UMLPackage.
- */
-bool UMLObject::setUMLPackage(UMLPackage* pPkg)
-{
- if (pPkg == this) {
- uDebug() << "setting parent to myself is not allowed";
- return false;
- }
-
- if (pPkg == NULL) {
- // Allow setting to NULL for stereotypes
- m_pUMLPackage = pPkg;
- return true;
- }
-
- if (pPkg->umlPackage() == this) {
- uDebug() << "setting parent to an object of which I'm already the parent is not allowed";
- return false;
- }
-
- m_pUMLPackage = pPkg;
- emitModified();
- return true;
-}
-
-/**
- * Returns the classes UMLStereotype object.
- *
- * @return Returns the classes UMLStereotype object.
- */
-UMLStereotype * UMLObject::umlStereotype()
-{
- return m_pStereotype;
-}
-
-/**
- * Returns the stereotype.
- */
-QString UMLObject::stereotype(bool includeAdornments /* = false */) const
-{
- if (m_pStereotype == NULL)
- return QString();
- return m_pStereotype->name(includeAdornments);
-}
-
-/**
- * Return the package(s) in which this UMLObject is contained
- * as a text.
- *
- * @param separator Separator string for joining together the
- * individual package prefixes (optional.)
- * If no separator is given then the separator
- * of the currently selected language is used.
- * @param includeRoot Whether to prefix the root folder name.
- * Default: false.
- * @return The UMLObject's enclosing package(s) as a text.
- */
-QString UMLObject::package(const QString& separator, bool includeRoot)
-{
- QString tempSeparator = separator;
- if (tempSeparator.isEmpty())
- tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
- QString fqn = fullyQualifiedName(tempSeparator, includeRoot);
- if (!fqn.contains(tempSeparator))
- return QString();
- QString scope = fqn.left(fqn.length() - tempSeparator.length() - m_name.length());
- return scope;
-}
-
-/**
- * Return a list of the packages in which this class is embedded.
- * The outermost package is first in the list.
- *
- * @param includeRoot Whether to prefix the root folder name.
- * Default: false.
- * @return UMLPackageList of the containing packages.
- */
-UMLPackageList UMLObject::packages(bool includeRoot) const
-{
- UMLPackageList pkgList;
- UMLPackage* pkg = m_pUMLPackage;
- while (pkg != NULL) {
- pkgList.prepend(pkg);
- pkg = pkg->umlPackage();
- }
- if (!includeRoot)
- pkgList.removeFirst();
- return pkgList;
-}
-
-/**
- * Returns the UMLPackage that this class is located in.
- *
- * @return Pointer to the UMLPackage of this class.
- */
-UMLPackage* UMLObject::umlPackage()
-{
- return m_pUMLPackage;
-}
-
-/**
- * Return secondary ID. Required by resolveRef().
- */
-QString UMLObject::secondaryId() const
-{
- return m_SecondaryId;
-}
-
-/**
- * Set the secondary ID.
- * Currently only required by petalTree2Uml(); all other setting of the
- * m_SecondaryID is internal to the UMLObject class hierarchy.
- */
-void UMLObject::setSecondaryId(const QString& id)
-{
- m_SecondaryId = id;
-}
-
-/**
- * Return secondary ID fallback.
- * Required by resolveRef() for imported model files.
- */
-QString UMLObject::secondaryFallback() const
-{
- return m_SecondaryFallback;
-}
-
-/**
- * Set the secondary ID fallback.
- * Currently only used by petalTree2Uml().
- */
-void UMLObject::setSecondaryFallback(const QString& id)
-{
- m_SecondaryFallback = id;
-}
-
-/**
- * Calls UMLDoc::signalUMLObjectCreated() if m_BaseType affords
- * doing so.
- */
-void UMLObject::maybeSignalObjectCreated()
-{
- if (!m_bCreationWasSignalled &&
- m_BaseType != ot_Stereotype &&
- m_BaseType != ot_Association &&
- m_BaseType != ot_Role) {
- m_bCreationWasSignalled = true;
- UMLDoc* umldoc = UMLApp::app()->document();
- umldoc->signalUMLObjectCreated(this);
- }
-}
-
-/**
- * Resolve referenced objects (if any.)
- * Needs to be called after all UML objects are loaded from file.
- * This needs to be done after all model objects are loaded because
- * some of the xmi.id's might be forward references, i.e. they may
- * identify model objects which were not yet loaded at the point of
- * reference.
- * The default implementation attempts resolution of the m_SecondaryId.
- *
- * @return True for success.
- */
-bool UMLObject::resolveRef()
-{
- if (m_pSecondary || (m_SecondaryId.isEmpty() && m_SecondaryFallback.isEmpty())) {
- maybeSignalObjectCreated();
- return true;
- }
-#ifdef VERBOSE_DEBUGGING
- uDebug() << m_name << ": m_SecondaryId is " << m_SecondaryId;
-#endif
- UMLDoc *pDoc = UMLApp::app()->document();
- // In the new, XMI standard compliant save format,
- // the type is the xmi.id of a UMLClassifier.
- if (! m_SecondaryId.isEmpty()) {
- m_pSecondary = pDoc->findObjectById(Uml::ID::fromString(m_SecondaryId));
- if (m_pSecondary != NULL) {
- if (m_pSecondary->baseType() == ot_Stereotype) {
- m_pStereotype = dynamic_cast<UMLStereotype*>(m_pSecondary.data());
- m_pStereotype->incrRefCount();
- m_pSecondary = NULL;
- }
- m_SecondaryId = QString();
- maybeSignalObjectCreated();
- return true;
- }
- if (m_SecondaryFallback.isEmpty()) {
- uDebug() << "object with xmi.id=" << m_SecondaryId << " not found, setting to undef";
- UMLFolder *datatypes = pDoc->datatypeFolder();
- m_pSecondary = Object_Factory::createUMLObject(ot_Datatype, QLatin1String("undef"), datatypes, false);
- return true;
- }
- }
- if (m_SecondaryFallback.isEmpty()) {
- uError() << m_name << ": cannot find type with id " << m_SecondaryId;
- return false;
- }
-#ifdef VERBOSE_DEBUGGING
- uDebug() << m_name << ": could not resolve secondary ID " << m_SecondaryId
- << ", using secondary fallback " << m_SecondaryFallback;
-#endif
- m_SecondaryId = m_SecondaryFallback;
- // Assume we're dealing with the older umbrello-kf6 format where
- // the type name was saved in the "type" attribute rather
- // than the xmi.id of the model object of the attribute type.
- m_pSecondary = pDoc->findUMLObject(m_SecondaryId, ot_UMLObject, this);
- if (m_pSecondary) {
- m_SecondaryId = QString();
- maybeSignalObjectCreated();
- return true;
- }
- // Work around Object_Factory::createUMLObject()'s incapability
- // of on-the-fly scope creation:
- if (m_SecondaryId.contains(QLatin1String("::"))) {
- // TODO: Merge Import_Utils::createUMLObject() into Object_Factory::createUMLObject()
- m_pSecondary = Import_Utils::createUMLObject(ot_UMLObject, m_SecondaryId, m_pUMLPackage);
- if (m_pSecondary) {
- if (Import_Utils::newUMLObjectWasCreated()) {
- maybeSignalObjectCreated();
- qApp->processEvents();
- uDebug() << "Import_Utils::createUMLObject() created a new type for "
- << m_SecondaryId;
- } else {
- uDebug() << "Import_Utils::createUMLObject() returned an existing type for "
- << m_SecondaryId;
- }
- m_SecondaryId = QString();
- return true;
- }
- uError() << "Import_Utils::createUMLObject() failed to create a new type for "
- << m_SecondaryId;
- return false;
- }
- uDebug() << "Creating new type for " << m_SecondaryId;
- // This is very C++ specific - we rely on some '*' or
- // '&' to decide it's a ref type. Plus, we don't recognize
- // typedefs of ref types.
- bool isReferenceType = (m_SecondaryId.contains(QLatin1Char('*')) ||
- m_SecondaryId.contains(QLatin1Char('&')));
- ObjectType ot = ot_Class;
- if (isReferenceType) {
- ot = ot_Datatype;
- } else {
- if (Model_Utils::isCommonDataType(m_SecondaryId))
- ot = ot_Datatype;
- }
- m_pSecondary = Object_Factory::createUMLObject(ot, m_SecondaryId, NULL);
- if (m_pSecondary == NULL)
- return false;
- m_SecondaryId = QString();
- maybeSignalObjectCreated();
- //qApp->processEvents();
- return true;
-}
-
-void UMLObject::saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
-{
- Q_UNUSED(qDoc); Q_UNUSED(qElement);
-}
-
-/**
- * Auxiliary to saveToXMI.
- * Create a QDomElement with the given tag, and save the XMI attributes
- * that are common to all child classes to the newly created element.
- * This method does not need to be overridden by child classes.
- */
-QDomElement UMLObject::save(const QString &tag, QDomDocument & qDoc)
-{
- /*
- Call as the first action of saveToXMI() in child class:
- This creates the QDomElement with which to work.
- */
- QDomElement qElement = qDoc.createElement(tag);
- qElement.setAttribute(QLatin1String("isSpecification"), QLatin1String("false"));
- if (m_BaseType != ot_Association &&
- m_BaseType != ot_Role &&
- m_BaseType != ot_Attribute) {
- qElement.setAttribute(QLatin1String("isLeaf"), QLatin1String("false"));
- qElement.setAttribute(QLatin1String("isRoot"), QLatin1String("false"));
- if (m_bAbstract)
- qElement.setAttribute(QLatin1String("isAbstract"), QLatin1String("true"));
- else
- qElement.setAttribute(QLatin1String("isAbstract"), QLatin1String("false"));
- }
- qElement.setAttribute(QLatin1String("xmi.id"), Uml::ID::toString(m_nId));
- qElement.setAttribute(QLatin1String("name"), m_name);
- if (m_BaseType != ot_Operation &&
- m_BaseType != ot_Role &&
- m_BaseType != ot_Attribute) {
- Uml::ID::Type nmSpc;
- if (m_pUMLPackage)
- nmSpc = m_pUMLPackage->id();
- else
- nmSpc = UMLApp::app()->document()->modelID();
- qElement.setAttribute(QLatin1String("namespace"), Uml::ID::toString(nmSpc));
- }
- if (! m_Doc.isEmpty())
- qElement.setAttribute(QLatin1String("comment"), m_Doc); //CHECK: uml13.dtd compliance
-#ifdef XMI_FLAT_PACKAGES
- if (m_pUMLPackage) //FIXME: uml13.dtd compliance
- qElement.setAttribute(QLatin1String("package"), m_pUMLPackage->ID());
-#endif
- QString visibility = Uml::Visibility::toString(m_visibility, false);
- qElement.setAttribute(QLatin1String("visibility"), visibility);
- if (m_pStereotype != NULL)
- qElement.setAttribute(QLatin1String("stereotype"), Uml::ID::toString(m_pStereotype->id()));
- if (m_bStatic)
- qElement.setAttribute(QLatin1String("ownerScope"), QLatin1String("classifier"));
- /* else
- qElement.setAttribute("ownerScope", "instance");
- *** ownerScope defaults to instance if not set **********/
- return qElement;
-}
-
-/**
- * Auxiliary to loadFromXMI.
- * This method is usually overridden by child classes.
- * It is responsible for loading the specific XMI structure
- * of the child class.
- */
-bool UMLObject::load(QDomElement&)
-{
- // This body is not usually executed because child classes
- // overwrite the load method.
- return true;
-}
-
-/**
- * Analyzes the given QDomElement for a reference to a stereotype.
- *
- * @param element QDomElement to analyze.
- * @return True if a stereotype reference was found, else false.
- */
-bool UMLObject::loadStereotype(QDomElement & element)
-{
- QString tag = element.tagName();
- if (!UMLDoc::tagEq(tag, QLatin1String("stereotype")))
- return false;
- QString stereo = element.attribute(QLatin1String("xmi.value"));
- if (stereo.isEmpty() && element.hasChildNodes()) {
- /* like so:
- <UML:ModelElement.stereotype>
- <UML:Stereotype xmi.idref = '07CD'/>
- </UML:ModelElement.stereotype>
- */
- QDomNode stereoNode = element.firstChild();
- QDomElement stereoElem = stereoNode.toElement();
- tag = stereoElem.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("Stereotype"))) {
- stereo = stereoElem.attribute(QLatin1String("xmi.idref"));
- }
- }
- if (stereo.isEmpty())
- return false;
- Uml::ID::Type stereoID = Uml::ID::fromString(stereo);
- UMLDoc *pDoc = UMLApp::app()->document();
- m_pStereotype = pDoc->findStereotypeById(stereoID);
- if (m_pStereotype)
- m_pStereotype->incrRefCount();
- else
- m_SecondaryId = stereo; // leave it to resolveRef()
- return true;
-}
-
-/**
- * This method loads the generic parts of the XMI common to most model
- * classes. It is not usually reimplemented by child classes.
- * Instead, it invokes the load() method which implements the loading
- * of the specifics of each child class.
- *
- * @param element The QDomElement from which to load.
- */
-bool UMLObject::loadFromXMI(QDomElement & element)
-{
- UMLDoc* umldoc = UMLApp::app()->document();
- if (umldoc == 0) {
- uError() << "umldoc is NULL";
- return false;
- }
- // Read the name first so that if we encounter a problem, the error
- // message can say the name.
- m_name = element.attribute(QLatin1String("name"));
- QString id = Model_Utils::getXmiId(element);
- if (id.isEmpty() || id == QLatin1String("-1")) {
- // Before version 1.4, umbrello-kf6 did not save the xmi.id of UMLRole objects.
- // Some tools (such as Embarcadero's) do not have an xmi.id on all attributes.
- m_nId = UniqueID::gen();
- uWarning() << m_name << ": xmi.id not present, generating a new one";
- } else {
- Uml::ID::Type nId = Uml::ID::fromString(id);
- if (m_BaseType == ot_Role) {
- // Some older umbrello-kf6 versions had a problem with xmi.id's
- // of other objects being reused for the UMLRole, see e.g.
- // attachment 21179 at http://bugs.kde.org/147988 .
- // If the xmi.id is already being used then we generate a new one.
- UMLObject *o = umldoc->findObjectById(nId);
- if (o) {
- uError() << "loadFromXMI(UMLRole): id " << id
- << " is already in use!!! Please fix your XMI file.";
- }
- }
- m_nId = nId;
- }
-
- if (element.hasAttribute(QLatin1String("documentation"))) // for bkwd compat.
- m_Doc = element.attribute(QLatin1String("documentation"));
- else
- m_Doc = element.attribute(QLatin1String("comment")); //CHECK: need a UML:Comment?
-
- m_visibility = Uml::Visibility::Public;
- if (element.hasAttribute(QLatin1String("scope"))) { // for bkwd compat.
- QString scope = element.attribute(QLatin1String("scope"));
- if (scope == QLatin1String("instance_level")) // nsuml compat.
- m_bStatic = false;
- else if (scope == QLatin1String("classifier_level")) // nsuml compat.
- m_bStatic = true;
- else {
- int nScope = scope.toInt();
- switch (nScope) {
- case 200:
- m_visibility = Uml::Visibility::Public;
- break;
- case 201:
- m_visibility = Uml::Visibility::Private;
- break;
- case 202:
- m_visibility = Uml::Visibility::Protected;
- break;
- default:
- uError() << m_name << ": illegal scope " << nScope;
- }
- }
- } else {
- QString visibility = element.attribute(QLatin1String("visibility"), QLatin1String("public"));
- if (visibility == QLatin1String("private")
- || visibility == QLatin1String("private_vis")) // for compatibility with other programs
- m_visibility = Uml::Visibility::Private;
- else if (visibility == QLatin1String("protected")
- || visibility == QLatin1String("protected_vis")) // for compatibility with other programs
- m_visibility = Uml::Visibility::Protected;
- else if (visibility == QLatin1String("implementation"))
- m_visibility = Uml::Visibility::Implementation;
- }
-
- QString stereo = element.attribute(QLatin1String("stereotype"));
- if (!stereo.isEmpty()) {
- Uml::ID::Type stereoID = Uml::ID::fromString(stereo);
- m_pStereotype = umldoc->findStereotypeById(stereoID);
- if (m_pStereotype) {
- m_pStereotype->incrRefCount();
- } else {
- uDebug() << m_name << ": UMLStereotype " << Uml::ID::toString(stereoID)
- << " not found, creating now.";
- setStereotypeCmd(stereo);
- }
- }
-
- if (element.hasAttribute(QLatin1String("abstract"))) { // for bkwd compat.
- QString abstract = element.attribute(QLatin1String("abstract"), QLatin1String("0"));
- m_bAbstract = (bool)abstract.toInt();
- } else {
- QString isAbstract = element.attribute(QLatin1String("isAbstract"), QLatin1String("false"));
- m_bAbstract = (isAbstract == QLatin1String("true"));
- }
-
- if (element.hasAttribute(QLatin1String("static"))) { // for bkwd compat.
- QString staticScope = element.attribute(QLatin1String("static"), QLatin1String("0"));
- m_bStatic = (bool)staticScope.toInt();
- } else {
- QString ownerScope = element.attribute(QLatin1String("ownerScope"), QLatin1String("instance"));
- m_bStatic = (ownerScope == QLatin1String("classifier"));
- }
-
- // If the node has child nodes, check whether attributes can be
- // extracted from them.
- if (element.hasChildNodes()) {
- QDomNode node = element.firstChild();
- if (node.isComment())
- node = node.nextSibling();
- QDomElement elem = node.toElement();
- while (!elem.isNull()) {
- QString tag = elem.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("name"))) {
- m_name = elem.attribute(QLatin1String("xmi.value"));
- if (m_name.isEmpty())
- m_name = elem.text();
- } else if (UMLDoc::tagEq(tag, QLatin1String("visibility"))) {
- QString vis = elem.attribute(QLatin1String("xmi.value"));
- if (vis.isEmpty())
- vis = elem.text();
- if (vis == QLatin1String("private") || vis == QLatin1String("private_vis"))
- m_visibility = Uml::Visibility::Private;
- else if (vis == QLatin1String("protected") || vis == QLatin1String("protected_vis"))
- m_visibility = Uml::Visibility::Protected;
- else if (vis == QLatin1String("implementation"))
- m_visibility = Uml::Visibility::Implementation;
- } else if (UMLDoc::tagEq(tag, QLatin1String("isAbstract"))) {
- QString isAbstract = elem.attribute(QLatin1String("xmi.value"));
- if (isAbstract.isEmpty())
- isAbstract = elem.text();
- m_bAbstract = (isAbstract == QLatin1String("true"));
- } else if (UMLDoc::tagEq(tag, QLatin1String("ownerScope"))) {
- QString ownerScope = elem.attribute(QLatin1String("xmi.value"));
- if (ownerScope.isEmpty())
- ownerScope = elem.text();
- m_bStatic = (ownerScope == QLatin1String("classifier"));
- } else {
- loadStereotype(elem);
- }
- node = node.nextSibling();
- if (node.isComment())
- node = node.nextSibling();
- elem = node.toElement();
- }
- }
-
- // Operations, attributes, enum literals, templates, stereotypes,
- // and association role objects get added and signaled elsewhere.
- if (m_BaseType != ot_Operation && m_BaseType != ot_Attribute &&
- m_BaseType != ot_EnumLiteral && m_BaseType != ot_EntityAttribute &&
- m_BaseType != ot_Template && m_BaseType != ot_Stereotype &&
- m_BaseType != ot_Role && m_BaseType != ot_UniqueConstraint &&
- m_BaseType != ot_ForeignKeyConstraint && m_BaseType != ot_CheckConstraint) {
- if (m_pUMLPackage) {
- m_pUMLPackage->addObject(this);
- } else if (umldoc->rootFolderType(this) == Uml::ModelType::N_MODELTYPES) {
- // m_pUMLPackage is not set on the root folders.
- uDebug() << m_name << ": m_pUMLPackage is not set";
- }
- }
- return load(element);
-}
-
-/**
- * Helper function for debug output.
- * Returns the given enum value as string.
- * @param ot ObjectType of which a string representation is wanted
- * @return the ObjectType as string
- */
-QString UMLObject::toString(ObjectType ot)
-{
- return QLatin1String(ENUM_NAME(UMLObject, ObjectType, ot));
-}
-
-/**
- * Returns the given object type value as localized string.
- * @param ot ObjectType of which a string representation is wanted
- * @return the ObjectType as localized string
- */
-QString UMLObject::toI18nString(ObjectType t)
-{
- QString name;
-
- switch (t) {
- case UMLObject::ot_Actor:
- name = i18n("Actor &name:");
- break;
- case UMLObject::ot_Artifact:
- name = i18n("Artifact &name:");
- break;
- case UMLObject::ot_Class:
- name = i18n("Class &name:");
- break;
- case UMLObject::ot_Component:
- name = i18n("Component &name:");
- break;
- case UMLObject::ot_Datatype:
- name = i18n("Datatype &name:");
- break;
- case UMLObject::ot_Entity:
- name = i18n("Entity &name:");
- break;
- case UMLObject::ot_Enum:
- name = i18n("Enum &name:");
- break;
- case UMLObject::ot_Folder:
- name = i18n("Folder &name:");
- break;
- case UMLObject::ot_Interface:
- name = i18n("Interface &name:");
- break;
- case UMLObject::ot_Node:
- name = i18n("Node &name:");
- break;
- case UMLObject::ot_Package:
- name = i18n("Package &name:");
- break;
- case UMLObject::ot_Port:
- name = i18n("Port &name:");
- break;
- case UMLObject::ot_Stereotype:
- name = i18n("Stereotype &name:");
- break;
- case UMLObject::ot_UseCase:
- name = i18n("Use case &name:");
- break;
- default:
- name = QLatin1String("<unknown> &name:");
- uWarning() << "unknown object type";
- break;
- }
- return name;
-}
-
-/**
- * Print UML Object to debug output stream, so it can be used like
- * uDebug() << "This object shouldn't be here: " << illegalObject;
- */
-QDebug operator<<(QDebug out, const UMLObject& obj)
-{
- out.nospace() << "UMLObject: name= " << obj.name()
- << ", type= " << UMLObject::toString(obj.m_BaseType);
- return out.space();
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlobject.h umbrello-kf6-15.08.1/umbrello/umlobject.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlobject.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlobject.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,198 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLOBJECT_H
-#define UMLOBJECT_H
-
-#include "basictypes.h"
-#include "umlpackagelist.h"
-
-//qt includes
-#include <QDomDocument>
-#include <QDomElement>
-#include <QObject>
-#include <QPointer>
-#include <QString>
-
-class UMLStereotype;
-
-/**
- * This class is the non-graphical version of @ref UMLWidget. These are
- * created and maintained in the class @ref UMLDoc. This class holds all
- * the generic information needed for all UML objects.
- *
- * @ref clone needs to be implemented by each child class.
- *
- * @ref saveToXMI saves the XMI attributes of each specific model class.
- * It needs to be implemented by each child class.
- * For creating the QDomElement and saving the common XMI parts,
- * it can use the save() method.
- *
- * @short The base class for UML objects.
- * @author Paul Hensgen <phensgen@techie.com>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLObject : public QObject
-{
- Q_OBJECT
- Q_ENUMS(ObjectType)
-
-public:
- enum ObjectType
- {
- ot_Unknown = -1,
- ot_UMLObject = 100,
- ot_Actor,
- ot_UseCase,
- ot_Package,
- ot_Interface,
- ot_Datatype,
- ot_Enum,
- ot_Class,
- ot_Association,
- ot_Attribute,
- ot_Operation,
- ot_EnumLiteral,
- ot_Template,
- ot_Component,
- ot_Artifact,
- ot_Node,
- ot_Stereotype,
- ot_Role,
- ot_Entity,
- ot_EntityAttribute,
- ot_Folder,
- ot_EntityConstraint,
- ot_UniqueConstraint,
- ot_ForeignKeyConstraint,
- ot_CheckConstraint,
- ot_Category,
- ot_Port
- };
-
- static QString toString(ObjectType ot);
- static QString toI18nString(ObjectType t);
-
- explicit UMLObject(const UMLObject& other);
- explicit UMLObject(UMLObject* parent, const QString& name, Uml::ID::Type id = Uml::ID::None);
- explicit UMLObject(UMLObject* parent);
- explicit UMLObject(const QString& name = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLObject();
-
- bool operator==(const UMLObject & rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- virtual void setBaseType(ObjectType ot);
- ObjectType baseType() const;
- QLatin1String baseTypeStr() const;
-
- virtual void setID(Uml::ID::Type NewID);
- virtual Uml::ID::Type id() const;
-
- QString doc() const;
- bool hasDoc() const;
- void setDoc(const QString &d);
-
- void setVisibility(Uml::Visibility::Enum visibility);
- void setVisibilityCmd(Uml::Visibility::Enum visibility);
- Uml::Visibility::Enum visibility() const;
-
- void setStereotype(const QString &_name);
- void setStereotypeCmd(const QString &_name);
- QString stereotype(bool includeAdornments = false) const;
-
- void setUMLStereotype(UMLStereotype *stereo);
- UMLStereotype *umlStereotype();
-
- QString package(const QString& separator = QString(),
- bool includeRoot = false);
-
- bool setUMLPackage(UMLPackage* pPkg);
- UMLPackage* umlPackage();
-
- UMLPackageList packages(bool includeRoot = false) const;
-
- virtual void setName(const QString &strName);
- void setNameCmd(const QString &strName) ;
- QString name() const;
-
- virtual QString fullyQualifiedName(const QString& separator = QString(),
- bool includeRoot = false) const;
-
- void setAbstract(bool bAbstract);
- bool isAbstract() const;
-
- virtual bool showPropertiesDialog(QWidget* parent = 0);
-
- virtual bool resolveRef();
-
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
- virtual bool loadFromXMI(QDomElement & element);
-
- bool loadStereotype(QDomElement & element);
-
- void setStatic(bool bStatic);
- bool isStatic() const;
-
- virtual bool acceptAssociationType(Uml::AssociationType::Enum); //:TODO: check if this is really needed here
-
- void setSecondaryId(const QString& id);
- QString secondaryId() const;
-
- void setSecondaryFallback(const QString& id);
- QString secondaryFallback() const;
-
- QDomElement save(const QString &tag, QDomDocument & qDoc);
-
- friend QDebug operator<< (QDebug out, const UMLObject& obj);
-
-public slots:
- void emitModified();
-
-signals:
- void modified();
-
-protected:
- void init();
-
- void maybeSignalObjectCreated();
-
- virtual bool load(QDomElement& element);
-
- Uml::ID::Type m_nId; ///< object's id
- QString m_Doc; ///< object's documentation
- UMLPackage* m_pUMLPackage; ///< package the object belongs to if applicable
- UMLStereotype* m_pStereotype; ///< stereotype of the object if applicable
- QString m_name; ///< objects name
- ObjectType m_BaseType; ///< objects type
- Uml::Visibility::Enum m_visibility; ///< objects visibility
- bool m_bAbstract; ///< state of whether the object is abstract or not
- bool m_bStatic; ///< flag for instance scope
- bool m_bInPaste; ///< caller sets this true when in paste operation
- bool m_bCreationWasSignalled; ///< auxiliary to maybeSignalObjectCreated()
- QPointer<UMLObject> m_pSecondary; ///< pointer to an associated object
- ///< Only a few of the classes inheriting from UMLObject use this.
- ///< However, it needs to be here because of inheritance graph
- ///< disjunctness.
- QString m_SecondaryId; ///< xmi.id of the secondary object for intermediate use during
- ///< loading. The secondary ID is resolved to the m_pSecondary
- ///< in the course of resolveRef() at the end of loading.
- QString m_SecondaryFallback; ///< Last-chance backup for when m_SecondaryId is not found.
- ///< Used by Rose import: MDL files specify both a "quidu"
- ///< (which corresponds to m_SecondaryId) and the human readable
- ///< fully qualified target name of a reference.
- ///< In case the quidu is not found, the human readable name is
- ///< used which we store in m_SecondaryFallback.
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlobjectlist.cpp umbrello-kf6-15.08.1/umbrello/umlobjectlist.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlobjectlist.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlobjectlist.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,53 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "umlobjectlist.h"
-#include "umlobject.h"
-
-UMLObjectList::UMLObjectList()
-{
-}
-
-UMLObjectList::~UMLObjectList()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the new
- * object.
- */
-void UMLObjectList::copyInto(UMLObjectList *rhs) const
-{
- // Don't copy yourself.
- if (rhs == this) return;
-
- rhs->clear();
-
- // Suffering from const; we shall not modify our object.
- UMLObjectList *tmp = new UMLObjectList(*this);
-
- UMLObject *item = NULL;
- for (UMLObjectListIt oit(*tmp); oit.hasNext() ;)
- {
- item = oit.next();
- rhs->append(item->clone());
- }
- delete tmp;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObjectList* UMLObjectList::clone() const
-{
- UMLObjectList *clone = new UMLObjectList();
- copyInto(clone);
- return clone;
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlobjectlist.h umbrello-kf6-15.08.1/umbrello/umlobjectlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlobjectlist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlobjectlist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,40 +0,0 @@
-/***************************************************************************
- * 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) 2001 Gustavo Madrigal gmadrigal@nextphere.com *
- * copyright (C) 2002-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLOBJECTLIST_H
-#define UMLOBJECTLIST_H
-
-#include <QList>
-#include <QPointer>
-
-// forward declarations
-class UMLObject;
-
-typedef QListIterator<QPointer<UMLObject> >
-UMLObjectListIt;
-
-/**
- * This sub-class adds copyInto and clone to the QList<UMLObject*>
- * base class.
- */
-class UMLObjectList : public QList<QPointer<UMLObject> >
-{
-public:
-
- UMLObjectList();
- virtual ~UMLObjectList();
-
- virtual void copyInto(UMLObjectList *rhs) const;
-
- virtual UMLObjectList* clone() const;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umloperationlist.h umbrello-kf6-15.08.1/umbrello/umloperationlist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umloperationlist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umloperationlist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,23 +0,0 @@
-/***************************************************************************
- * *
- * 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) 2003-2007 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLOPERATIONLIST_H
-#define UMLOPERATIONLIST_H
-
-#include <qlist.h>
-
-// forward declaration
-class UMLOperation;
-
-typedef QList<UMLOperation*> UMLOperationList;
-typedef QListIterator<UMLOperation*> UMLOperationListIt;
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlpackagelist.h umbrello-kf6-15.08.1/umbrello/umlpackagelist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlpackagelist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlpackagelist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,22 +0,0 @@
-/***************************************************************************
- * *
- * 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) 2003-2007 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLPACKAGELIST_H
-#define UMLPACKAGELIST_H
-
-#include <qlist.h>
-
-class UMLPackage;
-
-typedef QList<UMLPackage*> UMLPackageList;
-typedef QListIterator<UMLPackage*> UMLPackageListIt;
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlrole.cpp umbrello-kf6-15.08.1/umbrello/umlrole.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlrole.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlrole.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,415 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "umlrole.h"
-
-// local includes
-#include "association.h"
-#include "debug_utils.h"
-#include "umldoc.h"
-#include "umlroledialog.h"
-#include "uml.h"
-
-// qt includes
-#include <QPointer>
-#include <QRegExp>
-
-/**
- * Sets up an association.
- *
- * @param parent The parent (association) of this UMLRole.
- * @param parentObj The Parent UML Object of this UMLRole
- * @param role The Uml::RoleType::Enum of this UMLRole
- */
-UMLRole::UMLRole(UMLAssociation * parent, UMLObject * parentObj, Uml::RoleType::Enum role)
- : UMLObject(const_cast<UMLAssociation*>(parent)),
- m_pAssoc(parent),
- m_role(role),
- m_Multi(QString()),
- m_Changeability(Uml::Changeability::Changeable)
-{
- m_BaseType = UMLObject::ot_Role;
- m_name.clear();
- m_pSecondary = parentObj;
-
- // connect this up to parent
- connect(this, SIGNAL(modified()), parent, SIGNAL(modified()));
-}
-
-/**
- * Standard destructor.
- */
-UMLRole::~UMLRole()
-{
-}
-
-/**
- * Overloaded '==' operator.
- */
-bool UMLRole::operator==(const UMLRole &rhs) const
-{
- if (this == &rhs) {
- return true;
- }
- return (UMLObject::operator==(rhs) &&
- m_Changeability == rhs.m_Changeability &&
- m_Multi == rhs.m_Multi &&
- m_name == rhs.m_name
- );
-}
-
-UMLAssociation * UMLRole::parentAssociation() const
-{
- return m_pAssoc;
-}
-
-/**
- * Returns the UMLObject assigned to the role.
- * @return Pointer to the UMLObject in role.
- */
-UMLObject* UMLRole::object() const
-{
- return m_pSecondary;
-}
-
-/**
- * Returns the Changeablity of the role.
- *
- * @return Changeability of role.
- */
-Uml::Changeability::Enum UMLRole::changeability() const
-{
- return m_Changeability;
-}
-
-/**
- * Returns the multiplicity assigned to the role.
- *
- * @return The multiplicity assigned to the role.
- */
-QString UMLRole::multiplicity() const
-{
- return m_Multi;
-}
-
-/**
- * Sets the UMLObject playing the role in the association.
- *
- * @param obj Pointer to the UMLObject of role.
- */
-void UMLRole::setObject(UMLObject *obj)
-{
- // because we will get the id of this role from the parent
- // object, we CANT allow UMLRoles to take other UMLRoles as
- // parent objects. In fact, there is probably good reason
- // to only take UMLClassifiers here, but I'll leave it more open
- // for the time being. -b.t.
- if (obj && dynamic_cast<UMLRole*>(obj)) {
- uError() << "UMLRole(" << Uml::ID::toString(m_nId) << ") cannot setObject() to another UMLRole("
- << Uml::ID::toString(obj->id()) << ")";
- return;
- }
-
- m_pSecondary = obj;
- UMLObject::emitModified();
-}
-
-/**
- * Sets the changeability of the role.
- *
- * @param value Changeability::Enum of role.
- */
-void UMLRole::setChangeability(Uml::Changeability::Enum value)
-{
- m_Changeability = value;
- UMLObject::emitModified();
-}
-
-/**
- * Sets the multiplicity of the role.
- *
- * @param multi The multiplicity of role.
- */
-void UMLRole::setMultiplicity(const QString &multi)
-{
- m_Multi = multi;
- UMLObject::emitModified();
-}
-
-/**
- * Get the 'id' of the role (NOT the parent object). This could be
- * either Uml::RoleType::A or Uml::RoleType::B. Yes, it would be better if we
- * could get along without this, but we need it to distinguish saved
- * umlrole objects in the XMI for 'self' associations where both roles
- * will point to the same underlying UMLObject.
- */
-Uml::RoleType::Enum UMLRole::role() const
-{
- return m_role;
-}
-
-/**
- * Creates the <UML:AssociationEnd> XMI element.
- */
-void UMLRole::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement roleElement = UMLObject::save(QLatin1String("UML:AssociationEnd"), qDoc);
- if (m_pSecondary)
- roleElement.setAttribute(QLatin1String("type"), Uml::ID::toString(m_pSecondary->id()));
- else
- uError() << "id " << Uml::ID::toString(m_nId) << ": m_pSecondary is NULL";
- if (!m_Multi.isEmpty())
- roleElement.setAttribute(QLatin1String("multiplicity"), m_Multi);
- if (m_role == Uml::RoleType::A) { // role aggregation based on parent type
- // role A
- switch (m_pAssoc->getAssocType()) {
- case Uml::AssociationType::Composition:
- roleElement.setAttribute(QLatin1String("aggregation"), QLatin1String("composite"));
- break;
- case Uml::AssociationType::Aggregation:
- roleElement.setAttribute(QLatin1String("aggregation"), QLatin1String("aggregate"));
- break;
- default:
- roleElement.setAttribute(QLatin1String("aggregation"), QLatin1String("none"));
- break;
- }
- if (m_pAssoc->getAssocType() == Uml::AssociationType::UniAssociation) {
- // Normally the isNavigable attribute is "true".
- // We set it to false on role A to indicate that
- // role B gets an explicit arrowhead.
- roleElement.setAttribute(QLatin1String("isNavigable"), QLatin1String("false"));
- } else {
- roleElement.setAttribute(QLatin1String("isNavigable"), QLatin1String("true"));
- }
- } else {
- roleElement.setAttribute(QLatin1String("aggregation"), QLatin1String("none"));
- roleElement.setAttribute(QLatin1String("isNavigable"), QLatin1String("true"));
- //FIXME obviously this isn't standard XMI
- if (m_pAssoc->getAssocType() == Uml::AssociationType::Relationship) {
- roleElement.setAttribute(QLatin1String("relationship"), QLatin1String("true"));
- }
- }
-
- roleElement.setAttribute(QLatin1String("visibility"), Uml::Visibility::toString(visibility(), false));
-
- switch (m_Changeability) {
- case Uml::Changeability::Frozen:
- roleElement.setAttribute(QLatin1String("changeability"), QLatin1String("frozen"));
- break;
- case Uml::Changeability::AddOnly:
- roleElement.setAttribute(QLatin1String("changeability"), QLatin1String("addOnly"));
- break;
- case Uml::Changeability::Changeable:
- roleElement.setAttribute(QLatin1String("changeability"), QLatin1String("changeable"));
- break;
- }
- qElement.appendChild(roleElement);
-}
-
-/**
- * Display the properties configuration dialog for the object.
- *
- * @param parent The parent widget.
- * @return True for success of this operation.
- */
-bool UMLRole::showPropertiesDialog(QWidget *parent)
-{
- QPointer<UMLRoleDialog> dlg = new UMLRoleDialog(parent, this);
- bool modified = false;
- if (dlg->exec() == QDialog::Accepted) {
- modified = true;
- }
- delete dlg;
- return modified;
-}
-
-/**
- * Loads the <UML:AssociationEnd> XMI element.
- * Auxiliary to UMLObject::loadFromXMI.
- */
-bool UMLRole::load(QDomElement & element)
-{
- UMLDoc * doc = UMLApp::app()->document();
- QString type = element.attribute(QLatin1String("type"));
- if (!type.isEmpty()) {
- if (!m_SecondaryId.isEmpty())
- uWarning() << "overwriting old m_SecondaryId \"" << m_SecondaryId
- << " with new value \"" << type << "\"";
- m_SecondaryId = type;
- }
- // Inspect child nodes - for multiplicity (and type if not set above.)
- for (QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling()) {
- if (node.isComment())
- continue;
- QDomElement tempElement = node.toElement();
- QString tag = tempElement.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("name"))) {
- m_name = tempElement.text();
- } else if (UMLDoc::tagEq(tag, QLatin1String("AssociationEnd.multiplicity"))) {
- /*
- * There are different ways in which the multiplicity might be given:
- * - direct value in the <AssociationEnd.multiplicity> tag,
- * - attributes "lower" and "upper" of a subordinate <MultiplicityRange>,
- * - direct value in subordinate <MultiplicityRange.lower> and
- * <MultiplicityRange.upper> tags
- */
- QDomNode n = tempElement.firstChild();
- if (node.isNull() || tempElement.isNull() || n.isNull() ||
- n.toElement().isNull()) {
- m_Multi = tempElement.text().trimmed();
- continue;
- }
- tempElement = n.toElement();
- tag = tempElement.tagName();
- if (!UMLDoc::tagEq(tag, QLatin1String("Multiplicity"))) {
- m_Multi = tempElement.text().trimmed();
- continue;
- }
- n = tempElement.firstChild();
- tempElement = n.toElement();
- tag = tempElement.tagName();
- if (!UMLDoc::tagEq(tag, QLatin1String("Multiplicity.range"))) {
- m_Multi = tempElement.text().trimmed();
- continue;
- }
- n = tempElement.firstChild();
- tempElement = n.toElement();
- tag = tempElement.tagName();
- if (!UMLDoc::tagEq(tag, QLatin1String("MultiplicityRange"))) {
- m_Multi = tempElement.text().trimmed();
- continue;
- }
- QString multiUpper;
- if (tempElement.hasAttribute(QLatin1String("lower"))) {
- m_Multi = tempElement.attribute(QLatin1String("lower"));
- multiUpper = tempElement.attribute(QLatin1String("upper"));
- if (!multiUpper.isEmpty()) {
- if (!m_Multi.isEmpty())
- m_Multi.append(QLatin1String(".."));
- m_Multi.append(multiUpper);
- }
- continue;
- }
- n = tempElement.firstChild();
- while (!n.isNull()) {
- tempElement = n.toElement();
- tag = tempElement.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("MultiplicityRange.lower"))) {
- m_Multi = tempElement.text();
- } else if (UMLDoc::tagEq(tag, QLatin1String("MultiplicityRange.upper"))) {
- multiUpper = tempElement.text();
- }
- n = n.nextSibling();
- }
- if (!multiUpper.isEmpty()) {
- if (!m_Multi.isEmpty())
- m_Multi.append(QLatin1String(".."));
- m_Multi.append(multiUpper);
- }
- } else if (m_SecondaryId.isEmpty() &&
- (UMLDoc::tagEq(tag, QLatin1String("type")) ||
- UMLDoc::tagEq(tag, QLatin1String("participant")))) {
- m_SecondaryId = tempElement.attribute(QLatin1String("xmi.id"));
- if (m_SecondaryId.isEmpty())
- m_SecondaryId = tempElement.attribute(QLatin1String("xmi.idref"));
- if (m_SecondaryId.isEmpty()) {
- QDomNode inner = tempElement.firstChild();
- QDomElement innerElem = inner.toElement();
- m_SecondaryId = innerElem.attribute(QLatin1String("xmi.id"));
- if (m_SecondaryId.isEmpty())
- m_SecondaryId = innerElem.attribute(QLatin1String("xmi.idref"));
- }
- }
- }
- if (!m_Multi.isEmpty())
- uDebug() << name() << ": m_Multi is " << m_Multi;
- if (m_SecondaryId.isEmpty()) {
- uError() << name() << ": type not given or illegal";
- return false;
- }
- UMLObject * obj;
- obj = doc->findObjectById(Uml::ID::fromString(m_SecondaryId));
- if (obj) {
- m_pSecondary = obj;
- m_SecondaryId = QString();
- }
-
- // block signals to prevent needless updating
- blockSignals(true);
- // Here comes the handling of the association type.
- // This is open for discussion - I'm pretty sure there are better ways..
-
- // Yeah, for one, setting the *parent* object parameters from here is sucky
- // as hell. Why are we using roleA to store what is essentially a parent (association)
- // parameter, eh? The UML13.dtd is pretty silly, but since that is what
- // is driving us to that point, we have to go with it. Some analysis of
- // the component roles/linked items needs to be done in order to get things
- // right. *sigh* -b.t.
-
- // Setting association type from the role (A)
- // Determination of the "aggregation" attribute used to be done only
- // when (m_role == Uml::RoleType::A) but some XMI writers (e.g. StarUML) place
- // the aggregation attribute at role B.
- // The role end with the aggregation unequal to "none" wins.
- QString aggregation = element.attribute(QLatin1String("aggregation"), QLatin1String("none"));
- if (aggregation == QLatin1String("composite"))
- m_pAssoc->setAssociationType(Uml::AssociationType::Composition);
- else if (aggregation == QLatin1String("shared") // UML1.3
- || aggregation == QLatin1String("aggregate")) // UML1.4
- m_pAssoc->setAssociationType(Uml::AssociationType::Aggregation);
-
- if (!element.hasAttribute(QLatin1String("isNavigable"))) {
- // Backward compatibility mode: In umbrello-kf6 version 1.3.x the
- // logic for saving the isNavigable flag was wrong.
- // May happen on loading role A.
- m_pAssoc->setOldLoadMode(true);
- } else if (m_pAssoc->getOldLoadMode() == true) {
- // Here is the original logic:
- // "Role B:
- // If isNavigable is not given, we make no change to the
- // association type.
- // If isNavigable is given, and is "true", then we assume that
- // the association's other end (role A) is not navigable, and
- // therefore we change the association type to UniAssociation.
- // The case that isNavigable is given as "false" is ignored.
- // Combined with the association type logic for role A, this
- // allows us to support at_Association and at_UniAssociation."
- if (element.attribute(QLatin1String("isNavigable")) == QLatin1String("true"))
- m_pAssoc->setAssociationType(Uml::AssociationType::UniAssociation);
- } else if (element.attribute(QLatin1String("isNavigable")) == QLatin1String("false")) {
- m_pAssoc->setAssociationType(Uml::AssociationType::UniAssociation);
- }
-
- //FIXME not standard XMI
- if (element.hasAttribute(QLatin1String("relationship"))) {
- if (element.attribute(QLatin1String("relationship")) == QLatin1String("true")) {
- m_pAssoc->setAssociationType(Uml::AssociationType::Relationship);
- }
- }
-
- if (m_Multi.isEmpty())
- m_Multi = element.attribute(QLatin1String("multiplicity"));
-
- // Changeability defaults to Changeable if it cant set it here..
- m_Changeability = Uml::Changeability::Changeable;
- QString changeability = element.attribute(QLatin1String("changeability"));
- if (changeability.isEmpty())
- element.attribute(QLatin1String("changeable")); // for backward compatibility
- if (changeability == QLatin1String("frozen"))
- m_Changeability = Uml::Changeability::Frozen;
- else if (changeability == QLatin1String("addOnly"))
- m_Changeability = Uml::Changeability::AddOnly;
-
- // finished config, now unblock
- blockSignals(false);
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlrole.h umbrello-kf6-15.08.1/umbrello/umlrole.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlrole.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlrole.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,65 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLROLE_H
-#define UMLROLE_H
-
-#include "umlobject.h"
-
-class UMLAssociation;
-
-/**
- * This class contains the non-graphic representation of an association role.
- *
- * @author Brian Thomas <brian.thomas@gsfc.nasa.gov>
- * @see UMLObject
- */
-class UMLRole : public UMLObject
-{
- Q_OBJECT
-public:
-
- UMLRole(UMLAssociation * parent, UMLObject * parentUMLObject, Uml::RoleType::Enum role);
- virtual ~UMLRole();
-
- bool operator==(const UMLRole & rhs) const;
-
- void setObject(UMLObject *obj);
- UMLObject* object() const;
-
- void setChangeability(Uml::Changeability::Enum value);
- Uml::Changeability::Enum changeability() const;
-
- void setMultiplicity(const QString &multi);
- QString multiplicity() const;
-
- UMLAssociation * parentAssociation() const;
-
- Uml::RoleType::Enum role() const;
-
- UMLObject* clone() const { return NULL; }
-
- void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
- virtual bool showPropertiesDialog(QWidget *parent = 0);
-
-protected:
-
- bool load(QDomElement& element);
-
-private:
-
- UMLAssociation * m_pAssoc;
- Uml::RoleType::Enum m_role;
- QString m_Multi;
- Uml::Changeability::Enum m_Changeability;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlstereotypelist.h umbrello-kf6-15.08.1/umbrello/umlstereotypelist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlstereotypelist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umlstereotypelist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,22 +0,0 @@
-/***************************************************************************
- * 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) 2003-2012 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLSTEREOTYPELIST_H
-#define UMLSTEREOTYPELIST_H
-
-#include <QList>
-
-// forward declaration
-class UMLStereotype;
-
-typedef QList<UMLStereotype*> UMLStereotypeList;
-typedef QListIterator<UMLStereotype*> UMLStereotypeListIt;
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umltemplatelist.h umbrello-kf6-15.08.1/umbrello/umltemplatelist.h
--- umbrello-kf6-15.08.1.orig/umbrello/umltemplatelist.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/umltemplatelist.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,23 +0,0 @@
-/***************************************************************************
- * *
- * 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-2007 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLTEMPLATELIST_H
-#define UMLTEMPLATELIST_H
-
-#include <qlist.h>
-
-// forward declaration
-class UMLTemplate;
-
-typedef QList<UMLTemplate*> UMLTemplateList;
-typedef QListIterator<UMLTemplate*> UMLTemplateListIt;
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/activitywidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/activitywidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/activitywidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/activitywidget.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,457 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "activitywidget.h"
+
+// app includes
+#include "activitydialog.h"
+#include "debug_utils.h"
+#include "docwindow.h"
+#include "listpopupmenu.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+// kde includes
+#include <KLocalizedString>
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+#include <QPointer>
+/**
+ * Creates a Activity widget.
+ *
+ * @param scene The parent of the widget.
+ * @param activityType The type of activity.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+ActivityWidget::ActivityWidget(UMLScene * scene, ActivityType activityType, Uml::ID::Type id)
+ : UMLWidget(scene, WidgetBase::wt_Activity, id),
+ m_activityType(activityType)
+{
+ // set non zero size to avoid crash on painting
+ setSize(1, 1);
+}
+
+/**
+ * Destructor.
+ */
+ActivityWidget::~ActivityWidget()
+{
+}
+
+/**
+ * Returns the type of activity.
+ */
+ActivityWidget::ActivityType ActivityWidget::activityType() const
+{
+ return m_activityType;
+}
+
+/**
+ * Returns the type string of activity.
+ */
+QString ActivityWidget::activityTypeStr() const
+{
+ return QLatin1String(ENUM_NAME(ActivityWidget, ActivityType, m_activityType));
+}
+
+/**
+ * Sets the type of activity.
+ */
+void ActivityWidget::setActivityType(ActivityType activityType)
+{
+ m_activityType = activityType;
+ updateGeometry();
+ UMLWidget::m_resizable = true;
+}
+
+/**
+ * Determines whether a toolbar button represents an Activity.
+ * CHECK: currently unused - can this be removed?
+ *
+ * @param tbb The toolbar button enum input value.
+ * @param resultType The ActivityType corresponding to tbb.
+ * This is only set if tbb is an Activity.
+ * @return True if tbb represents an Activity.
+ */
+bool ActivityWidget::isActivity(WorkToolBar::ToolBar_Buttons tbb,
+ ActivityType& resultType)
+{
+ bool status = true;
+ switch (tbb) {
+ case WorkToolBar::tbb_Initial_Activity:
+ resultType = Initial;
+ break;
+ case WorkToolBar::tbb_Activity:
+ resultType = Normal;
+ break;
+ case WorkToolBar::tbb_End_Activity:
+ resultType = End;
+ break;
+ case WorkToolBar::tbb_Final_Activity:
+ resultType = Final;
+ break;
+ case WorkToolBar::tbb_Branch:
+ resultType = Branch;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ return status;
+}
+
+/**
+ * This method get the name of the preText attribute.
+ */
+QString ActivityWidget::preconditionText() const
+{
+ return m_preconditionText;
+}
+
+/**
+ * This method set the name of the preText attribute
+ */
+void ActivityWidget::setPreconditionText(const QString& aPreText)
+{
+ m_preconditionText = aPreText;
+ updateGeometry();
+ adjustAssocs(x(), y());
+}
+
+/**
+ * This method get the name of the postText attribute.
+ */
+QString ActivityWidget::postconditionText() const
+{
+ return m_postconditionText;
+}
+
+/**
+ * This method set the name of the postText attribute
+ */
+void ActivityWidget::setPostconditionText(const QString& aPostText)
+{
+ m_postconditionText = aPostText;
+ updateGeometry();
+ adjustAssocs(x(), y());
+}
+
+/**
+ * Reimplemented from UMLWidget::showPropertiesDialog to show a
+ * properties dialog for an ActivityWidget.
+ */
+void ActivityWidget::showPropertiesDialog()
+{
+ UMLApp::app()->docWindow()->updateDocumentation(false);
+
+ QPointer<ActivityDialog> dialog = new ActivityDialog(umlScene()->activeView(), this);
+ if (dialog->exec() && dialog->getChangesMade()) {
+ UMLApp::app()->docWindow()->showDocumentation(this, true);
+ UMLApp::app()->document()->setModified(true);
+ }
+ delete dialog;
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void ActivityWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ int w = width();
+ int h = height();
+
+ // Only for the final activity
+ float x;
+ float y;
+ QPen pen = painter->pen();
+
+ switch (m_activityType)
+ {
+ case Normal:
+ UMLWidget::setPenFromSettings(painter);
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ }
+ {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ int textStartY = (h / 2) - (fontHeight / 2);
+ painter->drawRoundRect(0, 0, w, h, (h * 60) / w, 60);
+ painter->setPen(textColor());
+ painter->setFont(UMLWidget::font());
+ painter->drawText(ACTIVITY_MARGIN, textStartY,
+ w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
+ }
+ break;
+
+ case Initial:
+ painter->setPen(QPen(WidgetBase::lineColor(), 1));
+ painter->setBrush(WidgetBase::lineColor());
+ painter->drawEllipse(0, 0, w, h);
+ break;
+
+ case Final:
+ UMLWidget::setPenFromSettings(painter);
+ painter->setBrush(Qt::white);
+ pen.setWidth(2);
+ pen.setColor (Qt::red);
+ painter->setPen(pen);
+ painter->drawEllipse(0, 0, w, h);
+ x = w/2 ;
+ y = h/2 ;
+ {
+ const float w2 = 0.7071 * (float)w / 2.0;
+ painter->drawLine((int)(x - w2 + 1), (int)(y - w2 + 1), (int)(x + w2), (int)(y + w2));
+ painter->drawLine((int)(x + w2 - 1), (int)(y - w2 + 1), (int)(x - w2), (int)(y + w2));
+ }
+ break;
+
+ case End:
+ painter->setPen(QPen(WidgetBase::lineColor(), 1));
+ painter->setBrush(WidgetBase::lineColor());
+ painter->drawEllipse(0, 0, w, h);
+ painter->setBrush(Qt::white);
+ painter->drawEllipse(1, 1, w - 2, h - 2);
+ painter->setBrush(WidgetBase::lineColor());
+ painter->drawEllipse(3, 3, w - 6, h - 6);
+ break;
+
+ case Branch:
+ UMLWidget::setPenFromSettings(painter);
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ }
+ {
+ QPolygon array(4);
+ array[ 0 ] = QPoint(w / 2, 0);
+ array[ 1 ] = QPoint(w, h / 2);
+ array[ 2 ] = QPoint(w / 2, h);
+ array[ 3 ] = QPoint(0, h / 2);
+ painter->drawPolygon(array);
+ painter->drawPolyline(array);
+ }
+ break;
+
+ case Invok:
+ UMLWidget::setPenFromSettings(painter);
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ }
+ {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ int textStartY = (h / 2) - (fontHeight / 2);
+ painter->drawRoundRect(0, 0, w, h, (h * 60) / w, 60);
+ painter->setPen(textColor());
+ painter->setFont(UMLWidget::font());
+ painter->drawText(ACTIVITY_MARGIN, textStartY,
+ w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
+
+ }
+ x = w - (w/5);
+ y = h - (h/3);
+
+ painter->drawLine((int)x, (int) y, (int)x, (int)(y + 20));
+ painter->drawLine((int)(x - 10), (int)(y + 10), (int)(x + 10), (int)(y + 10));
+ painter->drawLine((int)(x - 10), (int)(y + 10), (int)(x - 10), (int)(y + 20));
+ painter->drawLine((int)(x + 10), (int)(y + 10), (int)(x + 10), (int)(y + 20));
+ break;
+
+ case Param:
+ UMLWidget::setPenFromSettings(painter);
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ }
+ {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ QString preCond= QLatin1String("<<precondition>> ") + preconditionText();
+ QString postCond= QLatin1String("<<postcondition>> ") + postconditionText();
+ //int textStartY = (h / 2) - (fontHeight / 2);
+ painter->drawRoundRect(0, 0, w, h, (h * 60) / w, 60);
+ painter->setPen(textColor());
+ painter->setFont(UMLWidget::font());
+ painter->drawText(ACTIVITY_MARGIN, fontHeight + 10,
+ w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, preCond);
+ painter->drawText(ACTIVITY_MARGIN, fontHeight * 2 + 10,
+ w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, postCond);
+ painter->drawText(ACTIVITY_MARGIN, (fontHeight / 2),
+ w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
+ }
+
+ break;
+ }
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overridden from UMLWidget due to emission of signal sigActMoved()
+ */
+void ActivityWidget::moveWidgetBy(qreal diffX, qreal diffY)
+{
+ UMLWidget::moveWidgetBy(diffX, diffY);
+ emit sigActMoved(diffX, diffY);
+}
+
+/**
+ * Loads the widget from the "activitywidget" XMI element.
+ */
+bool ActivityWidget::loadFromXMI(QDomElement& qElement)
+{
+ if(!UMLWidget::loadFromXMI(qElement))
+ return false;
+ setName(qElement.attribute(QLatin1String("activityname")));
+ setDocumentation(qElement.attribute(QLatin1String("documentation")));
+ setPreconditionText(qElement.attribute(QLatin1String("precondition")));
+ setPostconditionText(qElement.attribute(QLatin1String("postcondition")));
+
+ QString type = qElement.attribute(QLatin1String("activitytype"), QLatin1String("1"));
+ setActivityType((ActivityType)type.toInt());
+
+ return true;
+}
+
+/**
+ * Saves the widget to the "activitywidget" XMI element.
+ */
+void ActivityWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement activityElement = qDoc.createElement(QLatin1String("activitywidget"));
+ UMLWidget::saveToXMI(qDoc, activityElement);
+ activityElement.setAttribute(QLatin1String("activityname"), name());
+ activityElement.setAttribute(QLatin1String("documentation"), documentation());
+ activityElement.setAttribute(QLatin1String("precondition"), preconditionText());
+ activityElement.setAttribute(QLatin1String("postcondition"), postconditionText());
+ activityElement.setAttribute(QLatin1String("activitytype"), m_activityType);
+ qElement.appendChild(activityElement);
+}
+
+/**
+ * Overrides Method from UMLWidget.
+ */
+void ActivityWidget::constrain(qreal& width, qreal& height)
+{
+ if (m_activityType == Normal || m_activityType == Invok || m_activityType == Param) {
+ UMLWidget::constrain(width, height);
+ return;
+ }
+
+ if (width > height)
+ width = height;
+ else if (height > width)
+ height = width;
+
+ UMLWidget::constrain(width, height);
+}
+
+/**
+ * Captures any popup menu signals for menus it created.
+ */
+void ActivityWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+
+ switch(sel) {
+ case ListPopupMenu::mt_Rename:
+ {
+ bool ok = false;
+ QString n = name();
+#if QT_VERSION >= 0x050000
+ n = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter Activity Name"),
+ i18n("Enter the name of the new activity:"),
+ QLineEdit::Normal,
+ n, &ok);
+#else
+ n = KInputDialog::getText(i18n("Enter Activity Name"),
+ i18n("Enter the name of the new activity:"),
+ n, &ok);
+#endif
+ if (ok && !n.isEmpty()) {
+ setName(n);
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ showPropertiesDialog();
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ }
+}
+
+/**
+ * Overrides method from UMLWidget
+ */
+QSizeF ActivityWidget::minimumSize() const
+{
+ if (m_activityType == Normal || m_activityType == Invok || m_activityType == Param) {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+
+ int textWidth = fm.width(name());
+ int height = fontHeight;
+ height = height > ACTIVITY_HEIGHT ? height : ACTIVITY_HEIGHT;
+ height += ACTIVITY_MARGIN * 2;
+
+ textWidth = textWidth > ACTIVITY_WIDTH ? textWidth : ACTIVITY_WIDTH;
+
+ if (m_activityType == Invok) {
+ height += 40;
+ } else if (m_activityType == Param) {
+ QString maxSize;
+
+ maxSize = name().length() > postconditionText().length() ? name() : postconditionText();
+ maxSize = maxSize.length() > preconditionText().length() ? maxSize : preconditionText();
+
+ textWidth = fm.width(maxSize);
+ textWidth = textWidth + 50;
+ height += 100;
+ }
+
+ int width = textWidth > ACTIVITY_WIDTH ? textWidth : ACTIVITY_WIDTH;
+
+ width += ACTIVITY_MARGIN * 4;
+ return QSizeF(width, height);
+ }
+ else if (m_activityType == Branch) {
+ return QSizeF(20, 20);
+ }
+ return QSizeF(15, 15);
+}
+
+/**
+ * Overrides method from UMLWidget
+ */
+QSizeF ActivityWidget::maximumSize()
+{
+ if (m_activityType == Normal || m_activityType == Invok || m_activityType == Param) {
+ return UMLWidget::maximumSize();
+ }
+ if (m_activityType == Branch) {
+ return QSizeF(50, 50);
+ }
+ return QSizeF(30, 30);
+}
+
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/activitywidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/activitywidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/activitywidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/activitywidget.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,98 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ACTIVITYWIDGET_H
+#define ACTIVITYWIDGET_H
+
+#include "umlwidget.h"
+#include "worktoolbar.h"
+
+#define ACTIVITY_MARGIN 5
+#define ACTIVITY_WIDTH 30
+#define ACTIVITY_HEIGHT 10
+
+/**
+ * This class is the graphical version of a UML Activity. A ActivityWidget is created
+ * by a @ref UMLView. An ActivityWidget belongs to only one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
+ *
+ * The ActivityWidget class inherits from the @ref UMLWidget class which adds most of the functionality
+ * to this class.
+ *
+ * @short A graphical version of a UML Activity.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class ActivityWidget : public UMLWidget
+{
+ Q_OBJECT
+ Q_ENUMS(ActivityType)
+public:
+ enum ActivityType
+ {
+ Initial = 0,
+ Normal,
+ End,
+ Final,
+ Branch,
+ Invok,
+ Param
+ };
+
+ explicit ActivityWidget(UMLScene * scene, ActivityType activityType = Normal, Uml::ID::Type id = Uml::ID::None);
+ virtual ~ActivityWidget();
+
+ ActivityType activityType() const;
+ QString activityTypeStr() const;
+ void setActivityType(ActivityType activityType);
+
+ static bool isActivity(WorkToolBar::ToolBar_Buttons tbb,
+ ActivityType& resultType);
+
+ QString preconditionText() const;
+ void setPreconditionText(const QString&);
+
+ QString postconditionText() const;
+ void setPostconditionText(const QString&);
+
+ virtual void showPropertiesDialog();
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ virtual void moveWidgetBy(qreal diffX, qreal diffY);
+
+ virtual bool loadFromXMI(QDomElement & qElement);
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ void constrain(qreal& width, qreal& height);
+
+signals:
+ /**
+ * Emitted when the activity widget is moved.
+ * Provides the delta X and delta Y amount by which the widget was moved
+ * relative to the previous position.
+ * Slots into PinWidget::slotActMoved()
+ * @param diffX The difference between previous and new X value.
+ * @param diffY The difference between previous and new Y value.
+ */
+ void sigActMoved(qreal diffX, qreal diffY);
+
+public Q_SLOTS:
+ virtual void slotMenuSelection(QAction* action);
+
+protected:
+ virtual QSizeF minimumSize() const;
+ virtual QSizeF maximumSize();
+
+ ActivityType m_activityType; ///< Type of activity.
+
+ QString m_preconditionText;
+ QString m_postconditionText;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/actorwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/actorwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/actorwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/actorwidget.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,104 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header file
+#include "actorwidget.h"
+
+// local includes
+#include "actor.h"
+#include "umlview.h"
+
+/**
+ * Constructs an ActorWidget.
+ *
+ * @param scene The parent of this ActorWidget.
+ * @param a The Actor class this ActorWidget will display.
+ */
+ActorWidget::ActorWidget(UMLScene * scene, UMLActor *a)
+ : UMLWidget(scene, WidgetBase::wt_Actor, a)
+{
+ setFixedAspectRatio(true);
+}
+
+/**
+ * Destructor.
+ */
+ActorWidget::~ActorWidget()
+{
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void ActorWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ UMLWidget::setPenFromSettings(painter);
+ if(UMLWidget::useFillColor())
+ painter->setBrush(UMLWidget::fillColor());
+ const int w = width();
+ const int h = height();
+ painter->setFont(UMLWidget::font());
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ bool drawStereotype = umlObject() && !umlObject()->stereotype().isEmpty();
+ const int a_height = h - (drawStereotype ? 2 * fontHeight : fontHeight) - A_MARGIN;
+ const int h2 = a_height / 2;
+ const int a_width = (h2);
+ const int middleX = w / 2;
+ const int thirdY = a_height / 3;
+
+ //draw actor
+ painter->drawEllipse(middleX - a_width / 2, 0, a_width, thirdY); //head
+ painter->drawLine(middleX, thirdY,
+ middleX, thirdY * 2); //body
+ painter->drawLine(middleX, 2 * thirdY,
+ middleX - a_width / 2, a_height); //left leg
+ painter->drawLine(middleX, 2 * thirdY,
+ middleX + a_width / 2, a_height); //right leg
+ painter->drawLine(middleX - a_width / 2, thirdY + thirdY / 2,
+ middleX + a_width / 2, thirdY + thirdY / 2); //arms
+ //draw text
+ painter->setPen(textColor());
+ if (drawStereotype)
+ painter->drawText(A_MARGIN, h - 2 * fontHeight, w - A_MARGIN * 2, fontHeight, Qt::AlignCenter, umlObject()->stereotype(true));
+ painter->drawText(A_MARGIN, h - fontHeight,
+ w - A_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Saves the widget to the "actorwidget" XMI element.
+ * Note: For loading from XMI, the inherited parent method is used.
+ */
+void ActorWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement actorElement = qDoc.createElement(QLatin1String("actorwidget"));
+ UMLWidget::saveToXMI(qDoc, actorElement);
+ qElement.appendChild(actorElement);
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF ActorWidget::minimumSize() const
+{
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int textWidth = fm.width(name());
+ bool drawStereotype = umlObject() && !umlObject()->stereotype().isEmpty();
+ int width = textWidth > A_WIDTH ? textWidth : A_WIDTH;
+ int height = A_HEIGHT + (drawStereotype ? 2 * fontHeight : fontHeight) + A_MARGIN;
+ width += A_MARGIN * 2;
+ return QSizeF(width, height);
+}
+
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/actorwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/actorwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/actorwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/actorwidget.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ACTORWIDGET_H
+#define ACTORWIDGET_H
+
+#include "umlwidget.h"
+
+#define A_WIDTH 20
+#define A_HEIGHT 40
+#define A_MARGIN 5
+
+class UMLActor;
+
+/**
+ * This class is the graphical version of a UML Actor.
+ * An ActorWidget is created by a @ref UMLView. An ActorWidget belongs to only
+ * one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to is destroyed, the
+ * ActorWidget will be automatically deleted.
+ *
+ * If the UMLActor class that this ActorWidget is displaying is deleted, the
+ * @ref UMLView will make sure that this instance is also deleted.
+ *
+ * The ActorWidget class inherits from the @ref UMLWidget class
+ * which adds most of the functionality to this class.
+ *
+ * @short A graphical version of a UML Actor.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLWidget
+ * @see UMLView
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class ActorWidget : public UMLWidget
+{
+public:
+ ActorWidget(UMLScene * scene, UMLActor *o);
+ virtual ~ActorWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+protected:
+ QSizeF minimumSize() const;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/artifactwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/artifactwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/artifactwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/artifactwidget.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,293 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "artifactwidget.h"
+
+// app includes
+#include "artifact.h"
+#include "debug_utils.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+/**
+ * Constructs a ArtifactWidget.
+ *
+ * @param scene The parent of this ArtifactWidget.
+ * @param a The Artifact this widget will be representing.
+ */
+ArtifactWidget::ArtifactWidget(UMLScene *scene, UMLArtifact *a)
+ : UMLWidget(scene, WidgetBase::wt_Artifact, a)
+{
+ setSize(100, 30);
+}
+
+/**
+ * Destructor.
+ */
+ArtifactWidget::~ArtifactWidget()
+{
+}
+
+/**
+ * Reimplemented to paint the articraft widget. Some part of specific
+ * drawing is delegeted to private method like drawAsFile..
+ */
+void ArtifactWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ UMLWidget::setPenFromSettings(painter);
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ } else {
+ painter->setBrush(m_scene->backgroundColor());
+ }
+
+ if (umlObject()) {
+ UMLArtifact *umlart = static_cast<UMLArtifact*>(m_umlObject);
+ UMLArtifact::Draw_Type drawType = umlart->getDrawAsType();
+ switch (drawType) {
+ case UMLArtifact::defaultDraw:
+ paintAsNormal(painter, option);
+ break;
+ case UMLArtifact::file:
+ paintAsFile(painter, option);
+ break;
+ case UMLArtifact::library:
+ paintAsLibrary(painter, option);
+ break;
+ case UMLArtifact::table:
+ paintAsTable(painter, option);
+ break;
+ default:
+ uWarning() << "Artifact drawn as unknown type";
+ break;
+ }
+ }
+ else {
+ uWarning() << "Cannot draw as there is no UMLArtifact for this widget.";
+ }
+}
+
+/**
+ * Reimplemented from WidgetBase::saveToXMI to save the widget to
+ * the "artifactwidget" XMI element.
+ */
+void ArtifactWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement conceptElement = qDoc.createElement(QLatin1String("artifactwidget"));
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF ArtifactWidget::minimumSize() const
+{
+ if (!m_umlObject) {
+ return UMLWidget::minimumSize();
+ }
+ UMLArtifact *umlart = static_cast<UMLArtifact*>(m_umlObject);
+ if (umlart->getDrawAsType() == UMLArtifact::defaultDraw) {
+ return calculateNormalSize();
+ } else {
+ return calculateIconSize();
+ }
+}
+
+/**
+ * calculates the size when drawing as an icon (it's the same size for all icons)
+ */
+QSize ArtifactWidget::calculateIconSize() const
+{
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
+ const int fontHeight = fm.lineSpacing();
+
+ int width = fm.width(m_umlObject->name());
+
+ width = width<50 ? 50 : width;
+
+ int height = 50 + fontHeight;
+
+ return QSize(width, height);
+}
+
+/**
+ * calculates the size for drawing as a box
+ */
+QSize ArtifactWidget::calculateNormalSize() const
+{
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
+ const int fontHeight = fm.lineSpacing();
+
+ int width = fm.width(m_umlObject->name());
+
+ int tempWidth = 0;
+ if(!m_umlObject->stereotype().isEmpty()) {
+ tempWidth = fm.width(m_umlObject->stereotype(true));
+ }
+ width = tempWidth>width ? tempWidth : width;
+ width += ARTIFACT_MARGIN * 2;
+
+ int height = (2*fontHeight) + (ARTIFACT_MARGIN * 2);
+
+ return QSize(width, height);
+}
+
+/**
+ * draw as a file icon
+ */
+void ArtifactWidget::paintAsFile(QPainter *painter, const QStyleOptionGraphicsItem *option)
+{
+ const int w = width();
+ const int h = height();
+ QFont font = UMLWidget::font();
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+
+ int startX = (w/2) - 25;
+ int iconHeight = h - fontHeight;
+ QPolygon pointArray(5);
+ pointArray.setPoint(0, startX, 0);
+ pointArray.setPoint(1, startX + 40, 0);
+ pointArray.setPoint(2, startX + 50, 10);
+ pointArray.setPoint(3, startX + 50, iconHeight);
+ pointArray.setPoint(4, startX, iconHeight);
+ painter->drawPolygon(pointArray);
+
+ painter->drawLine(startX + 40, 0, startX + 40, 10);
+ painter->drawLine(startX + 40, 10, startX + 50, 10);
+ painter->drawLine(startX + 40, 0, startX + 50, 10);
+
+ painter->setPen(textColor());
+ painter->setFont(font);
+
+ painter->drawText(0, h - fontHeight,
+ w, fontHeight, Qt::AlignCenter, name());
+
+ UMLWidget::paint(painter, option);
+}
+
+/**
+ * draw as a library file icon
+ */
+void ArtifactWidget::paintAsLibrary(QPainter *painter, const QStyleOptionGraphicsItem *option)
+{
+ //FIXME this should have gears on it
+ const int w = width();
+ const int h = height();
+ const QFont font = UMLWidget::font();
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+
+ const int startX = (w/2) - 25;
+ const int iconHeight = h - fontHeight;
+ QPolygon pointArray(5);
+ pointArray.setPoint(0, startX, 0);
+ pointArray.setPoint(1, startX + 40, 0);
+ pointArray.setPoint(2, startX + 50, 10);
+ pointArray.setPoint(3, startX + 50, iconHeight);
+ pointArray.setPoint(4, startX, iconHeight);
+ painter->drawPolygon(pointArray);
+
+ painter->drawLine(startX + 40, 0, startX + 40, 10);
+ painter->drawLine(startX + 40, 10, startX + 50, 10);
+ painter->drawLine(startX + 40, 0, startX + 50, 10);
+
+ painter->setPen(textColor());
+ painter->setFont(font);
+
+ painter->drawText(0, h - fontHeight,
+ w, fontHeight, Qt::AlignCenter, name());
+
+ UMLWidget::paint(painter, option);
+}
+
+/**
+ * draw as a database table icon
+ */
+void ArtifactWidget::paintAsTable(QPainter *painter, const QStyleOptionGraphicsItem *option)
+{
+ const int w = width();
+ const int h = height();
+ const QFont font = UMLWidget::font();
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+
+ const int startX = (w/2) - 25;
+ const int iconHeight = h - fontHeight;
+
+ painter->drawRect(startX, 0, 50, h - fontHeight + 1);
+ painter->drawLine(startX + 20, 0, startX + 20, iconHeight);
+ painter->drawLine(startX + 30, 0, startX + 30, iconHeight);
+ painter->drawLine(startX + 40, 0, startX + 40, iconHeight);
+ painter->drawLine(startX, (iconHeight/2), startX + 49, (iconHeight/2));
+ painter->drawLine(startX, (iconHeight/2) + (iconHeight/4),
+ startX + 49, (iconHeight/2) + (iconHeight/4));
+
+ QPen thickerPen = painter->pen();
+ thickerPen.setWidth(2);
+ painter->setPen(thickerPen);
+ painter->drawLine(startX + 10, 0, startX + 10, iconHeight);
+ painter->drawLine(startX, (iconHeight/4), startX + 50, (iconHeight/4));
+
+ painter->setPen(textColor());
+ painter->setFont(font);
+
+ painter->drawText(0, h - fontHeight,
+ w, fontHeight, Qt::AlignCenter, name());
+
+ UMLWidget::paint(painter, option);
+}
+
+/**
+ * draw as a box
+ */
+void ArtifactWidget::paintAsNormal(QPainter *painter, const QStyleOptionGraphicsItem *option)
+{
+ int w = width();
+ int h = height();
+ QFont font = UMLWidget::font();
+ font.setBold(true);
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD);
+ const int fontHeight = fm.lineSpacing();
+ QString stereotype = m_umlObject->stereotype();
+
+ painter->drawRect(0, 0, w, h);
+
+ painter->setPen(textColor());
+ painter->setFont(font);
+
+ if (!stereotype.isEmpty()) {
+ painter->drawText(ARTIFACT_MARGIN, (h/2) - fontHeight,
+ w, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true));
+ }
+
+ int lines;
+ if (!stereotype.isEmpty()) {
+ lines = 2;
+ } else {
+ lines = 1;
+ }
+
+ if (lines == 1) {
+ painter->drawText(0, (h/2) - (fontHeight/2),
+ w, fontHeight, Qt::AlignCenter, name());
+ } else {
+ painter->drawText(0, (h/2),
+ w, fontHeight, Qt::AlignCenter, name());
+ }
+
+ UMLWidget::paint(painter, option);
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/artifactwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/artifactwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/artifactwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/artifactwidget.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ARTIFACTWIDGET_H
+#define ARTIFACTWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLScene;
+class UMLArtifact;
+
+#define ARTIFACT_MARGIN 5
+
+/**
+ * Defines a graphical version of the @ref UMLArtifact.
+ * Most of the functionality will come from the @ref UMLWidget class.
+ *
+ * @short A graphical version of a Artifact.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class ArtifactWidget : public UMLWidget
+{
+public:
+ ArtifactWidget(UMLScene *scene, UMLArtifact *a);
+ virtual ~ArtifactWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ // Note: For loading from XMI, the inherited parent method is used.
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ QSizeF minimumSize() const;
+
+private:
+ void paintAsFile(QPainter *painter, const QStyleOptionGraphicsItem *option);
+ void paintAsLibrary(QPainter *painter, const QStyleOptionGraphicsItem *option);
+ void paintAsTable(QPainter *painter, const QStyleOptionGraphicsItem *option);
+ void paintAsNormal(QPainter *painter, const QStyleOptionGraphicsItem *option);
+
+ QSize calculateIconSize() const;
+ QSize calculateNormalSize() const;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/associationline.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/associationline.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/associationline.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/associationline.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,1404 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "associationline.h"
+
+// application includes
+#include "associationwidget.h"
+#include "debug_utils.h"
+#include "umlwidget.h"
+
+// qt includes
+#include <QDomDocument>
+#include <QPainter>
+
+// system includes
+#include <cstdlib>
+#include <cmath>
+
+DEBUG_REGISTER_DISABLED(AssociationLine)
+
+// Initialize static variables.
+const qreal AssociationLine::Delta = 5;
+const qreal AssociationLine::SelectedPointDiameter = 4;
+const qreal AssociationLine::SelfAssociationMinimumHeight = 30;
+
+/**
+ * Constructor.
+ * Constructs an AssociationLine item with its parent being \a parent.
+ */
+AssociationLine::AssociationLine(AssociationWidget *association)
+ : QGraphicsObject(association),
+ m_associationWidget(association),
+ m_activePointIndex(-1),
+ m_activeSegmentIndex(-1),
+ m_startSymbol(0),
+ m_endSymbol(0),
+ m_subsetSymbol(0),
+ m_collaborationLineItem(0),
+ m_collaborationLineHead(0),
+ m_layout(Polyline)
+{
+ Q_ASSERT(association);
+ setFlag(QGraphicsLineItem::ItemIsSelectable);
+ setAcceptHoverEvents(true);
+ setZValue(3);
+}
+
+/**
+ * Destructor.
+ */
+AssociationLine::~AssociationLine()
+{
+}
+
+/**
+ * Returns the point at the point index.
+ * @return point at given index
+ */
+QPointF AssociationLine::point(int index) const
+{
+ if ((index < 0) | (index >= m_points.size())) {
+ uWarning() << "Index " << index << " out of range [0.." << m_points.size() - 1 << "].";
+ return QPointF(-1.0, -1.0);
+ }
+ return m_points.at(index);
+}
+
+/**
+ * Sets the point value at given index to \a point.
+ */
+bool AssociationLine::setPoint(int index, const QPointF &point)
+{
+ if ((index < 0) | (index >= m_points.size())) {
+ uWarning() << "Index " << index << " out of range [0.." << m_points.size() - 1 << "].";
+ return false;
+ }
+ if (m_points.at(index) == point) {
+ return false; // nothing to change
+ }
+ prepareGeometryChange();
+ m_points[index] = point;
+ alignSymbols();
+ return true;
+}
+
+/**
+ * Shortcut for point(0).
+ */
+QPointF AssociationLine::startPoint() const
+{
+ return m_points.at(0);
+}
+
+/**
+ * Shortcut for end point.
+ */
+QPointF AssociationLine::endPoint() const
+{
+ return m_points.at(m_points.size()-1);
+}
+
+/**
+ * Inserts the passed in \a point at the \a index passed in and
+ * recalculates the bounding rect.
+ */
+void AssociationLine::insertPoint(int index, const QPointF &point)
+{
+ prepareGeometryChange();
+ m_points.insert(index, point);
+ alignSymbols();
+}
+
+/**
+ * Removes the point at \a index passed in.
+ * @see removeNonEndPoint
+ */
+void AssociationLine::removePoint(int index)
+{
+ prepareGeometryChange();
+ m_points.remove(index);
+ alignSymbols();
+}
+
+/**
+ * Returns the amount of POINTS on the line.
+ * Includes start and end points.
+ * @return number of points in the AssociationLine
+ */
+int AssociationLine::count() const
+{
+ return m_points.size();
+}
+
+/**
+ * Removes all the points and signals a geometry update.
+ */
+void AssociationLine::cleanup()
+{
+ if (!m_points.isEmpty()) {
+ prepareGeometryChange();
+ m_points.clear();
+ alignSymbols();
+ }
+}
+
+/**
+ * This method optimizes the number of points in the
+ * AssociationLine. This can be used to reduce the clutter caused
+ * due to too many points.
+ * TODO: Use delta comparison 'closestPointIndex' instead of exact comparison.
+ * TODO: Not used anywhere.
+ */
+void AssociationLine::optimizeLinePoints()
+{
+ int i = 1;
+ prepareGeometryChange();
+ while (i < m_points.size()) {
+ if (m_points.at(i) == m_points.at(i-1)) {
+ m_points.remove(i);
+ }
+ else {
+ ++i;
+ }
+ }
+ alignSymbols();
+}
+
+/**
+ * Return index of point closer a given delta.
+ *
+ * @param point The point which is to be tested for closeness.
+ * @param delta The distance the point should be closer to.
+ *
+ * @retval "Index" of the first line point closer to the \a point passed.
+ * @retval -1 If no line point is closer to passed in \a point.
+ */
+int AssociationLine::closestPointIndex(const QPointF &point, qreal delta) const
+{
+ for(int i = 0; i < m_points.size(); ++i) {
+ const QPointF& linePoint = m_points.at(i);
+ // Apply distance formula to see point closeness.
+ qreal deltaXSquare = (point.x() - linePoint.x()) * (point.x() - linePoint.x());
+ qreal deltaYSquare = (point.y() - linePoint.y()) * (point.y() - linePoint.y());
+
+ qreal lhs = deltaXSquare + deltaYSquare;
+ qreal rhs = delta * delta;
+
+ if (lhs <= rhs) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/**
+ * Return index of closest segment.
+ *
+ * @param point The point which is to be tested for closeness.
+ *
+ * @return Index of the line segment closest to the \a point passed;
+ * -1 if no line segment is closer to passed in \a point.
+ */
+int AssociationLine::closestSegmentIndex(const QPointF &point, qreal delta) const
+{
+ QPainterPathStroker stroker;
+ stroker.setWidth(delta);
+
+ for(int i = 1; i < m_points.size(); ++i) {
+ QLineF segment(m_points[i-1], m_points[i]);
+
+ QPainterPath path;
+ path.moveTo(segment.p1());
+ path.lineTo(segment.p2());
+
+ path = stroker.createStroke(path);
+
+ if (path.contains(point)) {
+ return i-1;
+ }
+ }
+ return -1;
+}
+
+/**
+ * Retval True If point at \a index is start or end.
+ */
+bool AssociationLine::isEndPointIndex(int index) const
+{
+ const int size = m_points.size();
+ Q_ASSERT(index >= 0 && index < size);
+
+ return (index == 0 || index == (size - 1));
+}
+
+/**
+ * Retval True If segment at \a index is start or end.
+ */
+bool AssociationLine::isEndSegmentIndex(int index) const
+{
+ // num of seg = num of points - 1
+ const int size = m_points.size() - 1;
+ Q_ASSERT(index >= 0 && index < size);
+
+ return (index == 0 || index == (size - 1));
+}
+
+/**
+ * Sets the start and end points.
+ */
+bool AssociationLine::setEndPoints(const QPointF &start, const QPointF &end)
+{
+ const int size = m_points.size();
+
+ prepareGeometryChange();
+
+ if (size == 0) {
+ m_points.insert(0, start);
+ m_points.insert(1, end);
+ }
+ else if (size == 1) {
+ m_points[0] = start;
+ m_points.insert(1, end);
+ }
+ else {
+ m_points[0] = start;
+ m_points[size-1] = end;
+ }
+
+ alignSymbols();
+ return true;
+}
+
+/**
+ * Debug helper method to write out the points.
+ */
+void AssociationLine::dumpPoints()
+{
+ for (int i = 1; i < m_points.size(); ++i) {
+ QPointF p = m_points.at(i);
+ DEBUG(DBG_SRC) << i << ". point x:" << p.x() << " / y:" << p.y();
+ }
+}
+
+/**
+ * Loads AssociationLine information saved in \a qElement XMI element.
+ */
+bool AssociationLine::loadFromXMI(QDomElement &qElement)
+{
+ QString layout = qElement.attribute(QLatin1String("layout"), QLatin1String("polyline"));
+ m_layout = fromString(layout);
+
+ QDomNode node = qElement.firstChild();
+
+ m_points.clear();
+
+ QDomElement startElement = node.toElement();
+ if(startElement.isNull() || startElement.tagName() != QLatin1String("startpoint")) {
+ return false;
+ }
+ QString x = startElement.attribute(QLatin1String("startx"), QLatin1String("0"));
+ qreal nX = x.toFloat();
+ QString y = startElement.attribute(QLatin1String("starty"), QLatin1String("0"));
+ qreal nY = y.toFloat();
+ QPointF startPoint(nX, nY);
+
+ node = startElement.nextSibling();
+ QDomElement endElement = node.toElement();
+ if(endElement.isNull() || endElement.tagName() != QLatin1String("endpoint")) {
+ return false;
+ }
+ x = endElement.attribute(QLatin1String("endx"), QLatin1String("0"));
+ nX = x.toFloat();
+ y = endElement.attribute(QLatin1String("endy"), QLatin1String("0"));
+ nY = y.toFloat();
+ QPointF endPoint(nX, nY);
+ setEndPoints(startPoint, endPoint);
+ QPointF point;
+ node = endElement.nextSibling();
+ QDomElement element = node.toElement();
+ int i = 1;
+ while(!element.isNull()) {
+ if(element.tagName() == QLatin1String("point")) {
+ x = element.attribute(QLatin1String("x"), QLatin1String("0"));
+ y = element.attribute(QLatin1String("y"), QLatin1String("0"));
+ point.setX(x.toFloat());
+ point.setY(y.toFloat());
+ insertPoint(i++, point);
+ }
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+
+ return true;
+}
+
+/**
+ * Saves association line information into XMI element named "linepath".
+ * @note Stored as linepath for backwared compatibility
+ */
+void AssociationLine::saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
+{
+ QPointF point = m_associationWidget->mapToScene(startPoint());
+ QDomElement lineElement = qDoc.createElement(QLatin1String("linepath"));
+ lineElement.setAttribute(QLatin1String("layout"), toString(m_layout));
+ QDomElement startElement = qDoc.createElement(QLatin1String("startpoint"));
+ startElement.setAttribute(QLatin1String("startx"), point.x());
+ startElement.setAttribute(QLatin1String("starty"), point.y());
+ lineElement.appendChild(startElement);
+ QDomElement endElement = qDoc.createElement(QLatin1String("endpoint"));
+ point = m_associationWidget->mapToScene(endPoint());
+ endElement.setAttribute(QLatin1String("endx"), point.x());
+ endElement.setAttribute(QLatin1String("endy"), point.y());
+ lineElement.appendChild(endElement);
+ for(int i = 1; i < count()-1; ++i) {
+ QDomElement pointElement = qDoc.createElement(QLatin1String("point"));
+ point = m_associationWidget->mapToScene(this->point(i));
+ pointElement.setAttribute(QLatin1String("x"), point.x());
+ pointElement.setAttribute(QLatin1String("y"), point.y());
+ lineElement.appendChild(pointElement);
+ }
+ qElement.appendChild(lineElement);
+}
+
+/**
+ * Returns the type of brush to use depending on the type of Association.
+ */
+QBrush AssociationLine::brush() const
+{
+ QBrush brush(Qt::solid-kf6Pattern);
+ Uml::AssociationType::Enum type = m_associationWidget->associationType();
+ if (type == Uml::AssociationType::Aggregation ||
+ type == Uml::AssociationType::Generalization ||
+ type == Uml::AssociationType::Realization) {
+ brush.setColor(Qt::white);
+ }
+ if (type == Uml::AssociationType::Composition) {
+ brush.setColor(m_associationWidget->lineColor());
+ }
+ return brush;
+}
+
+/**
+ * Returns the type of pen to use depending on the type of Association.
+ */
+QPen AssociationLine::pen() const
+{
+ QPen pen(m_associationWidget->lineColor(),
+ m_associationWidget->lineWidth(),
+ Qt::solid-kf6Line,
+ Qt::RoundCap,
+ Qt::RoundJoin);
+ Uml::AssociationType::Enum type = m_associationWidget->associationType();
+ if (type == Uml::AssociationType::Dependency ||
+ type == Uml::AssociationType::Realization ||
+ type == Uml::AssociationType::Anchor) {
+ pen.setStyle(Qt::DashLine);
+ }
+ return pen;
+}
+
+/**
+ * This method simply ensures presence of two points and
+ * adds the needed points for self associations.
+ */
+void AssociationLine::calculateInitialEndPoints()
+{
+ if (m_associationWidget->isSelf() && count() < 4) {
+ for (int i = count(); i < 4; ++i) {
+ insertPoint(i, QPointF());
+ }
+ UMLWidget *wid = m_associationWidget->widgetForRole(Uml::RoleType::B);
+ if (!wid) {
+ uError() << "AssociationWidget is partially constructed."
+ "UMLWidget for role B is null.";
+ return;
+ }
+ const QRectF rect = m_associationWidget->mapFromScene(
+ mapToScene(wid->rect()).boundingRect()).boundingRect();
+
+ qreal l = rect.left() + .25 * rect.width();
+ qreal r = rect.left() + .75 * rect.width();
+ bool drawAbove = rect.top() >= SelfAssociationMinimumHeight;
+ qreal y = drawAbove ? rect.top() : rect.bottom();
+ qreal yOffset = SelfAssociationMinimumHeight;
+ if (drawAbove) {
+ yOffset *= -1.0;
+ }
+
+ setPoint(0, QPointF(l, y));
+ setPoint(1, QPointF(l, y + yOffset));
+ setPoint(2, QPointF(r, y + yOffset));
+ setPoint(3, QPointF(r, y));
+ } else if (!m_associationWidget->isSelf() && count() < 2) {
+ setEndPoints(QPointF(), QPointF());
+ }
+}
+
+/**
+ * This method creates, deletes symbols and collaboration lines based on
+ * m_associationWidget->associationType().
+ *
+ * Call this method when associationType of m_associationWidget changes.
+ */
+void AssociationLine::reconstructSymbols()
+{
+ switch( m_associationWidget->associationType() ) {
+ case Uml::AssociationType::State:
+ case Uml::AssociationType::Activity:
+ case Uml::AssociationType::Exception:
+ case Uml::AssociationType::UniAssociation:
+ case Uml::AssociationType::Dependency:
+ setStartSymbol(Symbol::None);
+ setEndSymbol(Symbol::OpenArrow);
+ removeSubsetSymbol();
+ removeCollaborationLine();
+ break;
+
+ case Uml::AssociationType::Relationship:
+ setStartSymbol(Symbol::None);
+ setEndSymbol(Symbol::CrowFeet);
+ removeSubsetSymbol();
+ removeCollaborationLine();
+ break;
+
+ case Uml::AssociationType::Generalization:
+ case Uml::AssociationType::Realization:
+ setStartSymbol(Symbol::None);
+ setEndSymbol(Symbol::ClosedArrow);
+ removeSubsetSymbol();
+ removeCollaborationLine();
+ break;
+
+ case Uml::AssociationType::Composition:
+ case Uml::AssociationType::Aggregation:
+ setStartSymbol(Symbol::Diamond);
+ setEndSymbol(Symbol::None);
+ removeSubsetSymbol();
+ removeCollaborationLine();
+ break;
+
+ case Uml::AssociationType::Containment:
+ setStartSymbol(Symbol::Circle);
+ setEndSymbol(Symbol::None);
+ removeSubsetSymbol();
+ removeCollaborationLine();
+ break;
+
+ case Uml::AssociationType::Child2Category:
+ setStartSymbol(Symbol::None);
+ setEndSymbol(Symbol::None);
+ createSubsetSymbol();
+ removeCollaborationLine();
+ break;
+
+ case Uml::AssociationType::Coll_Message_Synchronous:
+ case Uml::AssociationType::Coll_Message_Asynchronous:
+ case Uml::AssociationType::Coll_Message_Self:
+ setStartSymbol(Symbol::None);
+ setEndSymbol(Symbol::None);
+ removeSubsetSymbol();
+ createCollaborationLine();
+ break;
+
+ default:
+ break;
+ }
+ alignSymbols();
+}
+
+/**
+ * Sets the Symbol to appear at the first line segment to \a symbol.
+ *
+ * If symbol == Symbol::None , then it deletes the symbol item.
+ */
+void AssociationLine::setStartSymbol(Symbol::SymbolType symbolType)
+{
+ Q_ASSERT(symbolType != Symbol::Count);
+ if (symbolType == Symbol::None) {
+ delete m_startSymbol;
+ m_startSymbol = 0;
+ return;
+ }
+
+ if (m_startSymbol) {
+ m_startSymbol->setSymbolType(symbolType);
+ }
+ else {
+ m_startSymbol = new Symbol(symbolType, m_associationWidget);
+ }
+ m_startSymbol->setPen(pen());
+ m_startSymbol->setBrush(brush());
+}
+
+/**
+ * Sets the Symbol to appear at the last line segment to \a symbol.
+ *
+ * If symbol == Symbol::None , then it deletes the symbol item.
+ */
+void AssociationLine::setEndSymbol(Symbol::SymbolType symbolType)
+{
+ Q_ASSERT(symbolType != Symbol::Count);
+ if (symbolType == Symbol::None) {
+ delete m_endSymbol;
+ m_endSymbol = 0;
+ return;
+ }
+
+ if (m_endSymbol) {
+ m_endSymbol->setSymbolType(symbolType);
+ }
+ else {
+ m_endSymbol = new Symbol(symbolType, m_associationWidget);
+ }
+ m_endSymbol->setPen(pen());
+ m_endSymbol->setBrush(brush());
+}
+
+/**
+ * Constructs a new subset symbol.
+ */
+void AssociationLine::createSubsetSymbol()
+{
+ delete m_subsetSymbol; // recreate
+ m_subsetSymbol = new Symbol(Symbol::Subset, m_associationWidget);
+ m_subsetSymbol->setPen(pen());
+ m_subsetSymbol->setBrush(brush());
+}
+
+/**
+ * Removes the subset symbol if it existed by deleting appropriate items.
+ */
+void AssociationLine::removeSubsetSymbol()
+{
+ delete m_subsetSymbol;
+ m_subsetSymbol = 0;
+}
+
+/**
+ * Constructs the open arrow symbol and arrow line, that would represent Collaboration line.
+ */
+void AssociationLine::createCollaborationLine()
+{
+ const QPen p = pen();
+
+ // recreate
+ delete m_collaborationLineItem;
+ delete m_collaborationLineHead;
+
+ m_collaborationLineItem = new QGraphicsLineItem(m_associationWidget);
+ m_collaborationLineItem->setPen(p);
+
+ if (m_associationWidget->associationType() == Uml::AssociationType::Coll_Message_Synchronous) {
+ m_collaborationLineHead = new Symbol(Symbol::ClosedArrow, m_associationWidget);
+ m_collaborationLineHead->setBrush(p.color());
+ }
+ else
+ m_collaborationLineHead = new Symbol(Symbol::OpenArrow, m_associationWidget);
+ m_collaborationLineHead->setPen(p);
+}
+
+/**
+ * Removes collaboration line by deleting the head and line item.
+ */
+void AssociationLine::removeCollaborationLine()
+{
+ delete m_collaborationLineItem;
+ m_collaborationLineItem = 0;
+
+ delete m_collaborationLineHead;
+ m_collaborationLineHead = 0;
+}
+
+/**
+ * This method aligns both the \b "start" and \b "end" symbols to
+ * the current angles of the \b "first" and the \b "last" line
+ * segment respectively.
+ */
+void AssociationLine::alignSymbols()
+{
+ const int sz = m_points.size();
+ if (sz < 2) {
+ // cannot align if there is no line (one line = 2 points)
+ return;
+ }
+
+ QList<QPolygonF> polygons = path().toSubpathPolygons();
+
+ if (m_startSymbol) {
+ QPolygonF firstLine = polygons.first();
+ QLineF segment(firstLine.at(1), firstLine.at(0));
+ m_startSymbol->alignTo(segment);
+ }
+
+ if (m_endSymbol) {
+ QPolygonF lastLine = polygons.last();
+ int maxIndex = lastLine.size();
+ QLineF segment(lastLine.at(maxIndex-2), lastLine.at(maxIndex-1));
+ m_endSymbol->alignTo(segment);
+ }
+
+ if (m_subsetSymbol) {
+ QPointF p1 = path().pointAtPercent(0.4);
+ QPointF p2 = path().pointAtPercent(0.5);
+ QLineF segment(p1, p2);
+ m_subsetSymbol->alignTo(segment);
+ }
+
+ if (m_collaborationLineItem) {
+ const qreal distance = 10;
+ const int midSegmentIndex = (sz - 1) / 2;
+
+ const QPointF a = m_points.at(midSegmentIndex);
+ const QPointF b = m_points.at(midSegmentIndex + 1);
+
+ if (a == b)
+ return;
+
+ const QPointF p1 = (a + b) / 2.0;
+ const QPointF p2 = (p1 + b) / 2.0;
+
+ // Reversed line as we want normal in opposite direction.
+ QLineF segment(p2, p1);
+ QLineF normal = segment.normalVector().unitVector();
+ normal.setLength(distance);
+
+ QLineF actualLine;
+ actualLine.setP2(normal.p2());
+
+ normal.translate(p1 - p2);
+ actualLine.setP1(normal.p2());
+
+ m_collaborationLineItem->setLine(actualLine);
+ m_collaborationLineHead->alignTo(actualLine);
+ }
+}
+
+/**
+ * @return The path of the AssociationLine.
+ */
+QPainterPath AssociationLine::path() const
+{
+ if (m_points.count() > 0) {
+ QPainterPath path;
+ switch (m_layout) {
+ case Direct:
+ path.moveTo(m_points.first());
+ path.lineTo(m_points.last());
+ break;
+
+ case Spline:
+ path = createBezierCurve(m_points);
+ break;
+
+ case Orthogonal:
+ path = createOrthogonalPath(m_points);
+ break;
+
+ case Polyline:
+ default:
+ QPolygonF polygon(m_points);
+ path.addPolygon(polygon);
+ break;
+ }
+ return path;
+ }
+ else {
+ return QPainterPath();
+ }
+}
+
+/**
+ * The points are used for the bounding rect. The reason is,
+ * that for splines the control points are further away from the path.
+ * @return The bounding rectangle for the AssociationLine.
+ */
+QRectF AssociationLine::boundingRect() const
+{
+ QPolygonF polygon(m_points);
+ QRectF rect = polygon.boundingRect();
+ const qreal margin(5.0);
+ rect.adjust(-margin, -margin, margin, margin);
+ return rect;
+}
+
+/**
+ * @return The shape of the AssociationLine.
+ */
+QPainterPath AssociationLine::shape() const
+{
+ QPainterPathStroker stroker;
+ stroker.setWidth(qMax<qreal>(2*SelectedPointDiameter, pen().widthF()) + 2.0); // allow delta region
+ stroker.setCapStyle(Qt::FlatCap);
+ return stroker.createStroke(path());
+}
+
+/**
+ * Convert enum LayoutType to string.
+ */
+QString AssociationLine::toString(LayoutType layout)
+{
+ return QLatin1String(ENUM_NAME(AssociationLine, LayoutType, layout));
+}
+
+/**
+ * Convert string to enum LayoutType.
+ */
+AssociationLine::LayoutType AssociationLine::fromString(const QString &layout)
+{
+ if (layout == QLatin1String("Direct"))
+ return Direct;
+ if (layout == QLatin1String("Spline"))
+ return Spline;
+ if (layout == QLatin1String("Orthogonal"))
+ return Orthogonal;
+ return Polyline;
+}
+
+/**
+ * Return the layout type of the association line.
+ * @return the currently used layout
+ */
+AssociationLine::LayoutType AssociationLine::layout() const
+{
+ return m_layout;
+}
+
+/**
+ * Set the layout type of the association line.
+ * @param layout the desired layout to set
+ */
+void AssociationLine::setLayout(LayoutType layout)
+{
+ prepareGeometryChange();
+ m_layout = layout;
+ DEBUG(DBG_SRC) << "new layout = " << toString(m_layout);
+ if (m_layout == Spline) {
+ createSplinePoints();
+ }
+ alignSymbols();
+}
+
+/**
+ * For a cubic Bezier curve at least four points are needed.
+ * If there are less, the missing points will be created.
+ * Note: Implementation is only for two points.
+ */
+void AssociationLine::createSplinePoints()
+{
+ if (m_points.size() == 2) { // create two points
+ QPointF p1 = m_points.first(); // start point
+ QPointF p2 = m_points.last(); // end point
+ qreal dx = p2.x() - p1.x();
+ qreal dy = p2.y() - p1.y();
+ qreal oneThirdX = 0.33 * dx;
+ qreal oneThirdY = 0.33 * dy;
+ QPointF c1(p1.x() + oneThirdX, // control point 1
+ p1.y() - oneThirdY);
+ QPointF c2(p2.x() - oneThirdX, // control point 2
+ p2.y() + oneThirdY);
+ insertPoint(1, c1);
+ insertPoint(2, c2);
+ }
+ if (m_points.size() == 3) { // create one point
+ // insertPoint(1 or 2, );
+ // Note: For now we use a quadratic Bezier curve in createBezierCurve(...).
+ }
+}
+
+/**
+ * Returns a Bézier path from given points.
+ * @param points points which define the Bézier curve
+ * @return cubic Bézier spline
+ */
+QPainterPath AssociationLine::createBezierCurve(QVector<QPointF> points)
+{
+ QPainterPath path;
+ if (points.size() > 3) { // cubic Bezier curve(s)
+ path.moveTo(points.at(0));
+ int i = 1;
+ while (i + 2 < points.size()) {
+ path.cubicTo(points.at(i), points.at(i+1), points.at(i+2));
+ i += 3;
+ }
+ while (i < points.size()) { // draw a line if points are not modulo 3
+ path.lineTo(points.at(i));
+ ++i;
+ }
+ }
+ else {
+ if (points.size() == 3) { // quadratic Bezier curve
+ path.moveTo(points.at(0));
+ path.quadTo(points.at(1), points.at(2));
+ }
+ else { // should not be reached
+ QPolygonF polygon(points);
+ path.addPolygon(polygon);
+ }
+ }
+ return path;
+}
+
+/**
+ * Returns an orthogonal path constructed of vertical and horizontal segments
+ * through the given points.
+ * @param points base points for the path
+ * @return orthogonal path
+ */
+QPainterPath AssociationLine::createOrthogonalPath(QVector<QPointF> points)
+{
+ QPainterPath path;
+ if (points.size() > 1) {
+ QPointF start = points.first();
+ QPointF end = points.last();
+ qreal deltaX = fabs(start.x() - end.x());
+ qreal deltaY = fabs(start.y() - end.y());
+ // DEBUG("AssociationLine") << "start=" << start << " / end=" << end
+ // << " / deltaX=" << deltaX << " / deltaY=" << deltaY;
+ QVector<QPointF> vector;
+ for (int i = 0; i < points.size() - 1; ++i) {
+ QPointF curr = points.at(i);
+ QPointF next = points.at(i+1);
+ QPointF center = (next + curr)/2.0;
+
+ vector.append(curr);
+ if (deltaX < deltaY) {
+ // go vertical first
+ vector.append(QPointF(curr.x(), center.y()));
+ vector.append(QPointF(next.x(), center.y()));
+ }
+ else {
+ // go horizontal first
+ vector.append(QPointF(center.x(), curr.y()));
+ vector.append(QPointF(center.x(), next.y()));
+ }
+ vector.append(next);
+ }
+
+ QPolygonF rectLine(vector);
+ path.addPolygon(rectLine);
+ }
+ else {
+ QPolygonF polygon(points);
+ path.addPolygon(polygon);
+ }
+ return path;
+}
+
+/**
+ * Reimplemented from QGraphicsItem::paint.
+ * Draws the AssociationLine and also takes care of highlighting active point or line.
+ */
+void AssociationLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
+{
+ Q_UNUSED(widget)
+ QPen _pen = pen();
+ const QColor orig = _pen.color().lighter();
+ QColor invertedColor(orig.green(), orig.blue(), orig.red());
+ if (invertedColor == _pen.color()) {
+ // Ensure different color.
+ invertedColor.setRed((invertedColor.red() + 50) % 256);
+ }
+ invertedColor.setAlpha(150);
+
+ int sz = m_points.size();
+ if (sz < 1) {
+ // not enough points - do nothing
+ return;
+ }
+
+ QPointF savedStart = m_points.first();
+ QPointF savedEnd = m_points.last();
+
+ // modify the m_points array not to include the Symbol, the value depends on Symbol
+ if (m_startSymbol) {
+ QPointF newStart = m_startSymbol->mapToParent(m_startSymbol->symbolEndPoints().first);
+ m_points[0] = newStart;
+ }
+
+ if (m_endSymbol) {
+ QPointF newEnd = m_endSymbol->mapToParent(m_endSymbol->symbolEndPoints().first);
+ m_points[sz - 1] = newEnd;
+ }
+
+ painter->setPen(_pen);
+ painter->setBrush(Qt::NoBrush);
+ painter->drawPath(path());
+
+ if (option->state & QStyle::State_Selected) {
+ // make the association broader in the selected state
+ QPainterPathStroker stroker;
+ stroker.setWidth(3.0);
+ QPainterPath outline = stroker.createStroke(path());
+ QColor shadowColor(Qt::lightGray);
+ shadowColor.setAlpha(80);
+ QBrush shadowBrush(shadowColor);
+ painter->setBrush(shadowBrush);
+ painter->setPen(Qt::NoPen);
+ painter->drawPath(outline);
+
+ // set color for selected painting
+ _pen.setColor(Qt::blue);
+ QRectF circle(0, 0, SelectedPointDiameter, SelectedPointDiameter);
+ painter->setBrush(_pen.color());
+ painter->setPen(Qt::NoPen);
+
+ // draw points
+ circle.moveCenter(savedStart);
+ painter->drawRect(circle);
+ for (int i = 1; i < sz-1; ++i) {
+ if (i != m_activePointIndex) {
+ circle.moveCenter(m_points.at(i));
+ painter->drawRect(circle);
+ }
+ }
+ circle.moveCenter(savedEnd);
+ painter->drawRect(circle);
+
+ if (m_activePointIndex != -1) {
+ painter->setBrush(invertedColor);
+ painter->setPen(Qt::NoPen);
+ circle.setWidth(1.5*SelectedPointDiameter);
+ circle.setHeight(1.5*SelectedPointDiameter);
+ circle.moveCenter(m_points.at(m_activePointIndex));
+ painter->drawEllipse(circle);
+ }
+ else if (m_activeSegmentIndex != -1) {
+ if (m_layout == Polyline) {
+ painter->setPen(QPen(invertedColor, _pen.widthF() + 1));
+ painter->setBrush(Qt::NoBrush);
+
+ QLineF segmentLine(m_points[m_activeSegmentIndex], m_points[m_activeSegmentIndex + 1]);
+ painter->drawLine(segmentLine);
+ }
+ }
+ // debug info
+ if (Tracer::instance()->isEnabled(QString::fromLatin1(metaObject()->className()))) {
+ painter->setPen(Qt::green);
+ painter->setBrush(Qt::NoBrush);
+ painter->drawPath(shape());
+ painter->setPen(Qt::red);
+ painter->drawRect(boundingRect());
+ // origin
+ painter->drawLine(-10, 0, 10, 0);
+ painter->drawLine(0, -10, 0, 10);
+ }
+
+ }
+
+ // now restore the points array
+ m_points[0] = savedStart;
+ m_points[sz - 1] = savedEnd;
+}
+
+/**
+ * Determines the active point or segment, the latter being given more priority.
+ */
+void AssociationLine::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ DEBUG(DBG_SRC) << "at " << event->scenePos();
+ if (event->buttons() & Qt::LeftButton) {
+ m_activePointIndex = closestPointIndex(event->scenePos());
+ if (m_activePointIndex != -1 && isEndPointIndex(m_activePointIndex)) {
+ // end points are not drawn and hence not active
+ m_activePointIndex = -1;
+ }
+ // calculate only if active point index is -1
+ m_activeSegmentIndex = (m_activePointIndex != -1) ? -1 : closestSegmentIndex(event->scenePos());
+ }
+ else if (event->buttons() & Qt::RightButton) {
+ DEBUG(DBG_SRC) << "call context menu of association widget at " << event->scenePos();
+ }
+ else {
+ m_activePointIndex = -1;
+ m_activeSegmentIndex = -1;
+ }
+}
+
+/**
+ * Moves the point or line if active.
+ */
+void AssociationLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ UMLScene* scene = m_associationWidget->umlScene();
+
+ QPointF oldPos = event->scenePos();
+ QPointF newPos(
+ scene->snappedX(oldPos.x()),
+ scene->snappedY(oldPos.y())
+ );
+
+ // Prevent the moving vertex from disappearing underneath a widget
+ // (else there's no way to get it back.)
+ UMLWidget *onW = scene->widgetAt(newPos);
+ if (onW && onW->baseType() != WidgetBase::wt_Box) { // boxes are transparent
+ const qreal pX = newPos.x();
+ const qreal pY = newPos.y();
+ const qreal wX = onW->x();
+ const qreal wY = onW->y();
+ const qreal wWidth = onW->width();
+ const qreal wHeight = onW->height();
+ if (pX > wX && pX < wX + wWidth) {
+ const qreal midX = wX + wWidth / 2.0;
+ if (pX <= midX)
+ newPos.setX(wX);
+ else
+ newPos.setX(wX + wWidth);
+ }
+ if (pY > wY && pY < wY + wHeight) {
+ const qreal midY = wY + wHeight / 2.0;
+ if (pY <= midY)
+ newPos.setY(wY);
+ else
+ newPos.setY(wY + wHeight);
+ }
+ }
+
+ if (m_activePointIndex != -1) {
+ // Move a single point (snap behaviour)
+ setPoint(m_activePointIndex, newPos);
+ }
+ else if (m_activeSegmentIndex != -1 && !isEndSegmentIndex(m_activeSegmentIndex)) {
+ // Move a segment (between two points, snap behaviour not implemented)
+ QPointF delta = event->scenePos() - event->lastScenePos();
+ setPoint(m_activeSegmentIndex, m_points[m_activeSegmentIndex] + delta);
+ setPoint(m_activeSegmentIndex + 1, m_points[m_activeSegmentIndex + 1] + delta);
+ }
+}
+
+/**
+ * Reset active indices and also push undo command.
+ */
+void AssociationLine::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->buttons() & Qt::LeftButton) {
+ m_activeSegmentIndex = -1;
+ m_activePointIndex = -1;
+ }
+}
+
+/**
+ * Calculates the "to be highlighted" point and segment indicies
+ * and updates if necessary.
+ */
+void AssociationLine::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ DEBUG(DBG_SRC) << "at " << event->scenePos();
+ int oldPointIndex = m_activePointIndex;
+ int oldSegmentIndex = m_activeSegmentIndex;
+
+ m_activePointIndex = closestPointIndex(event->scenePos());
+ // End points are not drawn and hence not active.
+ if (m_activePointIndex != -1 && isEndPointIndex(m_activePointIndex)) {
+ m_activePointIndex = -1;
+ }
+ // Activate segment index only if point index is -1
+ m_activeSegmentIndex = (m_activePointIndex != -1) ? -1 : closestSegmentIndex(event->scenePos());
+
+ bool isChanged = (oldSegmentIndex != m_activeSegmentIndex || oldPointIndex != m_activePointIndex);
+ if (isChanged) {
+ m_associationWidget->update();
+ }
+}
+
+/**
+ * Calculates the "to be highlighted" point and segment indicies
+ * and updates if necessary.
+ */
+void AssociationLine::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+{
+ int oldPointIndex = m_activePointIndex;
+ int oldSegmentIndex = m_activeSegmentIndex;
+
+ m_activePointIndex = closestPointIndex(event->scenePos());
+ // End points are not drawn and hence not active.
+ if (m_activePointIndex != -1 && isEndPointIndex(m_activePointIndex)) {
+ m_activePointIndex = -1;
+ }
+ // Activate segment index only if point index is -1
+ m_activeSegmentIndex = (m_activePointIndex != -1) ? -1 : closestSegmentIndex(event->scenePos());
+
+ bool isChanged = (oldSegmentIndex != m_activeSegmentIndex || oldPointIndex != m_activePointIndex);
+ if (isChanged) {
+ m_associationWidget->update();
+ }
+}
+
+/**
+ * Reset active indicies and updates.
+ */
+void AssociationLine::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ DEBUG(DBG_SRC) << "at " << event->scenePos();
+ //Q_UNUSED(event)
+ m_activePointIndex = -1;
+ m_activeSegmentIndex = -1;
+ m_associationWidget->update();
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * SymbolEndPoints:
+ * The first point is where the AssociationLine's visible line is
+ * supposed to end.
+ * The second points is where the actual symbol part is to appear.
+ */
+Symbol::SymbolProperty Symbol::symbolTable[Count] =
+{
+ {
+ QRectF(-6, 0, 12, 10), QPainterPath(), QLineF(0, 0, 0, 10),
+ SymbolEndPoints(QPointF(0, 10), QPointF(0, 10))
+ },
+ {
+ QRectF(-6, 0, 12, 10), QPainterPath(), QLineF(0, 0, 0, 10),
+ SymbolEndPoints(QPointF(0, 0), QPointF(0, 10))
+ },
+ {
+ QRectF(-6, 0, 12, 10), QPainterPath(), QLineF(0, 0, 0, 10),
+ SymbolEndPoints(QPointF(0, 10), QPointF(0, 10))
+ },
+ {
+ QRectF(-5, -10, 10, 20), QPainterPath(), QLineF(0, -10, 0, 10),
+ SymbolEndPoints(QPointF(0, -10), QPointF(0, 10))
+ },
+ {
+ QRectF(-15, -10, 30, 20), QPainterPath(), QLineF(-10, 0, 0, 0),
+ SymbolEndPoints(QPointF(0, 0), QPointF(0, 0))
+ },
+ {
+ QRectF(-8, -8, 16, 16), QPainterPath(), QLineF(0, -8, 0, 8),
+ SymbolEndPoints(QPointF(0, -8), QPointF(0, 8))
+ }
+
+};
+
+/**
+ * @internal A convenience method to setup shapes of all symbols.
+ */
+void Symbol::setupSymbolTable()
+{
+ SymbolProperty &openArrow = symbolTable[OpenArrow];
+ if (openArrow.shape.isEmpty()) {
+ QRectF rect = openArrow.boundRect;
+ // Defines a 'V' shape arrow fitting in the bound rect.
+ openArrow.shape.moveTo(rect.topLeft());
+ openArrow.shape.lineTo(rect.center().x(), rect.bottom());
+ openArrow.shape.lineTo(rect.topRight());
+ }
+
+ SymbolProperty &closedArrow = symbolTable[ClosedArrow];
+ if (closedArrow.shape.isEmpty()) {
+ QRectF rect = closedArrow.boundRect;
+ // Defines a 'V' shape arrow fitting in the bound rect.
+ closedArrow.shape.moveTo(rect.topLeft());
+ closedArrow.shape.lineTo(rect.center().x(), rect.bottom());
+ closedArrow.shape.lineTo(rect.topRight());
+ closedArrow.shape.lineTo(rect.topLeft());
+ }
+
+ SymbolProperty &crowFeet = symbolTable[CrowFeet];
+ if (crowFeet.shape.isEmpty()) {
+ QRectF rect = crowFeet.boundRect;
+ // Defines a crowFeet fitting in the bound rect.
+ QPointF topMid(rect.center().x(), rect.top());
+
+ // left leg
+ crowFeet.shape.moveTo(rect.bottomLeft());
+ crowFeet.shape.lineTo(topMid);
+
+ // middle leg
+ crowFeet.shape.moveTo(rect.center().x(), rect.bottom());
+ crowFeet.shape.lineTo(topMid);
+
+ // right leg
+ crowFeet.shape.moveTo(rect.bottomRight());
+ crowFeet.shape.lineTo(topMid);
+ }
+
+ SymbolProperty &diamond = symbolTable[Diamond];
+ if (diamond.shape.isEmpty()) {
+ QRectF rect = diamond.boundRect;
+ // Defines a 'diamond' shape fitting in the bound rect.
+ diamond.shape.moveTo(rect.center().x(), rect.top());
+ diamond.shape.lineTo(rect.left(), rect.center().y());
+ diamond.shape.lineTo(rect.center().x(), rect.bottom());
+ diamond.shape.lineTo(rect.right(), rect.center().y());
+ diamond.shape.lineTo(rect.center().x(), rect.top());
+ }
+
+ SymbolProperty &subset = symbolTable[Subset];
+ if (subset.shape.isEmpty()) {
+ QRectF rect = subset.boundRect;
+ // Defines an arc fitting in bound rect.
+ qreal start = 90, span = 180;
+ subset.shape.arcMoveTo(rect, start);
+ subset.shape.arcTo(rect, start, span);
+ }
+
+ SymbolProperty &circle = symbolTable[Circle];
+ if (circle.shape.isEmpty()) {
+ QRectF rect = circle.boundRect;
+ // Defines a circle with a horizontal-vertical cross lines.
+ circle.shape.addEllipse(rect);
+
+ circle.shape.moveTo(rect.center().x(), rect.top());
+ circle.shape.lineTo(rect.center().x(), rect.bottom());
+
+ circle.shape.moveTo(rect.left(), rect.center().y());
+ circle.shape.lineTo(rect.right(), rect.center().y());
+ }
+
+}
+
+/**
+ * Constructs a Symbol with current symbol being \a symbol and
+ * parented to \a parent.
+ */
+Symbol::Symbol(SymbolType symbolType, QGraphicsItem *parent)
+ : QGraphicsItem(parent),
+ m_symbolType(symbolType)
+{
+ // ensure SymbolTable is validly initialized
+ setupSymbolTable();
+}
+
+/**
+ * Destructor.
+ */
+Symbol::~Symbol()
+{
+}
+
+/**
+ * @return The current symbol being represented.
+ */
+Symbol::SymbolType Symbol::symbolType() const
+{
+ return m_symbolType;
+}
+
+/**
+ * Sets the current symbol type to \a symbol and updates the geometry.
+ */
+void Symbol::setSymbolType(SymbolType symbolType)
+{
+ prepareGeometryChange(); // calls update implicitly
+ m_symbolType = symbolType;
+}
+
+/**
+ * Draws the current symbol using the QPainterPath stored for the current
+ * symbol.
+ */
+void Symbol::paint(QPainter *painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
+{
+ Q_UNUSED(option) Q_UNUSED(widget)
+ painter->setPen(m_pen);
+ switch (m_symbolType) {
+ case ClosedArrow:
+ case CrowFeet:
+ case Diamond:
+ painter->setBrush(m_brush);
+ break;
+ default:
+ break;
+ }
+ painter->drawPath(Symbol::symbolTable[m_symbolType].shape);
+}
+
+/**
+ * @return The bound rectangle for this based on current symbol.
+ */
+QRectF Symbol::boundingRect() const
+{
+ const qreal adj = .5 * m_pen.widthF();
+ return Symbol::symbolTable[m_symbolType].boundRect.
+ adjusted(-adj, -adj, adj, adj);
+}
+
+/**
+ * @return The path for this based on current symbol.
+ */
+QPainterPath Symbol::shape() const
+{
+ QPainterPath path;
+ path.addRect(boundingRect());
+ return path;
+}
+
+/**
+ * This method aligns *this* Symbol to the line being
+ * passed. That is, it ensures that the axis of this symbol aligns
+ * exactly with the \a "to" line passed.
+ *
+ * Also this item is moved such that the second end point of the
+ * SymbolEndPoints for the current symbol *collides* with the second end
+ * point of \a "to" line.
+ */
+void Symbol::alignTo(const QLineF& to)
+{
+ QLineF toMapped(mapFromParent(to.p1()), mapFromParent(to.p2()));
+
+ QLineF origAxis = Symbol::symbolTable[m_symbolType].axisLine;
+ QLineF translatedAxis = origAxis.translated(toMapped.p2() - origAxis.p2());
+
+ qreal angle = translatedAxis.angleTo(toMapped);
+ setRotation(rotation() - angle);
+
+ QPointF delta = to.p2() - mapToParent(symbolEndPoints().second);
+ moveBy(delta.x(), delta.y());
+}
+
+/**
+ * @return The end points for the symbol.
+ */
+Symbol::SymbolEndPoints Symbol::symbolEndPoints() const
+{
+ return Symbol::symbolTable[m_symbolType].endPoints;
+}
+
+/**
+ * @return The pen used to draw symbol.
+ */
+QPen Symbol::pen() const
+{
+ return m_pen;
+}
+
+/**
+ * Sets the pen used to draw the symbol.
+ */
+void Symbol::setPen(const QPen& pen)
+{
+ prepareGeometryChange();
+ m_pen = pen;
+ if (m_symbolType == ClosedArrow)
+ m_pen.setStyle(Qt::solid-kf6Line);
+}
+
+/**
+ * @return The brush used to fill symbol.
+ */
+QBrush Symbol::brush() const
+{
+ return m_brush;
+}
+
+/**
+ * Sets the brush used to fill symbol.
+ */
+void Symbol::setBrush(const QBrush &brush)
+{
+ m_brush = brush;
+ update();
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/associationline.h umbrello-kf6-15.08.1/umbrello/umlwidgets/associationline.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/associationline.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/associationline.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,207 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ASSOCIATIONLINE_H
+#define ASSOCIATIONLINE_H
+
+#include "basictypes.h"
+
+#include <QGraphicsObject>
+#include <QList>
+#include <QPen>
+#include <QPoint>
+
+// forward declarations
+class AssociationWidget;
+class QDomDocument;
+class QDomElement;
+class QPainter;
+
+/**
+ * This class provides with various symbols that can be embedded in
+ * AssociationLine. It also provides with convenience methods to align
+ * the symbol to AssociationLine.
+ */
+class Symbol : public QGraphicsItem
+{
+ public:
+ typedef QPair<QPointF, QPointF> SymbolEndPoints;
+
+ /**
+ * This enumeration lists all the symbols that can be used as
+ * embedded on AssociationLine.
+ */
+ enum SymbolType {
+ None = -1,
+ OpenArrow,
+ ClosedArrow,
+ CrowFeet,
+ Diamond,
+ Subset,
+ Circle,
+ Count
+ };
+
+ explicit Symbol(SymbolType symbolType, QGraphicsItem *parent = 0);
+ virtual ~Symbol();
+
+ SymbolType symbolType() const;
+ void setSymbolType(SymbolType symbolType);
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+ virtual QRectF boundingRect() const;
+ virtual QPainterPath shape() const;
+
+ void alignTo(const QLineF& line);
+ SymbolEndPoints symbolEndPoints() const;
+
+ QPen pen() const;
+ void setPen(const QPen &pen);
+
+ QBrush brush() const;
+ void setBrush(const QBrush& brush);
+
+ private:
+ QPen m_pen; ///< pen used to draw Symbol
+ QBrush m_brush; ///< brush used to fill Symbol
+ SymbolType m_symbolType; ///< current symbol being represented by this item
+
+ /// A structure to hold a table of values for all symbols.
+ struct SymbolProperty {
+ QRectF boundRect;
+ QPainterPath shape;
+ QLineF axisLine;
+ SymbolEndPoints endPoints;
+ };
+
+ static SymbolProperty symbolTable[Symbol::Count]; ///< a table which stores all symbol properties
+ static void setupSymbolTable();
+};
+
+/**
+ * A convenience class that encapsulates geometry management, handles
+ * mouse and hover events, embeds and aligns symbols and finally draws the
+ * lines and points.
+ * Context menu events are handled in AssociationWidget.
+ *
+ * This class is infact a draw and event handling proxy for
+ * AssociationWidget.
+ *
+ * @note m_activePointIndex and m_activeSegmentIndex can't be
+ * active at same time!
+ *
+ * @author Gopala Krishna
+ * @author Andi Fischer
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class AssociationLine : public QGraphicsObject
+{
+ Q_OBJECT
+ Q_ENUMS(LayoutType)
+public:
+ enum LayoutType {
+ Direct = 1,
+ Orthogonal,
+ Polyline,
+ Spline
+ };
+
+ static QString toString(LayoutType layout);
+ static LayoutType fromString(const QString& layout);
+
+ explicit AssociationLine(AssociationWidget *association);
+ virtual ~AssociationLine();
+
+ QPointF point(int index) const;
+ bool setPoint(int index, const QPointF& point);
+ QPointF startPoint() const;
+ QPointF endPoint() const;
+
+ void insertPoint(int index, const QPointF& point);
+ void removePoint(int index);
+
+ int count() const;
+ void cleanup();
+
+ void optimizeLinePoints();
+
+ int closestPointIndex(const QPointF& point, qreal delta = Delta) const;
+ int closestSegmentIndex(const QPointF& point, qreal delta = Delta) const;
+
+ bool isEndPointIndex(int index) const;
+ bool isEndSegmentIndex(int index) const;
+
+ bool setEndPoints(const QPointF &start, const QPointF &end);
+
+ void dumpPoints();
+
+ bool loadFromXMI(QDomElement &qElement);
+ void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
+
+ QBrush brush() const;
+ QPen pen() const;
+
+ virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
+
+ QPainterPath path() const;
+
+ QRectF boundingRect() const;
+ QPainterPath shape() const;
+
+ LayoutType layout() const;
+ void setLayout(LayoutType layout);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+
+ void calculateInitialEndPoints();
+
+ void reconstructSymbols();
+
+private:
+ void setStartSymbol(Symbol::SymbolType symbolType);
+ void setEndSymbol(Symbol::SymbolType symbolType);
+
+ void createSubsetSymbol();
+ void removeSubsetSymbol();
+
+ void createCollaborationLine();
+ void removeCollaborationLine();
+
+ void alignSymbols();
+
+ void createSplinePoints();
+
+ AssociationWidget *m_associationWidget; ///< association widget for which this line represents
+ QVector<QPointF> m_points; ///< points representing the association line
+ int m_activePointIndex; ///< index of active point which can be dragged to modify association line
+ int m_activeSegmentIndex; ///< index of active segment
+ Symbol *m_startSymbol; ///< symbol drawn at the end of "first" line segment
+ Symbol *m_endSymbol; ///< symbol drawn at the end of "last" line segment
+ Symbol *m_subsetSymbol; ///< subset symbol
+ QGraphicsLineItem *m_collaborationLineItem; ///< parallel arrow line drawn in case of collaboration message
+ Symbol *m_collaborationLineHead; ///< arrow head drawn at end of m_collaborationLineItem
+ LayoutType m_layout;
+
+ static QPainterPath createBezierCurve(QVector<QPointF> points);
+ static QPainterPath createOrthogonalPath(QVector<QPointF> points);
+
+ static const qreal Delta; ///< default delta for fuzzy recognition of points closer to point
+ static const qreal SelectedPointDiameter; ///< radius of circles drawn to show "selection"
+ static const qreal SelfAssociationMinimumHeight; ///< minimum height for self association's loop
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/associationwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/associationwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/associationwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/associationwidget.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,4407 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "associationwidget.h"
+
+// app includes
+#include "association.h"
+#include "associationline.h"
+#include "associationpropertiesdialog.h"
+#include "assocrules.h"
+#include "attribute.h"
+#include "classifier.h"
+#include "classifierwidget.h"
+#include "debug_utils.h"
+#include "docwindow.h"
+#include "entity.h"
+#include "floatingtextwidget.h"
+#include "listpopupmenu.h"
+#include "messagewidget.h"
+#include "objectwidget.h"
+#include "operation.h"
+#include "optionstate.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+#include "umlwidget.h"
+#include "widget_utils.h"
+
+// kde includes
+#if QT_VERSION < 0x050000
+#include <kcolordialog.h>
+#include <kfontdialog.h>
+#include <kinputdialog.h>
+#endif
+#include <KLocalizedString>
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QColorDialog>
+#include <QFontDialog>
+#include <QInputDialog>
+#endif
+#include <QPainterPath>
+#include <QPointer>
+#include <QRegExpValidator>
+#include <QApplication>
+
+// system includes
+#include <cmath>
+
+#define DBG_AW() DEBUG(QLatin1String("AssociationWidget"))
+DEBUG_REGISTER_DISABLED(AssociationWidget)
+
+using namespace Uml;
+
+/**
+ * Constructor is private because the static create() methods shall
+ * be used for constructing AssociationWidgets.
+ *
+ * @param scene The parent view of this widget.
+ */
+AssociationWidget::AssociationWidget(UMLScene *scene)
+ : WidgetBase(scene, WidgetBase::wt_Association),
+ m_positions_len(0),
+ m_activated(false),
+ m_unNameLineSegment(-1),
+ m_nLinePathSegmentIndex(-1),
+ m_pAssocClassLine(0),
+ m_pAssocClassLineSel0(0),
+ m_pAssocClassLineSel1(0),
+ m_associationLine(new AssociationLine(this)),
+ m_associationClass(0),
+ m_associationType(Uml::AssociationType::Association),
+ m_nameWidget(0)
+{
+ // floating text widgets objects owned by this association
+ m_role[RoleType::A].changeabilityWidget = 0;
+ m_role[RoleType::B].changeabilityWidget = 0;
+ m_role[RoleType::A].multiplicityWidget = 0;
+ m_role[RoleType::B].multiplicityWidget = 0;
+ m_role[RoleType::A].roleWidget = 0;
+ m_role[RoleType::B].roleWidget = 0;
+ m_role[RoleType::A].umlWidget = 0;
+ m_role[RoleType::B].umlWidget = 0;
+
+ // associationwidget attributes
+ m_role[RoleType::A].m_WidgetRegion = Uml::Region::Error;
+ m_role[RoleType::B].m_WidgetRegion = Uml::Region::Error;
+ m_role[RoleType::A].m_nIndex = 0;
+ m_role[RoleType::B].m_nIndex = 0;
+ m_role[RoleType::A].m_nTotalCount = 0;
+ m_role[RoleType::B].m_nTotalCount = 0;
+ m_role[RoleType::A].visibility = Uml::Visibility::Public;
+ m_role[RoleType::B].visibility = Uml::Visibility::Public;
+ m_role[RoleType::A].changeability = Uml::Changeability::Changeable;
+ m_role[RoleType::B].changeability = Uml::Changeability::Changeable;
+
+ setFlag(QGraphicsLineItem::ItemIsSelectable);
+ setAcceptHoverEvents(true);
+}
+
+/**
+ * This constructor is really only for loading from XMI, otherwise it
+ * should not be allowed as it creates an incomplete associationwidget.
+ *
+ * @param scene The parent view of this widget.
+ */
+AssociationWidget* AssociationWidget::create(UMLScene *scene)
+{
+ AssociationWidget* instance = new AssociationWidget(scene);
+ return instance;
+}
+
+/**
+ * Preferred constructor (static factory method.)
+ *
+ * @param scene The parent view of this widget.
+ * @param pWidgetA Pointer to the role A widget for the association.
+ * @param assocType The AssociationType::Enum for this association.
+ * @param pWidgetB Pointer to the role B widget for the association.
+ * @param umlobject Pointer to the underlying UMLObject (if applicable.)
+ */
+AssociationWidget* AssociationWidget::create
+ (UMLScene *scene, UMLWidget* pWidgetA,
+ Uml::AssociationType::Enum assocType, UMLWidget* pWidgetB,
+ UMLObject *umlobject /* = NULL */)
+{
+ AssociationWidget* instance = new AssociationWidget(scene);
+ if (umlobject) {
+ instance->setUMLObject(umlobject);
+ } else {
+ // set up UMLAssociation obj if assoc is represented and both roles are UML objects
+ if (Uml::AssociationType::hasUMLRepresentation(assocType)) {
+ UMLObject* umlRoleA = pWidgetA->umlObject();
+ UMLObject* umlRoleB = pWidgetB->umlObject();
+ if (umlRoleA != NULL && umlRoleB != NULL) {
+ bool swap;
+
+ // This is not correct. We could very easily have more than one
+ // of the same type of association between the same two objects.
+ // Just create the association. This search should have been
+ // done BEFORE creation of the widget, if it mattered to the code.
+ // But lets leave check in here for the time being so that debugging
+ // output is shown, in case there is a collision with code elsewhere.
+ UMLDoc *doc = UMLApp::app()->document();
+ UMLAssociation *myAssoc = doc->findAssociation(assocType, umlRoleA, umlRoleB, &swap);
+ if (myAssoc != NULL) {
+ switch (assocType) {
+ case Uml::AssociationType::Generalization:
+ case Uml::AssociationType::Dependency:
+ case Uml::AssociationType::Association_Self:
+ case Uml::AssociationType::Coll_Message_Self:
+ case Uml::AssociationType::Seq_Message_Self:
+ case Uml::AssociationType::Containment:
+ case Uml::AssociationType::Realization:
+ DBG_AW() << "Ignoring second construction of same assoctype "
+ << assocType << " between " << umlRoleA->name()
+ << " and " << umlRoleB->name();
+ break;
+ default:
+ DBG_AW() << "constructing a similar or exact same assoctype "
+ << assocType << " between " << umlRoleA->name() << " and "
+ << umlRoleB->name() << "as an already existing assoc (swap="
+ << swap << ")";
+ // now, just create a new association anyways
+ myAssoc = NULL;
+ break;
+ }
+ }
+ if (myAssoc == NULL) {
+ myAssoc = new UMLAssociation(assocType, umlRoleA, umlRoleB);
+ // CHECK: myAssoc is not yet inserted at any parent UMLPackage -
+ // need to check carefully that all callers do this, lest it be
+ // orphaned.
+ // ToolBarStateAssociation::addAssociationInViewAndDoc() is
+ // okay in this regard.
+ }
+ instance->setUMLAssociation(myAssoc);
+ }
+ }
+ }
+
+ instance->setWidgetForRole(pWidgetA, RoleType::A);
+ instance->setWidgetForRole(pWidgetB, RoleType::B);
+
+ instance->setAssociationType(assocType);
+
+ instance->calculateEndingPoints();
+
+ instance->associationLine()->calculateInitialEndPoints();
+ instance->associationLine()->reconstructSymbols();
+
+ //The AssociationWidget is set to Activated because it already has its side widgets
+ instance->setActivated(true);
+
+ // sync UML meta-data to settings here
+ instance->mergeAssociationDataIntoUMLRepresentation();
+
+ // Collaboration messages need a name label because it's that
+ // which lets operator== distinguish them, which in turn
+ // permits us to have more than one message between two objects.
+ if (instance->isCollaboration()) {
+ // Create a temporary name to bring on setName()
+ int collabID = instance->m_scene->generateCollaborationId();
+ instance->setName(QLatin1Char('m') + QString::number(collabID));
+ }
+
+ return instance;
+}
+
+/**
+ * Destructor.
+ */
+AssociationWidget::~AssociationWidget()
+{
+ delete m_associationLine;
+}
+
+/**
+ * Overriding the method from WidgetBase because we need to do
+ * something extra in case this AssociationWidget represents
+ * an attribute of a classifier.
+ */
+void AssociationWidget::setUMLObject(UMLObject *obj)
+{
+ WidgetBase::setUMLObject(obj);
+ if (obj == NULL)
+ return;
+ UMLClassifier *klass = NULL;
+ UMLAttribute *attr = NULL;
+ UMLEntity *ent = NULL;
+ const UMLObject::ObjectType ot = obj->baseType();
+ switch (ot) {
+ case UMLObject::ot_Association:
+ setUMLAssociation(dynamic_cast<UMLAssociation*>(obj));
+ break;
+ case UMLObject::ot_Operation:
+ setOperation(dynamic_cast<UMLOperation*>(obj));
+ break;
+ case UMLObject::ot_Attribute:
+ klass = static_cast<UMLClassifier*>(obj->parent());
+ connect(klass, SIGNAL(attributeRemoved(UMLClassifierListItem*)),
+ this, SLOT(slotClassifierListItemRemoved(UMLClassifierListItem*)));
+ attr = static_cast<UMLAttribute*>(obj);
+ connect(attr, SIGNAL(attributeChanged()), this, SLOT(slotAttributeChanged()));
+ break;
+ case UMLObject::ot_EntityAttribute:
+ ent = static_cast<UMLEntity*>(obj->parent());
+ connect(ent, SIGNAL(entityAttributeRemoved(UMLClassifierListItem*)),
+ this, SLOT(slotClassifierListItemRemoved(UMLClassifierListItem*)));
+ break;
+ case UMLObject::ot_ForeignKeyConstraint:
+ ent = static_cast<UMLEntity*>(obj->parent());
+ connect(ent, SIGNAL(entityConstraintRemoved(UMLClassifierListItem*)),
+ this, SLOT(slotClassifierListItemRemoved(UMLClassifierListItem*)));
+ break;
+ default:
+ uError() << "cannot associate UMLObject of type " << UMLObject::toString(ot);
+ break;
+ }
+}
+
+/**
+ * Set all 'owned' child widgets to this font.
+ */
+void AssociationWidget::lwSetFont (QFont font)
+{
+ if (m_nameWidget) {
+ m_nameWidget->setFont(font);
+ }
+ if (m_role[RoleType::A].roleWidget) {
+ m_role[RoleType::A].roleWidget->setFont(font);
+ }
+ if (m_role[RoleType::B].roleWidget) {
+ m_role[RoleType::B].roleWidget->setFont(font);
+ }
+ if (m_role[RoleType::A].multiplicityWidget) {
+ m_role[RoleType::A].multiplicityWidget->setFont(font);
+ }
+ if (m_role[RoleType::B].multiplicityWidget) {
+ m_role[RoleType::B].multiplicityWidget->setFont(font);
+ }
+ if (m_role[RoleType::A].changeabilityWidget)
+ m_role[RoleType::A].changeabilityWidget->setFont(font);
+ if (m_role[RoleType::B].changeabilityWidget)
+ m_role[RoleType::B].changeabilityWidget->setFont(font);
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ * @todo Move to LinkWidget.
+ */
+UMLClassifier *AssociationWidget::operationOwner()
+{
+ Uml::RoleType::Enum role = (isCollaboration() ? Uml::RoleType::B : Uml::RoleType::A);
+ UMLObject *o = widgetForRole(role)->umlObject();
+ if (!o) {
+ return 0;
+ }
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(o);
+ if (!c) {
+ uError() << "widgetForRole(" << role << ") is not a classifier";
+ }
+ return c;
+}
+
+/**
+ * Implements operation from LinkWidget.
+ * Motivated by FloatingTextWidget.
+ */
+UMLOperation *AssociationWidget::operation()
+{
+ return dynamic_cast<UMLOperation*>(m_umlObject);
+}
+
+/**
+ * Implements operation from LinkWidget.
+ * Motivated by FloatingTextWidget.
+ */
+void AssociationWidget::setOperation(UMLOperation *op)
+{
+ if (m_umlObject)
+ disconnect(m_umlObject, SIGNAL(modified()), m_nameWidget, SLOT(setMessageText()));
+ m_umlObject = op;
+ if (m_umlObject)
+ connect(m_umlObject, SIGNAL(modified()), m_nameWidget, SLOT(setMessageText()));
+ if (m_nameWidget)
+ m_nameWidget->setMessageText();
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+QString AssociationWidget::customOpText()
+{
+ return name();
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+void AssociationWidget::setCustomOpText(const QString &opText)
+{
+ setName(opText);
+}
+
+/**
+ * Calls setTextPosition on all the labels.
+ * Overrides operation from LinkWidget.
+ */
+void AssociationWidget::resetTextPositions()
+{
+ if (m_role[RoleType::A].multiplicityWidget) {
+ setTextPosition(TextRole::MultiA);
+ }
+ if (m_role[RoleType::B].multiplicityWidget) {
+ setTextPosition(Uml::TextRole::MultiB);
+ }
+ if (m_role[RoleType::A].changeabilityWidget) {
+ setTextPosition(Uml::TextRole::ChangeA);
+ }
+ if (m_role[RoleType::B].changeabilityWidget) {
+ setTextPosition(Uml::TextRole::ChangeB);
+ }
+ if (m_nameWidget) {
+ setTextPosition(Uml::TextRole::Name);
+ }
+ if (m_role[RoleType::A].roleWidget) {
+ setTextPosition(Uml::TextRole::RoleAName);
+ }
+ if (m_role[RoleType::B].roleWidget) {
+ setTextPosition(Uml::TextRole::RoleBName);
+ }
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param ft The text widget which to update.
+ */
+void AssociationWidget::setMessageText(FloatingTextWidget *ft)
+{
+ if (isCollaboration()) {
+ ft->setSequenceNumber(m_SequenceNumber);
+ if (m_umlObject != NULL) {
+ ft->setText(operationText(m_scene));
+ } else {
+ ft->setText(name());
+ }
+ } else {
+ ft->setText(name());
+ }
+}
+
+/**
+ * Sets the text of the given FloatingTextWidget.
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+void AssociationWidget::setText(FloatingTextWidget *ft, const QString &text)
+{
+ Uml::TextRole::Enum role = ft->textRole();
+ switch (role) {
+ case Uml::TextRole::Name:
+ setName(text);
+ break;
+ case Uml::TextRole::RoleAName:
+ setRoleName(text, RoleType::A);
+ break;
+ case Uml::TextRole::RoleBName:
+ setRoleName(text, RoleType::B);
+ break;
+ case Uml::TextRole::MultiA:
+ setMultiplicity(text, RoleType::A);
+ break;
+ case Uml::TextRole::MultiB:
+ setMultiplicity(text, RoleType::B);
+ break;
+ default:
+ uWarning() << "Unhandled TextRole: " << Uml::TextRole::toString(role);
+ break;
+ }
+}
+
+/**
+ * Shows the association properties dialog and updates the
+ * corresponding texts if its execution is successful.
+ */
+void AssociationWidget::showPropertiesDialog()
+{
+ UMLApp::app()->docWindow()->updateDocumentation();
+ QPointer<AssociationPropertiesDialog> dlg = new AssociationPropertiesDialog(static_cast<QWidget*>(m_scene->activeView()), this);
+ if (dlg->exec()) {
+ //rules built into these functions to stop updating incorrect values
+ setName(name());
+
+ setRoleName(roleName(RoleType::A), RoleType::A);
+ setRoleName(roleName(RoleType::B), RoleType::B);
+
+ setDocumentation(documentation());
+
+ setRoleDocumentation(roleDocumentation(RoleType::A), RoleType::A);
+ setRoleDocumentation(roleDocumentation(RoleType::B), RoleType::B);
+
+ setMultiplicity(multiplicity(RoleType::A), RoleType::A);
+ setMultiplicity(multiplicity(RoleType::B), RoleType::B);
+
+ setVisibility(visibility(RoleType::A), RoleType::A);
+ setVisibility(visibility(RoleType::B), RoleType::B);
+
+ setChangeability(changeability(RoleType::A), RoleType::A);
+ setChangeability(changeability(RoleType::B), RoleType::B);
+
+ UMLApp::app()->docWindow()->showDocumentation(this, true);
+ }
+ delete dlg;
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param op Return this AssociationWidget's operation string.
+ */
+QString AssociationWidget::lwOperationText()
+{
+ return name();
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @return classifier
+ */
+UMLClassifier* AssociationWidget::lwClassifier()
+{
+ UMLObject *o = widgetForRole(RoleType::B)->umlObject();
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(o);
+ return c;
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param op The new operation string to set.
+ */
+void AssociationWidget::setOperationText(const QString &op)
+{
+ if (!op.isEmpty()) {
+ setName(op);
+ }
+}
+
+/**
+ * Calculates the m_unNameLineSegment value according to the new
+ * NameText topleft corner PT.
+ * It iterates through all AssociationLine's segments and for each one
+ * calculates the sum of PT's distance to the start point + PT's
+ * distance to the end point. The segment with the smallest sum will
+ * be the RoleTextSegment (if this segment moves then the RoleText
+ * will move with it). It sets m_unNameLineSegment to the start point
+ * of the chosen segment.
+ *
+ * Overrides operation from LinkWidget (i.e. this method is also
+ * required by FloatingTextWidget.)
+ */
+void AssociationWidget::calculateNameTextSegment()
+{
+ if (!m_nameWidget) {
+ return;
+ }
+ //changed to use the middle of the text
+ //i think this will give a better result.
+ //never know what sort of lines people come up with
+ //and text could be long to give a false reading
+ qreal xt = m_nameWidget->x();
+ qreal yt = m_nameWidget->y();
+ xt += m_nameWidget->width() / 2;
+ yt += m_nameWidget->height() / 2;
+ int size = m_associationLine->count();
+ //sum of length(PTP1) and length(PTP2)
+ qreal total_length = 0;
+ qreal smallest_length = 0;
+ for (int i = 0; i < size - 1; ++i) {
+ QPointF pi = m_associationLine->point( i );
+ QPointF pj = m_associationLine->point( i+1 );
+ qreal xtiDiff = xt - pi.x();
+ qreal xtjDiff = xt - pj.x();
+ qreal ytiDiff = yt - pi.y();
+ qreal ytjDiff = yt - pj.y();
+ total_length = sqrt( double(xtiDiff * xtiDiff + ytiDiff * ytiDiff) )
+ + sqrt( double(xtjDiff * xtjDiff + ytjDiff * ytjDiff) );
+ //this gives the closest point
+ if (total_length < smallest_length || i == 0) {
+ smallest_length = total_length;
+ m_unNameLineSegment = i;
+ }
+ }
+}
+
+/**
+ * Returns the UMLAssociation representation of this object.
+ *
+ * @return Pointer to the UMLAssociation that is represented by
+ * this AsociationWidget.
+ */
+UMLAssociation* AssociationWidget::association() const
+{
+ if (m_umlObject == NULL || m_umlObject->baseType() != UMLObject::ot_Association)
+ return NULL;
+ return static_cast<UMLAssociation*>(m_umlObject);
+}
+
+/**
+ * Returns the UMLAttribute representation of this object.
+ *
+ * @return Pointer to the UMLAttribute that is represented by
+ * this AsociationWidget.
+ */
+UMLAttribute* AssociationWidget::attribute() const
+{
+ if (m_umlObject == NULL)
+ return NULL;
+ UMLObject::ObjectType ot = m_umlObject->baseType();
+ if (ot != UMLObject::ot_Attribute && ot != UMLObject::ot_EntityAttribute)
+ return NULL;
+ return static_cast<UMLAttribute*>(m_umlObject);
+}
+
+#if 0 //:TODO:
+/**
+ * Overrides the assignment operator.
+ */
+AssociationWidget& AssociationWidget::operator=(const AssociationWidget& other)
+{
+ *m_associationLine = *other.m_associationLine;
+
+ if (other.m_nameWidget) {
+ m_nameWidget = new FloatingTextWidget(m_scene);
+ *m_nameWidget = *(other.m_nameWidget);
+ } else {
+ m_nameWidget = NULL;
+ }
+
+ for (unsigned r = (unsigned)A; r <= (unsigned)B; ++r) {
+ WidgetRole& lhs = m_role[r];
+ const WidgetRole& rhs = other.m_role[r];
+ lhs.m_nIndex = rhs.m_nIndex;
+ lhs.m_nTotalCount = rhs.m_nTotalCount;
+
+ if (rhs.multiplicityWidget) {
+ lhs.multiplicityWidget = new FloatingTextWidget(m_scene);
+ *(lhs.multiplicityWidget) = *(rhs.multiplicityWidget);
+ } else {
+ lhs.multiplicityWidget = NULL;
+ }
+
+ if (rhs.roleWidget) {
+ lhs.roleWidget = new FloatingTextWidget(m_scene);
+ *(lhs.roleWidget) = *(rhs.roleWidget);
+ } else {
+ lhs.roleWidget = NULL;
+ }
+
+ if (rhs.changeabilityWidget) {
+ lhs.changeabilityWidget = new FloatingTextWidget(m_scene);
+ *(lhs.changeabilityWidget) = *(rhs.changeabilityWidget);
+ } else {
+ lhs.changeabilityWidget = NULL;
+ }
+
+ lhs.umlWidget = rhs.umlWidget;
+ lhs.m_WidgetRegion = rhs.m_WidgetRegion;
+ }
+
+ m_activated = other.m_activated;
+ m_unNameLineSegment = other.m_unNameLineSegment;
+ m_pMenu = other.m_pMenu;
+ setUMLAssociation(other.association());
+ setSelected(other.isSelected());
+
+ return *this;
+}
+#endif //:TODO:
+
+/**
+ * Overrides the equality test operator.
+ */
+bool AssociationWidget::operator==(const AssociationWidget& other) const
+{
+ if (this == &other)
+ return true;
+
+ // if no model representation exists, then the widgets are not equal
+ if (association() == NULL && other.association() == NULL)
+ return false;
+
+ if (!m_umlObject || !other.m_umlObject ) {
+ if (!other.m_umlObject && m_umlObject)
+ return false;
+ if (other.m_umlObject && !m_umlObject)
+ return false;
+
+ } else if (m_umlObject != other.m_umlObject)
+ return false;
+
+ if (associationType() != other.associationType())
+ return false;
+
+ if (widgetIDForRole(RoleType::A) != other.widgetIDForRole(RoleType::A))
+ return false;
+
+ if (widgetIDForRole(RoleType::B) != other.widgetIDForRole(RoleType::B))
+ return false;
+
+ if (widgetForRole(RoleType::A)->baseType() == WidgetBase::wt_Object &&
+ other.widgetForRole(RoleType::A)->baseType() == WidgetBase::wt_Object) {
+ ObjectWidget *ownA = static_cast<ObjectWidget*>(widgetForRole(RoleType::A));
+ ObjectWidget *otherA = static_cast<ObjectWidget*>(other.widgetForRole(RoleType::A));
+ if (ownA->localID() != otherA->localID())
+ return false;
+ }
+
+ if (widgetForRole(RoleType::B)->baseType() == WidgetBase::wt_Object &&
+ other.widgetForRole(RoleType::B)->baseType() == WidgetBase::wt_Object) {
+ ObjectWidget *ownB = static_cast<ObjectWidget*>(widgetForRole(RoleType::B));
+ ObjectWidget *otherB = static_cast<ObjectWidget*>(other.widgetForRole(RoleType::B));
+ if (ownB->localID() != otherB->localID())
+ return false;
+ }
+
+ // Two objects in a collaboration can have multiple messages between each other.
+ // Here we depend on the messages having names, and the names must be different.
+ // That is the reason why collaboration messages have strange initial names like
+ // "m29997" or similar.
+ return (name() == other.name());
+}
+
+/**
+ * Overrides the != operator.
+ */
+bool AssociationWidget::operator!=(AssociationWidget& other) const
+{
+ return !(*this == other);
+}
+
+/**
+ * Returns a pointer to the association widget's line path.
+ */
+AssociationLine* AssociationWidget::associationLine() const
+{
+ return m_associationLine;
+}
+
+/**
+ * Activates the AssociationWidget after a load.
+ *
+ * @return true for success
+ */
+bool AssociationWidget::activate()
+{
+ if (m_umlObject == NULL &&
+ AssociationType::hasUMLRepresentation(m_associationType)) {
+ UMLObject *myObj = umlDoc()->findObjectById(m_nId);
+ if (myObj == NULL) {
+ uError() << "cannot find UMLObject " << Uml::ID::toString(m_nId);
+ return false;
+ } else {
+ const UMLObject::ObjectType ot = myObj->baseType();
+ if (ot == UMLObject::ot_Association) {
+ UMLAssociation * myAssoc = static_cast<UMLAssociation*>(myObj);
+ setUMLAssociation(myAssoc);
+ } else {
+ setUMLObject(myObj);
+ setAssociationType(m_associationType);
+ }
+ }
+ }
+
+ if (m_activated)
+ return true;
+
+ Uml::AssociationType::Enum type = associationType();
+
+ if (m_role[RoleType::A].umlWidget == NULL)
+ setWidgetForRole(m_scene->findWidget(widgetIDForRole(RoleType::A)), RoleType::A);
+ if (m_role[RoleType::B].umlWidget == NULL)
+ setWidgetForRole(m_scene->findWidget(widgetIDForRole(RoleType::B)), RoleType::B);
+
+ if (!m_role[RoleType::A].umlWidget || !m_role[RoleType::B].umlWidget) {
+ DEBUG(DBG_SRC) << "Cannot make association!";
+ return false;
+ }
+
+ calculateEndingPoints();
+
+ if (AssocRules::allowRole(type)) {
+ for (unsigned r = RoleType::A; r <= RoleType::B; ++r) {
+ WidgetRole& robj = m_role[r];
+ if (robj.roleWidget == NULL)
+ continue;
+ robj.roleWidget->setLink(this);
+ TextRole::Enum tr = (r == RoleType::A ? TextRole::RoleAName : TextRole::RoleBName);
+ robj.roleWidget->setTextRole(tr);
+ Uml::Visibility::Enum vis = visibility(Uml::RoleType::fromInt(r));
+ robj.roleWidget->setPreText(Uml::Visibility::toString(vis, true));
+
+ if (FloatingTextWidget::isTextValid(robj.roleWidget->text()))
+ robj.roleWidget->show();
+ else
+ robj.roleWidget->hide();
+ if (m_scene->type() == DiagramType::Collaboration)
+ robj.roleWidget->setUMLObject(robj.umlWidget->umlObject());
+ robj.roleWidget->activate();
+ }
+ }
+
+ if (m_nameWidget != NULL) {
+ m_nameWidget->setLink(this);
+ m_nameWidget->setTextRole(calculateNameType(TextRole::Name));
+
+ if (FloatingTextWidget::isTextValid(m_nameWidget->text())) {
+ m_nameWidget->show();
+ } else {
+ m_nameWidget->hide();
+ }
+ m_nameWidget->activate();
+ calculateNameTextSegment();
+ }
+
+ for (unsigned r = RoleType::A; r <= RoleType::B; ++r) {
+ WidgetRole& robj = m_role[r];
+
+ FloatingTextWidget* pMulti = robj.multiplicityWidget;
+ if (pMulti != NULL &&
+ AssocRules::allowMultiplicity(type, robj.umlWidget->baseType())) {
+ pMulti->setLink(this);
+ TextRole::Enum tr = (r == RoleType::A ? TextRole::MultiA : TextRole::MultiB);
+ pMulti->setTextRole(tr);
+ if (FloatingTextWidget::isTextValid(pMulti->text()))
+ pMulti->show();
+ else
+ pMulti->hide();
+ pMulti->activate();
+ }
+
+ FloatingTextWidget* pChangeWidget = robj.changeabilityWidget;
+ if (pChangeWidget != NULL) {
+ pChangeWidget->setLink(this);
+ TextRole::Enum tr = (r == RoleType::A ? TextRole::ChangeA : TextRole::ChangeB);
+ pChangeWidget->setTextRole(tr);
+ if (FloatingTextWidget::isTextValid(pChangeWidget->text()))
+ pChangeWidget->show();
+ else
+ pChangeWidget->hide ();
+ pChangeWidget->activate();
+ }
+ }
+
+ // Prepare the association class line if needed.
+ if (m_associationClass && !m_pAssocClassLine) {
+ createAssocClassLine();
+ }
+
+ m_activated = true;
+ return true;
+}
+
+/**
+ * Set the widget of the given role.
+ * Add this AssociationWidget at the widget.
+ * If this AssociationWidget has an underlying UMLAssociation then set
+ * the widget's underlying UMLObject at the UMLAssociation's role object.
+ *
+ * @param widget Pointer to the UMLWidget.
+ * @param role Role for which to set the widget.
+ */
+void AssociationWidget::setWidgetForRole(UMLWidget* widget, Uml::RoleType::Enum role)
+{
+ m_role[role].umlWidget = widget;
+ if (widget) {
+ m_role[role].umlWidget->addAssoc(this);
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association)
+ association()->setObject(widget->umlObject(), role);
+ }
+}
+
+/**
+ * Return the multiplicity FloatingTextWidget widget of the given role.
+ *
+ * @return Pointer to the multiplicity FloatingTextWidget object.
+ */
+FloatingTextWidget* AssociationWidget::multiplicityWidget(Uml::RoleType::Enum role) const
+{
+ return m_role[role].multiplicityWidget;
+}
+
+/**
+ * Read property of FloatingTextWidget* m_nameWidget.
+ *
+ * @return Pointer to the FloatingTextWidget name widget.
+ */
+FloatingTextWidget* AssociationWidget::nameWidget() const
+{
+ return m_nameWidget;
+}
+
+/**
+ * Return the given role's FloatingTextWidget object.
+ *
+ * @return Pointer to the role's FloatingTextWidget widget.
+ */
+FloatingTextWidget* AssociationWidget::roleWidget(Uml::RoleType::Enum role) const
+{
+ return m_role[role].roleWidget;
+}
+
+/**
+ * Return the given role's changeability FloatingTextWidget widget.
+ */
+FloatingTextWidget* AssociationWidget::changeabilityWidget(Uml::RoleType::Enum role) const
+{
+ return m_role[role].changeabilityWidget;
+}
+
+/**
+ * Return the FloatingTextWidget object indicated by the given TextRole::Enum.
+ *
+ * @return Pointer to the text role's FloatingTextWidget widget.
+ */
+FloatingTextWidget* AssociationWidget::textWidgetByRole(Uml::TextRole::Enum tr) const
+{
+ switch (tr) {
+ case Uml::TextRole::MultiA:
+ return m_role[RoleType::A].multiplicityWidget;
+ case Uml::TextRole::MultiB:
+ return m_role[RoleType::B].multiplicityWidget;
+ case Uml::TextRole::Name:
+ case Uml::TextRole::Coll_Message:
+ return m_nameWidget;
+ case Uml::TextRole::RoleAName:
+ return m_role[RoleType::A].roleWidget;
+ case Uml::TextRole::RoleBName:
+ return m_role[RoleType::B].roleWidget;
+ case Uml::TextRole::ChangeA:
+ return m_role[RoleType::A].changeabilityWidget;
+ case Uml::TextRole::ChangeB:
+ return m_role[RoleType::B].changeabilityWidget;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/**
+ * Returns the m_nameWidget's text.
+ *
+ * @return Text of the FloatingTextWidget name widget.
+ */
+QString AssociationWidget::name() const
+{
+ if (m_nameWidget == NULL)
+ return QString();
+ return m_nameWidget->text();
+}
+
+/**
+ * Sets the text in the FloatingTextWidget widget representing the Name
+ * of this association.
+ */
+void AssociationWidget::setName(const QString &strName)
+{
+ // set attribute of UMLAssociation associated with this associationwidget
+ UMLAssociation *umla = association();
+ if (umla)
+ umla->setName(strName);
+
+ bool newLabel = false;
+ if (!m_nameWidget) {
+ // Don't construct the FloatingTextWidget if the string is empty.
+ if (! FloatingTextWidget::isTextValid(strName))
+ return;
+
+ newLabel = true;
+ m_nameWidget = new FloatingTextWidget(m_scene, calculateNameType(Uml::TextRole::Name), strName);
+ m_nameWidget->setParentItem(this);
+ m_nameWidget->setLink(this);
+ } else {
+ m_nameWidget->setText(strName);
+ if (! FloatingTextWidget::isTextValid(strName)) {
+ //m_nameWidget->hide();
+ m_scene->removeWidget(m_nameWidget);
+ m_nameWidget = NULL;
+ return;
+ }
+ }
+
+ setTextPosition(Uml::TextRole::Name);
+ if (newLabel) {
+ m_nameWidget->setActivated();
+ m_scene->addFloatingTextWidget(m_nameWidget);
+ }
+
+ m_nameWidget->show();
+}
+
+void AssociationWidget::setStereotype(const QString &stereo) {
+ UMLAssociation *umlassoc = association();
+ if (umlassoc) {
+ umlassoc->setStereotype(stereo);
+ if (m_nameWidget) {
+ m_nameWidget->setText(umlassoc->stereotype(true));
+ } else {
+ uDebug() << "not setting " << stereo << " because m_nameWidget is NULL";
+ }
+ } else {
+ uDebug() << "not setting " << stereo << " because association is NULL";
+ }
+}
+
+/**
+ * Return the given role's FloatingTextWidget widget text.
+ *
+ * @return The name set at the FloatingTextWidget.
+ */
+QString AssociationWidget::roleName(Uml::RoleType::Enum role) const
+{
+ if (m_role[role].roleWidget == NULL)
+ return QString();
+ return m_role[role].roleWidget->text();
+}
+
+/**
+ * Sets the text to the FloatingTextWidget that display the Role text of this
+ * association.
+ * For this function to work properly, the associated widget
+ * should already be set.
+ */
+void AssociationWidget::setRoleName(const QString &strRole, Uml::RoleType::Enum role)
+{
+ Uml::AssociationType::Enum type = associationType();
+ //if the association is not supposed to have a Role FloatingTextWidget
+ if (!AssocRules::allowRole(type)) {
+ return;
+ }
+
+ TextRole::Enum tr = (role == RoleType::A ? TextRole::RoleAName : TextRole::RoleBName);
+ setFloatingText(tr, strRole, m_role[role].roleWidget);
+ if (m_role[role].roleWidget) {
+ Uml::Visibility::Enum vis = visibility(role);
+ if (FloatingTextWidget::isTextValid(m_role[role].roleWidget->text())) {
+ m_role[role].roleWidget->setPreText(Uml::Visibility::toString(vis, true));
+ //m_role[role].roleWidget->show();
+ } else {
+ m_role[role].roleWidget->setPreText(QString());
+ //m_role[role].roleWidget->hide();
+ }
+ }
+
+ // set attribute of UMLAssociation associated with this associationwidget
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association)
+ association()->setRoleName(strRole, role);
+}
+
+/**
+ * Set the documentation on the given role.
+ */
+void AssociationWidget::setRoleDocumentation(const QString &doc, Uml::RoleType::Enum role)
+{
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association)
+ association()->setRoleDoc(doc, role);
+ else
+ m_role[role].roleDocumentation = doc;
+}
+
+/**
+ * Returns the given role's documentation.
+ */
+QString AssociationWidget::roleDocumentation(Uml::RoleType::Enum role) const
+{
+ if (m_umlObject == NULL || m_umlObject->baseType() != UMLObject::ot_Association)
+ return QString();
+ UMLAssociation *umla = static_cast<UMLAssociation*>(m_umlObject);
+ return umla->getRoleDoc(role);
+}
+
+/**
+ * Change, create, or delete the FloatingTextWidget indicated by the given TextRole::Enum.
+ *
+ * @param tr TextRole::Enum of the FloatingTextWidget to change or create.
+ * @param text Text string that controls the action:
+ * If empty and ft is NULL then setFloatingText() is a no-op.
+ * If empty and ft is non-NULL then the existing ft is deleted.
+ * If non-empty and ft is NULL then a new FloatingTextWidget is created
+ * and returned in ft with the text set.
+ * If non-empty and ft is non-NULL then the existing ft text is modified.
+ * @param ft Reference to the pointer to FloatingTextWidget to change or create.
+ * On creation/deletion, the pointer value will be changed.
+ */
+void AssociationWidget::setFloatingText(Uml::TextRole::Enum role,
+ const QString &text,
+ FloatingTextWidget* &ft)
+{
+ if (! FloatingTextWidget::isTextValid(text)) {
+ if (ft) {
+ // Remove preexisting FloatingTextWidget
+ m_scene->removeWidget(ft); // physically deletes ft
+ ft = NULL;
+ }
+ return;
+ }
+
+ if (ft == NULL) {
+ ft = new FloatingTextWidget(m_scene, role, text);
+ ft->setParentItem(this);
+ ft->setLink(this);
+ ft->activate();
+ setTextPosition(role);
+ m_scene->addFloatingTextWidget(ft);
+ } else {
+ bool newLabel = ft->text().isEmpty();
+ ft->setText(text);
+ if (newLabel)
+ setTextPosition(role);
+ }
+
+ ft->show();
+}
+
+/**
+ * Return the given role's multiplicity text.
+ *
+ * @return Text of the given role's multiplicity widget.
+ */
+QString AssociationWidget::multiplicity(Uml::RoleType::Enum role) const
+{
+ if (m_role[role].multiplicityWidget == NULL)
+ return QString();
+ return m_role[role].multiplicityWidget->text();
+}
+
+/**
+ * Sets the text in the FloatingTextWidget representing the multiplicity
+ * at the given side of the association.
+ */
+void AssociationWidget::setMultiplicity(const QString& text, Uml::RoleType::Enum role)
+{
+ TextRole::Enum tr = (role == RoleType::A ? TextRole::MultiA : TextRole::MultiB);
+
+ setFloatingText(tr, text, m_role[role].multiplicityWidget);
+
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association)
+ association()->setMultiplicity(text, role);
+}
+
+/**
+ * Gets the visibility on the given role of the association.
+ */
+Visibility::Enum AssociationWidget::visibility(Uml::RoleType::Enum role) const
+{
+ const UMLAssociation *assoc = association();
+ if (assoc)
+ return assoc->visibility(role);
+ const UMLAttribute *attr = attribute();
+ if (attr)
+ return attr->visibility();
+ return m_role[role].visibility;
+}
+
+/**
+ * Sets the visibility on the given role of the association.
+ */
+void AssociationWidget::setVisibility(Visibility::Enum value, Uml::RoleType::Enum role)
+{
+ if (value == visibility(role)) {
+ return;
+ }
+ if (m_umlObject) {
+ // update our model object
+ const UMLObject::ObjectType ot = m_umlObject->baseType();
+ if (ot == UMLObject::ot_Association)
+ association()->setVisibility(value, role);
+ else if (ot == UMLObject::ot_Attribute)
+ attribute()->setVisibility(value);
+ }
+ m_role[role].visibility = value;
+ // update role pre-text attribute as appropriate
+ if (m_role[role].roleWidget) {
+ QString scopeString = Visibility::toString(value, true);
+ m_role[role].roleWidget->setPreText(scopeString);
+ }
+}
+
+/**
+ * Gets the changeability on the given end of the Association.
+ */
+Uml::Changeability::Enum AssociationWidget::changeability(Uml::RoleType::Enum role) const
+{
+ if (m_umlObject == NULL || m_umlObject->baseType() != UMLObject::ot_Association)
+ return m_role[role].changeability;
+ UMLAssociation *umla = static_cast<UMLAssociation*>(m_umlObject);
+ return umla->changeability(role);
+}
+
+/**
+ * Sets the changeability on the given end of the Association.
+ */
+void AssociationWidget::setChangeability(Uml::Changeability::Enum value, Uml::RoleType::Enum role)
+{
+ if (value == changeability(role))
+ return;
+ QString changeString = Uml::Changeability::toString(value);
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) // update our model object
+ association()->setChangeability(value, role);
+ m_role[role].changeability = value;
+ // update our string representation
+ setChangeWidget(changeString, role);
+}
+
+/**
+ * For internal purpose-kf6s only.
+ * Other classes/users should use setChangeability() instead.
+ */
+void AssociationWidget::setChangeWidget(const QString &strChangeWidget, Uml::RoleType::Enum role)
+{
+ bool newLabel = false;
+ TextRole::Enum tr = (role == RoleType::A ? TextRole::ChangeA : TextRole::ChangeB);
+
+ if (!m_role[role].changeabilityWidget) {
+ // Don't construct the FloatingTextWidget if the string is empty.
+ if (strChangeWidget.isEmpty())
+ return;
+
+ newLabel = true;
+ m_role[role].changeabilityWidget = new FloatingTextWidget(m_scene, tr, strChangeWidget);
+ m_role[role].changeabilityWidget->setParentItem(this);
+ m_role[role].changeabilityWidget->setLink(this);
+ m_scene->addFloatingTextWidget(m_role[role].changeabilityWidget);
+ m_role[role].changeabilityWidget->setPreText(QLatin1String("{")); // all types have this
+ m_role[role].changeabilityWidget->setPostText(QLatin1String("}")); // all types have this
+ } else {
+ if (m_role[role].changeabilityWidget->text().isEmpty()) {
+ newLabel = true;
+ }
+ m_role[role].changeabilityWidget->setText(strChangeWidget);
+ }
+ m_role[role].changeabilityWidget->setActivated();
+
+ if (newLabel) {
+ setTextPosition(tr);
+ }
+
+ if (FloatingTextWidget::isTextValid(m_role[role].changeabilityWidget->text()))
+ m_role[role].changeabilityWidget->show();
+ else
+ m_role[role].changeabilityWidget->hide();
+}
+
+/**
+ * Returns true if the line path starts at the given widget.
+ */
+bool AssociationWidget::linePathStartsAt(const UMLWidget* widget)
+{
+//:TODO:
+// QPointF lpStart = m_associationLine->point(0);
+// int startX = lpStart.x();
+// int startY = lpStart.y();
+// int wX = widget->x();
+// int wY = widget->y();
+// int wWidth = widget->width();
+// int wHeight = widget->height();
+// bool result = (startX >= wX && startX <= wX + wWidth &&
+// startY >= wY && startY <= wY + wHeight);
+// return result;
+ bool result = widget->contains(m_associationLine->point(0));
+ DEBUG(DBG_SRC) << "widget=" << widget->name() << " / result=" << result;
+ return result;
+}
+
+/**
+ * This function calculates which role should be set for the m_nameWidget FloatingTextWidget.
+ */
+Uml::TextRole::Enum AssociationWidget::calculateNameType(Uml::TextRole::Enum defaultRole)
+{
+ TextRole::Enum result = defaultRole;
+ if (m_scene->type() == DiagramType::Collaboration) {
+ if (m_role[RoleType::A].umlWidget == m_role[RoleType::B].umlWidget) {
+ result = TextRole::Coll_Message;//for now same as other Coll_Message
+ } else {
+ result = TextRole::Coll_Message;
+ }
+ } else if (m_scene->type() == DiagramType::Sequence) {
+ if (m_role[RoleType::A].umlWidget == m_role[RoleType::B].umlWidget) {
+ result = TextRole::Seq_Message_Self;
+ } else {
+ result = TextRole::Seq_Message;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * Gets the given role widget.
+ *
+ * @return Pointer to the role's UMLWidget.
+ */
+UMLWidget* AssociationWidget::widgetForRole(Uml::RoleType::Enum role) const
+{
+ return m_role[role].umlWidget;
+}
+
+/**
+ * Sets the associated widgets.
+ *
+ * @param widgetA Pointer the role A widget for the association.
+ * @param assocType The AssociationType::Enum for this association.
+ * @param widgetB Pointer the role B widget for the association.
+ */
+bool AssociationWidget::setWidgets(UMLWidget* widgetA,
+ Uml::AssociationType::Enum assocType,
+ UMLWidget* widgetB)
+{
+ //if the association already has a WidgetB or WidgetA associated, then
+ //it cannot be changed to other widget, that would require a deletion
+ //of the association and the creation of a new one
+ if ((m_role[RoleType::A].umlWidget && (m_role[RoleType::A].umlWidget != widgetA)) ||
+ (m_role[RoleType::B].umlWidget && (m_role[RoleType::B].umlWidget != widgetB))) {
+ return false;
+ }
+ setWidgetForRole(widgetA, RoleType::A);
+ setAssociationType(assocType);
+ setWidgetForRole(widgetB, RoleType::B);
+
+ calculateEndingPoints();
+ return true;
+}
+
+/**
+ * CleansUp all the association's data in the related widgets.
+ */
+void AssociationWidget::cleanup()
+{
+ //let any other associations know we are going so they can tidy their positions up
+ if (m_role[RoleType::A].m_nTotalCount > 2)
+ updateAssociations(m_role[RoleType::A].m_nTotalCount - 1, m_role[RoleType::A].m_WidgetRegion, RoleType::A);
+ if (m_role[RoleType::B].m_nTotalCount > 2)
+ updateAssociations(m_role[RoleType::B].m_nTotalCount - 1, m_role[RoleType::B].m_WidgetRegion, RoleType::B);
+
+ for (unsigned r = RoleType::A; r <= RoleType::B; ++r) {
+ WidgetRole& robj = m_role[r];
+
+ if (robj.umlWidget) {
+ robj.umlWidget->removeAssoc(this);
+ robj.umlWidget = 0;
+ }
+ if (robj.roleWidget) {
+ m_scene->removeWidget(robj.roleWidget);
+ robj.roleWidget = 0;
+ }
+ if (robj.multiplicityWidget) {
+ m_scene->removeWidget(robj.multiplicityWidget);
+ robj.multiplicityWidget = 0;
+ }
+ if (robj.changeabilityWidget) {
+ m_scene->removeWidget(robj.changeabilityWidget);
+ robj.changeabilityWidget = 0;
+ }
+ }
+
+ if (m_nameWidget) {
+ m_scene->removeWidget(m_nameWidget);
+ m_nameWidget = 0;
+ }
+
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
+ /*
+ We do not remove the UMLAssociation from the document.
+ Why? - Well, for example we might be in the middle of
+ a cut/paste. If the UMLAssociation is removed by the cut
+ then upon pasteing we have a problem.
+ This is not quite clean yet - there should be a way to
+ explicitly delete a UMLAssociation. The Right Thing would
+ be to have a ListView representation for UMLAssociation.
+ `
+ IF we are cut n pasting, why are we handling this association as a pointer?
+ We should be using the XMI representation for a cut and paste. This
+ allows us to be clean here, AND a choice of recreating the object
+ w/ same id IF its a "cut", or a new object if its a "copy" operation
+ (in which case we wouldnt be here, in cleanup()).
+ */
+ setUMLAssociation(0);
+ }
+
+ m_associationLine->cleanup();
+ removeAssocClassLine();
+}
+
+/**
+ * @brief Return state if the assocation line point in the near of the last context
+ * menu event position is addable or not.
+ * A point is addable if the association is not an Exception and there is no point in the near.
+ *
+ * @return true if point is addable
+ */
+bool AssociationWidget::isPointAddable()
+{
+ if (!isSelected() || associationType() == Uml::AssociationType::Exception)
+ return false;
+ int i = m_associationLine->closestPointIndex(m_eventScenePos);
+ return i == -1;
+}
+
+/**
+ * @brief Return state if the assocation line point in the near of the last context
+ * menu event position is removable or not.
+ * A point is removable if the association is not an Exception and is not the start or end point.
+ *
+ * @return true if point is removable
+ */
+bool AssociationWidget::isPointRemovable()
+{
+ if (!isSelected() || associationType() == Uml::AssociationType::Exception || m_associationLine->count() <= 2)
+ return false;
+ int i = m_associationLine->closestPointIndex(m_eventScenePos);
+ return i > 0 && i < m_associationLine->count() - 1;
+}
+
+/**
+ * Set our internal umlAssociation.
+ */
+void AssociationWidget::setUMLAssociation (UMLAssociation * assoc)
+{
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
+ UMLAssociation *umla = association();
+
+ // safety check. Did some num-nuts try to set the existing
+ // association again? If so, just bail here
+ if (umla == assoc)
+ return;
+
+ //umla->disconnect(this); //Qt does disconnect automatically upon destruction.
+ umla->nrof_parent_widgets--;
+
+ // ANSWER: This is the wrong treatment of cut and paste. Associations that
+ // are being cut/n pasted should be serialized to XMI, then reconstituted
+ // (IF a paste operation) rather than passing around object pointers. Its
+ // just too hard otherwise to prevent problems in the code. Bottom line: we need to
+ // delete orphaned associations or we well get code crashes and memory leaks.
+ if (umla->nrof_parent_widgets <= 0) {
+ //umla->deleteLater();
+ }
+
+ m_umlObject = NULL;
+ }
+
+ if (assoc) {
+ m_umlObject = assoc;
+
+ // move counter to "0" from "-1" (which means, no assocwidgets)
+ if (assoc->nrof_parent_widgets < 0)
+ assoc->nrof_parent_widgets = 0;
+
+ assoc->nrof_parent_widgets++;
+ connect(assoc, SIGNAL(modified()), this, SLOT(syncToModel()));
+ }
+
+}
+
+/**
+ * Returns true if the Widget is either at the starting or ending side of the association.
+ */
+bool AssociationWidget::containsAsEndpoint(UMLWidget* widget)
+{
+ return (widget == m_role[RoleType::A].umlWidget || widget == m_role[RoleType::B].umlWidget);
+}
+
+/**
+ * Returns true if this AssociationWidget represents a collaboration message.
+ */
+bool AssociationWidget::isCollaboration() const
+{
+ Uml::AssociationType::Enum at = associationType();
+ return (at == AssociationType::Coll_Message_Synchronous
+ || at == AssociationType::Coll_Message_Asynchronous
+ || at == AssociationType::Coll_Message_Self);
+}
+
+/**
+ * Returns true if this AssociationWidget represents a self message.
+ */
+bool AssociationWidget::isSelf() const
+{
+ return widgetForRole(Uml::RoleType::A) == widgetForRole(Uml::RoleType::B);
+}
+
+/**
+ * Gets the association's type.
+ *
+ * @return This AssociationWidget's AssociationType::Enum.
+ */
+Uml::AssociationType::Enum AssociationWidget::associationType() const
+{
+ if (m_umlObject == NULL || m_umlObject->baseType() != UMLObject::ot_Association)
+ return m_associationType;
+ UMLAssociation *umla = static_cast<UMLAssociation*>(m_umlObject);
+ return umla->getAssocType();
+}
+
+/**
+ * Sets the association's type.
+ *
+ * @param type The AssociationType::Enum to set.
+ */
+void AssociationWidget::setAssociationType(Uml::AssociationType::Enum type)
+{
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
+ association()->setAssociationType(type);
+ }
+ m_associationType = type;
+ // If the association new type is not supposed to have Multiplicity
+ // FloatingTexts and a Role FloatingTextWidget then set the texts
+ // to empty.
+ // NB We do not physically delete the floatingtext widgets here because
+ // those widgets are also stored in the UMLView::m_WidgetList.
+ if (!AssocRules::allowMultiplicity(type, widgetForRole(RoleType::A)->baseType())) {
+ if (m_role[RoleType::A].multiplicityWidget) {
+ m_role[RoleType::A].multiplicityWidget->setName(QString());
+ }
+ if (m_role[RoleType::B].multiplicityWidget) {
+ m_role[RoleType::B].multiplicityWidget->setName(QString());
+ }
+ }
+ if (!AssocRules::allowRole(type)) {
+ if (m_role[RoleType::A].roleWidget) {
+ m_role[RoleType::A].roleWidget->setName(QString());
+ }
+ if (m_role[RoleType::B].roleWidget) {
+ m_role[RoleType::B].roleWidget->setName(QString());
+ }
+ setRoleDocumentation(QString(), RoleType::A);
+ setRoleDocumentation(QString(), RoleType::B);
+ }
+ m_associationLine->reconstructSymbols();
+}
+
+/**
+ * Gets the ID of the given role widget.
+ */
+Uml::ID::Type AssociationWidget::widgetIDForRole(Uml::RoleType::Enum role) const
+{
+ if (m_role[role].umlWidget == NULL) {
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
+ UMLAssociation *umla = static_cast<UMLAssociation*>(m_umlObject);
+ return umla->getObjectId(role);
+ }
+ uError() << "umlWidget is NULL";
+ return Uml::ID::None;
+ }
+ if (m_role[role].umlWidget->baseType() == WidgetBase::wt_Object)
+ return static_cast<ObjectWidget*>(m_role[role].umlWidget)->localID();
+ Uml::ID::Type id = m_role[role].umlWidget->id();
+ return id;
+}
+
+/**
+ * Gets the local ID of the given role widget.
+ */
+Uml::ID::Type AssociationWidget::widgetLocalIDForRole(Uml::RoleType::Enum role) const
+{
+ if (m_role[role].umlWidget == NULL) {
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
+ UMLAssociation *umla = static_cast<UMLAssociation*>(m_umlObject);
+ return umla->getObjectId(role);
+ }
+ uError() << "umlWidget is NULL";
+ return Uml::ID::None;
+ }
+ if (m_role[role].umlWidget->baseType() == WidgetBase::wt_Object)
+ return static_cast<ObjectWidget*>(m_role[role].umlWidget)->localID();
+ Uml::ID::Type id = m_role[role].umlWidget->localID();
+ return id;
+}
+
+/**
+ * Returns a QString Object representing this AssociationWidget.
+ */
+QString AssociationWidget::toString() const
+{
+ QString string;
+ static const QChar colon(QLatin1Char(':'));
+
+ if (widgetForRole(RoleType::A)) {
+ string = widgetForRole(RoleType::A)->name();
+ }
+ string.append(colon);
+
+ if (m_role[RoleType::A].roleWidget) {
+ string += m_role[RoleType::A].roleWidget->text();
+ }
+ string.append(colon);
+ string.append(Uml::AssociationType::toStringI18n(associationType()));
+ string.append(colon);
+
+ if (widgetForRole(RoleType::B)) {
+ string += widgetForRole(RoleType::B)->name();
+ }
+
+ string.append(colon);
+ if (m_role[RoleType::B].roleWidget) {
+ string += m_role[RoleType::B].roleWidget->text();
+ }
+
+ return string;
+}
+
+/**
+ * Adds a break point (if left mouse button).
+ */
+void AssociationWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ uDebug() << "widget = " << name() << " / type = " << baseTypeStr();
+ showPropertiesDialog();
+ event->accept();
+ }
+}
+
+/**
+ * Overrides moveEvent.
+ */
+void AssociationWidget::moveEvent(QGraphicsSceneMouseEvent *me)
+{
+ // 2004-04-30: Achim Spangler
+ // Simple Approach to block moveEvent during load of XMI
+ /// @todo avoid trigger of this event during load
+
+ if (umlDoc()->loading()) {
+ // hmmh - change of position during load of XMI
+ // -> there is something wrong
+ // -> avoid movement during opening
+ // -> print warn and stay at old position
+ uWarning() << "called during load of XMI for ViewType: "
+ << m_scene->type() << ", and BaseType: " << baseType();
+ return;
+ }
+ /*to be here a line segment has moved.
+ we need to see if the three text widgets needs to be moved.
+ there are a few things to check first though:
+
+ 1) Do they exist
+ 2) does it need to move:
+ 2a) for the multi widgets only move if they changed region, otherwise they are close enough
+ 2b) for role name move if the segment it is on moves.
+ */
+ //first see if either the first or last segments moved, else no need to recalculate their point positions
+
+ QPointF oldNamePoint = calculateTextPosition(TextRole::Name);
+ QPointF oldMultiAPoint = calculateTextPosition(TextRole::MultiA);
+ QPointF oldMultiBPoint = calculateTextPosition(TextRole::MultiB);
+ QPointF oldChangeAPoint = calculateTextPosition(TextRole::ChangeA);
+ QPointF oldChangeBPoint = calculateTextPosition(TextRole::ChangeB);
+ QPointF oldRoleAPoint = calculateTextPosition(TextRole::RoleAName);
+ QPointF oldRoleBPoint = calculateTextPosition(TextRole::RoleBName);
+
+ int movingPoint = m_associationLine->closestPointIndex(me->scenePos());
+ if (movingPoint != -1)
+ m_associationLine->setPoint(movingPoint, me->scenePos());
+ int pos = m_associationLine->count() - 1;//set to last point for widget b
+
+ if ( movingPoint == 1 || (movingPoint == pos-1) ) {
+ calculateEndingPoints();
+ }
+ if (m_role[RoleType::A].changeabilityWidget && (movingPoint == 1)) {
+ setTextPositionRelatively(TextRole::ChangeA, oldChangeAPoint);
+ }
+ if (m_role[RoleType::B].changeabilityWidget && (movingPoint == 1)) {
+ setTextPositionRelatively(TextRole::ChangeB, oldChangeBPoint);
+ }
+ if (m_role[RoleType::A].multiplicityWidget && (movingPoint == 1)) {
+ setTextPositionRelatively(TextRole::MultiA, oldMultiAPoint);
+ }
+ if (m_role[RoleType::B].multiplicityWidget && (movingPoint == pos-1)) {
+ setTextPositionRelatively(TextRole::MultiB, oldMultiBPoint);
+ }
+
+ if (m_nameWidget) {
+ if (movingPoint == m_unNameLineSegment ||
+ movingPoint - 1 == m_unNameLineSegment) {
+ setTextPositionRelatively(TextRole::Name, oldNamePoint);
+ }
+ }
+
+ if (m_role[RoleType::A].roleWidget) {
+ setTextPositionRelatively(TextRole::RoleAName, oldRoleAPoint);
+ }
+ if (m_role[RoleType::B].roleWidget) {
+ setTextPositionRelatively(TextRole::RoleBName, oldRoleBPoint);
+ }
+
+ if (m_pAssocClassLine) {
+ computeAssocClassLine();
+ }
+}
+
+/**
+ * Calculates and sets the first and last point in the Association's AssociationLine.
+ * Each point is a middle point of its respecting UMLWidget's Bounding rectangle
+ * or a corner of it.
+ * This method picks which sides to use for the association.
+ */
+void AssociationWidget::calculateEndingPoints()
+{
+ /*
+ * For each UMLWidget the diagram is divided in four regions by its diagonals
+ * as indicated below
+ * Region 2
+ * \ /
+ * \ /
+ * +--------+
+ * | \ / |
+ * Region 1 | >< | Region 3
+ * | / \ |
+ * +--------+
+ * / \
+ * / \
+ * Region 4
+ *
+ * Each diagonal is defined by two corners of the bounding rectangle
+ *
+ * To calculate the first point in the AssociationLine we have to find out in which
+ * Region (defined by WidgetA's diagonals) is WidgetB's center
+ * (let's call it Region M.) After that the first point will be the middle
+ * point of the rectangle's side contained in Region M.
+ *
+ * To calculate the last point in the AssociationLine we repeat the above but
+ * in the opposite direction (from widgetB to WidgetA)
+ */
+
+ UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
+ UMLWidget *pWidgetB = m_role[RoleType::B].umlWidget;
+ if (!pWidgetA || !pWidgetB) {
+ uWarning() << "Returning - one of the role widgets is not set.";
+ return;
+ }
+
+ int size = m_associationLine->count();
+ if (size < 2) {
+ QPointF pA = pWidgetA->pos();
+ QPointF pB = pWidgetB->pos();
+ QPolygonF polyA = pWidgetA->shape().toFillPolygon().translated(pA);
+ QPolygonF polyB = pWidgetB->shape().toFillPolygon().translated(pB);
+ QLineF nearestPoints = Widget_Utils::closestPoints(polyA, polyB);
+ if (nearestPoints.isNull()) {
+ uError() << "Widget_Utils::closestPoints failed, falling back to simple widget positions";
+ } else {
+ pA = nearestPoints.p1();
+ pB = nearestPoints.p2();
+ }
+ m_associationLine->setEndPoints(pA, pB);
+ }
+
+ // See if an association to self.
+ // See if it needs to be set up before we continue:
+ // If self association/message and doesn't have the minimum 4 points
+ // then create it. Make sure no points are out of bounds of viewing area.
+ // This only happens on first time through that we are worried about.
+ if (isSelf() && size < 4) {
+ createPointsSelfAssociation();
+ return;
+ }
+
+ if (associationType() == AssociationType::Exception && size < 4) {
+ createPointsException();
+ updatePointsException();
+ return;
+ }
+
+ // If the line has more than one segment change the values to calculate
+ // from widget to point 1.
+ qreal xB = pWidgetB->x() + pWidgetB->width() / 2;
+ qreal yB = pWidgetB->y() + pWidgetB->height() / 2;
+ if (size > 2) {
+ QPointF p = m_associationLine->point(1);
+ xB = p.x();
+ yB = p.y();
+ }
+ doUpdates(QPointF(xB, yB), RoleType::A);
+
+ // Now do the same for widgetB.
+ // If the line has more than one segment change the values to calculate
+ // from widgetB to the last point away from it.
+ qreal xA = pWidgetA->x() + pWidgetA->width() / 2;
+ qreal yA = pWidgetA->y() + pWidgetA->height() / 2;
+ if (size > 2 ) {
+ QPointF p = m_associationLine->point(size - 2);
+ xA = p.x();
+ yA = p.y();
+ }
+ doUpdates(QPointF(xA, yA), RoleType::B);
+
+ computeAssocClassLine();
+}
+
+/**
+ * Used by @ref calculateEndingPoints.
+ */
+void AssociationWidget::doUpdates(const QPointF &otherP, RoleType::Enum role)
+{
+ // Find widget region.
+ Uml::Region::Enum oldRegion = m_role[role].m_WidgetRegion;
+ UMLWidget *pWidget = m_role[role].umlWidget;
+ QRectF rc(pWidget->x(), pWidget->y(),
+ pWidget->width(), pWidget->height());
+ Uml::Region::Enum region = m_role[role].m_WidgetRegion; // alias for brevity
+ region = findPointRegion(rc, otherP);
+ // Move some regions to the standard ones.
+ switch( region ) {
+ case Uml::Region::NorthWest:
+ region = Uml::Region::North;
+ break;
+ case Uml::Region::NorthEast:
+ region = Uml::Region::East;
+ break;
+ case Uml::Region::SouthEast:
+ region = Uml::Region::South;
+ break;
+ case Uml::Region::SouthWest:
+ case Uml::Region::Center:
+ region = Uml::Region::West;
+ break;
+ default:
+ break;
+ }
+ int regionCount = getRegionCount(region, role) + 2; //+2 = (1 for this one and one to halve it)
+ int totalCount = m_role[role].m_nTotalCount;
+ if (oldRegion != region) {
+ updateRegionLineCount(regionCount - 1, regionCount, region, role);
+ updateAssociations(totalCount - 1, oldRegion, role);
+ } else if (totalCount != regionCount) {
+ updateRegionLineCount(regionCount - 1, regionCount, region, role);
+ } else {
+ updateRegionLineCount(m_role[role].m_nIndex, totalCount, region, role);
+ }
+ updateAssociations(regionCount, region, role);
+}
+
+/**
+ * Read property of bool m_activated.
+ */
+bool AssociationWidget::isActivated() const
+{
+ return m_activated;
+}
+
+/**
+ * Set the m_activated flag of a widget but does not perform the Activate method.
+ */
+void AssociationWidget::setActivated(bool active)
+{
+ m_activated = active;
+}
+
+/**
+ * Synchronize this widget from the UMLAssociation.
+ */
+void AssociationWidget::syncToModel()
+{
+ UMLAssociation *uml = association();
+
+ if (uml == NULL) {
+ UMLAttribute *attr = attribute();
+ if (attr == NULL)
+ return;
+ setVisibility(attr->visibility(), RoleType::B);
+ setRoleName(attr->name(), RoleType::B);
+ return;
+ }
+ // block signals until finished
+ uml->blockSignals(true);
+
+ setName(uml->name());
+ setRoleName(uml->getRoleName(RoleType::A), RoleType::A);
+ setRoleName(uml->getRoleName(RoleType::B), RoleType::B);
+ setVisibility(uml->visibility(RoleType::A), RoleType::A);
+ setVisibility(uml->visibility(RoleType::B), RoleType::B);
+ setChangeability(uml->changeability(RoleType::A), RoleType::A);
+ setChangeability(uml->changeability(RoleType::B), RoleType::B);
+ setMultiplicity(uml->getMultiplicity(RoleType::A), RoleType::A);
+ setMultiplicity(uml->getMultiplicity(RoleType::B), RoleType::B);
+
+ uml->blockSignals(false);
+}
+
+/**
+ * Merges/syncs the association widget data into UML object
+ * representation.
+ * This will synchronize UMLAssociation w/ this new Widget
+ * CHECK: Can we get rid of this.
+ */
+void AssociationWidget::mergeAssociationDataIntoUMLRepresentation()
+{
+ UMLAssociation *umlassoc = association();
+ UMLAttribute *umlattr = attribute();
+ if (umlassoc == NULL && umlattr == NULL)
+ return;
+
+ // block emit modified signal, or we get a horrible loop
+ m_umlObject->blockSignals(true);
+
+ // would be desirable to do the following
+ // so that we can be sure its back to initial state
+ // in case we missed something here.
+ //uml->init();
+
+ // floating text widgets
+ FloatingTextWidget *text = nameWidget();
+ if (text)
+ m_umlObject->setName(text->text());
+
+ text = roleWidget(RoleType::A);
+ if (text && umlassoc)
+ umlassoc->setRoleName(text->text(), RoleType::A);
+
+ text = roleWidget(RoleType::B);
+ if (text) {
+ if (umlassoc)
+ umlassoc->setRoleName(text->text(), RoleType::B);
+ else if (umlattr)
+ umlattr->setName(text->text());
+ }
+
+ text = multiplicityWidget(RoleType::A);
+ if (text && umlassoc)
+ umlassoc->setMultiplicity(text->text(), RoleType::A);
+
+ text = multiplicityWidget(RoleType::B);
+ if (text && umlassoc)
+ umlassoc->setMultiplicity(text->text(), RoleType::B);
+
+ // unblock
+ m_umlObject->blockSignals(false);
+}
+
+/**
+ * Auxiliary method for widgetMoved():
+ * Saves all ideally computed floatingtext positions before doing any
+ * kind of change. This is necessary because a single invocation of
+ * calculateEndingPoints() modifies the AssociationLine ending points on ALL
+ * AssociationWidgets. This means that if we don't save the old ideal
+ * positions then they are irretrievably lost as soon as
+ * calculateEndingPoints() is invoked.
+ */
+void AssociationWidget::saveIdealTextPositions()
+{
+ m_oldNamePoint = calculateTextPosition(TextRole::Name);
+ m_oldMultiAPoint = calculateTextPosition(TextRole::MultiA);
+ m_oldMultiBPoint = calculateTextPosition(TextRole::MultiB);
+ m_oldChangeAPoint = calculateTextPosition(TextRole::ChangeA);
+ m_oldChangeBPoint = calculateTextPosition(TextRole::ChangeB);
+ m_oldRoleAPoint = calculateTextPosition(TextRole::RoleAName);
+ m_oldRoleBPoint = calculateTextPosition(TextRole::RoleBName);
+}
+
+/**
+ * Adjusts the ending point of the association that connects to Widget.
+ */
+void AssociationWidget::widgetMoved(UMLWidget* widget, qreal dx, qreal dy)
+{
+ Q_UNUSED(dx); Q_UNUSED(dy);
+
+ // Simple Approach to block moveEvent during load of XMI
+ /// @todo avoid trigger of this event during load
+ if (umlDoc()->loading()) {
+ // change of position during load of XMI
+ // -> there is something wrong
+ // -> avoid movement during opening
+ // -> print warn and stay at old position
+ DEBUG(DBG_SRC) << "called during load of XMI for ViewType: " << m_scene->type()
+ << ", and BaseType: " << baseTypeStr();
+ return;
+ }
+
+ DEBUG(DBG_SRC) << "association type=" << Uml::AssociationType::toString(associationType());
+ if (associationType() == AssociationType::Exception) {
+ updatePointsException();
+ setTextPosition(TextRole::Name);
+ }
+ else {
+ calculateEndingPoints();
+ computeAssocClassLine();
+ }
+
+ // Assoc to self - move all points:
+ if (isSelf()) {
+ updatePointsSelfAssociation();
+
+ if (m_nameWidget && !m_nameWidget->isSelected()) {
+ setTextPositionRelatively(TextRole::Name, m_oldNamePoint);
+ }
+
+ }//end if widgetA = widgetB
+ else if (m_role[RoleType::A].umlWidget == widget) {
+ if (m_nameWidget && m_unNameLineSegment == 0 && !m_nameWidget->isSelected() ) {
+ //only calculate position and move text if the segment it is on is moving
+ setTextPositionRelatively(TextRole::Name, m_oldNamePoint);
+ }
+ }//end if widgetA moved
+ else if (m_role[RoleType::B].umlWidget == widget) {
+ const int size = m_associationLine->count();
+ if (m_nameWidget && (m_unNameLineSegment == size-2) && !m_nameWidget->isSelected() ) {
+ //only calculate position and move text if the segment it is on is moving
+ setTextPositionRelatively(TextRole::Name, m_oldNamePoint);
+ }
+ }//end if widgetB moved
+
+ if (m_role[RoleType::A].roleWidget && !m_role[RoleType::A].roleWidget->isSelected()) {
+ setTextPositionRelatively(TextRole::RoleAName, m_oldRoleAPoint);
+ }
+ if (m_role[RoleType::B].roleWidget && !m_role[RoleType::B].roleWidget->isSelected()) {
+ setTextPositionRelatively(TextRole::RoleBName, m_oldRoleBPoint);
+ }
+ if (m_role[RoleType::A].multiplicityWidget && !m_role[RoleType::A].multiplicityWidget->isSelected()) {
+ setTextPositionRelatively(TextRole::MultiA, m_oldMultiAPoint);
+ }
+ if (m_role[RoleType::B].multiplicityWidget && !m_role[RoleType::B].multiplicityWidget->isSelected()) {
+ setTextPositionRelatively(TextRole::MultiB, m_oldMultiBPoint);
+ }
+ if (m_role[RoleType::A].changeabilityWidget && !m_role[RoleType::A].changeabilityWidget->isSelected()) {
+ setTextPositionRelatively(TextRole::ChangeA, m_oldChangeAPoint);
+ }
+ if (m_role[RoleType::B].changeabilityWidget && !m_role[RoleType::B].changeabilityWidget->isSelected()) {
+ setTextPositionRelatively(TextRole::ChangeB, m_oldChangeBPoint);
+ }
+}
+
+/**
+ * Creates the points of the self association.
+ * Method called when a widget end points are calculated by calculateEndingPoints().
+ */
+void AssociationWidget::createPointsSelfAssociation()
+{
+ UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
+
+ const int DISTANCE = 50;
+ qreal x = pWidgetA->x();
+ qreal y = pWidgetA->y();
+ qreal h = pWidgetA->height();
+ qreal w = pWidgetA->width();
+ // see if above widget ok to start
+ if (y - DISTANCE > 0) {
+ m_associationLine->setEndPoints(QPointF(x + w / 4, y) , QPointF(x + w * 3 / 4, y));
+ m_associationLine->insertPoint(1, QPointF(x + w / 4, y - DISTANCE));
+ m_associationLine->insertPoint(2, QPointF(x + w * 3 / 4, y - DISTANCE));
+ m_role[RoleType::A].m_WidgetRegion = m_role[RoleType::B].m_WidgetRegion = Uml::Region::North;
+ } else {
+ m_associationLine->setEndPoints(QPointF(x + w / 4, y + h), QPointF(x + w * 3 / 4, y + h));
+ m_associationLine->insertPoint(1, QPointF(x + w / 4, y + h + DISTANCE));
+ m_associationLine->insertPoint(2, QPointF(x + w * 3 / 4, y + h + DISTANCE));
+ m_role[RoleType::A].m_WidgetRegion = m_role[RoleType::B].m_WidgetRegion = Uml::Region::South;
+ }
+}
+
+/**
+ * Adjusts the points of the self association.
+ * Method called when a widget was moved by widgetMoved(widget, x, y).
+ */
+void AssociationWidget::updatePointsSelfAssociation()
+{
+ UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
+
+ const int DISTANCE = 50;
+ qreal x = pWidgetA->x();
+ qreal y = pWidgetA->y();
+ qreal h = pWidgetA->height();
+ qreal w = pWidgetA->width();
+ // see if above widget ok to start
+ if (y - DISTANCE > 0) {
+ m_associationLine->setEndPoints(QPointF(x + w / 4, y) , QPointF(x + w * 3 / 4, y));
+ m_associationLine->setPoint(1, QPointF(x + w / 4, y - DISTANCE));
+ m_associationLine->setPoint(2, QPointF(x + w * 3 / 4, y - DISTANCE));
+ m_role[RoleType::A].m_WidgetRegion = m_role[RoleType::B].m_WidgetRegion = Uml::Region::North;
+ } else {
+ m_associationLine->setEndPoints(QPointF(x + w / 4, y + h), QPointF(x + w * 3 / 4, y + h));
+ m_associationLine->setPoint(1, QPointF(x + w / 4, y + h + DISTANCE));
+ m_associationLine->setPoint(2, QPointF(x + w * 3 / 4, y + h + DISTANCE));
+ m_role[RoleType::A].m_WidgetRegion = m_role[RoleType::B].m_WidgetRegion = Uml::Region::South;
+ }
+}
+
+/**
+ * Creates the points of the association exception.
+ * Method called when a widget end points are calculated by calculateEndingPoints().
+ */
+void AssociationWidget::createPointsException()
+{
+ UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
+ UMLWidget *pWidgetB = m_role[RoleType::B].umlWidget;
+
+ qreal xa = pWidgetA->x();
+ qreal ya = pWidgetA->y();
+ qreal ha = pWidgetA->height();
+ qreal wa = pWidgetA->width();
+
+ qreal xb = pWidgetB->x();
+ qreal yb = pWidgetB->y();
+ qreal hb = pWidgetB->height();
+ //qreal wb = pWidgetB->width();
+
+ m_associationLine->setEndPoints(QPointF(xa + wa , ya + ha/2) , QPointF(xb , yb + hb/2));
+ m_associationLine->insertPoint(1, QPointF(xa + wa , ya + ha/2));
+ m_associationLine->insertPoint(2, QPointF(xb , yb + hb/2));
+}
+
+/**
+ * Adjusts the points of the association exception.
+ * Method called when a widget was moved by widgetMoved(widget, x, y).
+ */
+void AssociationWidget::updatePointsException()
+{
+ UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
+ UMLWidget *pWidgetB = m_role[RoleType::B].umlWidget;
+
+ qreal xa = pWidgetA->x();
+ qreal ya = pWidgetA->y();
+ qreal ha = pWidgetA->height();
+ qreal wa = pWidgetA->width();
+
+ qreal xb = pWidgetB->x();
+ qreal yb = pWidgetB->y();
+ qreal hb = pWidgetB->height();
+ qreal wb = pWidgetB->width();
+ qreal xmil, ymil;
+ qreal xdeb, ydeb;
+ qreal xfin, yfin;
+ qreal ESPACEX, ESPACEY;
+ QPointF p1;
+ QPointF p2;
+ //calcul des coordonnées au milieu de la flèche eclair
+ if (xb - xa - wa >= 45) {
+ ESPACEX = 0;
+ xdeb = xa + wa;
+ xfin = xb;
+ } else if (xa - xb - wb > 45) {
+ ESPACEX = 0;
+ xdeb = xa;
+ xfin = xb + wb;
+ } else {
+ ESPACEX = 15;
+ xdeb = xa + wa/2;
+ xfin = xb + wb/2;
+ }
+
+ xmil = xdeb + (xfin - xdeb)/2;
+
+ if (yb - ya - ha >= 45) {
+ ESPACEY = 0;
+ ydeb = ya + ha;
+ yfin = yb;
+ } else if (ya - yb - hb > 45) {
+ ESPACEY = 0;
+ ydeb = ya;
+ yfin = yb + hb;
+ } else {
+ ESPACEY = 15;
+ ydeb = ya + ha/2;
+ yfin = yb + hb/2;
+ }
+
+ ymil = ydeb + (yfin - ydeb)/2;
+
+ p1.setX(xmil + (xfin - xmil)*1/2); p1.setY(ymil + (yfin - ymil)*1/3);
+ p2.setX(xmil - (xmil - xdeb)*1/2); p2.setY(ymil - (ymil - ydeb)*1/3);
+
+ if (abs(p1.x() - p2.x()) <= 10)
+ ESPACEX = 15;
+ if (abs(p1.y() - p2.y()) <= 10)
+ ESPACEY = 15;
+
+ m_associationLine->setEndPoints(QPointF(xdeb, ydeb), QPointF(xfin, yfin));
+ m_associationLine->setPoint(1, QPointF(p1.x() + ESPACEX, p1.y() + ESPACEY));
+ m_associationLine->setPoint(2, QPointF(p2.x() - ESPACEX, p2.y() - ESPACEY));
+
+ m_role[RoleType::A].m_WidgetRegion = m_role[RoleType::B].m_WidgetRegion = Uml::Region::North;
+}
+
+/**
+ * Finds out which region of rectangle 'rect' contains the point 'pos' and returns the region
+ * number:
+ * 1 = Region 1
+ * 2 = Region 2
+ * 3 = Region 3
+ * 4 = Region 4
+ * 5 = On diagonal 2 between Region 1 and 2
+ * 6 = On diagonal 1 between Region 2 and 3
+ * 7 = On diagonal 2 between Region 3 and 4
+ * 8 = On diagonal 1 between Region 4 and 1
+ * 9 = On diagonal 1 and On diagonal 2 (the center)
+ */
+Uml::Region::Enum AssociationWidget::findPointRegion(const QRectF& rect, const QPointF &pos)
+{
+ qreal w = rect.width();
+ qreal h = rect.height();
+ qreal x = rect.x();
+ qreal y = rect.y();
+ qreal slope2 = w / h;
+ qreal slope1 = slope2 *(-1.0);
+ qreal b1 = x + w - (slope1 * y);
+ qreal b2 = x - (slope2 * y);
+
+ qreal eval1 = slope1 * pos.y() + b1;
+ qreal eval2 = slope2 * pos.y() + b2;
+
+ Uml::Region::Enum result = Uml::Region::Error;
+ //if inside region 1
+ if (eval1 > pos.x() && eval2 > pos.x()) {
+ result = Uml::Region::West;
+ }
+ //if inside region 2
+ else if (eval1 > pos.x() && eval2 < pos.x()) {
+ result = Uml::Region::North;
+ }
+ //if inside region 3
+ else if (eval1 < pos.x() && eval2 < pos.x()) {
+ result = Uml::Region::East;
+ }
+ //if inside region 4
+ else if (eval1 < pos.x() && eval2 > pos.x()) {
+ result = Uml::Region::South;
+ }
+ //if inside region 5
+ else if (eval1 == pos.x() && eval2 < pos.x()) {
+ result = Uml::Region::NorthWest;
+ }
+ //if inside region 6
+ else if (eval1 < pos.x() && eval2 == pos.x()) {
+ result = Uml::Region::NorthEast;
+ }
+ //if inside region 7
+ else if (eval1 == pos.x() && eval2 > pos.x()) {
+ result = Uml::Region::SouthEast;
+ }
+ //if inside region 8
+ else if (eval1 > pos.x() && eval2 == pos.x()) {
+ result = Uml::Region::SouthWest;
+ }
+ //if inside region 9
+ else if (eval1 == pos.x() && eval2 == pos.x()) {
+ result = Uml::Region::Center;
+ }
+ return result;
+}
+
+/**
+ * Returns a point with interchanged X and Y coordinates.
+ */
+QPointF AssociationWidget::swapXY(const QPointF &p)
+{
+ QPointF swapped( p.y(), p.x() );
+ return swapped;
+}
+
+#if 0 // not used at the moment
+/**
+ * Calculates which point of segment P1P2 has a distance equal to
+ * Distance from P1.
+ * Let's say such point is PX, the distance from P1 to PX must be equal
+ * to Distance and if PX is not a point of the segment P1P2 then the
+ * function returns (-1, -1).
+ */
+QPointF AssociationWidget::calculatePointAtDistance(const QPointF &P1, const QPointF &P2, float Distance)
+{
+ /*
+ the distance D between points (x1, y1) and (x3, y3) has the following formula:
+ --- ------------------------------
+ D = \ / 2 2
+ \ / (x3 - x1) + (y3 - y1)
+
+ D, x1 and y1 are known and the point (x3, y3) is inside line (x1, y1)(x2, y2), so if the
+ that line has the formula y = mx + b
+ then y3 = m*x3 + b
+
+ 2 2 2
+ D = (x3 - x1) + (y3 - y1)
+
+ 2 2 2 2 2
+ D = x3 - 2*x3*x1 + x1 + y3 - 2*y3*y1 + y1
+
+ 2 2 2 2 2
+ D - x1 - y1 = x3 - 2*x3*x1 + y3 - 2*y3*y1
+
+ 2 2 2 2 2
+ D - x1 - y1 = x3 - 2*x3*x1 + (m*x3 + b) - 2*(m*x3 + b)*y1
+
+ 2 2 2 2 2 2
+ D - x1 - y1 + 2*b*y1 - b = (m + 1)*x3 + (-2*x1 + 2*m*b -2*m*y1)*x3
+
+ 2 2 2 2
+ C = - D + x1 + y1 - 2*b*y1 + b
+
+
+ 2
+ A = (m + 1)
+
+ B = (-2*x1 + 2*m*b -2*m*y1)
+
+ and we have
+ 2
+ A * x3 + B * x3 - C = 0
+
+ ---------------
+ -B + --- / 2
+ \/ B - 4*A*C
+ sol_1 = --------------------------------
+ 2*A
+
+
+ ---------------
+ -B - --- / 2
+ \/ B - 4*A*C
+ sol_2 = --------------------------------
+ 2*A
+
+
+ then in the distance formula we have only one variable x3 and that is easy
+ to calculate
+ */
+ int x1 = P1.y();
+ int y1 = P1.x();
+ int x2 = P2.y();
+ int y2 = P2.x();
+
+ if (x2 == x1) {
+ return QPointF(x1, y1 + (int)Distance);
+ }
+ float slope = ((float)y2 - (float)y1) / ((float)x2 - (float)x1);
+ float b = (y1 - slope*x1);
+ float A = (slope * slope) + 1;
+ float B = (2*slope*b) - (2*x1) - (2*slope*y1);
+ float C = (b*b) - (Distance*Distance) + (x1*x1) + (y1*y1) - (2*b*y1);
+ float t = B*B - 4*A*C;
+
+ if (t < 0) {
+ return QPointF(-1, -1);
+ }
+ float sol_1 = ((-1* B) + sqrt(t)) / (2*A);
+ float sol_2 = ((-1*B) - sqrt(t)) / (2*A);
+
+ if (sol_1 < 0.0 && sol_2 < 0.0) {
+ return QPointF(-1, -1);
+ }
+ QPointF sol1Point((int)(slope*sol_1 + b), (int)(sol_1));
+ QPointF sol2Point((int)(slope*sol_2 + b), (int)(sol_2));
+ if (sol_1 < 0 && sol_2 >=0) {
+ if (x2 > x1) {
+ if (x1 <= sol_2 && sol_2 <= x2)
+ return sol2Point;
+ } else {
+ if (x2 <= sol_2 && sol_2 <= x1)
+ return sol2Point;
+ }
+ } else if (sol_1 >= 0 && sol_2 < 0) {
+ if (x2 > x1) {
+ if (x1 <= sol_1 && sol_1 <= x2)
+ return sol1Point;
+ } else {
+ if (x2 <= sol_1 && sol_1 <= x1)
+ return sol1Point;
+ }
+ } else {
+ if (x2 > x1) {
+ if (x1 <= sol_1 && sol_1 <= x2)
+ return sol1Point;
+ if (x1 <= sol_2 && sol_2 <= x2)
+ return sol2Point;
+ } else {
+ if (x2 <= sol_1 && sol_1 <= x1)
+ return sol1Point;
+ if (x2 <= sol_2 && sol_2 <= x1)
+ return sol2Point;
+ }
+ }
+ return QPointF(-1, -1);
+}
+
+/**
+ * Calculates which point of a perpendicular line to segment P1P2 that contains P2
+ * has a distance equal to Distance from P2,
+ * Lets say such point is P3, the distance from P2 to P3 must be equal to Distance
+ */
+QPointF AssociationWidget::calculatePointAtDistanceOnPerpendicular(const QPointF &P1, const QPointF &P2, float Distance)
+{
+ /*
+ the distance D between points (x2, y2) and (x3, y3) has the following formula:
+
+ --- ------------------------------
+ D = \ / 2 2
+ \ / (x3 - x2) + (y3 - y2)
+
+ D, x2 and y2 are known and line P2P3 is perpendicular to line (x1, y1)(x2, y2), so if the
+ line P1P2 has the formula y = m*x + b,
+ then (x1 - x2)
+ m = -----------, because it is perpendicular to line P1P2
+ (y2 - y1)
+
+ also y2 = m*x2 + b
+ => b = y2 - m*x2
+
+ then P3 = (x3, m*x3 + b)
+
+ 2 2 2
+ D = (x3 - x2) + (y3 - y2)
+
+ 2 2 2 2 2
+ D = x3 - 2*x3*x2 + x2 + y3 - 2*y3*y2 + y2
+
+ 2 2 2 2 2
+ D - x2 - y2 = x3 - 2*x3*x2 + y3 - 2*y3*y2
+
+
+
+ 2 2 2 2 2
+ D - x2 - y2 = x3 - 2*x3*x2 + (m*x3 + b) - 2*(m*x3 + b)*y2
+
+ 2 2 2 2 2 2
+ D - x2 - y2 + 2*b*y2 - b = (m + 1)*x3 + (-2*x2 + 2*m*b -2*m*y2)*x3
+
+ 2 2 2 2
+ C = - D + x2 + y2 - 2*b*y2 + b
+
+ 2
+ A = (m + 1)
+
+ B = (-2*x2 + 2*m*b -2*m*y2)
+
+ and we have
+ 2
+ A * x3 + B * x3 - C = 0
+
+
+ ---------------
+ --- / 2
+ -B + \/ B - 4*A*C
+ sol_1 = --------------------------------
+ 2*A
+
+
+ ---------------
+ --- / 2
+ -B - \/ B - 4*A*C
+ sol_2 = --------------------------------
+ 2*A
+
+ then in the distance formula we have only one variable x3 and that is easy
+ to calculate
+ */
+ if (P1.x() == P2.x()) {
+ return QPointF((int)(P2.x() + Distance), P2.y());
+ }
+ const int x1 = P1.y();
+ const int y1 = P1.x();
+ const int x2 = P2.y();
+ const int y2 = P2.x();
+
+ float slope = ((float)x1 - (float)x2) / ((float)y2 - (float)y1);
+ float b = (y2 - slope*x2);
+ float A = (slope * slope) + 1;
+ float B = (2*slope*b) - (2*x2) - (2*slope*y2);
+ float C = (b*b) - (Distance*Distance) + (x2*x2) + (y2*y2) - (2*b*y2);
+ float t = B*B - 4*A*C;
+ if (t < 0) {
+ return QPointF(-1, -1);
+ }
+ float sol_1 = ((-1* B) + sqrt(t)) / (2*A);
+
+ float sol_2 = ((-1*B) - sqrt(t)) / (2*A);
+
+ if (sol_1 < 0 && sol_2 < 0) {
+ return QPointF(-1, -1);
+ }
+ QPointF sol1Point((int)(slope*sol_1 + b), (int)sol_1);
+ QPointF sol2Point((int)(slope*sol_2 + b), (int)sol_2);
+ if (sol_1 < 0 && sol_2 >=0) {
+ return sol2Point;
+ } else if (sol_1 >= 0 && sol_2 < 0) {
+ return sol1Point;
+ } else { // Choose one solution, either will work fine
+ if (slope >= 0) {
+ if (sol_1 <= sol_2)
+ return sol2Point;
+ else
+ return sol1Point;
+ } else {
+ if (sol_1 <= sol_2)
+ return sol1Point;
+ else
+ return sol2Point;
+ }
+
+ }
+ return QPointF(-1, -1); // never reached, just keep compilers happy
+}
+
+/**
+ * Calculates the intersection (PS) between line P1P2 and a perpendicular line containing
+ * P3, the result is returned in ResultingPoint. and result value represents the distance
+ * between ResultingPoint and P3; if this value is negative an error ocurred.
+ */
+float AssociationWidget::perpendicularProjection(const QPointF& P1, const QPointF& P2, const QPointF& P3,
+ QPointF& ResultingPoint)
+{
+ //line P1P2 is Line 1 = y=slope1*x + b1
+
+ //line P3PS is Line 1 = y=slope2*x + b2
+
+ float slope2 = 0;
+ float slope1 = 0;
+ float sx = 0, sy = 0;
+ int y2 = P2.x();
+ int y1 = P1.x();
+ int x2 = P2.y();
+ int x1 = P1.y();
+ int y3 = P3.x();
+ int x3 = P3.y();
+ float distance = 0;
+ float b1 = 0;
+
+ float b2 = 0;
+
+ if (x2 == x1) {
+ sx = x2;
+ sy = y3;
+ } else if (y2 == y1) {
+ sy = y2;
+ sx = x3;
+ } else {
+ slope1 = (y2 - y1)/ (x2 - x1);
+ slope2 = (x1 - x2)/ (y2 - y1);
+ b1 = y2 - (slope1 * x2);
+ b2 = y3 - (slope2 * x3);
+ sx = (b2 - b1) / (slope1 - slope2);
+ sy = slope1*sx + b1;
+ }
+ distance = (int)(sqrt(((x3 - sx)*(x3 - sx)) + ((y3 - sy)*(y3 - sy))));
+
+ ResultingPoint.setX((int)sy);
+ ResultingPoint.setY((int)sx);
+
+ return distance;
+}
+#endif
+
+/**
+ * Calculates the position of the text widget depending on the role
+ * that widget is playing.
+ * Returns the point at which to put the widget.
+ */
+QPointF AssociationWidget::calculateTextPosition(Uml::TextRole::Enum role)
+{
+ const int SPACE = 2;
+ QPointF p(-1, -1), q(-1, -1);
+
+ // used to find out if association end point (p)
+ // is at top or bottom edge of widget.
+
+ if (role == TextRole::MultiA || role == TextRole::ChangeA || role == TextRole::RoleAName) {
+ p = m_associationLine->point(0);
+ q = m_associationLine->point(1);
+ } else if (role == TextRole::MultiB || role == TextRole::ChangeB || role == TextRole::RoleBName) {
+ const int lastSegment = m_associationLine->count() - 1;
+ p = m_associationLine->point(lastSegment);
+ q = m_associationLine->point(lastSegment - 1);
+ } else if (role != TextRole::Name) {
+ uError() << "called with unsupported TextRole::Enum " << role;
+ return QPointF(-1, -1);
+ }
+
+ FloatingTextWidget *text = textWidgetByRole(role);
+ int textW = 0, textH = 0;
+ if (text) {
+ textW = text->width();
+ textH = text->height();
+ }
+
+ qreal x = 0.0, y = 0.0;
+
+ if (role == TextRole::MultiA || role == TextRole::MultiB) {
+ const bool isHorizontal = (p.y() == q.y());
+ const int atBottom = p.y() + SPACE;
+ const int atTop = p.y() - SPACE - textH;
+ const int atLeft = p.x() - SPACE - textW;
+ const int atRight = p.x() + SPACE;
+ y = (p.y() > q.y()) == isHorizontal ? atBottom : atTop;
+ x = (p.x() < q.x()) == isHorizontal ? atRight : atLeft;
+
+ } else if (role == TextRole::ChangeA || role == TextRole::ChangeB) {
+
+ if (p.y() > q.y())
+ y = p.y() - SPACE - (textH * 2);
+ else
+ y = p.y() + SPACE + textH;
+
+ if (p.x() < q.x())
+ x = p.x() + SPACE;
+ else
+ x = p.x() - SPACE - textW;
+
+ } else if (role == TextRole::RoleAName || role == TextRole::RoleBName) {
+
+ if (p.y() > q.y())
+ y = p.y() - SPACE - textH;
+ else
+ y = p.y() + SPACE;
+
+ if (p.x() < q.x())
+ x = p.x() + SPACE;
+ else
+ x = p.x() - SPACE - textW;
+
+ } else if (role == TextRole::Name) {
+
+ calculateNameTextSegment();
+ if (m_unNameLineSegment == -1) {
+ uWarning() << "TODO:negative line segment index";
+ m_unNameLineSegment = 0;
+ }
+ x = ( m_associationLine->point(m_unNameLineSegment).x() +
+ m_associationLine->point(m_unNameLineSegment + 1).x() ) / 2;
+ y = ( m_associationLine->point(m_unNameLineSegment).y() +
+ m_associationLine->point(m_unNameLineSegment + 1).y() ) / 2;
+ }
+
+ if (text) {
+ constrainTextPos(x, y, textW, textH, role);
+ }
+ p = QPointF( x, y );
+ return p;
+}
+
+/**
+ * Return the mid point between p0 and p1
+ */
+QPointF AssociationWidget::midPoint(const QPointF& p0, const QPointF& p1)
+{
+ QPointF midP;
+ if (p0.x() < p1.x())
+ midP.setX(p0.x() + (p1.x() - p0.x()) / 2);
+ else
+ midP.setX(p1.x() + (p0.x() - p1.x()) / 2);
+ if (p0.y() < p1.y())
+ midP.setY(p0.y() + (p1.y() - p0.y()) / 2);
+ else
+ midP.setY(p1.y() + (p0.y() - p1.y()) / 2);
+ return midP;
+}
+
+/**
+ * Constrains the FloatingTextWidget X and Y values supplied.
+ * Implements the abstract operation from LinkWidget.
+ *
+ * @param textX Candidate X value (may be modified by the constraint.)
+ * @param textY Candidate Y value (may be modified by the constraint.)
+ * @param textWidth Width of the text.
+ * @param textHeight Height of the text.
+ * @param tr Uml::Text_Role of the text.
+ */
+void AssociationWidget::constrainTextPos(qreal &textX, qreal &textY,
+ qreal textWidth, qreal textHeight,
+ Uml::TextRole::Enum tr)
+{
+ const int textCenterX = textX + textWidth / 2;
+ const int textCenterY = textY + textHeight / 2;
+ const int lastSegment = m_associationLine->count() - 1;
+ QPointF p0, p1;
+ switch (tr) {
+ case TextRole::RoleAName:
+ case TextRole::MultiA:
+ case TextRole::ChangeA:
+ p0 = m_associationLine->point(0);
+ p1 = m_associationLine->point(1);
+ // If we are dealing with a single line then tie the
+ // role label to the proper half of the line, i.e.
+ // the role label must be closer to the "other"
+ // role object.
+ if (lastSegment == 1)
+ p1 = midPoint(p0, p1);
+ break;
+ case TextRole::RoleBName:
+ case TextRole::MultiB:
+ case TextRole::ChangeB:
+ p0 = m_associationLine->point(lastSegment - 1);
+ p1 = m_associationLine->point(lastSegment);
+ if (lastSegment == 1)
+ p0 = midPoint(p0, p1);
+ break;
+ case TextRole::Name:
+ case TextRole::Coll_Message: // CHECK: collab.msg texts seem to be TextRole::Name
+ case TextRole::State: // CHECK: is this used?
+ // Find the linepath segment to which the (textX, textY) is closest
+ // and constrain to the corridor of that segment (see farther below)
+ {
+ int minDistSquare = 100000; // utopian initial value
+ int lpIndex = 0;
+ for (int i = 0; i < lastSegment; ++i) {
+ p0 = m_associationLine->point(i);
+ p1 = m_associationLine->point(i + 1);
+ QPointF midP = midPoint(p0, p1);
+ const int deltaX = textCenterX - midP.x();
+ const int deltaY = textCenterY - midP.y();
+ const int cSquare = deltaX * deltaX + deltaY * deltaY;
+ if (cSquare < minDistSquare) {
+ minDistSquare = cSquare;
+ lpIndex = i;
+ }
+ }
+ p0 = m_associationLine->point(lpIndex);
+ p1 = m_associationLine->point(lpIndex + 1);
+ }
+ break;
+ default:
+ uError() << "unexpected TextRole::Enum " << tr;
+ return;
+ break;
+ }
+ /* Constraint:
+ The midpoint between p0 and p1 is taken to be the center of a circle
+ with radius D/2 where D is the distance between p0 and p1.
+ The text center needs to be within this circle else it is constrained
+ to the nearest point on the circle.
+ */
+ p0 = swapXY(p0); // go to the natural coordinate system
+ p1 = swapXY(p1); // with (0,0) in the lower left corner
+ QPointF midP = midPoint(p0, p1);
+ // If (textX,textY) is not inside the circle around midP then
+ // constrain (textX,textY) to the nearest point on that circle.
+ const int x0 = p0.x();
+ const int y0 = p0.y();
+ const int x1 = p1.x();
+ const int y1 = p1.y();
+ double r = sqrt((double)((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0))) / 2;
+ if (textWidth > r)
+ r = textWidth;
+ // swap textCenter{X,Y} to convert from Qt coord.system.
+ const QPointF origTextCenter(textCenterY, textCenterX);
+ const int relX = abs(origTextCenter.x() - midP.x());
+ const int relY = abs(origTextCenter.y() - midP.y());
+ const double negativeWhenInsideCircle = relX * relX + relY * relY - r * r;
+ if (negativeWhenInsideCircle <= 0.0) {
+ return;
+ }
+ /*
+ The original constraint was to snap the text position to the
+ midpoint but that creates unpleasant visual jitter:
+ textX = midP.y() - textWidth / 2; // go back to Qt coord.sys.
+ textY = midP.x() - textHeight / 2; // go back to Qt coord.sys.
+
+ Rather, we project the text position onto the closest point
+ on the circle:
+
+ Circle equation:
+ relX^2 + relY^2 - r^2 = 0, or in other words
+ relY^2 = r^2 - relX^2, or
+ relY = sqrt(r^2 - relX^2)
+ Line equation:
+ relY = a * relX + b
+ We can omit "b" because relX and relY are already relative to
+ the circle origin, therefore we can also write:
+ a = relY / relX
+ To obtain the point of intersection between the circle of radius r
+ and the line connecting the circle origin with the point (relX, relY),
+ we equate the relY:
+ a * x = sqrt(r^2 - x^2), or in other words
+ a^2 * x^2 = r^2 - x^2, or
+ x^2 * (a^2 + 1) = r^2, or
+ x^2 = r^2 / (a^2 + 1), or
+ x = sqrt(r^2 / (a^2 + 1))
+ and then
+ y = a * x
+ The resulting x and y are relative to the circle origin so we just add
+ the circle origin (X, Y) to obtain the constrained (textX, textY).
+ */
+ // Handle the special case, relX = 0.
+ if (relX == 0) {
+ if (origTextCenter.y() > midP.y())
+ textX = midP.y() + (int)r; // go back to Qt coord.sys.
+ else
+ textX = midP.y() - (int)r; // go back to Qt coord.sys.
+ textX -= textWidth / 2;
+ return;
+ }
+ const double a = (double)relY / (double)relX;
+ const double x = sqrt(r*r / (a*a + 1));
+ const double y = a * x;
+ if (origTextCenter.x() > midP.x())
+ textY = midP.x() + (int)x; // go back to Qt coord.sys.
+ else
+ textY = midP.x() - (int)x; // go back to Qt coord.sys.
+ textY -= textHeight / 2;
+ if (origTextCenter.y() > midP.y())
+ textX = midP.y() + (int)y; // go back to Qt coord.sys.
+ else
+ textX = midP.y() - (int)y; // go back to Qt coord.sys.
+ textX -= textWidth / 2;
+}
+
+/**
+ * Puts the text widget with the given role at the given position.
+ * This method calls @ref calculateTextPostion to get the needed position.
+ * I.e. the line segment it is on has moved and it should move the same
+ * amount as the line.
+ */
+void AssociationWidget::setTextPosition(Uml::TextRole::Enum role)
+{
+ bool startMove = false;
+ if (m_role[RoleType::A].multiplicityWidget && m_role[RoleType::A].multiplicityWidget->getStartMove())
+ startMove = true;
+ else if (m_role[RoleType::B].multiplicityWidget && m_role[RoleType::B].multiplicityWidget->getStartMove())
+ startMove = true;
+ else if (m_role[RoleType::A].changeabilityWidget && m_role[RoleType::A].changeabilityWidget->getStartMove())
+ startMove = true;
+ else if (m_role[RoleType::B].changeabilityWidget && m_role[RoleType::B].changeabilityWidget->getStartMove())
+ startMove = true;
+ else if (m_role[RoleType::A].roleWidget && m_role[RoleType::A].roleWidget->getStartMove())
+ startMove = true;
+ else if (m_role[RoleType::B].roleWidget && m_role[RoleType::B].roleWidget->getStartMove())
+ startMove = true;
+ else if (m_nameWidget && m_nameWidget->getStartMove())
+ startMove = true;
+ if (startMove) {
+ return;
+ }
+ FloatingTextWidget *ft = textWidgetByRole(role);
+ if (ft == NULL)
+ return;
+ QPointF pos = calculateTextPosition(role);
+ ft->setX(pos.x());
+ ft->setY(pos.y());
+}
+
+/**
+ * Moves the text widget with the given role by the difference between
+ * the two points.
+ */
+void AssociationWidget::setTextPositionRelatively(Uml::TextRole::Enum role, const QPointF &oldPosition)
+{
+ bool startMove = false;
+ if (m_role[RoleType::A].multiplicityWidget && m_role[RoleType::A].multiplicityWidget->getStartMove())
+ startMove = true;
+ else if (m_role[RoleType::B].multiplicityWidget && m_role[RoleType::B].multiplicityWidget->getStartMove())
+ startMove = true;
+ else if (m_role[RoleType::A].changeabilityWidget && m_role[RoleType::A].changeabilityWidget->getStartMove())
+ startMove = true;
+ else if (m_role[RoleType::B].changeabilityWidget && m_role[RoleType::B].changeabilityWidget->getStartMove())
+ startMove = true;
+ else if (m_role[RoleType::A].roleWidget && m_role[RoleType::A].roleWidget->getStartMove())
+ startMove = true;
+ else if (m_role[RoleType::B].roleWidget && m_role[RoleType::B].roleWidget->getStartMove())
+ startMove = true;
+ else if (m_nameWidget && m_nameWidget->getStartMove())
+ startMove = true;
+
+ if (startMove) {
+ return;
+ }
+ FloatingTextWidget *ft = textWidgetByRole(role);
+ if (ft == NULL)
+ return;
+ qreal ftX = ft->x();
+ qreal ftY = ft->y();
+
+ QPointF pos = calculateTextPosition(role);
+ int relX = pos.x() - oldPosition.x();
+ int relY = pos.y() - oldPosition.y();
+ qreal ftNewX = ftX + relX;
+ qreal ftNewY = ftY + relY;
+
+ bool oldIgnoreSnapToGrid = ft->getIgnoreSnapToGrid();
+ ft->setIgnoreSnapToGrid(true);
+ ft->setX(ftNewX);
+ ft->setY(ftNewY);
+ ft->setIgnoreSnapToGrid(oldIgnoreSnapToGrid);
+}
+
+/**
+ * Remove dashed connecting line for association class.
+ */
+void AssociationWidget::removeAssocClassLine()
+{
+ delete m_pAssocClassLineSel0;
+ m_pAssocClassLineSel0 = 0;
+ delete m_pAssocClassLineSel1;
+ m_pAssocClassLineSel1 = 0;
+ delete m_pAssocClassLine;
+ m_pAssocClassLine = 0;
+ if (m_associationClass) {
+ m_associationClass->setClassAssociationWidget(0);
+ m_associationClass = 0;
+ }
+}
+
+/**
+ * Creates the association class connecting line.
+ */
+void AssociationWidget::createAssocClassLine()
+{
+ if (m_pAssocClassLine == NULL) {
+ m_pAssocClassLine = new QGraphicsLineItem(this);
+ }
+ QPen pen(lineColor(), lineWidth(), Qt::DashLine);
+ m_pAssocClassLine->setPen(pen);
+ // decoration points
+ m_pAssocClassLineSel0 = Widget_Utils::decoratePoint(m_pAssocClassLine->line().p1(),
+ m_pAssocClassLine);
+ m_pAssocClassLineSel1 = Widget_Utils::decoratePoint(m_pAssocClassLine->line().p2(),
+ m_pAssocClassLine);
+ computeAssocClassLine();
+ selectAssocClassLine(false);
+}
+
+/**
+ * Creates the association class connecting line using the specified
+ * ClassifierWidget.
+ *
+ * @param classifier The ClassifierWidget to use.
+ * @param linePathSegmentIndex The index of the segment where the
+ * association class is created.
+ */
+void AssociationWidget::createAssocClassLine(ClassifierWidget* classifier,
+ int linePathSegmentIndex)
+{
+ m_nLinePathSegmentIndex = linePathSegmentIndex;
+
+ if (m_nLinePathSegmentIndex < 0) {
+ return;
+ }
+
+ m_associationClass = classifier;
+ m_associationClass->setClassAssociationWidget(this);
+ m_associationClass->addAssoc(this); // to get widgetMoved(...) for association classes
+
+ createAssocClassLine();
+}
+
+/**
+ * Compute the end points of m_pAssocClassLine in case this
+ * association has an attached association class.
+ * TODO: The decoration points make no sense for now, because they are not movable.
+ */
+void AssociationWidget::computeAssocClassLine()
+{
+ if (m_associationClass == NULL || m_pAssocClassLine == NULL) {
+ return;
+ }
+ if (m_nLinePathSegmentIndex < 0) {
+ uError() << "m_nLinePathSegmentIndex is not set";
+ return;
+ }
+
+ QPointF segStart = m_associationLine->point(m_nLinePathSegmentIndex);
+ QPointF segEnd = m_associationLine->point(m_nLinePathSegmentIndex + 1);
+ const qreal midSegX = segStart.x() + (segEnd.x() - segStart.x()) / 2.0;
+ const qreal midSegY = segStart.y() + (segEnd.y() - segStart.y()) / 2.0;
+ QPointF segmentMidPoint(midSegX, midSegY);
+
+ QLineF possibleAssocLine = QLineF(segmentMidPoint,
+ m_associationClass->mapRectToScene(m_associationClass->rect()).center());
+ QPointF intersectionPoint;
+ QLineF::IntersectType type = intersect(m_associationClass->mapRectToScene(m_associationClass->boundingRect()),
+ possibleAssocLine,
+ &intersectionPoint);
+ // DEBUG(DBG_SRC) << "intersect type=" << type << " / point=" << intersectionPoint;
+
+ if (type == QLineF::BoundedIntersection) {
+ m_pAssocClassLine->setLine(midSegX, midSegY,
+ intersectionPoint.x(), intersectionPoint.y());
+
+ if (m_pAssocClassLineSel0 && m_pAssocClassLineSel1) {
+ m_pAssocClassLineSel0->setPos(m_pAssocClassLine->line().p1());
+ m_pAssocClassLineSel1->setPos(m_pAssocClassLine->line().p2());
+ }
+ }
+}
+
+/**
+ * Renders the association class connecting line selected.
+ */
+void AssociationWidget::selectAssocClassLine(bool sel)
+{
+ if (m_pAssocClassLineSel0 && m_pAssocClassLineSel1) {
+ m_pAssocClassLineSel0->setVisible(sel);
+ m_pAssocClassLineSel1->setVisible(sel);
+ }
+}
+
+/**
+ * Sets the association to be selected.
+ */
+void AssociationWidget::mousePressEvent(QGraphicsSceneMouseEvent * me)
+{
+ // clear other selected stuff on the screen of ShiftKey
+ if (me->modifiers() != Qt::ShiftModifier) {
+ m_scene->clearSelected();
+ }
+
+ if (me->button() == Qt::LeftButton && me->modifiers() == Qt::ControlModifier) {
+ if (checkRemovePoint(me->scenePos()))
+ return;
+ }
+
+ // make sure we should be here depending on the button
+ if (me->button() != Qt::RightButton && me->button() != Qt::LeftButton) {
+ return;
+ }
+ QPointF mep = me->scenePos();
+ // see if `mep' is on the connecting line to the association class
+ if (onAssocClassLine(mep)) {
+ setSelected(true);
+ selectAssocClassLine();
+ return;
+ }
+ setSelected(!isSelected());
+ associationLine()->mousePressEvent(me);
+}
+
+/**
+ * Displays the right mouse buttom menu if right button is pressed.
+ */
+void AssociationWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent * me)
+{
+ associationLine()->mouseReleaseEvent(me);
+}
+
+/**
+ * Handles the selection from the popup menu.
+ */
+void AssociationWidget::slotMenuSelection(QAction* action)
+{
+ QString oldText, newText;
+ QRegExpValidator v(QRegExp(QLatin1String(".*")), 0);
+ Uml::AssociationType::Enum atype = associationType();
+ Uml::RoleType::Enum r = RoleType::B;
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ DEBUG(DBG_SRC) << "menu selection = " << ListPopupMenu::toString(sel);
+
+ // if it's a collaboration message we now just use the code in floatingtextwidget
+ // this means there's some redundant code below but that's better than duplicated code
+ if (isCollaboration() && sel != ListPopupMenu::mt_Delete) {
+ m_nameWidget->slotMenuSelection(action);
+ return;
+ }
+
+ switch(sel) {
+ case ListPopupMenu::mt_Properties:
+ if (atype == AssociationType::Seq_Message || atype == AssociationType::Seq_Message_Self) {
+ // show op dlg for seq. diagram here
+ // don't worry about here, I don't think it can get here as
+ // line is widget on seq. diagram
+ // here just in case - remove later after testing
+ DEBUG(DBG_SRC) << "mt_Properties: assoctype is " << atype;
+ } else { //standard assoc dialog
+ UMLApp::app()->docWindow()->updateDocumentation(false);
+ showPropertiesDialog();
+ }
+ break;
+
+ case ListPopupMenu::mt_Add_Point:
+ checkAddPoint(m_eventScenePos);
+ break;
+
+ case ListPopupMenu::mt_Delete_Point:
+ checkRemovePoint(m_eventScenePos);
+ break;
+
+ case ListPopupMenu::mt_Delete:
+ if (m_pAssocClassLineSel0)
+ removeAssocClassLine();
+ else if (association())
+ m_scene->removeAssocInViewAndDoc(this);
+ else
+ m_scene->removeAssoc(this);
+ break;
+
+ case ListPopupMenu::mt_Rename_MultiA:
+ r = RoleType::A; // fall through
+ case ListPopupMenu::mt_Rename_MultiB:
+ if (m_role[r].multiplicityWidget)
+ oldText = m_role[r].multiplicityWidget->text();
+ else
+ oldText = QString();
+#if QT_VERSION >= 0x050000
+ newText = QInputDialog::getText(m_scene->activeView(),
+ i18n("Multiplicity"),
+ i18n("Enter multiplicity:"),
+ QLineEdit::Normal,
+ oldText, NULL);
+#else
+ newText = KInputDialog::getText(i18n("Multiplicity"),
+ i18n("Enter multiplicity:"),
+ oldText, NULL, m_scene->activeView(), &v);
+#endif
+ if (newText != oldText) {
+ if (FloatingTextWidget::isTextValid(newText)) {
+ setMultiplicity(newText, r);
+ } else {
+ m_scene->removeWidget(m_role[r].multiplicityWidget);
+ m_role[r].multiplicityWidget = NULL;
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Rename_Name:
+ if (m_nameWidget)
+ oldText = m_nameWidget->text();
+ else
+ oldText = QString();
+#if QT_VERSION >= 0x050000
+ newText = QInputDialog::getText(m_scene->activeView(),
+ i18n("Association Name"),
+ i18n("Enter association name:"),
+ QLineEdit::Normal,
+ oldText, NULL);
+#else
+ newText = KInputDialog::getText(i18n("Association Name"),
+ i18n("Enter association name:"),
+ oldText, NULL, m_scene->activeView(), &v);
+#endif
+ if (newText != oldText) {
+ if (FloatingTextWidget::isTextValid(newText)) {
+ setName(newText);
+ } else if (m_nameWidget) {
+ m_scene->removeWidget(m_nameWidget);
+ m_nameWidget = NULL;
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Rename_RoleAName:
+ r = RoleType::A; // fall through
+ case ListPopupMenu::mt_Rename_RoleBName:
+ if (m_role[r].roleWidget)
+ oldText = m_role[r].roleWidget->text();
+ else
+ oldText = QString();
+#if QT_VERSION >= 0x050000
+ newText = QInputDialog::getText(m_scene->activeView(),
+ i18n("Role Name"),
+ i18n("Enter role name:"),
+ QLineEdit::Normal,
+ oldText, NULL);
+#else
+ newText = KInputDialog::getText(i18n("Role Name"),
+ i18n("Enter role name:"),
+ oldText, NULL, m_scene->activeView(), &v);
+#endif
+ if (newText != oldText) {
+ if (FloatingTextWidget::isTextValid(newText)) {
+ setRoleName(newText, r);
+ } else {
+ m_scene->removeWidget(m_role[r].roleWidget);
+ m_role[r].roleWidget = NULL;
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Change_Font:
+ {
+#if QT_VERSION >= 0x050000
+ bool ok = false;
+ QFont fnt = QFontDialog::getFont(&ok, font(), m_scene->activeView());
+ if (ok)
+#else
+ QFont fnt = font();
+ if (KFontDialog::getFont(fnt, KFontChooser::NoDisplayFlags, m_scene->activeView()))
+#endif
+ lwSetFont(fnt);
+ }
+ break;
+
+ case ListPopupMenu::mt_Line_Color:
+ {
+#if QT_VERSION >= 0x050000
+ QColor newColor = QColorDialog::getColor(lineColor());
+ if (newColor != lineColor()) {
+#else
+ QColor newColor;
+ if (KColorDialog::getColor(newColor)) {
+#endif
+ m_scene->selectionSetLineColor(newColor);
+ umlDoc()->setModified(true);
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Cut:
+ m_scene->setStartedCut();
+ UMLApp::app()->slotEditCut();
+ break;
+
+ case ListPopupMenu::mt_Copy:
+ UMLApp::app()->slotEditCopy();
+ break;
+
+ case ListPopupMenu::mt_Paste:
+ UMLApp::app()->slotEditPaste();
+ break;
+
+ case ListPopupMenu::mt_Reset_Label_Positions:
+ resetTextPositions();
+ break;
+
+ case ListPopupMenu::mt_LayoutDirect:
+ m_associationLine->setLayout(AssociationLine::Direct);
+ break;
+ case ListPopupMenu::mt_LayoutSpline:
+ m_associationLine->setLayout(AssociationLine::Spline);
+ break;
+ case ListPopupMenu::mt_LayoutOrthogonal:
+ m_associationLine->setLayout(AssociationLine::Orthogonal);
+ break;
+ case ListPopupMenu::mt_LayoutPolyline:
+ m_associationLine->setLayout(AssociationLine::Polyline);
+ break;
+
+ default:
+ DEBUG(DBG_SRC) << "MenuType " << ListPopupMenu::toString(sel) << " not implemented";
+ break;
+ }//end switch
+}
+
+/**
+ * Return the first font found being used by any child widget. (They
+ * could be different fonts, so this is a slightly misleading method.)
+ */
+QFont AssociationWidget::font() const
+{
+ //:TODO: find a general font for the association
+ QFont font;
+
+ if (m_role[RoleType::A].roleWidget)
+ font = m_role[RoleType::A].roleWidget->font();
+ else if (m_role[RoleType::B].roleWidget)
+ font = m_role[RoleType::B].roleWidget->font();
+ else if (m_role[RoleType::A].multiplicityWidget)
+ font = m_role[RoleType::A].multiplicityWidget->font();
+ else if (m_role[RoleType::B].multiplicityWidget)
+ font = m_role[RoleType::B].multiplicityWidget->font();
+ else if (m_role[RoleType::A].changeabilityWidget)
+ font = m_role[RoleType::A].changeabilityWidget->font();
+ else if (m_role[RoleType::B].changeabilityWidget)
+ font = m_role[RoleType::B].changeabilityWidget->font();
+ else if (m_nameWidget)
+ font = m_nameWidget->font();
+ else
+ font = m_role[RoleType::A].umlWidget->font();
+
+ return font;
+}
+
+/**
+ * Set all 'owned' child widgets to this text color.
+ */
+void AssociationWidget::setTextColor(const QColor &color)
+{
+ WidgetBase::setTextColor(color);
+ if (m_nameWidget) {
+ m_nameWidget->setTextColor(color);
+ }
+ if (m_role[RoleType::A].roleWidget) {
+ m_role[RoleType::A].roleWidget->setTextColor(color);
+ }
+ if (m_role[RoleType::B].roleWidget) {
+ m_role[RoleType::B].roleWidget->setTextColor(color);
+ }
+ if (m_role[RoleType::A].multiplicityWidget) {
+ m_role[RoleType::A].multiplicityWidget->setTextColor(color);
+ }
+ if (m_role[RoleType::B].multiplicityWidget) {
+ m_role[RoleType::B].multiplicityWidget->setTextColor(color);
+ }
+ if (m_role[RoleType::A].changeabilityWidget)
+ m_role[RoleType::A].changeabilityWidget->setTextColor(color);
+ if (m_role[RoleType::B].changeabilityWidget)
+ m_role[RoleType::B].changeabilityWidget->setTextColor(color);
+}
+
+bool AssociationWidget::checkAddPoint(const QPointF &scenePos)
+{
+ if (associationType() == AssociationType::Exception) {
+ return false;
+ }
+
+ // if there is no point around the mouse pointer, we insert a new one
+ if (m_associationLine->closestPointIndex(scenePos) < 0) {
+ int i = m_associationLine->closestSegmentIndex(scenePos);
+ if (i < 0) {
+ DEBUG(DBG_SRC) << "no closest segment found!";
+ return false;
+ }
+ m_associationLine->insertPoint(i + 1, scenePos);
+ if (m_nLinePathSegmentIndex == i) {
+ QPointF segStart = m_associationLine->point(i);
+ QPointF segEnd = m_associationLine->point(i + 2);
+ const int midSegX = segStart.x() + (segEnd.x() - segStart.x()) / 2;
+ const int midSegY = segStart.y() + (segEnd.y() - segStart.y()) / 2;
+ /*
+ DEBUG(DBG_SRC) << "segStart=" << segStart << ", segEnd=" << segEnd
+ << ", midSeg=(" << midSegX << "," << midSegY
+ << "), mp=" << mp;
+ */
+ if (midSegX > scenePos.x() || midSegY < scenePos.y()) {
+ m_nLinePathSegmentIndex++;
+ DEBUG(DBG_SRC) << "setting m_nLinePathSegmentIndex to "
+ << m_nLinePathSegmentIndex;
+ computeAssocClassLine();
+ }
+ m_associationLine->update();
+ calculateNameTextSegment();
+ umlDoc()->setModified(true);
+ setSelected(true);
+ }
+ return true;
+ }
+ else {
+ DEBUG(DBG_SRC) << "found point already close enough!";
+ return false;
+ }
+}
+
+/**
+ * Remove point close to the given point and redraw the association.
+ * @param scenePos point which should be removed
+ * @return success status of the remove action
+ */
+bool AssociationWidget::checkRemovePoint(const QPointF &scenePos)
+{
+ int i = m_associationLine->closestPointIndex(scenePos);
+ if (i == -1)
+ return false;
+
+ m_associationLine->setSelected(false);
+
+ // there was a point so we remove the point
+ m_associationLine->removePoint(i);
+
+ // Maybe reattach association class connecting line
+ // to different association linepath segment.
+ const int numberOfLines = m_associationLine->count() - 1;
+ if (m_nLinePathSegmentIndex >= numberOfLines) {
+ m_nLinePathSegmentIndex = numberOfLines - 1;
+ }
+ calculateEndingPoints();
+
+ // select the line path
+ m_associationLine->setSelected(true);
+
+ m_associationLine->update();
+
+ calculateNameTextSegment();
+ umlDoc()->setModified(true);
+ return true;
+}
+
+/**
+ * Moves the break point being dragged.
+ */
+void AssociationWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* me)
+{
+ if (me->buttons() != Qt::LeftButton) {
+ return;
+ }
+
+ setSelected(true);
+
+ associationLine()->mouseMoveEvent(me);
+ moveEvent(me);
+ m_scene->resizeSceneToItems();
+}
+
+/**
+ * Returns the Region the widget to line intersection is for the given
+ * widget in this Association. If the given widget is not in the
+ * Association then Region::Error is returned.
+ * Used by @ref calculateEndingPoints to work these positions out for
+ * another Association - since the number of Associations on the same
+ * region for the same widget will mean the lines will need to be
+ * spread out across the region.
+ */
+//Uml::Region::Enum AssociationWidget::getWidgetRegion(AssociationWidget * widget) const
+//{
+// if (widget->widgetForRole(RoleType::A) == m_role[RoleType::A].umlWidget)
+// return m_role[RoleType::A].m_WidgetRegion;
+// if (widget->widgetForRole(RoleType::B) == m_role[RoleType::B].umlWidget)
+// return m_role[RoleType::B].m_WidgetRegion;
+// return Uml::Region::Error;
+//}
+
+/**
+ * Returns the number of lines there are on the given region for
+ * either widget A or B of the association.
+ */
+int AssociationWidget::getRegionCount(Uml::Region::Enum region, Uml::RoleType::Enum role)
+{
+ if ((region == Uml::Region::Error) | (umlScene() == NULL)) {
+ return 0;
+ }
+ int widgetCount = 0;
+ AssociationWidgetList list = m_scene->associationList();
+ foreach (AssociationWidget* assocwidget, list) {
+ //don't count this association
+ if (assocwidget == this)
+ continue;
+ const WidgetRole& otherA = assocwidget->m_role[RoleType::A];
+ const WidgetRole& otherB = assocwidget->m_role[RoleType::B];
+ const UMLWidget *a = otherA.umlWidget;
+ const UMLWidget *b = otherB.umlWidget;
+ /*
+ //don't count associations to self if both of their end points are on the same region
+ //they are different and placement won't interfere with them
+ if (a == b && otherA.m_WidgetRegion == otherB.m_WidgetRegion)
+ continue;
+ */
+ if (m_role[role].umlWidget == a && region == otherA.m_WidgetRegion)
+ widgetCount++;
+ else if (m_role[role].umlWidget == b && region == otherB.m_WidgetRegion)
+ widgetCount++;
+ }//end foreach
+ return widgetCount;
+}
+
+/**
+ * Find the border point of the given rect when a line is drawn from the
+ * given point to the rect.
+ * @param rect rect of a classifier
+ * @param line a line to the rect
+ * @param intersectionPoint the intercept point on the border of the rect
+ * @return the type of the intersection @ref QLineF::IntersectType
+ */
+QLineF::IntersectType AssociationWidget::intersect(const QRectF &rect, const QLineF &line,
+ QPointF* intersectionPoint)
+{
+ QList<QLineF> lines;
+ lines << QLineF(rect.topLeft(), rect.topRight());
+ lines << QLineF(rect.topRight(), rect.bottomRight());
+ lines << QLineF(rect.bottomRight(), rect.bottomLeft());
+ lines << QLineF(rect.bottomLeft(), rect.topLeft());
+ foreach (const QLineF& rectLine, lines) {
+ QLineF::IntersectType type = rectLine.intersect(line, intersectionPoint);
+ if (type == QLineF::BoundedIntersection) {
+ return type;
+ }
+ }
+ return QLineF::NoIntersection;
+}
+
+/**
+ * Given a rectangle and a point, findInterceptOnEdge computes the
+ * connecting line between the middle point of the rectangle and
+ * the point, and returns the intercept of this line with the
+ * the edge of the rectangle identified by `region'.
+ * When the region is North or South, the X value is returned (Y is
+ * constant.)
+ * When the region is East or West, the Y value is returned (X is
+ * constant.)
+ * @todo This is buggy. Try replacing by intersect()
+ */
+qreal AssociationWidget::findInterceptOnEdge(const QRectF &rect,
+ Uml::Region::Enum region,
+ const QPointF &point)
+{
+ // The Qt coordinate system has (0, 0) in the top left corner.
+ // In order to go to the regular XY coordinate system with (0, 0)
+ // in the bottom left corner, we swap the X and Y axis.
+ // That's why the following assignments look twisted.
+ const qreal rectHalfWidth = rect.height() / 2.0;
+ const qreal rectHalfHeight = rect.width() / 2.0;
+ const qreal rectMidX = rect.y() + rectHalfWidth;
+ const qreal rectMidY = rect.x() + rectHalfHeight;
+ const qreal dX = rectMidX - point.y();
+ const qreal dY = rectMidY - point.x();
+ switch (region) {
+ case Uml::Region::West:
+ region = Uml::Region::South;
+ break;
+ case Uml::Region::North:
+ region = Uml::Region::West;
+ break;
+ case Uml::Region::East:
+ region = Uml::Region::North;
+ break;
+ case Uml::Region::South:
+ region = Uml::Region::East;
+ break;
+ default:
+ break;
+ }
+ // Now we have regular coordinates with the point (0, 0) in the
+ // bottom left corner.
+ if (region == Uml::Region::North || region == Uml::Region::South) {
+ if (dX == 0)
+ return rectMidY;
+ // should be rectMidX, but we go back to Qt coord.sys.
+ if (dY == 0) {
+ uError() << "usage error: " << "North/South (dY == 0)";
+ return -1.0;
+ }
+ const qreal m = dY / dX;
+ qreal relativeX;
+ if (region == Uml::Region::North)
+ relativeX = rectHalfHeight / m;
+ else
+ relativeX = -rectHalfHeight / m;
+ return (rectMidY + relativeX);
+ // should be rectMidX, but we go back to Qt coord.sys.
+ } else {
+ if (dY == 0)
+ return rectMidX;
+ // should be rectMidY, but we go back to Qt coord.sys.
+ if (dX == 0) {
+ uError() << "usage error: " << "East/West (dX == 0)";
+ return -1.0;
+ }
+ const qreal m = dY / dX;
+ qreal relativeY = m * rectHalfWidth;
+ if (region == Uml::Region::West)
+ relativeY = -relativeY;
+ return (rectMidX + relativeY);
+ // should be rectMidY, but we go back to Qt coord.sys.
+ }
+}
+
+/**
+ * Auxiliary method for updateAssociations():
+ * Put position into m_positions and assoc into m_ordered at the
+ * correct index.
+ * m_positions and m_ordered move in parallel and are sorted by
+ * ascending position.
+ */
+void AssociationWidget::insertIntoLists(qreal position, const AssociationWidget* assoc)
+{
+ bool did_insertion = false;
+ for (int index = 0; index < m_positions_len; ++index) {
+ if (position < m_positions[index]) {
+ for (int moveback = m_positions_len; moveback > index; moveback--)
+ m_positions[moveback] = m_positions[moveback - 1];
+ m_positions[index] = position;
+ m_ordered.insert(index, const_cast<AssociationWidget*>(assoc));
+ did_insertion = true;
+ break;
+ }
+ }
+ if (! did_insertion) {
+ m_positions[m_positions_len] = position;
+ m_ordered.append(const_cast<AssociationWidget*>(assoc));
+ }
+ m_positions_len++;
+}
+
+/**
+ * Tells all the other view associations the new count for the
+ * given widget on a certain region. And also what index they should be.
+ */
+void AssociationWidget::updateAssociations(int totalCount,
+ Uml::Region::Enum region,
+ Uml::RoleType::Enum role)
+{
+ if ((region == Uml::Region::Error) | (umlScene() == NULL)) {
+ return;
+ }
+ AssociationWidgetList list = m_scene->associationList();
+
+ UMLWidget *ownWidget = m_role[role].umlWidget;
+ m_positions_len = 0;
+ m_ordered.clear();
+ // we order the AssociationWidget list by region and x/y value
+ foreach (AssociationWidget* assocwidget, list) {
+ WidgetRole *roleA = &assocwidget->m_role[RoleType::A];
+ WidgetRole *roleB = &assocwidget->m_role[RoleType::B];
+ UMLWidget *wA = roleA->umlWidget;
+ UMLWidget *wB = roleB->umlWidget;
+ // Skip self associations.
+ if (wA == wB)
+ continue;
+ // Now we must find out with which end the assocwidget connects
+ // to the input widget (ownWidget).
+ bool inWidgetARegion = (ownWidget == wA &&
+ region == roleA->m_WidgetRegion);
+ bool inWidgetBRegion = (ownWidget == wB &&
+ region == roleB->m_WidgetRegion);
+ if (!inWidgetARegion && !inWidgetBRegion)
+ continue;
+ // Determine intercept position on the edge indicated by `region'.
+ UMLWidget * otherWidget = (inWidgetARegion ? wB : wA);
+ AssociationLine *linepath = assocwidget->associationLine();
+ QPointF refpoint;
+ if (assocwidget->linePathStartsAt(otherWidget))
+ refpoint = linepath->point(linepath->count() - 2);
+ else
+ refpoint = linepath->point(1);
+ // The point is authoritative if we're called for the second time
+ // (i.e. role==B) or it is a waypoint on the line path.
+ bool pointIsAuthoritative = (role == RoleType::B || linepath->count() > 2);
+ if (! pointIsAuthoritative) {
+ // If the point is not authoritative then we use the other
+ // widget's center.
+ refpoint.setX(otherWidget->x() + otherWidget->width() / 2);
+ refpoint.setY(otherWidget->y() + otherWidget->height() / 2);
+ }
+ qreal intercept = findInterceptOnEdge(ownWidget->rect(), region, refpoint);
+ if (intercept < 0) {
+ DEBUG(DBG_SRC) << "error from findInterceptOnEdge for"
+ << " assocType=" << assocwidget->associationType()
+ << " ownWidget=" << ownWidget->name()
+ << " otherWidget=" << otherWidget->name();
+ continue;
+ }
+ insertIntoLists(intercept, assocwidget);
+ } // while ((assocwidget = assoc_it.current()))
+
+ // we now have an ordered list and we only have to call updateRegionLineCount
+ int index = 1;
+ foreach (AssociationWidget* assocwidget, m_ordered ) {
+ if (ownWidget == assocwidget->widgetForRole(RoleType::A)) {
+ assocwidget->updateRegionLineCount(index++, totalCount, region, RoleType::A);
+ } else if (ownWidget == assocwidget->widgetForRole(RoleType::B)) {
+ assocwidget->updateRegionLineCount(index++, totalCount, region, RoleType::B);
+ }
+ } // for (assocwidget = ordered.first(); ...)
+}
+
+/**
+ * Called to tell the association that another association has added
+ * a line to the region of one of its widgets. The widget is identified
+ * by its role (A or B).
+ *
+ * Called by @ref updateAssociations which is called by
+ * @ref calculateEndingPoints when required.
+ */
+void AssociationWidget::updateRegionLineCount(int index, int totalCount,
+ Uml::Region::Enum region,
+ Uml::RoleType::Enum role)
+{
+ if ((region == Uml::Region::Error) | (umlScene() == NULL)) {
+ return;
+ }
+ // If the association is to self and the line ends are on the same region then
+ // use a different calculation.
+ if (isSelf() &&
+ m_role[RoleType::A].m_WidgetRegion == m_role[RoleType::B].m_WidgetRegion) {
+ UMLWidget * pWidget = m_role[RoleType::A].umlWidget;
+ qreal x = pWidget->x();
+ qreal y = pWidget->y();
+ qreal wh = pWidget->height();
+ qreal ww = pWidget->width();
+ int size = m_associationLine->count();
+ // See if above widget ok to place assoc.
+ switch( m_role[RoleType::A].m_WidgetRegion ) {
+ case Uml::Region::North:
+ m_associationLine->setPoint( 0, QPointF( x + ( ww / 4 ), y ) );
+ m_associationLine->setPoint( size - 1, QPointF(x + ( ww * 3 / 4 ), y ) );
+ break;
+
+ case Uml::Region::South:
+ m_associationLine->setPoint( 0, QPointF( x + ( ww / 4 ), y + wh ) );
+ m_associationLine->setPoint( size - 1, QPointF( x + ( ww * 3 / 4 ), y + wh ) );
+ break;
+
+ case Uml::Region::East:
+ m_associationLine->setPoint( 0, QPointF( x + ww, y + ( wh / 4 ) ) );
+ m_associationLine->setPoint( size - 1, QPointF( x + ww, y + ( wh * 3 / 4 ) ) );
+ break;
+
+ case Uml::Region::West:
+ m_associationLine->setPoint( 0, QPointF( x, y + ( wh / 4 ) ) );
+ m_associationLine->setPoint( size - 1, QPointF( x, y + ( wh * 3 / 4 ) ) );
+ break;
+ default:
+ break;
+ }//end switch
+
+ return;
+ }
+
+ WidgetRole& robj = m_role[role];
+ UMLWidget * pWidget = robj.umlWidget;
+
+ robj.m_nIndex = index;
+ robj.m_nTotalCount = totalCount;
+ qreal x = pWidget->x();
+ qreal y = pWidget->y();
+ qreal ww = pWidget->width();
+ qreal wh = pWidget->height();
+ const bool angular = Settings::optionState().generalState.angularlines;
+ qreal ch = 0;
+ qreal cw = 0;
+ if (angular) {
+ uint nind = (role == RoleType::A ? 1 : m_associationLine->count() - 2);
+ QPointF neighbour = m_associationLine->point(nind);
+ if (neighbour.x() < x)
+ cw = 0;
+ else if (neighbour.x() > x + ww)
+ cw = 0 + ww;
+ else
+ cw = neighbour.x() - x;
+ if (neighbour.y() < y)
+ ch = 0;
+ else if (neighbour.y() > y + wh)
+ ch = 0 + wh;
+ else
+ ch = neighbour.y() - y;
+ } else {
+ ch = wh * index / totalCount;
+ cw = ww * index / totalCount;
+ }
+
+ qreal newX = x + cw;
+ qreal newY = y + ch;
+
+ QPointF pt;
+ if (angular) {
+ pt = QPointF(newX, newY);
+ } else {
+ UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
+ UMLWidget *pWidgetB = m_role[RoleType::B].umlWidget;
+ QList<QPolygonF> polyListA = pWidgetA->shape().toSubpathPolygons();
+ QPolygonF polyA = polyListA.at(0);
+ if (polyListA.size() > 1) {
+ for (int i = 1; i < polyListA.size(); i++) {
+ polyA = polyA.united(polyListA.at(i));
+ }
+ }
+ polyA = polyA.translated(pWidgetA->pos());
+ QList<QPolygonF> polyListB = pWidgetB->shape().toSubpathPolygons();
+ QPolygonF polyB = polyListB.at(0);
+ if (polyListB.size() > 1) {
+ for (int i = 1; i < polyListB.size(); i++) {
+ polyB = polyB.united(polyListB.at(i));
+ }
+ }
+ polyB = polyB.translated(pWidgetB->pos());
+ QLineF nearestPoints = Widget_Utils::closestPoints(polyA, polyB);
+ if (nearestPoints.isNull()) {
+ uError() << "Widget_Utils::closestPoints failed, falling back to simple widget positions";
+ switch(region) {
+ case Uml::Region::West:
+ pt.setX(x);
+ pt.setY(newY);
+ break;
+ case Uml::Region::North:
+ pt.setX(newX);
+ pt.setY(y);
+ break;
+ case Uml::Region::East:
+ pt.setX(x + ww);
+ pt.setY(newY);
+ break;
+ case Uml::Region::South:
+ pt.setX(newX);
+ pt.setY(y + wh);
+ break;
+ case Uml::Region::Center:
+ pt.setX(x + ww / 2);
+ pt.setY(y + wh / 2);
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (role == RoleType::A)
+ pt = nearestPoints.p1();
+ else
+ pt = nearestPoints.p2();
+ }
+ }
+ if (role == RoleType::A) {
+ m_associationLine->setPoint(0, pt);
+ }
+ else {
+ m_associationLine->setPoint(m_associationLine->count() - 1, pt);
+ }
+}
+
+/**
+ * Sets the state of whether the widget is selected.
+ *
+ * @param _select The state of whether the widget is selected.
+ */
+void AssociationWidget::setSelected(bool _select /* = true */)
+{
+ WidgetBase::setSelected(_select);
+ if ( m_nameWidget)
+ m_nameWidget->setSelected( _select );
+ if ( m_role[RoleType::A].roleWidget )
+ m_role[RoleType::A].roleWidget->setSelected( _select );
+ if ( m_role[RoleType::B].roleWidget )
+ m_role[RoleType::B].roleWidget->setSelected( _select );
+ if ( m_role[RoleType::A].multiplicityWidget )
+ m_role[RoleType::A].multiplicityWidget->setSelected( _select );
+ if ( m_role[RoleType::B].multiplicityWidget )
+ m_role[RoleType::B].multiplicityWidget->setSelected( _select );
+ if ( m_role[RoleType::A].changeabilityWidget)
+ m_role[RoleType::A].changeabilityWidget->setSelected( _select );
+ if ( m_role[RoleType::B].changeabilityWidget)
+ m_role[RoleType::B].changeabilityWidget->setSelected( _select );
+
+ // Update the docwindow for this association.
+ // This is done last because each of the above setSelected calls
+ // overwrites the docwindow, but we want the main association doc
+ // to win.
+ if (_select) {
+ if (m_scene->selectedCount() == 0)
+ UMLApp::app()->docWindow()->showDocumentation(this, false);
+ } else
+ UMLApp::app()->docWindow()->updateDocumentation(true);
+
+ m_associationLine->setSelected(_select);
+ if (! _select) {
+ // For now, if _select is true we don't make the assoc class line
+ // selected. But that's certainly open for discussion.
+ // At any rate, we need to deselect the assoc class line
+ // if _select is false.
+ selectAssocClassLine(false);
+ }
+ UMLApp::app()->document()->writeToStatusBar(_select ? i18n("Press Ctrl with left mouse click to delete a point") : QString());
+}
+
+/**
+ * Reimplement method from WidgetBase in order to check owned floating texts.
+ *
+ * @param p Point to be checked.
+ *
+ * @return m_nameWidget if m_nameWidget is non NULL and m_nameWidget->onWidget(p) returns non NULL;
+ * m_role[0].(multiplicity|changeability|role)Widget if the resp. widget is non NULL and
+ * its onWidget(p) returns non NULL;
+ * m_role[1].(multiplicity|changeability|role)Widget if the resp. widget is non NULL and
+ * its onWidget(p) returns non NULL;
+ * else NULL.
+ */
+UMLWidget* AssociationWidget::onWidget(const QPointF &p)
+{
+ if (m_nameWidget && m_nameWidget->onWidget(p)) {
+ return m_nameWidget;
+ }
+ for (int i = 0; i <= 1; i++) {
+ const WidgetRole& r = m_role[i];
+ if (r.multiplicityWidget && r.multiplicityWidget->onWidget(p))
+ return r.multiplicityWidget;
+ if (r.changeabilityWidget && r.changeabilityWidget->onWidget(p))
+ return r.changeabilityWidget;
+ if (r.roleWidget && r.roleWidget->onWidget(p))
+ return r.roleWidget;
+ }
+ return NULL;
+}
+
+/**
+ * Returns true if the given point is on the connecting line to
+ * the association class. Returns false if there is no association
+ * class attached, or if the given point is not on the connecting
+ * line.
+ */
+bool AssociationWidget::onAssocClassLine(const QPointF &point)
+{
+ bool onLine = false;
+ if (m_pAssocClassLine) {
+//:TODO:
+// const QPointF mapped = m_pAssocClassLine->mapFromParent(point);
+// bool onLine = m_pAssocClassLine->contains(mapped);
+// return onLine;
+ UMLSceneItemList list = m_scene->collisions(point);
+ UMLSceneItemList::iterator end(list.end());
+ for (UMLSceneItemList::iterator item_it(list.begin()); item_it != end; ++item_it) {
+ if (*item_it == m_pAssocClassLine) {
+ onLine = true;
+ break;
+ }
+ }
+ }
+ DEBUG(DBG_SRC) << onLine;
+ return onLine;
+}
+
+/**
+ * Returns true if the given point is on the association line.
+ * A circle (rectangle) around the point is used to obtain more tolerance.
+ * @param point the point to check
+ * @return flag whether point is on association line
+ */
+bool AssociationWidget::onAssociation(const QPointF& point)
+{
+ // check the path
+ const qreal diameter(4.0);
+ QPainterPath path = m_associationLine->shape();
+ if (path.contains(point)) {
+ DEBUG(DBG_SRC) << "on path";
+ return true;
+ }
+ // check also the points
+ if (m_associationLine->layout() == AssociationLine::Spline) {
+ if (m_associationLine->closestPointIndex(point, diameter) > -1) {
+ DEBUG(DBG_SRC) << "on spline point";
+ return true;
+ }
+ }
+ return onAssocClassLine(point);
+}
+
+/**
+ * Set all association points to x coordinate.
+ */
+void AssociationWidget::setXEntireAssoc(qreal x)
+{
+ for (int i = 0; i < m_associationLine->count(); ++i) {
+ QPointF p = m_associationLine->point(i);
+ p.setX(x);
+ m_associationLine->setPoint(i, p);
+ }
+}
+
+/**
+ * Set all association points to y coordinate.
+ */
+void AssociationWidget::setYEntireAssoc(qreal y)
+{
+ for (int i = 0; i < m_associationLine->count(); ++i) {
+ QPointF p = m_associationLine->point(i);
+ p.setY(y);
+ m_associationLine->setPoint(i, p);
+ }
+}
+
+/**
+ * Moves all the mid points (all expcept start /end) by the given amount.
+ */
+void AssociationWidget::moveMidPointsBy(qreal x, qreal y)
+{
+ int pos = m_associationLine->count() - 1;
+ for (int i = 1; i < (int)pos; ++i) {
+ QPointF p = m_associationLine->point( i );
+ qreal newX = p.x() + x;
+ qreal newY = p.y() + y;
+ p.setX( newX );
+ p.setY( newY );
+ m_associationLine->setPoint( i, p );
+ }
+}
+
+/**
+ * Moves the entire association by the given offset.
+ */
+void AssociationWidget::moveEntireAssoc(qreal x, qreal y)
+{
+ //TODO: ADD SUPPORT FOR ASSOC. ON SEQ. DIAGRAMS WHEN NOTES BACK IN.
+ moveMidPointsBy(x, y);
+ calculateEndingPoints();
+ calculateNameTextSegment();
+ resetTextPositions();
+}
+
+/**
+ * Returns the bounding rectangle of all segments of the association.
+ */
+QRectF AssociationWidget::boundingRect() const
+{
+ return m_associationLine->boundingRect();
+}
+
+/**
+ * Returns the shape of all segments of the association.
+ */
+QPainterPath AssociationWidget::shape() const
+{
+ return m_associationLine->shape();
+}
+
+/**
+ * Connected to UMLClassifier::attributeRemoved() or UMLEntity::constraintRemoved()
+ * in case this AssociationWidget is linked to a clasifier list item
+ * (an attribute or a foreign key constraint)
+ *
+ * @param obj The UMLClassifierListItem removed.
+ */
+void AssociationWidget::slotClassifierListItemRemoved(UMLClassifierListItem* obj)
+{
+ if (obj != m_umlObject) {
+ DEBUG(DBG_SRC) << "obj=" << obj << ": m_umlObject=" << m_umlObject;
+ return;
+ }
+ m_umlObject = 0;
+ m_scene->removeAssoc(this);
+}
+
+/**
+ * Connected to UMLObject::modified() in case this
+ * AssociationWidget is linked to a classifer's attribute type.
+ */
+void AssociationWidget::slotAttributeChanged()
+{
+ UMLAttribute *attr = attribute();
+ if (attr == NULL) {
+ uError() << "attribute() returns NULL";
+ return;
+ }
+ setVisibility(attr->visibility(), RoleType::B);
+ setRoleName(attr->name(), RoleType::B);
+}
+
+void AssociationWidget::clipSize()
+{
+ if (m_nameWidget)
+ m_nameWidget->clipSize();
+
+ if (m_role[RoleType::A].multiplicityWidget)
+ m_role[RoleType::A].multiplicityWidget->clipSize();
+
+ if (m_role[RoleType::B].multiplicityWidget)
+ m_role[RoleType::B].multiplicityWidget->clipSize();
+
+ if (m_role[RoleType::A].roleWidget)
+ m_role[RoleType::A].roleWidget->clipSize();
+
+ if (m_role[RoleType::B].roleWidget)
+ m_role[RoleType::B].roleWidget->clipSize();
+
+ if (m_role[RoleType::A].changeabilityWidget)
+ m_role[RoleType::A].changeabilityWidget->clipSize();
+
+ if (m_role[RoleType::B].changeabilityWidget)
+ m_role[RoleType::B].changeabilityWidget->clipSize();
+
+ if (m_associationClass)
+ m_associationClass->clipSize();
+}
+
+/**
+ * Event handler for context menu events, called from the line segments.
+ */
+void AssociationWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+{
+ const Uml::AssociationType::Enum type = associationType();
+ ListPopupMenu::MenuType menuType = ListPopupMenu::mt_Association_Selected;
+ if ((type == Uml::AssociationType::Anchor) ||
+ onAssocClassLine(event->scenePos())) {
+ menuType = ListPopupMenu::mt_Anchor;
+ } else if (isCollaboration()) {
+ menuType = ListPopupMenu::mt_Collaboration_Message;
+ } else if (!association()) {
+ menuType = ListPopupMenu::mt_AttributeAssociation;
+ } else if (AssocRules::allowRole(type)) {
+ menuType = ListPopupMenu::mt_FullAssociation;
+ }
+
+ event->accept();
+ DEBUG(DBG_SRC) << "menue type = " << ListPopupMenu::toString(menuType)
+ << " / association = " << Uml::AssociationType::toString(type);
+
+ UMLScene *scene = umlScene();
+ QWidget *parent = 0;
+ if (scene) {
+ parent = scene->activeView();
+ }
+
+ if (!isSelected() && scene && !scene->selectedItems().isEmpty()) {
+ Qt::KeyboardModifiers forSelection = (Qt::ControlModifier | Qt::ShiftModifier);
+ if ((event->modifiers() & forSelection) == 0) {
+ scene->clearSelection();
+ }
+ }
+ setSelected(true);
+ m_eventScenePos = event->scenePos();
+ ListPopupMenu popup(parent, menuType, this);
+ QAction *triggered = popup.exec(event->screenPos());
+ ListPopupMenu *parentMenu = ListPopupMenu::menuFromAction(triggered);
+
+ if (!parentMenu) {
+ uWarning() << "Action's data field does not contain ListPopupMenu pointer";
+ return;
+ }
+
+ WidgetBase *ownerWidget = parentMenu->ownerWidget();
+ // assert because logic is based on only WidgetBase being the owner of
+ // ListPopupMenu actions executed in this context menu.
+ Q_ASSERT_X(ownerWidget != 0, "AssociationWidget::contextMenuEvent",
+ "ownerWidget is null which means action belonging to UMLView, UMLScene"
+ " or UMLObject is the one triggered in ListPopupMenu");
+
+ ownerWidget->slotMenuSelection(triggered);
+}
+
+/**
+ * Reimplemented event handler for hover enter events.
+ */
+void AssociationWidget::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ associationLine()->hoverEnterEvent(event);
+}
+
+/**
+ * Reimplemented event handler for hover leave events.
+ */
+void AssociationWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ associationLine()->hoverLeaveEvent(event);
+}
+
+/**
+ * Reimplemented event handler for hover move events.
+ */
+void AssociationWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+{
+ associationLine()->hoverMoveEvent(event);
+}
+
+/**
+ * Saves this widget to the "assocwidget" XMI element.
+ */
+void AssociationWidget::saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
+{
+ QDomElement assocElement = qDoc.createElement(QLatin1String("assocwidget"));
+
+ WidgetBase::saveToXMI(qDoc, assocElement);
+ LinkWidget::saveToXMI(qDoc, assocElement);
+ if (m_umlObject) {
+ assocElement.setAttribute(QLatin1String("xmi.id"), Uml::ID::toString(m_umlObject->id()));
+ }
+ assocElement.setAttribute(QLatin1String("type"), associationType());
+ if (!association()) {
+ assocElement.setAttribute(QLatin1String("visibilityA"), visibility(RoleType::A));
+ assocElement.setAttribute(QLatin1String("visibilityB"), visibility(RoleType::B));
+ assocElement.setAttribute(QLatin1String("changeabilityA"), changeability(RoleType::A));
+ assocElement.setAttribute(QLatin1String("changeabilityB"), changeability(RoleType::B));
+ if (m_umlObject == NULL) {
+ assocElement.setAttribute(QLatin1String("roleAdoc"), roleDocumentation(RoleType::A));
+ assocElement.setAttribute(QLatin1String("roleBdoc"), roleDocumentation(RoleType::B));
+ assocElement.setAttribute(QLatin1String("documentation"), documentation());
+ }
+ }
+ assocElement.setAttribute(QLatin1String("widgetaid"), Uml::ID::toString(widgetIDForRole(RoleType::A)));
+ assocElement.setAttribute(QLatin1String("widgetbid"), Uml::ID::toString(widgetIDForRole(RoleType::B)));
+ assocElement.setAttribute(QLatin1String("indexa"), m_role[RoleType::A].m_nIndex);
+ assocElement.setAttribute(QLatin1String("indexb"), m_role[RoleType::B].m_nIndex);
+ assocElement.setAttribute(QLatin1String("totalcounta"), m_role[RoleType::A].m_nTotalCount);
+ assocElement.setAttribute(QLatin1String("totalcountb"), m_role[RoleType::B].m_nTotalCount);
+ m_associationLine->saveToXMI(qDoc, assocElement);
+
+ if (m_nameWidget) {
+ m_nameWidget->saveToXMI(qDoc, assocElement);
+ }
+
+ if (multiplicityWidget(RoleType::A)) {
+ multiplicityWidget(RoleType::A)->saveToXMI(qDoc, assocElement);
+ }
+
+ if (multiplicityWidget(RoleType::B)) {
+ multiplicityWidget(RoleType::B)->saveToXMI(qDoc, assocElement);
+ }
+
+ if (roleWidget(RoleType::A)) {
+ roleWidget(RoleType::A)->saveToXMI(qDoc, assocElement);
+ }
+
+ if (roleWidget(RoleType::B)) {
+ roleWidget(RoleType::B)->saveToXMI(qDoc, assocElement);
+ }
+
+ if (changeabilityWidget(RoleType::A)) {
+ changeabilityWidget(RoleType::A)->saveToXMI(qDoc, assocElement);
+ }
+
+ if (changeabilityWidget(RoleType::B)) {
+ changeabilityWidget(RoleType::B)->saveToXMI(qDoc, assocElement);
+ }
+
+ if (m_associationClass) {
+ QString acid = Uml::ID::toString(m_associationClass->id());
+ assocElement.setAttribute(QLatin1String("assocclass"), acid);
+ assocElement.setAttribute(QLatin1String("aclsegindex"), m_nLinePathSegmentIndex);
+ }
+
+ qElement.appendChild(assocElement);
+}
+
+/**
+ * Uses the supplied widgetList for resolving
+ * the role A and role B widgets. (The other loadFromXMI() queries
+ * the UMLView for these widgets.)
+ * Required for clipboard operations.
+ */
+bool AssociationWidget::loadFromXMI(QDomElement& qElement,
+ const UMLWidgetList& widgets,
+ const MessageWidgetList* messages)
+{
+ if (!WidgetBase::loadFromXMI(qElement)) {
+ return false;
+ }
+
+ if (!LinkWidget::loadFromXMI(qElement)) {
+ return false;
+ }
+
+ // load child widgets first
+ QString widgetaid = qElement.attribute(QLatin1String("widgetaid"), QLatin1String("-1"));
+ QString widgetbid = qElement.attribute(QLatin1String("widgetbid"), QLatin1String("-1"));
+ Uml::ID::Type aId = Uml::ID::fromString(widgetaid);
+ Uml::ID::Type bId = Uml::ID::fromString(widgetbid);
+ UMLWidget *pWidgetA = Widget_Utils::findWidget(aId, widgets, messages);
+ if (!pWidgetA) {
+ uError() << "cannot find widget for roleA id " << Uml::ID::toString(aId);
+ return false;
+ }
+ UMLWidget *pWidgetB = Widget_Utils::findWidget(bId, widgets, messages);
+ if (!pWidgetB) {
+ uError() << "cannot find widget for roleB id " << Uml::ID::toString(bId);
+ return false;
+ }
+ setWidgetForRole(pWidgetA, RoleType::A);
+ setWidgetForRole(pWidgetB, RoleType::B);
+
+ QString type = qElement.attribute(QLatin1String("type"), QLatin1String("-1"));
+ Uml::AssociationType::Enum aType = Uml::AssociationType::fromInt(type.toInt());
+
+ QString id = qElement.attribute(QLatin1String("xmi.id"), QLatin1String("-1"));
+ bool oldStyleLoad = false;
+ if (id == QLatin1String("-1")) {
+ // xmi.id not present, ergo either a pure widget association,
+ // or old (pre-1.2) style:
+ // Everything is loaded from the AssociationWidget.
+ // UMLAssociation may or may not be saved - if it is, it's a dummy.
+ // Create the UMLAssociation if both roles are UML objects;
+ // else load the info locally.
+
+ if (Uml::AssociationType::hasUMLRepresentation(aType)) {
+ // lack of an association in our widget AND presence of
+ // both uml objects for each role clearly identifies this
+ // as reading in an old-school file. Note it as such, and
+ // create, and add, the UMLAssociation for this widget.
+ // Remove this special code when backwards compatibility
+ // with older files isn't important anymore. -b.t.
+ UMLObject* umlRoleA = pWidgetA->umlObject();
+ UMLObject* umlRoleB = pWidgetB->umlObject();
+ if (!m_umlObject && umlRoleA && umlRoleB) {
+ oldStyleLoad = true; // flag for further special config below
+ if (aType == AssociationType::Aggregation || aType == AssociationType::Composition) {
+ uWarning()<<" Old Style save file? swapping roles on association widget"<<this;
+ // We have to swap the A and B widgets to compensate
+ // for the long standing bug in AssociationLine of drawing
+ // the diamond at the wrong end which was fixed
+ // just before the 1.2 release.
+ // The logic here is that the user has understood
+ // that the diamond belongs at the SOURCE end of the
+ // the association (i.e. at the container, not at the
+ // contained), and has compensated for this anomaly
+ // by drawing the aggregations/compositions from
+ // target to source.
+ UMLWidget *tmpWidget = pWidgetA;
+ pWidgetA = pWidgetB;
+ pWidgetB = tmpWidget;
+ setWidgetForRole(pWidgetA, RoleType::A);
+ setWidgetForRole(pWidgetB, RoleType::B);
+ umlRoleA = pWidgetA->umlObject();
+ umlRoleB = pWidgetB->umlObject();
+ }
+
+ setUMLAssociation(umlDoc()->createUMLAssociation(umlRoleA, umlRoleB, aType));
+ }
+ }
+
+ setDocumentation(qElement.attribute(QLatin1String("documentation")));
+ setRoleDocumentation(qElement.attribute(QLatin1String("roleAdoc")), RoleType::A);
+ setRoleDocumentation(qElement.attribute(QLatin1String("roleBdoc")), RoleType::B);
+
+ // visibility defaults to Public if it cant set it here..
+ QString visibilityA = qElement.attribute(QLatin1String("visibilityA"), QLatin1String("0"));
+ int vis = visibilityA.toInt();
+ if (vis >= 200) { // bkwd compat.
+ vis -= 200;
+ }
+ setVisibility((Uml::Visibility::Enum)vis, RoleType::A);
+
+ QString visibilityB = qElement.attribute(QLatin1String("visibilityB"), QLatin1String("0"));
+ vis = visibilityB.toInt();
+ if (vis >= 200) { // bkwd compat.
+ vis -= 200;
+ }
+ setVisibility((Uml::Visibility::Enum)vis, RoleType::B);
+
+ // Changeability defaults to "Changeable" if it cant set it here..
+ QString changeabilityA = qElement.attribute(QLatin1String("changeabilityA"), QLatin1String("0"));
+ if (changeabilityA.toInt() > 0)
+ setChangeability(Uml::Changeability::fromInt(changeabilityA.toInt()), RoleType::A);
+
+ QString changeabilityB = qElement.attribute(QLatin1String("changeabilityB"), QLatin1String("0"));
+ if (changeabilityB.toInt() > 0)
+ setChangeability(Uml::Changeability::fromInt(changeabilityB.toInt()), RoleType::B);
+
+ } else {
+
+ // we should disconnect any prior association (can this happen??)
+ if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
+ UMLAssociation *umla = association();
+ umla->disconnect(this);
+ umla->nrof_parent_widgets--;
+ }
+
+ // New style: The xmi.id is a reference to the UMLAssociation.
+ // If the UMLObject is not found right now, we try again later
+ // during the type resolution pass - see activate().
+ m_nId = Uml::ID::fromString(id);
+ UMLObject *myObj = umlDoc()->findObjectById(m_nId);
+ if (myObj) {
+ const UMLObject::ObjectType ot = myObj->baseType();
+ if (ot != UMLObject::ot_Association) {
+ setUMLObject(myObj);
+ } else {
+ UMLAssociation * myAssoc = static_cast<UMLAssociation*>(myObj);
+ setUMLAssociation(myAssoc);
+ if (type == QLatin1String("-1"))
+ aType = myAssoc->getAssocType();
+ }
+ }
+ }
+
+ setAssociationType(aType);
+
+ QString indexa = qElement.attribute(QLatin1String("indexa"), QLatin1String("0"));
+ QString indexb = qElement.attribute(QLatin1String("indexb"), QLatin1String("0"));
+ QString totalcounta = qElement.attribute(QLatin1String("totalcounta"), QLatin1String("0"));
+ QString totalcountb = qElement.attribute(QLatin1String("totalcountb"), QLatin1String("0"));
+ m_role[RoleType::A].m_nIndex = indexa.toInt();
+ m_role[RoleType::B].m_nIndex = indexb.toInt();
+ m_role[RoleType::A].m_nTotalCount = totalcounta.toInt();
+ m_role[RoleType::B].m_nTotalCount = totalcountb.toInt();
+
+ QString assocclassid = qElement.attribute(QLatin1String("assocclass"));
+ if (! assocclassid.isEmpty()) {
+ Uml::ID::Type acid = Uml::ID::fromString(assocclassid);
+ UMLWidget *w = Widget_Utils::findWidget(acid, widgets);
+ if (w) {
+ ClassifierWidget* aclWidget = static_cast<ClassifierWidget*>(w);
+ QString aclSegIndex = qElement.attribute(QLatin1String("aclsegindex"), QLatin1String("0"));
+ createAssocClassLine(aclWidget, aclSegIndex.toInt());
+ } else {
+ uError() << "cannot find assocclass " << assocclassid;
+ }
+ }
+
+ //now load child elements
+ QDomNode node = qElement.firstChild();
+ QDomElement element = node.toElement();
+ while (!element.isNull()) {
+ QString tag = element.tagName();
+ if (tag == QLatin1String("linepath")) {
+ if (!m_associationLine->loadFromXMI(element)) {
+ return false;
+ }
+ } else if (tag == QLatin1String("floatingtext") ||
+ tag == QLatin1String("UML:FloatingTextWidget")) { // for bkwd compatibility
+ QString r = element.attribute(QLatin1String("role"), QLatin1String("-1"));
+ if (r == QLatin1String("-1"))
+ return false;
+ Uml::TextRole::Enum role = Uml::TextRole::fromInt(r.toInt());
+ FloatingTextWidget *ft = new FloatingTextWidget(m_scene, role, QString(), Uml::ID::Reserved);
+ if (! ft->loadFromXMI(element)) {
+ // Most likely cause: The FloatingTextWidget is empty.
+ delete ft;
+ node = element.nextSibling();
+ element = node.toElement();
+ continue;
+ }
+ // always need this
+ ft->setParentItem(this);
+ ft->setLink(this);
+ ft->setSequenceNumber(m_SequenceNumber);
+ ft->setFontCmd(ft->font());
+
+ switch(role) {
+ case Uml::TextRole::MultiA:
+ m_role[RoleType::A].multiplicityWidget = ft;
+ if (oldStyleLoad)
+ setMultiplicity(m_role[RoleType::A].multiplicityWidget->text(), RoleType::A);
+ break;
+
+ case Uml::TextRole::MultiB:
+ m_role[RoleType::B].multiplicityWidget = ft;
+ if (oldStyleLoad)
+ setMultiplicity(m_role[RoleType::B].multiplicityWidget->text(), RoleType::B);
+ break;
+
+ case Uml::TextRole::ChangeA:
+ m_role[RoleType::A].changeabilityWidget = ft;
+ break;
+
+ case Uml::TextRole::ChangeB:
+ m_role[RoleType::B].changeabilityWidget = ft;
+ break;
+
+ case Uml::TextRole::Name:
+ m_nameWidget = ft;
+ if (oldStyleLoad)
+ setName(m_nameWidget->text());
+ break;
+
+ case Uml::TextRole::Coll_Message:
+ case Uml::TextRole::Coll_Message_Self:
+ m_nameWidget = ft;
+ ft->setLink(this);
+ ft->setActivated();
+ if (FloatingTextWidget::isTextValid(ft->text()))
+ ft->show();
+ else
+ ft->hide();
+ break;
+
+ case Uml::TextRole::RoleAName:
+ m_role[RoleType::A].roleWidget = ft;
+ setRoleName(ft->text(), RoleType::A);
+ break;
+ case Uml::TextRole::RoleBName:
+ m_role[RoleType::B].roleWidget = ft;
+ setRoleName(ft->text(), RoleType::B);
+ break;
+ default:
+ DEBUG(DBG_SRC) << "unexpected FloatingTextWidget (TextRole::Enum " << role << ")";
+ delete ft;
+ break;
+ }
+ }
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+
+ return true;
+}
+
+/**
+ * Queries the UMLView for resolving the role A and role B widgets.
+ * ....
+ */
+bool AssociationWidget::loadFromXMI(QDomElement& qElement)
+{
+ UMLScene *scene = umlScene();
+ if (scene) {
+ const UMLWidgetList& widgetList = scene->widgetList();
+ const MessageWidgetList& messageList = scene->messageList();
+ return loadFromXMI(qElement, widgetList, &messageList);
+ }
+ else {
+ DEBUG(DBG_SRC) << "This isn't on UMLScene yet, so can neither fetch"
+ "messages nor widgets on umlscene";
+ return false;
+ }
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/associationwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/associationwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/associationwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/associationwidget.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,328 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ASSOCIATIONWIDGET_H
+#define ASSOCIATIONWIDGET_H
+
+#include "associationwidgetlist.h"
+#include "linkwidget.h"
+#include "messagewidgetlist.h"
+#include "umlwidgetlist.h"
+#include "widgetbase.h"
+
+class AssociationLine;
+class ClassifierWidget;
+class UMLScene;
+class UMLAssociation;
+class UMLAttribute;
+class UMLClassifierListItem;
+class UMLOperation;
+
+/**
+ * This class represents an association inside a diagram.
+ *
+ * Constructor is made non accessible:
+ * Users shall use the static create() methods for constructing AssociationWidgets.
+ *
+ * Associations exist not only between UML objects. For example, when a Note is
+ * attached to a UML object, the Note itself is not a UML object.
+ * This class supports both kinds of associations. An association where one or
+ * both roles are not a UML object is called a "pure widget association".
+ *
+ * An AssociationWidget where both roles are UML objects has a corresponding
+ * UMLAssociation. The UMLAssociation can be retrieved using the getAssociation
+ * method.
+ * A pure widget association does not have a corresponding UMLAssociation.
+ * The getAssociation method returns NULL in this case.
+ *
+ * @author Gustavo Madrigal
+ * @author Gopala Krishna
+ * @short This class represents an association inside a diagram.
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class AssociationWidget : public WidgetBase, public LinkWidget
+{
+ Q_OBJECT
+public:
+ static AssociationWidget* create(UMLScene *scene);
+ static AssociationWidget* create
+ (UMLScene *scene, UMLWidget* WidgetA,
+ Uml::AssociationType::Enum assocType, UMLWidget* WidgetB,
+ UMLObject *umlobject = NULL);
+
+ virtual ~AssociationWidget();
+
+ virtual void setUMLObject(UMLObject *obj);
+
+ //---------- LinkWidget Interface methods implementation from now on.
+
+ virtual void lwSetFont(QFont font);
+ virtual UMLClassifier *operationOwner();
+
+ virtual UMLOperation *operation();
+ virtual void setOperation(UMLOperation *op);
+
+ virtual QString customOpText();
+ virtual void setCustomOpText(const QString &opText);
+
+ virtual void resetTextPositions();
+
+ virtual void setMessageText(FloatingTextWidget *ft);
+ virtual void setText(FloatingTextWidget *ft, const QString &newText);
+
+ virtual void showPropertiesDialog();
+
+ virtual QString lwOperationText();
+ virtual UMLClassifier *lwClassifier();
+ virtual void setOperationText(const QString &op);
+
+ virtual void constrainTextPos(qreal &textX, qreal &textY,
+ qreal textWidth, qreal textHeight,
+ Uml::TextRole::Enum tr);
+
+ virtual void calculateNameTextSegment();
+
+ //---------- End LinkWidget Interface methods implementation.
+
+ UMLAssociation* association() const;
+ UMLAttribute* attribute() const;
+
+// AssociationWidget& operator=(const AssociationWidget& other);
+ bool operator==(const AssociationWidget& other) const;
+ bool operator!=(AssociationWidget& other) const;
+
+ FloatingTextWidget* textWidgetByRole(Uml::TextRole::Enum tr) const;
+
+ FloatingTextWidget* nameWidget() const;
+ QString name() const;
+ void setName(const QString &strRole);
+ void setStereotype(const QString &stereo);
+
+ FloatingTextWidget* roleWidget(Uml::RoleType::Enum role) const;
+ QString roleName(Uml::RoleType::Enum role) const;
+ void setRoleName(const QString &strRole, Uml::RoleType::Enum role);
+
+ QString roleDocumentation(Uml::RoleType::Enum role) const;
+ void setRoleDocumentation(const QString& doc, Uml::RoleType::Enum role);
+
+ FloatingTextWidget* multiplicityWidget(Uml::RoleType::Enum role) const;
+ QString multiplicity(Uml::RoleType::Enum role) const;
+ void setMultiplicity(const QString& text, Uml::RoleType::Enum role);
+
+ Uml::Visibility::Enum visibility(Uml::RoleType::Enum role) const;
+ void setVisibility(Uml::Visibility::Enum value, Uml::RoleType::Enum role);
+
+ FloatingTextWidget* changeabilityWidget(Uml::RoleType::Enum role) const;
+ Uml::Changeability::Enum changeability(Uml::RoleType::Enum role) const;
+ void setChangeability(Uml::Changeability::Enum value, Uml::RoleType::Enum role);
+
+ Uml::ID::Type widgetIDForRole(Uml::RoleType::Enum role) const;
+ Uml::ID::Type widgetLocalIDForRole(Uml::RoleType::Enum role) const;
+ UMLWidget* widgetForRole(Uml::RoleType::Enum role) const;
+ void setWidgetForRole(UMLWidget* widget, Uml::RoleType::Enum role);
+
+ bool setWidgets(UMLWidget* widgetA, Uml::AssociationType::Enum assocType, UMLWidget* widgetB);
+
+ bool containsAsEndpoint(UMLWidget* widget);
+
+ Uml::AssociationType::Enum associationType() const;
+ void setAssociationType(Uml::AssociationType::Enum type);
+
+ bool isCollaboration() const;
+ bool isSelf() const;
+
+ QString toString() const;
+
+ bool isActivated() const;
+ void setActivated(bool active);
+
+ AssociationLine* associationLine() const;
+
+ virtual bool activate();
+ virtual QRectF boundingRect() const;
+ virtual QPainterPath shape() const;
+
+ void widgetMoved(UMLWidget* widget, qreal x, qreal y);
+
+ void saveIdealTextPositions();
+
+ UMLWidget* onWidget(const QPointF &p);
+ bool onAssociation(const QPointF& point);
+ bool onAssocClassLine(const QPointF& point);
+
+ void createAssocClassLine();
+ void createAssocClassLine(ClassifierWidget* classifierWidget,
+ int linePathSegmentIndex);
+
+ void selectAssocClassLine(bool sel = true);
+ void removeAssocClassLine();
+ void computeAssocClassLine();
+
+ void setXEntireAssoc(qreal x);
+ void setYEntireAssoc(qreal y);
+
+ void moveMidPointsBy(qreal x, qreal y);
+ void moveEntireAssoc(qreal x, qreal y);
+
+ QFont font() const;
+
+ virtual void setTextColor(const QColor &color);
+
+ void calculateEndingPoints();
+
+ void clipSize();
+
+ bool loadFromXMI(QDomElement& qElement, const UMLWidgetList& widgets,
+ const MessageWidgetList* messages);
+ virtual bool loadFromXMI(QDomElement& qElement);
+ virtual void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
+
+ void cleanup();
+
+ bool isPointAddable();
+ bool isPointRemovable();
+
+ //:TODO: the following four methods should be protected
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+ virtual void setSelected(bool _select);
+public Q_SLOTS: //:TODO: all virtual?
+ virtual void slotMenuSelection(QAction* action);
+ void slotClassifierListItemRemoved(UMLClassifierListItem* obj);
+ void slotAttributeChanged();
+
+ void syncToModel();
+
+protected:
+ virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
+
+ virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+ virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
+
+private:
+ QPointF calculateTextPosition(Uml::TextRole::Enum role);
+ void setTextPosition(Uml::TextRole::Enum role);
+ void setTextPositionRelatively(Uml::TextRole::Enum role, const QPointF &oldPosition);
+ void setFloatingText(Uml::TextRole::Enum role, const QString& text, FloatingTextWidget* &ft);
+
+ AssociationWidget(UMLScene *scene);
+
+ void setUMLAssociation(UMLAssociation * assoc);
+
+ void mergeAssociationDataIntoUMLRepresentation();
+
+ static Uml::Region::Enum findPointRegion(const QRectF& rect, const QPointF& pos);
+ static qreal findInterceptOnEdge(const QRectF &rect, Uml::Region::Enum region, const QPointF &point);
+ static QLineF::IntersectType intersect(const QRectF &rect, const QLineF &line,
+ QPointF* intersectionPoint);
+
+ void moveEvent(QGraphicsSceneMouseEvent *me);
+
+ Uml::TextRole::Enum calculateNameType(Uml::TextRole::Enum defaultRoleType);
+
+ static QPointF swapXY(const QPointF &p);
+
+ // not used at the moment
+ // static QPointF calculatePointAtDistance(const QPointF &P1, const QPointF &P2, float Distance);
+ // static QPointF calculatePointAtDistanceOnPerpendicular(const QPointF &P1, const QPointF &P2, float Distance);
+ // static float perpendicularProjection(const QPointF& P1, const QPointF& P2, const QPointF& P3, QPointF& ResultingPoint);
+
+ static QPointF midPoint(const QPointF& p0, const QPointF& p1);
+
+ void createPointsSelfAssociation();
+ void updatePointsSelfAssociation();
+ void createPointsException();
+ void updatePointsException();
+
+ /**
+ * The WidgetRole struct gathers all information pertaining to the role.
+ * The AssociationWidget class contains two WidgetRole objects, one for each
+ * side of the association (A and B).
+ */
+ struct WidgetRole {
+
+ FloatingTextWidget* multiplicityWidget; ///< information regarding multiplicity
+ FloatingTextWidget* changeabilityWidget; ///< information regarding changeability
+ FloatingTextWidget* roleWidget; ///< role's label of this association
+
+ UMLWidget* umlWidget; ///< UMLWidget at this role's side of this association
+
+ Uml::Region::Enum m_WidgetRegion; ///< region of this role's widget
+
+ int m_nIndex; ///< the index of where the line is on the region for this role
+ int m_nTotalCount; ///< total amount of associations on the region this role's line is on
+
+ // The following items are only used if m_pObject is not set.
+ Uml::Visibility::Enum visibility;
+ Uml::Changeability::Enum changeability;
+ QString roleDocumentation;
+
+ };
+
+ void updateRegionLineCount(int index, int totalCount,
+ Uml::Region::Enum region, Uml::RoleType::Enum role);
+
+ void updateAssociations(int totalCount, Uml::Region::Enum region, Uml::RoleType::Enum role);
+
+ int getRegionCount(Uml::Region::Enum region, Uml::RoleType::Enum role);
+
+ void doUpdates(const QPointF &otherP, Uml::RoleType::Enum role);
+
+ void setChangeWidget(const QString &strChangeWidget, Uml::RoleType::Enum role);
+
+ bool checkAddPoint(const QPointF &scenePos);
+ bool checkRemovePoint(const QPointF &scenePos);
+
+ bool linePathStartsAt(const UMLWidget* widget);
+
+ void insertIntoLists(qreal position, const AssociationWidget* assoc);
+
+ qreal m_positions[100]; ///< auxiliary variable for updateAssociations()
+ int m_positions_len; ///< auxiliary variable for updateAssociations()
+ AssociationWidgetList m_ordered; ///< auxiliary variable for updateAssociations()
+
+ bool m_activated; ///< flag which is true if the activate method has been called for this class instance
+
+ /**
+ * When the association has a Role Floating Text this text should move
+ * when the AssociationLine moves but only if the closest segment to the
+ * role text moves.
+ * This segment is:
+ * m_associationLine[m_unNameLineSegment] -- m_associationLine[m_unNameLineSegment+1]
+ */
+ int m_unNameLineSegment;
+
+ QPointF m_oldNamePoint; ///< Position of name floatingtext saved by saveIdealTextPositions()
+ QPointF m_oldMultiAPoint; ///< Position of role A multiplicity floatingtext saved by saveIdealTextPositions()
+ QPointF m_oldMultiBPoint; ///< Position of role B multiplicity floatingtext saved by saveIdealTextPositions()
+ QPointF m_oldChangeAPoint; ///< Position of role A changeability floatingtext saved by saveIdealTextPositions()
+ QPointF m_oldChangeBPoint; ///< Position of role B changeability floatingtext saved by saveIdealTextPositions()
+ QPointF m_oldRoleAPoint; ///< Position of role A name floatingtext saved by saveIdealTextPositions()
+ QPointF m_oldRoleBPoint; ///< Position of role B name floatingtext saved by saveIdealTextPositions()
+
+ int m_nLinePathSegmentIndex; ///< anchor for m_pAssocClassLine
+ QGraphicsLineItem *m_pAssocClassLine; ///< used for connecting assoc. class
+ QGraphicsRectItem *m_pAssocClassLineSel0; ///< selection decoration for the start point of the assoc. class line
+ QGraphicsRectItem *m_pAssocClassLineSel1; ///< selection decoration for the end point of the assoc. class line
+
+ AssociationLine *m_associationLine; ///< the definition points for the association line
+ ClassifierWidget *m_associationClass; ///< used if we have an assoc. class
+ Uml::AssociationType::Enum m_associationType; ///< is only used if m_pObject is not set
+ WidgetRole m_role[2];
+ FloatingTextWidget* m_nameWidget; ///< displays the name of this association
+ QPointF m_eventScenePos; ///< holds scene pos of contextMenuEvent()
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/boxwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/boxwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/boxwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/boxwidget.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "boxwidget.h"
+
+// app includes
+#include "uml.h"
+#include "umldoc.h"
+
+// qt includes
+#include <QColorDialog>
+
+/**
+ * Constructs a BoxWidget.
+ *
+ * @param scene The parent to this widget.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ * @param type The WidgetType (wt_Box.)
+ */
+BoxWidget::BoxWidget(UMLScene * scene, Uml::ID::Type id, WidgetType type)
+ : UMLWidget(scene, type, id)
+{
+ setSize(100, 80);
+ m_usesDiagramLineColor = false; // boxes be black
+ m_lineColor = QColor("black");
+ setZValue(-10);
+}
+
+/**
+ * Destructor.
+ */
+BoxWidget::~BoxWidget()
+{
+}
+
+/**
+ * Draws a rectangle.
+ */
+void BoxWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ setPenFromSettings(painter);
+ painter->drawRect(0, 0, width(), height());
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Saves the widget to the "boxwidget" XMI element.
+ * Note: For loading from XMI, the inherited parent method is used.
+ */
+void BoxWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement boxElement = qDoc.createElement(QLatin1String("boxwidget"));
+ UMLWidget::saveToXMI(qDoc, boxElement);
+ qElement.appendChild(boxElement);
+}
+
+/**
+ * Show a properties dialog for a BoxWidget.
+ */
+void BoxWidget::showPropertiesDialog()
+{
+ QColor newColor = QColorDialog::getColor(lineColor()); // krazy:exclude=qclasses
+ if (newColor != lineColor()) {
+ setLineColor(newColor);
+ setUsesDiagramLineColor(false);
+ umlDoc()->setModified(true);
+ }
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/boxwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/boxwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/boxwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/boxwidget.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef BOXWIDGET_H
+#define BOXWIDGET_H
+
+//app includes
+#include "umlwidget.h"
+
+/**
+ * Displays a rectangular box.
+ * These widgets are diagram specific. They will still need a unique id
+ * from the @ref UMLDoc class for deletion and other purpose-kf6s.
+ *
+ * @short Displays a box.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class BoxWidget : public UMLWidget
+{
+public:
+ explicit BoxWidget(UMLScene * scene, Uml::ID::Type id = Uml::ID::None, WidgetType type = WidgetBase::wt_Box);
+ virtual ~BoxWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ virtual void showPropertiesDialog();
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/categorywidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/categorywidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/categorywidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/categorywidget.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,148 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header file
+#include "categorywidget.h"
+
+// local includes
+#include "category.h"
+#include "debug_utils.h"
+#include "umlview.h"
+#include "listpopupmenu.h"
+
+// qt includes
+#include <QPainter>
+
+/**
+ * Creates a Category widget.
+ *
+ * @param scene The parent of the widget.
+ * @param o The UMLCategory to represent.
+ */
+CategoryWidget::CategoryWidget(UMLScene * scene, UMLCategory *o)
+ : UMLWidget(scene, WidgetBase::wt_Category, o)
+{
+ m_fixedAspectRatio = true;
+}
+
+/**
+ * Destructor.
+ */
+CategoryWidget::~CategoryWidget()
+{
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void CategoryWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ UMLWidget::setPenFromSettings(painter);
+ if (UMLWidget::useFillColor())
+ painter->setBrush(UMLWidget::fillColor());
+ QFont font = UMLWidget::font();
+ font.setUnderline(false);
+ font.setBold(false);
+ font.setItalic(m_umlObject->isAbstract());
+ painter->setFont(font);
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ // the height is our radius
+ const int h = height();
+ const int w = width();
+ const int r = h > w ? h : w;
+
+ //int middleX = w / 2;
+ const int textStartY = (r / 2) - (fontHeight / 2);
+
+ // draw a circle
+ painter->drawEllipse(0, 0, r, r);
+ painter->setPen(textColor());
+
+ QString letterType(QLatin1Char('D'));
+ switch(static_cast<UMLCategory*>(m_umlObject)->getType()) {
+ case UMLCategory::ct_Disjoint_Specialisation:
+ letterType = QLatin1Char('D');
+ break;
+ case UMLCategory::ct_Overlapping_Specialisation:
+ letterType = QLatin1Char('O');
+ break;
+ case UMLCategory::ct_Union:
+ letterType = QLatin1Char('U');
+ break;
+ default:
+ break;
+ }
+
+ painter->drawText(UC_MARGIN, textStartY, r - UC_MARGIN * 2, fontHeight, Qt::AlignCenter, letterType);
+ UMLWidget::setPenFromSettings(painter);
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF CategoryWidget::minimumSize() const
+{
+ const UMLWidget::FontType ft = (m_umlObject->isAbstract() ? FT_BOLD_ITALIC : FT_BOLD);
+ const QFontMetrics &fm = UMLWidget::getFontMetrics(ft);
+ const int fontHeight = fm.lineSpacing();
+ int radius = UC_RADIUS + fontHeight + UC_MARGIN;
+
+ return QSizeF(radius, radius);
+}
+
+/**
+ * Saves this Category to file.
+ */
+void CategoryWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement categoryElement = qDoc.createElement(QLatin1String("categorywidget"));
+ UMLWidget::saveToXMI(qDoc, categoryElement);
+ qElement.appendChild(categoryElement);
+}
+
+/**
+ * Will be called when a menu selection has been made from the
+ * popup menu.
+ *
+ * @param action The action that has been selected.
+ */
+void CategoryWidget::slotMenuSelection(QAction* action)
+{
+ UMLCategory* catObj = static_cast<UMLCategory*>(umlObject());
+ if (!catObj) {
+ uWarning() << "No UMLCategory for this widget.";
+ return;
+ }
+
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_DisjointSpecialisation:
+ catObj->setType(UMLCategory::ct_Disjoint_Specialisation);
+ break;
+
+ case ListPopupMenu::mt_OverlappingSpecialisation:
+ catObj->setType(UMLCategory::ct_Overlapping_Specialisation);
+ break;
+
+ case ListPopupMenu::mt_Union:
+ catObj->setType(UMLCategory::ct_Union);
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ }
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/categorywidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/categorywidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/categorywidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/categorywidget.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef CATEGORYWIDGET_H
+#define CATEGORYWIDGET_H
+
+#include "umlwidget.h"
+
+#define UC_MARGIN 5
+#define UC_RADIUS 30
+
+class UMLCategory;
+
+/**
+ * This class is the graphical version of a UMLCategory. A CategoryWidget is created
+ * by a @ref UMLView. An CategoryWidget belongs to only one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
+ *
+ * If the Category class that this CategoryWidget is displaying is deleted, the @ref UMLView will
+ * make sure that this instance is also deleted.
+ *
+ * The CategoryWidget class inherits from the @ref UMLWidget class which adds most of the functionality
+ * to this class.
+ *
+ * @short A graphical version of a UMLCategory.
+ * @author Sharan Rao
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class CategoryWidget : public UMLWidget
+{
+ Q_OBJECT
+public:
+ CategoryWidget(UMLScene * scene, UMLCategory *o);
+ virtual ~CategoryWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+ // For loading we can use the loadFromXMI() inherited from UMLWidget.
+
+protected:
+ QSizeF minimumSize() const;
+
+public slots:
+ void slotMenuSelection(QAction* action);
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/classifierwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/classifierwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/classifierwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/classifierwidget.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,1426 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// 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 "listpopupmenu.h"
+#include "object_factory.h"
+#include "operation.h"
+#include "template.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+
+#define PACKAGE_MARGIN 5
+
+// qt includes
+#include <QPainter>
+
+DEBUG_REGISTER_DISABLED(ClassifierWidget)
+
+const int ClassifierWidget::MARGIN = 5;
+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()) {
+ m_baseType = WidgetBase::wt_Interface;
+ m_visualProperties = ShowOperations | ShowVisibility | ShowStereotype;
+ setShowStereotype(true);
+ updateSignatureTypes();
+ }
+}
+
+/**
+ * Constructs a ClassifierWidget.
+ *
+ * @param scene The parent of this ClassifierWidget.
+ * @param c The UMLClassifier 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 dynamic_cast<UMLClassifier*>(m_umlObject);
+}
+
+/**
+ * @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 += MARGIN;
+ }
+
+ // consider name
+ height += fontHeight;
+ // ... width
+ QString displayedName;
+ if (visualProperty(ShowPackage))
+ displayedName = m_umlObject->fullyQualifiedName();
+ else
+ displayedName = m_umlObject->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*MARGIN, 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(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)).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);
+ 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() - MARGIN;
+ }
+ }
+
+ // allow for height margin
+ if (showNameOnly) {
+ height += MARGIN;
+ }
+
+ // allow for width margin
+ width += MARGIN * 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() + (MARGIN*2);
+
+ foreach (UMLTemplate *t, list) {
+ int textWidth = fm.size(0, t->toString()).width();
+ if (textWidth > width)
+ width = textWidth;
+ }
+
+ width += (MARGIN*2);
+ return QSize(width, height);
+}
+
+/**
+ * Return the number of displayed attributes.
+ */
+int ClassifierWidget::displayedAttributes() const
+{
+ if (!visualProperty(ShowAttributes))
+ return 0;
+ 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 = NULL;
+ 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.
+ */
+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() - MARGIN;
+ int w = width();
+ if (templatesBoxSize.width() > 0)
+ w -= templatesBoxSize.width() / 2;
+ int h = height();
+ if (templatesBoxSize.height() > 0)
+ h -= templatesBoxSize.height() - MARGIN;
+ 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() + MARGIN;
+ int y = MARGIN;
+ foreach (UMLTemplate *t, tlist) {
+ QString text = t->toString();
+ painter->drawText(x, y, fm.size(0, text).width(), fontHeight, Qt::AlignVCenter, text);
+ y += fontHeight;
+ }
+ }
+
+ const int textX = MARGIN;
+ const int textWidth = w - MARGIN * 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;
+ if (visualProperty(ShowPackage)) {
+ name = m_umlObject->fullyQualifiedName();
+ } else {
+ name = this->name();
+ }
+ font.setItalic(m_umlObject->isAbstract());
+ painter->setFont(font);
+ painter->drawText(textX, bodyOffsetY, textWidth, nameHeight, Qt::AlignCenter, name);
+ 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*MARGIN, h-bodyOffsetY), Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, documentation());
+ if (brect.width() > width() + 2*MARGIN)
+ brect.setWidth(width()-2*MARGIN);
+ 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) {
+ 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(rect());
+ return path;
+ }
+#ifdef ENABLE_WIDGET_SHOW_DOC
+ QSizeF mainSize = rect().size();
+#else
+ QSizeF mainSize = calculateSize(false);
+#endif
+ QSize templatesBoxSize = calculateTemplatesBoxSize();
+ qreal mainY = 0.0;
+ if (templatesBoxSize.height() > 0) {
+ mainY += templatesBoxSize.height() - MARGIN;
+ 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)
+{
+ const int w = width();
+
+ if (m_Assocs.size() > 1) {
+ painter->drawEllipse(w/2 - CIRCLE_SIZE/2, SOCKET_INCREMENT / 2, CIRCLE_SIZE, CIRCLE_SIZE);
+ // 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, m_Assocs) {
+ 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;
+
+ 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);
+
+ UMLWidget::paint(painter, option);
+}
+
+/**
+ * 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 (m_Assocs.size() > 1)
+ 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 + PACKAGE_MARGIN,
+ w, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true));
+ lines = 2;
+ }
+
+ painter->drawText(0, (fontHeight*lines) + PACKAGE_MARGIN,
+ 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 += PACKAGE_MARGIN * 2;
+ if (width < 70)
+ width = 70; // minumin width of 70
+
+ int height = (lines*fontHeight) + fontHeight + (PACKAGE_MARGIN * 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);
+ 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 NULL;
+ * m_pInterfaceName if m_pName is non NULL and
+ * m_pInterfaceName->onWidget(p) returns non NULL; else NULL.
+ */
+UMLWidget* ClassifierWidget::onWidget(const QPointF &p)
+{
+ if (UMLWidget::onWidget(p) != NULL)
+ return this;
+ if (getDrawAsCircle() && m_pInterfaceName) {
+ uDebug() << "floatingtext: " << m_pInterfaceName->text();
+ return m_pInterfaceName->onWidget(p);
+ }
+ return NULL;
+}
+
+/**
+ * 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 NULL;
+}
+
+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;
+ }
+ 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()
+{
+ m_baseType = 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()
+{
+ m_baseType = 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()
+{
+ m_baseType = 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::loadFromXMI(QDomElement & qElement)
+{
+ if (!UMLWidget::loadFromXMI(qElement)) {
+ return false;
+ }
+
+ 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"));
+#ifdef ENABLE_WIDGET_SHOW_DOC
+ QString showDocumentation = qElement.attribute(QLatin1String("showdocumentation"), QLatin1String("0"));
+#endif
+
+ 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());
+#ifdef ENABLE_WIDGET_SHOW_DOC
+ setVisualPropertyCmd(ShowDocumentation, (bool)showDocumentation.toInt());
+#endif
+
+ m_attributeSignature = Uml::SignatureType::fromInt(showattsigs.toInt());
+ m_operationSignature = Uml::SignatureType::fromInt(showopsigs.toInt());
+
+ 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 == NULL) {
+ m_pInterfaceName = new FloatingTextWidget(m_scene,
+ Uml::TextRole::Floating,
+ name(), Uml::ID::Reserved);
+ m_pInterfaceName->setParentItem(this);
+ }
+ if (!m_pInterfaceName->loadFromXMI(element)) {
+ // Most likely cause: The FloatingTextWidget is empty.
+ delete m_pInterfaceName;
+ m_pInterfaceName = NULL;
+ } else {
+ m_pInterfaceName->activate();
+ m_pInterfaceName->update();
+ }
+ } else {
+ uError() << "unknown tag " << tag;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Creates the "classwidget" or "interfacewidget" XML element.
+ */
+void ClassifierWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement conceptElement;
+ UMLClassifier *umlc = classifier();
+ if (umlObject() && umlObject()->baseType() == UMLObject::ot_Package) {
+ conceptElement = qDoc.createElement(QLatin1String("packagewidget"));
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+ return;
+ }
+ else if (umlc && umlc->isInterface())
+ conceptElement = qDoc.createElement(QLatin1String("interfacewidget"));
+ else
+ conceptElement = qDoc.createElement(QLatin1String("classwidget"));
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ 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);
+#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->saveToXMI(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:
+ {
+ 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_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);
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/classifierwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/classifierwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/classifierwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/classifierwidget.h 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,146 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef CLASSIFIERWIDGET_H
+#define CLASSIFIERWIDGET_H
+
+#include "basictypes.h"
+#include "umlobject.h"
+#include "umlwidget.h"
+
+class AssociationWidget;
+class FloatingTextWidget;
+class QPainter;
+class UMLClassifier;
+
+/**
+ * @short Common implementation for class widget and interface widget
+ *
+ * @author Oliver Kellogg
+ * @author Gopala Krishna
+ *
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class ClassifierWidget : public UMLWidget
+{
+ Q_OBJECT
+ Q_ENUMS(VisualProperty)
+public:
+ /**
+ * This enumeration lists the visual properties that can be easily
+ * set, reset and toggled and all these operate on an integer
+ * which stores all the flag status.
+ */
+ enum VisualProperty {
+ ShowStereotype = 0x1,
+ ShowOperations = 0x2,
+ ShowPublicOnly = 0x4,
+ ShowVisibility = 0x8,
+ ShowPackage = 0x10,
+ ShowAttributes = 0x20,
+ DrawAsCircle = 0x40,
+ ShowOperationSignature = 0x60, ///< only in setter
+ ShowAttributeSignature = 0x80, ///< only in setter
+ DrawAsPackage = 0x100,
+ ShowDocumentation = 0x200,
+ };
+
+ Q_DECLARE_FLAGS(VisualProperties, VisualProperty)
+
+ ClassifierWidget(UMLScene * scene, UMLClassifier * o);
+ ClassifierWidget(UMLScene * scene, UMLPackage * o);
+ virtual ~ClassifierWidget();
+
+ UMLClassifier *classifier() const;
+
+ VisualProperties visualProperties() const;
+ void setVisualProperties(VisualProperties properties);
+
+ bool visualProperty(VisualProperty property) const;
+ void setVisualProperty(VisualProperty property, bool enable = true);
+ void setVisualPropertyCmd(VisualProperty property, bool enable = true);
+ void toggleVisualProperty(VisualProperty property);
+
+ int displayedAttributes() const;
+ int displayedOperations() const;
+
+ Uml::SignatureType::Enum attributeSignature() const;
+ void setAttributeSignature(Uml::SignatureType::Enum sig);
+
+ Uml::SignatureType::Enum operationSignature() const;
+ void setOperationSignature(Uml::SignatureType::Enum sig);
+
+ void setShowAttSigs(bool _show);
+ void toggleShowAttSigs();
+
+ bool getDrawAsCircle() const;
+ void setDrawAsCircle(bool drawAsCircle);
+ void toggleDrawAsCircle();
+
+ void changeToClass();
+ void changeToInterface();
+ void changeToPackage();
+
+ AssociationWidget *classAssociationWidget() const;
+ void setClassAssociationWidget(AssociationWidget *assocwidget);
+// virtual void adjustAssociations(int x, int y);
+
+ UMLWidget* onWidget(const QPointF& p);
+ UMLWidget* widgetWithID(Uml::ID::Type id);
+
+ virtual void setDocumentation(const QString& doc);
+
+ QSizeF calculateSize(bool withExtensions = true) const;
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ virtual QPainterPath shape() const;
+
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+ virtual bool loadFromXMI(QDomElement & qElement);
+
+public Q_SLOTS:
+ virtual void slotMenuSelection(QAction* action);
+
+private Q_SLOTS:
+ void slotShowAttributes(bool state);
+ void slotShowOperations(bool state);
+
+private:
+ void updateSignatureTypes();
+ QSize calculateTemplatesBoxSize() const;
+
+ QSizeF minimumSize() const;
+
+ void drawAsCircle(QPainter *p, const QStyleOptionGraphicsItem *option);
+ QSize calculateAsCircleSize() const;
+
+ void drawAsPackage(QPainter *painter, const QStyleOptionGraphicsItem *option);
+ QSize calculateAsPackageSize() const;
+
+ int displayedMembers(UMLObject::ObjectType ot) const;
+ void drawMembers(QPainter *painter, UMLObject::ObjectType ot, Uml::SignatureType::Enum sigType,
+ int x, int y, int fontHeight);
+
+ static const int MARGIN; ///< text width margin
+ static const int CIRCLE_SIZE; ///< size of circle when interface is rendered as such
+ static const int SOCKET_INCREMENT; ///< augmentation of circle for socket (required interface)
+
+ VisualProperties m_visualProperties;
+ Uml::SignatureType::Enum m_attributeSignature; ///< Loaded/saved item.
+ Uml::SignatureType::Enum m_operationSignature; ///< Loaded/saved item.
+ AssociationWidget *m_pAssocWidget; ///< related AssociationWidget in case this classifier acts as an association class
+ FloatingTextWidget *m_pInterfaceName; ///< Separate widget for name in case of interface drawn as circle
+
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(ClassifierWidget::VisualProperties)
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/combinedfragmentwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/combinedfragmentwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/combinedfragmentwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/combinedfragmentwidget.cpp 2015-10-08 11:48:59.508089026 +0300
@@ -0,0 +1,477 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "combinedfragmentwidget.h"
+
+// app includes
+#include "debug_utils.h"
+#include "dialog_utils.h"
+#include "listpopupmenu.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+// kde includes
+#include <KLocalizedString>
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+#include <QPainter>
+#include <QString>
+
+/**
+ * Creates a Combined Fragment widget.
+ *
+ * @param scene The parent of the widget.
+ * @param combinedfragmentType The type of combined fragment.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+CombinedFragmentWidget::CombinedFragmentWidget(UMLScene * scene, CombinedFragmentType combinedfragmentType, Uml::ID::Type id)
+ : UMLWidget(scene, WidgetBase::wt_CombinedFragment, id)
+{
+ setCombinedFragmentType(combinedfragmentType);
+}
+
+/**
+ * Destructor.
+ */
+CombinedFragmentWidget::~CombinedFragmentWidget()
+{
+ for (QList<FloatingDashLineWidget*>::iterator it=m_dashLines.begin() ; it!=m_dashLines.end() ; ++it) {
+ delete(*it);
+ }
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void CombinedFragmentWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ int w = width();
+ int h = height();
+ int line_width = 45;
+ int old_Y;
+
+ setPenFromSettings(painter);
+
+ if (m_CombinedFragment == Ref) {
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ }
+ }
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const QString combined_fragment_value = name();
+ int textStartY = (h / 2) - (fontHeight / 2);
+ painter->drawRect(0, 0, w, h);
+
+ painter->setPen(textColor());
+ painter->setFont(UMLWidget::font());
+ QString temp = QLatin1String("loop");
+
+ switch (m_CombinedFragment)
+ {
+ case Ref :
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, textStartY, w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignCenter, combined_fragment_value);
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, 0, w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("ref"));
+ break;
+
+ case Opt :
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
+ w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("opt"));
+ break;
+
+ case Break :
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
+ w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("break"));
+ break;
+
+ case Loop :
+ if (combined_fragment_value != QLatin1String("-"))
+ {
+ temp += QLatin1String(" [") + combined_fragment_value + QLatin1Char(']');
+ line_width += (combined_fragment_value.size() + 2) * 8;
+ }
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, 0, w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, temp);
+
+ break;
+
+ case Neg :
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
+ w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("neg"));
+ break;
+
+ case Crit :
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
+ w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("critical"));
+ break;
+
+ case Ass :
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
+ w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("assert"));
+ break;
+
+ case Alt :
+ if (combined_fragment_value != QLatin1String("-"))
+ {
+ temp = QLatin1Char('[') + combined_fragment_value + QLatin1Char(']');
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, 20, w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, temp);
+ if (m_dashLines.size() == 1 && m_dashLines.first()->y() < y() + 20 + fontHeight)
+ m_dashLines.first()->setY(y() + h/2);
+ }
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
+ w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("alt"));
+ // dash lines
+ //m_dashLines.first()->paint(painter);
+ // TODO: move to UMLWidget::calculateSize api
+ for (QList<FloatingDashLineWidget*>::iterator it=m_dashLines.begin() ; it!=m_dashLines.end() ; ++it) {
+ (*it)->setX(x());
+ old_Y = (*it)->getYMin();
+ (*it)->setYMin(y());
+ (*it)->setYMax(y() + height());
+ (*it)->setY(y() + (*it)->y() - old_Y);
+ (*it)->setSize(w, (*it)->height());
+ (*it)->setLineColor(lineColor());
+ (*it)->setLineWidth(lineWidth());
+ }
+
+ break;
+
+ case Par :
+ painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
+ w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("parallel"));
+ // dash lines
+ if (m_dashLines.size() != 0) {
+ //m_dashLines.first()->paint(painter);
+ // TODO: move to UMLWidget::calculateSize api
+ for (QList<FloatingDashLineWidget*>::iterator it=m_dashLines.begin() ; it!=m_dashLines.end() ; ++it) {
+ (*it)->setX(x());
+ old_Y = (*it)->getYMin();
+ (*it)->setYMin(y());
+ (*it)->setYMax(y() + height());
+ (*it)->setY(y() + (*it)->y() - old_Y);
+ (*it)->setSize(w, (*it)->height());
+ (*it)->setLineColor(lineColor());
+ (*it)->setLineWidth(lineWidth());
+ }
+ }
+ break;
+
+ default : break;
+ }
+
+ setPenFromSettings(painter);
+ painter->drawLine(0, 20, line_width, 20);
+ painter->drawLine(line_width, 20, line_width + 10, 10);
+ painter->drawLine(line_width + 10, 10, line_width + 10, 0);
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF CombinedFragmentWidget::minimumSize() const
+{
+ int width = 10, height = 10;
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int textWidth = fm.width(name());
+ height = fontHeight;
+ width = textWidth + 60 > COMBINED_FRAGMENT_WIDTH ? textWidth + 60: COMBINED_FRAGMENT_WIDTH;
+ if (m_CombinedFragment == Loop)
+ width += int((float)textWidth * 0.4f);
+ if (m_CombinedFragment == Alt)
+ height += fontHeight + 40;
+ height = height > COMBINED_FRAGMENT_HEIGHT ? height : COMBINED_FRAGMENT_HEIGHT;
+ width += COMBINED_FRAGMENT_MARGIN * 2;
+ height += COMBINED_FRAGMENT_MARGIN * 2;
+
+ return QSizeF(width, height);
+}
+
+/**
+ * Returns the type of combined fragment.
+ */
+CombinedFragmentWidget::CombinedFragmentType CombinedFragmentWidget::combinedFragmentType() const
+{
+ return m_CombinedFragment;
+}
+
+/**
+ * Sets the type of combined fragment.
+ */
+void CombinedFragmentWidget::setCombinedFragmentType(CombinedFragmentType combinedfragmentType)
+{
+ m_CombinedFragment = combinedfragmentType;
+ UMLWidget::m_resizable = true ; //(m_CombinedFragment == Normal);
+ // creates a dash line if the combined fragment type is alternative or parallel
+ if (m_CombinedFragment == Alt && m_dashLines.isEmpty())
+ {
+ m_dashLines.push_back(new FloatingDashLineWidget(m_scene, Uml::ID::None, this));
+ if (m_CombinedFragment == Alt)
+ {
+ m_dashLines.back()->setText(QLatin1String("else"));
+ }
+ // TODO: move to UMLWidget::calculateSize api
+ m_dashLines.back()->setX(x());
+ m_dashLines.back()->setYMin(y());
+ m_dashLines.back()->setYMax(y() + height());
+ m_dashLines.back()->setY(y() + height()/2);
+ m_dashLines.back()->setSize(width(), m_dashLines.back()->height());
+ m_scene->widgetList().append(m_dashLines.back());
+ }
+}
+
+/**
+ * Returns the type of combined fragment.
+ */
+CombinedFragmentWidget::CombinedFragmentType CombinedFragmentWidget::combinedFragmentType(const QString& type) const
+{
+ if (type == QLatin1String("Reference"))
+ return (CombinedFragmentWidget::Ref);
+ if (type == QLatin1String("Option"))
+ return (CombinedFragmentWidget::Opt);
+ if (type == QLatin1String("Break"))
+ return (CombinedFragmentWidget::Break);
+ if (type == QLatin1String("Loop"))
+ return (CombinedFragmentWidget::Loop);
+ if (type == QLatin1String("Negative"))
+ return (CombinedFragmentWidget::Neg);
+ if (type == QLatin1String("Critical"))
+ return (CombinedFragmentWidget::Crit);
+ if (type == QLatin1String("Assertion"))
+ return (CombinedFragmentWidget::Ass);
+ if (type == QLatin1String("Alternative"))
+ return (CombinedFragmentWidget::Alt);
+ if (type == QLatin1String("Parallel"))
+ return (CombinedFragmentWidget::Par);
+ // Shouldn't happen
+ Q_ASSERT(0);
+ return (CombinedFragmentWidget::Ref);
+}
+
+/**
+ * Sets the type of combined fragment.
+ */
+void CombinedFragmentWidget::setCombinedFragmentType(const QString& combinedfragmentType)
+{
+ setCombinedFragmentType(combinedFragmentType(combinedfragmentType));
+}
+
+/**
+ * ...
+ */
+void CombinedFragmentWidget::askNameForWidgetType(UMLWidget* &targetWidget, const QString& dialogTitle,
+ const QString& dialogPrompt, const QString& defaultName)
+{
+ Q_UNUSED(defaultName);
+ bool pressedOK = false;
+ const QStringList list = QStringList()
+ << QLatin1String("Reference")
+ << QLatin1String("Option")
+ << QLatin1String("Break")
+ << QLatin1String("Loop")
+ << QLatin1String("Negative")
+ << QLatin1String("Critical")
+ << QLatin1String("Assertion")
+ << QLatin1String("Alternative")
+ << QLatin1String("Parallel") ;
+#if QT_VERSION >= 0x050000
+ QPointer<QInputDialog> inputDlg = new QInputDialog();
+ inputDlg->setComboBoxItems(list);
+ inputDlg->setOptions(QInputDialog::UseListViewForComboBoxItems);
+ inputDlg->setWindowTitle(dialogTitle);
+ inputDlg->setLabelText(dialogPrompt);
+ pressedOK = inputDlg->exec();
+ QStringList result;
+ result.append(inputDlg->textValue());
+ delete inputDlg;
+#else
+ const QStringList select = list;
+ QStringList result = KInputDialog::getItemList (dialogTitle, dialogPrompt, list, select, false, &pressedOK, UMLApp::app());
+#endif
+ if (pressedOK) {
+ QString type = result.join(QString());
+ dynamic_cast<CombinedFragmentWidget*>(targetWidget)->setCombinedFragmentType(type);
+ if (type == QLatin1String("Reference"))
+ Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the name of the diagram referenced"), i18n("Enter the name of the diagram referenced"), i18n("Diagram name"));
+ else if (type == QLatin1String(QLatin1String("Loop")))
+ Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the guard of the loop"), i18n("Enter the guard of the loop"), i18n("-"));
+ else if (type == QLatin1String("Alternative"))
+ Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the first alternative name"), i18n("Enter the first alternative name"), i18n("-"));
+ } else {
+ targetWidget->cleanup();
+ delete targetWidget;
+ targetWidget = NULL;
+ }
+}
+
+/**
+ * Saves the widget to the "combinedFragmentwidget" XMI element.
+ */
+void CombinedFragmentWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement combinedFragmentElement = qDoc.createElement(QLatin1String("combinedFragmentwidget"));
+ UMLWidget::saveToXMI(qDoc, combinedFragmentElement);
+ combinedFragmentElement.setAttribute(QLatin1String("combinedFragmentname"), m_Text);
+ combinedFragmentElement.setAttribute(QLatin1String("documentation"), m_Doc);
+ combinedFragmentElement.setAttribute(QLatin1String("CombinedFragmenttype"), m_CombinedFragment);
+
+ // save the corresponding floating dash lines
+ for (QList<FloatingDashLineWidget*>::iterator it = m_dashLines.begin() ; it != m_dashLines.end() ; ++it) {
+ (*it)-> saveToXMI(qDoc, combinedFragmentElement);
+ }
+
+ qElement.appendChild(combinedFragmentElement);
+}
+
+/**
+ * Loads the widget from the "CombinedFragmentwidget" XMI element.
+ */
+bool CombinedFragmentWidget::loadFromXMI(QDomElement & qElement)
+{
+ if (!UMLWidget::loadFromXMI(qElement))
+ return false;
+ m_Text = qElement.attribute(QLatin1String("combinedFragmentname"));
+ m_Doc = qElement.attribute(QLatin1String("documentation"));
+ QString type = qElement.attribute(QLatin1String("CombinedFragmenttype"));
+
+ //now load child elements
+ QDomNode node = qElement.firstChild();
+ QDomElement element = node.toElement();
+ while (!element.isNull()) {
+ QString tag = element.tagName();
+ if (tag == QLatin1String("floatingdashlinewidget")) {
+ FloatingDashLineWidget * fdlwidget = new FloatingDashLineWidget(m_scene, Uml::ID::None, this);
+ m_dashLines.push_back(fdlwidget);
+ if (!fdlwidget->loadFromXMI(element)) {
+ // Most likely cause: The FloatingTextWidget is empty.
+ delete m_dashLines.back();
+ return false;
+ }
+ else {
+ m_scene->widgetList().append(fdlwidget);
+ fdlwidget->clipSize();
+ }
+ } else {
+ uError() << "unknown tag " << tag;
+ }
+ node = node.nextSibling();
+ element = node.toElement();
+ }
+ // m_dashLines = listline;
+ setCombinedFragmentType((CombinedFragmentType)type.toInt());
+
+ return true;
+}
+
+void CombinedFragmentWidget::removeDashLine(FloatingDashLineWidget *line)
+{
+ if (m_dashLines.contains(line))
+ m_dashLines.removeOne(line);
+}
+
+/**
+ * Overrides the function from UMLWidget. Deletes all FloatingDashLineWidgets
+ * that are associated with this instance.
+ */
+void CombinedFragmentWidget::cleanup()
+{
+ foreach (FloatingDashLineWidget* w, m_dashLines)
+ {
+ if (!w->isSelected()) {
+ // no need to make this undoable, since the dashlines will be
+ // reconstructed when deleting the combined fragment is undone.
+ umlScene()->removeWidgetCmd(w);
+ }
+ }
+}
+
+/**
+ * Overrides the function from UMLWidget.
+ *
+ * @param action The command to be executed.
+ */
+void CombinedFragmentWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch (sel) {
+ // for alternative or parallel combined fragments
+ case ListPopupMenu::mt_AddInteractionOperand:
+ m_dashLines.push_back(new FloatingDashLineWidget(m_scene, Uml::ID::None, this));
+ if (m_CombinedFragment == Alt)
+ {
+ m_dashLines.back()->setText(QLatin1String("else"));
+ }
+ // TODO: move to UMLWidget::calculateSize api
+ m_dashLines.back()->setX(x());
+ m_dashLines.back()->setYMin(y());
+ m_dashLines.back()->setYMax(y() + height());
+ m_dashLines.back()->setY(y() + height() / 2);
+ m_dashLines.back()->setSize(width(), m_dashLines.back()->height());
+ m_scene->setupNewWidget(m_dashLines.back());
+ break;
+
+ case ListPopupMenu::mt_Rename:
+ {
+ bool ok = false;
+ QString name = m_Text;
+
+#if QT_VERSION >= 0x050000
+ if (m_CombinedFragment == Alt) {
+ name = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter first alternative"), i18n("Enter first alternative :"),
+ QLineEdit::Normal,
+ m_Text, &ok);
+ }
+ else if (m_CombinedFragment == Ref) {
+ name = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter referenced diagram name"), i18n("Enter referenced diagram name :"),
+ QLineEdit::Normal,
+ m_Text, &ok);
+ }
+ else if (m_CombinedFragment == Loop) {
+ name = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter the guard of the loop"), i18n("Enter the guard of the loop:"),
+ QLineEdit::Normal,
+ m_Text, &ok);
+ }
+#else
+ if (m_CombinedFragment == Alt) {
+ name = KInputDialog::getText(i18n("Enter first alternative"), i18n("Enter first alternative :"), m_Text, &ok);
+ }
+ else if (m_CombinedFragment == Ref) {
+ name = KInputDialog::getText(i18n("Enter referenced diagram name"), i18n("Enter referenced diagram name :"), m_Text, &ok);
+ }
+ else if (m_CombinedFragment == Loop) {
+ name = KInputDialog::getText(i18n("Enter the guard of the loop"), i18n("Enter the guard of the loop:"), m_Text, &ok);
+ }
+#endif
+ if (ok && name.length() > 0)
+ m_Text = name;
+ }
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ }
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/combinedfragmentwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/combinedfragmentwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/combinedfragmentwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/combinedfragmentwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef COMBINEDFRAGMENTWIDGET_H
+#define COMBINEDFRAGMENTWIDGET_H
+
+#include "umlwidget.h"
+#include "worktoolbar.h"
+#include "floatingdashlinewidget.h"
+
+#include <QList>
+
+#define COMBINED_FRAGMENT_MARGIN 5
+#define COMBINED_FRAGMENT_WIDTH 100
+#define COMBINED_FRAGMENT_HEIGHT 50
+
+/**
+ * This class is the graphical version of a UML combined fragment. A combinedfragmentWidget is created
+ * by a @ref UMLView. An combinedfragmentWidget belongs to only one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
+ *
+ * The combinedfragmentWidget class inherits from the @ref UMLWidget class which adds most of the functionality
+ * to this class.
+ *
+ * @short A graphical version of a UML combined fragment.
+ * @author Hassan KOUCH <hkouch@hotmail.com>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class CombinedFragmentWidget : public UMLWidget
+{
+ Q_OBJECT
+
+public:
+ enum CombinedFragmentType
+ {
+ Ref = 0,
+ Opt,
+ Break,
+ Loop,
+ Neg,
+ Crit,
+ Ass,
+ Alt,
+ Par
+ };
+
+ explicit CombinedFragmentWidget(UMLScene * scene,
+ CombinedFragmentType combinedfragmentType = Ref,
+ Uml::ID::Type id = Uml::ID::None);
+ virtual ~CombinedFragmentWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ CombinedFragmentType combinedFragmentType() const;
+ CombinedFragmentType combinedFragmentType(const QString& combinedfragmentType) const;
+ void setCombinedFragmentType(CombinedFragmentType combinedfragmentType);
+ void setCombinedFragmentType(const QString& combinedfragmentType);
+
+ void askNameForWidgetType(UMLWidget* &targetWidget, const QString& dialogTitle,
+ const QString& dialogPrompt, const QString& defaultName);
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+ bool loadFromXMI(QDomElement & qElement);
+ void removeDashLine(FloatingDashLineWidget *line);
+
+ virtual void cleanup();
+
+public slots:
+ void slotMenuSelection(QAction* action);
+
+
+protected:
+ QSizeF minimumSize() const;
+
+ /// Type of CombinedFragment.
+ CombinedFragmentType m_CombinedFragment;
+
+private:
+ /// Dash lines of an alternative or parallel combined fragment
+ QList<FloatingDashLineWidget*> m_dashLines ;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/componentwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/componentwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/componentwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/componentwidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,207 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "componentwidget.h"
+
+// app includes
+#include "component.h"
+#include "debug_utils.h"
+#include "umlscene.h"
+#include "umlview.h"
+#include "optionstate.h"
+#include "umldoc.h"
+#include "package.h"
+#include "portwidget.h"
+
+/**
+ * Constructs a ComponentWidget.
+ *
+ * @param scene The parent of this ComponentWidget.
+ * @param c The UMLComponent this will be representing.
+ */
+ComponentWidget::ComponentWidget(UMLScene * scene, UMLComponent *c)
+ : UMLWidget(scene, WidgetBase::wt_Component, c)
+{
+ setSize(100, 30);
+ //set defaults from m_scene
+ if (m_scene) {
+ //check to see if correct
+ const Settings::OptionState& ops = m_scene->optionState();
+ m_showStereotype = ops.classState.showStereoType;
+ }
+}
+
+/**
+ * Destructor.
+ */
+ComponentWidget::~ComponentWidget()
+{
+}
+
+/**
+ * Reimplemented from UMLWidget::paint to paint component
+ * widget.
+ */
+void ComponentWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ UMLComponent *umlcomp = static_cast<UMLComponent*>(m_umlObject);
+ if (umlcomp == NULL)
+ return;
+ setPenFromSettings(painter);
+ QPen origPen = painter->pen();
+ QPen pen = origPen;
+ if (umlcomp->getExecutable()) {
+ pen.setWidth(origPen.width() + 2);
+ painter->setPen(pen);
+ }
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ } else {
+ painter->setBrush(m_scene->backgroundColor());
+ }
+
+ const int w = width();
+ const int h = height();
+ const int halfHeight = h / 2;
+ int textXOffset = 0;
+ QFont font = UMLWidget::font();
+ font.setBold(true);
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD);
+ const int fontHeight = fm.lineSpacing();
+ QString nameStr = name();
+ const QString stereotype = m_umlObject->stereotype();
+
+ if (Settings::optionState().generalState.uml2) {
+ painter->drawRect(0, 0, w, h);
+ // draw small component symbol in upper right corner
+ painter->setPen(origPen);
+ painter->drawRect(w - 17, 5, 11, 13);
+ painter->drawRect(w - 19, 7, 2, 2);
+ painter->drawRect(w - 19, 11, 2, 2);
+ painter->setPen(pen);
+ } else {
+ painter->drawRect(2*COMPONENT_MARGIN, 0, w - 2*COMPONENT_MARGIN, h);
+ painter->drawRect(0, halfHeight - fontHeight/2 - fontHeight, COMPONENT_MARGIN*4, fontHeight);
+ painter->drawRect(0, halfHeight + fontHeight/2, COMPONENT_MARGIN*4, fontHeight);
+ textXOffset = COMPONENT_MARGIN * 4;
+ }
+
+ painter->setPen(textColor());
+ painter->setFont(font);
+
+ int lines = 1;
+
+ if (!stereotype.isEmpty()) {
+ painter->drawText(textXOffset, halfHeight - fontHeight,
+ w - textXOffset, fontHeight, Qt::AlignCenter,
+ m_umlObject->stereotype(true));
+ lines = 2;
+ }
+
+ if (UMLWidget::isInstance()) {
+ font.setUnderline(true);
+ painter->setFont(font);
+ nameStr = UMLWidget::instanceName() + QLatin1String(" : ") + nameStr;
+ }
+
+ if (lines == 1) {
+ painter->drawText(textXOffset, halfHeight - (fontHeight/2),
+ w - textXOffset, fontHeight, Qt::AlignCenter, nameStr);
+ } else {
+ painter->drawText(textXOffset, halfHeight,
+ w - textXOffset, fontHeight, Qt::AlignCenter, nameStr);
+ }
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overridden from UMLWidget due to emission of signal sigCompMoved()
+ */
+void ComponentWidget::moveWidgetBy(qreal diffX, qreal diffY)
+{
+ UMLWidget::moveWidgetBy(diffX, diffY);
+ emit sigCompMoved(diffX, diffY);
+}
+
+/**
+ * Override method from UMLWidget for adjustment of attached PortWidgets.
+ */
+void ComponentWidget::adjustAssocs(qreal dx, qreal dy)
+{
+ if (m_doc->loading()) {
+ // don't recalculate the assocs during load of XMI
+ // -> return immediately without action
+ return;
+ }
+ UMLWidget::adjustAssocs(dx, dy);
+ UMLPackage *comp = static_cast<UMLPackage*>(m_umlObject);
+ foreach (UMLObject *o, comp->containedObjects()) {
+ uIgnoreZeroPointer(o);
+ if (o->baseType() != UMLObject::ot_Port)
+ continue;
+ UMLWidget *portW = m_scene->widgetOnDiagram(o->id());
+ if (portW)
+ portW->adjustAssocs(dx, dy);
+ }
+}
+
+/**
+ * Saves to the "componentwidget" XMI element.
+ */
+void ComponentWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement conceptElement = qDoc.createElement(QLatin1String("componentwidget"));
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF ComponentWidget::minimumSize() const
+{
+ if (!m_umlObject) {
+ return QSizeF(70, 70);
+ }
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
+ const int fontHeight = fm.lineSpacing();
+
+ QString name = m_umlObject->name();
+ if (UMLWidget::isInstance()) {
+ name = UMLWidget::instanceName() + QLatin1String(" : ") + name;
+ }
+
+ int width = fm.width(name);
+
+ int stereoWidth = 0;
+ if (!m_umlObject->stereotype().isEmpty()) {
+ stereoWidth = fm.width(m_umlObject->stereotype(true));
+ }
+ if (stereoWidth > width)
+ width = stereoWidth;
+ width += COMPONENT_MARGIN * 6;
+ width = 70>width ? 70 : width; //minumin width of 70
+
+ int height = (2*fontHeight) + (COMPONENT_MARGIN * 3);
+
+ UMLComponent *umlcomp = static_cast<UMLComponent*>(m_umlObject);
+ if (umlcomp && umlcomp->getExecutable()) {
+ width += 2;
+ height += 2;
+ }
+
+ return QSizeF(width, height);
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/componentwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/componentwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/componentwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/componentwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef COMPONENTWIDGET_H
+#define COMPONENTWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLComponent;
+
+#define COMPONENT_MARGIN 10
+
+/**
+ * Defines a graphical version of the Component. Most of the functionality
+ * will come from the @ref UMLComponent class.
+ *
+ * @short A graphical version of a Component.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class ComponentWidget : public UMLWidget
+{
+ Q_OBJECT
+public:
+ ComponentWidget(UMLScene * scene, UMLComponent *c);
+ virtual ~ComponentWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ virtual void moveWidgetBy(qreal diffX, qreal diffY);
+ virtual void adjustAssocs(qreal dx, qreal dy);
+
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+signals:
+ /**
+ * Emitted when the component widget is moved.
+ * Provides the delta X and delta Y amount by which the widget was moved
+ * relative to the previous position.
+ * Slots into PortWidget::slotCompMoved()
+ * @param diffX The difference between previous and new X value.
+ * @param diffY The difference between previous and new Y value.
+ */
+ void sigCompMoved(qreal diffX, qreal diffY);
+
+protected:
+ QSizeF minimumSize() const;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/datatypewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/datatypewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/datatypewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/datatypewidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,129 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "datatypewidget.h"
+
+// app includes
+#include "classifier.h"
+#include "classifierlistitem.h"
+#include "debug_utils.h"
+#include "operation.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+// qt includes
+#include <QPainter>
+
+/**
+ * Constructs an DatatypeWidget.
+ *
+ * @param scene The parent of this DatatypeWidget.
+ * @param d The UMLClassifier this will be representing.
+ */
+DatatypeWidget::DatatypeWidget(UMLScene *scene, UMLClassifier *d)
+ : UMLWidget(scene, WidgetBase::wt_Datatype, d)
+{
+ setSize(100, 30);
+}
+
+/**
+ * Standard deconstructor.
+ */
+DatatypeWidget::~DatatypeWidget()
+{
+}
+
+/**
+ * Overrides standard method.
+ */
+void DatatypeWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ setPenFromSettings(painter);
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ } else {
+ painter->setBrush(m_scene->backgroundColor());
+ }
+
+ int w = width();
+ int h = height();
+
+ QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ int fontHeight = fm.lineSpacing();
+
+ painter->drawRect(0, 0, w, h);
+ painter->setPen(textColor());
+
+ QFont font = UMLWidget::font();
+ font.setBold(true);
+ painter->setFont(font);
+ painter->drawText(DATATYPE_MARGIN, 0,
+ w - DATATYPE_MARGIN* 2, fontHeight,
+ Qt::AlignCenter, m_umlObject->stereotype(true));
+
+ font.setItalic(m_umlObject->isAbstract());
+ painter->setFont(font);
+ painter->drawText(DATATYPE_MARGIN, fontHeight,
+ w - DATATYPE_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Loads from a "datatypewidget" XMI element.
+ */
+bool DatatypeWidget::loadFromXMI(QDomElement & qElement)
+{
+ return UMLWidget::loadFromXMI(qElement);
+}
+
+/**
+ * Saves to the "datatypewidget" XMI element.
+ */
+void DatatypeWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement conceptElement = qDoc.createElement(QLatin1String("datatypewidget"));
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF DatatypeWidget::minimumSize() const
+{
+ if (!m_umlObject) {
+ return UMLWidget::minimumSize();
+ }
+ int width, height;
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+
+ int lines = 1;//always have one line - for name
+ lines++; //for the stereotype
+
+ height = width = 0;
+ height += lines * fontHeight;
+
+ //now set the width of the concept
+ //set width to name to start with
+ //set width to name to start with
+ width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(m_umlObject->fullyQualifiedName()).width();
+ int w = getFontMetrics(FT_BOLD).boundingRect(m_umlObject->stereotype(true)).width();
+
+ width = w > width?w:width;
+
+ //allow for width margin
+ width += DATATYPE_MARGIN * 2;
+
+ return QSizeF(width, height);
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/datatypewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/datatypewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/datatypewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/datatypewidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef DATATYPEWIDGET_H
+#define DATATYPEWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLClassifier;
+
+#define DATATYPE_MARGIN 5
+
+/**
+ * Defines a graphical version of the datatype. Most of the functionality
+ * will come from the @ref UMLWidget class from which class inherits from.
+ *
+ * @short A graphical version of an datatype.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class DatatypeWidget : public UMLWidget
+{
+ Q_OBJECT
+public:
+ DatatypeWidget(UMLScene *scene, UMLClassifier *d);
+ virtual ~DatatypeWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ bool loadFromXMI(QDomElement& qElement);
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+public Q_SLOTS:
+
+protected:
+ QSizeF minimumSize() const;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/entitywidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/entitywidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/entitywidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/entitywidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,246 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "entitywidget.h"
+
+// app includes
+#include "classifier.h"
+#include "classifierlistitem.h"
+#include "debug_utils.h"
+#include "entity.h"
+#include "entityattribute.h"
+#include "foreignkeyconstraint.h"
+#include "listpopupmenu.h"
+#include "object_factory.h"
+#include "uml.h"
+#include "umlclassifierlistitemlist.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+#include "uniqueconstraint.h"
+
+/**
+ * Constructs an EntityWidget.
+ *
+ * @param scene The parent of this EntityWidget.
+ * @param o The UMLObject this will be representing.
+ */
+EntityWidget::EntityWidget(UMLScene *scene, UMLObject* o)
+ : UMLWidget(scene, WidgetBase::wt_Entity, o)
+{
+ setSize(100, 30);
+}
+
+/**
+ * Destructor.
+ */
+EntityWidget::~EntityWidget()
+{
+}
+
+/**
+ * Draws the entity as a rectangle with a box underneith with a list of literals
+ */
+void EntityWidget::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());
+
+ const int w = width();
+ const int h = height();
+
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ int fontHeight = fm.lineSpacing();
+ const QString name = this->name();
+
+ painter->drawRect(0, 0, w, h);
+ painter->setPen(textColor());
+
+ QFont font = UMLWidget::font();
+ font.setBold(true);
+ painter->setFont(font);
+ int y = 0;
+ if (!m_umlObject->stereotype().isEmpty()) {
+ painter->drawText(ENTITY_MARGIN, 0,
+ w - ENTITY_MARGIN * 2, fontHeight,
+ Qt::AlignCenter, m_umlObject->stereotype(true));
+ font.setItalic(m_umlObject->isAbstract());
+ painter->setFont(font);
+ painter->drawText(ENTITY_MARGIN, fontHeight,
+ w - ENTITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
+ font.setBold(false);
+ font.setItalic(false);
+ painter->setFont(font);
+ y = fontHeight * 2;
+ } else {
+ font.setItalic(m_umlObject->isAbstract());
+ painter->setFont(font);
+ painter->drawText(ENTITY_MARGIN, 0,
+ w - ENTITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
+ font.setBold(false);
+ font.setItalic(false);
+ painter->setFont(font);
+
+ y = fontHeight;
+ }
+
+ setPenFromSettings(painter);
+
+ painter->drawLine(0, y, w, y);
+
+ QFontMetrics fontMetrics(font);
+ UMLClassifier *classifier = (UMLClassifier*)m_umlObject;
+ UMLClassifierListItem* entityattribute = 0;
+ UMLClassifierListItemList list = classifier->getFilteredList(UMLObject::ot_EntityAttribute);
+ foreach (entityattribute, list) {
+ QString text = entityattribute->name();
+ painter->setPen(textColor());
+ UMLEntityAttribute* casted = dynamic_cast<UMLEntityAttribute*>(entityattribute);
+ if(casted && casted->indexType() == UMLEntityAttribute::Primary)
+ {
+ font.setUnderline(true);
+ painter->setFont(font);
+ font.setUnderline(false);
+ }
+ painter->drawText(ENTITY_MARGIN, y,
+ fontMetrics.width(text), fontHeight, Qt::AlignVCenter, text);
+ painter->setFont(font);
+ y+=fontHeight;
+ }
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Saves to the "entitywidget" XMI element.
+ */
+void EntityWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement conceptElement = qDoc.createElement(QLatin1String("entitywidget"));
+ UMLWidget::saveToXMI(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 EntityWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_EntityAttribute:
+ if (Object_Factory::createChildObject(static_cast<UMLClassifier*>(m_umlObject),
+ UMLObject::ot_EntityAttribute)) {
+ UMLApp::app()->document()->setModified();
+ }
+ break;
+
+ case ListPopupMenu::mt_PrimaryKeyConstraint:
+ case ListPopupMenu::mt_UniqueConstraint:
+ if (UMLObject* obj = Object_Factory::createChildObject(static_cast<UMLEntity*>(m_umlObject),
+ UMLObject::ot_UniqueConstraint)) {
+ UMLApp::app()->document()->setModified();
+
+ if (sel == ListPopupMenu::mt_PrimaryKeyConstraint) {
+ UMLUniqueConstraint* uc = static_cast<UMLUniqueConstraint*>(obj);
+ static_cast<UMLEntity*>(m_umlObject)->setAsPrimaryKey(uc);
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_ForeignKeyConstraint:
+ if (Object_Factory::createChildObject(static_cast<UMLEntity*>(m_umlObject),
+ UMLObject::ot_ForeignKeyConstraint)) {
+ UMLApp::app()->document()->setModified();
+
+ }
+ break;
+
+ case ListPopupMenu::mt_CheckConstraint:
+ if (Object_Factory::createChildObject(static_cast<UMLEntity*>(m_umlObject),
+ UMLObject::ot_CheckConstraint)) {
+ UMLApp::app()->document()->setModified();
+
+ }
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ }
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF EntityWidget::minimumSize() const
+{
+ if (!m_umlObject) {
+ return UMLWidget::minimumSize();
+ }
+
+ int width, height;
+ QFont font = UMLWidget::font();
+ font.setItalic(false);
+ font.setUnderline(false);
+ font.setBold(false);
+ const QFontMetrics fm(font);
+
+ const int fontHeight = fm.lineSpacing();
+
+ int lines = 1;//always have one line - for name
+ if (!m_umlObject->stereotype().isEmpty()) {
+ lines++;
+ }
+
+ const int numberOfEntityAttributes = ((UMLEntity*)m_umlObject)->entityAttributes();
+
+ height = width = 0;
+ //set the height of the entity
+
+ lines += numberOfEntityAttributes;
+ if (numberOfEntityAttributes == 0) {
+ height += fontHeight / 2; //no entity literals, so just add a bit of space
+ }
+
+ height += lines * fontHeight;
+
+ //now set the width of the concept
+ //set width to name to start with
+ // FIXME spaces to get round beastie with font width,
+ // investigate UMLWidget::getFontMetrics()
+ width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(QLatin1Char(' ') + name() +
+ QLatin1Char(' ')).width();
+ const int w = getFontMetrics(FT_BOLD).boundingRect(m_umlObject->stereotype(true)).width();
+
+ width = w > width ? w : width;
+
+ UMLClassifier* classifier = (UMLClassifier*)m_umlObject;
+ UMLClassifierListItemList list = classifier->getFilteredList(UMLObject::ot_EntityAttribute);
+ UMLClassifierListItem* listItem = 0;
+ foreach (listItem, list) {
+ int w = fm.width(listItem->name());
+ width = w > width?w:width;
+ }
+
+ //allow for width margin
+ width += ENTITY_MARGIN * 2;
+
+ return QSizeF(width, height);
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/entitywidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/entitywidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/entitywidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/entitywidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ENTITYWIDGET_H
+#define ENTITYWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLScene;
+
+#define ENTITY_MARGIN 5
+
+/**
+ * Defines a graphical version of the entity. Most of the functionality
+ * will come from the @ref UMLWidget class from which class inherits from.
+ *
+ * @short A graphical version of an entity.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class EntityWidget : public UMLWidget
+{
+ Q_OBJECT
+public:
+ explicit EntityWidget(UMLScene *scene, UMLObject* o);
+ virtual ~EntityWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ // UMLWidget::loadFromXMI is used to load this widget.
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+public Q_SLOTS:
+ virtual void slotMenuSelection(QAction* action);
+
+protected:
+ QSizeF minimumSize() const;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/enumwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/enumwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/enumwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/enumwidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,262 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "enumwidget.h"
+
+// app includes
+#include "classifier.h"
+#include "classifierlistitem.h"
+#include "debug_utils.h"
+#include "enum.h"
+#include "enumliteral.h"
+#include "listpopupmenu.h"
+#include "object_factory.h"
+#include "uml.h"
+#include "umlclassifierlistitemlist.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+/**
+ * Constructs an instance of EnumWidget.
+ *
+ * @param scene The parent of this EnumWidget.
+ * @param o The UMLObject this will be representing.
+ */
+EnumWidget::EnumWidget(UMLScene *scene, UMLObject* o)
+ : UMLWidget(scene, WidgetBase::wt_Enum, o),
+ m_showPackage(false)
+{
+ setSize(100, 30);
+ //set defaults from m_scene
+ if (m_scene) {
+ //check to see if correct
+ const Settings::OptionState& ops = m_scene->optionState();
+ m_showPackage = ops.classState.showPackage;
+ } else {
+ // For completeness only. Not supposed to happen.
+ m_showPackage = false;
+ }
+}
+
+/**
+ * Destructor.
+ */
+EnumWidget::~EnumWidget()
+{
+}
+
+/**
+ * Returns the status of whether to show Package.
+ *
+ * @return True if package is shown.
+ */
+bool EnumWidget::showPackage() const
+{
+ return m_showPackage;
+}
+
+/**
+ * Set the status of whether to show Package.
+ *
+ * @param _status True if package shall be shown.
+ */
+void EnumWidget::setShowPackage(bool _status)
+{
+ m_showPackage = _status;
+ updateGeometry();
+ update();
+}
+
+/**
+ * Toggles the status of whether to show package.
+ */
+void EnumWidget::toggleShowPackage()
+{
+ m_showPackage = !m_showPackage;
+ updateGeometry();
+ update();
+}
+
+/**
+ * Draws the enum as a rectangle with a box underneith with a list of literals
+ * Reimplemented from UMLWidget::paint
+ */
+void EnumWidget::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());
+
+ const int w = width();
+ const int h = height();
+
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ QString name;
+ if (m_showPackage) {
+ name = m_umlObject->fullyQualifiedName();
+ } else {
+ name = this->name();
+ }
+
+ painter->drawRect(0, 0, w, h);
+ painter->setPen(textColor());
+
+ QFont font = UMLWidget::font();
+ font.setBold(true);
+ painter->setFont(font);
+ painter->drawText(ENUM_MARGIN, 0,
+ w - ENUM_MARGIN * 2, fontHeight,
+ Qt::AlignCenter, m_umlObject->stereotype(true));
+
+ font.setItalic(m_umlObject->isAbstract());
+ painter->setFont(font);
+ painter->drawText(ENUM_MARGIN, fontHeight,
+ w - ENUM_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
+ font.setBold(false);
+ font.setItalic(false);
+ painter->setFont(font);
+
+ int y = fontHeight * 2;
+
+ setPenFromSettings(painter);
+
+ painter->drawLine(0, y, w, y);
+
+ QFontMetrics fontMetrics(font);
+ UMLClassifier *classifier = (UMLClassifier*)m_umlObject;
+ UMLClassifierListItem* enumLiteral = 0;
+ UMLClassifierListItemList list = classifier->getFilteredList(UMLObject::ot_EnumLiteral);
+ foreach (enumLiteral, list) {
+ QString text = enumLiteral->name();
+ painter->setPen(textColor());
+ painter->drawText(ENUM_MARGIN, y,
+ fontMetrics.width(text), fontHeight, Qt::AlignVCenter, text);
+ y+=fontHeight;
+ }
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Loads from an "enumwidget" XMI element.
+ */
+bool EnumWidget::loadFromXMI(QDomElement & qElement)
+{
+ if (!UMLWidget::loadFromXMI(qElement)) {
+ return false;
+ }
+ QString showpackage = qElement.attribute(QLatin1String("showpackage"), QLatin1String("0"));
+
+ m_showPackage = (bool)showpackage.toInt();
+
+ return true;
+}
+
+/**
+ * Saves to the "enumwidget" XMI element.
+ */
+void EnumWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement conceptElement = qDoc.createElement(QLatin1String("enumwidget"));
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+
+ conceptElement.setAttribute(QLatin1String("showpackage"), m_showPackage);
+ 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 EnumWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ if (sel == ListPopupMenu::mt_EnumLiteral) {
+ if (Object_Factory::createChildObject(static_cast<UMLClassifier*>(m_umlObject),
+ UMLObject::ot_EnumLiteral)) {
+ /* I don't know why it works without these calls:
+ updateComponentSize();
+ update();
+ */
+ UMLApp::app()->document()->setModified();
+ }
+ return;
+ }
+ UMLWidget::slotMenuSelection(action);
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF EnumWidget::minimumSize() const
+{
+ if (!m_umlObject) {
+ return UMLWidget::minimumSize();
+ }
+
+ int width, height;
+ QFont font = UMLWidget::font();
+ font.setItalic(false);
+ font.setUnderline(false);
+ font.setBold(false);
+ const QFontMetrics fm(font);
+
+ const int fontHeight = fm.lineSpacing();
+
+ int lines = 1;//always have one line - for name
+ lines++; //for the stereotype
+
+ const int numberOfEnumLiterals = ((UMLEnum*)m_umlObject)->enumLiterals();
+
+ height = width = 0;
+ //set the height of the enum
+
+ lines += numberOfEnumLiterals;
+ if (numberOfEnumLiterals == 0) {
+ height += fontHeight / 2; //no enum literals, so just add a bit of space
+ }
+
+ height += lines * fontHeight;
+
+ //now set the width of the concept
+ //set width to name to start with
+ if (m_showPackage) {
+ width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(m_umlObject->fullyQualifiedName()).width();
+ } else {
+ width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(name()).width();
+ }
+ int w = getFontMetrics(FT_BOLD).boundingRect(m_umlObject->stereotype(true)).width();
+
+
+ width = w > width?w:width;
+
+ UMLClassifier *classifier = (UMLClassifier*)m_umlObject;
+ UMLClassifierListItemList list = classifier->getFilteredList(UMLObject::ot_EnumLiteral);
+ UMLClassifierListItem* listItem = 0;
+ foreach (listItem, list) {
+ int w = fm.width(listItem->name());
+ width = w > width?w:width;
+ }
+
+ //allow for width margin
+ width += ENUM_MARGIN * 2;
+
+ return QSizeF(width, height);
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/enumwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/enumwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/enumwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/enumwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef ENUMWIDGET_H
+#define ENUMWIDGET_H
+
+#include "umlwidget.h"
+
+#define ENUM_MARGIN 5
+
+/**
+ * Defines a graphical version of the enum. Most of the functionality
+ * will come from the @ref UMLWidget class from which class inherits from.
+ *
+ * @short A graphical version of an enum.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class EnumWidget : public UMLWidget
+{
+ Q_OBJECT
+public:
+ explicit EnumWidget(UMLScene *scene, UMLObject* o);
+ virtual ~EnumWidget();
+
+ bool showPackage() const;
+ void setShowPackage(bool _status);
+ void toggleShowPackage();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ virtual bool loadFromXMI(QDomElement& qElement);
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+public Q_SLOTS:
+ virtual void slotMenuSelection(QAction* action);
+
+protected:
+ QSizeF minimumSize() const;
+
+ bool m_showPackage;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/floatingdashlinewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/floatingdashlinewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/floatingdashlinewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/floatingdashlinewidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,199 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+// own header
+#include "floatingdashlinewidget.h"
+#include "combinedfragmentwidget.h"
+
+//kde includes
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+#include <KLocalizedString>
+
+//app includes
+#include "debug_utils.h"
+#include "umlview.h"
+#include "widget_utils.h"
+#include "listpopupmenu.h"
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+#include <QPainter>
+
+DEBUG_REGISTER_DISABLED(FloatingDashLineWidget)
+
+/**
+ * Creates a floating dash line.
+ * @param scene The parent of the widget
+ * @param id The ID to assign (-1 will prompt a new ID)
+ * @param parent The CombinedFragmentWidget which acts as the parent
+ */
+FloatingDashLineWidget::FloatingDashLineWidget(UMLScene * scene, Uml::ID::Type id, CombinedFragmentWidget *parent)
+ : UMLWidget(scene, WidgetBase::wt_FloatingDashLine, id),
+ m_yMin(0),
+ m_yMax(0),
+ m_parent(parent)
+{
+ m_resizable = false;
+ m_Text = QString();
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ setSize(10, fontHeight);
+}
+
+/**
+ * Destructor.
+ */
+FloatingDashLineWidget::~FloatingDashLineWidget()
+{
+ if (m_parent)
+ m_parent->removeDashLine(this);
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void FloatingDashLineWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ painter->setPen(textColor());
+ painter->setFont(UMLWidget::font());
+ painter->drawText(FLOATING_DASH_LINE_TEXT_MARGIN, 0,
+ width() - FLOATING_DASH_LINE_TEXT_MARGIN * 2, fontHeight,
+ Qt::AlignLeft, QLatin1Char('[') + m_Text + QLatin1Char(']'));
+ painter->setPen(QPen(UMLWidget::lineColor(), 0, Qt::DashLine));
+ painter->drawLine(0, 0, width(), 0);
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Sets m_text.
+ */
+void FloatingDashLineWidget::setText(const QString& text)
+{
+ m_Text = text;
+}
+
+/**
+ * Returns true if the given point is near the floatingdashline.
+ */
+bool FloatingDashLineWidget::onLine(const QPointF& point)
+{
+ // check if the given point is the start or end point of the line
+ if (((abs((long)(y() + height() - point.y()))) <= POINT_DELTA) || (abs((long)(y() - point.y())) <= POINT_DELTA)) {
+ return true;
+ }
+ // check if the given point is the start or end point of the line
+ return false;
+}
+
+void FloatingDashLineWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_Rename:
+ {
+ bool ok = false;
+ QString name = m_Text;
+#if QT_VERSION >= 0x050000
+ name = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter alternative Name"), i18n("Enter the alternative:"),
+ QLineEdit::Normal,
+ m_Text, &ok);
+#else
+ name = KInputDialog::getText(i18n("Enter alternative Name"), i18n("Enter the alternative:"), m_Text, &ok);
+#endif
+ if (ok && name.length() > 0)
+ m_Text = name;
+ }
+ break;
+ default:
+ UMLWidget::slotMenuSelection(action);
+ }
+}
+
+/**
+ * Overrides the setY method.
+ */
+void FloatingDashLineWidget::setY(qreal y)
+{
+ if(y >= m_yMin + FLOATING_DASH_LINE_MARGIN && y <= m_yMax - FLOATING_DASH_LINE_MARGIN)
+ UMLWidget::setY(y);
+}
+
+/**
+ * Sets m_yMin.
+ */
+void FloatingDashLineWidget::setYMin(qreal yMin)
+{
+ m_yMin = yMin;
+}
+
+/**
+ * Sets m_yMax.
+ */
+void FloatingDashLineWidget::setYMax(qreal yMax)
+{
+ m_yMax = yMax;
+}
+
+/**
+ * Returns m_yMin.
+ */
+qreal FloatingDashLineWidget::getYMin() const
+{
+ return m_yMin;
+}
+
+/**
+ * Returns the difference between the y-coordinate of the dash line and m_yMin.
+ */
+qreal FloatingDashLineWidget::getDiffY() const
+{
+ return (y() - getYMin());
+}
+
+/**
+ * Creates the "floatingdashline" XMI element.
+ */
+void FloatingDashLineWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement textElement = qDoc.createElement(QLatin1String("floatingdashlinewidget"));
+ UMLWidget::saveToXMI(qDoc, textElement);
+ textElement.setAttribute(QLatin1String("text"), m_Text);
+ textElement.setAttribute(QLatin1String("y"), y());
+ textElement.setAttribute(QLatin1String("minY"), m_yMin);
+ textElement.setAttribute(QLatin1String("maxY"), m_yMax);
+
+ qElement.appendChild(textElement);
+}
+
+/**
+ * Loads the "floatingdashline" XMI element.
+ */
+bool FloatingDashLineWidget::loadFromXMI(QDomElement & qElement)
+{
+ if(!UMLWidget::loadFromXMI(qElement)) {
+ return false;
+ }
+ DEBUG(DBG_SRC) << "load.......";
+ m_yMax = qElement.attribute(QLatin1String("maxY")).toFloat();
+ m_yMin = qElement.attribute(QLatin1String("minY")).toFloat();
+ m_Text = qElement.attribute(QLatin1String("text"));
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/floatingdashlinewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/floatingdashlinewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/floatingdashlinewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/floatingdashlinewidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,77 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef FLOATINGDASHLINEWIDGET_H
+#define FLOATINGDASHLINEWIDGET_H
+
+#include "umlwidget.h"
+class CombinedFragmentWidget;
+
+#define FLOATING_DASH_LINE_MARGIN 25
+#define FLOATING_DASH_LINE_TEXT_MARGIN 5
+
+/* how many pixels a user could click around a point */
+#define POINT_DELTA 5
+
+/**
+ * This class is used to draw dash lines for UML combined fragments. A FloatingDashLineWidget
+ * belongs to one @ref CombinedFragmentWidget instance.
+ *
+ * The FloatingDashLineWidget class inherits from the @ref UMLWidget class.
+ *
+ * @short A dash line for UML combined fragments.
+ * @author Thomas GALLINARI <tg8187@yahoo.fr>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class FloatingDashLineWidget : public UMLWidget
+{
+ Q_OBJECT
+public:
+ explicit FloatingDashLineWidget(UMLScene * scene, Uml::ID::Type id = Uml::ID::None, CombinedFragmentWidget *parent = 0);
+ ~FloatingDashLineWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option = 0, QWidget *widget = 0);
+
+ void slotMenuSelection(QAction* action);
+
+ bool onLine(const QPointF& point);
+
+ void setText(const QString& text);
+
+ void setY(qreal y);
+ void setYMin(qreal yMin);
+ void setYMax(qreal yMax);
+ qreal getYMin() const;
+ qreal getDiffY() const;
+
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+ bool loadFromXMI(QDomElement & qElement);
+
+private:
+ /**
+ * Text associated to the dash line
+ */
+ QString m_text;
+
+ /**
+ * Minimum value of the Y-coordinate of the dash line
+ * (= y-coordinate of the combined fragment)
+ */
+ int m_yMin;
+
+ /**
+ * Maximum value of the Y-coordinate of the dash line
+ * (= y-coordinate of the combined fragment + height of the combined fragment)
+ */
+ int m_yMax;
+ CombinedFragmentWidget *m_parent;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/floatingtextwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/floatingtextwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/floatingtextwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/floatingtextwidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,854 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "floatingtextwidget.h"
+
+// local includes
+#include "association.h"
+#include "associationwidget.h"
+#include "associationpropertiesdialog.h"
+#include "classifier.h"
+#include "cmds.h"
+#include "debug_utils.h"
+#include "linkwidget.h"
+#include "classifierwidget.h"
+#include "listpopupmenu.h"
+#include "messagewidget.h"
+#include "model_utils.h"
+#include "object_factory.h"
+#include "operation.h"
+#include "selectoperationdialog.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+
+// kde includes
+#if QT_VERSION < 0x050000
+#include <kfontdialog.h>
+#include <kinputdialog.h>
+#endif
+#include <KLocalizedString>
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QFontDialog>
+#include <QInputDialog>
+#endif
+#include <QPointer>
+#include <QRegExp>
+#include <QPainter>
+#include <QValidator>
+
+DEBUG_REGISTER_DISABLED(FloatingTextWidget)
+
+/**
+ * Constructs a FloatingTextWidget instance.
+ *
+ * @param scene The parent of this FloatingTextWidget.
+ * @param role The role this FloatingTextWidget will take up.
+ * @param text The main text to display.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+FloatingTextWidget::FloatingTextWidget(UMLScene * scene, Uml::TextRole::Enum role, const QString& text, Uml::ID::Type id)
+ : UMLWidget(scene, WidgetBase::wt_Text, id),
+ m_linkWidget(0),
+ m_preText(QString()),
+ m_postText(QString()),
+ m_textRole(role),
+ m_unconstrainedPositionX(0),
+ m_unconstrainedPositionY(0),
+ m_movementDirectionX(0),
+ m_movementDirectionY(0)
+{
+ m_Text = text;
+ m_resizable = false;
+ setZValue(10); //make sure always on top.
+}
+
+/**
+ * Destructor.
+ */
+FloatingTextWidget::~FloatingTextWidget()
+{
+}
+
+/**
+ * Use to get the _main body_ of text (e.g. prepended and appended
+ * text is omitted) as currently displayed by the widget.
+ *
+ * @return The main text currently being displayed by the widget.
+ */
+QString FloatingTextWidget::text() const
+{
+ // test to make sure not just the ":" between the seq number and
+ // the actual message widget
+
+ // hmm. this section looks like it could have been avoided by
+ // using pre-, post- text instead of storing in the main body of
+ // the text -b.t.
+ if (m_textRole == Uml::TextRole::Seq_Message || m_textRole == Uml::TextRole::Seq_Message_Self ||
+ m_textRole == Uml::TextRole::Coll_Message || m_textRole == Uml::TextRole::Coll_Message_Self) {
+ if (m_Text.length() <= 1 || m_Text == QLatin1String(": "))
+ return QString();
+ }
+ return m_Text;
+}
+
+/**
+ * Set the main body of text to display.
+ *
+ * @param t The text to display.
+ */
+void FloatingTextWidget::setText(const QString &t)
+{
+ if (m_textRole == Uml::TextRole::Seq_Message || m_textRole == Uml::TextRole::Seq_Message_Self) {
+ QString op;
+ if (m_linkWidget)
+ op = m_linkWidget->lwOperationText();
+ if (op.length() > 0) {
+ if (!m_scene->showOpSig())
+ op.replace(QRegExp(QLatin1String("\\(.*\\)")), QLatin1String("()"));
+ m_Text = op;
+ }
+ else
+ m_Text = t;
+ }
+ else {
+ m_Text = t;
+ }
+
+ QSizeF s = minimumSize();
+ setSize(s.width(), s.height());
+
+ updateGeometry();
+ update();
+}
+
+/**
+ * Set some text to be prepended to the main body of text.
+ * @param t The text to prepend to main body which is displayed.
+ */
+void FloatingTextWidget::setPreText(const QString &t)
+{
+ m_preText = t;
+ updateGeometry();
+ update();
+}
+
+/**
+ * Set some text to be appended to the main body of text.
+ * @param t The text to append to main body which is displayed.
+ */
+void FloatingTextWidget::setPostText(const QString &t)
+{
+ m_postText = t;
+ updateGeometry();
+ update();
+}
+
+/**
+ * Use to get the total text (prepended + main body + appended)
+ * currently displayed by the widget.
+ *
+ * @return The text currently being displayed by the widget.
+ */
+QString FloatingTextWidget::displayText() const
+{
+ QString displayText;
+ if (!m_SequenceNumber.isEmpty())
+ displayText = m_SequenceNumber + QLatin1String(": ") + m_Text;
+ else
+ displayText = m_Text;
+ displayText.prepend(m_preText);
+ displayText.append(m_postText);
+ return displayText;
+}
+
+/**
+ * Return state if no pre, post and main text is empty
+ * @return true if widget contains no text
+ */
+bool FloatingTextWidget::isEmpty()
+{
+ return m_Text.isEmpty() && m_preText.isEmpty() && m_postText.isEmpty();
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF FloatingTextWidget::minimumSize() const
+{
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ int h = fm.lineSpacing();
+ int w = fm.width(displayText());
+ return QSizeF(w + 8, h + 4); // give a small margin
+}
+
+/**
+ * Method used by setText: its called by cmdsetTxt, Don't use it!
+ *
+ * @param t The text to display.
+ */
+void FloatingTextWidget::setTextcmd(const QString &t)
+{
+ UMLApp::app()->executeCommand(new Uml::CmdSetTxt(this, t));
+}
+
+/**
+ * Displays a dialog box to change the text.
+ */
+void FloatingTextWidget::showChangeTextDialog()
+{
+ bool ok = false;
+#if QT_VERSION >= 0x050000
+ QString newText = QInputDialog::getText(m_scene->activeView(),
+ i18n("Change Text"), i18n("Enter new text:"),
+ QLineEdit::Normal,
+ text(), &ok);
+#else
+ QString newText = KInputDialog::getText(i18n("Change Text"), i18n("Enter new text:"), text(), &ok, m_scene->activeView());
+#endif
+ if (ok && newText != text() && isTextValid(newText)) {
+ setText(newText);
+ setVisible(!text().isEmpty());
+ updateGeometry();
+ update();
+ }
+ if (!isTextValid(newText))
+ hide();
+}
+
+/**
+ * Shows an operation dialog box.
+ *
+ * @param enableAutoIncrement Enable auto increment checkbox
+ */
+void FloatingTextWidget::showOperationDialog(bool enableAutoIncrement)
+{
+ if (!m_linkWidget) {
+ uError() << "m_linkWidget is NULL";
+ return;
+ }
+ QString seqNum = m_linkWidget->sequenceNumber();
+ UMLClassifier* c = m_linkWidget->lwClassifier();
+ QString opText = m_linkWidget->lwOperationText();
+ if (!c) {
+ uError() << "m_linkWidget->lwClassifier() returns a NULL classifier";
+ return;
+ }
+
+ QPointer<SelectOperationDialog> selectDialog = new SelectOperationDialog(m_scene->activeView(), c, enableAutoIncrement);
+ if (enableAutoIncrement && m_scene->autoIncrementSequence()) {
+ seqNum = m_scene->autoIncrementSequenceValue();
+ selectDialog->setAutoIncrementSequence(true);
+ }
+ selectDialog->setSeqNumber(seqNum);
+ if (m_linkWidget->operation() == 0) {
+ selectDialog->setCustomOp(opText);
+ } else {
+ selectDialog->setClassOp(opText);
+ }
+ if (selectDialog->exec()) {
+ seqNum = selectDialog->getSeqNumber();
+ opText = selectDialog->getOpText();
+ if (selectDialog->isClassOp()) {
+ Model_Utils::OpDescriptor od;
+ Model_Utils::Parse_Status st = Model_Utils::parseOperation(opText, od, c);
+ if (st == Model_Utils::PS_OK) {
+ UMLClassifierList selfAndAncestors = c->findSuperClassConcepts();
+ selfAndAncestors.prepend(c);
+ UMLOperation *op = 0;
+ foreach (UMLClassifier *cl, selfAndAncestors) {
+ op = cl->findOperation(od.m_name, od.m_args);
+ if (op) {
+ break;
+ }
+ }
+ if (!op) {
+ // The op does not yet exist. Create a new one.
+ UMLObject *o = c->createOperation(od.m_name, 0, &od.m_args);
+ op = static_cast<UMLOperation*>(o);
+ }
+ if (od.m_pReturnType) {
+ op->setType(od.m_pReturnType);
+ }
+
+ m_linkWidget->setOperation(op);
+ opText.clear();
+ } else {
+ m_linkWidget->setOperation(0);
+ }
+ } else {
+ m_linkWidget->setOperation(0);
+ }
+ m_linkWidget->setSequenceNumber(seqNum);
+ m_linkWidget->setOperationText(opText);
+ if (enableAutoIncrement) {
+ m_scene->setAutoIncrementSequence(selectDialog->autoIncrementSequence());
+ }
+ setMessageText();
+ }
+ delete selectDialog;
+}
+
+/**
+ * Show the properties for a FloatingTextWidget.
+ * Depending on the role of the floating text wiget, the options dialog
+ * for the floating text widget, the rename dialog for floating text or
+ * the options dialog for the link widget are shown.
+ */
+void FloatingTextWidget::showPropertiesDialog()
+{
+ if (m_textRole == Uml::TextRole::Coll_Message || m_textRole == Uml::TextRole::Coll_Message_Self ||
+ m_textRole == Uml::TextRole::Seq_Message || m_textRole == Uml::TextRole::Seq_Message_Self) {
+ showOperationDialog(false);
+ } else if (m_textRole == Uml::TextRole::Floating) {
+ // double clicking on a text line opens the dialog to change the text
+ handleRename();
+ } else if (m_linkWidget) {
+ m_linkWidget->showPropertiesDialog();
+ }
+}
+
+/**
+ * Use to get the pre-text which is prepended to the main body of
+ * text to be displayed.
+ *
+ * @return The pre-text currently displayed by the widget.
+ */
+QString FloatingTextWidget::preText() const
+{
+ return m_preText;
+}
+
+/**
+ * Use to get the post-text which is appended to the main body of
+ * text to be displayed.
+ *
+ * @return The post-text currently displayed by the widget.
+ */
+QString FloatingTextWidget::postText() const
+{
+ return m_postText;
+}
+
+/**
+ * Activate the FloatingTextWidget after the saved data has been loaded
+ *
+ * @param ChangeLog Pointer to the IDChangeLog.
+ * @return true for success
+ */
+bool FloatingTextWidget::activate(IDChangeLog* ChangeLog /*= 0 */)
+{
+ if (! UMLWidget::activate(ChangeLog))
+ return false;
+ update();
+ return true;
+}
+
+/**
+ * Set the LinkWidget that this FloatingTextWidget is related to.
+ *
+ * @param l The related LinkWidget.
+ */
+void FloatingTextWidget::setLink(LinkWidget * l)
+{
+ m_linkWidget = l;
+}
+
+/**
+ * Returns the LinkWidget this floating text is related to.
+ *
+ * @return The LinkWidget this floating text is related to.
+ */
+LinkWidget * FloatingTextWidget::link() const
+{
+ return m_linkWidget;
+}
+
+/**
+ * Sets the role type of this FloatingTextWidget.
+ *
+ * @param role The TextRole::Enum of this FloatingTextWidget.
+ */
+void FloatingTextWidget::setTextRole(Uml::TextRole::Enum role)
+{
+ m_textRole = role;
+}
+
+/**
+ * Return the role of the text widget
+ * @return The TextRole::Enum of this FloatingTextWidget.
+ */
+Uml::TextRole::Enum FloatingTextWidget::textRole() const
+{
+ return m_textRole;
+}
+
+/**
+ * Handle the ListPopupMenu::mt_Rename case of the slotMenuSelection.
+ * Given an own method because it requires rather lengthy code.
+ */
+void FloatingTextWidget::handleRename()
+{
+ QRegExpValidator v(QRegExp(QLatin1String(".*")), 0);
+ QString t;
+ if (m_textRole == Uml::TextRole::RoleAName || m_textRole == Uml::TextRole::RoleBName) {
+ t = i18n("Enter role name:");
+ } else if (m_textRole == Uml::TextRole::MultiA || m_textRole == Uml::TextRole::MultiB) {
+ t = i18n("Enter multiplicity:");
+ /*
+ // NO! shouldn't be allowed
+ } else if (m_textRole == Uml::TextRole::ChangeA || m_textRole == Uml::TextRole::ChangeB) {
+ t = i18n("Enter changeability");
+ */
+ } else if (m_textRole == Uml::TextRole::Name) {
+ t = i18n("Enter association name:");
+ } else if (m_textRole == Uml::TextRole::Floating) {
+ t = i18n("Enter new text:");
+ } else {
+ t = i18n("ERROR");
+ }
+ bool ok = false;
+#if QT_VERSION >= 0x050000
+ QString newText = QInputDialog::getText(m_scene->activeView(),
+ i18n("Rename"), t,
+ QLineEdit::Normal,
+ text(), &ok);
+#else
+ QString newText = KInputDialog::getText(i18n("Rename"), t, text(), &ok, m_scene->activeView(), &v);
+#endif
+ if (!ok || newText == text()) {
+ return;
+ }
+
+ UMLApp::app()->executeCommand(new Uml::CmdHandleRename(this, newText));
+}
+
+/**
+ * Changes the text of linked widget.
+ * @param newText the new text
+ */
+void FloatingTextWidget::changeName(const QString& newText)
+{
+ if (m_linkWidget && !isTextValid(newText)) {
+ AssociationWidget *assoc = dynamic_cast<AssociationWidget*>(m_linkWidget);
+ if (assoc) {
+ switch (m_textRole) {
+ case Uml::TextRole::MultiA:
+ assoc->setMultiplicity(QString(), Uml::RoleType::A);
+ break;
+ case Uml::TextRole::MultiB:
+ assoc->setMultiplicity(QString(), Uml::RoleType::B);
+ break;
+ case Uml::TextRole::RoleAName:
+ assoc->setRoleName(QString(), Uml::RoleType::A);
+ break;
+ case Uml::TextRole::RoleBName:
+ assoc->setRoleName(QString(), Uml::RoleType::B);
+ break;
+ case Uml::TextRole::ChangeA:
+ assoc->setChangeability(Uml::Changeability::Changeable, Uml::RoleType::A);
+ break;
+ case Uml::TextRole::ChangeB:
+ assoc->setChangeability(Uml::Changeability::Changeable, Uml::RoleType::B);
+ break;
+ default:
+ assoc->setName(QString());
+ break;
+ }
+ }
+ else {
+ MessageWidget *msg = dynamic_cast<MessageWidget*>(m_linkWidget);
+ if (msg) {
+ msg->setName(QString());
+ m_scene->removeWidget(this);
+ }
+ }
+ return;
+ }
+
+ if (m_linkWidget && m_textRole != Uml::TextRole::Seq_Message
+ && m_textRole != Uml::TextRole::Seq_Message_Self) {
+ m_linkWidget->setText(this, newText);
+ }
+ else {
+ setText(newText);
+ UMLApp::app()->document()->setModified(true);
+ }
+
+ setVisible(true);
+ updateGeometry();
+ update();
+}
+
+/**
+ * Write property of QString m_SequenceNumber.
+ */
+void FloatingTextWidget::setSequenceNumber(const QString &sequenceNumber)
+{
+ m_SequenceNumber = sequenceNumber;
+}
+
+/**
+ * Read property of QString m_SequenceNumber.
+ */
+QString FloatingTextWidget::sequenceNumber() const
+{
+ return m_SequenceNumber;
+}
+
+/**
+ * For a text to be valid it must be non-empty, i.e. have a length
+ * larger than zero, and have at least one non whitespace character.
+ *
+ * @param text The string to analyze.
+ * @return True if the given text is valid.
+ */
+bool FloatingTextWidget::isTextValid(const QString &text)
+{
+ int length = text.length();
+ if(length < 1)
+ return false;
+ for(int i=0;i<length;i++) {
+ if(!text.at(i).isSpace()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Returns a constrained position for the widget after applying the position
+ * difference.
+ * If no link widget exists, the position returned is the current widget
+ * position with the difference applied. If there's a link, the position
+ * to be returned is constrained using constrainTextPos method from the
+ * LinkWidget, if any.
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ * @return A QPointF with the constrained new position.
+ */
+QPointF FloatingTextWidget::constrainPosition(qreal diffX, qreal diffY)
+{
+ qreal newX = x() + diffX;
+ qreal newY = y() + diffY;
+
+ if (link()) {
+ link()->constrainTextPos(newX, newY, width(), height(), textRole());
+ }
+
+ return QPointF(newX, newY);
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Moves the widget to a new position using the difference between the
+ * current position and the new position.
+ * If the floating text widget is part of a sequence message, and the
+ * message widget is selected, it does nothing: the message widget will
+ * update the text position when it's moved.
+ * In any other case, the floating text widget constrains its move using
+ * constrainPosition. When the position of the floating text is constrained,
+ * it's kept at that position until it can be moved to another valid
+ * position (m_unconstrainedPositionX/Y and m_movementDirectionX/Y are
+ * used for that).
+ * Moreover, if is part of a sequence message (and the message widget
+ * isn't selected), it updates the position of the message widget.
+ * @see constrainPosition
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+void FloatingTextWidget::moveWidgetBy(qreal diffX, qreal diffY)
+{
+ if (textRole() == Uml::TextRole::Seq_Message_Self)
+ return;
+
+ if (textRole() == Uml::TextRole::Seq_Message
+ && ((MessageWidget*)link())->isSelected()) {
+ return;
+ }
+
+ m_unconstrainedPositionX += diffX;
+ m_unconstrainedPositionY += diffY;
+ QPointF constrainedPosition = constrainPosition(diffX, diffY);
+
+ qreal newX = constrainedPosition.x();
+ qreal newY = constrainedPosition.y();
+
+ if (!m_movementDirectionX) {
+ if (m_unconstrainedPositionX != constrainedPosition.x()) {
+ m_movementDirectionX = (diffX > 0)? 1: -1;
+ }
+ } else if ((m_movementDirectionX < 0 && m_unconstrainedPositionX > x()) ||
+ (m_movementDirectionX > 0 && m_unconstrainedPositionX < x()) ) {
+ newX = m_unconstrainedPositionX;
+ m_movementDirectionX = 0;
+ }
+
+ if (!m_movementDirectionY) {
+ if (m_unconstrainedPositionY != constrainedPosition.y()) {
+ m_movementDirectionY = (diffY > 0)? 1: -1;
+ }
+ } else if ((m_movementDirectionY < 0 && m_unconstrainedPositionY > y()) ||
+ (m_movementDirectionY > 0 && m_unconstrainedPositionY < y()) ) {
+ newY = m_unconstrainedPositionY;
+ m_movementDirectionY = 0;
+ }
+
+ setX(newX);
+ setY(newY);
+
+ if (link()) {
+ link()->calculateNameTextSegment();
+ if (textRole() == Uml::TextRole::Seq_Message) {
+ MessageWidget* messageWidget = (MessageWidget*)link();
+ messageWidget->setY(newY + height());
+ }
+ }
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Modifies the value of the diffX and diffY variables used to move the
+ * widgets.
+ * The values are constrained using constrainPosition.
+ * @see constrainPosition
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+void FloatingTextWidget::constrainMovementForAllWidgets(qreal &diffX, qreal &diffY)
+{
+ QPointF constrainedPosition = constrainPosition(diffX, diffY);
+
+ diffX = constrainedPosition.x() - x();
+ diffY = constrainedPosition.y() - y();
+}
+
+/**
+ * Override method from UMLWidget in order to additionally check widget parentage.
+ *
+ * @param p Point to be checked.
+ *
+ * @return 'this' if UMLWidget::onWidget(p) returns non NULL;
+ * else NULL.
+ */
+UMLWidget* FloatingTextWidget::onWidget(const QPointF &p)
+{
+ WidgetBase *pw = dynamic_cast<WidgetBase*>(parentItem());
+ if (pw == NULL) {
+ return WidgetBase::onWidget(p);
+ }
+ const WidgetBase::WidgetType t = pw->baseType();
+ bool isWidgetChild = false;
+ if (t == WidgetBase::wt_Interface) {
+ ClassifierWidget *cw = static_cast<ClassifierWidget*>(pw);
+ isWidgetChild = cw->getDrawAsCircle();
+ } else if (t == wt_Association ||
+ t == WidgetBase::wt_Port || t == WidgetBase::wt_Pin) {
+ isWidgetChild = true;
+ }
+ if (!isWidgetChild) {
+ return WidgetBase::onWidget(p);
+ }
+ const qreal w = width();
+ const qreal h = height();
+ const qreal left = pw->x() + x();
+ const qreal right = left + w;
+ const qreal top = pw->y() + y();
+ const qreal bottom = top + h;
+ // uDebug() << "child_of_pw; p=(" << p.x() << "," << p.y() << "), "
+ // << "x=" << left << ", y=" << top << ", w=" << w << ", h=" << h
+ // << "; right=" << right << ", bottom=" << bottom;
+ if (p.x() >= left && p.x() <= right &&
+ p.y() >= top && p.y() <= bottom) { // Qt coord.sys. origin in top left corner
+ // uDebug() << "floatingtext: " << m_Text;
+ return this;
+ }
+ return NULL;
+}
+
+/**
+ * Overrides default method
+ */
+void FloatingTextWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ int w = width();
+ int h = height();
+ painter->setFont(UMLWidget::font());
+ painter->setPen(textColor());
+ painter->drawText(0, 0, w, h, Qt::AlignCenter, displayText());
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Loads the "floatingtext" XMI element.
+ */
+bool FloatingTextWidget::loadFromXMI(QDomElement & qElement)
+{
+ if(!UMLWidget::loadFromXMI(qElement))
+ return false;
+
+ m_unconstrainedPositionX = x();
+ m_unconstrainedPositionY = y();
+ QString role = qElement.attribute(QLatin1String("role"));
+ if(!role.isEmpty())
+ m_textRole = Uml::TextRole::fromInt(role.toInt());
+
+ m_preText = qElement.attribute(QLatin1String("pretext"));
+ m_postText = qElement.attribute(QLatin1String("posttext"));
+ setText(qElement.attribute(QLatin1String("text"))); // use setText for geometry update
+ // If all texts are empty then this is a useless widget.
+ // In that case we return false.
+ // CAVEAT: The caller should not interpret the false return value
+ // as an indication of failure since previous umbrello-kf6 versions
+ // saved lots of these empty FloatingTexts.
+ bool usefulWidget = !isEmpty();
+ return usefulWidget;
+}
+
+/**
+ * Reimplemented from UMLWidget::saveToXMI to save the widget
+ * data into XMI 'floatingtext' element.
+ */
+void FloatingTextWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ if (isEmpty())
+ return;
+
+ QDomElement textElement = qDoc.createElement(QLatin1String("floatingtext"));
+ UMLWidget::saveToXMI(qDoc, textElement);
+ textElement.setAttribute(QLatin1String("text"), m_Text);
+ textElement.setAttribute(QLatin1String("pretext"), m_preText);
+ textElement.setAttribute(QLatin1String("posttext"), m_postText);
+
+ /* No need to save these - the messagewidget already did it.
+ m_Operation = qElement.attribute("operation");
+ m_SeqNum = qElement.attribute("seqnum");
+ */
+
+ textElement.setAttribute(QLatin1String("role"), m_textRole);
+ qElement.appendChild(textElement);
+}
+
+/**
+ * Called when a menu selection has been made.
+ *
+ * @param action The action that has been selected.
+ */
+void FloatingTextWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_Properties:
+ showPropertiesDialog();
+ break;
+
+ case ListPopupMenu::mt_Delete:
+ hide(); // This is only a workaround; if set then m_linkWidget should
+ // really delete this FloatingTextWidget.
+ update();
+ m_scene->removeWidget(this);
+ break;
+
+ case ListPopupMenu::mt_New_Operation: // needed by AssociationWidget
+ case ListPopupMenu::mt_Operation:
+ {
+ if (m_linkWidget == 0) {
+ DEBUG(DBG_SRC) << "mt_Operation: m_linkWidget is NULL";
+ return;
+ }
+ UMLClassifier* c = m_linkWidget->operationOwner();
+ if (c == 0) {
+ bool ok = false;
+#if QT_VERSION >= 0x050000
+ QString opText = QInputDialog::getText(m_scene->activeView(),
+ i18nc("operation name", "Name"),
+ i18n("Enter operation name:"),
+ QLineEdit::Normal,
+ text(), &ok);
+#else
+ QString opText = KInputDialog::getText(i18nc("operation name", "Name"),
+ i18n("Enter operation name:"),
+ text(), &ok, m_scene->activeView());
+#endif
+ if (ok)
+ m_linkWidget->setCustomOpText(opText);
+ return;
+ }
+ UMLClassifierListItem* umlObj = Object_Factory::createChildObject(c, UMLObject::ot_Operation);
+ if (umlObj) {
+ UMLOperation* newOperation = static_cast<UMLOperation*>(umlObj);
+ m_linkWidget->setOperation(newOperation);
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Select_Operation:
+ showOperationDialog(false);
+ break;
+
+ case ListPopupMenu::mt_Rename:
+ handleRename();
+ break;
+
+ case ListPopupMenu::mt_Change_Font:
+ {
+#if QT_VERSION >= 0x050000
+ bool ok = false;
+ QFont fnt = QFontDialog::getFont(&ok, font(), m_scene->activeView());
+ if (ok) {
+#else
+ QFont fnt = font();
+ if(KFontDialog::getFont(fnt, KFontChooser::NoDisplayFlags, m_scene->activeView())) {
+#endif
+ if(m_textRole == Uml::TextRole::Floating || m_textRole == Uml::TextRole::Seq_Message) {
+ setFont(fnt);
+ } else if (m_linkWidget) {
+ m_linkWidget->lwSetFont(fnt);
+ }
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Reset_Label_Positions:
+ if (m_linkWidget)
+ m_linkWidget->resetTextPositions();
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ break;
+ }//end switch
+}
+
+/**
+ * Sets the text for this label if it is acting as a sequence diagram
+ * message or a collaboration diagram message.
+ */
+void FloatingTextWidget::setMessageText()
+{
+ if (m_linkWidget) {
+ m_linkWidget->setMessageText(this);
+ QSizeF s = minimumSize();
+ setSize(s.width(), s.height());
+
+ }
+ setVisible(!text().isEmpty());
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/floatingtextwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/floatingtextwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/floatingtextwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/floatingtextwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,131 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef FLOATINGTEXTWIDGET_H
+#define FLOATINGTEXTWIDGET_H
+
+#include "basictypes.h"
+#include "umlwidget.h"
+
+class LinkWidget;
+class UMLScene;
+
+/**
+ * @short Displays a line of text or an operation.
+ *
+ * This is a multipurpose-kf6 class. In its simplest form it will display a
+ * line of text.
+ * It can also be setup to be the text for an operation with regard to the
+ * @ref MessageWidget on the sequence diagram.
+ * It is also used for the text required for an association.
+ *
+ * The differences between all these different uses will be the popup menu
+ * that is associated with it.
+ *
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class FloatingTextWidget : public UMLWidget
+{
+ Q_OBJECT
+public:
+ explicit FloatingTextWidget(UMLScene * scene, Uml::TextRole::Enum role = Uml::TextRole::Floating,
+ const QString& text = QString(), Uml::ID::Type id = Uml::ID::None);
+ virtual ~FloatingTextWidget();
+
+ QString text() const;
+ void setText(const QString &t);
+
+ void setTextcmd(const QString &t);
+
+ QString preText() const;
+ void setPreText(const QString &t);
+
+ QString postText() const;
+ void setPostText(const QString &t);
+
+ QString displayText() const;
+
+ bool isEmpty();
+
+ void showChangeTextDialog();
+ void showOperationDialog(bool enableAutoIncrement = true);
+ virtual void showPropertiesDialog();
+
+ LinkWidget* link() const;
+ void setLink(LinkWidget * l);
+
+ bool activate(IDChangeLog* ChangeLog = 0);
+
+ Uml::TextRole::Enum textRole() const;
+ void setTextRole(Uml::TextRole::Enum role);
+
+ void handleRename();
+ void changeName(const QString& newText);
+
+ void setSequenceNumber(const QString &sequenceNumber);
+ QString sequenceNumber() const;
+
+ static bool isTextValid(const QString &text);
+
+ UMLWidget* onWidget(const QPointF& p);
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+ virtual bool loadFromXMI(QDomElement& qElement);
+
+public Q_SLOTS:
+ virtual void slotMenuSelection(QAction* action);
+ void setMessageText();
+
+protected:
+ QSizeF minimumSize() const;
+
+ virtual void moveWidgetBy(qreal diffX, qreal diffY);
+ virtual void constrainMovementForAllWidgets(qreal &diffX, qreal &diffY);
+
+private:
+ QPointF constrainPosition(qreal diffX, qreal diffY);
+
+ /// The association or message widget we may be linked to.
+ LinkWidget * m_linkWidget;
+
+ //////////////////// Data loaded/saved:
+
+ /// Prepended text (such as for scope of association Role or method)
+ QString m_preText;
+ /// Ending text (such as bracket on changability notation for association Role)
+ QString m_postText;
+ /// The role the text widget will enact.
+ Uml::TextRole::Enum m_textRole;
+
+ ////////
+
+ /// The horizontal position the widget would have if its move wasn't constrained.
+ qreal m_unconstrainedPositionX;
+
+ /// The vertical position the widget would have if its move wasn't constrained.
+ qreal m_unconstrainedPositionY;
+
+ /// The X direction the widget was moved when the constrain was applied.
+ /// -1 means left, 1 means right.
+ int m_movementDirectionX;
+
+ /// The Y direction the widget was moved when the constrain was applied.
+ /// -1 means up, 1 means down.
+ int m_movementDirectionY;
+
+ /// Contains sequence number for sequence or collaboration diagram message.
+ QString m_SequenceNumber;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/forkjoinwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/forkjoinwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/forkjoinwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/forkjoinwidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,205 @@
+/***************************************************************************
+ * 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) 2005-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "forkjoinwidget.h"
+
+//app includes
+#include "debug_utils.h"
+#include "umlview.h"
+#include "umldoc.h"
+#include "listpopupmenu.h"
+
+// qt includes
+#include <QColorDialog>
+
+/**
+ * Constructs a ForkJoinWidget.
+ *
+ * @param scene The parent to this widget.
+ * @param ori Whether to draw the plate horizontally or vertically.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+ForkJoinWidget::ForkJoinWidget(UMLScene * scene, Qt::Orientation ori, Uml::ID::Type id)
+ : BoxWidget(scene, id, WidgetBase::wt_ForkJoin),
+ m_orientation(ori)
+{
+ setSize(10, 40);
+ m_usesDiagramFillColor = false;
+ setFillColorCmd(QColor("black"));
+}
+
+/**
+ * Destructor.
+ */
+ForkJoinWidget::~ForkJoinWidget()
+{
+}
+
+/**
+ * Get whether to draw the plate vertically or horizontally.
+ */
+Qt::Orientation ForkJoinWidget::orientation() const
+{
+ return m_orientation;
+}
+
+/**
+ * Set whether to draw the plate vertically or horizontally.
+ */
+void ForkJoinWidget::setOrientation(Qt::Orientation ori)
+{
+ m_orientation = ori;
+ updateGeometry();
+ UMLWidget::adjustAssocs(x(), y());
+}
+
+/**
+ * Reimplemented from UMLWidget::paint to draw the plate of
+ * fork join.
+ */
+void ForkJoinWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ painter->fillRect(0, 0, width(), height(), fillColor());
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Reimplemented from UMLWidget::loadFromXMI to load widget
+ * info from XMI element - 'forkjoin'.
+ */
+bool ForkJoinWidget::loadFromXMI(QDomElement& qElement)
+{
+ if (!UMLWidget::loadFromXMI(qElement)) {
+ return false;
+ }
+
+ QString drawVerticalStr = qElement.attribute(QLatin1String("drawvertical"), QLatin1String("0"));
+ bool drawVertical = (bool)drawVerticalStr.toInt();
+ if (drawVertical) {
+ setOrientation(Qt::Vertical);
+ }
+ else {
+ setOrientation(Qt::Horizontal);
+ }
+
+ return true;
+}
+
+/**
+ * Reimplemented from UMLWidget::saveToXMI to save widget info
+ * into XMI element - 'forkjoin'.
+ */
+void ForkJoinWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement fjElement = qDoc.createElement(QLatin1String("forkjoin"));
+ UMLWidget::saveToXMI(qDoc, fjElement);
+ bool drawVertical = true;
+ if (m_orientation == Qt::Horizontal) {
+ drawVertical = false;
+ }
+ fjElement.setAttribute(QLatin1String("drawvertical"), drawVertical);
+ qElement.appendChild(fjElement);
+}
+
+/**
+ * Show a properties dialog for a Fork/Join Widget.
+ */
+void ForkJoinWidget::showPropertiesDialog()
+{
+ QColor newColor = QColorDialog::getColor(fillColor()); // krazy:exclude=qclasses
+ if (newColor != fillColor()) {
+ setFillColor(newColor);
+ setUsesDiagramFillColor(false);
+ umlDoc()->setModified(true);
+ }
+}
+
+/**
+ * Reimplemented form UMLWidget::slotMenuSelection to handle
+ * Flip action.
+ */
+void ForkJoinWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch (sel) {
+ case ListPopupMenu::mt_Fill_Color:
+ showPropertiesDialog();
+ break;
+
+ case ListPopupMenu::mt_Flip:
+ switch (m_orientation) {
+ case Qt::Vertical:
+ setOrientation(Qt::Horizontal);
+ break;
+ case Qt::Horizontal:
+ default:
+ setOrientation(Qt::Vertical);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Overrides the function from UMLWidget.
+ */
+QSizeF ForkJoinWidget::minimumSize() const
+{
+ if (m_orientation == Qt::Vertical) {
+ return QSizeF(4, 40);
+ } else {
+ return QSizeF(40, 4);
+ }
+}
+
+/**
+ * Reimplement method from UMLWidget to suppress the resize corner.
+ * Although the ForkJoinWidget supports resizing, we suppress the
+ * resize corner because it is too large for this very slim widget.
+ */
+void ForkJoinWidget::paintSelected(QPainter * p, int offsetX, int offsetY)
+{
+ Q_UNUSED(p);
+ Q_UNUSED(offsetX);
+ Q_UNUSED(offsetY);
+}
+
+/**
+ * Reimplement method from UMLWidget.
+ */
+void ForkJoinWidget::constrain(qreal& width, qreal& height)
+{
+ if (m_orientation == Qt::Vertical) {
+ if (width < 4)
+ width = 4;
+ else if (width > 10)
+ width = 10;
+ if (height < 40)
+ height = 40;
+ else if (height > 100)
+ height = 100;
+ } else {
+ if (height < 4)
+ height = 4;
+ else if (height > 10)
+ height = 10;
+ if (width < 40)
+ width = 40;
+ else if (width > 100)
+ width = 100;
+ }
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/forkjoinwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/forkjoinwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/forkjoinwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/forkjoinwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * 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) 2005-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef FORKJOINWIDGET_H
+#define FORKJOINWIDGET_H
+
+//app includes
+#include "boxwidget.h"
+
+/**
+ * @short Displays a fork/join plate in a state diagram.
+ *
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ *
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class ForkJoinWidget : public BoxWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+public:
+ explicit ForkJoinWidget(UMLScene * scene, Qt::Orientation ori = Qt::Horizontal, Uml::ID::Type id = Uml::ID::None);
+ virtual ~ForkJoinWidget();
+
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation ori);
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ virtual bool loadFromXMI(QDomElement & qElement);
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ void showPropertiesDialog();
+
+public Q_SLOTS:
+ virtual void slotMenuSelection(QAction* action);
+
+protected:
+ QSizeF minimumSize() const;
+
+ virtual void paintSelected(QPainter * p, int offsetX = 0, int offsetY = 0);
+
+ void constrain(qreal& width, qreal& height);
+
+private:
+ Qt::Orientation m_orientation; ///< whether to draw the plate horizontally or vertically
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/layoutgrid.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/layoutgrid.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/layoutgrid.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/layoutgrid.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * Copyright (C) 2011 by Andi Fischer <andi.fischer@hispeed.ch> *
+ * Copyright (C) 2012 by Ralf Habacker <ralf.habacker@freenet.de> *
+ * *
+ * This 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, or (at your option) *
+ * any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR purpose-kf6. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this package; see the file COPYING. If not, write to *
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, *
+ * Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "layoutgrid.h"
+
+#include "debug_utils.h"
+#include "umlscene.h"
+
+#include <QPainter>
+#include <QVarLengthArray>
+
+#define DBG_LOG() DEBUG(QLatin1String("LayoutGrid"))
+DEBUG_REGISTER_DISABLED(LayoutGrid)
+
+/**
+ * Constructor.
+ */
+LayoutGrid::LayoutGrid(UMLScene *scene)
+ : m_scene(scene),
+ m_gridSpacingX(25),
+ m_gridSpacingY(25),
+ m_gridDotColor(Qt::gray),
+ m_isVisible(false)
+{
+}
+
+/**
+ * Destructor.
+ */
+LayoutGrid::~LayoutGrid()
+{
+}
+
+void LayoutGrid::paint(QPainter *painter, const QRectF &rect)
+{
+ if (!isVisible())
+ return;
+
+ int gridSizeX = gridSpacingX();
+ int gridSizeY = gridSpacingY();
+
+ qreal left = int(rect.left()) - (int(rect.left()) % gridSizeX);
+ qreal top = int(rect.top()) - (int(rect.top()) % gridSizeY);
+
+ QVarLengthArray<QLineF, 200> lines;
+
+ for (qreal x = left; x < rect.right(); x += gridSizeX)
+ lines.append(QLineF(x, rect.top(), x, rect.bottom()));
+ for (qreal y = top; y < rect.bottom(); y += gridSizeY)
+ lines.append(QLineF(rect.left(), y, rect.right(), y));
+
+ painter->setPen(m_gridDotColor);
+ painter->drawLines(lines.data(), lines.size());
+}
+
+int LayoutGrid::gridSpacingX() const
+{
+ return m_gridSpacingX;
+}
+
+int LayoutGrid::gridSpacingY() const
+{
+ return m_gridSpacingY;
+}
+
+void LayoutGrid::setGridSpacing(int sizeX, int sizeY)
+{
+ DBG_LOG() << "x = " << sizeX << " / y = " << sizeY;
+ m_gridSpacingX= sizeX;
+ m_gridSpacingY= sizeY;
+}
+
+const QColor& LayoutGrid::gridDotColor() const
+{
+ return m_gridDotColor;
+}
+
+void LayoutGrid::setGridDotColor(const QColor& color)
+{
+ DBG_LOG() << "color = " << color;
+ m_gridDotColor = color;
+}
+
+bool LayoutGrid::isVisible() const
+{
+ return m_isVisible;
+}
+
+void LayoutGrid::setVisible(bool visible)
+{
+ if (m_isVisible != visible) {
+ DBG_LOG() << "visible = " << visible;
+ m_isVisible = visible;
+ m_scene->update();
+ }
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/layoutgrid.h umbrello-kf6-15.08.1/umbrello/umlwidgets/layoutgrid.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/layoutgrid.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/layoutgrid.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * Copyright (C) 2011 by Andi Fischer <andi.fischer@hispeed.ch> *
+ * Copyright (C) 2012 by Ralf Habacker <ralf.habacker@freenet.de> *
+ * *
+ * This 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, or (at your option) *
+ * any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR purpose-kf6. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this package; see the file COPYING. If not, write to *
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, *
+ * Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef LAYOUTGRID_H
+#define LAYOUTGRID_H
+
+#include <QColor>
+#include <QFont>
+
+class UMLScene;
+class QRectF;
+
+/**
+ * @author Andi Fischer
+ * This class handles the layout grid, which is drawn in the background
+ * of the scene. It is used only in UMLScene.
+ */
+class LayoutGrid
+{
+public:
+ explicit LayoutGrid(UMLScene *scene);
+ ~LayoutGrid();
+
+ void paint(QPainter *painter, const QRectF &rect);
+
+ QRect gridRect() const;
+ void setGridRect(const QRect& rect);
+
+ int gridSpacingX() const;
+ int gridSpacingY() const;
+ void setGridSpacing(int sizeX, int sizeY);
+
+ const QColor& gridDotColor() const;
+ void setGridDotColor(const QColor& color);
+
+ const QColor& gridCrossColor() const;
+ void setGridCrossColor(const QColor& color);
+
+ const QColor& textColor() const;
+ void setTextColor(const QColor& color);
+
+ QFont textFont() const;
+ void setTextFont(const QFont& font);
+
+ bool isVisible() const;
+ void setVisible(bool visible);
+
+ bool isTextVisible() const;
+ void setTextVisible(bool visible);
+
+private:
+ UMLScene *m_scene;
+ int m_gridSpacingX;
+ int m_gridSpacingY;
+ QColor m_gridDotColor;
+ bool m_isVisible;
+};
+
+#endif // LAYOUTGRID_H
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/linkwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/linkwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/linkwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/linkwidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,121 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "linkwidget.h"
+
+// app includes
+#include "classifier.h"
+#include "operation.h"
+#include "uml.h"
+#include "umlobject.h"
+#include "umlview.h"
+
+LinkWidget::LinkWidget()
+{
+}
+
+LinkWidget::~LinkWidget()
+{
+}
+
+/**
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
+ */
+UMLClassifier *LinkWidget::operationOwner()
+{
+ UMLOperation *op = operation();
+ if (op == NULL)
+ return NULL;
+ return static_cast<UMLClassifier*>(op->parent());
+}
+
+/**
+ * Return the operation text.
+ * When no scene parameter is given, the scene of the current view
+ * is taken instead.
+ * @param scene the given scene
+ * @return the operation text
+ */
+QString LinkWidget::operationText(UMLScene *scene)
+{
+ UMLOperation *op = operation();
+ if (op == NULL)
+ return customOpText();
+ if (scene == NULL)
+ scene = UMLApp::app()->currentView()->umlScene();
+ Uml::SignatureType::Enum sigType;
+ if (scene && scene->showOpSig())
+ sigType = Uml::SignatureType::SigNoVis;
+ else
+ sigType = Uml::SignatureType::NoSigNoVis;
+ QString opText = op->toString(sigType);
+ return opText;
+}
+
+/**
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Reset_Label_Positions)
+ * Only applies to AssociationWidget.
+ */
+void LinkWidget::resetTextPositions()
+{
+}
+
+/**
+ * Motivated by FloatingTextWidget::mouseDoubleClickEvent()
+ * Only applies to AssociationWidget.
+ */
+void LinkWidget::showPropertiesDialog()
+{
+}
+
+/**
+ * Motivated by FloatingTextWidget::setLink().
+ * Only applies to AssociationWidget.
+ */
+void LinkWidget::calculateNameTextSegment()
+{
+}
+
+
+/**
+ * Write property of QString m_SequenceNumber.
+ */
+void LinkWidget::setSequenceNumber(const QString &sequenceNumber)
+{
+ m_SequenceNumber = sequenceNumber;
+}
+
+/**
+ * Read property of QString m_SequenceNumber.
+ */
+QString LinkWidget::sequenceNumber() const
+{
+ return m_SequenceNumber;
+}
+
+/**
+ * Load data from XMI.
+ */
+bool LinkWidget::loadFromXMI(QDomElement &qElement)
+{
+ m_SequenceNumber = qElement.attribute(QLatin1String("seqnum"));
+ return true;
+}
+
+/**
+ * Save data to XMI.
+ */
+void LinkWidget::saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
+{
+ Q_UNUSED(qDoc);
+
+ qElement.setAttribute(QLatin1String("seqnum"), m_SequenceNumber);
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/linkwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/linkwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/linkwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/linkwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,123 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef LINKWIDGET_H
+#define LINKWIDGET_H
+
+#include "basictypes.h"
+#include "umlscene.h"
+
+#include <QFont>
+
+// forward declarations
+class UMLClassifier;
+class UMLOperation;
+class FloatingTextWidget;
+
+/**
+ * This is an interface realized by AssociationWidget and MessageWidget.
+ * The design of this interface was driven by the requirements of
+ * class FloatingTextWidget. As the architecture of umbrello-kf6 evolves (for
+ * example, if the class FloatingTextWidget is redesigned), it can be
+ * cleaned up.
+ *
+ * @short Interface to FloatingTextWidget for AssociationWidget and MessageWidget.
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class LinkWidget
+{
+public:
+ LinkWidget();
+ virtual ~LinkWidget();
+
+ /**
+ * Sets the font the widget is to use.
+ * Abstract operation implemented by inheriting classes.
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
+ *
+ * @param font Font to be set.
+ */
+ virtual void lwSetFont(QFont font) = 0;
+
+ virtual UMLClassifier *operationOwner();
+
+ /**
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
+ */
+ virtual UMLOperation *operation() = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
+ */
+ virtual void setOperation(UMLOperation *op) = 0;
+
+ /**
+ * Motivated by getOperationText()
+ */
+ virtual QString customOpText() = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
+ */
+ virtual void setCustomOpText(const QString &opText) = 0;
+
+ QString operationText(UMLScene *scene = 0);
+
+ virtual void resetTextPositions();
+
+ /**
+ * Motivated by FloatingTextWidget::setMessageText()
+ */
+ virtual void setMessageText(FloatingTextWidget *ft) = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::handleRename()
+ */
+ virtual void setText(FloatingTextWidget *ft, const QString &newText) = 0;
+
+ virtual void showPropertiesDialog();
+
+ /**
+ * Motivated by FloatingTextWidget::showOpDialog()
+ */
+ virtual QString lwOperationText() = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::showOpDialog()
+ */
+ virtual UMLClassifier *lwClassifier() = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::showOpDialog()
+ */
+ virtual void setOperationText(const QString &op) = 0;
+
+ /**
+ * Abstract operation implemented by inheriting classes.
+ * Motivated by FloatingTextWidget::mouseMoveEvent()
+ */
+ virtual void constrainTextPos(qreal &textX, qreal &textY,
+ qreal textWidth, qreal textHeight,
+ Uml::TextRole::Enum tr) = 0;
+
+ virtual void calculateNameTextSegment();
+
+ void setSequenceNumber(const QString &sequenceNumber);
+ QString sequenceNumber() const;
+
+ virtual bool loadFromXMI(QDomElement &qElement);
+ virtual void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
+
+protected:
+ QString m_SequenceNumber;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/messagewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/messagewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/messagewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/messagewidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,1385 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// onw header
+#include "messagewidget.h"
+
+//app includes
+#include "classifier.h"
+#include "debug_utils.h"
+#include "floatingtextwidget.h"
+#include "listpopupmenu.h"
+#include "objectwidget.h"
+#include "operation.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+#include "uniqueid.h"
+#include "idchangelog.h"
+
+//qt includes
+#include <QMoveEvent>
+#include <QPainter>
+#include <QPolygon>
+#include <QResizeEvent>
+
+//kde includes
+#include <KLocalizedString>
+
+DEBUG_REGISTER_DISABLED(MessageWidget)
+
+static const int circleWidth = 10;
+
+/**
+ * Constructs a MessageWidget.
+ *
+ * This method is used for creation, synchronous and synchronous message types.
+ *
+ * @param scene The parent to this class.
+ * @param a The role A widget for this message.
+ * @param b The role B widget for this message.
+ * @param y The vertical position to display this message.
+ * @param sequenceMessageType Whether synchronous or asynchronous
+ * @param id A unique id used for deleting this object cleanly.
+ * The default (-1) will prompt generation of a new ID.
+ */
+MessageWidget::MessageWidget(UMLScene * scene, ObjectWidget* a, ObjectWidget* b,
+ int y, Uml::SequenceMessage::Enum sequenceMessageType,
+ Uml::ID::Type id /* = Uml::id_None */)
+ : UMLWidget(scene, WidgetBase::wt_Message, id)
+{
+ init();
+ m_pOw[Uml::RoleType::A] = a;
+ m_pOw[Uml::RoleType::B] = b;
+ m_sequenceMessageType = sequenceMessageType;
+ if (m_sequenceMessageType == Uml::SequenceMessage::Creation) {
+ y -= m_pOw[Uml::RoleType::B]->height() / 2;
+ m_pOw[Uml::RoleType::B]->setY(y);
+ }
+ updateResizability();
+ calculateWidget();
+ y = y < getMinY() ? getMinY() : y;
+ y = y > getMaxY() ? getMaxY() : y;
+ setY(y);
+
+ this->activate();
+}
+
+/**
+ * Constructs a MessageWidget.
+ *
+ * @param scene The parent to this class.
+ * @param seqMsgType The Uml::SequenceMessage::Enum of this message widget
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+MessageWidget::MessageWidget(UMLScene * scene, Uml::SequenceMessage::Enum seqMsgType,
+ Uml::ID::Type id)
+ : UMLWidget(scene, WidgetBase::wt_Message, id)
+{
+ init();
+ m_sequenceMessageType = seqMsgType;
+}
+
+/**
+ * Constructs a Lost or Found MessageWidget.
+ *
+ * @param scene The parent to this class.
+ * @param a The role A widget for this message.
+ * @param xclick The horizontal position clicked by the user
+ * @param yclick The vertical position clicked by the user
+ * @param sequenceMessageType Whether lost or found
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+MessageWidget::MessageWidget(UMLScene * scene, ObjectWidget* a, int xclick, int yclick,
+ Uml::SequenceMessage::Enum sequenceMessageType,
+ Uml::ID::Type id /*= Uml::id_None*/)
+ : UMLWidget(scene, WidgetBase::wt_Message, id)
+{
+ init();
+ m_pOw[Uml::RoleType::A] = a;
+ m_pOw[Uml::RoleType::B] = a;
+
+ m_sequenceMessageType = sequenceMessageType;
+
+ m_xclicked = xclick;
+ m_yclicked = yclick;
+
+ updateResizability();
+ calculateWidget();
+ yclick = yclick < getMinY() ? getMinY() : yclick;
+ yclick = yclick > getMaxY() ? getMaxY() : yclick;
+ setY(yclick);
+ m_yclicked = yclick;
+
+ this->activate();
+}
+
+/**
+ * Initializes key variables of the class.
+ */
+void MessageWidget::init()
+{
+ m_xclicked = -1;
+ m_yclicked = -1;
+ m_ignoreSnapToGrid = true;
+ m_ignoreSnapComponentSizeToGrid = true;
+ m_pOw[Uml::RoleType::A] = m_pOw[Uml::RoleType::B] = NULL;
+ m_pFText = NULL;
+}
+
+/**
+ * Standard destructor.
+ */
+MessageWidget::~MessageWidget()
+{
+}
+
+/**
+ * Sets the y-coordinate.
+ * Reimplemented from UMLWidget.
+ *
+ * @param y The y-coordinate to be set.
+ */
+void MessageWidget::setY(qreal y)
+{
+ if (y < getMinY()) {
+ DEBUG(DBG_SRC) << "got out of bounds y position, check the reason" << this->y() << getMinY();
+ return;
+ }
+
+ UMLWidget::setY(y);
+ if (m_sequenceMessageType == Uml::SequenceMessage::Creation) {
+ const qreal objWidgetHalfHeight = m_pOw[Uml::RoleType::B]->height() / 2;
+ m_pOw[Uml::RoleType::B]->setY(y - objWidgetHalfHeight);
+ }
+
+ if (m_pFText && !UMLApp::app()->document()->loading()) {
+ setTextPosition();
+ emit sigMessageMoved();
+ }
+}
+
+/**
+ * Update the UMLWidget::m_resizable flag according to the
+ * charactersitics of this message.
+ */
+void MessageWidget::updateResizability()
+{
+ if (m_sequenceMessageType == Uml::SequenceMessage::Synchronous)
+ UMLWidget::m_resizable = true;
+ else
+ UMLWidget::m_resizable = false;
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Returns the cursor to be shown when resizing the widget.
+ * The cursor shown is KCursor::sizeVerCursor().
+ *
+ * @return The cursor to be shown when resizing the widget.
+ */
+QCursor MessageWidget::resizeCursor() const
+{
+ return Qt::SizeVerCursor;
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Resizes the height of the message widget and emits the message moved signal.
+ * Message widgets can only be resized vertically, so width isn't modified.
+ *
+ * @param newW The new width for the widget (isn't used).
+ * @param newH The new height for the widget.
+ */
+void MessageWidget::resizeWidget(qreal newW, qreal newH)
+{
+ if (sequenceMessageType() == Uml::SequenceMessage::Creation)
+ setSize(width(), newH);
+ else {
+ qreal x1 = m_pOw[Uml::RoleType::A]->x();
+ qreal x2 = getxclicked();
+ qreal diffX = 0;
+ if (x1 < x2) {
+ diffX = x2 + (newW - width());
+ }
+ else {
+ diffX = x2 - (newW - width());
+ }
+ if (diffX <= 0 )
+ diffX = 10;
+ setxclicked (diffX);
+ setSize(newW, newH);
+ calculateWidget();
+
+ }
+ emit sigMessageMoved();
+}
+
+/**
+ * Constrains the vertical position of the message widget so it doesn't go
+ * upper than the bottom side of the lower object.
+ * The height of the floating text widget in the message is taken in account
+ * if there is any and isn't empty.
+ *
+ * @param diffY The difference between current Y position and new Y position.
+ * @return The new Y position, constrained.
+ */
+qreal MessageWidget::constrainPositionY(qreal diffY)
+{
+ qreal newY = y() + diffY;
+
+ qreal minY = getMinY();
+ if (m_pFText && !m_pFText->displayText().isEmpty()) {
+ minY += m_pFText->height();
+ }
+
+ if (newY < minY) {
+ newY = minY;
+ }
+
+ return newY;
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Moves the widget to a new position using the difference between the
+ * current position and the new position. X position is ignored, and widget
+ * is only moved along Y axis. If message goes upper than the object, it's
+ * kept at this position until it should be lowered again (the unconstrained
+ * Y position is saved to know when it's the time to lower it again).
+ * If the message is a creation message, the object created is also moved to
+ * the new vertical position.
+ * @see constrainPositionY
+ *
+ * @param diffX The difference between current X position and new X position
+ * (isn't used).
+ * @param diffY The difference between current Y position and new Y position.
+ */
+void MessageWidget::moveWidgetBy(qreal diffX, qreal diffY)
+{
+ Q_UNUSED(diffX);
+ qreal newY = constrainPositionY(diffY);
+ setY(newY);
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Modifies the value of the diffX and diffY variables used to move the widgets.
+ * All the widgets are constrained to be moved only in Y axis (diffX is set to 0).
+ * @see constrainPositionY
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+void MessageWidget::constrainMovementForAllWidgets(qreal &diffX, qreal &diffY)
+{
+ diffX = 0;
+ diffY = constrainPositionY(diffY) - y();
+}
+
+/**
+ * Reimplemented from UMLWidget and calls other paint...() methods
+ * depending on the message type.
+ */
+void MessageWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ if(!m_pOw[Uml::RoleType::A] || !m_pOw[Uml::RoleType::B]) {
+ return;
+ }
+ setPenFromSettings(painter);
+ if (m_sequenceMessageType == Uml::SequenceMessage::Synchronous) {
+ paintSynchronous(painter, option);
+ } else if (m_sequenceMessageType == Uml::SequenceMessage::Asynchronous) {
+ paintAsynchronous(painter, option);
+ } else if (m_sequenceMessageType == Uml::SequenceMessage::Creation) {
+ paintCreation(painter, option);
+ } else if (m_sequenceMessageType == Uml::SequenceMessage::Lost) {
+ paintLost(painter, option);
+ } else if (m_sequenceMessageType == Uml::SequenceMessage::Found) {
+ paintFound(painter, option);
+ } else {
+ uWarning() << "Unknown message type";
+ }
+}
+
+/**
+ * Draw a solid-kf6 (triangular) arrowhead pointing in the given direction.
+ * The direction can be either Qt::LeftArrow or Qt::RightArrow.
+ */
+void MessageWidget::paintsolid-kf6Arrowhead(QPainter *p, int x, int y, Qt::ArrowType direction)
+{
+ int arrowheadExtentX = 4;
+ if (direction == Qt::RightArrow) {
+ arrowheadExtentX = -arrowheadExtentX;
+ }
+ QPolygon points;
+ points.putPoints(0, 3, x, y, x + arrowheadExtentX, y - 3, x + arrowheadExtentX, y + 3);
+ p->setBrush(QBrush(p->pen().color()));
+ p->drawPolygon(points);
+}
+
+/**
+ * Draw an arrow pointing in the given direction.
+ * The arrow head is not solid-kf6, i.e. it is made up of two lines
+ * like so: --->
+ * The direction can be either Qt::LeftArrow or Qt::RightArrow.
+ */
+void MessageWidget::paintArrow(QPainter *p, int x, int y, int w,
+ Qt::ArrowType direction, bool useDottedLine /* = false */)
+{
+ if (w > 3) {
+ int arrowheadStartX = x;
+ int arrowheadExtentX = 4;
+ if (direction == Qt::RightArrow) {
+ arrowheadStartX += w;
+ arrowheadExtentX = -arrowheadExtentX;
+ }
+ // draw upper half of arrowhead
+ p->drawLine(arrowheadStartX, y, arrowheadStartX + arrowheadExtentX, y - 3);
+ // draw lower half of arrowhead
+ p->drawLine(arrowheadStartX, y, arrowheadStartX + arrowheadExtentX, y + 3);
+ }
+ // draw arrow line
+ if (useDottedLine) {
+ QPen pen = p->pen();
+ pen.setStyle(Qt::DotLine);
+ p->setPen(pen);
+ }
+ p->drawLine(x, y, x + w, y);
+}
+
+/**
+ * Draws the calling arrow with filled in arrowhead, the
+ * timeline box and the returning arrow with a dashed line and
+ * stick arrowhead.
+ */
+void MessageWidget::paintSynchronous(QPainter *painter, const QStyleOptionGraphicsItem *option)
+{
+ int x1 = m_pOw[Uml::RoleType::A]->x();
+ int x2 = m_pOw[Uml::RoleType::B]->x();
+ int w = width() - 1;
+ int h = height();
+ int offsetX = 0;
+ int offsetY = 0;
+
+ bool messageOverlaps = m_pOw[Uml::RoleType::A]->messageOverlap(y(), this);
+ const int boxWidth = 17;
+ const int wr = w < boxWidth ? w : boxWidth;
+ const int arrowWidth = 4;
+
+ if(isSelf()) {
+ painter->fillRect(offsetX, offsetY, wr, h, QBrush(Qt::white)); //box
+ painter->drawRect(offsetX, offsetY, wr, h); //box
+ offsetX += wr;
+ w -= wr;
+ offsetY += 3;
+ const int lowerLineY = offsetY + h - 6;
+ // draw upper line segment (leaving the life line)
+ painter->drawLine(offsetX, offsetY, offsetX + w, offsetY);
+ // draw line segment parallel to (and at the right of) the life line
+ painter->drawLine(offsetX + w, offsetY, offsetX + w, lowerLineY);
+ // draw lower line segment (back to the life line)
+ paintArrow(painter, offsetX, lowerLineY, w, Qt::LeftArrow);
+ offsetX -= wr;
+ offsetY -= 3;
+ } else if(x1 < x2) {
+ if (messageOverlaps) {
+ offsetX += 8;
+ w -= 8;
+ }
+ QPen pen = painter->pen();
+ int startX = offsetX + w - wr + 1;
+ painter->fillRect(startX, offsetY, wr, h, QBrush(Qt::white)); //box
+ painter->drawRect(startX, offsetY, wr, h); //box
+ painter->drawLine(offsetX, offsetY + arrowWidth, startX, offsetY + arrowWidth); //arrow line
+ if (w > boxWidth + arrowWidth)
+ paintsolid-kf6Arrowhead(painter, startX - 1, offsetY + arrowWidth, Qt::RightArrow);
+ paintArrow(painter, offsetX, offsetY + h - arrowWidth + 1, w - wr + 1, Qt::LeftArrow, true); // return arrow
+ if (messageOverlaps) {
+ offsetX -= 8; //reset for drawSelected()
+ }
+ } else {
+ if (messageOverlaps) {
+ w -=8;
+ }
+ QPen pen = painter->pen();
+ painter->fillRect(offsetX, offsetY, wr, h, QBrush(Qt::white)); //box
+ painter->drawRect(offsetX, offsetY, wr, h); //box
+ painter->drawLine(offsetX + wr + 1, offsetY + arrowWidth, offsetX + w, offsetY + arrowWidth); //arrow line
+ if (w > boxWidth + arrowWidth)
+ paintsolid-kf6Arrowhead(painter, offsetX + wr, offsetY + arrowWidth, Qt::LeftArrow);
+ paintArrow(painter, offsetX + wr + 1, offsetY + h - arrowWidth + 1, w - wr - 1, Qt::RightArrow, true); // return arrow
+ }
+
+ UMLWidget::paint(painter, option);
+}
+
+/**
+ * Draws a solid-kf6 arrow line and a stick arrow head.
+ */
+void MessageWidget::paintAsynchronous(QPainter *painter, const QStyleOptionGraphicsItem *option)
+{
+ int x1 = m_pOw[Uml::RoleType::A]->x();
+ int x2 = m_pOw[Uml::RoleType::B]->x();
+ int w = width() - 1;
+ int h = height() - 1;
+ int offsetX = 0;
+ int offsetY = 0;
+ bool messageOverlapsA = m_pOw[Uml::RoleType::A]->messageOverlap(y(), this);
+ //bool messageOverlapsB = m_pOw[Uml::RoleType::B]->messageOverlap(y(), this);
+
+ if(isSelf()) {
+ if (messageOverlapsA) {
+ offsetX += 7;
+ w -= 7;
+ }
+ const int lowerLineY = offsetY + h - 3;
+ // draw upper line segment (leaving the life line)
+ painter->drawLine(offsetX, offsetY, offsetX + w, offsetY);
+ // draw line segment parallel to (and at the right of) the life line
+ painter->drawLine(offsetX + w, offsetY, offsetX + w, lowerLineY);
+ // draw lower line segment (back to the life line)
+ paintArrow(painter, offsetX, lowerLineY, w, Qt::LeftArrow);
+ if (messageOverlapsA) {
+ offsetX -= 7; //reset for drawSelected()
+ }
+ } else if(x1 < x2) {
+ if (messageOverlapsA) {
+ offsetX += 7;
+ w -= 7;
+ }
+ paintArrow(painter, offsetX, offsetY + 4, w, Qt::RightArrow);
+ if (messageOverlapsA) {
+ offsetX -= 7;
+ }
+ } else {
+ if (messageOverlapsA) {
+ w -= 7;
+ }
+ paintArrow(painter, offsetX, offsetY + 4, w, Qt::LeftArrow);
+ }
+
+ UMLWidget::paint(painter, option);
+}
+
+/**
+ * Draws a solid-kf6 arrow line and a stick arrow head to the
+ * edge of the target object widget instead of to the
+ * sequence line.
+ */
+void MessageWidget::paintCreation(QPainter *painter, const QStyleOptionGraphicsItem *option)
+{
+ int x1 = m_pOw[Uml::RoleType::A]->x();
+ int x2 = m_pOw[Uml::RoleType::B]->x();
+ int w = width();
+ //int h = height() - 1;
+ int offsetX = 0;
+ int offsetY = 0;
+ bool messageOverlapsA = m_pOw[Uml::RoleType::A]->messageOverlap(y(), this);
+ //bool messageOverlapsB = m_pOw[Uml::RoleType::B]->messageOverlap(y(), this);
+
+ const int lineY = offsetY + 4;
+ if (x1 < x2) {
+ if (messageOverlapsA) {
+ offsetX += 7;
+ w -= 7;
+ }
+ paintArrow(painter, offsetX, lineY, w, Qt::RightArrow);
+ if (messageOverlapsA) {
+ offsetX -= 7;
+ }
+ } else {
+ if (messageOverlapsA) {
+ w -= 7;
+ }
+ paintArrow(painter, offsetX, lineY, w, Qt::LeftArrow);
+ }
+
+ UMLWidget::paint(painter, option);
+}
+
+
+/**
+ * Draws a solid-kf6 arrow line and a stick arrow head
+ * and a circle
+ */
+void MessageWidget::paintLost(QPainter *painter, const QStyleOptionGraphicsItem *option)
+{
+ int x1 = m_pOw[Uml::RoleType::A]->centerX();
+ int x2 = m_xclicked;
+ int w = width();
+ int h = height();
+ int offsetX = 0;
+ int offsetY = 0;
+ bool messageOverlapsA = m_pOw[Uml::RoleType::A]->messageOverlap(y(), this);
+ //bool messageOverlapsB = m_pOw[Uml::RoleType::B]->messageOverlap(y(), this);
+
+ if(x1 < x2) {
+ if (messageOverlapsA) {
+ offsetX += 7;
+ w -= 7;
+ }
+
+ setPenFromSettings(painter);
+ painter->setBrush(WidgetBase::lineColor());
+ painter->drawEllipse(offsetX + w - h, offsetY, h, h);
+ paintArrow(painter, offsetX, offsetY + h/2, w - h, Qt::RightArrow);
+
+ if (messageOverlapsA) {
+ offsetX -= 7;
+ }
+ } else {
+ setPenFromSettings(painter);
+ painter->setBrush(WidgetBase::lineColor());
+ painter->drawEllipse(offsetX, offsetY, h, h);
+ paintArrow(painter, offsetX + h, offsetY + h/2, w - h, Qt::LeftArrow);
+ }
+
+ UMLWidget::paint(painter, option);
+}
+
+/**
+ * Draws a circle and a solid-kf6 arrow line and a stick arrow head.
+ */
+void MessageWidget::paintFound(QPainter *painter, const QStyleOptionGraphicsItem *option)
+{
+ int x1 = m_pOw[Uml::RoleType::A]->centerX();
+ int x2 = m_xclicked;
+ int w = width();
+ int h = height();
+ int offsetX = 0;
+ int offsetY = 0;
+ bool messageOverlapsA = m_pOw[Uml::RoleType::A]->messageOverlap(y(), this);
+ //bool messageOverlapsB = m_pOw[Uml::RoleType::B]->messageOverlap(y(), this);
+
+ if(x1 < x2) {
+ if (messageOverlapsA) {
+ offsetX += 7;
+ w -= 7;
+ }
+ setPenFromSettings(painter);
+ painter->setBrush(WidgetBase::lineColor());
+ painter->drawEllipse(offsetX + w - h, offsetY, h, h);
+ paintArrow(painter, offsetX, offsetY + h/2, w, Qt::LeftArrow);
+ if (messageOverlapsA) {
+ offsetX -= 7;
+ }
+ } else {
+ if (messageOverlapsA) {
+ w -= 7;
+ }
+ setPenFromSettings(painter);
+ painter->setBrush(WidgetBase::lineColor());
+ painter->drawEllipse(offsetX, offsetY, h, h);
+ paintArrow(painter, offsetX, offsetY + h/2, w, Qt::RightArrow);
+ }
+
+ UMLWidget::paint(painter, option);
+}
+
+/**
+ * Overrides operation from UMLWidget.
+ *
+ * @param p Point to be checked.
+ *
+ * @return 'this' if the point is on a part of the MessageWidget.
+ * NB In case of a synchronous message, the empty space
+ * between call line and return line does not count, i.e. if
+ * the point is located in that space the function returns NULL.
+ */
+UMLWidget* MessageWidget::onWidget(const QPointF& p)
+{
+ if (m_sequenceMessageType != Uml::SequenceMessage::Synchronous) {
+ return UMLWidget::onWidget(p);
+ }
+ // Synchronous message:
+ // Consists of top arrow (call) and bottom arrow (return.)
+ if (p.x() < x() || p.x() > x() + width())
+ return NULL;
+ const int tolerance = 5; // pixels
+ const int pY = p.y();
+ const int topArrowY = y() + 3;
+ const int bottomArrowY = y() + height() - 3;
+ if (pY < topArrowY - tolerance || pY > bottomArrowY + tolerance)
+ return NULL;
+ if (height() <= 2 * tolerance)
+ return this;
+ if (pY > topArrowY + tolerance && pY < bottomArrowY - tolerance)
+ return NULL;
+ return this;
+}
+
+/**
+ * Sets the text position relative to the sequence message.
+ */
+void MessageWidget::setTextPosition()
+{
+ if (m_pFText == NULL) {
+ DEBUG(DBG_SRC) << "m_pFText is NULL";
+ return;
+ }
+ if (m_pFText->displayText().isEmpty()) {
+ return;
+ }
+ m_pFText->updateGeometry();
+ int ftX = constrainX(m_pFText->x(), m_pFText->width(), m_pFText->textRole());
+ int ftY = y() - m_pFText->height();
+ m_pFText->setX(ftX);
+ m_pFText->setY(ftY);
+}
+
+/**
+ * Returns the textX arg with constraints applied.
+ * Auxiliary to setTextPosition() and constrainTextPos().
+ */
+int MessageWidget::constrainX(int textX, int textWidth, Uml::TextRole::Enum tr)
+{
+ int result = textX;
+ const int minTextX = x() + 5;
+ if (textX < minTextX || tr == Uml::TextRole::Seq_Message_Self) {
+ result = minTextX;
+ } else {
+ ObjectWidget *objectAtRight = NULL;
+ if (m_pOw[Uml::RoleType::B]->x() > m_pOw[Uml::RoleType::A]->x())
+ objectAtRight = m_pOw[Uml::RoleType::B];
+ else
+ objectAtRight = m_pOw[Uml::RoleType::A];
+ const int objRight_seqLineX = objectAtRight->centerX();
+ const int maxTextX = objRight_seqLineX - textWidth - 5;
+ if (maxTextX <= minTextX)
+ result = minTextX;
+ else if (textX > maxTextX)
+ result = maxTextX;
+ }
+ return result;
+}
+
+/**
+ * Constrains the FloatingTextWidget X and Y values supplied.
+ * Overrides operation from LinkWidget.
+ *
+ * @param textX candidate X value (may be modified by the constraint)
+ * @param textY candidate Y value (may be modified by the constraint)
+ * @param textWidth width of the text
+ * @param textHeight height of the text
+ * @param tr Uml::TextRole::Enum of the text
+ */
+void MessageWidget::constrainTextPos(qreal &textX, qreal &textY, qreal textWidth, qreal textHeight,
+ Uml::TextRole::Enum tr)
+{
+ textX = constrainX(textX, textWidth, tr);
+ // Constrain Y.
+ const qreal minTextY = getMinY();
+ const qreal maxTextY = getMaxY() - textHeight - 5;
+ if (textY < minTextY)
+ textY = minTextY;
+ else if (textY > maxTextY)
+ textY = maxTextY;
+// setY(textY + textHeight); // NB: side effect
+}
+
+/**
+ * Shortcut for calling m_pFText->setLink() followed by
+ * this->setTextPosition().
+ */
+void MessageWidget::setLinkAndTextPos()
+{
+ if (m_pFText) {
+ m_pFText->setLink(this);
+ setTextPosition();
+ }
+}
+
+void MessageWidget::resizeEvent(QResizeEvent* /*re*/)
+{
+}
+
+/**
+ * Calculate the geometry of the widget.
+ */
+void MessageWidget::calculateWidget()
+{
+ setMessageText(m_pFText);
+ calculateDimensions();
+ setVisible(true);
+}
+
+void MessageWidget::slotWidgetMoved(Uml::ID::Type id)
+{
+ const Uml::ID::Type idA = m_pOw[Uml::RoleType::A]->localID();
+ const Uml::ID::Type idB = m_pOw[Uml::RoleType::B]->localID();
+ if (idA != id && idB != id) {
+ DEBUG(DBG_SRC) << "id=" << Uml::ID::toString(id) << ": ignoring for idA=" << Uml::ID::toString(idA)
+ << ", idB=" << Uml::ID::toString(idB);
+ return;
+ }
+ qreal y = this->y();
+ if (y < getMinY())
+ y = getMinY();
+ if (y > getMaxY())
+ y = getMaxY();
+ setPos(x(), y);
+ calculateWidget();
+ if(!m_pFText)
+ return;
+ if (m_scene->selectedCount(true) > 1)
+ return;
+ setTextPosition();
+}
+
+/**
+ * Check to see if the given ObjectWidget is involved in the message.
+ *
+ * @param w The ObjectWidget to check for.
+ * @return true - if is contained, false - not contained.
+ */
+bool MessageWidget::hasObjectWidget(ObjectWidget * w)
+{
+ if(m_pOw[Uml::RoleType::A] == w || m_pOw[Uml::RoleType::B] == w)
+ return true;
+ else
+ return false;
+}
+
+/**
+ * This method determines whether the message is for "Self" for
+ * an ObjectWidget.
+ *
+ * @retval True If both ObjectWidgets for this widget exists and
+ * are same.
+ */
+bool MessageWidget::isSelf() const
+{
+ return (m_pOw[Uml::RoleType::A] && m_pOw[Uml::RoleType::B] &&
+ m_pOw[Uml::RoleType::A] == m_pOw[Uml::RoleType::B]);
+}
+
+void MessageWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ if (sel == ListPopupMenu::mt_Delete) {
+ // This will clean up this widget and the text widget:
+ m_scene->removeWidget(this);
+ } else {
+
+ UMLWidget::slotMenuSelection(action);
+ }
+}
+
+/**
+ * Activates a MessageWidget. Connects its m_pOw[] pointers
+ * to UMLObjects and also send signals about its FloatingTextWidget.
+ */
+bool MessageWidget::activate(IDChangeLog * /*Log = 0*/)
+{
+ m_scene->resetPastep-kf6oint();
+ // UMLWidget::activate(Log); CHECK: I don't think we need this ?
+ if (m_pOw[Uml::RoleType::A] == NULL) {
+ UMLWidget *pWA = m_scene->findWidget(m_widgetAId);
+ if (pWA == NULL) {
+ DEBUG(DBG_SRC) << "role A object " << Uml::ID::toString(m_widgetAId) << " not found";
+ return false;
+ }
+ m_pOw[Uml::RoleType::A] = dynamic_cast<ObjectWidget*>(pWA);
+ if (m_pOw[Uml::RoleType::A] == NULL) {
+ DEBUG(DBG_SRC) << "role A widget " << Uml::ID::toString(m_widgetAId)
+ << " is not an ObjectWidget";
+ return false;
+ }
+ }
+ if (m_pOw[Uml::RoleType::B] == NULL) {
+ UMLWidget *pWB = m_scene->findWidget(m_widgetBId);
+ if (pWB == NULL) {
+ DEBUG(DBG_SRC) << "role B object " << Uml::ID::toString(m_widgetBId) << " not found";
+ return false;
+ }
+ m_pOw[Uml::RoleType::B] = dynamic_cast<ObjectWidget*>(pWB);
+ if (m_pOw[Uml::RoleType::B] == NULL) {
+ DEBUG(DBG_SRC) << "role B widget " << Uml::ID::toString(m_widgetBId)
+ << " is not an ObjectWidget";
+ return false;
+ }
+ }
+ updateResizability();
+
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(m_pOw[Uml::RoleType::B]->umlObject());
+ UMLOperation *op = NULL;
+ if (c && !m_CustomOp.isEmpty()) {
+ Uml::ID::Type opId = Uml::ID::fromString(m_CustomOp);
+ op = dynamic_cast<UMLOperation*>(c->findChildObjectById(opId, true));
+ if (op) {
+ // If the UMLOperation is set, m_CustomOp isn't used anyway.
+ // Just setting it empty for the sake of sanity.
+ m_CustomOp.clear();
+ }
+ }
+
+ if(!m_pFText) {
+ Uml::TextRole::Enum tr = Uml::TextRole::Seq_Message;
+ if (isSelf())
+ tr = Uml::TextRole::Seq_Message_Self;
+ m_pFText = new FloatingTextWidget(m_scene, tr, operationText(m_scene));
+ m_scene->addFloatingTextWidget(m_pFText);
+ m_pFText->setFontCmd(UMLWidget::font());
+ }
+ if (op)
+ setOperation(op); // This requires a valid m_pFText.
+ setLinkAndTextPos();
+ m_pFText->setText(QString());
+ m_pFText->setActivated();
+ QString messageText = m_pFText->text();
+ m_pFText->setVisible(messageText.length() > 1);
+
+ connect(m_pOw[Uml::RoleType::A], SIGNAL(sigWidgetMoved(Uml::ID::Type)), this, SLOT(slotWidgetMoved(Uml::ID::Type)));
+ connect(m_pOw[Uml::RoleType::B], SIGNAL(sigWidgetMoved(Uml::ID::Type)), this, SLOT(slotWidgetMoved(Uml::ID::Type)));
+
+ connect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::RoleType::A], SLOT(slotMessageMoved()));
+ connect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::RoleType::B], SLOT(slotMessageMoved()));
+ m_pOw[Uml::RoleType::A]->messageAdded(this);
+ if (!isSelf())
+ m_pOw[Uml::RoleType::B]->messageAdded(this);
+
+ // Calculate the size and position of the message widget
+ calculateDimensions();
+
+ // Position the floating text accordingly
+ setTextPosition();
+
+ emit sigMessageMoved();
+ return true;
+}
+
+/**
+ * Resolve references of this message so they reference the correct
+ * new object widgets after paste.
+ */
+void MessageWidget::resolveObjectWidget(IDChangeLog* log) {
+ m_widgetAId = log->findNewID(m_widgetAId);
+ m_widgetBId = log->findNewID(m_widgetBId);
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param ft The text widget which to update.
+ */
+void MessageWidget::setMessageText(FloatingTextWidget *ft)
+{
+ if (ft == NULL)
+ return;
+ ft->setSequenceNumber(m_SequenceNumber);
+ ft->setText(operationText(m_scene));
+ setTextPosition();
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param ft The text widget which to update.
+ * @param newText The new text to set.
+ */
+void MessageWidget::setText(FloatingTextWidget *ft, const QString &newText)
+{
+ ft->setText(newText);
+ UMLApp::app()->document()->setModified(true);
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param op The new operation string to set.
+ */
+void MessageWidget::setOperationText(const QString &op)
+{
+ m_CustomOp = op; ///FIXME m_pOperation
+}
+
+/**
+ * Implements operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+void MessageWidget::lwSetFont (QFont font)
+{
+ UMLWidget::setFont(font);
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ * @todo Move to LinkWidget.
+ */
+UMLClassifier *MessageWidget::operationOwner()
+{
+ UMLObject *pObject = m_pOw[Uml::RoleType::B]->umlObject();
+ if (pObject == NULL)
+ return NULL;
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(pObject);
+ return c;
+}
+
+/**
+ * Implements operation from LinkWidget.
+ * Motivated by FloatingTextWidget.
+ */
+UMLOperation *MessageWidget::operation()
+{
+ return static_cast<UMLOperation*>(m_umlObject);
+}
+
+/**
+ * Implements operation from LinkWidget.
+ * Motivated by FloatingTextWidget.
+ */
+void MessageWidget::setOperation(UMLOperation *op)
+{
+ if (m_umlObject && m_pFText)
+ disconnect(m_umlObject, SIGNAL(modified()), m_pFText, SLOT(setMessageText()));
+ m_umlObject = op;
+ if (m_umlObject && m_pFText) {
+ connect(m_umlObject, SIGNAL(modified()), m_pFText, SLOT(setMessageText()));
+ m_pFText->setMessageText();
+ }
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+QString MessageWidget::customOpText()
+{
+ return m_CustomOp;
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+void MessageWidget::setCustomOpText(const QString &opText)
+{
+ m_CustomOp = opText;
+ m_pFText->setMessageText();
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+QString MessageWidget::lwOperationText()
+{
+ UMLOperation *pOperation = operation();
+ if (pOperation != NULL) {
+ return pOperation->toString(Uml::SignatureType::SigNoVis);
+ } else {
+ return customOpText();
+ }
+}
+
+/**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+UMLClassifier *MessageWidget::lwClassifier()
+{
+ UMLObject *o = m_pOw[Uml::RoleType::B]->umlObject();
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(o);
+ return c;
+}
+
+/**
+ * Calculates the size of the widget by calling
+ * calculateDimensionsSynchronous(),
+ * calculateDimensionsAsynchronous(), or
+ * calculateDimensionsCreation()
+ */
+void MessageWidget::calculateDimensions()
+{
+ if (m_sequenceMessageType == Uml::SequenceMessage::Synchronous) {
+ calculateDimensionsSynchronous();
+ } else if (m_sequenceMessageType == Uml::SequenceMessage::Asynchronous) {
+ calculateDimensionsAsynchronous();
+ } else if (m_sequenceMessageType == Uml::SequenceMessage::Creation) {
+ calculateDimensionsCreation();
+ } else if (m_sequenceMessageType == Uml::SequenceMessage::Lost) {
+ calculateDimensionsLost();
+ } else if (m_sequenceMessageType == Uml::SequenceMessage::Found) {
+ calculateDimensionsFound();
+ } else {
+ uWarning() << "Unknown message type";
+ }
+ if (! UMLApp::app()->document()->loading()) {
+ adjustAssocs(x(), y()); // adjust assoc lines
+ }
+}
+
+/**
+ * Calculates and sets the size of the widget for a synchronous message.
+ */
+void MessageWidget::calculateDimensionsSynchronous()
+{
+ int x = 0;
+
+ int x1 = m_pOw[Uml::RoleType::A]->centerX();
+ int x2 = m_pOw[Uml::RoleType::B]->centerX();
+
+ int widgetWidth = 0;
+ int widgetHeight = 0;
+ if(isSelf()) {
+ widgetWidth = 50;
+ x = x1 - 2;
+ } else if(x1 < x2) {
+ x = x1;
+ widgetWidth = x2 - x1 + 8;
+ } else {
+ x = x2 - 8;
+ widgetWidth = x1 - x2 + 8;
+ }
+
+ if (height() < 20) {
+ widgetHeight = 20;
+ } else {
+ widgetHeight = height();
+ }
+
+ setX(x);
+ setSize(widgetWidth, widgetHeight);
+}
+
+/**
+ * Calculates and sets the size of the widget for an asynchronous message.
+ */
+void MessageWidget::calculateDimensionsAsynchronous()
+{
+ int x = 0;
+
+ int x1 = m_pOw[Uml::RoleType::A]->centerX();
+ int x2 = m_pOw[Uml::RoleType::B]->centerX();
+
+ int widgetWidth = 0;
+ int widgetHeight = 8;
+ if(isSelf()) {
+ widgetWidth = 50;
+ x = x1;
+ if(height() < 20) {
+ widgetHeight = 20;
+ } else {
+ widgetHeight = height();
+ }
+ } else if(x1 < x2) {
+ x = x1;
+ widgetWidth = x2 - x1;
+ } else {
+ x = x2;
+ widgetWidth = x1 - x2;
+ }
+ x += 1;
+ widgetWidth -= 2;
+ setX(x);
+ setSize(widgetWidth, widgetHeight);
+}
+
+/**
+ * Calculates and sets the size of the widget for a creation message.
+ */
+void MessageWidget::calculateDimensionsCreation()
+{
+ int x = 0;
+
+ int x1 = m_pOw[Uml::RoleType::A]->centerX();
+ int x2 = m_pOw[Uml::RoleType::B]->x();
+ int w2 = m_pOw[Uml::RoleType::B]->width();
+
+ if (x1 > x2)
+ x2 += w2;
+
+ int widgetWidth = 0;
+ int widgetHeight = 8;
+ if (x1 < x2) {
+ x = x1;
+ widgetWidth = x2 - x1;
+ } else {
+ x = x2;
+ widgetWidth = x1 - x2;
+ }
+ x += 1;
+ widgetWidth -= 2;
+ setPos(x, m_pOw[Uml::RoleType::B]->y() + m_pOw[Uml::RoleType::B]->height() / 2);
+ setSize(widgetWidth, widgetHeight);
+}
+
+/**
+ * Calculates and sets the size of the widget for a lost message.
+ */
+void MessageWidget::calculateDimensionsLost()
+{
+ int x = 0;
+
+ int x1 = m_pOw[Uml::RoleType::A]->centerX();
+ int x2 = m_xclicked;
+
+ int widgetWidth = 0;
+ int widgetHeight = 10;
+ if(x1 < x2) {
+ x = x1;
+ widgetWidth = x2 - x1 + circleWidth/2;
+ } else {
+ x = x2 - circleWidth/2;
+ widgetWidth = x1 - x2 + circleWidth/2;
+ }
+ setX(x);
+ setSize(widgetWidth, widgetHeight);
+}
+
+/**
+ * Calculates and sets the size of the widget for a found message.
+ */
+void MessageWidget::calculateDimensionsFound()
+{
+ int x = 0;
+
+ int x1 = m_pOw[Uml::RoleType::A]->centerX();
+ int x2 = m_xclicked;
+
+ int widgetWidth = 0;
+ int widgetHeight = 10;
+ if(x1 < x2) {
+ x = x1;
+ widgetWidth = x2 - x1 + circleWidth/2;
+ } else {
+ x = x2 - circleWidth/2;
+ widgetWidth = x1 - x2 + circleWidth/2;
+ }
+
+ setX(x);
+ setSize(widgetWidth, widgetHeight);
+}
+
+/**
+ * Used to cleanup any other widget it may need to delete.
+ */
+void MessageWidget::cleanup()
+{
+ if (m_pOw[Uml::RoleType::A]) {
+ disconnect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::RoleType::A], SLOT(slotMessageMoved()));
+ m_pOw[Uml::RoleType::A]->messageRemoved(this);
+ }
+ if (m_pOw[Uml::RoleType::B]) {
+ disconnect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::RoleType::B], SLOT(slotMessageMoved()));
+ m_pOw[Uml::RoleType::B]->messageRemoved(this);
+ }
+
+ UMLWidget::cleanup();
+ if (m_pFText) {
+ m_scene->removeWidgetCmd(m_pFText);
+ m_pFText = NULL;
+ }
+}
+
+/**
+ * Sets the state of whether the widget is selected.
+ *
+ * @param _select True if the widget is selected.
+ */
+void MessageWidget::setSelected(bool _select)
+{
+ UMLWidget::setSelected(_select);
+ if(!m_pFText || m_pFText->displayText().isEmpty())
+ return;
+ if(isSelected() && m_pFText->isSelected())
+ return;
+ if(!isSelected() && !m_pFText->isSelected())
+ return;
+
+ m_pFText->setSelected(isSelected());
+}
+
+/**
+ * Returns the minimum height this widget should be set at on
+ * a sequence diagrams. Takes into account the widget positions
+ * it is related to.
+ */
+int MessageWidget::getMinY()
+{
+ if (!m_pOw[Uml::RoleType::A] || !m_pOw[Uml::RoleType::B]) {
+ return 0;
+ }
+ if (m_sequenceMessageType == Uml::SequenceMessage::Creation) {
+ return m_pOw[Uml::RoleType::A]->y() + m_pOw[Uml::RoleType::A]->height();
+ }
+ int heightA = m_pOw[Uml::RoleType::A]->y() + m_pOw[Uml::RoleType::A]->height();
+ int heightB = m_pOw[Uml::RoleType::B]->y() + m_pOw[Uml::RoleType::B]->height();
+ int height = heightA;
+ if(heightA < heightB) {
+ height = heightB;
+ }
+ return height;
+}
+
+/**
+ * Returns the maximum height this widget should be set at on
+ * a sequence diagrams. Takes into account the widget positions
+ * it is related to.
+ */
+int MessageWidget::getMaxY()
+{
+ if(!m_pOw[Uml::RoleType::A] || !m_pOw[Uml::RoleType::B]) {
+ return 0;
+ }
+ int heightA = (int)((ObjectWidget*)m_pOw[Uml::RoleType::A])->getEndLineY();
+ int heightB = (int)((ObjectWidget*)m_pOw[Uml::RoleType::B])->getEndLineY();
+ int height = heightA;
+ if(heightA > heightB) {
+ height = heightB;
+ }
+ return (height - this->height());
+}
+
+/**
+ * Sets the related widget on the given side.
+ *
+ * @param ow The ObjectWidget we are related to.
+ * @param role The Uml::RoleType::Enum to be set for the ObjectWidget
+ */
+void MessageWidget::setObjectWidget(ObjectWidget * ow, Uml::RoleType::Enum role)
+{
+ m_pOw[role] = ow;
+ updateResizability();
+}
+
+/**
+ * Returns the related widget on the given side.
+ *
+ * @return The ObjectWidget we are related to.
+ */
+ObjectWidget* MessageWidget::objectWidget(Uml::RoleType::Enum role)
+{
+ return m_pOw[role];
+}
+
+/**
+ * Set the xclicked
+ */
+void MessageWidget::setxclicked(int xclick)
+{
+ m_xclicked = xclick;
+}
+
+/**
+ * Set the yclicked
+ */
+void MessageWidget::setyclicked(int yclick)
+{
+ m_yclicked = yclick;
+}
+
+/**
+ * Event handler for mouse double click events.
+ * @param event QGraphicsSceneMouseEvent which triggered the double click event
+ */
+void MessageWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(event)
+ DEBUG(DBG_SRC) << "NOT IMPLEMENTED YET!";
+ if (m_pFText != NULL) {
+ DEBUG(DBG_SRC) << "NOT IMPLEMENTED YET - on floating text widget!";
+// QAction* action = m_pMenu->getAction(ListPopupMenu::mt_Select_Operation);
+// m_pFText->slotMenuSelection(action);
+ }
+}
+
+/**
+ * Saves to the "messagewidget" XMI element.
+ */
+void MessageWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement messageElement = qDoc.createElement(QLatin1String("messagewidget"));
+ UMLWidget::saveToXMI(qDoc, messageElement);
+ LinkWidget::saveToXMI(qDoc, messageElement);
+ if (m_pOw[Uml::RoleType::A])
+ messageElement.setAttribute(QLatin1String("widgetaid"), Uml::ID::toString(m_pOw[Uml::RoleType::A]->localID()));
+ if (m_pOw[Uml::RoleType::B])
+ messageElement.setAttribute(QLatin1String("widgetbid"), Uml::ID::toString(m_pOw[Uml::RoleType::B]->localID()));
+ UMLOperation *pOperation = operation();
+ if (pOperation)
+ messageElement.setAttribute(QLatin1String("operation"), Uml::ID::toString(pOperation->id()));
+ else
+ messageElement.setAttribute(QLatin1String("operation"), m_CustomOp);
+ messageElement.setAttribute(QLatin1String("sequencemessagetype"), m_sequenceMessageType);
+ if (m_sequenceMessageType == Uml::SequenceMessage::Lost || m_sequenceMessageType == Uml::SequenceMessage::Found) {
+ messageElement.setAttribute(QLatin1String("xclicked"), m_xclicked);
+ messageElement.setAttribute(QLatin1String("yclicked"), m_yclicked);
+ }
+
+ // save the corresponding message text
+ if (m_pFText && !m_pFText->text().isEmpty()) {
+ messageElement.setAttribute(QLatin1String("textid"), Uml::ID::toString(m_pFText->id()));
+ m_pFText->saveToXMI(qDoc, messageElement);
+ }
+
+ qElement.appendChild(messageElement);
+}
+
+/**
+ * Loads from the "messagewidget" XMI element.
+ */
+bool MessageWidget::loadFromXMI(QDomElement& qElement)
+{
+ if (!UMLWidget::loadFromXMI(qElement)) {
+ return false;
+ }
+ if (!LinkWidget::loadFromXMI(qElement)) {
+ return false;
+ }
+ QString textid = qElement.attribute(QLatin1String("textid"), QLatin1String("-1"));
+ QString widgetaid = qElement.attribute(QLatin1String("widgetaid"), QLatin1String("-1"));
+ QString widgetbid = qElement.attribute(QLatin1String("widgetbid"), QLatin1String("-1"));
+ m_CustomOp = qElement.attribute(QLatin1String("operation"));
+ QString sequenceMessageType = qElement.attribute(QLatin1String("sequencemessagetype"), QLatin1String("1001"));
+ m_sequenceMessageType = Uml::SequenceMessage::fromInt(sequenceMessageType.toInt());
+ if (m_sequenceMessageType == Uml::SequenceMessage::Lost || m_sequenceMessageType == Uml::SequenceMessage::Found) {
+ m_xclicked = qElement.attribute(QLatin1String("xclicked"), QLatin1String("-1")).toFloat();
+ m_yclicked = qElement.attribute(QLatin1String("yclicked"), QLatin1String("-1")).toFloat();
+ }
+
+ m_widgetAId = Uml::ID::fromString(widgetaid);
+ m_widgetBId = Uml::ID::fromString(widgetbid);
+ m_textId = Uml::ID::fromString(textid);
+
+ Uml::TextRole::Enum tr = Uml::TextRole::Seq_Message;
+ if (m_widgetAId == m_widgetBId)
+ tr = Uml::TextRole::Seq_Message_Self;
+
+ //now load child elements
+ QDomNode node = qElement.firstChild();
+ QDomElement element = node.toElement();
+ if (!element.isNull()) {
+ QString tag = element.tagName();
+ if (tag == QLatin1String("floatingtext") || tag == QLatin1String("UML::FloatingTextWidget")) {
+ m_pFText = new FloatingTextWidget(m_scene, tr, operationText(m_scene), m_textId);
+ m_scene->addFloatingTextWidget(m_pFText);
+ if(! m_pFText->loadFromXMI(element)) {
+ // Most likely cause: The FloatingTextWidget is empty.
+ delete m_pFText;
+ m_pFText = NULL;
+ }
+ else
+ m_pFText->setSequenceNumber(m_SequenceNumber);
+ } else {
+ uError() << "unknown tag " << tag;
+ }
+ }
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/messagewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/messagewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/messagewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/messagewidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,212 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef MESSAGEWIDGET_H
+#define MESSAGEWIDGET_H
+
+#include "umlwidget.h"
+#include "linkwidget.h"
+
+// forward declarations
+class FloatingTextWidget;
+class ObjectWidget;
+class QResizeEvent;
+class UMLOperation;
+
+/**
+ * Used to display a message on a sequence diagram. The message
+ * could be between two objects or a message that calls itself on
+ * an object. This class will only display the line that is
+ * required and the text will be setup by the @ref FloatingTextWidget
+ * widget that is passed in the constructor. A message can be
+ * synchronous (calls a method and gains control back on return,
+ * as happens in most programming languages) or asynchronous
+ * (calls a method and gains back control immediately).
+ *
+ * @short Displays a message.
+ * @author Paul Hensgen
+ * @see UMLWidget
+ * @see ObjectWidget
+ * @see FloatingTextWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class MessageWidget : public UMLWidget, public LinkWidget
+{
+ Q_OBJECT
+public:
+ MessageWidget(UMLScene * scene, ObjectWidget* a, ObjectWidget* b,
+ int y, Uml::SequenceMessage::Enum sequenceMessageType,
+ Uml::ID::Type id = Uml::ID::None);
+ MessageWidget(UMLScene * scene, Uml::SequenceMessage::Enum sequenceMessageType,
+ Uml::ID::Type id = Uml::ID::None);
+ MessageWidget(UMLScene * scene, ObjectWidget* a, int xclick, int yclick,
+ Uml::SequenceMessage::Enum sequenceMessageType,
+ Uml::ID::Type id = Uml::ID::None);
+ virtual ~MessageWidget();
+
+ virtual void setY(qreal y);
+
+ //---------- LinkWidget Interface methods implemementation from now on.
+
+ virtual void lwSetFont (QFont font);
+ virtual UMLClassifier *operationOwner();
+
+ virtual UMLOperation *operation();
+ virtual void setOperation(UMLOperation *op);
+
+ virtual QString customOpText();
+ virtual void setCustomOpText(const QString &opText);
+
+ virtual void setMessageText(FloatingTextWidget *ft);
+ virtual void setText(FloatingTextWidget *ft, const QString &newText);
+
+ virtual QString lwOperationText();
+ virtual UMLClassifier *lwClassifier();
+ virtual void setOperationText(const QString &op);
+
+ virtual void constrainTextPos(qreal &textX, qreal &textY, qreal textWidth, qreal textHeight,
+ Uml::TextRole::Enum tr);
+
+ //---------- End LinkWidget Interface methods implemementation.
+
+ /// @return Whether the message is synchronous or asynchronous
+ Uml::SequenceMessage::Enum sequenceMessageType() const {
+ return m_sequenceMessageType;
+ }
+
+ bool hasObjectWidget(ObjectWidget * w);
+
+ ObjectWidget* objectWidget(Uml::RoleType::Enum role);
+ void setObjectWidget(ObjectWidget * ow, Uml::RoleType::Enum role) ;
+
+ bool isSelf() const;
+
+ /**
+ * Returns the text widget it is related to.
+ *
+ * @return The text widget we are related to.
+ */
+ FloatingTextWidget * floatingTextWidget() {
+ return m_pFText;
+ }
+
+ /**
+ * Sets the text widget it is related to.
+ *
+ * @param f The text widget we are related to.
+ */
+ void setFloatingTextWidget(FloatingTextWidget * f) {
+ m_pFText = f;
+ }
+
+ void calculateWidget();
+
+ virtual bool activate(IDChangeLog * Log = 0);
+ void resolveObjectWidget(IDChangeLog* log);
+
+ void calculateDimensions();
+ void calculateDimensionsSynchronous();
+ void calculateDimensionsAsynchronous();
+ void calculateDimensionsCreation();
+ void calculateDimensionsLost();
+ void calculateDimensionsFound();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ void setTextPosition();
+
+ void cleanup();
+
+ void setSelected(bool _select);
+
+ int getMinY();
+ int getMaxY();
+
+ UMLWidget* onWidget(const QPointF& p);
+
+ virtual void resizeWidget(qreal newW, qreal newH);
+
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+ virtual bool loadFromXMI(QDomElement & qElement);
+
+ void setxclicked(int xclick);
+ void setyclicked(int yclick);
+
+ /**
+ * Return the xclicked
+ */
+ int getxclicked() const {
+ return m_xclicked;
+ }
+
+protected:
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+
+ virtual void moveWidgetBy(qreal diffX, qreal diffY);
+ virtual void constrainMovementForAllWidgets(qreal &diffX, qreal &diffY);
+
+ virtual QCursor resizeCursor() const;
+
+ void setLinkAndTextPos();
+
+ int constrainX(int textX, int textWidth, Uml::TextRole::Enum tr);
+
+ static void paintArrow(QPainter *p, int x, int y, int w,
+ Qt::ArrowType direction, bool useDottedLine = false);
+ static void paintsolid-kf6Arrowhead(QPainter *p, int x, int y, Qt::ArrowType direction);
+
+ void updateResizability();
+
+ void paintSynchronous(QPainter *painter, const QStyleOptionGraphicsItem *option);
+ void paintAsynchronous(QPainter *painter, const QStyleOptionGraphicsItem *option);
+ void paintCreation(QPainter *painter, const QStyleOptionGraphicsItem *option);
+ void paintLost(QPainter *painter, const QStyleOptionGraphicsItem *option);
+ void paintFound(QPainter *painter, const QStyleOptionGraphicsItem *option);
+
+ // Data loaded/saved
+ QString m_CustomOp;
+ /**
+ * Whether the message is synchronous or asynchronous
+ */
+ Uml::SequenceMessage::Enum m_sequenceMessageType;
+
+private:
+ void resizeEvent(QResizeEvent *re);
+
+ qreal constrainPositionY(qreal diffY);
+
+ void init();
+
+ ObjectWidget * m_pOw[2];
+ FloatingTextWidget * m_pFText;
+
+ int m_xclicked;
+ int m_yclicked;
+
+ /**
+ * The following variables are used by loadFromXMI() as an intermediate
+ * store. activate() resolves the IDs, i.e. after activate() the variables
+ * m_pOw[] and m_pFText can be used.
+ */
+ Uml::ID::Type m_widgetAId, m_widgetBId, m_textId;
+
+public slots:
+ void slotWidgetMoved(Uml::ID::Type id);
+ void slotMenuSelection(QAction* action);
+
+signals:
+ /**
+ * emitted when the message widget is moved up or down
+ * slots into ObjectWidget::slotMessageMoved()
+ */
+ void sigMessageMoved();
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/nodewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/nodewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/nodewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/nodewidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,156 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "nodewidget.h"
+
+// app includes
+#include "debug_utils.h"
+#include "node.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+// qt includes
+#include <QPainter>
+#include <QPolygon>
+
+DEBUG_REGISTER_DISABLED(NodeWidget)
+
+/**
+ * Constructs a NodeWidget.
+ *
+ * @param scene The parent of this NodeWidget.
+ * @param n The UMLNode this will be representing.
+ */
+NodeWidget::NodeWidget(UMLScene * scene, UMLNode *n)
+ : UMLWidget(scene, WidgetBase::wt_Node, n)
+{
+ setSize(100, 30);
+ setZValue(1); // above box but below UMLWidget because may embed widgets
+}
+
+/**
+ * Destructor.
+ */
+NodeWidget::~NodeWidget()
+{
+}
+
+/**
+ * Overrides standard method.
+ */
+void NodeWidget::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());
+ }
+ const int w = width();
+ const int h = height();
+ const int wDepth = (w/3 > DEPTH ? DEPTH : w/3);
+ const int hDepth = (h/3 > DEPTH ? DEPTH : h/3);
+ const int bodyOffsetY = hDepth;
+ const int bodyWidth = w - wDepth;
+ const int bodyHeight = h - hDepth;
+ QFont font = UMLWidget::font();
+ font.setBold(true);
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD);
+ const int fontHeight = fm.lineSpacing();
+ QString nameStr = name();
+
+ QPolygon pointArray(5);
+ pointArray.setPoint(0, 0, bodyOffsetY);
+ pointArray.setPoint(1, wDepth, 0);
+ pointArray.setPoint(2, w, 0);
+ pointArray.setPoint(3, w, bodyHeight);
+ pointArray.setPoint(4, bodyWidth, h);
+ painter->drawPolygon(pointArray);
+ painter->drawRect(0, bodyOffsetY, bodyWidth, bodyHeight);
+ painter->drawLine(w, 0, bodyWidth, bodyOffsetY);
+
+ painter->setPen(textColor());
+ painter->setFont(font);
+
+ int lines = 1;
+ if (m_umlObject) {
+ QString stereotype = m_umlObject->stereotype();
+ if (!stereotype.isEmpty()) {
+ painter->drawText(0, bodyOffsetY + (bodyHeight/2) - fontHeight,
+ bodyWidth, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true));
+ lines = 2;
+ }
+ }
+
+ if (UMLWidget::isInstance()) {
+ font.setUnderline(true);
+ painter->setFont(font);
+ nameStr = UMLWidget::instanceName() + QLatin1String(" : ") + nameStr;
+ }
+
+ if (lines == 1) {
+ painter->drawText(0, bodyOffsetY + (bodyHeight/2) - (fontHeight/2),
+ bodyWidth, fontHeight, Qt::AlignCenter, nameStr);
+ } else {
+ painter->drawText(0, bodyOffsetY + (bodyHeight/2),
+ bodyWidth, fontHeight, Qt::AlignCenter, nameStr);
+ }
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF NodeWidget::minimumSize() const
+{
+ if (m_umlObject == NULL) {
+ DEBUG(DBG_SRC) << "m_umlObject is NULL";
+ return UMLWidget::minimumSize();
+ }
+
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
+ const int fontHeight = fm.lineSpacing();
+
+ QString name = m_umlObject->name();
+ if (UMLWidget::isInstance()) {
+ name = UMLWidget::instanceName() + QLatin1String(" : ") + name;
+ }
+
+ int width = fm.width(name) + 2 * defaultMargin;
+
+ int tempWidth = 0;
+ if (!m_umlObject->stereotype().isEmpty()) {
+ tempWidth = fm.width(m_umlObject->stereotype(true));
+ }
+ if (tempWidth > width)
+ width = tempWidth;
+ width += DEPTH;
+
+ int height = (2*fontHeight) + DEPTH;
+
+ return QSizeF(width, height);
+}
+
+/**
+ * Saves to the "nodewidget" XMI element.
+ * Note: For loading we use the method inherited from UMLWidget.
+ */
+void NodeWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement conceptElement = qDoc.createElement(QLatin1String("nodewidget"));
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/nodewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/nodewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/nodewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/nodewidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef NODEWIDGET_H
+#define NODEWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLNode;
+
+/**
+ * Defines a graphical version of the Node. Most of the functionality
+ * will come from the @ref UMLNode class.
+ *
+ * @short A graphical version of a Node.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class NodeWidget : public UMLWidget
+{
+public:
+
+ NodeWidget(UMLScene * scene, UMLNode *n);
+ virtual ~NodeWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ QSizeF minimumSize() const;
+
+ static const int DEPTH = 30; ///< pixels on Z axis
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/notewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/notewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/notewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/notewidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,517 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "notewidget.h"
+
+// app includes
+#include "debug_utils.h"
+#include "docwindow.h"
+#include "listpopupmenu.h"
+#include "notedialog.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+// kde includes
+#include <KLocalizedString>
+#if QT_VERSION < 0x050000
+#include <kcolordialog.h>
+#include <kinputdialog.h>
+#endif
+
+// qt includes
+#include <QPainter>
+#if QT_VERSION >= 0x050000
+#include <QColorDialog>
+#include <QInputDialog>
+#endif
+
+NoteWidget * NoteWidget::s_pCurrentNote;
+
+/**
+ * Constructs a NoteWidget.
+ *
+ * @param scene The parent to this widget.
+ * @param noteType The NoteWidget::NoteType of this NoteWidget
+ * @param id The unique id of the widget.
+ * The default (-1) will prompt a new ID.
+ */
+NoteWidget::NoteWidget(UMLScene * scene, NoteType noteType , Uml::ID::Type id)
+ : UMLWidget(scene, WidgetBase::wt_Note, id),
+ m_diagramLink(Uml::ID::None),
+ m_noteType(noteType)
+{
+ setZValue(20); //make sure always on top.
+}
+
+/**
+ * Destructor.
+ */
+NoteWidget::~NoteWidget()
+{
+}
+
+/**
+ * Override default method.
+ */
+void NoteWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ const int margin = 10;
+ int w = width();
+ int h = height();
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ QPolygon poly(6);
+ poly.setPoint(0, 0, 0);
+ poly.setPoint(1, 0, h);
+ poly.setPoint(2, w, h);
+ poly.setPoint(3, w, margin);
+ poly.setPoint(4, w - margin, 0);
+ poly.setPoint(5, 0, 0);
+
+ setPenFromSettings(painter);
+ if (UMLWidget::useFillColor()) {
+ QBrush brush(UMLWidget::fillColor());
+ painter->setBrush(brush);
+ painter->drawPolygon(poly);
+ } else
+ painter->drawPolyline(poly);
+ painter->drawLine(w - margin, 0, w - margin, margin);
+ painter->drawLine(w - margin, margin, w, margin);
+ painter->setPen(textColor());
+ switch(m_noteType) {
+ case NoteWidget::PreCondition :
+ painter->drawText(0, margin, w, fontHeight, Qt::AlignCenter, QLatin1String("<< precondition >>"));
+ break;
+ case NoteWidget::PostCondition :
+ painter->drawText(0, margin, w, fontHeight, Qt::AlignCenter, QLatin1String("<< postcondition >>"));
+ break;
+ case NoteWidget::Transformation :
+ painter->drawText(0, margin, w, fontHeight, Qt::AlignCenter, QLatin1String("<< transformation >>"));
+ break;
+ case NoteWidget::Normal :
+ default :
+ break;
+ }
+
+ UMLWidget::paint(painter, option, widget);
+
+// paintText(&p, 0, 0);
+ paintTextWordWrap(painter);
+}
+
+/**
+ * Returns the type of note.
+ */
+NoteWidget::NoteType NoteWidget::noteType() const
+{
+ return m_noteType;
+}
+
+/**
+ * Converts a string to NoteWidget::NoteType.
+ */
+NoteWidget::NoteType NoteWidget::stringToNoteType(const QString& noteType)
+{
+ if (noteType == QLatin1String("Precondition"))
+ return NoteWidget::PreCondition;
+ else if (noteType == QLatin1String("Postcondition"))
+ return NoteWidget::PostCondition;
+ else if (noteType == QLatin1String("Transformation"))
+ return NoteWidget::Transformation;
+ else
+ return NoteWidget::Normal;
+}
+
+/**
+ * Sets the type of note.
+ */
+void NoteWidget::setNoteType(NoteType noteType)
+{
+ m_noteType = noteType;
+}
+
+/**
+ * Sets the type of note.
+ */
+void NoteWidget::setNoteType(const QString& noteType)
+{
+ setNoteType(stringToNoteType(noteType));
+}
+
+/**
+ * Return the ID of the diagram hyperlinked to this note.
+ *
+ * @return ID of an UMLView, or Uml::ID::None if no
+ * hyperlink is set.
+ */
+Uml::ID::Type NoteWidget::diagramLink() const
+{
+ return m_diagramLink;
+}
+
+/**
+ * Set the ID of the diagram hyperlinked to this note.
+ * To switch off the hyperlink, set this to Uml::id_None.
+ *
+ * @param viewID ID of an UMLScene.
+ */
+void NoteWidget::setDiagramLink(Uml::ID::Type viewID)
+{
+ UMLDoc *umldoc = UMLApp::app()->document();
+ UMLView *view = umldoc->findView(viewID);
+ if (view == NULL) {
+ uError() << "no view found for viewID " << Uml::ID::toString(viewID);
+ return;
+ }
+ QString linkText(QLatin1String("Diagram: ") + view->umlScene()->name());
+ setDocumentation(linkText);
+ m_diagramLink = viewID;
+ update();
+}
+
+/**
+ * Display a dialog box to allow the user to choose the note's type.
+ */
+void NoteWidget::askForNoteType(UMLWidget* &targetWidget)
+{
+ static const QStringList list = QStringList() << i18n("Precondition")
+ << i18n("Postcondition")
+ << i18n("Transformation");
+ bool pressedOK = false;
+
+#if QT_VERSION >= 0x050000
+ QString type = QInputDialog::getItem (UMLApp::app(),
+ i18n("Note Type"), i18n("Select the Note Type"), list,
+ 0, false, &pressedOK);
+#else
+ QString type = KInputDialog::getItem (i18n("Note Type"), i18n("Select the Note Type"), list,
+ 0, false, &pressedOK, UMLApp::app());
+#endif
+
+ if (pressedOK) {
+ dynamic_cast<NoteWidget*>(targetWidget)->setNoteType(type);
+ } else {
+ targetWidget->cleanup();
+ delete targetWidget;
+ targetWidget = 0;
+ }
+}
+
+/**
+ * Loads a "notewidget" XMI element.
+ */
+bool NoteWidget::loadFromXMI(QDomElement & qElement)
+{
+ if (!UMLWidget::loadFromXMI(qElement))
+ return false;
+ setZValue(20); //make sure always on top.
+ setDocumentation(qElement.attribute(QLatin1String("text")));
+ QString diagramlink = qElement.attribute(QLatin1String("diagramlink"));
+ if (!diagramlink.isEmpty())
+ m_diagramLink = Uml::ID::fromString(diagramlink);
+ QString type = qElement.attribute(QLatin1String("noteType"));
+ setNoteType((NoteType)type.toInt());
+ return true;
+}
+
+/**
+ * Saves to the "notewidget" XMI element.
+ */
+void NoteWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement noteElement = qDoc.createElement(QLatin1String("notewidget"));
+ UMLWidget::saveToXMI(qDoc, noteElement);
+ noteElement.setAttribute(QLatin1String("text"), documentation());
+ if (m_diagramLink != Uml::ID::None)
+ noteElement.setAttribute(QLatin1String("diagramlink"), Uml::ID::toString(m_diagramLink));
+ noteElement.setAttribute(QLatin1String("noteType"), m_noteType);
+ qElement.appendChild(noteElement);
+}
+
+/**
+ * Show a properties dialog for a NoteWidget.
+ */
+void NoteWidget::showPropertiesDialog()
+{
+ NoteDialog * dlg = 0;
+ UMLApp::app()->docWindow()->updateDocumentation(false);
+ dlg = new NoteDialog(umlScene()->activeView(), this);
+ if (dlg->exec()) {
+ UMLApp::app()->docWindow()->showDocumentation(this, true);
+ UMLApp::app()->document()->setModified(true);
+ update();
+ }
+ delete dlg;
+}
+
+/**
+ * Will be called when a menu selection has been made from the popup
+ * menu.
+ *
+ * @param action The action that has been selected.
+ */
+void NoteWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_Rename:
+ showPropertiesDialog();
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ break;
+ }
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF NoteWidget::minimumSize() const
+{
+ int width = 60;
+ int height = 30;
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int textWidth = fm.width(documentation());
+ if (m_noteType == PreCondition) {
+ const int widthtemp = fm.width(QLatin1String("<< precondition >>"));
+ width = textWidth > widthtemp ? textWidth : widthtemp;
+ width += 10;
+ }
+ else if (m_noteType == PostCondition) {
+ const int widthtemp = fm.width(QLatin1String("<< postcondition >>"));
+ width = textWidth > widthtemp ? textWidth : widthtemp;
+ width += 10;
+ }
+ else if (m_noteType == Transformation) {
+ const int widthtemp = fm.width(QLatin1String("<< transformation >>"));
+ width = textWidth > widthtemp ? textWidth : widthtemp;
+ width += 10;
+ }
+ return QSizeF(width, height);
+}
+
+/**
+ * Calculate content related size of widget.
+ * Overrides method from UMLWidget.
+ */
+QSizeF NoteWidget::calculateSize(bool withExtensions /* = true */) const
+{
+ Q_UNUSED(withExtensions)
+ int width = this->width();
+ int height = this->height();
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int margin = fm.width(QLatin1String("W"));
+ QSize size = fm.size (0, documentation());
+ const int textWidth = size.width();
+ if (m_noteType == PreCondition) {
+ const int widthtemp = fm.width(QLatin1String("<< precondition >>"));
+ width = textWidth > widthtemp ? textWidth : widthtemp;
+ width += 2 * margin;
+ }
+ else if (m_noteType == PostCondition) {
+ const int widthtemp = fm.width(QLatin1String("<< postcondition >>"));
+ width = textWidth > widthtemp ? textWidth : widthtemp;
+ width += 2 * margin;
+ }
+ else if (m_noteType == Transformation) {
+ const int widthtemp = fm.width(QLatin1String("<< transformation >>"));
+ width = textWidth > widthtemp ? textWidth : widthtemp;
+ width += 2 * margin;
+ }
+ return QSizeF(width, height);
+}
+
+/**
+ * Paints the text. Auxiliary to paint().
+ * Implemented without word wrap.
+ */
+void NoteWidget::paintText(QPainter *painter)
+{
+ if (painter == 0) {
+ return;
+ }
+
+ QString text = documentation();
+ if (text.length() == 0) {
+ return;
+ }
+
+ painter->setPen(Qt::black);
+ QFont font = UMLWidget::font();
+ painter->setFont(font);
+
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int margin = fm.width(QLatin1String("W"));
+ const QSize textSize = fm.size(Qt::TextExpandTabs, text);
+
+ const int width = this->width() - margin * 2;
+ const int height = this->height() - fontHeight;
+ int textY = fontHeight / 2;
+ int textX = margin;
+
+ if ((textSize.width() < width) && (textSize.height() < height)) {
+ // the entire text is small enough - draw it
+ painter->drawText(textX, textY,
+ textSize.width(), textSize.height(),
+ Qt::AlignLeft, text);
+ }
+ else {
+ // not all text can be drawn
+ QStringList lines = text.split(QLatin1Char('\n'));
+ foreach(const QString& line, lines) {
+ int lineWidth = fm.width(line);
+ if (lineWidth < width) {
+ // line is small enough - draw it
+ painter->drawText(textX, textY,
+ textSize.width(), fontHeight,
+ Qt::AlignLeft, line);
+ }
+ else {
+ // draw a smaller line
+ for(int len = line.length(); len > 0; --len) {
+ QString smallerLine = line.left(len);
+ int smallerLineWidth = fm.width(smallerLine);
+ if (smallerLineWidth < width) {
+ // line is small enough - draw it
+ painter->drawText(textX, textY,
+ width, fontHeight,
+ Qt::AlignLeft, smallerLine);
+ }
+ }
+ }
+ textY += fontHeight;
+ if (textY > height) {
+ // skip the next lines - size is not enough
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Paints the text. Auxiliary to paint().
+ * Implemented with word wrap.
+ */
+void NoteWidget::paintTextWordWrap(QPainter *painter)
+{
+ if (painter == 0) {
+ return;
+ }
+ QString text = documentation();
+ if (text.length() == 0) {
+ return;
+ }
+ // Implement word wrap for text as follows:
+ // wrap at width on whole words.
+ // if word is wider than width then clip word
+ // if reach height exit and don't print anymore
+ // start new line on \n character
+ painter->setPen(Qt::black);
+ QFont font = UMLWidget::font();
+ painter->setFont(font);
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ QString word;
+ QString fullLine;
+ QString testCombineLine;
+ const int margin = fm.width(QLatin1String("W"));
+ int textY = fontHeight / 2;
+ int textX = margin;
+ const int width = this -> width() - margin * 2;
+ const int height = this -> height() - fontHeight;
+ QChar returnChar = QChar::fromLatin1('\n');
+ QChar c;
+
+ for (int i = 0; i <= text.length(); ++i) {
+ if (i < text.length()) {
+ c = text[i];
+ } else {
+ // all chars of text have been handled already ->
+ // perform this last run to spool current content of "word"
+ c = returnChar;
+ }
+ if (c == returnChar || c.isSpace()) {
+ // new word delimiter found -> it is time to decide on word wrap
+ testCombineLine = fullLine + QLatin1Char(' ') + word;
+ int textWidth = fm.width(testCombineLine);
+ if (textX + textWidth > width) {
+ // combination of "fullLine" and "word" doesn't fit into one line ->
+ // print "fullLine" in current line, update write position to next line
+ // and decide then on following actions
+ painter->drawText(textX, textY,
+ textWidth, fontHeight, Qt::AlignLeft, fullLine);
+ fullLine = word;
+ word = QString();
+ // update write position
+ textX = margin;
+ textY += fontHeight;
+ if (textY > height)
+ return;
+ // in case of c==newline ->
+ // print "word" and set write position one additional line lower
+ if (c == returnChar) {
+ // print "word" - which is now "fullLine" and set to next line
+ painter->drawText(textX, textY,
+ textWidth, fontHeight, Qt::AlignLeft, fullLine);
+ fullLine = QString();
+ textX = margin;
+ textY += fontHeight;
+ if(textY > height) return;
+ }
+ }
+ else if (c == returnChar) {
+ // newline found and combination of "fullLine" and "word" fits
+ // in one line
+ painter->drawText(textX, textY,
+ textWidth, fontHeight, Qt::AlignLeft, testCombineLine);
+ fullLine = word = QString();
+ textX = margin;
+ textY += fontHeight;
+ if (textY > height)
+ return;
+ } else {
+ // word delimiter found, and combination of "fullLine", space and "word" fits into one line
+ fullLine = testCombineLine;
+ word = QString();
+ }
+ } else {
+ // no word delimiter found --> add current char to "word"
+ if (c != QLatin1Char('\0'))
+ word += c;
+ }
+ }//end for
+}
+
+/**
+ * Event handler for moude double click events.
+ *
+ * @param event The QGraphicsSceneMouseEvent event.
+ */
+void NoteWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ if (m_diagramLink == Uml::ID::None) {
+ showPropertiesDialog();
+ } else {
+ UMLDoc *umldoc = UMLApp::app()->document();
+ umldoc->changeCurrentView(m_diagramLink);
+ }
+ event->accept();
+ }
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/notewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/notewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/notewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/notewidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef NOTEWIDGET_H
+#define NOTEWIDGET_H
+
+//app includes
+#include "umlwidget.h"
+
+// Qt forward declarations
+class QPainter;
+
+/**
+ * Displays a note box to allow multiple lines of text to be displayed.
+ * These widgets are diagram specific. They will still need a unique id
+ * from the @ref UMLDoc class for deletion and other purpose-kf6s.
+ *
+ * @short Displays a note box.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class NoteWidget : public UMLWidget
+{
+ Q_OBJECT
+public:
+
+ /// This enum type is used to specify the type of note.
+ enum NoteType
+ {
+ Normal,
+ PreCondition,
+ PostCondition,
+ Transformation
+ };
+
+ explicit NoteWidget(UMLScene * scene, NoteWidget::NoteType noteType = Normal,
+ Uml::ID::Type id = Uml::ID::None);
+ virtual ~NoteWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ static NoteType stringToNoteType(const QString& noteType);
+
+ NoteType noteType() const;
+ void setNoteType(NoteType noteType);
+ void setNoteType(const QString& noteType);
+
+ Uml::ID::Type diagramLink() const;
+ void setDiagramLink(Uml::ID::Type viewID);
+
+ void askForNoteType(UMLWidget* &targetWidget);
+
+ virtual void showPropertiesDialog();
+
+ virtual bool loadFromXMI(QDomElement & qElement);
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ static NoteWidget *s_pCurrentNote;
+
+public Q_SLOTS:
+ void slotMenuSelection(QAction* action);
+
+protected:
+ virtual QSizeF minimumSize() const;
+ virtual QSizeF calculateSize(bool withExtensions = true) const;
+ void paintText(QPainter *painter);
+ void paintTextWordWrap(QPainter *painter);
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+
+private:
+ Uml::ID::Type m_diagramLink; ///< The diagram/scene this note links to.
+ NoteType m_noteType; ///< The type of note. @see NoteWidget::NoteType
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/objectnodewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/objectnodewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/objectnodewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/objectnodewidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,377 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "objectnodewidget.h"
+
+// app includes
+#include "debug_utils.h"
+#include "docwindow.h"
+#include "dialog_utils.h"
+#include "listpopupmenu.h"
+#include "objectnodedialog.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+// kde includes
+#include <KLocalizedString>
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+#include <QPainter>
+#include <QPointer>
+
+#define OBJECTNODE_MARGIN 5
+#define OBJECTNODE_WIDTH 30
+#define OBJECTNODE_HEIGHT 10
+
+/**
+ * Creates a Object Node widget.
+ *
+ * @param scene The parent of the widget.
+ * @param objectNodeType The type of object node
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+ObjectNodeWidget::ObjectNodeWidget(UMLScene * scene, ObjectNodeType objectNodeType, Uml::ID::Type id)
+ : UMLWidget(scene, WidgetBase::wt_ObjectNode, id)
+{
+ setObjectNodeType(objectNodeType);
+ setState(QString());
+}
+
+/**
+ * Destructor.
+ */
+ObjectNodeWidget::~ObjectNodeWidget()
+{
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void ObjectNodeWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ int w = width();
+ int h = height();
+
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ int textStartY = (h / 2) - (fontHeight / 2);
+
+ setPenFromSettings(painter);
+
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ }
+
+ painter->drawRect(0, 0, w, h);
+ painter->setFont(UMLWidget::font());
+
+ switch (m_objectNodeType)
+ {
+ case Normal : break;
+ case Buffer :
+ {
+ painter->setPen(textColor());
+ painter->drawText(OBJECTNODE_MARGIN, (textStartY/2), w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, QLatin1String("<< centralBuffer >>"));
+ painter->drawText(OBJECTNODE_MARGIN, (textStartY/2) + fontHeight + 5, w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, name());
+ }
+ break;
+ case Data :
+ {
+ painter->setPen(textColor());
+ painter->drawText(OBJECTNODE_MARGIN, (textStartY/2), w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, QLatin1String("<< datastore >>"));
+ painter->drawText(OBJECTNODE_MARGIN, (textStartY/2) + fontHeight + 5, w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, name());
+ }
+ break;
+ case Flow :
+ {
+ QString objectflow_value;
+ if (state() == QLatin1String("-") || state().isEmpty())
+ {
+ objectflow_value = QLatin1Char(' ');
+ }
+ else
+ {
+ objectflow_value = QLatin1Char('[') + state() + QLatin1Char(']');
+ }
+
+ painter->drawLine(10, h/2, w-10, h/2);
+ painter->setPen(textColor());
+ painter->setFont(UMLWidget::font());
+ painter->drawText(OBJECTNODE_MARGIN, textStartY/2 - OBJECTNODE_MARGIN, w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, name());
+ painter->drawText(OBJECTNODE_MARGIN, textStartY/2 + textStartY + OBJECTNODE_MARGIN, w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, objectflow_value);
+ }
+ break;
+ }
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF ObjectNodeWidget::minimumSize() const
+{
+ int widthtmp = 10, height = 10, width=10;
+ if (m_objectNodeType == Buffer) {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int textWidth = fm.width(QLatin1String("<< centralBuffer >>"));
+ const int namewidth = fm.width(name());
+ height = fontHeight * 2;
+ widthtmp = textWidth > OBJECTNODE_WIDTH ? textWidth : OBJECTNODE_WIDTH;
+ width = namewidth > widthtmp ? namewidth : widthtmp;
+ height = height > OBJECTNODE_HEIGHT ? height : OBJECTNODE_HEIGHT;
+ width += OBJECTNODE_MARGIN * 2;
+ height += OBJECTNODE_MARGIN * 2 + 5;
+ } else if (m_objectNodeType == Data) {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int textWidth = fm.width(QLatin1String("<< datastore >>"));
+ const int namewidth = fm.width(name());
+ height = fontHeight * 2;
+ widthtmp = textWidth > OBJECTNODE_WIDTH ? textWidth : OBJECTNODE_WIDTH;
+ width = namewidth > widthtmp ? namewidth : widthtmp;
+ height = height > OBJECTNODE_HEIGHT ? height : OBJECTNODE_HEIGHT;
+ width += OBJECTNODE_MARGIN * 2;
+ height += OBJECTNODE_MARGIN * 2 + 5;
+ } else if (m_objectNodeType == Flow) {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int textWidth = fm.width(QLatin1Char('[') + state() + QLatin1Char(']'));
+ const int namewidth = fm.width(name());
+ height = fontHeight * 2;
+ widthtmp = textWidth > OBJECTNODE_WIDTH ? textWidth : OBJECTNODE_WIDTH;
+ width = namewidth > widthtmp ? namewidth : widthtmp;
+ height = height > OBJECTNODE_HEIGHT ? height : OBJECTNODE_HEIGHT;
+ width += OBJECTNODE_MARGIN * 2;
+ height += OBJECTNODE_MARGIN * 4;
+ }
+
+ return QSizeF(width, height);
+}
+
+/**
+ * Returns the type of object node.
+ */
+ObjectNodeWidget::ObjectNodeType ObjectNodeWidget::objectNodeType() const
+{
+ return m_objectNodeType;
+}
+
+/**
+ * Returns the type of object node.
+ */
+ObjectNodeWidget::ObjectNodeType ObjectNodeWidget::toObjectNodeType(const QString& type)
+{
+ if (type == QLatin1String("Central buffer"))
+ return ObjectNodeWidget::Buffer;
+ if (type == QLatin1String("Data store"))
+ return ObjectNodeWidget::Data;
+ if (type == QLatin1String("Object Flow"))
+ return ObjectNodeWidget::Flow;
+ // Shouldn't happen
+ Q_ASSERT(0);
+ return ObjectNodeWidget::Flow;
+}
+
+/**
+ * Sets the type of object node.
+ */
+void ObjectNodeWidget::setObjectNodeType(ObjectNodeType objectNodeType)
+{
+ m_objectNodeType = objectNodeType;
+ UMLWidget::m_resizable = true;
+}
+
+/**
+ * Sets the type of object node.
+ */
+void ObjectNodeWidget::setObjectNodeType(const QString& type)
+{
+ setObjectNodeType(ObjectNodeWidget::toObjectNodeType(type));
+}
+
+/**
+ * Sets the state of an object node when it's an objectflow.
+ */
+void ObjectNodeWidget::setState(const QString& state)
+{
+ m_state = state;
+ updateGeometry();
+}
+
+/**
+ * Returns the state of object node.
+ */
+QString ObjectNodeWidget::state() const
+{
+ return m_state;
+}
+
+/**
+ * Captures any popup menu signals for menus it created.
+ */
+void ObjectNodeWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_Rename:
+ {
+ bool ok = false;
+ QString text = name();
+#if QT_VERSION >= 0x050000
+ text = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter Object Node Name"),
+ i18n("Enter the name of the object node :"),
+ QLineEdit::Normal,
+ name(), &ok);
+#else
+ text = KInputDialog::getText(i18n("Enter Object Node Name"),
+ i18n("Enter the name of the object node :"),
+ name(), &ok);
+#endif
+ if (ok && !text.isEmpty()) {
+ setName(text);
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ showPropertiesDialog();
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ }
+}
+
+/**
+ * Show a properties dialog for an ObjectNodeWidget.
+ */
+void ObjectNodeWidget::showPropertiesDialog()
+{
+ UMLApp::app()->docWindow()->updateDocumentation(false);
+
+ QPointer<ObjectNodeDialog> dialog = new ObjectNodeDialog(UMLApp::app()->currentView(), this);
+ if (dialog->exec() && dialog->getChangesMade()) {
+ UMLApp::app()->docWindow()->showDocumentation(this, true);
+ UMLApp::app()->document()->setModified(true);
+ }
+ delete dialog;
+}
+
+/**
+ * Saves the widget to the "objectnodewidget" XMI element.
+ */
+void ObjectNodeWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement objectNodeElement = qDoc.createElement(QLatin1String("objectnodewidget"));
+ UMLWidget::saveToXMI(qDoc, objectNodeElement);
+ objectNodeElement.setAttribute(QLatin1String("objectnodename"), m_Text);
+ objectNodeElement.setAttribute(QLatin1String("documentation"), m_Doc);
+ objectNodeElement.setAttribute(QLatin1String("objectnodetype"), m_objectNodeType);
+ objectNodeElement.setAttribute(QLatin1String("objectnodestate"), m_state);
+ qElement.appendChild(objectNodeElement);
+}
+
+/**
+ * Loads the widget from the "objectnodewidget" XMI element.
+ */
+bool ObjectNodeWidget::loadFromXMI(QDomElement& qElement)
+{
+ if(!UMLWidget::loadFromXMI(qElement) )
+ return false;
+ m_Text = qElement.attribute(QLatin1String("objectnodename"));
+ m_Doc = qElement.attribute(QLatin1String("documentation"));
+ QString type = qElement.attribute(QLatin1String("objectnodetype"), QLatin1String("1"));
+ m_state = qElement.attribute(QLatin1String("objectnodestate"));
+ setObjectNodeType((ObjectNodeType)type.toInt());
+ return true;
+}
+
+/**
+ * Open a dialog box to select the objectNode type (Data, Buffer or Flow).
+ */
+void ObjectNodeWidget::askForObjectNodeType(UMLWidget* &targetWidget)
+{
+ bool pressedOK = false;
+ int current = 0;
+ const QStringList list = QStringList()
+ << QLatin1String("Central buffer")
+ << QLatin1String("Data store")
+ << QLatin1String("Object Flow");
+
+#if QT_VERSION >= 0x050000
+ QString type = QInputDialog::getItem (UMLApp::app(),
+ i18n("Select Object node type"), i18n("Select the object node type"),
+ list, current, false, &pressedOK);
+
+#else
+ QString type = KInputDialog::getItem (i18n("Select Object node type"), i18n("Select the object node type"), list, current, false, &pressedOK, UMLApp::app());
+#endif
+
+ if (pressedOK) {
+ dynamic_cast<ObjectNodeWidget*>(targetWidget)->setObjectNodeType(type);
+ if (type == QLatin1String("Data store"))
+ Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the name of the data store node"), i18n("Enter the name of the data store node"), i18n("data store name"));
+ if (type == QLatin1String("Central buffer"))
+ Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the name of the buffer node"), i18n("Enter the name of the buffer"), i18n("centralBuffer"));
+ if (type == QLatin1String("Object Flow")) {
+ Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the name of the object flow"), i18n("Enter the name of the object flow"), i18n("object flow"));
+ askStateForWidget();
+ }
+ } else {
+ targetWidget->cleanup();
+ delete targetWidget;
+ targetWidget = NULL;
+ }
+}
+
+/**
+ * Open a dialog box to input the state of the widget.
+ * This box is shown only if m_objectNodeType = Flow.
+ */
+void ObjectNodeWidget::askStateForWidget()
+{
+ bool pressedOK = false;
+#if QT_VERSION >= 0x050000
+ QString state = QInputDialog::getText(UMLApp::app(),
+ i18n("Enter Object Flow State"), i18n("Enter State (keep '-' if there is no state for the object) "),
+ QLineEdit::Normal,
+ i18n("-"), &pressedOK);
+#else
+ QString state = KInputDialog::getText(i18n("Enter Object Flow State"), i18n("Enter State (keep '-' if there is no state for the object) "), i18n("-"), &pressedOK, UMLApp::app());
+#endif
+
+ if (pressedOK) {
+ setState(state);
+ } else {
+ cleanup();
+ }
+}
+
+void ObjectNodeWidget::slotOk()
+{
+ // kdialog-kf6::accept();
+}
+
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/objectnodewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/objectnodewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/objectnodewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/objectnodewidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef OBJECTNODEWIDGET_H
+#define OBJECTNODEWIDGET_H
+
+#include "umlwidget.h"
+
+/**
+ * This class is the graphical version of a UML Object Node. A ObjectNodeWidget is created
+ * by a @ref UMLView. An ObjectNodeWidget belongs to only one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
+ *
+ * The ObjectNodeWidget class inherits from the @ref UMLWidget class which adds most of the functionality
+ * to this class.
+ *
+ * @short A graphical version of a UML Activity.
+ * @author Florence Mattler <florence.mattler@libertysurf.fr>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class ObjectNodeWidget : public UMLWidget
+{
+ Q_OBJECT
+
+public:
+ enum ObjectNodeType
+ {
+ Normal,
+ Data,
+ Buffer,
+ Flow
+ };
+
+ explicit ObjectNodeWidget(UMLScene * scene, ObjectNodeType objectNodeType = Normal, Uml::ID::Type id = Uml::ID::None);
+ virtual ~ObjectNodeWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ ObjectNodeType objectNodeType() const;
+ static ObjectNodeType toObjectNodeType(const QString& type);
+
+ void setObjectNodeType(ObjectNodeType objectNodeType);
+ void setObjectNodeType(const QString& type) ;
+
+ void setState(const QString& state);
+ QString state() const;
+
+ virtual void showPropertiesDialog();
+
+ void askStateForWidget();
+ void askForObjectNodeType(UMLWidget* &targetWidget);
+
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+ virtual bool loadFromXMI(QDomElement& qElement);
+
+protected:
+ QSizeF minimumSize() const;
+
+public slots:
+ void slotMenuSelection(QAction* action);
+ void slotOk();
+
+private:
+ ObjectNodeType m_objectNodeType; ///< type of object node
+ QString m_state; ///< state of object node when it's an objectFlow
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/objectwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/objectwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/objectwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/objectwidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,710 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header file
+#include "objectwidget.h"
+
+// local includes
+#include "classpropertiesdialog.h"
+#include "debug_utils.h"
+#include "docwindow.h"
+#include "listpopupmenu.h"
+#include "messagewidget.h"
+#include "seqlinewidget.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlobject.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+// kde includes
+#include <KLocalizedString>
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+#include <QPointer>
+#include <QPainter>
+#include <QValidator>
+
+#define O_MARGIN 5
+#define O_WIDTH 40
+#define A_WIDTH 20
+#define A_HEIGHT 40
+#define A_MARGIN 5
+
+DEBUG_REGISTER_DISABLED(ObjectWidget)
+
+/**
+ * The number of pixels margin between the lowest message
+ * and the bottom of the vertical line
+ */
+static const int sequenceLineMargin = 20;
+
+/**
+ * Creates an ObjectWidget.
+ *
+ * @param scene The parent to this object.
+ * @param o The object it will be representing.
+ */
+ObjectWidget::ObjectWidget(UMLScene * scene, UMLObject *o)
+ : UMLWidget(scene, WidgetBase::wt_Object, o),
+ m_multipleInstance(false),
+ m_drawAsActor(false),
+ m_showDestruction(false),
+ m_isOnDestructionBox(false)
+{
+ if (m_scene && (m_scene->type() == Uml::DiagramType::Sequence)) {
+ m_pLine = new SeqLineWidget( m_scene, this );
+ m_pLine->setStartPoint(x() + width() / 2, y() + height());
+ } else {
+ m_pLine = 0;
+ }
+}
+
+/**
+ * Destructor.
+ */
+ObjectWidget::~ObjectWidget()
+{
+ cleanup();
+}
+
+/**
+ * Sets whether representing a multi-instance object.
+ *
+ * @param multiple Object state. true- multi, false - single.
+ */
+void ObjectWidget::setMultipleInstance(bool multiple)
+{
+ //make sure only calling this in relation to an object on a collab. diagram
+ if (m_scene && (m_scene->type() == Uml::DiagramType::Collaboration)) {
+ m_multipleInstance = multiple;
+ updateGeometry();
+ update();
+ }
+}
+
+/**
+ * Returns whether object is representing a multi-object.
+ *
+ * @return True if object is representing a multi-object.
+ */
+bool ObjectWidget::multipleInstance() const
+{
+ return m_multipleInstance;
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Moves the widget to a new position using the difference between the
+ * current position and the new position.
+ * Y position is ignored, and widget is only moved along X axis.
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position
+ * (isn't used).
+ */
+void ObjectWidget::moveWidgetBy(qreal diffX, qreal diffY)
+{
+ setX(x() + diffX);
+ if (m_scene && (m_scene->type() != Uml::DiagramType::Sequence)) {
+ setY(y() + diffY);
+ }
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Modifies the value of the diffX and diffY variables used to move the widgets.
+ * All the widgets are constrained to be moved only in X axis (diffY is set to 0).
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+void ObjectWidget::constrainMovementForAllWidgets(qreal &diffX, qreal &diffY)
+{
+ Q_UNUSED(diffX);
+ if (m_scene && (m_scene->type() == Uml::DiagramType::Sequence)) {
+ diffY = 0;
+ }
+}
+
+/**
+ * Override default method.
+ */
+void ObjectWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ if (m_drawAsActor)
+ paintActor(painter);
+ else
+ paintObject(painter);
+
+ setPenFromSettings(painter);
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Handles a popup menu selection.
+ */
+void ObjectWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_Rename_Object:
+ {
+ bool ok;
+ QRegExpValidator* validator = new QRegExpValidator(QRegExp(QLatin1String(".*")), 0);
+#if QT_VERSION >= 0x050000
+ QString name = QInputDialog::getText(m_scene->activeView(),
+ i18n("Rename Object"),
+ i18n("Enter object name:"),
+ QLineEdit::Normal,
+ m_instanceName,
+ &ok);
+#else
+ QString name = KInputDialog::getText
+ (i18n("Rename Object"),
+ i18n("Enter object name:"),
+ m_instanceName,
+ &ok,
+ m_scene->activeView(),
+ validator);
+#endif
+ if (ok) {
+ m_instanceName = name;
+ updateGeometry();
+ moveEvent(0);
+ update();
+ UMLApp::app()->document()->setModified(true);
+ }
+ delete validator;
+ break;
+ }
+ case ListPopupMenu::mt_Properties:
+ showPropertiesDialog();
+ updateGeometry();
+ moveEvent(0);
+ update();
+ break;
+
+ case ListPopupMenu::mt_Up:
+ tabUp();
+ break;
+
+ case ListPopupMenu::mt_Down:
+ tabDown();
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ break;
+ }
+}
+
+/**
+ * Overrides method from UMLWidget
+ */
+QSizeF ObjectWidget::minimumSize() const
+{
+ int width, height;
+ const QFontMetrics &fm = getFontMetrics(FT_UNDERLINE);
+ const int fontHeight = fm.lineSpacing();
+ const QString t = m_instanceName + QLatin1String(" : ") + name();
+ const int textWidth = fm.width(t);
+ if (m_drawAsActor) {
+ width = textWidth > A_WIDTH?textWidth:A_WIDTH;
+ height = A_HEIGHT + fontHeight + A_MARGIN;
+ width += A_MARGIN * 2;
+ } else {
+ width = textWidth > O_WIDTH?textWidth:O_WIDTH;
+ height = fontHeight + O_MARGIN * 2;
+ width += O_MARGIN * 2;
+ if (m_multipleInstance) {
+ width += 10;
+ height += 10;
+ }
+ }//end else drawasactor
+
+ return QSizeF(width, height);
+}
+
+/**
+ * Sets whether to draw as an Actor.
+ *
+ * @param drawAsActor True if widget shall be drawn as an actor.
+ */
+void ObjectWidget::setDrawAsActor(bool drawAsActor)
+{
+ m_drawAsActor = drawAsActor;
+ updateGeometry();
+}
+
+/**
+ * Returns whether to draw as an Actor or not.
+ *
+ * @return True if widget is drawn as an actor.
+ */
+bool ObjectWidget::drawAsActor() const
+{
+ return m_drawAsActor;
+}
+
+/**
+ * Activate the object after serializing it from a QDataStream
+ */
+bool ObjectWidget::activate(IDChangeLog* ChangeLog /*= 0*/)
+{
+ if (! UMLWidget::activate(ChangeLog))
+ return false;
+ if (m_showDestruction && m_pLine)
+ m_pLine->setupDestructionBox();
+ moveEvent(0);
+ return true;
+}
+
+/**
+ * Sets the x-coordinate.
+ * Reimplements the method from UMLWidget.
+ *
+ * @param x The x-coordinate to be set.
+ */
+void ObjectWidget::setX(qreal x)
+{
+ UMLWidget::setX(x);
+ moveEvent(0);
+}
+
+/**
+ * Sets the y-coordinate.
+ * Reimplements the method from UMLWidget.
+ *
+ * @param y The y-coordinate to be set.
+ */
+void ObjectWidget::setY(qreal y)
+{
+ UMLWidget::setY(y);
+ if (!UMLApp::app()->document()->loading())
+ moveEvent(0);
+}
+
+/**
+ * Return the x coordinate of the widgets center.
+ * @return The x-coordinate of the widget center.
+ */
+qreal ObjectWidget::centerX()
+{
+ return x() + width()/2;
+}
+
+/**
+ * Overrides the standard operation.
+ */
+void ObjectWidget::moveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(event)
+ emit sigWidgetMoved(m_nLocalID);
+ if (m_pLine) {
+ m_pLine->setStartPoint(x() + width() / 2, y() + height());
+ }
+}
+
+/**
+ * Overrides the standard operation.
+ */
+void ObjectWidget::mousePressEvent(QGraphicsSceneMouseEvent *me)
+{
+ UMLWidget::mousePressEvent(me);
+ m_isOnDestructionBox = false;
+ if (m_pLine && m_pLine->onDestructionBox(me->scenePos())) {
+ m_isOnDestructionBox = true;
+ qreal oldX = x() + width() / 2;
+ qreal oldY = getEndLineY() - 10;
+ m_oldPos = QPointF(oldX, oldY);
+ }
+}
+
+/**
+ * Overrides the standard operation.
+ */
+void ObjectWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* me)
+{
+ if (m_inResizeArea) {
+ DEBUG(DBG_SRC) << "resizing...";
+ resize(me);
+ moveEvent(0);
+ return;
+ }
+
+ if (m_isOnDestructionBox) {
+ qreal diffY = me->scenePos().y() - m_oldPos.y();
+ moveDestructionBy(diffY);
+ }
+ else {
+ UMLWidget::mouseMoveEvent(me);
+ }
+}
+
+/**
+ * Moves the destruction Box to a new position using the difference between the
+ * current position and the new position.
+ * The destruction box is only moved along Y axis.
+ *
+ * @param diffY The difference between current Y position and new Y position
+ */
+void ObjectWidget::moveDestructionBy(qreal diffY)
+{
+ // endLine = length of the life line + diffY - 10 to center on the destruction box
+ qreal endLine = getEndLineY() + diffY - 10;
+ SeqLineWidget *pLine = sequentialLine();
+ pLine->setEndOfLine(endLine);
+ m_oldPos.setY(endLine);
+}
+
+/**
+ * Handles a color change signal.
+ */
+void ObjectWidget::slotFillColorChanged(Uml::ID::Type /*viewID*/)
+{
+ UMLWidget::setFillColor(m_scene->fillColor());
+ UMLWidget::setLineColor(m_scene->lineColor());
+
+ if(m_pLine)
+ m_pLine->setPen(QPen(UMLWidget::lineColor(), UMLWidget::lineWidth(), Qt::DashLine));
+}
+
+/**
+ * Used to cleanup any other widget it may need to delete.
+ */
+void ObjectWidget::cleanup()
+{
+ UMLWidget::cleanup();
+ if(m_pLine) {
+ m_pLine->cleanup();
+ delete m_pLine;
+ m_pLine = 0;
+ }
+}
+
+/**
+ * Show a properties dialog for an ObjectWidget.
+ */
+void ObjectWidget::showPropertiesDialog()
+{
+ UMLApp::app()->docWindow()->updateDocumentation(false);
+ QPointer<ClassPropertiesDialog> dlg = new ClassPropertiesDialog((QWidget*)UMLApp::app(), this);
+ if (dlg->exec()) {
+ UMLApp::app()->docWindow()->showDocumentation(this, true);
+ UMLApp::app()->document()->setModified(true);
+ }
+ dlg->close();
+ delete dlg;
+}
+
+/**
+ * Draw the object as an object (default).
+ */
+void ObjectWidget::paintObject(QPainter *painter)
+{
+ QFont oldFont = painter->font();
+ QFont font = UMLWidget::font();
+ font.setUnderline(true);
+ painter->setFont(font);
+
+ setPenFromSettings(painter);
+ if(UMLWidget::useFillColor())
+ painter->setBrush(UMLWidget::fillColor());
+ else
+ painter->setBrush(m_scene->backgroundColor());
+ const int w = width();
+ const int h = height();
+
+ const QString t = m_instanceName + QLatin1String(" : ") + name();
+ int multiInstOfst = 0;
+ if (m_multipleInstance) {
+ painter->drawRect(10, 10, w - 10, h - 10);
+ painter->drawRect(5, 5, w - 10, h - 10);
+ multiInstOfst = 10;
+ }
+ painter->drawRect(0, 0, w - multiInstOfst, h - multiInstOfst);
+ painter->setPen(textColor());
+ painter->drawText(O_MARGIN, O_MARGIN,
+ w - O_MARGIN * 2 - multiInstOfst, h - O_MARGIN * 2 - multiInstOfst,
+ Qt::AlignCenter, t);
+
+ painter->setFont(oldFont);
+}
+
+/**
+ * Draw the object as an actor.
+ */
+void ObjectWidget::paintActor(QPainter *painter)
+{
+ const QFontMetrics &fm = getFontMetrics(FT_UNDERLINE);
+
+ setPenFromSettings(painter);
+ if (UMLWidget::useFillColor())
+ painter->setBrush(UMLWidget::fillColor());
+ const int w = width();
+ const int textStartY = A_HEIGHT + A_MARGIN;
+ const int fontHeight = fm.lineSpacing();
+
+ const int middleX = w / 2;
+ const int thirdH = A_HEIGHT / 3;
+
+ //draw actor
+ painter->drawEllipse(middleX - A_WIDTH / 2, 0, A_WIDTH, thirdH);//head
+ painter->drawLine(middleX, thirdH, middleX, thirdH * 2);//body
+ painter->drawLine(middleX, 2 * thirdH,
+ middleX - A_WIDTH / 2, A_HEIGHT);//left leg
+ painter->drawLine(middleX, 2 * thirdH,
+ middleX + A_WIDTH / 2, A_HEIGHT);//right leg
+ painter->drawLine(middleX - A_WIDTH / 2, thirdH + thirdH / 2,
+ middleX + A_WIDTH / 2, thirdH + thirdH / 2);//arms
+ //draw text
+ painter->setPen(textColor());
+ QString t = m_instanceName + QLatin1String(" : ") + name();
+ painter->drawText(A_MARGIN, textStartY,
+ w - A_MARGIN * 2, fontHeight, Qt::AlignCenter, t);
+}
+
+/**
+ * Move the object up on a sequence diagram.
+ */
+void ObjectWidget::tabUp()
+{
+ int newY = y() - height();
+ if (newY < topMargin())
+ newY = topMargin();
+ setY(newY);
+ adjustAssocs(x(), newY);
+}
+
+/**
+ * Move the object down on a sequence diagram.
+ */
+void ObjectWidget::tabDown()
+{
+ int newY = y() + height();
+ setY(newY);
+ adjustAssocs(x(), newY);
+}
+
+/**
+ * Returns the top margin constant (Y axis value)
+ *
+ * @return Y coordinate of the space between the diagram top
+ * and the upper edge of the ObjectWidget.
+ */
+int ObjectWidget::topMargin()
+{
+ return 80 - height();
+}
+
+/**
+ * Returns whether or not the widget can be moved vertically up.
+ *
+ * @return True if widget can be moved upwards vertically.
+ */
+bool ObjectWidget::canTabUp()
+{
+ return (y() > topMargin());
+}
+
+/**
+ * Sets whether to show deconstruction on sequence line.
+ *
+ * @param bShow True if destruction on line shall be shown.
+ */
+void ObjectWidget::setShowDestruction(bool bShow)
+{
+ m_showDestruction = bShow;
+ if(m_pLine)
+ m_pLine->setupDestructionBox();
+}
+
+/**
+ * Returns whether to show deconstruction on sequence line.
+ *
+ * @return True if destruction on sequence line is shown.
+ */
+bool ObjectWidget::showDestruction() const
+{
+ return m_showDestruction;
+}
+
+/**
+ * Sets the y position of the bottom of the vertical line.
+ *
+ * @param yPosition The y coordinate for the bottom of the line.
+ */
+void ObjectWidget::setEndLine(int yPosition)
+{
+ if (m_pLine) {
+ m_pLine->setEndOfLine(yPosition);
+ }
+}
+
+/**
+ * Returns the end Y co-ord of the sequence line.
+ *
+ * @return Y coordinate of the endpoint of the sequence line.
+ */
+int ObjectWidget::getEndLineY()
+{
+ int y = this->y() + height();
+ if(m_pLine)
+ y += m_pLine->getLineLength();
+ if (m_showDestruction)
+ y += 10;
+ return y;
+}
+
+/**
+ * Add a message widget to the list.
+ *
+ * @param message Pointer to the MessageWidget to add.
+ */
+void ObjectWidget::messageAdded(MessageWidget* message)
+{
+ if (m_messages.count(message)) {
+ uError() << message->name() << ": duplicate entry !";
+ return ;
+ }
+ m_messages.append(message);
+}
+
+/**
+ * Remove a message widget from the list.
+ *
+ * @param message Pointer to the MessageWidget to remove.
+ */
+void ObjectWidget::messageRemoved(MessageWidget* message)
+{
+ if (m_messages.removeAll(message) == false) {
+ uError() << message->name() << ": missing entry !";
+ return ;
+ }
+}
+
+/**
+ * Called when a message widget with an end on this object has
+ * moved up or down.
+ * Sets the bottom of the line to a nice position.
+ */
+void ObjectWidget::slotMessageMoved()
+{
+ if (m_pLine) {
+ int lowestMessage = 0;
+ foreach (MessageWidget* message, m_messages) {
+ int messageHeight = message->y() + message->height();
+ if (lowestMessage < messageHeight) {
+ lowestMessage = messageHeight;
+ }
+ }
+ m_pLine->setEndOfLine(lowestMessage + sequenceLineMargin);
+ }
+}
+
+/**
+ * Returns whether a message is overlapping with another message.
+ * Used by MessageWidget::paint() methods.
+ *
+ * @param y top of your message
+ * @param messageWidget pointer to your message so it doesn't check against itself
+ */
+bool ObjectWidget::messageOverlap(qreal y, MessageWidget* messageWidget)
+{
+ foreach (MessageWidget* message, m_messages) {
+ if (message == messageWidget) {
+ continue;
+ }
+ const qreal msgY = message->y();
+ const qreal msgHeight = msgY + message->height();
+ if (y >= msgY && y <= msgHeight) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Return the SeqLineWidget.
+ * Returns a non NULL pointer if this ObjectWidget is part of a
+ * sequence diagram.
+ */
+SeqLineWidget *ObjectWidget::sequentialLine() const
+{
+ return m_pLine;
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Returns the cursor to be shown when resizing the widget.
+ * The cursor shown is KCursor::sizeHorCursor().
+ *
+ * @return The cursor to be shown when resizing the widget.
+ */
+QCursor ObjectWidget::resizeCursor() const
+{
+ return Qt::SizeHorCursor;
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Resizes the width of the object widget.
+ * Object widgets can only be resized horizontally, so height isn't modified.
+ *
+ * @param newW The new width for the widget.
+ * @param newH The new height for the widget (isn't used).
+ */
+void ObjectWidget::resizeWidget(qreal newW, qreal newH)
+{
+ Q_UNUSED(newH);
+ setSize(newW, height());
+}
+
+/**
+ * Saves to the "objectwidget" XMI element.
+ */
+void ObjectWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement objectElement = qDoc.createElement(QLatin1String("objectwidget"));
+ UMLWidget::saveToXMI(qDoc, objectElement);
+ objectElement.setAttribute(QLatin1String("drawasactor"), m_drawAsActor);
+ objectElement.setAttribute(QLatin1String("multipleinstance"), m_multipleInstance);
+ objectElement.setAttribute(QLatin1String("decon"), m_showDestruction);
+ qElement.appendChild(objectElement);
+}
+
+/**
+ * Loads from a "objectwidget" XMI element.
+ */
+bool ObjectWidget::loadFromXMI(QDomElement& qElement)
+{
+ if(!UMLWidget::loadFromXMI(qElement))
+ return false;
+ QString draw = qElement.attribute(QLatin1String("drawasactor"), QLatin1String("0"));
+ QString multi = qElement.attribute(QLatin1String("multipleinstance"), QLatin1String("0"));
+ QString decon = qElement.attribute(QLatin1String("decon"), QLatin1String("0"));
+
+ m_drawAsActor = (bool)draw.toInt();
+ m_multipleInstance = (bool)multi.toInt();
+ m_showDestruction = (bool)decon.toInt();
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/objectwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/objectwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/objectwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/objectwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef OBJECTWIDGET_H
+#define OBJECTWIDGET_H
+
+#include "messagewidgetlist.h"
+#include "umlwidget.h"
+
+class MessageWidget;
+class SeqLineWidget;
+class UMLScene;
+
+/**
+ * Displays an instance UMLObject of a concept.
+ *
+ * The local ID is needed as a it can represent a class
+ * that has many objects representing it.
+ *
+ * @short Displays an instance of a Concept.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class ObjectWidget : public UMLWidget
+{
+ Q_OBJECT
+public:
+ ObjectWidget(UMLScene *scene, UMLObject *o);
+ virtual ~ObjectWidget();
+
+ virtual void setX(qreal x);
+ virtual void setY(qreal y);
+
+ qreal centerX();
+
+ void setMultipleInstance(bool multiple);
+ bool multipleInstance() const;
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ bool activate(IDChangeLog* ChangeLog = 0);
+
+ void cleanup();
+
+ void showPropertiesDialog();
+
+ void setDrawAsActor(bool drawAsActor);
+ bool drawAsActor() const;
+
+ void setShowDestruction(bool bShow);
+ bool showDestruction() const;
+
+ int topMargin();
+
+ void setEndLine(int yPosition);
+ int getEndLineY();
+
+ void messageAdded(MessageWidget* message);
+ void messageRemoved(MessageWidget* message);
+
+ bool canTabUp();
+
+ bool messageOverlap(qreal y, MessageWidget* messageWidget);
+
+ SeqLineWidget *sequentialLine() const;
+
+ virtual void resizeWidget(qreal newW, qreal newH);
+
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+ virtual bool loadFromXMI(QDomElement& qElement);
+
+public slots:
+ void slotMenuSelection(QAction* action);
+ virtual void slotFillColorChanged(Uml::ID::Type viewID);
+ void slotMessageMoved();
+
+protected:
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *me);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *me);
+
+ QSizeF minimumSize() const;
+
+ virtual void moveEvent(QGraphicsSceneMouseEvent *event);
+ virtual void moveWidgetBy(qreal diffX, qreal diffY);
+ virtual void constrainMovementForAllWidgets(qreal &diffX, qreal &diffY);
+
+ virtual QCursor resizeCursor() const;
+
+ void paintActor(QPainter *p);
+ void paintObject(QPainter *p);
+
+private:
+ void tabUp();
+ void tabDown();
+
+ void moveDestructionBy(qreal diffY);
+
+ SeqLineWidget* m_pLine;
+ bool m_multipleInstance; ///< draw an object as a multiple object
+ bool m_drawAsActor; ///< object should be drawn as an Actor or an Object
+ bool m_showDestruction; ///< show object destruction on sequence diagram line
+ bool m_isOnDestructionBox; ///< true when a click occurred on the destruction box
+ MessageWidgetList m_messages; ///< message widgets with an end on this widget
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/packagewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/packagewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/packagewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/packagewidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,149 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "packagewidget.h"
+
+// app includes
+#include "debug_utils.h"
+#include "package.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlobject.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+// qt includes
+#include <QPainter>
+
+/**
+ * Constructs a PackageWidget.
+ *
+ * @param scene The parent of this PackageWidget.
+ * @param o The UMLObject this will be representing.
+ */
+PackageWidget::PackageWidget(UMLScene * scene, UMLPackage *o)
+ : UMLWidget(scene, WidgetBase::wt_Package, o),
+ m_pMenu(0)
+{
+ setSize(100, 30);
+ setZValue(1); // above box but below UMLWidget because may embed widgets
+ //set defaults from m_scene
+ if (m_scene) {
+ //check to see if correct
+ const Settings::OptionState& ops = m_scene->optionState();
+ m_showStereotype = ops.classState.showStereoType;
+ }
+}
+
+/**
+ * Destructor.
+ */
+PackageWidget::~PackageWidget()
+{
+}
+
+/**
+ * Overrides standard method.
+ */
+void PackageWidget::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());
+
+ 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 != NULL
+ && 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;
+ if (m_umlObject != NULL) {
+ QString stereotype = m_umlObject->stereotype();
+ if (!stereotype.isEmpty()) {
+ painter->drawText(0, fontHeight + PACKAGE_MARGIN,
+ w, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true));
+ lines = 2;
+ }
+ }
+
+ painter->drawText(0, (fontHeight*lines) + PACKAGE_MARGIN,
+ w, fontHeight, Qt::AlignCenter, name());
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overrides method from UMLWidget
+ */
+QSizeF PackageWidget::minimumSize() const
+{
+ if (!m_umlObject) {
+ return UMLWidget::minimumSize();
+ }
+
+ 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 += PACKAGE_MARGIN * 2;
+ if (width < 70)
+ width = 70; // minumin width of 70
+
+ int height = (lines*fontHeight) + fontHeight + (PACKAGE_MARGIN * 2);
+
+ return QSizeF(width, height);
+}
+
+/**
+ * Saves to the "packagewidget" XMI element.
+ */
+void PackageWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement conceptElement = qDoc.createElement(QLatin1String("packagewidget"));
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/packagewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/packagewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/packagewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/packagewidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * 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) 2003-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef PACKAGEWIDGET_H
+#define PACKAGEWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLPackage;
+class ListPopupMenu;
+
+#define PACKAGE_MARGIN 5
+
+/**
+ * Defines a graphical version of the Package. Most of the
+ * functionality will come from the @ref UMLPackage class.
+ *
+ * @short A graphical version of a Package.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class PackageWidget : public UMLWidget
+{
+public:
+ explicit PackageWidget(UMLScene * scene, UMLPackage * o);
+ virtual ~PackageWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ QSizeF minimumSize() const;
+
+private:
+ ListPopupMenu* m_pMenu; ///< the right mouse button menu
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/pinportbase.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/pinportbase.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/pinportbase.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/pinportbase.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,378 @@
+/***************************************************************************
+ * 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) 2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "pinportbase.h"
+
+// app includes
+#include "port.h"
+#include "package.h"
+#include "debug_utils.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+#include "floatingtextwidget.h"
+
+// qt includes
+#include <QPainter>
+#include <QToolTip>
+
+// sys includes
+#include <cmath>
+
+PinPortBase::PinPortBase(UMLScene *scene, WidgetType type, UMLObject *o)
+ : UMLWidget(scene, type, o)
+{
+ init();
+}
+
+PinPortBase::PinPortBase(UMLScene *scene, WidgetType type, UMLWidget *a, Uml::ID::Type id)
+ : UMLWidget(scene, type, id)
+{
+ init(a);
+}
+
+/**
+ * Standard destructor.
+ */
+PinPortBase::~PinPortBase()
+{
+}
+
+/**
+ * Performs initializations which are common to PinWidget and PortWidget.
+ */
+void PinPortBase::init(UMLWidget *owner)
+{
+ m_ignoreSnapToGrid = true;
+ m_ignoreSnapComponentSizeToGrid = true;
+ m_resizable = false;
+ m_pOw = owner;
+ m_pName = NULL;
+ m_motionConnected = false;
+ const int edgeLength = 15; // old: (m_baseType == wt_Pin ? 10 : 15);
+ const QSizeF FixedSize(edgeLength, edgeLength);
+ setMinimumSize(FixedSize);
+ setMaximumSize(FixedSize);
+ setSize(FixedSize);
+}
+
+UMLWidget* PinPortBase::ownerWidget()
+{
+ return m_pOw;
+}
+
+/**
+ * Overrides method from UMLWidget in order to set a tooltip.
+ * The tooltip is set to the name().
+ * The reason for using a tooltip for the name is that the size of this
+ * widget is not large enough to accommodate the average name.
+ */
+void PinPortBase::updateWidget()
+{
+ QString strName = name();
+ uDebug() << " port name is " << strName;
+ if (m_pName) {
+ m_pName->setText(strName);
+ } else {
+ setToolTip(strName);
+ }
+}
+
+/**
+ * Overrides method from UMLWidget to set the name.
+ */
+void PinPortBase::setName(const QString &strName)
+{
+ UMLWidget::setName(strName);
+ updateGeometry();
+ if (m_pName) {
+ m_pName->setText(strName);
+ }
+}
+
+/**
+ * Overridden from UMLWidget.
+ * Moves the widget to a new position using the difference between the
+ * current position and the new position.
+ * Movement is constrained such that the port is always attached to its
+ * owner widget.
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+void PinPortBase::moveWidgetBy(qreal diffX, qreal diffY)
+{
+ UMLWidget* owner = ownerWidget();
+ qreal newX = x() + diffX;
+ qreal newY = y() + diffY;
+ uDebug() << "PinPortBase::moveWidgetBy " << diffX << "," << diffY;
+ if (owner == NULL) {
+ uError() << "PinPortBase::moveWidgetBy: ownerWidget() returns NULL";
+ setX(newX);
+ setY(newY);
+ return;
+ }
+ const qreal deltaTop = fabs(y() + height() - owner->y());
+ const qreal deltaBottom = fabs(owner->y() + owner->height() - y());
+ const qreal deltaLeft = fabs(x() + width() - owner->x());
+ const qreal deltaRight = fabs(owner->x() + owner->width() - x());
+ bool didAnyMovement = false;
+ if (deltaTop < 1.0 || deltaBottom < 1.0) {
+ if (newX < owner->x() - width())
+ newX = owner->x() - width();
+ else if (newX > owner->x() + owner->width())
+ newX = owner->x() + owner->width();
+ setX(newX);
+ didAnyMovement = true;
+ }
+ if (deltaLeft < 1.0 || deltaRight < 1.0) {
+ if (newY < owner->y() - height())
+ newY = owner->y() - height();
+ else if (newY > owner->y() + owner->height())
+ newY = owner->y() + owner->height();
+ setY(newY);
+ didAnyMovement = true;
+ }
+ if (!didAnyMovement) {
+ uDebug() << "constraint failed for (" << diffX << ", " << diffY << ")";
+ setX(newX);
+ setY(newY);
+ }
+}
+
+/**
+ * Align this widget's position such that it is attached at one of the
+ * sides of its owner's widget.
+ */
+void PinPortBase::attachToOwner() {
+ UMLWidget *owner = ownerWidget();
+ const QPointF scenePos = m_scene->pos();
+ if (owner == NULL) {
+ uError() << "PinPortBase::attachToOwner: ownerWidget() returns NULL";
+ setX(scenePos.x());
+ setY(scenePos.y());
+ return;
+ }
+ bool xIsWithinOwner = false;
+ if (scenePos.x() < owner->x() - width()) {
+ setX(owner->x() - width());
+ } else if (scenePos.x() <= owner->x() + owner->width()) {
+ setX(scenePos.x());
+ xIsWithinOwner = true;
+ } else {
+ setX(owner->x() + owner->width());
+ }
+ if (scenePos.y() < owner->y() - height()) {
+ setY(owner->y() - height());
+ } else if (scenePos.y() <= owner->y() + owner->height()) {
+ if (xIsWithinOwner) {
+ if (scenePos.y() <= owner->y() + owner->height() / 2.0)
+ setY(owner->y() - height());
+ else
+ setY(owner->y() + owner->height());
+ } else {
+ setY(scenePos.y());
+ }
+ } else {
+ setY(owner->y() + owner->height());
+ }
+
+ if (m_motionConnected) {
+ uDebug() << "connectOwnerMotion was already done";
+ } else {
+ connectOwnerMotion();
+ m_motionConnected = true;
+ }
+}
+
+/**
+ * Overrides standard method.
+ */
+void PinPortBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ setPenFromSettings(painter);
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ } else {
+ painter->setBrush(m_scene->backgroundColor());
+ }
+
+ int w = width();
+ int h = height();
+
+ painter->drawRect(0, 0, w, h);
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+void PinPortBase::slotOwnerMoved(qreal diffX, qreal diffY)
+{
+ setX(x() + diffX);
+ setY(y() + diffY);
+}
+
+/**
+ * Captures any popup menu signals for menus it created.
+ */
+void PinPortBase::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_NameAsTooltip:
+ if (m_pName) {
+ action->setChecked(true);
+ delete m_pName;
+ m_pName = NULL;
+ setToolTip(name());
+ } else {
+ action->setChecked(false);
+ m_pName = new FloatingTextWidget(m_scene, Uml::TextRole::Floating, name());
+ m_pName->setParentItem(this);
+ m_pName->setText(name()); // to get geometry update
+ m_pName->activate();
+ UMLWidget* owner = ownerWidget();
+ if (owner == NULL) {
+ uError() << "PinPortBase::slotMenuSelection: ownerWidget() returns NULL";
+ setX(x());
+ setY(y());
+ } else {
+ const qreal w = width();
+ const qreal h = height();
+ if (x() < owner->x())
+ m_pName->setX(-m_pName->width());
+ else if (x() >= owner->x() + owner->width())
+ m_pName->setX(w);
+ else
+ m_pName->setX(-m_pName->width() / 2.0 + w / 2.0);
+ if (y() < owner->y())
+ m_pName->setY(-m_pName->height() - 2);
+ else if (y() >= owner->y() + owner->height())
+ m_pName->setY(h);
+ else
+ m_pName->setY(-m_pName->height() / 2.0 + h / 2.0);
+ }
+ m_pName->update();
+ setToolTip(QString());
+ QToolTip::hideText();
+ }
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ }
+}
+
+FloatingTextWidget *PinPortBase::floatingTextWidget() {
+ return m_pName;
+}
+
+void PinPortBase::setFloatingTextWidget(FloatingTextWidget *ft) {
+ m_pName = ft;
+ if (m_pName)
+ m_pName->setParentItem(this);
+}
+
+/**
+ * Override method from UMLWidget in order to additionally check m_pName.
+ *
+ * @param p Point to be checked.
+ *
+ * @return 'this' if UMLWidget::onWidget(p) returns non NULL;
+ * m_pName if m_pName is non NULL and m_pName->onWidget(p) returns non NULL;
+ * else NULL.
+ */
+UMLWidget* PinPortBase::onWidget(const QPointF &p)
+{
+ if (UMLWidget::onWidget(p) != NULL)
+ return this;
+ if (m_pName) {
+ uDebug() << "floatingtext: " << m_pName->text();
+ return m_pName->onWidget(p);
+ }
+ return NULL;
+}
+
+/**
+ * Reimplement function from UMLWidget
+ */
+UMLWidget* PinPortBase::widgetWithID(Uml::ID::Type id)
+{
+ if (UMLWidget::widgetWithID(id))
+ return this;
+ if (m_pName && m_pName->widgetWithID(id))
+ return m_pName;
+ return NULL;
+}
+
+
+/**
+ * Saves the widget to the "pinwidget" or "portwidget" XMI element.
+ */
+void PinPortBase::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement element = qDoc.createElement(m_baseType == wt_Pin ? QLatin1String("pinwidget")
+ : QLatin1String("portwidget"));
+ element.setAttribute(QLatin1String("widgetaid"), Uml::ID::toString(ownerWidget()->id()));
+ UMLWidget::saveToXMI(qDoc, element);
+ if (m_pName && !m_pName->text().isEmpty()) {
+ m_pName->saveToXMI(qDoc, element);
+ }
+ qElement.appendChild(element);
+}
+
+/**
+ * Loads from a "pinwidget" or from a "portwidget" XMI element.
+ */
+bool PinPortBase::loadFromXMI(QDomElement & qElement)
+{
+ if (!UMLWidget::loadFromXMI(qElement))
+ return false;
+
+ QString widgetaid = qElement.attribute(QLatin1String("widgetaid"), QLatin1String("-1"));
+ Uml::ID::Type aId = Uml::ID::fromString(widgetaid);
+ UMLWidget *owner = m_scene->findWidget(aId);
+ if (owner == NULL) {
+ DEBUG(DBG_SRC) << "owner object " << Uml::ID::toString(aId) << " not found";
+ return false;
+ }
+ m_pOw = owner;
+
+ // Optional child element: floatingtext
+ QDomNode node = qElement.firstChild();
+ QDomElement element = node.toElement();
+ if (!element.isNull()) {
+ QString tag = element.tagName();
+ if (tag == QLatin1String("floatingtext")) {
+ m_pName = new FloatingTextWidget(m_scene, Uml::TextRole::Floating,
+ name(), Uml::ID::Reserved);
+ if (!m_pName->loadFromXMI(element)) {
+ // Most likely cause: The FloatingTextWidget is empty.
+ delete m_pName;
+ m_pName = NULL;
+ } else {
+ m_pName->setParentItem(this);
+ m_pName->activate();
+ m_pName->update();
+ }
+ } else {
+ uError() << "unknown tag " << tag;
+ }
+ }
+
+ if (m_motionConnected) {
+ uDebug() << "connectOwnerMotion was already done";
+ } else {
+ connectOwnerMotion();
+ m_motionConnected = true;
+ }
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/pinportbase.h umbrello-kf6-15.08.1/umbrello/umlwidgets/pinportbase.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/pinportbase.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/pinportbase.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * 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) 2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef PINPORTBASE_H
+#define PINPORTBASE_H
+
+#include "umlwidget.h"
+
+class FloatingTextWidget;
+
+/**
+ * @short Abstract base class for PinWidget and PortWidget
+ * @author Oliver Kellogg
+ * @see UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class PinPortBase : public UMLWidget
+{
+ Q_OBJECT
+public:
+ PinPortBase(UMLScene *scene, WidgetType type, UMLObject *o);
+ PinPortBase(UMLScene *scene, WidgetType type, UMLWidget *a, Uml::ID::Type id = Uml::ID::None);
+ virtual ~PinPortBase();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ virtual UMLWidget* ownerWidget();
+ virtual void connectOwnerMotion() = 0;
+
+ void setName(const QString &strName);
+ void updateWidget();
+ void moveWidgetBy(qreal diffX, qreal diffY);
+ void attachToOwner();
+
+ UMLWidget* onWidget(const QPointF& p);
+ UMLWidget* widgetWithID(Uml::ID::Type id);
+
+ FloatingTextWidget *floatingTextWidget();
+ void setFloatingTextWidget(FloatingTextWidget *ft);
+
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+ bool loadFromXMI(QDomElement& qElement);
+
+public slots:
+ void slotOwnerMoved(qreal diffX, qreal diffY);
+ virtual void slotMenuSelection(QAction* action);
+
+protected:
+ void init(UMLWidget *owner = 0);
+
+ UMLWidget* m_pOw;
+ FloatingTextWidget *m_pName;
+ bool m_motionConnected;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/pinwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/pinwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/pinwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/pinwidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,103 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "pinwidget.h"
+
+// app includes
+#include "debug_utils.h"
+#include "floatingtextwidget.h"
+#include "listpopupmenu.h"
+#include "umlscene.h"
+#include "activitywidget.h"
+
+// kde includes
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+#include <KLocalizedString>
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+#include <QPainter>
+
+DEBUG_REGISTER_DISABLED(PinWidget)
+
+/**
+ * Creates a Pin widget.
+ *
+ * @param scene The parent of the widget.
+ * @param a The widget to which this pin is attached.
+ * @param id The ID to assign (-1 will prompt a new ID).
+ */
+PinWidget::PinWidget(UMLScene* scene, UMLWidget* a, Uml::ID::Type id)
+ : PinPortBase(scene, WidgetBase::wt_Pin, a, id)
+{
+ // setParent(a);
+ // m_nY = y() < getMinY() ? getMinY() : y();
+
+ m_pName = new FloatingTextWidget(m_scene, Uml::TextRole::Floating, name());
+ m_pName->setParentItem(this);
+ m_pName->setText(name()); // to get geometry update
+ m_pName->activate();
+ setVisible(true);
+}
+
+/**
+ * Destructor.
+ */
+PinWidget::~PinWidget()
+{
+}
+
+/**
+ * Implement abstract function from PinPortWidget.
+ */
+void PinWidget::connectOwnerMotion()
+{
+ ActivityWidget *owner = static_cast<ActivityWidget*>(ownerWidget());
+ connect(owner, SIGNAL(sigActMoved(qreal,qreal)), this, SLOT(slotOwnerMoved(qreal,qreal)));
+}
+
+/**
+ * Captures any popup menu signals for menus it created.
+ */
+void PinWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_Rename:
+ {
+ bool ok = false;
+ QString name = m_Text;
+#if QT_VERSION >= 0x050000
+ name = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter Pin Name"),
+ i18n("Enter the pin name :"),
+ QLineEdit::Normal,
+ m_Text, &ok);
+#else
+ name = KInputDialog::getText(i18n("Enter Pin Name"),
+ i18n("Enter the pin name :"),
+ m_Text, &ok);
+#endif
+ if (ok) {
+ setName(name);
+ }
+ }
+ break;
+
+ default:
+ PinPortBase::slotMenuSelection(action);
+ }
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/pinwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/pinwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/pinwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/pinwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef PINWIDGET_H
+#define PINWIDGET_H
+
+#include "pinportbase.h"
+
+/**
+ * This class is the graphical version of a UML Pin. A pinWidget is created
+ * by a @ref UMLView. An pinWidget belongs to only one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
+ *
+ * The pinWidget class inherits from the @ref UMLWidget class which adds most of the functionality
+ * to this class.
+ *
+ * @short A graphical version of a UML pin.
+ * @author Hassan KOUCH <hkouch@hotmail.com>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class PinWidget : public PinPortBase
+{
+ Q_OBJECT
+public:
+
+ PinWidget(UMLScene* scene, UMLWidget* a, Uml::ID::Type id = Uml::ID::None);
+ virtual ~PinWidget();
+
+ void connectOwnerMotion();
+ // int getMinY();
+
+public slots:
+ void slotMenuSelection(QAction* action);
+
+// private:
+ // int m_nY;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/portwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/portwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/portwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/portwidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * 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) 2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "portwidget.h"
+
+// app includes
+#include "port.h"
+#include "package.h"
+#include "debug_utils.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "componentwidget.h"
+#include "floatingtextwidget.h"
+
+// kde includes
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+#include <KLocalizedString>
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+#include <QPainter>
+#include <QToolTip>
+
+/**
+ * Constructs a PortWidget.
+ *
+ * @param scene The parent of this PortWidget.
+ * @param d The UMLPort this will be representing.
+ */
+PortWidget::PortWidget(UMLScene *scene, UMLPort *d)
+ : PinPortBase(scene, WidgetBase::wt_Port, d)
+{
+ setToolTip(d->name());
+}
+
+/**
+ * Standard deconstructor.
+ */
+PortWidget::~PortWidget()
+{
+}
+
+/**
+ * Override function from PinPortWidget.
+ */
+UMLWidget* PortWidget::ownerWidget()
+{
+ if (m_pOw == NULL) {
+ const Uml::ID::Type compWidgetId = m_umlObject->umlPackage()->id();
+ m_pOw = m_scene->widgetOnDiagram(compWidgetId);
+ }
+ return m_pOw;
+}
+
+/**
+ * Implement abstract function from PinPortWidget.
+ */
+void PortWidget::connectOwnerMotion()
+{
+ ComponentWidget *owner = static_cast<ComponentWidget*>(ownerWidget());
+ connect(owner, SIGNAL(sigCompMoved(qreal,qreal)), this, SLOT(slotOwnerMoved(qreal,qreal)));
+}
+
+/**
+ * Captures any popup menu signals for menus it created.
+ */
+void PortWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_Rename:
+ {
+ bool ok = false;
+ QString newName;
+#if QT_VERSION >= 0x050000
+ newName = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter Port Name"), i18n("Enter the port name :"),
+ QLineEdit::Normal,
+ name(), &ok);
+#else
+ newName = KInputDialog::getText(i18n("Enter Port Name"), i18n("Enter the port name :"),
+ name(), &ok);
+#endif
+ if (ok) {
+ setName(newName);
+ }
+ }
+ break;
+
+ default:
+ PinPortBase::slotMenuSelection(action);
+ }
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/portwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/portwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/portwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/portwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * 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) 2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef PORTWIDGET_H
+#define PORTWIDGET_H
+
+#include "pinportbase.h"
+
+class UMLPort;
+
+/**
+ * Defines a graphical version of the UML2 port. Most of the functionality
+ * comes from the @ref PinPortBase class from which this class inherits.
+ *
+ * @short A graphical version of a port on a component.
+ * @author Oliver Kellogg
+ * @see PinPortBase, UMLWidget
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class PortWidget : public PinPortBase
+{
+ Q_OBJECT
+public:
+ PortWidget(UMLScene *scene, UMLPort *d);
+ virtual ~PortWidget();
+
+ UMLWidget* ownerWidget();
+ void connectOwnerMotion();
+
+public slots:
+ void slotMenuSelection(QAction* action);
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/preconditionwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/preconditionwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/preconditionwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/preconditionwidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,335 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "preconditionwidget.h"
+
+// app includes
+#include "debug_utils.h"
+#include "listpopupmenu.h"
+#include "objectwidget.h"
+#include "uml.h"
+#include "umlscene.h"
+#include "uniqueid.h"
+#include "idchangelog.h"
+
+// kde includes
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+#include <KLocalizedString>
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+#include <QPainter>
+
+DEBUG_REGISTER_DISABLED(PreconditionWidget)
+
+#define PRECONDITION_MARGIN 5
+#define PRECONDITION_WIDTH 30
+#define PRECONDITION_HEIGHT 10
+
+/**
+ * Creates a Precondition widget.
+ *
+ * @param scene The parent of the widget.
+ * @param a The role A widget for this precondition.
+ * @param id The ID to assign (-1 will prompt a new ID).
+ */
+PreconditionWidget::PreconditionWidget(UMLScene* scene, ObjectWidget* a, Uml::ID::Type id)
+ : UMLWidget(scene, WidgetBase::wt_Precondition, id),
+ m_objectWidget(a)
+{
+ m_ignoreSnapToGrid = true;
+ m_ignoreSnapComponentSizeToGrid = true;
+ m_resizable = true ;
+ setVisible(true);
+ //updateResizability();
+ // calculateWidget();
+ if (y() < minY())
+ m_nY = minY();
+ else if (y() > maxY())
+ m_nY = maxY();
+ else
+ m_nY = y();
+
+ activate();
+}
+
+/**
+ * Destructor.
+ */
+PreconditionWidget::~PreconditionWidget()
+{
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void PreconditionWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ int w = width();
+ int h = height();
+
+ int x = m_objectWidget->x() + m_objectWidget->width() / 2;
+ x -= w/2;
+ setX(x);
+ int y = this->y();
+
+ //test if y isn't above the object
+ if (y <= m_objectWidget->y() + m_objectWidget->height()) {
+ y = m_objectWidget->y() + m_objectWidget->height() + 15;
+ }
+ if (y + h >= m_objectWidget->getEndLineY()) {
+ y = m_objectWidget->getEndLineY() - h;
+ }
+ setY(y);
+ setPenFromSettings(painter);
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ }
+ {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const QString precondition_value = QLatin1String("{ ") + name() + QLatin1String(" }");
+ //int middleX = w / 2;
+ int textStartY = (h / 2) - (fontHeight / 2);
+ painter->drawRoundRect(0, 0, w, h, (h * 60) / w, 60);
+ painter->setPen(textColor());
+ painter->setFont(UMLWidget::font());
+ painter->drawText(PRECONDITION_MARGIN, textStartY,
+ w - PRECONDITION_MARGIN * 2, fontHeight, Qt::AlignCenter, precondition_value);
+ }
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overrides method from UMLWidget.
+ */
+QSizeF PreconditionWidget::minimumSize() const
+{
+ int width = 10, height = 10;
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int textWidth = fm.width(name()) + 25;
+ height = fontHeight;
+ width = textWidth > PRECONDITION_WIDTH ? textWidth : PRECONDITION_WIDTH;
+ height = height > PRECONDITION_HEIGHT ? height : PRECONDITION_HEIGHT;
+ width += PRECONDITION_MARGIN * 2;
+ height += PRECONDITION_MARGIN * 2;
+
+ return QSizeF(width, height);
+}
+
+/**
+ * Calculate the geometry of the widget.
+ */
+void PreconditionWidget::calculateWidget()
+{
+ calculateDimensions();
+
+ setVisible(true);
+
+ setX(m_nPosX);
+ setY(m_nY);
+}
+
+/**
+ * Activates a PreconditionWidget. Connects the WidgetMoved signal from
+ * its m_objectWidget pointer so that PreconditionWidget can adjust to the move of
+ * the object widget.
+ */
+bool PreconditionWidget::activate(IDChangeLog * Log /*= 0*/)
+{
+ m_scene->resetPastep-kf6oint();
+ UMLWidget::activate(Log);
+
+ loadObjectWidget();
+
+ if (!m_objectWidget) {
+ DEBUG(DBG_SRC) << "role A widget " << Uml::ID::toString(m_widgetAId)
+ << " could not be found";
+ return false;
+ }
+
+ connect(m_objectWidget, SIGNAL(sigWidgetMoved(Uml::ID::Type)), this, SLOT(slotWidgetMoved(Uml::ID::Type)));
+
+ calculateDimensions();
+ return true;
+}
+
+/**
+ * Resolve references of this precondition so it references the correct
+ * new object widget after paste.
+ */
+void PreconditionWidget::resolveObjectWidget(IDChangeLog* log) {
+ m_widgetAId = log->findNewID(m_widgetAId);
+}
+
+/**
+ * Calculates the size of the widget.
+ */
+void PreconditionWidget::calculateDimensions()
+{
+ int x = 0;
+ int w = 0;
+ int h = 0;
+ int x1 = m_objectWidget->x();
+ int w1 = m_objectWidget->width() / 2;
+
+ x1 += w1;
+
+ QSizeF q = minimumSize();
+ w = q.width() > width() ? q.width() : width();
+ h = q.height() > height() ? q.height() : height();
+
+ x = x1 - w/2;
+
+ m_nPosX = x;
+
+ setSize(w, h);
+}
+
+/**
+ * Slot when widget is moved.
+ */
+void PreconditionWidget::slotWidgetMoved(Uml::ID::Type id)
+{
+ const Uml::ID::Type idA = m_objectWidget->localID();
+ if (idA != id) {
+ DEBUG(DBG_SRC) << "id=" << Uml::ID::toString(id) << ": ignoring for idA=" << Uml::ID::toString(idA);
+ return;
+ }
+ m_nY = y();
+ if (m_nY < minY())
+ m_nY = minY();
+ if (m_nY > maxY())
+ m_nY = maxY();
+
+ calculateDimensions();
+ if (m_scene->selectedCount(true) > 1)
+ return;
+}
+
+/**
+ * Returns the minimum height this widget should be set at on
+ * a sequence diagrams. Takes into account the widget positions
+ * it is related to.
+ */
+int PreconditionWidget::minY() const
+{
+ if (m_objectWidget) {
+ return m_objectWidget->y() + m_objectWidget->height();
+ }
+ return 0;
+}
+
+/**
+ * Returns the maximum height this widget should be set at on
+ * a sequence diagrams. Takes into account the widget positions
+ * it is related to.
+ */
+int PreconditionWidget::maxY() const
+{
+ if (m_objectWidget) {
+ return ((int)m_objectWidget->getEndLineY() - height());
+ }
+ return 0;
+}
+
+/**
+ * Captures any popup menu signals for menus it created.
+ */
+void PreconditionWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_Rename:
+ {
+ bool ok = false;
+ QString text = name();
+#if QT_VERSION >= 0x050000
+ text = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter Precondition Name"),
+ i18n("Enter the precondition :"),
+ QLineEdit::Normal,
+ text, &ok);
+#else
+ text = KInputDialog::getText(i18n("Enter Precondition Name"),
+ i18n("Enter the precondition :"),
+ text, &ok);
+#endif
+ if (ok && !text.isEmpty()) {
+ setName(text);
+ }
+ calculateWidget();
+ }
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ }
+}
+
+/**
+ * Saves the widget to the "preconditionwidget" XMI element.
+ */
+void PreconditionWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement preconditionElement = qDoc.createElement(QLatin1String("preconditionwidget"));
+ UMLWidget::saveToXMI(qDoc, preconditionElement);
+
+ preconditionElement.setAttribute(QLatin1String("widgetaid"), Uml::ID::toString(m_objectWidget->localID()));
+ preconditionElement.setAttribute(QLatin1String("preconditionname"), name());
+ preconditionElement.setAttribute(QLatin1String("documentation"), documentation());
+ qElement.appendChild(preconditionElement);
+}
+
+/**
+ * Loads the widget from the "preconditionwidget" XMI element.
+ */
+bool PreconditionWidget::loadFromXMI(QDomElement& qElement)
+{
+ if(!UMLWidget::loadFromXMI(qElement))
+ return false;
+ QString widgetaid = qElement.attribute(QLatin1String("widgetaid"), QLatin1String("-1"));
+ setName(qElement.attribute(QLatin1String("preconditionname")));
+ setDocumentation(qElement.attribute(QLatin1String("documentation")));
+
+ m_widgetAId = Uml::ID::fromString(widgetaid);
+
+ // Lookup the ObjectWidget, if it can't be found, assume it will be
+ // resolved later
+ loadObjectWidget();
+
+ return true;
+}
+
+/**
+ * Load the object widget from m_widgetAId
+ *
+ * This method is called in loadFromXMI() when loading an XMI file, and called
+ * from activate() when activating a widget after pasting.
+ */
+void PreconditionWidget::loadObjectWidget()
+{
+ if (m_objectWidget == 0) {
+ m_objectWidget = dynamic_cast<ObjectWidget*>(
+ umlScene()->findWidget(m_widgetAId)
+ );
+ }
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/preconditionwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/preconditionwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/preconditionwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/preconditionwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,70 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef PRECONDITIONWIDGET_H
+#define PRECONDITIONWIDGET_H
+
+#include "umlwidget.h"
+
+class ObjectWidget;
+
+/**
+ * @short A graphical version of a UML Precondition (new in UML 2.0).
+ *
+ * This class is the graphical version of a UML Precondition. A PreconditionWidget is created
+ * by a @ref UMLView. An PreconditionWidget belongs to only one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
+ *
+ * The PreconditionWidget class inherits from the @ref UMLWidget class which adds most of the functionality
+ * to this class.
+ *
+ * @author Florence Mattler <florence.mattler@libertysurf.fr>
+ *
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class PreconditionWidget : public UMLWidget
+{
+ Q_OBJECT
+public:
+ PreconditionWidget(UMLScene* scene, ObjectWidget* a, Uml::ID::Type id = Uml::ID::None);
+ virtual ~PreconditionWidget();
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ int minY() const;
+ int maxY() const;
+
+ bool activate(IDChangeLog* Log = 0);
+ void resolveObjectWidget(IDChangeLog* log);
+
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+ virtual bool loadFromXMI(QDomElement& qElement);
+
+ void setObjectWidget(ObjectWidget* widget);
+
+public slots:
+ void slotMenuSelection(QAction* action);
+ void slotWidgetMoved(Uml::ID::Type id);
+
+protected:
+ QSizeF minimumSize() const;
+
+private:
+ void calculateWidget();
+ void calculateDimensions();
+
+ ObjectWidget* m_objectWidget;
+ int m_nY;
+
+ Uml::ID::Type m_widgetAId;
+ void loadObjectWidget();
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/regionwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/regionwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/regionwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/regionwidget.cpp 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,108 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "regionwidget.h"
+
+// app includes
+#include "basictypes.h"
+#include "debug_utils.h"
+
+// kde includes
+#include <KLocalizedString>
+
+#define REGION_MARGIN 5
+#define REGION_WIDTH 90
+#define REGION_HEIGHT 45
+
+/**
+ * Creates a Region widget.
+ *
+ * @param scene The parent of the widget.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+RegionWidget::RegionWidget(UMLScene* scene, Uml::ID::Type id)
+ : UMLWidget(scene, WidgetBase::wt_Region, id)
+{
+}
+
+/**
+ * Destructor.
+ */
+RegionWidget::~RegionWidget()
+{
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void RegionWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ const int w = width();
+ const int h = height();
+
+ setPenFromSettings(painter);
+ QPen pen = painter->pen();
+ pen.setColor(Qt::red);
+ pen.setStyle(Qt::DashLine);
+ painter->setPen(pen);
+ painter->drawRoundRect(0, 0, w, h, (h * 60) / w, 60);
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overrides method from UMLWidget
+ */
+QSizeF RegionWidget::minimumSize() const
+{
+ int width = 10, height = 10;
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ int textWidth = fm.width(name());
+
+ height = fontHeight;
+ width = textWidth > REGION_WIDTH?textWidth:REGION_WIDTH;
+ height = height > REGION_HEIGHT ? height : REGION_HEIGHT;
+ width += REGION_MARGIN * 2;
+ height += REGION_MARGIN * 2;
+
+ return QSizeF(width, height);
+}
+
+/**
+ * Saves region widget to XMI element.
+ */
+void RegionWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+{
+ QDomElement regionElement = qDoc.createElement(QLatin1String("regionwidget"));
+ UMLWidget::saveToXMI(qDoc, regionElement);
+ regionElement.setAttribute(QLatin1String("regionname"), name());
+ regionElement.setAttribute(QLatin1String("documentation"), documentation());
+
+ qElement.appendChild(regionElement);
+}
+
+/**
+ * Loads region widget from XMI element.
+ */
+bool RegionWidget::loadFromXMI(QDomElement& qElement)
+{
+ if (!UMLWidget::loadFromXMI(qElement)) {
+ return false;
+ }
+ setName(qElement.attribute(QLatin1String("regionname")));
+ setDocumentation(qElement.attribute(QLatin1String("documentation")));
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/regionwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/regionwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/regionwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/regionwidget.h 2015-10-08 11:48:59.509089026 +0300
@@ -0,0 +1,36 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+***************************************************************************/
+
+#ifndef REGIONWIDGET_H
+#define REGIONWIDGET_H
+
+#include "umlwidget.h"
+
+/**
+ * Represents a rectangular region on Activity diagram.
+ */
+class RegionWidget: public UMLWidget
+{
+ Q_OBJECT
+public:
+ explicit RegionWidget(UMLScene* scene, Uml::ID::Type id = Uml::ID::None);
+ virtual ~RegionWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+ bool loadFromXMI(QDomElement& qElement);
+
+protected:
+ QSizeF minimumSize() const;
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/seqlinewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/seqlinewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/seqlinewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/seqlinewidget.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,197 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "seqlinewidget.h"
+
+//app includes
+#include "messagewidget.h"
+#include "objectwidget.h"
+#include "umlscene.h"
+#include "umlview.h"
+
+//qt includes
+#include <QPainter>
+
+// class members
+int const SeqLineWidget::m_nMouseDownEpsilonX = 20;
+
+/**
+ * Constructor.
+ */
+SeqLineWidget::SeqLineWidget(UMLScene *scene, ObjectWidget * pObject)
+ : QGraphicsLineItem(),
+ m_scene(scene)
+{
+ scene->addItem(this);
+ m_pObject = pObject;
+ setPen(QPen(m_pObject->lineColor(), 0, Qt::DashLine));
+ setZValue(0);
+ setVisible(true);
+ m_DestructionBox.line1 = 0;
+ m_nLengthY = 250;
+ setupDestructionBox();
+}
+
+/**
+ * Destructor.
+ */
+SeqLineWidget::~SeqLineWidget()
+{
+}
+
+/**
+ * Return whether point is on sequence line.
+ * Takes into account destruction box if shown.
+ *
+ * @param p The point to investigate.
+ * @return True if point is on this sequence line.
+ */
+bool SeqLineWidget::onWidget(const QPointF & p)
+{
+ bool isOnWidget = false;
+ QPointF sp = line().p1();
+ QPointF ep = line().p2();
+ //see if on widget (for message creation)
+ if (sp.x() - m_nMouseDownEpsilonX < p.x()
+ && ep.x() + m_nMouseDownEpsilonX > p.x()
+ && sp.y() < p.y() && ep.y() + 3 > p.y())
+ {
+ isOnWidget = true;
+ }
+ return isOnWidget;
+}
+
+/**
+ * Return whether point is on the destruction box.
+ *
+ * @param p The point to investigate.
+ * @return True if point is on the destruction box of this sequence line.
+ */
+bool SeqLineWidget::onDestructionBox(const QPointF & p)
+{
+ bool isOnDestructionBox = false;
+ int x = m_pObject->x() + m_pObject->width() / 2;
+ int y = m_pObject->y() + m_pObject->height() + m_nLengthY;
+
+ //see if on destruction box
+ if (!m_pObject->showDestruction()) {
+ return false;
+ }
+ if (x - 10 < p.x() && x + 10 > p.x()
+ && y - 10 < p.y() && y + 10 > p.y())
+ {
+ isOnDestructionBox = true;
+ }
+ return isOnDestructionBox;
+}
+
+/**
+ * Clean up anything before deletion.
+ */
+void SeqLineWidget::cleanup()
+{
+ cleanupDestructionBox();
+}
+
+/**
+ * Set the start point of the line.
+ *
+ * @param startX X coordinate of the start point.
+ * @param startY Y coordinate of the start point.
+ */
+void SeqLineWidget::setStartPoint(int startX, int startY)
+{
+ int endX = startX;
+ int endY = startY + m_nLengthY;
+ QGraphicsLineItem::setLine(startX, startY, endX, endY);
+ moveDestructionBox();
+}
+
+/**
+ * Clean up destruction box.
+ */
+void SeqLineWidget::cleanupDestructionBox()
+{
+ if (m_DestructionBox.line1) {
+ delete m_DestructionBox.line1;
+ m_DestructionBox.line1 = 0;
+ delete m_DestructionBox.line2;
+ m_DestructionBox.line2 = 0;
+ }
+}
+
+/**
+ * Set up destruction box.
+ */
+void SeqLineWidget::setupDestructionBox()
+{
+ cleanupDestructionBox();
+ if(!m_pObject->showDestruction()) {
+ return;
+ }
+ QRect rect;
+ rect.setX(m_pObject->x() + m_pObject->width() / 2 - 10);
+ rect.setY(m_pObject->y() + m_pObject->height() + m_nLengthY);
+ rect.setWidth(14);
+ rect.setHeight(14);
+
+ m_DestructionBox.line1 = new QGraphicsLineItem;
+ m_scene->addItem(m_DestructionBox.line1);
+ m_DestructionBox.setLine1Points(rect);
+ m_DestructionBox.line1->setVisible(true);
+ m_DestructionBox.line1->setPen(QPen(m_pObject->lineColor(), 2));
+ m_DestructionBox.line1->setZValue(3);
+
+ m_DestructionBox.line2 = new QGraphicsLineItem;
+ m_scene->addItem(m_DestructionBox.line2);
+ m_DestructionBox.setLine2Points(rect);
+ m_DestructionBox.line2->setVisible(true);
+ m_DestructionBox.line2->setPen(QPen(m_pObject->lineColor(), 2));
+ m_DestructionBox.line2->setZValue(3);
+}
+
+/**
+ * Move destruction box.
+ */
+void SeqLineWidget::moveDestructionBox()
+{
+ if(!m_DestructionBox.line1) {
+ return;
+ }
+ QRect rect;
+ rect.setX(m_pObject->x() + m_pObject->width() / 2 - 7);
+ rect.setY(m_pObject->y() + m_pObject->height() + m_nLengthY - 7);
+ rect.setWidth(14);
+ rect.setHeight(14);
+ m_DestructionBox.setLine1Points(rect);
+ m_DestructionBox.setLine2Points(rect);
+}
+
+/**
+ * Sets the y position of the bottom of the vertical line.
+ *
+ * @param yPosition The y coordinate for the bottom of the line.
+ */
+void SeqLineWidget::setEndOfLine(int yPosition)
+{
+ QPointF sp = line().p1();
+ int newY = yPosition;
+ m_nLengthY = yPosition - m_pObject->y() - m_pObject->height();
+ // normally the managing Objectwidget is responsible for the call of this function
+ // but to be sure - make a double check _against current position_
+ if (m_nLengthY < 0) {
+ m_nLengthY = 0;
+ newY = m_pObject->y() + m_pObject->height();
+ }
+ setLine(sp.x(), sp.y(), sp.x(), newY);
+ moveDestructionBox();
+ m_scene->resizeSceneToItems();
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/seqlinewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/seqlinewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/seqlinewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/seqlinewidget.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef SEQLINEWIDGET_H
+#define SEQLINEWIDGET_H
+
+#include <QGraphicsLineItem>
+
+class ObjectWidget;
+class UMLScene;
+
+/**
+ * @short Widget class for graphical representation of sequence lines
+ * @author Paul Hensgen
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class SeqLineWidget : public QGraphicsLineItem
+{
+public:
+ SeqLineWidget(UMLScene *scene, ObjectWidget * pObject);
+ virtual ~SeqLineWidget();
+
+ bool onWidget(const QPointF& p);
+
+ bool onDestructionBox(const QPointF& p);
+
+ void cleanup();
+
+ void setupDestructionBox();
+
+ void setStartPoint(int startX, int startY);
+
+ /**
+ * Gets the length of the line.
+ *
+ * @return Length of the line.
+ */
+ int getLineLength() {
+ return m_nLengthY;
+ }
+
+ /**
+ * Returns the @ref ObjectWidget associated with this sequence line.
+ *
+ * @return Pointer to the associated ObjectWidget.
+ */
+ ObjectWidget * getObjectWidget() {
+ return m_pObject;
+ }
+
+ void setEndOfLine(int yPosition);
+
+protected:
+ void cleanupDestructionBox();
+
+ void moveDestructionBox();
+
+ ObjectWidget* m_pObject; ///< ObjectWidget associated with this sequence line
+ UMLScene* m_scene; ///< scene displayed on
+
+ struct DestructionBox {
+ QGraphicsLineItem * line1;
+ QGraphicsLineItem * line2;
+ void setLine1Points(QRect rect) {
+ line1->setLine(rect.x(), rect.y(),
+ rect.x() + rect.width(), rect.y() + rect.height());
+ }
+ void setLine2Points(QRect rect) {
+ line2->setLine(rect.x(), rect.y() + rect.height(),
+ rect.x() + rect.width(), rect.y());
+ }
+ } m_DestructionBox; ///< the destruction box
+
+ int m_nLengthY; ///< the length of the line
+
+ static int const m_nMouseDownEpsilonX; ///< margin used for mouse clicks
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/signalwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/signalwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/signalwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/signalwidget.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,386 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "signalwidget.h"
+
+// app includes
+#include "basictypes.h"
+#include "debug_utils.h"
+#include "floatingtextwidget.h"
+#include "linkwidget.h"
+#include "listpopupmenu.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "uniqueid.h"
+#include "umlview.h"
+#include "umlwidget.h"
+
+// kde includes
+#include <KLocalizedString>
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+
+// qt includes
+#include <QEvent>
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+#include <QPolygon>
+
+/**
+ * Creates a Signal widget.
+ *
+ * @param scene The parent of the widget.
+ * @param signalType The type of Signal.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+SignalWidget::SignalWidget(UMLScene *scene, SignalType signalType, Uml::ID::Type id)
+ : UMLWidget(scene, WidgetBase::wt_Signal, id),
+ m_oldX(0),
+ m_oldY(0)
+{
+ m_signalType = signalType;
+ m_pName = NULL;
+ if (signalType == SignalWidget::Time) {
+ m_pName = new FloatingTextWidget(scene, Uml::TextRole::Floating, QString());
+ scene->setupNewWidget(m_pName);
+ m_pName->setX(0);
+ m_pName->setY(0);
+ connect(m_pName, SIGNAL(destroyed()), this, SLOT(slotTextDestroyed()));
+ }
+}
+
+/**
+ * Destructor.
+ */
+SignalWidget::~SignalWidget()
+{
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void SignalWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ setPenFromSettings(painter);
+ const int w = width();
+ const int h = height();
+ QPolygon a;
+ switch (m_signalType)
+ {
+ case Send :
+ if(UMLWidget::useFillColor())
+ painter->setBrush(UMLWidget::fillColor());
+ {
+ a.setPoints(5, 0, 0,
+ (w*2)/3, 0,
+ w, h/2,
+ (w*2)/3, h,
+ 0, h);
+ painter->drawPolygon(a);
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ int textStartY = (h / 2) - (fontHeight / 2);
+
+ painter->setPen(textColor());
+ QFont font = UMLWidget::font();
+ font.setBold(false);
+ painter->setFont(font);
+ painter->drawText(SIGNAL_MARGIN, textStartY,
+ w - SIGNAL_MARGIN * 2, fontHeight,
+ Qt::AlignCenter, name());
+ setPenFromSettings(painter);
+ }
+ break;
+ case Accept :
+ if(UMLWidget::useFillColor())
+ painter->setBrush(UMLWidget::fillColor());
+ {
+ a.setPoints(5, 0, 0,
+ w/3, h/2,
+ 0, h,
+ w, h,
+ w, 0);
+
+ painter->drawPolygon(a);
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ int textStartY = (h / 2) - (fontHeight / 2);
+
+ painter->setPen(textColor());
+ QFont font = UMLWidget::font();
+ font.setBold(false);
+ painter->setFont(font);
+ painter->drawText(SIGNAL_MARGIN, textStartY,
+ w - SIGNAL_MARGIN * 2 + (w/3), fontHeight,
+ Qt::AlignCenter, name());
+ setPenFromSettings(painter);
+ }
+ break;
+ case Time :
+ if(UMLWidget::useFillColor())
+ painter->setBrush(UMLWidget::fillColor());
+ {
+ a.setPoints(4, 0, 0,
+ w, h,
+ 0, h,
+ w, 0);
+
+ painter->drawPolygon(a);
+ //const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ //const int fontHeight = fm.lineSpacing();
+ //int textStartY = (h / 2) - (fontHeight / 2);
+ painter->setPen(textColor());
+ QFont font = UMLWidget::font();
+ font.setBold(false);
+ painter->setFont(font);
+
+ setPenFromSettings(painter);
+ }
+ if (m_pName) {
+ if (m_pName->x() == 0 && m_pName->y() == 0) {
+ //the floating text has not been linked with the signal
+ m_pName->setX(w/2 - m_pName->width()/2);
+ m_pName->setY(h);
+ }
+ m_pName->setVisible((m_pName->text().length() > 0));
+ m_pName->updateGeometry();
+ }
+
+ break;
+ default:
+ uWarning() << "Unknown signal type:" << m_signalType;
+ break;
+ }
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overrides the UMLWidget method.
+ */
+void SignalWidget::setX(qreal newX)
+{
+ m_oldX = x();
+ UMLWidget::setX(newX);
+}
+
+/**
+ * Overrides the UMLWidget method.
+ */
+void SignalWidget::setY(qreal newY)
+{
+ m_oldY = y();
+ UMLWidget::setY(newY);
+}
+
+/**
+ * Sets the name of the signal.
+ */
+void SignalWidget::setName(const QString &strName)
+{
+ UMLWidget::setName(strName);
+ updateGeometry();
+ if (signalType() == SignalWidget::Time) {
+ if (!m_pName) {
+ m_pName = new FloatingTextWidget(umlScene(), Uml::TextRole::Floating, m_Text);
+ umlScene()->setupNewWidget(m_pName);
+ m_pName->setX(0);
+ m_pName->setY(0);
+ connect(m_pName, SIGNAL(destroyed()), this, SLOT(slotTextDestroyed()));
+ }
+ else
+ m_pName->setText(m_Text);
+ }
+}
+
+/**
+ * Returns the type of Signal.
+ */
+SignalWidget::SignalType SignalWidget::signalType() const
+{
+ return m_signalType;
+}
+
+/**
+ * Returns the type string of Signal.
+ */
+QString SignalWidget::signalTypeStr() const
+{
+ return QLatin1String(ENUM_NAME(SignalWidget, SignalType, m_signalType));
+}
+
+/**
+ * Sets the type of Signal.
+ */
+void SignalWidget::setSignalType(SignalType signalType)
+{
+ m_signalType = signalType;
+}
+
+/**
+ * Show a properties dialog for a UMLWidget.
+ */
+void SignalWidget::showPropertiesDialog()
+{
+}
+
+/**
+ * Overrides mouseMoveEvent.
+ */
+void SignalWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* me)
+{
+ UMLWidget::mouseMoveEvent(me);
+ int diffX = m_oldX - x();
+ int diffY = m_oldY - y();
+ if (m_pName!=NULL) {
+ m_pName->setX(m_pName->x() - diffX);
+ m_pName->setY(m_pName->y() - diffY);
+ }
+}
+
+/**
+ * Loads a "signalwidget" XMI element.
+ */
+bool SignalWidget::loadFromXMI(QDomElement & qElement)
+{
+ if(!UMLWidget::loadFromXMI(qElement))
+ return false;
+ m_Text = qElement.attribute(QLatin1String("signalname"));
+ m_Doc = qElement.attribute(QLatin1String("documentation"));
+ QString type = qElement.attribute(QLatin1String("signaltype"));
+ QString textid = qElement.attribute(QLatin1String("textid"), QLatin1String("-1"));
+ Uml::ID::Type textId = Uml::ID::fromString(textid);
+
+ setSignalType((SignalType)type.toInt());
+ if (signalType() == Time) {
+
+ if (textId != Uml::ID::None) {
+ UMLWidget *flotext = m_scene -> findWidget(textId);
+ if (flotext != NULL) {
+ // This only happens when loading files produced by
+ // umbrello-kf6-1.3-beta2.
+ m_pName = static_cast<FloatingTextWidget*>(flotext);
+ return true;
+ }
+ } else {
+ // no textid stored -> get unique new one
+ textId = UniqueID::gen();
+ }
+ }
+ //now load child elements
+ QDomNode node = qElement.firstChild();
+ QDomElement element = node.toElement();
+ if (!element.isNull()) {
+ QString tag = element.tagName();
+ if (tag == QLatin1String("floatingtext") || tag == QLatin1String("UML::FloatingTextWidget")) {
+ m_pName = new FloatingTextWidget(m_scene, Uml::TextRole::Floating, m_Text, textId);
+ if(! m_pName->loadFromXMI(element)) {
+ // Most likely cause: The FloatingTextWidget is empty.
+ delete m_pName;
+ m_pName = NULL;
+ }
+ else
+ connect(m_pName, SIGNAL(destroyed()), this, SLOT(slotTextDestroyed()));
+ } else {
+ uError() << "unknown tag " << tag;
+ }
+ }
+ return true;
+}
+
+/**
+ * Creates the "signalwidget" XMI element.
+ */
+void SignalWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement signalElement = qDoc.createElement(QLatin1String("signalwidget"));
+ UMLWidget::saveToXMI(qDoc, signalElement);
+ signalElement.setAttribute(QLatin1String("signalname"), m_Text);
+ signalElement.setAttribute(QLatin1String("documentation"), m_Doc);
+ signalElement.setAttribute(QLatin1String("signaltype"), m_signalType);
+ if (m_pName && !m_pName->text().isEmpty()) {
+ signalElement.setAttribute(QLatin1String("textid"), Uml::ID::toString(m_pName->id()));
+ m_pName -> saveToXMI(qDoc, signalElement);
+ }
+ qElement.appendChild(signalElement);
+}
+
+/**
+ * Show a properties dialog for a SignalWidget.
+ *
+ */
+void SignalWidget::slotMenuSelection(QAction* action)
+{
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_Rename:
+ {
+ bool ok = false;
+ QString name = m_Text;
+#if QT_VERSION >= 0x050000
+ name = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter signal name"),
+ i18n("Enter the signal name :"),
+ QLineEdit::Normal,
+ m_Text, &ok);
+#else
+ name = KInputDialog::getText(i18n("Enter signal name"),
+ i18n("Enter the signal name :"),
+ m_Text, &ok);
+#endif
+ if (ok && name.length() > 0) {
+ setName(name);
+ }
+ }
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ }
+}
+
+/**
+ * Overrides method from UMLWidget
+ */
+QSizeF SignalWidget::minimumSize() const
+{
+ int width = SIGNAL_WIDTH, height = SIGNAL_HEIGHT;
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD);
+ const int fontHeight = fm.lineSpacing();
+ int textWidth = fm.width(name());
+
+ if (m_signalType == Accept)
+ textWidth = int((float)textWidth * 1.3f);
+ height = fontHeight;
+ if (m_signalType != Time)
+ {
+ width = textWidth > SIGNAL_WIDTH?textWidth:SIGNAL_WIDTH;
+ height = height > SIGNAL_HEIGHT?height:SIGNAL_HEIGHT;
+ }
+ width += SIGNAL_MARGIN * 2;
+ height += SIGNAL_MARGIN * 2;
+
+ return QSizeF(width, height);
+}
+
+/**
+ * Called if user deletes text widget
+ */
+void SignalWidget::slotTextDestroyed()
+{
+ m_pName = 0;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/signalwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/signalwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/signalwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/signalwidget.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+***************************************************************************/
+
+#ifndef SIGNALWIDGET_H
+#define SIGNALWIDGET_H
+
+#include "floatingtextwidget.h"
+#include "linkwidget.h"
+#include "umlwidget.h"
+#include "worktoolbar.h"
+
+#define SIGNAL_MARGIN 5
+#define SIGNAL_WIDTH 45
+#define SIGNAL_HEIGHT 15
+
+/**
+ * Represents a Send signal, Accept signal or Time event on an
+ * Activity diagram.
+ */
+class SignalWidget : public UMLWidget
+{
+ Q_OBJECT
+ Q_ENUMS(SignalType)
+public:
+ /// Enumeration that codes the different types of signal.
+ enum SignalType
+ {
+ Send = 0,
+ Accept,
+ Time
+ };
+
+ explicit SignalWidget(UMLScene * scene, SignalType signalType = Send, Uml::ID::Type id = Uml::ID::None);
+ virtual ~SignalWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ void setX(qreal newX);
+ void setY(qreal newY);
+
+ virtual void setName(const QString &strName);
+
+ SignalType signalType() const;
+ QString signalTypeStr() const;
+ void setSignalType(SignalType signalType);
+
+ virtual void showPropertiesDialog();
+
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *me);
+
+ virtual bool loadFromXMI(QDomElement & qElement);
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+public Q_SLOTS:
+ virtual void slotMenuSelection(QAction* action);
+
+protected:
+ QSizeF minimumSize() const;
+
+ /**
+ * Save the value of the widget to know how to move the floatingtext
+ */
+ int m_oldX;
+ int m_oldY;
+
+ // Only for the time event
+ /**
+ * This is a pointer to the Floating Text widget which displays the
+ * name of the signal widget.
+ */
+ FloatingTextWidget* m_pName;
+
+ SignalType m_signalType; ///< Type of signal
+
+protected Q_SLOTS:
+ void slotTextDestroyed();
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/statewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/statewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/statewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/statewidget.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,534 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "statewidget.h"
+
+// app includes
+#include "debug_utils.h"
+#include "docwindow.h"
+#include "listpopupmenu.h"
+#include "statedialog.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+#include "umlwidget.h"
+
+// kde includes
+#include <KLocalizedString>
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+#include <QPointer>
+
+/**
+ * Creates a State widget.
+ *
+ * @param scene The parent of the widget.
+ * @param stateType The type of state.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+StateWidget::StateWidget(UMLScene * scene, StateType stateType, Uml::ID::Type id)
+ : UMLWidget(scene, WidgetBase::wt_State, id)
+{
+ m_stateType = stateType;
+ m_drawVertical = true;
+ setAspectRatioMode();
+ m_Text = QLatin1String("State");
+ QSizeF size = minimumSize();
+ setSize(size.width(), size.height());
+}
+
+/**
+ * Destructor.
+ */
+StateWidget::~StateWidget()
+{
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void StateWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ const qreal w = width();
+ const qreal h = height();
+ if (w == 0 || h == 0)
+ return;
+
+ setPenFromSettings(painter);
+ switch (m_stateType) {
+ case StateWidget::Normal:
+ {
+ if (UMLWidget::useFillColor()) {
+ painter->setBrush(UMLWidget::fillColor());
+ }
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ int textStartY = (h / 2) - (fontHeight / 2);
+ const int count = m_Activities.count();
+ if (count == 0) {
+ painter->drawRoundRect(0, 0, w, h, (h*40)/w, (w*40)/h);
+ painter->setPen(textColor());
+ QFont font = UMLWidget::font();
+ font.setBold(false);
+ painter->setFont(font);
+ painter->drawText(STATE_MARGIN, textStartY,
+ w - STATE_MARGIN * 2, fontHeight,
+ Qt::AlignCenter, name());
+ setPenFromSettings(painter);
+ } else {
+ painter->drawRoundRect(0, 0, w, h, (h*40)/w, (w*40)/h);
+ textStartY = STATE_MARGIN;
+ painter->setPen(textColor());
+ QFont font = UMLWidget::font();
+ font.setBold(true);
+ painter->setFont(font);
+ painter->drawText(STATE_MARGIN, textStartY, w - STATE_MARGIN * 2,
+ fontHeight, Qt::AlignCenter, name());
+ font.setBold(false);
+ painter->setFont(font);
+ setPenFromSettings(painter);
+ int linePosY = textStartY + fontHeight;
+
+ QStringList::Iterator end(m_Activities.end());
+ for(QStringList::Iterator it(m_Activities.begin()); it != end; ++it) {
+ textStartY += fontHeight;
+ painter->drawLine(0, linePosY, w, linePosY);
+ painter->setPen(textColor());
+ painter->drawText(STATE_MARGIN, textStartY, w - STATE_MARGIN * 2,
+ fontHeight, Qt::AlignCenter, *it);
+ setPenFromSettings(painter);
+ linePosY += fontHeight;
+ }//end for
+ }//end else
+ }
+ break;
+ case StateWidget::Initial :
+ painter->setBrush(WidgetBase::lineColor());
+ painter->drawEllipse(0, 0, w, h);
+ break;
+ case StateWidget::End :
+ painter->setBrush(WidgetBase::lineColor());
+ painter->drawEllipse(0, 0, w, h);
+ painter->setBrush(Qt::white);
+ painter->drawEllipse(1, 1, w - 2, h - 2);
+ painter->setBrush(WidgetBase::lineColor());
+ painter->drawEllipse(3, 3, w - 6, h - 6);
+ break;
+ case StateWidget::Fork:
+ case StateWidget::Join:
+ {
+ painter->setPen(Qt::black);
+ painter->setBrush(Qt::black);
+ painter->drawRect(rect());
+ }
+ break;
+ case StateWidget::Junction:
+ {
+ painter->setPen(Qt::black);
+ painter->setBrush(Qt::black);
+ painter->drawEllipse(rect());
+ }
+ break;
+ case StateWidget::DeepHistory:
+ {
+ painter->setBrush(Qt::white);
+ painter->drawEllipse(rect());
+ painter->setPen(Qt::black);
+ painter->setFont(UMLWidget::font());
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing() / 2;
+ const int xStar = fm.boundingRect(QLatin1String("H")).width();
+ const int yStar = fontHeight / 4;
+ painter->drawText((w / 6),
+ (h / 4) + fontHeight, QLatin1String("H"));
+ painter->drawText((w / 6) + xStar,
+ (h / 4) + fontHeight - yStar, QLatin1String("*"));
+ }
+ break;
+ case StateWidget::ShallowHistory:
+ {
+ painter->setBrush(Qt::white);
+ painter->drawEllipse(rect());
+ painter->setPen(Qt::black);
+ painter->setFont(UMLWidget::font());
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing() / 2;
+ painter->drawText((w / 6),
+ (h / 4) + fontHeight, QLatin1String("H"));
+ }
+ break;
+ case StateWidget::Choice:
+ {
+ const qreal x = w / 2;
+ const qreal y = h / 2;
+ QPolygonF polygon;
+ polygon << QPointF(x, 0) << QPointF(w, y)
+ << QPointF(x, h) << QPointF(0, y);
+ painter->setBrush(UMLWidget::fillColor());
+ painter->drawPolygon(polygon);
+ }
+ break;
+ default:
+ uWarning() << "Unknown state type: " << stateTypeStr();
+ break;
+ }
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Overrides method from UMLWidget
+ */
+QSizeF StateWidget::minimumSize() const
+{
+ int width = 10, height = 10;
+ switch (m_stateType) {
+ case StateWidget::Normal:
+ {
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD);
+ const int fontHeight = fm.lineSpacing();
+ int textWidth = fm.width(name());
+ const int count = m_Activities.count();
+ height = fontHeight;
+ if(count > 0) {
+ height = fontHeight * (count + 1);
+
+ QStringList::ConstIterator end(m_Activities.end());
+ for(QStringList::ConstIterator it(m_Activities.begin()); it != end; ++it) {
+ int w = fm.width(*it);
+ if(w > textWidth)
+ textWidth = w;
+ }//end for
+ }//end if
+ width = textWidth > STATE_WIDTH?textWidth:STATE_WIDTH;
+ height = height > STATE_HEIGHT?height:STATE_HEIGHT;
+ width += STATE_MARGIN * 2;
+ height += STATE_MARGIN * 2;
+ break;
+ }
+ case StateWidget::Fork:
+ case StateWidget::Join:
+ if (m_drawVertical) {
+ width = 8;
+ height = 60;
+ } else {
+ width = 60;
+ height = 8;
+ }
+ break;
+ case StateWidget::Junction:
+ width = 18;
+ height = 18;
+ break;
+ case StateWidget::DeepHistory:
+ case StateWidget::ShallowHistory:
+ {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ width = height = fm.lineSpacing();
+ }
+ break;
+ case StateWidget::Choice:
+ width = 25;
+ height = 25;
+ break;
+ default:
+ break;
+ }
+
+ return QSizeF(width, height);
+}
+
+/**
+ * Overrides method from UMLWidget
+ */
+QSizeF StateWidget::maximumSize()
+{
+ switch (m_stateType) {
+ case StateWidget::Initial:
+ case StateWidget::End:
+ case StateWidget::Junction:
+ case StateWidget::Choice:
+ return QSizeF(35, 35);
+ break;
+ case StateWidget::DeepHistory:
+ case StateWidget::ShallowHistory:
+ {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ return QSizeF(fontHeight + 10, fontHeight + 10);
+ }
+ break;
+ default:
+ break;
+ }
+ return UMLWidget::maximumSize();
+}
+
+/**
+ * Set the aspect ratio mode.
+ * Some state types have a fixed aspect ratio
+ */
+void StateWidget::setAspectRatioMode()
+{
+ switch (m_stateType) {
+ case StateWidget::Initial:
+ case StateWidget::End:
+ case StateWidget::Choice:
+ case StateWidget::DeepHistory:
+ case StateWidget::ShallowHistory:
+ case StateWidget::Fork:
+ case StateWidget::Join:
+ case StateWidget::Junction:
+ setFixedAspectRatio(true);
+ break;
+ default:
+ setFixedAspectRatio(false);
+ break;
+ }
+}
+
+/**
+ * Returns the type of state.
+ * @return StateType
+ */
+StateWidget::StateType StateWidget::stateType() const
+{
+ return m_stateType;
+}
+
+/**
+ * Returns the type string of state.
+ */
+QString StateWidget::stateTypeStr() const
+{
+ return QLatin1String(ENUM_NAME(StateWidget, StateType, m_stateType));
+}
+
+/**
+ * Sets the type of state.
+ */
+void StateWidget::setStateType(StateType stateType)
+{
+ m_stateType = stateType;
+ setAspectRatioMode();
+}
+
+/**
+ * Adds an activity to this widget.
+ * @return true on success
+ */
+bool StateWidget::addActivity(const QString &activity)
+{
+ m_Activities.append(activity);
+ updateGeometry();
+ return true;
+}
+
+/**
+ * Removes the given activity from the state.
+ */
+bool StateWidget::removeActivity(const QString &activity)
+{
+ if(m_Activities.removeAll(activity) == 0)
+ return false;
+ updateGeometry();
+ return true;
+}
+
+/**
+ * Renames the given activity.
+ */
+bool StateWidget::renameActivity(const QString &activity, const QString &newName)
+{
+ int index = - 1;
+ if((index = m_Activities.indexOf(activity)) == -1)
+ return false;
+ m_Activities[ index ] = newName;
+ return true;
+}
+
+/**
+ * Sets the states activities to the ones given.
+ */
+void StateWidget::setActivities(const QStringList &list)
+{
+ m_Activities = list;
+ updateGeometry();
+}
+
+/**
+ * Returns the list of activities.
+ */
+QStringList StateWidget::activities() const
+{
+ return m_Activities;
+}
+
+/**
+ * Get whether to draw a fork or join vertically.
+ */
+bool StateWidget::drawVertical() const
+{
+ return m_drawVertical;
+}
+
+/**
+ * Set whether to draw a fork or join vertically.
+ */
+void StateWidget::setDrawVertical(bool to)
+{
+ m_drawVertical = to;
+ setSize(height(), width());
+ updateGeometry();
+ UMLWidget::adjustAssocs(x(), y());
+}
+
+/**
+ * Show a properties dialog for a StateWidget.
+ */
+void StateWidget::showPropertiesDialog()
+{
+ UMLApp::app()->docWindow()->updateDocumentation(false);
+
+ QPointer<StateDialog> dialog = new StateDialog(m_scene->activeView(), this);
+ if (dialog->exec() && dialog->getChangesMade()) {
+ UMLApp::app()->docWindow()->showDocumentation(this, true);
+ UMLApp::app()->document()->setModified(true);
+ }
+ delete dialog;
+}
+
+/**
+ * Creates the "statewidget" XMI element.
+ */
+void StateWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement stateElement = qDoc.createElement(QLatin1String("statewidget"));
+ UMLWidget::saveToXMI(qDoc, stateElement);
+ stateElement.setAttribute(QLatin1String("statename"), m_Text);
+ stateElement.setAttribute(QLatin1String("documentation"), m_Doc);
+ stateElement.setAttribute(QLatin1String("statetype"), m_stateType);
+ if (m_stateType == Fork || m_stateType == Join)
+ stateElement.setAttribute(QLatin1String("drawvertical"), m_drawVertical);
+ //save states activities
+ QDomElement activitiesElement = qDoc.createElement(QLatin1String("Activities"));
+
+ QStringList::Iterator end(m_Activities.end());
+ for(QStringList::Iterator it(m_Activities.begin()); it != end; ++it) {
+ QDomElement tempElement = qDoc.createElement(QLatin1String("Activity"));
+ tempElement.setAttribute(QLatin1String("name"), *it);
+ activitiesElement.appendChild(tempElement);
+ }//end for
+ stateElement.appendChild(activitiesElement);
+ qElement.appendChild(stateElement);
+}
+
+/**
+ * Loads a "statewidget" XMI element.
+ */
+bool StateWidget::loadFromXMI(QDomElement & qElement)
+{
+ if(!UMLWidget::loadFromXMI(qElement))
+ return false;
+ m_Text = qElement.attribute(QLatin1String("statename"));
+ m_Doc = qElement.attribute(QLatin1String("documentation"));
+ QString type = qElement.attribute(QLatin1String("statetype"), QLatin1String("1"));
+ m_stateType = (StateType)type.toInt();
+ setAspectRatioMode();
+ QString drawVertical = qElement.attribute(QLatin1String("drawvertical"), QLatin1String("1"));
+ m_drawVertical = (bool)drawVertical.toInt();
+ //load states activities
+ QDomNode node = qElement.firstChild();
+ QDomElement tempElement = node.toElement();
+ if(!tempElement.isNull() && tempElement.tagName() == QLatin1String("Activities")) {
+ QDomNode node = tempElement.firstChild();
+ QDomElement activityElement = node.toElement();
+ while(!activityElement.isNull()) {
+ if(activityElement.tagName() == QLatin1String("Activity")) {
+ QString name = activityElement.attribute(QLatin1String("name"));
+ if(!name.isEmpty())
+ m_Activities.append(name);
+ }//end if
+ node = node.nextSibling();
+ activityElement = node.toElement();
+ }//end while
+ }//end if
+ return true;
+}
+
+/**
+ * Captures any popup menu signals for menus it created.
+ */
+void StateWidget::slotMenuSelection(QAction* action)
+{
+ bool ok = false;
+ QString nameNew = name();
+
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
+ switch(sel) {
+ case ListPopupMenu::mt_Rename:
+#if QT_VERSION >= 0x050000
+ nameNew = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter State Name"),
+ i18n("Enter the name of the new state:"),
+ QLineEdit::Normal,
+ name(), &ok);
+#else
+ nameNew = KInputDialog::getText(i18n("Enter State Name"),
+ i18n("Enter the name of the new state:"),
+ name(), &ok);
+#endif
+ if (ok && nameNew.length() > 0) {
+ setName(nameNew);
+ }
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ showPropertiesDialog();
+ break;
+
+ case ListPopupMenu::mt_New_Activity:
+#if QT_VERSION >= 0x050000
+ nameNew = QInputDialog::getText(Q_NULLPTR,
+ i18n("Enter Activity"),
+ i18n("Enter the name of the new activity:"),
+ QLineEdit::Normal,
+ i18n("new activity"), &ok);
+#else
+ nameNew = KInputDialog::getText(i18n("Enter Activity"),
+ i18n("Enter the name of the new activity:"),
+ i18n("new activity"), &ok);
+#endif
+ if (ok && nameNew.length() > 0) {
+ addActivity(nameNew);
+ }
+ break;
+
+ case ListPopupMenu::mt_Flip:
+ setDrawVertical(!m_drawVertical);
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(action);
+ break;
+ }
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/statewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/statewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/statewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/statewidget.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,99 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+***************************************************************************/
+
+#ifndef STATEWIDGET_H
+#define STATEWIDGET_H
+
+#include "umlwidget.h"
+
+#include <QPainter>
+#include <QStringList>
+
+#define STATE_MARGIN 5
+#define STATE_WIDTH 30
+#define STATE_HEIGHT 10
+
+/**
+ * This class is the graphical version of a UML State.
+ *
+ * A StateWidget is created by a @ref UMLView. A StateWidget belongs to
+ * only one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to is destroyed,
+ * it will be automatically deleted.
+ *
+ * The StateWidget class inherits from the @ref UMLWidget class
+ * which adds most of the functionality to this class.
+ *
+ * @short A graphical version of a UML State.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class StateWidget : public UMLWidget
+{
+ Q_OBJECT
+ Q_ENUMS(StateType)
+public:
+ /// Enumeration that codes the different types of state.
+ enum StateType
+ {
+ Initial = 0, // Pseudostate
+ Normal,
+ End,
+ Fork, // Pseudostate
+ Join, // Pseudostate
+ Junction, // Pseudostate
+ DeepHistory, // Pseudostate
+ ShallowHistory, // Pseudostate
+ Choice // Pseudostate
+ //Terminate // Pseudostate
+ //EntryPoint // Pseudostate
+ //ExitPoint // Pseudostate
+ };
+
+ explicit StateWidget(UMLScene * scene, StateType stateType = Normal, Uml::ID::Type id = Uml::ID::None);
+ virtual ~StateWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ StateType stateType() const;
+ QString stateTypeStr() const;
+ void setStateType(StateType stateType);
+
+ bool addActivity(const QString &activity);
+ bool removeActivity(const QString &activity);
+ bool renameActivity(const QString &activity, const QString &newName);
+
+ QStringList activities() const;
+ void setActivities(const QStringList &list);
+
+ bool drawVertical() const;
+ void setDrawVertical(bool to = true);
+
+ virtual void showPropertiesDialog();
+
+ virtual bool loadFromXMI(QDomElement & qElement);
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+protected:
+ QSizeF minimumSize() const;
+ QSizeF maximumSize();
+ void setAspectRatioMode();
+
+public Q_SLOTS:
+ virtual void slotMenuSelection(QAction* action);
+
+private:
+ StateType m_stateType; ///< Type of state.
+ bool m_drawVertical; ///< whether to draw the fork/join horizontally or vertically
+ QStringList m_Activities; ///< List of activities for the state.
+
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/statusbartoolbutton.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/statusbartoolbutton.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/statusbartoolbutton.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/statusbartoolbutton.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,122 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+Widget taken from gwenview-kf6
+Copyright 2007 Aurélien Gâteau <agateau@kde.org>
+
+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.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR purpose-kf6. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+// Self
+#include "statusbartoolbutton.h"
+
+// Qt
+#include <QAction>
+#include <QStyleOptionToolButton>
+#include <QStylePainter>
+#include <QToolButton>
+
+// KDE
+#include <KLocalizedString>
+
+StatusBarToolButton::StatusBarToolButton(QWidget* parent)
+ : QToolButton(parent),
+ mGroupPosition(NotGrouped)
+{
+ setToolButtonStyle(Qt::ToolButtonTextOnly);
+ setFocusPolicy(Qt::NoFocus);
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+}
+
+
+QSize StatusBarToolButton::minimumSizeHint() const
+{
+ return sizeHint();
+}
+
+
+QSize StatusBarToolButton::sizeHint() const
+{
+ QSize sh = QToolButton::sizeHint();
+ sh.setHeight(fontMetrics().height());
+ return sh;
+}
+
+
+void StatusBarToolButton::setGroupPosition(StatusBarToolButton::GroupPosition groupPosition)
+{
+ mGroupPosition = groupPosition;
+}
+
+
+void StatusBarToolButton::paintEvent(QPaintEvent* event)
+{
+ if (mGroupPosition == NotGrouped) {
+ QToolButton::paintEvent(event);
+ return;
+ }
+ QStylePainter painter(this);
+ QStyleOptionToolButton opt;
+ initStyleOption(&opt);
+ QStyleOptionToolButton panelOpt = opt;
+
+ // Panel
+ QRect& panelRect = panelOpt.rect;
+ switch (mGroupPosition) {
+ case GroupLeft:
+ panelRect.setWidth(panelRect.width() * 2);
+ break;
+ case GroupCenter:
+ panelRect.setLeft(panelRect.left() - panelRect.width());
+ panelRect.setWidth(panelRect.width() * 3);
+ break;
+ case GroupRight:
+ panelRect.setLeft(panelRect.left() - panelRect.width());
+ break;
+ case NotGrouped:
+ Q_ASSERT(0);
+ }
+ painter.drawPrimitive(QStyle::PE_PanelButtonTool, panelOpt);
+
+ // Separator
+ const int y1 = opt.rect.top() + 6;
+ const int y2 = opt.rect.bottom() - 6;
+ if (mGroupPosition & GroupRight) {
+ const int x = opt.rect.left();
+ painter.setPen(opt.palette.color(QPalette::Light));
+ painter.drawLine(x, y1, x, y2);
+ }
+ if (mGroupPosition & GroupLeft) {
+ const int x = opt.rect.right();
+ painter.setPen(opt.palette.color(QPalette::Mid));
+ painter.drawLine(x, y1, x, y2);
+ }
+
+ // Text
+ painter.drawControl(QStyle::CE_ToolButtonLabel, opt);
+
+ // Filtering message on tooltip text for CJK to remove accelerators.
+ // Quoting ktoolbar.cpp:
+ // """
+ // CJK languages use more verbose accelerator marker: they add a Latin
+ // letter in parenthesis, and put accelerator on that. Hence, the default
+ // removal of ampersand only may not be enough there, instead the whole
+ // parenthesis construct should be removed. Provide these filtering i18n
+ // messages so that translators can use Transcript for custom removal.
+ // """
+ if (!actions().isEmpty()) {
+ QAction* action = actions().first();
+ setToolTip(i18nc("@info:tooltip of custom toolbar button", "%1", action->toolTip()));
+ }
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/statusbartoolbutton.h umbrello-kf6-15.08.1/umbrello/umlwidgets/statusbartoolbutton.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/statusbartoolbutton.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/statusbartoolbutton.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,58 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+gwenview-kf6: an image viewer
+Copyright 2007 Aurélien Gâteau <agateau@kde.org>
+
+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.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR purpose-kf6. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+#ifndef STATUSBARTOOLBUTTON_H
+#define STATUSBARTOOLBUTTON_H
+
+// Qt
+#include <QToolButton>
+
+/**
+ * A thin tool button which can be grouped with another and look like one solid-kf6
+ * bar:
+ *
+ * (button1 | button2)
+ */
+class StatusBarToolButton : public QToolButton
+{
+ Q_OBJECT
+public:
+ enum GroupPosition {
+ NotGrouped = 0,
+ GroupLeft = 1,
+ GroupRight = 2,
+ GroupCenter = 3
+ };
+
+ explicit StatusBarToolButton(QWidget* parent = 0);
+
+ virtual QSize minimumSizeHint() const;
+ virtual QSize sizeHint() const;
+
+ void setGroupPosition(StatusBarToolButton::GroupPosition groupPosition);
+
+protected:
+ virtual void paintEvent(QPaintEvent* event);
+
+private:
+ GroupPosition mGroupPosition;
+};
+
+#endif /* STATUSBARTOOLBUTTON_H */
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/toolbarstateonewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/toolbarstateonewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/toolbarstateonewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/toolbarstateonewidget.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,249 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "toolbarstateonewidget.h"
+
+// app includes
+#include "activitywidget.h"
+#include "dialog_utils.h"
+#include "floatingtextwidget.h"
+#include "messagewidget.h"
+#include "objectwidget.h"
+#include "pinwidget.h"
+#include "portwidget.h"
+#include "preconditionwidget.h"
+#include "regionwidget.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlwidget.h"
+#include "object_factory.h"
+#include "package.h"
+#include "widget_factory.h"
+
+// kde includes
+#include <KLocalizedString>
+#include <KMessageBox>
+#if QT_VERSION < 0x050000
+#include <kinputdialog.h>
+#endif
+
+// qt includes
+#if QT_VERSION >= 0x050000
+#include <QInputDialog>
+#endif
+
+// using namespace Uml;
+
+/**
+ * Creates a new ToolBarStateOneWidget.
+ *
+ * @param umlScene The UMLScene to use.
+ */
+ToolBarStateOneWidget::ToolBarStateOneWidget(UMLScene *umlScene)
+ : ToolBarStatePool(umlScene),
+ m_firstObject(0),
+ m_isObjectWidgetLine(false)
+{
+}
+
+/**
+ * Destroys this ToolBarStateOneWidget.
+ */
+ToolBarStateOneWidget::~ToolBarStateOneWidget()
+{
+}
+
+/**
+ * Called when the current tool is changed to use another tool.
+ * Executes base method and cleans the message.
+ */
+void ToolBarStateOneWidget::cleanBeforeChange()
+{
+ ToolBarStatePool::cleanBeforeChange();
+}
+
+/**
+ * Called when a mouse event happened.
+ * It executes the base method and then updates the position of the
+ * message line, if any.
+ */
+void ToolBarStateOneWidget::mouseMove(QGraphicsSceneMouseEvent* ome)
+{
+ ToolBarStatePool::mouseMove(ome);
+}
+
+/**
+ * A widget was removed from the UMLView.
+ * If the widget removed was the current widget, the current widget is set
+ * to 0.
+ * Also, if it was the first object, the message is cleaned.
+ */
+void ToolBarStateOneWidget::slotWidgetRemoved(UMLWidget* widget)
+{
+ ToolBarState::slotWidgetRemoved(widget);
+}
+
+/**
+ * Selects only widgets, but no associations.
+ * Overrides base class method.
+ * If the press event happened on the line of an object, the object is set
+ * as current widget. If the press event happened on a widget, the widget is
+ * set as current widget.
+ */
+void ToolBarStateOneWidget::setCurrentElement()
+{
+ m_isObjectWidgetLine = false;
+ ObjectWidget* objectWidgetLine = m_pUMLScene->onWidgetLine(m_pMouseEvent->scenePos());
+ if (objectWidgetLine) {
+ setCurrentWidget(objectWidgetLine);
+ m_isObjectWidgetLine = true;
+ return;
+ }
+
+ UMLWidget *widget = m_pUMLScene->widgetAt(m_pMouseEvent->scenePos());
+ if (widget) {
+ setCurrentWidget(widget);
+ return;
+ }
+}
+
+/**
+ * Called when the release event happened on a widget.
+ * If the button pressed isn't left button or the widget isn't an object
+ * widget, the message is cleaned.
+ * If the release event didn't happen on the line of an object and the first
+ * object wasn't selected, nothing is done. If the first object was already
+ * selected, a creation message is made.
+ * If the event happened on the line of an object, the first object or the
+ * second are set, depending on whether the first object was already set or
+ * not.
+ */
+void ToolBarStateOneWidget::mouseReleaseWidget()
+{
+ WidgetBase::WidgetType type = widgetType();
+
+ if (type == WidgetBase::wt_Precondition) {
+ m_firstObject = 0;
+ }
+ if (type == WidgetBase::wt_Pin) {
+ m_firstObject = 0;
+ }
+
+ if (m_pMouseEvent->button() != Qt::LeftButton ||
+ (currentWidget()->baseType() != WidgetBase::wt_Object &&
+ currentWidget()->baseType() != WidgetBase::wt_Activity &&
+ currentWidget()->baseType() != WidgetBase::wt_Component &&
+ currentWidget()->baseType() != WidgetBase::wt_Region)) {
+ return;
+ }
+
+ if (!m_firstObject && type == WidgetBase::wt_Pin) {
+ setWidget(currentWidget());
+ return ;
+ }
+
+ if (!m_isObjectWidgetLine && !m_firstObject) {
+ return;
+ }
+
+ if (!m_firstObject) {
+ setWidget(currentWidget());
+ }
+
+}
+
+/**
+ * Called when the release event happened on an empty space.
+ * Cleans the message.
+ * Empty spaces are not only actual empty spaces, but also associations.
+ */
+void ToolBarStateOneWidget::mouseReleaseEmpty()
+{
+}
+
+/**
+ * Sets the first object of the message using the specified object.
+ * The temporal visual message is created and mouse tracking enabled, so
+ * mouse events will be delivered.
+ *
+ * @param firstObject The first object of the message.
+ */
+void ToolBarStateOneWidget::setWidget(UMLWidget* firstObject)
+{
+ m_firstObject = firstObject;
+
+ UMLWidget * umlwidget = 0;
+ //m_pUMLScene->viewport()->setMouseTracking(true);
+ if (widgetType() == WidgetBase::wt_Precondition) {
+ umlwidget = new PreconditionWidget(m_pUMLScene, static_cast<ObjectWidget*>(m_firstObject));
+
+ Dialog_Utils::askNameForWidget(umlwidget, i18n("Enter Precondition Name"), i18n("Enter the precondition"), i18n("new precondition"));
+ // Create the widget. Some setup functions can remove the widget.
+ }
+
+ if (widgetType() == WidgetBase::wt_Pin) {
+ if (m_firstObject->baseType() == WidgetBase::wt_Activity) {
+ umlwidget = new PinWidget(m_pUMLScene, m_firstObject);
+ // Create the widget. Some setup functions can remove the widget.
+ } else if (m_firstObject->baseType() == WidgetBase::wt_Component) {
+ bool pressedOK = false;
+#if QT_VERSION >= 0x050000
+ QString name = QInputDialog::getText(UMLApp::app(),
+ i18n("Enter Port Name"), i18n("Enter the port"),
+ QLineEdit::Normal,
+ i18n("new port"),
+ &pressedOK);
+#else
+ QString name = KInputDialog::getText(i18n("Enter Port Name"), i18n("Enter the port"), i18n("new port"),
+ &pressedOK, UMLApp::app());
+#endif
+ if (pressedOK) {
+ UMLPackage* component = static_cast<UMLPackage*>(m_firstObject->umlObject());
+ UMLObject *port = Object_Factory::createUMLObject(UMLObject::ot_Port, name, component);
+ umlwidget = Widget_Factory::createWidget(m_pUMLScene, port);
+ }
+ }
+ }
+
+ if (umlwidget) {
+ m_pUMLScene->setupNewWidget(umlwidget);
+ }
+
+}
+
+/**
+ * Returns the widget type of this tool.
+ *
+ * @return The widget type of this tool.
+ */
+WidgetBase::WidgetType ToolBarStateOneWidget::widgetType()
+{
+ if (getButton() == WorkToolBar::tbb_Seq_Precondition) {
+ return WidgetBase::wt_Precondition;
+ }
+
+ if (getButton() == WorkToolBar::tbb_Pin) {
+ return WidgetBase::wt_Pin;
+ }
+ // Shouldn't happen
+ Q_ASSERT(0);
+ return WidgetBase::wt_Pin;
+}
+
+/**
+ * Goes back to the initial state.
+ */
+void ToolBarStateOneWidget::init()
+{
+ ToolBarStatePool::init();
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/toolbarstateonewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/toolbarstateonewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/toolbarstateonewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/toolbarstateonewidget.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef TOOLBARSTATEONEWIDGET_H
+#define TOOLBARSTATEONEWIDGET_H
+
+#include "toolbarstatepool.h"
+#include "widgetbase.h"
+
+/**
+ * Sequence tool to create components linked with one object in sequence diagram
+ * like precondition.
+ * With sequence tool, one objects is selected clicking with left button on
+ * it
+ */
+class ToolBarStateOneWidget : public ToolBarStatePool
+{
+ Q_OBJECT
+public:
+ explicit ToolBarStateOneWidget(UMLScene *umlScene);
+ virtual ~ToolBarStateOneWidget();
+
+ virtual void cleanBeforeChange();
+
+ // FIXME: obsolete
+ virtual void mouseMove(QGraphicsSceneMouseEvent* ome);
+
+public Q_SLOTS:
+ virtual void slotWidgetRemoved(UMLWidget* widget);
+
+protected:
+ virtual void setCurrentElement();
+
+ virtual void mouseReleaseWidget();
+ virtual void mouseReleaseEmpty();
+
+ void setWidget(UMLWidget* firstObject);
+ WidgetBase::WidgetType widgetType();
+
+ UMLWidget* m_firstObject; ///< The first object in the message.
+
+ /**
+ * If there is a current widget, it is true if the press event happened on
+ * the line of an object, or false if it happened on a normal UMLWidget.
+ */
+ bool m_isObjectWidgetLine;
+
+private:
+ virtual void init();
+};
+
+#endif //TOOLBARSTATEONEWIDGET_H
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/umlwidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/umlwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/umlwidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/umlwidget.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,1859 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "umlwidget.h"
+
+// local includes
+#include "associationwidget.h"
+#include "classifier.h"
+#include "classpropertiesdialog.h"
+#include "cmds.h"
+#include "debug_utils.h"
+#include "docwindow.h"
+#include "floatingtextwidget.h"
+#include "idchangelog.h"
+#include "listpopupmenu.h"
+#include "settingsdialog.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umllistview.h"
+#include "umlobject.h"
+#include "umlscene.h"
+#include "umlview.h"
+#include "uniqueid.h"
+
+// kde includes
+#include <KLocalizedString>
+#include <KMessageBox>
+
+// qt includes
+#include <QApplication>
+#include <QColor>
+#include <QPainter>
+#include <QPointer>
+
+using namespace Uml;
+
+DEBUG_REGISTER_DISABLED(UMLWidget)
+
+const QSizeF UMLWidget::DefaultMinimumSize(50, 20);
+const QSizeF UMLWidget::DefaultMaximumSize(1000, 5000);
+const qreal UMLWidget::defaultMargin = 5;
+
+/**
+ * Creates a UMLWidget object.
+ *
+ * @param scene The view to be displayed on.
+ * @param type The WidgetType to construct.
+ * This must be set to the appropriate value by the constructors of inheriting classes.
+ * @param o The UMLObject to represent.
+ */
+UMLWidget::UMLWidget(UMLScene * scene, WidgetType type, UMLObject * o)
+ : WidgetBase(scene, type)
+{
+ init();
+ m_umlObject = o;
+ if (m_umlObject) {
+ connect(m_umlObject, SIGNAL(modified()), this, SLOT(updateWidget()));
+ m_nId = m_umlObject->id();
+ }
+}
+
+/**
+ * Creates a UMLWidget object.
+ *
+ * @param scene The view to be displayed on.
+ * @param type The WidgetType to construct.
+ * This must be set to the appropriate value by the constructors of inheriting classes.
+ * @param id The id of the widget.
+ * The default value (id_None) will prompt generation of a new ID.
+ */
+UMLWidget::UMLWidget(UMLScene *scene, WidgetType type, Uml::ID::Type id)
+ : WidgetBase(scene, type)
+{
+ init();
+ if (id == Uml::ID::None)
+ m_nId = UniqueID::gen();
+ else
+ m_nId = id;
+}
+
+/**
+ * Destructor.
+ */
+UMLWidget::~UMLWidget()
+{
+ cleanup();
+}
+
+/**
+ * Assignment operator
+ */
+UMLWidget& UMLWidget::operator=(const UMLWidget & other)
+{
+ if (this == &other)
+ return *this;
+
+ WidgetBase::operator=(other);
+
+ // assign members loaded/saved
+ m_useFillColor = other.m_useFillColor;
+ m_usesDiagramFillColor = other.m_usesDiagramFillColor;
+ m_usesDiagramUseFillColor = other.m_usesDiagramUseFillColor;
+ m_fillColor = other.m_fillColor;
+ m_Assocs = other.m_Assocs;
+ m_isInstance = other.m_isInstance;
+ m_instanceName = other.m_instanceName;
+ m_instanceName = other.m_instanceName;
+ m_showStereotype = other.m_showStereotype;
+ setX(other.x());
+ setY(other.y());
+ setRect(rect().x(), rect().y(), other.width(), other.height());
+
+ // assign volatile (non-saved) members
+ m_startMove = other.m_startMove;
+ m_nPosX = other.m_nPosX;
+ m_doc = other.m_doc; //new
+ m_resizable = other.m_resizable;
+ for (unsigned i = 0; i < FT_INVALID; ++i)
+ m_pFontMetrics[i] = other.m_pFontMetrics[i];
+ m_activated = other.m_activated;
+ m_ignoreSnapToGrid = other.m_ignoreSnapToGrid;
+ m_ignoreSnapComponentSizeToGrid = other.m_ignoreSnapComponentSizeToGrid;
+ return *this;
+}
+
+/**
+ * Overload '==' operator
+ */
+bool UMLWidget::operator==(const UMLWidget& other) const
+{
+ if (this == &other)
+ return true;
+
+ if (m_baseType != other.m_baseType) {
+ return false;
+ }
+
+ if (id() != other.id())
+ return false;
+
+ /* Testing the associations is already an exaggeration, no?
+ The type and ID should uniquely identify an UMLWidget.
+ */
+ if (m_Assocs.count() != other.m_Assocs.count()) {
+ return false;
+ }
+
+ // if(getBaseType() != wt_Text) // DON'T do this for floatingtext widgets, an infinite loop will result
+ // {
+ AssociationWidgetListIt assoc_it(m_Assocs);
+ AssociationWidgetListIt assoc_it2(other.m_Assocs);
+ AssociationWidget * assoc = 0, *assoc2 = 0;
+ while (assoc_it.hasNext() && assoc_it2.hasNext()) {
+ assoc = assoc_it.next();
+ assoc2 = assoc_it2.next();
+
+ if (!(*assoc == *assoc2)) {
+ return false;
+ }
+ }
+ // }
+ return true;
+ // NOTE: In the comparison tests we are going to do, we don't need these values.
+ // They will actually stop things functioning correctly so if you change these, be aware of that.
+ /*
+ if(m_useFillColor != other.m_useFillColor)
+ return false;
+ if(m_nId != other.m_nId)
+ return false;
+ if(m_nX != other.m_nX)
+ return false;
+ if(m_nY != other.m_nY)
+ return false;
+ */
+}
+
+/**
+ * Sets the local id of the object.
+ *
+ * @param id The local id of the object.
+ */
+void UMLWidget::setLocalID(Uml::ID::Type id)
+{
+ m_nLocalID = id;
+}
+
+/**
+ * Returns the local ID for this object. This ID is used so that
+ * many objects of the same @ref UMLObject instance can be on the
+ * same diagram.
+ *
+ * @return The local ID.
+ */
+Uml::ID::Type UMLWidget::localID() const
+{
+ return m_nLocalID;
+}
+
+/**
+ * Returns the widget with the given ID.
+ * The default implementation tests the following IDs:
+ * - m_nLocalID
+ * - if m_umlObject is non NULL: m_umlObject->id()
+ * - m_nID
+ * Composite widgets override this function to test further owned widgets.
+ *
+ * @param id The ID to test this widget against.
+ * @return 'this' if id is either of m_nLocalID, m_umlObject->id(), or m_nId;
+ * else NULL.
+ */
+UMLWidget* UMLWidget::widgetWithID(Uml::ID::Type id)
+{
+ if (id == m_nLocalID ||
+ (m_umlObject != NULL && id == m_umlObject->id()) ||
+ id == m_nId)
+ return this;
+ return NULL;
+}
+
+/**
+ * Compute the minimum possible width and height.
+ *
+ * @return QSizeF(mininum_width, minimum_height)
+ */
+QSizeF UMLWidget::minimumSize() const
+{
+ return m_minimumSize;
+}
+
+/**
+ * This method is used to set the minimum size variable for this
+ * widget.
+ *
+ * @param newSize The size being set as minimum.
+ */
+void UMLWidget::setMinimumSize(const QSizeF& newSize)
+{
+ m_minimumSize = newSize;
+}
+
+/**
+ * Compute the maximum possible width and height.
+ *
+ * @return maximum size
+ */
+QSizeF UMLWidget::maximumSize()
+{
+ return m_maximumSize;
+}
+
+/**
+ * This method is used to set the maximum size variable for this
+ * widget.
+ *
+ * @param newSize The size being set as maximum.
+ */
+void UMLWidget::setMaximumSize(const QSizeF& newSize)
+{
+ m_maximumSize = newSize;
+}
+
+/**
+ * Event handler for context menu events.
+ */
+void UMLWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+{
+ WidgetBase::contextMenuEvent(event);
+}
+
+/**
+ * Moves the widget to a new position using the difference between the
+ * current position and the new position.
+ * This method doesn't adjust associations. It only moves the widget.
+ *
+ * It can be overridden to constrain movement only in one axis even when
+ * the user isn't constraining the movement with shift or control buttons, for example.
+ * The movement policy set here is applied whenever the widget is moved, being it
+ * moving it explicitly, or as a part of a selection but not receiving directly the
+ * mouse events.
+ *
+ * Default behaviour is move the widget to the new position using the diffs.
+ * @see constrainMovementForAllWidgets
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+void UMLWidget::moveWidgetBy(qreal diffX, qreal diffY)
+{
+ setX(x() + diffX);
+ setY(y() + diffY);
+}
+
+/**
+ * Modifies the value of the diffX and diffY variables used to move the widgets.
+ *
+ * It can be overridden to constrain movement of all the selected widgets only in one
+ * axis even when the user isn't constraining the movement with shift or control
+ * buttons, for example.
+ * The difference with moveWidgetBy is that the diff positions used here are
+ * applied to all the selected widgets instead of only to m_widget, and that
+ * moveWidgetBy, in fact, moves the widget, and here simply the diff positions
+ * are modified.
+ *
+ * Default behaviour is do nothing.
+ * @see moveWidgetBy
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+void UMLWidget::constrainMovementForAllWidgets(qreal &diffX, qreal &diffY)
+{
+ Q_UNUSED(diffX) Q_UNUSED(diffY)
+}
+
+/**
+ * Bring the widget at the pressed position to the foreground.
+ */
+void UMLWidget::toForeground()
+{
+ QRectF rect = QRectF(scenePos(), QSizeF(width(), height()));
+ QList<QGraphicsItem*> items = scene()->items(rect, Qt::IntersectsItemShape, Qt::DescendingOrder);
+ DEBUG(DBG_SRC) << "items at " << rect << " = " << items.count();
+ if (items.count() > 1) {
+ foreach(QGraphicsItem* i, items) {
+ UMLWidget* w = dynamic_cast<UMLWidget*>(i);
+ if (w) {
+ DEBUG(DBG_SRC) << "item=" << w->name() << " with zValue=" << w->zValue();
+ if (w->name() != name()) {
+ if (w->zValue() >= zValue()) {
+ setZValue(w->zValue() + 1.0);
+ DEBUG(DBG_SRC) << "bring to foreground with zValue: " << zValue();
+ }
+ }
+ }
+ }
+ }
+ else {
+ setZValue(0.0);
+ }
+ DEBUG(DBG_SRC) << "zValue is " << zValue();
+}
+
+/**
+ * Handles a mouse press event.
+ * It'll select the widget (or mark it to be deselected) and prepare it to
+ * be moved or resized. Go on reading for more info about this.
+ *
+ * Widget values and message bar status are saved.
+ *
+ * If shift or control buttons are pressed, we're in move area no matter
+ * where the button was pressed in the widget. Moreover, if the widget
+ * wasn't already selected, it's added to the selection. If already selected,
+ * it's marked to be deselected when releasing the button (provided it isn't
+ * moved).
+ * Also, if the widget is already selected with other widgets but shift nor
+ * control buttons are pressed, we're in move area. If finally we don't move
+ * the widget, it's selected and the other widgets deselected when releasing
+ * the left button.
+ *
+ * If shift nor control buttons are pressed, we're facing a single selection.
+ * Depending on the position of the cursor, we're in move or in resize area.
+ * If the widget wasn't selected (both when there are no widgets selected, or
+ * when there're other widgets selected but not the one receiving the press
+ * event) it's selected and the others deselected, if any. If already selected,
+ * it's marked to be deselected when releasing the button (provided it wasn't
+ * moved or resized).
+ *
+ * @param event The QGraphicsSceneMouseEvent event.
+ */
+void UMLWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->button() != Qt::LeftButton) {
+ event->ignore();
+ return;
+ }
+ event->accept();
+ DEBUG(DBG_SRC) << "widget = " << name() << " / type = " << baseTypeStr();
+
+ toForeground();
+
+ m_startMovePostion = pos();
+ m_startResizeSize = QSizeF(width(), height());
+
+ // saving the values of the widget
+ m_pressOffset = event->scenePos() - pos();
+ DEBUG(DBG_SRC) << "press offset=" << m_pressOffset;
+
+ m_oldStatusBarMsg = UMLApp::app()->statusBarMsg();
+
+ if (event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) {
+ m_shiftPressed = true;
+
+ if (event->button() == Qt::LeftButton) {
+ m_inMoveArea = true;
+ }
+
+ if (!isSelected()) {
+ selectMultiple(event);
+ }
+ return;
+ }
+
+ m_shiftPressed = false;
+
+ int count = m_scene->selectedCount(true);
+ if (event->button() == Qt::LeftButton) {
+ if (isSelected() && count > 1) {
+ // single selection is made in release event if the widget wasn't moved
+ m_inMoveArea = true;
+ m_oldPos = pos();
+ return;
+ }
+
+ if (isInResizeArea(event)) {
+ m_inResizeArea = true;
+ m_oldW = width();
+ m_oldH = height();
+ } else {
+ m_inMoveArea = true;
+ }
+ }
+
+ // if widget wasn't selected, or it was selected but with other widgets also selected
+ if (!isSelected() || count > 1) {
+ selectSingle(event);
+ }
+}
+
+/**
+ * Handles a mouse move event.
+ * It resizes or moves the widget, depending on where the cursor is pressed
+ * on the widget. Go on reading for more info about this.
+ *
+ * If resizing, the widget is resized using UMLWidget::resizeWidget (where specific
+ * widget resize constraint can be applied), and then the associations are
+ * adjusted.
+ * The resizing can be constrained also to a specific axis using control
+ * and shift buttons. If on or another is pressed, it's constrained to X axis.
+ * If both are pressed, it's constrained to Y axis.
+ *
+ * If not resizing, the widget is being moved. If the move is being started,
+ * the selection bounds are set (which includes updating the list of selected
+ * widgets).
+ * The difference between the previous position of the selection and the new
+ * one is got (taking in account the selection bounds so widgets don't go
+ * beyond the scene limits). Then, it's constrained to X or Y axis depending
+ * on shift and control buttons.
+ * A further constraint is made using constrainMovementForAllWidgets (for example,
+ * if the widget that receives the event can only be moved in Y axis, with this
+ * method the movement of all the widgets in the selection can be constrained to
+ * be moved only in Y axis).
+ * Then, all the selected widgets are moved using moveWidgetBy (where specific
+ * widget movement constraint can be applied) and, if a certain amount of time
+ * passed from the last move event, the associations are also updated (they're
+ * not updated always to be easy on the CPU). Finally, the scene is resized,
+ * and selection bounds updated.
+ *
+ * @param event The QGraphicsSceneMouseEvent event.
+ */
+void UMLWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
+{
+ if (m_inResizeArea) {
+ resize(event);
+ return;
+ }
+
+ if (!m_moved) {
+ UMLApp::app()->document()->writeToStatusBar(i18n("Hold shift or ctrl to move in X axis. Hold shift and control to move in Y axis. Right button click to cancel move."));
+
+ m_moved = true;
+ //Maybe needed by AssociationWidget
+ m_startMove = true;
+
+ setSelectionBounds();
+ }
+
+ QPointF position = event->scenePos() - m_pressOffset;
+ qreal diffX = position.x() - x();
+ qreal diffY = position.y() - y();
+
+ if ((event->modifiers() & Qt::ShiftModifier) && (event->modifiers() & Qt::ControlModifier)) {
+ // move only in Y axis
+ diffX = 0;
+ } else if ((event->modifiers() & Qt::ShiftModifier) || (event->modifiers() & Qt::ControlModifier)) {
+ // move only in X axis
+ diffY = 0;
+ }
+
+ constrainMovementForAllWidgets(diffX, diffY);
+
+ // nothing to move
+ if (diffX == 0 && diffY == 0) {
+ return;
+ }
+
+ QPointF delta = event->scenePos() - event->lastScenePos();
+ adjustUnselectedAssocs(delta.x(), delta.y());
+
+ DEBUG(DBG_SRC) << "diffX=" << diffX << " / diffY=" << diffY;
+ foreach(UMLWidget* widget, umlScene()->selectedWidgets()) {
+ widget->moveWidgetBy(diffX, diffY);
+ widget->slotSnapToGrid();
+ }
+
+ // Move any selected associations.
+ foreach(AssociationWidget* aw, m_scene->selectedAssocs()) {
+ if (aw->isSelected()) {
+ aw->moveEntireAssoc(diffX, diffY);
+ }
+ }
+
+ umlScene()->resizeSceneToItems();
+}
+
+/**
+ * Handles a mouse release event.
+ * It selects or deselects the widget and cancels or confirms the move or
+ * resize. Go on reading for more info about this.
+ * No matter which tool is selected, Z position of widget is updated.
+ *
+ * Middle button release resets the selection.
+ * Left button release, if it wasn't moved nor resized, selects the widget
+ * and deselect the others if it wasn't selected and there were other widgets
+ * selected. If the widget was marked to be deselected, deselects it.
+ * If it was moved or resized, the document is set to modified if position
+ * or size changed. Also, if moved, all the associations are adjusted because
+ * the timer could have prevented the adjustment in the last move event before
+ * the release.
+ * If mouse was pressed in resize area, cursor is set again to normal cursor
+ * Right button release if right button was pressed shows the pop up menu for
+ * the widget.
+ * If left button was pressed, it cancels the move or resize with a mouse move
+ * event at the same position than the cursor was when pressed. Another left
+ * button release is also sent.
+ *
+ * @param event The QGraphicsSceneMouseEvent event.
+ */
+void UMLWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (!m_moved && !m_resized) {
+ if (!m_shiftPressed && (m_scene->selectedCount(true) > 1)) {
+ selectSingle(event);
+ } else if (!isSelected()) {
+ deselect(event);
+ }
+ } else {
+ // Commands
+ if (m_moved) {
+ int selectionCount = umlScene()->selectedWidgets().count();
+ if (selectionCount > 1) {
+ UMLApp::app()->beginMacro(i18n("Move widgets"));
+ }
+ foreach(UMLWidget* widget, umlScene()->selectedWidgets()) {
+ UMLApp::app()->executeCommand(new Uml::CmdMoveWidget(widget));
+ }
+ if (selectionCount > 1) {
+ UMLApp::app()->endMacro();
+ }
+ m_moved = false;
+ } else {
+ UMLApp::app()->executeCommand(new Uml::CmdResizeWidget(this));
+ m_resized = false;
+ }
+
+ if ((m_inMoveArea && wasPositionChanged()) ||
+ (m_inResizeArea && wasSizeChanged())) {
+ umlDoc()->setModified(true);
+ }
+
+ UMLApp::app()->document()->writeToStatusBar(m_oldStatusBarMsg);
+ }
+
+ if (m_inResizeArea) {
+ m_inResizeArea = false;
+ m_scene->activeView()->setCursor(Qt::ArrowCursor);
+ } else {
+ m_inMoveArea = false;
+ }
+}
+
+/**
+ * Event handler for mouse double click events.
+ * @param event the QGraphicsSceneMouseEvent event.
+ */
+void UMLWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ DEBUG(DBG_SRC) << "widget = " << name() << " / type = " << baseTypeStr();
+ switch(baseType()) {
+ case WidgetBase::wt_Message: // will be handled in its class
+ QGraphicsItem::mouseDoubleClickEvent(event);
+ break;
+ default:
+ showPropertiesDialog();
+ event->accept();
+ break;
+ }
+ }
+}
+
+/**
+ * Return the start position of the move action.
+ * @return point where the move began
+ */
+QPointF UMLWidget::startMovePosition() const
+{
+ return m_startMovePostion;
+}
+
+/**
+ * Set the start position of the move action.
+ * @param position point where the move began
+ */
+void UMLWidget::setStartMovePosition(const QPointF &position)
+{
+ m_startMovePostion = position;
+}
+
+/**
+ * Return the start size of the resize action.
+ * @return size where the resize began
+ */
+QSizeF UMLWidget::startResizeSize() const
+{
+ return m_startResizeSize;
+}
+
+/**
+ * Resizes the widget.
+ * It's called from resize, after the values are constrained and before
+ * the associations are adjusted.
+ *
+ * Default behaviour is resize the widget using the new size values.
+ * @see resize
+ *
+ * @param newW The new width for the widget.
+ * @param newH The new height for the widget.
+ */
+void UMLWidget::resizeWidget(qreal newW, qreal newH)
+{
+ setSize(newW, newH);
+}
+
+/**
+ * When a widget changes this slot captures that signal.
+ */
+void UMLWidget::updateWidget()
+{
+ updateGeometry();
+ switch (m_baseType) {
+ case WidgetBase::wt_Class:
+ m_scene->createAutoAttributeAssociations(this);
+ break;
+ case WidgetBase::wt_Entity:
+ m_scene->createAutoConstraintAssociations(this);
+ break;
+ default:
+ break;
+ }
+
+ if (isVisible())
+ update();
+}
+
+/**
+ * Apply possible constraints to the given candidate width and height.
+ * The default implementation limits input values to the bounds returned
+ * by minimumSize()/maximumSize().
+ *
+ * @param width input value, may be modified by the constraint
+ * @param height input value, may be modified by the constraint
+ */
+void UMLWidget::constrain(qreal& width, qreal& height)
+{
+ QSizeF minSize = minimumSize();
+ if (width < minSize.width())
+ width = minSize.width();
+ if (height < minSize.height())
+ height = minSize.height();
+ QSizeF maxSize = maximumSize();
+ if (width > maxSize.width())
+ width = maxSize.width();
+ if (height > maxSize.height())
+ height = maxSize.height();
+
+ if (fixedAspectRatio()) {
+ QSizeF size = rect().size();
+ float aspectRatio = size.width() > 0 ? (float)size.height()/size.width() : 1;
+ height = width * aspectRatio;
+ }
+}
+
+/**
+ * Initializes key attributes of the class.
+ */
+void UMLWidget::init()
+{
+ m_nId = Uml::ID::None;
+ m_nLocalID = UniqueID::gen();
+ m_isInstance = false;
+ setMinimumSize(DefaultMinimumSize);
+ setMaximumSize(DefaultMaximumSize);
+
+ m_font = QApplication::font();
+ for (int i = (int)FT_INVALID - 1; i >= 0; --i) {
+ FontType fontType = (FontType)i;
+ setupFontType(m_font, fontType);
+ m_pFontMetrics[fontType] = new QFontMetrics(m_font);
+ }
+
+ if (m_scene) {
+ m_useFillColor = true;
+ m_usesDiagramFillColor = true;
+ m_usesDiagramUseFillColor = true;
+ const Settings::OptionState& optionState = m_scene->optionState();
+ m_fillColor = optionState.uiState.fillColor;
+ m_showStereotype = optionState.classState.showStereoType;
+ } else {
+ uError() << "SERIOUS PROBLEM - m_scene is NULL";
+ m_useFillColor = false;
+ m_usesDiagramFillColor = false;
+ m_usesDiagramUseFillColor = false;
+ m_showStereotype = false;
+ }
+
+ m_resizable = true;
+ m_fixedAspectRatio = false;
+
+ m_startMove = false;
+ m_activated = false;
+ m_ignoreSnapToGrid = false;
+ m_ignoreSnapComponentSizeToGrid = false;
+ m_doc = UMLApp::app()->document();
+ m_nPosX = 0;
+ connect(m_scene, SIGNAL(sigFillColorChanged(Uml::ID::Type)), this, SLOT(slotFillColorChanged(Uml::ID::Type)));
+ connect(m_scene, SIGNAL(sigLineColorChanged(Uml::ID::Type)), this, SLOT(slotLineColorChanged(Uml::ID::Type)));
+ connect(m_scene, SIGNAL(sigTextColorChanged(Uml::ID::Type)), this, SLOT(slotTextColorChanged(Uml::ID::Type)));
+ connect(m_scene, SIGNAL(sigLineWidthChanged(Uml::ID::Type)), this, SLOT(slotLineWidthChanged(Uml::ID::Type)));
+
+ m_umlObject = 0;
+
+ m_oldPos = QPointF();
+ m_pressOffset = QPointF();
+ m_oldW = 0;
+ m_oldH = 0;
+
+ m_shiftPressed = false;
+ m_inMoveArea = false;
+ m_inResizeArea = false;
+ m_moved = false;
+ m_resized = false;
+
+ setZValue(2.0); // default for most widgets
+}
+
+/**
+ * This is usually called synchronously after menu.exec() and \a
+ * trigger's parent is always the ListPopupMenu which can be used to
+ * get the type of action of \a trigger.
+ *
+ * @note Subclasses can reimplement to handle specific actions and
+ * leave the rest to WidgetBase::slotMenuSelection.
+ */
+void UMLWidget::slotMenuSelection(QAction *trigger)
+{
+ if (!trigger) {
+ return;
+ }
+
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(trigger);
+ switch (sel) {
+ case ListPopupMenu::mt_Resize:
+ umlScene()->resizeSelection();
+ break;
+
+ default:
+ WidgetBase::slotMenuSelection(trigger);
+ break;
+ }
+}
+
+/**
+ * Captures when another widget moves if this widget is linked to it.
+ * @see sigWidgetMoved
+ *
+ * @param id The id of object behind the widget.
+ */
+void UMLWidget::slotWidgetMoved(Uml::ID::Type /*id*/)
+{
+}
+
+/**
+ * Captures a color change signal.
+ *
+ * @param viewID The id of the UMLScene behind the widget.
+ */
+void UMLWidget::slotFillColorChanged(Uml::ID::Type viewID)
+{
+ //only change if on the diagram concerned
+ if (m_scene->ID() != viewID) {
+ return;
+ }
+ if (m_usesDiagramFillColor) {
+ WidgetBase::setFillColor(m_scene->fillColor());
+ }
+ if (m_usesDiagramUseFillColor) {
+ WidgetBase::setUseFillColor(m_scene->useFillColor());
+ }
+ update();
+}
+
+/**
+ * Captures a text color change signal.
+ *
+ * @param viewID The id of the UMLScene behind the widget.
+ */
+void UMLWidget::slotTextColorChanged(Uml::ID::Type viewID)
+{
+ //only change if on the diagram concerned
+ if (m_scene->ID() != viewID)
+ return;
+ WidgetBase::setTextColor(m_scene->textColor());
+ update();
+}
+
+
+/**
+ * Captures a line color change signal.
+ *
+ * @param viewID The id of the UMLScene behind the widget.
+ */
+void UMLWidget::slotLineColorChanged(Uml::ID::Type viewID)
+{
+ //only change if on the diagram concerned
+ if (m_scene->ID() != viewID)
+ return;
+
+ if (m_usesDiagramLineColor) {
+ WidgetBase::setLineColor(m_scene->lineColor());
+ }
+ update();
+}
+
+/**
+ * Captures a linewidth change signal.
+ *
+ * @param viewID The id of the UMLScene behind the widget.
+ */
+void UMLWidget::slotLineWidthChanged(Uml::ID::Type viewID)
+{
+ //only change if on the diagram concerned
+ if (m_scene->ID() != viewID) {
+ return;
+ }
+ if (m_usesDiagramLineWidth) {
+ WidgetBase::setLineWidth(m_scene->lineWidth());
+ }
+ update();
+}
+
+/**
+ * Set the status of using fill color (undo action)
+ *
+ * @param fc the status of using fill color.
+ */
+void UMLWidget::setUseFillColor(bool fc)
+{
+ if (useFillColor() != fc) {
+ UMLApp::app()->executeCommand(new CmdChangeUseFillColor(this, fc));
+ }
+}
+
+/**
+ * Set the status of using fill color.
+ *
+ * @param fc the status of using fill color.
+ */
+void UMLWidget::setUseFillColorCmd(bool fc)
+{
+ WidgetBase::setUseFillColor(fc);
+ update();
+}
+
+/**
+ * Overrides the method from WidgetBase.
+ */
+void UMLWidget::setTextColorCmd(const QColor &color)
+{
+ WidgetBase::setTextColor(color);
+ update();
+}
+
+/**
+ * Overrides the method from WidgetBase.
+ */
+void UMLWidget::setTextColor(const QColor &color)
+{
+ if (textColor() != color) {
+ UMLApp::app()->executeCommand(new CmdChangeTextColor(this, color));
+ update();
+ }
+}
+
+/**
+ * Overrides the method from WidgetBase.
+ */
+void UMLWidget::setLineColorCmd(const QColor &color)
+{
+ WidgetBase::setLineColor(color);
+ update();
+}
+
+/**
+ * Overrides the method from WidgetBase.
+ */
+void UMLWidget::setLineColor(const QColor &color)
+{
+ if (lineColor() != color) {
+ UMLApp::app()->executeCommand(new CmdChangeLineColor(this, color));
+ }
+}
+
+/**
+ * Overrides the method from WidgetBase, execute CmdChangeLineWidth
+ */
+void UMLWidget::setLineWidth(uint width)
+{
+ if (lineWidth() != width) {
+ UMLApp::app()->executeCommand(new CmdChangeLineWidth(this, width));
+ }
+}
+
+/**
+ * Overrides the method from WidgetBase.
+ */
+void UMLWidget::setLineWidthCmd(uint width)
+{
+ WidgetBase::setLineWidth(width);
+ update();
+}
+
+/**
+ * Sets the background fill color
+ *
+ * @param color the new fill color
+ */
+void UMLWidget::setFillColor(const QColor &color)
+{
+ if (fillColor() != color) {
+ UMLApp::app()->executeCommand(new CmdChangeFillColor(this, color));
+ }
+}
+
+/**
+ * Sets the background fill color
+ *
+ * @param color the new fill color
+ */
+void UMLWidget::setFillColorCmd(const QColor &color)
+{
+ WidgetBase::setFillColor(color);
+ update();
+}
+
+/**
+ * Activate the object after serializing it from a QDataStream
+ *
+ * @param ChangeLog
+ * @return true for success
+ */
+bool UMLWidget::activate(IDChangeLog* /*ChangeLog = 0 */)
+{
+ if (widgetHasUMLObject(m_baseType) && m_umlObject == NULL) {
+ m_umlObject = m_doc->findObjectById(m_nId);
+ if (m_umlObject == NULL) {
+ uError() << "cannot find UMLObject with id=" << Uml::ID::toString(m_nId);
+ return false;
+ }
+ }
+ setFontCmd(m_font);
+ setSize(width(), height());
+ m_activated = true;
+ updateGeometry();
+ if (m_scene->getPaste()) {
+ FloatingTextWidget * ft = 0;
+ QPointF point = m_scene->getPastep-kf6oint();
+ int x = point.x() + this->x();
+ int y = point.y() + this->y();
+ if (m_scene->type() == Uml::DiagramType::Sequence) {
+ switch (baseType()) {
+ case WidgetBase::wt_Object:
+ case WidgetBase::wt_Precondition :
+ setY(this->y());
+ setX(x);
+ break;
+
+ case WidgetBase::wt_Message:
+ setY(this->y());
+ setX(x);
+ break;
+
+ case WidgetBase::wt_Text:
+ ft = static_cast<FloatingTextWidget *>(this);
+ if (ft->textRole() == Uml::TextRole::Seq_Message) {
+ setX(x);
+ setY(this->y());
+ } else {
+ setX(this->x());
+ setY(this->y());
+ }
+ break;
+
+ default:
+ setY(y);
+ break;
+ }//end switch base type
+ }//end if sequence
+ else {
+ setX(x);
+ setY(y);
+ }
+ }//end if pastep-kf6oint
+ else {
+ setX(this->x());
+ setY(this->y());
+ }
+ if (m_scene->getPaste())
+ m_scene->createAutoAssociations(this);
+ updateGeometry();
+ return true;
+}
+
+/**
+ * Returns true if the Activate method has been called for this instance
+ *
+ * @return The activate status.
+ */
+bool UMLWidget::isActivated() const
+{
+ return m_activated;
+}
+
+/**
+ * Set the m_activated flag of a widget but does not perform the Activate method
+ *
+ * @param active Status of activation is to be set.
+ */
+void UMLWidget::setActivated(bool active /*=true*/)
+{
+ m_activated = active;
+}
+
+/**
+ * Adds an already created association to the list of
+ * associations that include this UMLWidget
+ */
+void UMLWidget::addAssoc(AssociationWidget* pAssoc)
+{
+ if (pAssoc && !m_Assocs.contains(pAssoc)) {
+ m_Assocs.append(pAssoc);
+ }
+}
+
+/**
+ * Removes an already created association from the list of
+ * associations that include this UMLWidget
+ */
+void UMLWidget::removeAssoc(AssociationWidget* pAssoc)
+{
+ if (pAssoc) {
+ m_Assocs.removeAll(pAssoc);
+ }
+}
+
+/**
+ * Adjusts associations with the given co-ordinates
+ *
+ * @param dx The amount by which the widget moved in X direction.
+ * @param dy The amount by which the widget moved in Y direction.
+ */
+void UMLWidget::adjustAssocs(qreal dx, qreal dy)
+{
+ // don't adjust Assocs on file load, as
+ // the original positions, which are stored in XMI
+ // should be reproduced exactly
+ // (don't try to reposition assocs as long
+ // as file is only partly loaded -> reposition
+ // could be misguided)
+ /// @todo avoid trigger of this event during load
+ if (m_doc->loading()) {
+ // don't recalculate the assocs during load of XMI
+ // -> return immediately without action
+ return;
+ }
+
+ foreach(AssociationWidget* assocwidget, m_Assocs) {
+ assocwidget->saveIdealTextPositions();
+ }
+
+ foreach(AssociationWidget* assocwidget, m_Assocs) {
+ assocwidget->widgetMoved(this, dx, dy);
+ }
+}
+
+/**
+ * Adjusts all unselected associations with the given co-ordinates
+ *
+ * @param dx The amount by which the widget moved in X direction.
+ * @param dy The amount by which the widget moved in Y direction.
+ */
+void UMLWidget::adjustUnselectedAssocs(qreal dx, qreal dy)
+{
+ foreach(AssociationWidget* assocwidget, m_Assocs) {
+ if (!assocwidget->isSelected())
+ assocwidget->saveIdealTextPositions();
+ }
+
+ foreach(AssociationWidget* assocwidget, m_Assocs) {
+ if (!assocwidget->isSelected()) {
+ assocwidget->widgetMoved(this, dx, dy);
+ }
+ }
+}
+
+/**
+ * Show a properties dialog for a UMLWidget.
+ */
+void UMLWidget::showPropertiesDialog()
+{
+ // will already be selected so make sure docWindow updates the doc
+ // back it the widget
+ UMLApp::app()->docWindow()->updateDocumentation(false);
+ QPointer<ClassPropertiesDialog> dlg = new ClassPropertiesDialog((QWidget*)UMLApp::app(), this);
+
+ if (dlg->exec()) {
+ UMLApp::app()->docWindow()->showDocumentation(umlObject(), true);
+ m_doc->setModified(true);
+ }
+ dlg->close(); //wipe from memory
+ delete dlg;
+}
+
+/**
+ * Move the widget by an X and Y offset relative to
+ * the current position.
+ */
+void UMLWidget::moveByLocal(qreal dx, qreal dy)
+{
+ qreal newX = x() + dx;
+ qreal newY = y() + dy;
+ setX(newX);
+ setY(newY);
+ adjustAssocs(dx, dy);
+}
+
+/**
+ * Set the pen.
+ */
+void UMLWidget::setPenFromSettings(QPainter & p)
+{
+ p.setPen(QPen(m_lineColor, m_lineWidth));
+}
+
+/**
+ * Set the pen.
+ */
+void UMLWidget::setPenFromSettings(QPainter *p)
+{
+ p->setPen(QPen(m_lineColor, m_lineWidth));
+}
+
+/**
+ * Returns the cursor to be shown when resizing the widget.
+ * Default cursor is KCursor::sizeFDiagCursor().
+ *
+ * @return The cursor to be shown when resizing the widget.
+ */
+QCursor UMLWidget::resizeCursor() const
+{
+ return Qt::SizeFDiagCursor;
+}
+
+/**
+ * Checks if the mouse is in resize area (right bottom corner), and sets
+ * the cursor depending on that.
+ * The cursor used when resizing is gotten from resizeCursor().
+ *
+ * @param me The QMouseEVent to check.
+ * @return true if the mouse is in resize area, false otherwise.
+ */
+bool UMLWidget::isInResizeArea(QGraphicsSceneMouseEvent *me)
+{
+ qreal m = 10.0;
+ const qreal w = width();
+ const qreal h = height();
+
+ // If the widget itself is very small then make the resize area small, too.
+ // Reason: Else it becomes impossible to do a move instead of resize.
+ if (w - m < m || h - m < m) {
+ m = 2.0;
+ }
+
+ if (m_resizable &&
+ me->scenePos().x() >= (x() + w - m) &&
+ me->scenePos().y() >= (y() + h - m)) {
+ m_scene->activeView()->setCursor(resizeCursor());
+ return true;
+ } else {
+ m_scene->activeView()->setCursor(Qt::ArrowCursor);
+ return false;
+ }
+}
+
+/**
+ * calculate content related size of widget.
+ *
+ * @return calculated widget size
+ */
+QSizeF UMLWidget::calculateSize(bool withExtensions /* = true */) const
+{
+ Q_UNUSED(withExtensions)
+ return QSizeF(width(), height());
+}
+
+/**
+ * Resize widget to minimum size.
+ */
+void UMLWidget::resize()
+{
+ qreal oldW = width();
+ qreal oldH = height();
+ // @TODO minimumSize() do not work in all cases, we need a dedicated autoResize() method
+ QSizeF size = minimumSize();
+ setSize(size.width(), size.height());
+ DEBUG(DBG_SRC) << "size=" << size;
+ adjustAssocs(size.width()-oldW, size.height()-oldH);
+}
+
+/**
+ * Resizes the widget and adjusts the associations.
+ * It's called when a mouse move event happens and the cursor was
+ * in resize area when pressed.
+ * Resizing can be constrained to an specific axis using control and shift buttons.
+ *
+ * @param me The QGraphicsSceneMouseEvent to get the values from.
+ */
+void UMLWidget::resize(QGraphicsSceneMouseEvent *me)
+{
+ // TODO the status message lies for at least MessageWidget which could only be resized vertical
+ UMLApp::app()->document()->writeToStatusBar(i18n("Hold shift or ctrl to move in X axis. Hold shift and control to move in Y axis. Right button click to cancel resize."));
+
+ m_resized = true;
+
+ qreal newW = m_oldW + me->scenePos().x() - x() - m_pressOffset.x();
+ qreal newH = m_oldH + me->scenePos().y() - y() - m_pressOffset.y();
+
+ if ((me->modifiers() & Qt::ShiftModifier) && (me->modifiers() & Qt::ControlModifier)) {
+ //Move in Y axis
+ newW = m_oldW;
+ } else if ((me->modifiers() & Qt::ShiftModifier) || (me->modifiers() & Qt::ControlModifier)) {
+ //Move in X axis
+ newH = m_oldH;
+ }
+
+ constrain(newW, newH);
+ resizeWidget(newW, newH);
+ DEBUG(DBG_SRC) << "event=" << me->scenePos() << "/ pos=" << pos() << " / newW=" << newW << " / newH=" << newH;
+ QPointF delta = me->scenePos() - me->lastScenePos();
+ adjustAssocs(delta.x(), delta.y());
+
+ m_scene->resizeSceneToItems();
+}
+
+/**
+ * Checks if the size of the widget changed respect to the size that
+ * it had when press event was fired.
+ *
+ * @return true if was resized, false otherwise.
+ */
+bool UMLWidget::wasSizeChanged()
+{
+ return m_oldW != width() || m_oldH != height();
+}
+
+/**
+ * Checks if the position of the widget changed respect to the position that
+ * it had when press event was fired.
+ *
+ * @return true if was moved, false otherwise.
+ */
+bool UMLWidget::wasPositionChanged()
+{
+ return m_oldPos != pos();
+}
+
+/**
+ * Fills m_selectedWidgetsList and sets the selection bounds ((m_min/m_max)X/Y attributes).
+ */
+void UMLWidget::setSelectionBounds()
+{
+}
+
+void UMLWidget::setSelectedFlag(bool _select)
+{
+ WidgetBase::setSelected(_select);
+}
+
+/**
+ * Sets the state of whether the widget is selected.
+ *
+ * @param _select The state of whether the widget is selected.
+ */
+void UMLWidget::setSelected(bool _select)
+{
+ WidgetBase::setSelected(_select);
+ const WidgetBase::WidgetType wt = m_baseType;
+ if (_select) {
+ if (m_scene->selectedCount() == 0) {
+ if (widgetHasUMLObject(wt)) {
+ UMLApp::app()->docWindow()->showDocumentation(m_umlObject, false);
+ } else {
+ UMLApp::app()->docWindow()->showDocumentation(this, false);
+ }
+ }//end if
+ /* if (wt != wt_Text && wt != wt_Box) {
+ setZ(9);//keep text on top and boxes behind so don't touch Z value
+ } */
+ } else {
+ /* if (wt != wt_Text && wt != wt_Box) {
+ setZ(m_origZ);
+ } */
+ if (isSelected())
+ UMLApp::app()->docWindow()->updateDocumentation(true);
+ }
+
+ // TODO: isn't this handled by toForeground() ?
+ const QPoint pos(x(), y());
+ UMLWidget *bkgnd = m_scene->widgetAt(pos);
+ if (bkgnd && bkgnd != this && _select) {
+ DEBUG(DBG_SRC) << "setting Z to " << bkgnd->zValue() + 1.0 << ", SelectState: " << _select;
+ setZValue(bkgnd->zValue() + 1.0);
+ }
+
+ update();
+
+ // selection changed, we have to make sure the copy and paste items
+ // are correctly enabled/disabled
+ UMLApp::app()->slotCopyChanged();
+
+ // select in tree view as done for diagrams
+ if (_select) {
+ UMLListViewItem * item = UMLApp::app()->listView()->findItem(id());
+ if (item)
+ UMLApp::app()->listView()->setCurrentItem(item);
+ else
+ UMLApp::app()->listView()->clearSelection();
+ }
+}
+
+/**
+ * Selects the widget and clears the other selected widgets, if any.
+ *
+ * @param me The QGraphicsSceneMouseEvent which made the selection.
+ */
+void UMLWidget::selectSingle(QGraphicsSceneMouseEvent *me)
+{
+ m_scene->clearSelected();
+
+ // Adds the widget to the selected widgets list, but as it has been cleared
+ // only the current widget is selected.
+ selectMultiple(me);
+}
+
+/**
+ * Selects the widget and adds it to the list of selected widgets.
+ *
+ * @param me The QGraphicsSceneMouseEvent which made the selection.
+ */
+void UMLWidget::selectMultiple(QGraphicsSceneMouseEvent *me)
+{
+ Q_UNUSED(me);
+
+ setSelected(true);
+}
+
+/**
+ * Deselects the widget and removes it from the list of selected widgets.
+ *
+ * @param me The QGraphicsSceneMouseEvent which made the selection.
+ */
+void UMLWidget::deselect(QGraphicsSceneMouseEvent *me)
+{
+ Q_UNUSED(me);
+
+ setSelected(false);
+}
+
+/**
+ * Clears the selection, resets the toolbar and deselects the widget.
+ */
+//void UMLWidget::resetSelection()
+//{
+// m_scene->clearSelected();
+// m_scene->resetToolbar();
+// setSelected(false);
+//}
+
+/**
+ * Sets the view the widget is on.
+ *
+ * @param scene The UMLScene the widget is on.
+ */
+void UMLWidget::setScene(UMLScene *scene)
+{
+ //remove signals from old view - was probably 0 anyway
+ disconnect(m_scene, SIGNAL(sigFillColorChanged(Uml::ID::Type)), this, SLOT(slotFillColorChanged(Uml::ID::Type)));
+ disconnect(m_scene, SIGNAL(sigTextColorChanged(Uml::ID::Type)), this, SLOT(slotTextColorChanged(Uml::ID::Type)));
+ disconnect(m_scene, SIGNAL(sigLineWidthChanged(Uml::ID::Type)), this, SLOT(slotLineWidthChanged(Uml::ID::Type)));
+ m_scene = scene;
+ connect(m_scene, SIGNAL(sigFillColorChanged(Uml::ID::Type)), this, SLOT(slotFillColorChanged(Uml::ID::Type)));
+ connect(m_scene, SIGNAL(sigTextColorChanged(Uml::ID::Type)), this, SLOT(slotTextColorChanged(Uml::ID::Type)));
+ connect(m_scene, SIGNAL(sigLineWidthChanged(Uml::ID::Type)), this, SLOT(slotLineWidthChanged(Uml::ID::Type)));
+}
+
+/**
+ * Sets the x-coordinate.
+ * Currently, the only class that reimplements this method is
+ * ObjectWidget.
+ *
+ * @param x The x-coordinate to be set.
+ */
+void UMLWidget::setX(qreal x)
+{
+ QGraphicsObject::setX(x);
+}
+
+/**
+ * Sets the y-coordinate.
+ * Currently, the only class that reimplements this method is
+ * ObjectWidget.
+ *
+ * @param y The y-coordinate to be set.
+ */
+void UMLWidget::setY(qreal y)
+{
+ QGraphicsObject::setY(y);
+}
+
+/**
+ * Used to cleanup any other widget it may need to delete.
+ * Used by child classes. This should be called before deleting a widget of a diagram.
+ */
+void UMLWidget::cleanup()
+{
+}
+
+/**
+ * Tells the widget to snap to grid.
+ * Will use the grid settings of the @ref UMLView it belongs to.
+ */
+void UMLWidget::slotSnapToGrid()
+{
+ if (!m_ignoreSnapToGrid) {
+ qreal newX = m_scene->snappedX(x());
+ setX(newX);
+ qreal newY = m_scene->snappedY(y());
+ setY(newY);
+ }
+}
+
+/**
+ * Returns whether the widget type has an associated UMLObject
+ */
+bool UMLWidget::widgetHasUMLObject(WidgetBase::WidgetType type)
+{
+ if (type == WidgetBase::wt_Actor ||
+ type == WidgetBase::wt_UseCase ||
+ type == WidgetBase::wt_Class ||
+ type == WidgetBase::wt_Interface ||
+ type == WidgetBase::wt_Enum ||
+ type == WidgetBase::wt_Datatype ||
+ type == WidgetBase::wt_Package ||
+ type == WidgetBase::wt_Component ||
+ type == WidgetBase::wt_Port ||
+ type == WidgetBase::wt_Node ||
+ type == WidgetBase::wt_Artifact ||
+ type == WidgetBase::wt_Object) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * Set m_ignoreSnapToGrid.
+ */
+void UMLWidget::setIgnoreSnapToGrid(bool to)
+{
+ m_ignoreSnapToGrid = to;
+}
+
+/**
+ * Return the value of m_ignoreSnapToGrid.
+ */
+bool UMLWidget::getIgnoreSnapToGrid() const
+{
+ return m_ignoreSnapToGrid;
+}
+
+/**
+ * Sets the size.
+ * If m_scene->snapComponentSizeToGrid() is true, then
+ * set the next larger size that snaps to the grid.
+ */
+void UMLWidget::setSize(qreal width, qreal height)
+{
+ // snap to the next larger size that is a multiple of the grid
+ if (!m_ignoreSnapComponentSizeToGrid
+ && m_scene->snapComponentSizeToGrid()) {
+ // integer divisions
+ int numX = width / m_scene->snapX();
+ int numY = height / m_scene->snapY();
+ // snap to the next larger valid value
+ if (width > numX * m_scene->snapX())
+ width = (numX + 1) * m_scene->snapX();
+ if (height > numY * m_scene->snapY())
+ height = (numY + 1) * m_scene->snapY();
+ }
+
+ setRect(rect().x(), rect().y(), width, height);
+}
+
+/**
+ * Sets the size with another size.
+ */
+void UMLWidget::setSize(const QSizeF& size)
+{
+ setSize(size.width(), size.height());
+}
+
+/**
+ * Update the size of this widget.
+ */
+void UMLWidget::updateGeometry()
+{
+ if (m_doc->loading()) {
+ return;
+ }
+ qreal oldW = width();
+ qreal oldH = height();
+ QSizeF size = calculateSize();
+ qreal clipWidth = size.width();
+ qreal clipHeight = size.height();
+ constrain(clipWidth, clipHeight);
+ setSize(clipWidth, clipHeight);
+ slotSnapToGrid();
+ adjustAssocs(size.width()-oldW, size.height()-oldH);
+}
+
+/**
+ * clip the size of this widget against the
+ * minimal and maximal limits.
+ */
+void UMLWidget::clipSize()
+{
+ qreal clipWidth = width();
+ qreal clipHeight = height();
+ constrain(clipWidth, clipHeight);
+ setSize(clipWidth, clipHeight);
+}
+
+/**
+ * Template Method, override this to set the default font metric.
+ */
+void UMLWidget::setDefaultFontMetrics(QFont &font, UMLWidget::FontType fontType)
+{
+ setupFontType(font, fontType);
+ setFontMetrics(fontType, QFontMetrics(font));
+}
+
+void UMLWidget::setupFontType(QFont &font, UMLWidget::FontType fontType)
+{
+ switch (fontType) {
+ case FT_NORMAL:
+ font.setBold(false);
+ font.setItalic(false);
+ font.setUnderline(false);
+ break;
+ case FT_BOLD:
+ font.setBold(true);
+ font.setItalic(false);
+ font.setUnderline(false);
+ break;
+ case FT_ITALIC:
+ font.setBold(false);
+ font.setItalic(true);
+ font.setUnderline(false);
+ break;
+ case FT_UNDERLINE:
+ font.setBold(false);
+ font.setItalic(false);
+ font.setUnderline(true);
+ break;
+ case FT_BOLD_ITALIC:
+ font.setBold(true);
+ font.setItalic(true);
+ font.setUnderline(false);
+ break;
+ case FT_BOLD_UNDERLINE:
+ font.setBold(true);
+ font.setItalic(false);
+ font.setUnderline(true);
+ break;
+ case FT_ITALIC_UNDERLINE:
+ font.setBold(false);
+ font.setItalic(true);
+ font.setUnderline(true);
+ break;
+ case FT_BOLD_ITALIC_UNDERLINE:
+ font.setBold(true);
+ font.setItalic(true);
+ font.setUnderline(true);
+ break;
+ default: return;
+ }
+}
+
+void UMLWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ if (option->state & QStyle::State_Selected) {
+ const qreal w = width();
+ const qreal h = height();
+ const qreal s = 4;
+ QBrush brush(Qt::blue);
+ painter->fillRect(0, 0, s, s, brush);
+ painter->fillRect(0, 0 + h - s, s, s, brush);
+ painter->fillRect(0 + w - s, 0, s, s, brush);
+
+ // Draw the resize anchor in the lower right corner.
+ // Don't draw it if the widget is so small that the
+ // resize anchor would cover up most of the widget.
+ if (m_resizable && w >= s+8 && h >= s+8) {
+ brush.setColor(Qt::red);
+ const int right = 0 + w;
+ const int bottom = 0 + h;
+ painter->drawLine(right - s, 0 + h - 1, 0 + w - 1, 0 + h - s);
+ painter->drawLine(right - (s*2), bottom - 1, right - 1, bottom - (s*2));
+ painter->drawLine(right - (s*3), bottom - 1, right - 1, bottom - (s*3));
+ } else {
+ painter->fillRect(0 + w - s, 0 + h - s, s, s, brush);
+ }
+ // debug info
+ if (Tracer::instance()->isEnabled(QLatin1String(metaObject()->className()))) {
+ painter->setPen(Qt::green);
+ painter->setBrush(Qt::NoBrush);
+ painter->drawPath(shape());
+ painter->setPen(Qt::red);
+ painter->drawRect(boundingRect());
+ // origin
+ painter->drawLine(-10, 0, 10, 0);
+ painter->drawLine(0, -10, 0, 10);
+ }
+ }
+
+ if (umlScene()->isShowDocumentationIndicator() && hasDocumentation()) {
+ const qreal h = height();
+ const qreal d = 8;
+ QPolygonF p;
+ p << QPointF(0, h - d) << QPointF(d, h) << QPointF(0, h);
+ painter->setPen(Qt::blue);
+ painter->setBrush(Qt::red);
+ painter->drawPolygon(p);
+ }
+}
+
+/**
+ * Template Method, override this to set the default font metric.
+ */
+void UMLWidget::setDefaultFontMetrics(QFont &font, UMLWidget::FontType fontType, QPainter &painter)
+{
+ setupFontType(font, fontType);
+ painter.setFont(font);
+ setFontMetrics(fontType, painter.fontMetrics());
+}
+
+/**
+ * Returns the font metric used by this object for Text
+ * which uses bold/italic fonts.
+ */
+QFontMetrics &UMLWidget::getFontMetrics(UMLWidget::FontType fontType) const
+{
+ return *m_pFontMetrics[fontType];
+}
+
+/**
+ * Set the font metric to use.
+ */
+void UMLWidget::setFontMetrics(UMLWidget::FontType fontType, QFontMetrics fm)
+{
+ delete m_pFontMetrics[fontType];
+ m_pFontMetrics[fontType] = new QFontMetrics(fm);
+}
+
+/**
+ * Sets the font the widget is to use.
+ *
+ * @param font Font to be set.
+ */
+void UMLWidget::setFont(const QFont &font)
+{
+ QFont newFont = font;
+ forceUpdateFontMetrics(newFont, 0);
+
+ if (m_font != newFont) {
+ UMLApp::app()->executeCommand(new CmdChangeFont(this, font));
+ }
+}
+
+/**
+ * Sets the font the widget is to use.
+ *
+ * @param font Font to be set.
+ */
+void UMLWidget::setFontCmd(const QFont &font)
+{
+ WidgetBase::setFont(font);
+ forceUpdateFontMetrics(0);
+ if (m_doc->loading())
+ return;
+ update();
+}
+
+/**
+ * Updates font metrics for widgets current m_font
+ */
+void UMLWidget::forceUpdateFontMetrics(QPainter *painter)
+{
+ forceUpdateFontMetrics(m_font, painter);
+}
+
+/**
+ * @note For performance Reasons, only FontMetrics for already used
+ * font types are updated. Not yet used font types will not get a font metric
+ * and will get the same font metric as if painter was zero.
+ * This behaviour is acceptable, because diagrams will always be shown on Display
+ * first before a special painter like a printer device is used.
+ */
+void UMLWidget::forceUpdateFontMetrics(QFont& font, QPainter *painter)
+{
+ if (painter == 0) {
+ for (int i = (int)FT_INVALID - 1; i >= 0; --i) {
+ if (m_pFontMetrics[(UMLWidget::FontType)i] != 0)
+ setDefaultFontMetrics(font, (UMLWidget::FontType)i);
+ }
+ } else {
+ for (int i2 = (int)FT_INVALID - 1; i2 >= 0; --i2) {
+ if (m_pFontMetrics[(UMLWidget::FontType)i2] != 0)
+ setDefaultFontMetrics(font, (UMLWidget::FontType)i2, *painter);
+ }
+ }
+ if (m_doc->loading())
+ return;
+ // calculate the size, based on the new font metric
+ updateGeometry();
+}
+
+/**
+ * Set the status of whether to show Stereotype.
+ *
+ * @param flag True if stereotype shall be shown.
+ */
+void UMLWidget::setShowStereotype(bool flag)
+{
+ m_showStereotype = flag;
+ updateGeometry();
+ update();
+}
+
+/**
+ * Returns the status of whether to show Stereotype.
+ *
+ * @return True if stereotype is shown.
+ */
+bool UMLWidget::showStereotype() const
+{
+ return m_showStereotype;
+}
+
+/**
+ * Overrides the standard operation.
+ *
+ * @param me The move event.
+ */
+void UMLWidget::moveEvent(QGraphicsSceneMouseEvent* me)
+{
+ Q_UNUSED(me)
+}
+
+void UMLWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ /*
+ Call after required actions in child class.
+ Type must be set in the child class.
+ */
+ WidgetBase::saveToXMI(qDoc, qElement);
+ qElement.setAttribute(QLatin1String("xmi.id"), Uml::ID::toString(id()));
+ qElement.setAttribute(QLatin1String("x"), x());
+ qElement.setAttribute(QLatin1String("y"), y());
+ qElement.setAttribute(QLatin1String("width"), width());
+ qElement.setAttribute(QLatin1String("height"), height());
+ qElement.setAttribute(QLatin1String("isinstance"), m_isInstance);
+ if (!m_instanceName.isEmpty())
+ qElement.setAttribute(QLatin1String("instancename"), m_instanceName);
+ if (m_showStereotype)
+ qElement.setAttribute(QLatin1String("showstereotype"), m_showStereotype);
+
+ // Unique identifier for widget (todo: id() should be unique, new attribute
+ // should indicate the UMLObject's ID it belongs to)
+ qElement.setAttribute(QLatin1String("localid"), Uml::ID::toString(m_nLocalID));
+}
+
+bool UMLWidget::loadFromXMI(QDomElement & qElement)
+{
+ QString id = qElement.attribute(QLatin1String("xmi.id"), QLatin1String("-1"));
+ m_nId = Uml::ID::fromString(id);
+
+ WidgetBase::loadFromXMI(qElement);
+ QString x = qElement.attribute(QLatin1String("x"), QLatin1String("0"));
+ QString y = qElement.attribute(QLatin1String("y"), QLatin1String("0"));
+ QString h = qElement.attribute(QLatin1String("height"), QLatin1String("0"));
+ QString w = qElement.attribute(QLatin1String("width"), QLatin1String("0"));
+
+ setSize(w.toFloat(), h.toFloat());
+ setX(x.toFloat());
+ setY(y.toFloat());
+ QString isinstance = qElement.attribute(QLatin1String("isinstance"), QLatin1String("0"));
+ m_isInstance = (bool)isinstance.toInt();
+ m_instanceName = qElement.attribute(QLatin1String("instancename"));
+ QString showstereo = qElement.attribute(QLatin1String("showstereotype"), QLatin1String("0"));
+ m_showStereotype = (bool)showstereo.toInt();
+
+ QString localid = qElement.attribute(QLatin1String("localid"), QLatin1String("0"));
+ if (localid != QLatin1String("0")) {
+ m_nLocalID = Uml::ID::fromString(localid);
+ }
+
+ return true;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/umlwidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/umlwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/umlwidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/umlwidget.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,347 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef UMLWIDGET_H
+#define UMLWIDGET_H
+
+#include "associationwidgetlist.h"
+#include "basictypes.h"
+#include "optionstate.h"
+#include "umlwidgetlist.h"
+#include "widgetbase.h"
+
+#include <QCursor>
+#include <QFont>
+
+class IDChangeLog;
+class UMLDoc;
+class UMLObject;
+class UMLScene;
+
+class QPainter;
+class QFontMetrics;
+
+/**
+ * This is the base class for nearly all graphical widgets.
+ *
+ * @short The base class for graphical UML objects.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UMLWidget : public WidgetBase
+{
+ Q_OBJECT
+public:
+
+ friend class ToolBarStateArrow; // for calling the mouse*Event handlers
+
+ static const QSizeF DefaultMinimumSize;
+ static const QSizeF DefaultMaximumSize;
+ static const qreal defaultMargin;
+
+ explicit UMLWidget(UMLScene *scene, WidgetType type = wt_UMLWidget, UMLObject *o = 0);
+ explicit UMLWidget(UMLScene *scene, WidgetType type = wt_UMLWidget, Uml::ID::Type id = Uml::ID::None);
+ virtual ~UMLWidget();
+
+ // Copy constructor - not implemented.
+ // UMLWidget(const UMLWidget& other);
+
+ UMLWidget& operator=(const UMLWidget& other);
+
+ bool operator==(const UMLWidget& other) const;
+
+ void setLocalID(Uml::ID::Type id);
+ Uml::ID::Type localID() const;
+
+ virtual UMLWidget* widgetWithID(Uml::ID::Type id);
+
+ virtual QSizeF minimumSize() const;
+ void setMinimumSize(const QSizeF &size);
+
+ virtual QSizeF maximumSize();
+ void setMaximumSize(const QSizeF &size);
+
+ virtual void setUseFillColor(bool fc);
+ void setUseFillColorCmd(bool fc);
+
+ virtual void setTextColor(const QColor &color);
+ void setTextColorCmd(const QColor &color);
+
+ virtual void setLineColor(const QColor &color);
+ void setLineColorCmd(const QColor &color);
+
+ virtual void setLineWidth(uint width);
+ void setLineWidthCmd(uint width);
+
+ virtual void setFillColor(const QColor &color);
+ void setFillColorCmd(const QColor &color);
+
+ void setSelectedFlag(bool _select);
+ virtual void setSelected(bool _select);
+
+ void setScene(UMLScene *scene);
+
+ virtual bool activate(IDChangeLog* ChangeLog = 0);
+
+ void setPenFromSettings(QPainter &p);
+ void setPenFromSettings(QPainter *p);
+
+ virtual void setFont(const QFont &font);
+ void setFontCmd(const QFont &font);
+
+ /**
+ * Returns whether we triggered the update of position movement.
+ * If so, you probably don't want to move it.
+ *
+ * @return The moving state.
+ */
+ bool getStartMove() const {
+ return m_startMove;
+ }
+
+ virtual void setX(qreal x);
+ virtual void setY(qreal y);
+
+ /**
+ * Returns the height of widget.
+ */
+ qreal height() const {
+ return rect().height();
+ }
+
+ /**
+ * Returns the width of the widget.
+ */
+ qreal width() const {
+ return rect().width();
+ }
+
+ void setSize(qreal width, qreal height);
+ void setSize(const QSizeF& size);
+
+ virtual void resizeWidget(qreal newW, qreal newH);
+
+ bool getIgnoreSnapToGrid() const;
+ void setIgnoreSnapToGrid(bool to);
+
+ void moveByLocal(qreal dx, qreal dy);
+
+ void removeAssoc(AssociationWidget* pAssoc);
+ void addAssoc(AssociationWidget* pAssoc);
+
+ /**
+ * Returns the list of associations connected to this widget.
+ */
+ AssociationWidgetList & associationWidgetList() {
+ return m_Assocs;
+ }
+
+ /**
+ * Read property of bool m_isInstance
+ */
+ bool isInstance() const {
+ return m_isInstance;
+ }
+
+ /**
+ * Write property of bool m_isInstance
+ */
+ void setIsInstance(bool isInstance) {
+ m_isInstance = isInstance;
+ }
+
+ /**
+ * Write property of m_instanceName
+ */
+ void setInstanceName(const QString &instanceName) {
+ m_instanceName = instanceName;
+ }
+
+ /**
+ * Read property of m_instanceName
+ */
+ QString instanceName() const {
+ return m_instanceName;
+ }
+
+ bool showStereotype() const;
+ virtual void setShowStereotype(bool flag);
+
+ virtual void showPropertiesDialog();
+
+ virtual void adjustAssocs(qreal dx, qreal dy);
+ void adjustUnselectedAssocs(qreal dx, qreal dy);
+
+ bool isActivated() const;
+ void setActivated(bool active = true);
+
+ virtual void cleanup();
+
+ static bool widgetHasUMLObject(WidgetBase::WidgetType type);
+
+ void updateGeometry();
+
+ void clipSize();
+
+ void forceUpdateFontMetrics(QPainter *painter);
+ void forceUpdateFontMetrics(QFont &font, QPainter *painter);
+
+ virtual bool loadFromXMI(QDomElement &qElement);
+ virtual void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
+
+ QPointF startMovePosition() const;
+ void setStartMovePosition(const QPointF &position);
+
+ QSizeF startResizeSize() const;
+
+ virtual QSizeF calculateSize(bool withExtensions = true) const;
+ void resize();
+
+ bool fixedAspectRatio() const {
+ return m_fixedAspectRatio;
+ }
+
+ void setFixedAspectRatio(bool state) {
+ m_fixedAspectRatio = state;
+ }
+
+ typedef enum {
+ FT_NORMAL = 0,
+ FT_BOLD = 1,
+ FT_ITALIC = 2,
+ FT_UNDERLINE = 3,
+ FT_BOLD_ITALIC = 4,
+ FT_BOLD_UNDERLINE = 5,
+ FT_ITALIC_UNDERLINE = 6,
+ FT_BOLD_ITALIC_UNDERLINE = 7,
+ FT_INVALID = 8
+ } FontType;
+
+ virtual void setDefaultFontMetrics(QFont &font, UMLWidget::FontType fontType);
+ virtual void setDefaultFontMetrics(QFont &font, UMLWidget::FontType fontType, QPainter &painter);
+
+ QFontMetrics &getFontMetrics(UMLWidget::FontType fontType) const;
+ void setFontMetrics(UMLWidget::FontType fontType, QFontMetrics fm);
+ void setupFontType(QFont &font, UMLWidget::FontType fontType);
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+public Q_SLOTS:
+ virtual void updateWidget();
+ virtual void slotMenuSelection(QAction* action);
+ virtual void slotWidgetMoved(Uml::ID::Type id);
+ virtual void slotFillColorChanged(Uml::ID::Type viewID);
+ virtual void slotLineColorChanged(Uml::ID::Type viewID);
+ virtual void slotTextColorChanged(Uml::ID::Type viewID);
+ virtual void slotLineWidthChanged(Uml::ID::Type viewID);
+
+ void slotSnapToGrid();
+
+signals:
+ /**
+ * Emit when the widget moves its' position.
+ * @param id The id of the object behind the widget.
+ */
+ void sigWidgetMoved(Uml::ID::Type id);
+
+protected:
+ virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent* event);
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+ virtual void moveEvent(QGraphicsSceneMouseEvent *event);
+ virtual void moveWidgetBy(qreal diffX, qreal diffY);
+ virtual void constrainMovementForAllWidgets(qreal &diffX, qreal &diffY);
+ virtual void constrain(qreal& width, qreal& height);
+
+ virtual bool isInResizeArea(QGraphicsSceneMouseEvent *me);
+ virtual QCursor resizeCursor() const;
+
+ void selectSingle(QGraphicsSceneMouseEvent *me);
+ void selectMultiple(QGraphicsSceneMouseEvent *me);
+ void deselect(QGraphicsSceneMouseEvent *me);
+ // void resetSelection();
+
+ void setSelectionBounds();
+
+ void resize(QGraphicsSceneMouseEvent *me);
+
+ bool wasSizeChanged();
+ bool wasPositionChanged();
+
+ ///////////////// Data Loaded/Saved /////////////////////////////////
+
+ /// A list of AssociationWidgets between the UMLWidget and other UMLWidgets in the diagram
+ AssociationWidgetList m_Assocs;
+
+ QString m_instanceName; ///< instance name (used if on a deployment diagram)
+ bool m_isInstance; ///< holds whether this widget is a component instance (i.e. on a deployment diagram)
+ bool m_showStereotype; ///< should the stereotype be displayed
+
+ ///////////////// End of Data Loaded/Saved //////////////////////////
+
+ Uml::ID::Type m_nLocalID;
+ bool m_startMove;
+ QPointF m_startMovePostion;
+ QSizeF m_startResizeSize;
+ int m_nPosX;
+ UMLDoc *m_doc; ///< shortcut for UMLApp::app()->getDocument()
+ bool m_resizable;
+ QFontMetrics *m_pFontMetrics[FT_INVALID];
+ QSizeF m_minimumSize;
+ QSizeF m_maximumSize;
+
+ /// true if the activate function has been called for this class instance
+ bool m_activated;
+
+ /**
+ * Change Widget Behaviour
+ */
+ bool m_ignoreSnapToGrid;
+ bool m_ignoreSnapComponentSizeToGrid;
+ bool m_fixedAspectRatio;
+
+ /// The text in the status bar when the cursor was pressed.
+ QString m_oldStatusBarMsg;
+
+ /// The X/Y offset from the position of the cursor when it was pressed to the
+ /// upper left corner of the widget.
+ QPointF m_pressOffset;
+
+ /// The X/Y position the widget had when the movement started.
+ QPointF m_oldPos;
+
+ /// The width/height the widget had when the resize started.
+ qreal m_oldW, m_oldH;
+
+ /// If shift or control button were pressed in mouse press event.
+ bool m_shiftPressed;
+
+ /**
+ * If cursor was in move/resize area when left button was pressed (and no
+ * other widgets were selected).
+ */
+ bool m_inMoveArea, m_inResizeArea;
+
+ /**
+ * If the widget was selected/moved/resized in the press and release cycle.
+ * Moved/resized is true if the widget was moved/resized even if the final
+ * position/size is the same as the starting one.
+ */
+ bool m_moved, m_resized;
+
+private:
+ void init();
+ void toForeground();
+
+};
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/usecasewidget.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/usecasewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/usecasewidget.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/usecasewidget.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header file
+#include "usecasewidget.h"
+
+// app includes
+#include "usecase.h"
+#include "umlview.h"
+
+/**
+ * Creates a UseCase widget.
+ * @param scene The parent of the widget.
+ * @param o The UMLUseCase to represent.
+ */
+UseCaseWidget::UseCaseWidget(UMLScene * scene, UMLUseCase *o)
+ : UMLWidget(scene, WidgetBase::wt_UseCase, o)
+{
+}
+
+/**
+ * Destructor.
+ */
+UseCaseWidget::~UseCaseWidget()
+{
+}
+
+/**
+ * Overrides the standard paint event.
+ */
+void UseCaseWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ setPenFromSettings(painter);
+ if (UMLWidget::useFillColor())
+ painter->setBrush(UMLWidget::fillColor());
+ QFont font = UMLWidget::font();
+ font.setUnderline(false);
+ font.setBold(false);
+ font.setItalic(m_umlObject->isAbstract());
+ painter->setFont(font);
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int w = width();
+ const int h = height();
+ //int middleX = w / 2;
+ bool drawStereotype = umlObject() && !umlObject()->stereotype().isEmpty();
+ const int textStartY = (h / 2) - (drawStereotype ? fontHeight / 4 : fontHeight / 2);
+
+ painter->drawEllipse(0, 0, w, h);
+ painter->setPen(textColor());
+ if (drawStereotype)
+ painter->drawText(UC_MARGIN, textStartY-fontHeight, w - UC_MARGIN * 2, fontHeight, Qt::AlignCenter, umlObject()->stereotype(true));
+
+ painter->drawText(UC_MARGIN, textStartY, w - UC_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
+ setPenFromSettings(painter);
+
+ UMLWidget::paint(painter, option, widget);
+}
+
+/**
+ * Saves this UseCase to file.
+ */
+void UseCaseWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
+{
+ QDomElement usecaseElement = qDoc.createElement(QLatin1String("usecasewidget"));
+ UMLWidget::saveToXMI(qDoc, usecaseElement);
+ qElement.appendChild(usecaseElement);
+}
+
+/**
+ * Overrides method from UMLWidget
+ */
+QSizeF UseCaseWidget::minimumSize() const
+{
+ const UMLWidget::FontType ft = (m_umlObject->isAbstract() ? FT_BOLD_ITALIC : FT_BOLD);
+ const QFontMetrics &fm = UMLWidget::getFontMetrics(ft);
+ const int fontHeight = fm.lineSpacing();
+ const int textWidth = fm.width(name());
+ bool drawStereotype = umlObject() && !umlObject()->stereotype().isEmpty();
+ int width = textWidth > UC_WIDTH?textWidth:UC_WIDTH;
+ int height = UC_HEIGHT + (drawStereotype ? 2 * fontHeight : fontHeight) + UC_MARGIN;
+
+ width += UC_MARGIN * 2;
+
+ return QSizeF(width, height);
+}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/usecasewidget.h umbrello-kf6-15.08.1/umbrello/umlwidgets/usecasewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/usecasewidget.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/usecasewidget.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef USECASEWIDGET_H
+#define USECASEWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLUseCase;
+
+#define UC_MARGIN 5
+#define UC_WIDTH 60
+#define UC_HEIGHT 30
+
+
+/**
+ * This class is the graphical version of a UMLUseCase. The
+ * UseCaseWidget class inherits from the @ref UMLWidget class
+ * which adds most of the functionality to this class.
+
+ * A UseCaseWidget is created by a @ref UMLView. An UseCaseWidget belongs to only one
+ * @ref UMLView instance. When the @ref UMLView instance that this class belongs to,
+ * it will be automatically deleted.
+ *
+ * If the @ref UMLUseCase class that this UseCaseWidget is displaying is deleted, the @ref UMLView will
+ * make sure that this instance is also deleted.
+ *
+ * The UseCaseWidget class inherits from the @ref UMLWidget class which adds most of the functionality
+ * to this class.
+ *
+ * @short A graphical version of a UMLUseCase.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class UseCaseWidget : public UMLWidget
+{
+public:
+ UseCaseWidget(UMLScene * scene, UMLUseCase *o);
+ virtual ~UseCaseWidget();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ // For loading we can use the loadFromXMI() inherited from
+ // UMLWidget.
+ virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+protected:
+ QSizeF minimumSize() const;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widgetbase.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/widgetbase.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widgetbase.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/widgetbase.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,1119 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#include "widgetbase.h"
+
+#include "classifier.h"
+#include "debug_utils.h"
+#include "floatingtextwidget.h"
+#include "optionstate.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlobject.h"
+#include "umlscene.h"
+
+#if QT_VERSION < 0x050000
+#include <kcolordialog.h>
+#include <kfontdialog.h>
+#endif
+#include <KLocalizedString>
+
+#include <QAction>
+#if QT_VERSION >= 0x050000
+#include <QColorDialog>
+#include <QFontDialog>
+#endif
+#include <QPointer>
+
+/**
+ * Creates a WidgetBase object.
+ *
+ * @param scene The view to be displayed on.
+ * @param type The WidgetType to construct. This must be set to the appropriate
+ * value by the constructors of inheriting classes.
+ */
+WidgetBase::WidgetBase(UMLScene *scene, WidgetType type)
+ : QGraphicsObject(),
+ m_baseType(type),
+ m_scene(scene),
+ m_umlObject(0),
+ m_textColor(QColor("black")),
+ m_lineColor(QColor("black")),
+ m_fillColor(QColor("yellow")),
+ m_brush(m_fillColor),
+ m_lineWidth(0), // initialize with 0 to have valid start condition
+ m_useFillColor(true),
+ m_usesDiagramTextColor(true),
+ m_usesDiagramLineColor(true),
+ m_usesDiagramLineWidth(true)
+{
+ setSelected(false);
+ scene->addItem(this);
+
+ // TODO 310283
+ setFlags(ItemIsSelectable);
+ //setFlags(ItemIsSelectable | ItemIsMovable |ItemSendsGeometryChanges);
+ if (m_scene) {
+ m_usesDiagramLineColor = true;
+ m_usesDiagramLineWidth = true;
+ m_usesDiagramTextColor = true;
+ const Settings::OptionState& optionState = m_scene->optionState();
+ m_textColor = optionState.uiState.textColor;
+ m_lineColor = optionState.uiState.lineColor;
+ m_lineWidth = optionState.uiState.lineWidth;
+ m_font = optionState.uiState.font;
+ } else {
+ uError() << "WidgetBase constructor: SERIOUS PROBLEM - m_scene is NULL";
+ }
+}
+
+/**
+ * Destructor.
+ */
+WidgetBase::~WidgetBase()
+{
+}
+
+/**
+ * Read property of m_baseType.
+ */
+WidgetBase::WidgetType WidgetBase::baseType() const
+{
+ return m_baseType;
+}
+
+/**
+ * @return The type used for rtti as string.
+ */
+QLatin1String WidgetBase::baseTypeStr() const
+{
+ return QLatin1String(ENUM_NAME(WidgetBase, WidgetType, m_baseType));
+}
+
+/*
+ * Sets the state of whether the widget is selected.
+ *
+ * @param select The state of whether the widget is selected.
+ */
+void WidgetBase::setSelected(bool select)
+{
+ QGraphicsObject::setSelected(select);
+}
+
+/**
+ * Deliver a pointer to the connected UMLView
+ * (needed esp. by event handling of AssociationLine).
+ */
+UMLScene* WidgetBase::umlScene() const
+{
+ return m_scene;
+}
+
+/**
+ * This is shortcut method for UMLApp::app()->document().
+ *
+ * @return Pointer to the UMLDoc object.
+ */
+UMLDoc* WidgetBase::umlDoc() const
+{
+ return UMLApp::app()->document();
+}
+
+/**
+ * Returns the @ref UMLObject set to represent.
+ *
+ * @return the UMLObject to represent.
+ */
+UMLObject* WidgetBase::umlObject() const
+{
+ return m_umlObject;
+}
+
+/**
+ * Sets the @ref UMLObject to represent.
+ *
+ * @param obj The object to represent.
+ */
+void WidgetBase::setUMLObject(UMLObject *obj)
+{
+ m_umlObject = obj;
+}
+
+/**
+ * Write property of m_nId.
+ */
+void WidgetBase::setID(Uml::ID::Type id)
+{
+ if (m_umlObject) {
+ if (m_umlObject->id() != Uml::ID::None)
+ uWarning() << "changing old UMLObject " << Uml::ID::toString(m_umlObject->id())
+ << " to " << Uml::ID::toString(id);
+ m_umlObject->setID(id);
+ }
+ m_nId = id;
+}
+
+/**
+ * Read property of m_nId.
+ */
+Uml::ID::Type WidgetBase::id() const
+{
+ if (m_umlObject)
+ return m_umlObject->id();
+ return m_nId;
+}
+
+/**
+ * Used by some child classes to get documentation.
+ *
+ * @return The documentation from the UMLObject (if m_umlObject is set.)
+ */
+QString WidgetBase::documentation() const
+{
+ if (m_umlObject)
+ return m_umlObject->doc();
+ return m_Doc;
+}
+
+/**
+ * Returns state of documentation for the widget.
+ *
+ * @return false if documentation is empty
+ */
+bool WidgetBase::hasDocumentation()
+{
+ if (m_umlObject)
+ return m_umlObject->hasDoc();
+ return !m_Doc.isEmpty();
+}
+
+/**
+ * Used by some child classes to set documentation.
+ *
+ * @param doc The documentation to be set in the UMLObject
+ * (if m_umlObject is set.)
+ */
+void WidgetBase::setDocumentation(const QString& doc)
+{
+ if (m_umlObject)
+ m_umlObject->setDoc(doc);
+ else
+ m_Doc = doc;
+}
+
+/**
+ * Gets the name from the corresponding UMLObject if this widget has an
+ * underlying UMLObject; if it does not, then it returns the local
+ * m_Text (notably the case for FloatingTextWidget.)
+ *
+ * @return the currently set name
+ */
+QString WidgetBase::name() const
+{
+ if (m_umlObject)
+ return m_umlObject->name();
+ return m_Text;
+}
+
+/**
+ * Sets the name in the corresponding UMLObject.
+ * Sets the local m_Text if m_umlObject is NULL.
+ *
+ * @param strName The name to be set.
+ */
+void WidgetBase::setName(const QString &strName)
+{
+ if (m_umlObject)
+ m_umlObject->setName(strName);
+ else
+ m_Text = strName;
+}
+
+/**
+ * Returns text color
+ *
+ * @return currently used text color
+ */
+QColor WidgetBase::textColor() const
+{
+ return m_textColor;
+}
+
+/**
+ * Sets the text color
+ *
+ * @param color the new text color
+ */
+void WidgetBase::setTextColor(const QColor &color)
+{
+ m_textColor = color;
+ m_usesDiagramTextColor = false;
+}
+
+/**
+ * Returns line color
+ *
+ * @return currently used line color
+ */
+QColor WidgetBase::lineColor() const
+{
+ return m_lineColor;
+}
+
+/**
+ * Sets the line color
+ *
+ * @param color The new line color
+ */
+void WidgetBase::setLineColor(const QColor &color)
+{
+ m_lineColor = color;
+ m_usesDiagramLineColor = false;
+}
+
+/**
+ * Returns fill color
+ *
+ * @return currently used fill color
+ */
+QColor WidgetBase::fillColor() const
+{
+ return m_fillColor;
+}
+
+/**
+ * Sets the fill color
+ *
+ * @param color The new fill color
+ */
+void WidgetBase::setFillColor(const QColor &color)
+{
+ m_fillColor = color;
+ m_usesDiagramFillColor = false;
+}
+
+/**
+ * Returns line width
+ *
+ * @return currently used line with
+ */
+uint WidgetBase::lineWidth() const
+{
+ return m_lineWidth;
+}
+
+/**
+ * Sets the line width
+ *
+ * @param width The new line width
+ */
+void WidgetBase::setLineWidth(uint width)
+{
+ m_lineWidth = width;
+ m_usesDiagramLineWidth = false;
+}
+
+/**
+ * Return state of fill color usage
+ *
+ * @return True if fill color is used
+ */
+bool WidgetBase::useFillColor()
+{
+ return m_useFillColor;
+}
+
+/**
+ * Set state if fill color is used
+ *
+ * @param state The state to set
+ */
+void WidgetBase::setUseFillColor(bool state)
+{
+ m_useFillColor = state;
+ m_usesDiagramUseFillColor = false;
+}
+
+/**
+ * Returns state if diagram text color is used
+ *
+ * @return True means diagram text color is used
+ */
+bool WidgetBase::usesDiagramTextColor() const
+{
+ return m_usesDiagramTextColor;
+}
+
+/**
+ * Set state if diagram text color is used
+ *
+ * @param state The state to set
+ */
+void WidgetBase::setUsesDiagramTextColor(bool state)
+{
+ if (m_usesDiagramTextColor == state) {
+ return;
+ }
+ m_usesDiagramTextColor = state;
+ setTextColor(m_textColor);
+}
+
+/**
+ * Returns state of diagram line color is used
+ *
+ * @return True means diagrams line color is used
+*/
+bool WidgetBase::usesDiagramLineColor() const
+{
+ return m_usesDiagramLineColor;
+}
+
+/**
+ * Set state of diagram line color is used
+ *
+ * @param state The state to set
+ */
+void WidgetBase::setUsesDiagramLineColor(bool state)
+{
+ m_usesDiagramLineColor = state;
+}
+
+/**
+ * Returns state of diagram fill color is used
+ *
+ * @return True means diagrams fill color is used
+*/
+bool WidgetBase::usesDiagramFillColor() const
+{
+ return m_usesDiagramFillColor;
+}
+
+/**
+ * Set state if diagram fill color is used
+ *
+ * @param state The state to set
+ */
+void WidgetBase::setUsesDiagramFillColor(bool state)
+{
+ m_usesDiagramFillColor = state;
+}
+
+/**
+ * Returns state of diagram use fill color is used
+ *
+ * @return True means diagrams fill color is used
+*/
+bool WidgetBase::usesDiagramUseFillColor() const
+{
+ return m_usesDiagramUseFillColor;
+}
+
+/**
+ * Set state of diagram use fill color is used
+ *
+ * @param state The state to set
+ */
+void WidgetBase::setUsesDiagramUseFillColor(bool state)
+{
+ m_usesDiagramUseFillColor = state;
+}
+
+/**
+ * Returns state of diagram line width is used
+ *
+ * @return True means diagrams line width is used
+ */
+bool WidgetBase::usesDiagramLineWidth() const
+{
+ return m_usesDiagramLineWidth;
+}
+
+/**
+ * Set state of diagram line width is used
+ *
+ * @param state The state to set
+ */
+void WidgetBase::setUsesDiagramLineWidth(bool state)
+{
+ m_usesDiagramLineWidth = state;
+}
+
+/**
+ * Returns the font used for diaplaying any text.
+ * @return the font
+ */
+QFont WidgetBase::font() const
+{
+ return m_font;
+}
+
+/**
+ * Set the font used to display text inside this widget.
+ */
+void WidgetBase::setFont(const QFont& font)
+{
+ m_font = font;
+}
+
+/**
+ * A virtual method for the widget to display a property dialog box.
+ * Subclasses should reimplment this appropriately.
+ */
+void WidgetBase::showPropertiesDialog()
+{
+}
+
+/**
+ * A virtual method to save the properties of this widget into a
+ * QDomElement i.e xml.
+ *
+ * Subclasses should first create a new dedicated element as the child
+ * of \a qElement parameter passed. Then this base method should be
+ * called to save basic widget properties.
+ *
+ * @param qDoc A QDomDocument object representing the xml document.
+ * @param qElement A QDomElement representing xml element data.
+ */
+void WidgetBase::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
+ {
+ Q_UNUSED(qDoc)
+
+ qElement.setAttribute(QLatin1String("textcolor"), m_usesDiagramTextColor ? QLatin1String("none")
+ : m_textColor.name());
+ if (m_usesDiagramLineColor) {
+ qElement.setAttribute(QLatin1String("linecolor"), QLatin1String("none"));
+ } else {
+ qElement.setAttribute(QLatin1String("linecolor"), m_lineColor.name());
+ }
+ if (m_usesDiagramLineWidth) {
+ qElement.setAttribute(QLatin1String("linewidth"), QLatin1String("none"));
+ } else {
+ qElement.setAttribute(QLatin1String("linewidth"), m_lineWidth);
+ }
+ qElement.setAttribute(QLatin1String("usefillcolor"), m_useFillColor);
+ // for consistency the following attributes now use american spelling for "color"
+ qElement.setAttribute(QLatin1String("usesdiagramfillcolor"), m_usesDiagramFillColor);
+ qElement.setAttribute(QLatin1String("usesdiagramusefillcolor"), m_usesDiagramUseFillColor);
+ if (m_usesDiagramFillColor) {
+ qElement.setAttribute(QLatin1String("fillcolor"), QLatin1String("none"));
+ } else {
+ qElement.setAttribute(QLatin1String("fillcolor"), m_fillColor.name());
+ }
+ qElement.setAttribute(QLatin1String("font"), m_font.toString());
+}
+
+/**
+ * A virtual method to load the properties of this widget from a
+ * QDomElement into this widget.
+ *
+ * Subclasses should reimplement this to load addtional properties
+ * required, calling this base method to load the basic properties of
+ * the widget.
+ *
+ * @param qElement A QDomElement which contains xml info for this widget.
+ *
+ * @todo Add support to load older version.
+ */
+bool WidgetBase::loadFromXMI(QDomElement& qElement)
+{
+ // first load from "linecolour" and then overwrite with the "linecolor"
+ // attribute if that one is present. The "linecolour" name was a "typo" in
+ // earlier versions of umbrello-kf6
+ QString lineColor = qElement.attribute(QLatin1String("linecolour"), QLatin1String("none"));
+ lineColor = qElement.attribute(QLatin1String("linecolor"), lineColor);
+ if (lineColor != QLatin1String("none")) {
+ m_lineColor = QColor(lineColor);
+ m_usesDiagramLineColor = false;
+ } else if (m_baseType != WidgetBase::wt_Box && m_scene != NULL) {
+ m_lineColor = m_scene->lineColor();
+ m_usesDiagramLineColor = true;
+ }
+ QString lineWidth = qElement.attribute(QLatin1String("linewidth"), QLatin1String("none"));
+ if (lineWidth != QLatin1String("none")) {
+ m_lineWidth = lineWidth.toInt();
+ m_usesDiagramLineWidth = false;
+ } else if (m_scene) {
+ m_lineWidth = m_scene->lineWidth();
+ m_usesDiagramLineWidth = true;
+ }
+ QString textColor = qElement.attribute(QLatin1String("textcolor"), QLatin1String("none"));
+ if (textColor != QLatin1String("none")) {
+ m_textColor = QColor(textColor);
+ m_usesDiagramTextColor = false;
+ } else if (m_scene) {
+ m_textColor = m_scene->textColor();
+ m_usesDiagramTextColor = true;
+ }
+ QString usefillcolor = qElement.attribute(QLatin1String("usefillcolor"), QLatin1String("1"));
+ m_useFillColor = (bool)usefillcolor.toInt();
+ /*
+ For the next three *color attributes, there was a mixup of american and english spelling for "color".
+ So first we need to keep backward compatibility and try to retrieve the *colour attribute.
+ Next we overwrite this value if we find a *color, otherwise the former *colour is kept.
+ */
+ QString fillColor = qElement.attribute(QLatin1String("fillcolour"), QLatin1String("none"));
+ fillColor = qElement.attribute(QLatin1String("fillcolor"), fillColor);
+ if (fillColor != QLatin1String("none")) {
+ m_fillColor = QColor(fillColor);
+ }
+
+ QString usesDiagramFillColor = qElement.attribute(QLatin1String("usesdiagramfillcolour"), QLatin1String("1"));
+ usesDiagramFillColor = qElement.attribute(QLatin1String("usesdiagramfillcolor"), usesDiagramFillColor);
+ m_usesDiagramFillColor = (bool)usesDiagramFillColor.toInt();
+
+ QString usesDiagramUseFillColor = qElement.attribute(QLatin1String("usesdiagramusefillcolour"), QLatin1String("1"));
+ usesDiagramUseFillColor = qElement.attribute(QLatin1String("usesdiagramusefillcolor"), usesDiagramUseFillColor);
+ m_usesDiagramUseFillColor = (bool)usesDiagramUseFillColor.toInt();
+
+ QString font = qElement.attribute(QLatin1String("font"));
+ if (!font.isEmpty()) {
+ QFont newFont;
+ newFont.fromString(font);
+ m_font = newFont;
+ } else {
+ uWarning() << "Using default font " << m_font.toString()
+ << " for widget with xmi.id " << Uml::ID::toString(m_nId);
+ }
+
+ return true;
+}
+
+/**
+ * Assignment operator
+ */
+WidgetBase& WidgetBase::operator=(const WidgetBase& other)
+{
+ m_baseType = other.m_baseType;
+ m_scene = other.m_scene;
+ m_umlObject = other.m_umlObject;
+ m_Doc = other.m_Doc;
+ m_Text = other.m_Text;
+ m_nId = other.m_nId;
+ m_textColor = other.m_textColor;
+ m_lineColor = other.m_lineColor;
+ m_fillColor = other.m_fillColor;
+ m_brush = other.m_brush;
+ m_font = other.m_font;
+ m_lineWidth = other.m_lineWidth;
+ m_useFillColor = other.m_useFillColor;
+ m_usesDiagramTextColor = other.m_usesDiagramTextColor;
+ m_usesDiagramLineColor = other.m_usesDiagramLineColor;
+ m_usesDiagramFillColor = other.m_usesDiagramFillColor;
+ m_usesDiagramLineWidth = other.m_usesDiagramLineWidth;
+ setSelected(other.isSelected());
+
+ return *this;
+}
+
+/**
+ * return drawing rectangle of widget in local coordinates
+ */
+QRectF WidgetBase::rect() const
+{
+ return m_rect;
+}
+
+/**
+ * set widget rectangle in item coordinates
+ */
+void WidgetBase::setRect(const QRectF& rect)
+{
+ if (m_rect == rect)
+ return;
+ prepareGeometryChange();
+ m_rect = rect;
+ update();
+}
+
+/**
+ * set widget rectangle in item coordinates
+ */
+void WidgetBase::setRect(qreal x, qreal y, qreal width, qreal height)
+{
+ setRect(QRectF(x, y, width, height));
+}
+
+/**
+ * @return The bounding rectangle for this widget.
+ * @see setRect
+ */
+QRectF WidgetBase::boundingRect() const
+{
+ int halfWidth = lineWidth()/2;
+ return m_rect.adjusted(-halfWidth, -halfWidth, halfWidth, halfWidth);
+}
+
+/**
+ * Test if point is inside the bounding rectangle of the widget.
+ * Inheriting classes may reimplement this to test possible child widgets.
+ *
+ * @param p Point to be checked.
+ *
+ * @return 'this' if the given point is in the boundaries of the widget;
+ * else NULL.
+ */
+UMLWidget* WidgetBase::onWidget(const QPointF &p)
+{
+ UMLWidget *uw = dynamic_cast<UMLWidget*>(this);
+ if (uw == NULL)
+ return NULL;
+ const qreal w = m_rect.width();
+ const qreal h = m_rect.height();
+ const qreal left = x(); // don't use m_rect.x() for this, it is always 0
+ const qreal right = left + w;
+ const qreal top = y(); // don't use m_rect.y() for this, it is always 0
+ const qreal bottom = top + h;
+ // uDebug() << "p=(" << p.x() << "," << p.y()
+ // << "), x=" << left << ", y=" << top << ", w=" << w << ", h=" << h
+ // << "; right=" << right << ", bottom=" << bottom;
+ if (p.x() < left || p.x() > right ||
+ p.y() < top || p.y() > bottom) { // Qt coord.sys. origin in top left corner
+ // uDebug() << "returning NULL";
+ return NULL;
+ }
+ // uDebug() << "returning this";
+ return uw;
+}
+
+/**
+ * Draws the UMLWidget on the given paint device
+ *
+ * @param painter The painter for the drawing device
+ * @param option Painting related options
+ * @param widget Background widget on which to paint (optional)
+ *
+ */
+void WidgetBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(painter); Q_UNUSED(option); Q_UNUSED(widget);
+}
+
+/**
+ * Reimplemented to show appropriate context menu.
+ */
+void WidgetBase::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+{
+ event->accept();
+ uDebug() << "widget = " << name() << " / type = " << baseTypeStr();
+
+ UMLScene *scene = umlScene();
+
+ // If right-click was done on a widget that was not selected, clear the
+ // current selection and select the new widget. The context menu is shown
+ // with actions for that single widget.
+ // If a keyboard modifier was used, add the widget to the current selection
+ // and show the menu with actions for the whole selection.
+ if (!isSelected()) {
+ Qt::KeyboardModifiers forSelection = (Qt::ControlModifier | Qt::ShiftModifier);
+ if ((event->modifiers() & forSelection) == 0) {
+ scene->clearSelected();
+ }
+
+ if (umlObject() != 0) {
+ scene->selectWidget(dynamic_cast<UMLWidget*>(this));
+ } else {
+ setSelected(true);
+ }
+ }
+
+ int count = scene->selectedCount(true);
+
+ // Determine multi state
+ bool multi = (isSelected() && count > 1);
+
+ ListPopupMenu popup(0, this, multi, scene->getUniqueSelectionType());
+
+ // Disable the "view code" menu for simple code generators
+ if (UMLApp::app()->isSimpleCodeGeneratorActive()) {
+ popup.setActionEnabled(ListPopupMenu::mt_ViewCode, false);
+ }
+
+ QAction *triggered = popup.exec(event->screenPos());
+ ListPopupMenu *parentMenu = ListPopupMenu::menuFromAction(triggered);
+
+ if (!parentMenu) {
+ uDebug() << "Action's data field does not contain ListPopupMenu pointer";
+ return;
+ }
+
+ WidgetBase *ownerWidget = parentMenu->ownerWidget();
+ // assert because logic is based on only WidgetBase being the owner of
+ // ListPopupMenu actions executed in this context menu.
+ Q_ASSERT_X(ownerWidget != 0, "WidgetBase::contextMenuEvent",
+ "ownerWidget is null which means action belonging to UMLView, UMLScene"
+ " or UMLObject is the one triggered in ListPopupMenu");
+
+ ownerWidget->slotMenuSelection(triggered);
+}
+
+/**
+ * This is usually called synchronously after menu.exec() and \a
+ * trigger's parent is always the ListPopupMenu which can be used to
+ * get the type of action of \a trigger.
+ *
+ * @note Subclasses can reimplement to handle specific actions and
+ * leave the rest to WidgetBase::slotMenuSelection.
+ */
+void WidgetBase::slotMenuSelection(QAction *trigger)
+{
+ if (!trigger) {
+ return;
+ }
+ QColor newColor;
+
+ const WidgetType wt = m_baseType; // short hand name
+
+ ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(trigger);
+ switch (sel) {
+ case ListPopupMenu::mt_Rename:
+ umlDoc()->renameUMLObject(umlObject());
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ if (wt == WidgetBase::wt_Actor || wt == WidgetBase::wt_UseCase ||
+ wt == WidgetBase::wt_Package || wt == WidgetBase::wt_Interface ||
+ wt == WidgetBase::wt_Datatype || wt == WidgetBase::wt_Node ||
+ wt == WidgetBase::wt_Component || wt == WidgetBase::wt_Artifact ||
+ wt == WidgetBase::wt_Enum || wt == WidgetBase::wt_Entity ||
+ wt == WidgetBase::wt_Port ||
+ (wt == WidgetBase::wt_Class && umlScene()->type() == Uml::DiagramType::Class)) {
+
+ showPropertiesDialog();
+
+ } else if (wt == WidgetBase::wt_Object) {
+ m_umlObject->showPropertiesDialog();
+ } else {
+ uWarning() << "making properties dialog for unknown widget type";
+ }
+ break;
+
+ case ListPopupMenu::mt_Line_Color:
+ case ListPopupMenu::mt_Line_Color_Selection:
+#if QT_VERSION >= 0x050000
+ newColor = QColorDialog::getColor(lineColor());
+ if (newColor != lineColor()) {
+#else
+ newColor = lineColor();
+ if (KColorDialog::getColor(newColor)) {
+#endif
+ if (sel == ListPopupMenu::mt_Line_Color_Selection) {
+ umlScene()->selectionSetLineColor(newColor);
+ } else {
+ setLineColor(newColor);
+ }
+ setUsesDiagramLineColor(false);
+ umlDoc()->setModified(true);
+ }
+ break;
+
+ case ListPopupMenu::mt_Fill_Color:
+ case ListPopupMenu::mt_Fill_Color_Selection:
+#if QT_VERSION >= 0x050000
+ newColor = QColorDialog::getColor(fillColor());
+ if (newColor != fillColor()) {
+#else
+ newColor = fillColor();
+ if (KColorDialog::getColor(newColor)) {
+#endif
+ if (sel == ListPopupMenu::mt_Fill_Color_Selection) {
+ umlScene()->selectionSetFillColor(newColor);
+ } else {
+ setFillColor(newColor);
+ }
+ umlDoc()->setModified(true);
+ }
+ break;
+
+ case ListPopupMenu::mt_Use_Fill_Color:
+ setUseFillColor(!m_useFillColor);
+ break;
+
+ case ListPopupMenu::mt_Set_Use_Fill_Color_Selection:
+ umlScene()->selectionUseFillColor(true);
+ break;
+
+ case ListPopupMenu::mt_Unset_Use_Fill_Color_Selection:
+ umlScene()->selectionUseFillColor(false);
+ break;
+
+ case ListPopupMenu::mt_Show_Attributes_Selection:
+ case ListPopupMenu::mt_Hide_Attributes_Selection:
+ umlScene()->selectionSetVisualProperty(
+ ClassifierWidget::ShowAttributes, sel != ListPopupMenu::mt_Hide_Attributes_Selection
+ );
+ break;
+
+ case ListPopupMenu::mt_Show_Operations_Selection:
+ case ListPopupMenu::mt_Hide_Operations_Selection:
+ umlScene()->selectionSetVisualProperty(
+ ClassifierWidget::ShowOperations, sel != ListPopupMenu::mt_Hide_Operations_Selection
+ );
+ break;
+
+ case ListPopupMenu::mt_Show_Visibility_Selection:
+ case ListPopupMenu::mt_Hide_Visibility_Selection:
+ umlScene()->selectionSetVisualProperty(
+ ClassifierWidget::ShowVisibility, sel != ListPopupMenu::mt_Hide_Visibility_Selection
+ );
+ break;
+
+ case ListPopupMenu::mt_Show_Operation_Signature_Selection:
+ case ListPopupMenu::mt_Hide_Operation_Signature_Selection:
+ umlScene()->selectionSetVisualProperty(
+ ClassifierWidget::ShowOperationSignature, sel != ListPopupMenu::mt_Hide_Operation_Signature_Selection
+ );
+ break;
+
+ case ListPopupMenu::mt_Show_Attribute_Signature_Selection:
+ case ListPopupMenu::mt_Hide_Attribute_Signature_Selection:
+ umlScene()->selectionSetVisualProperty(
+ ClassifierWidget::ShowAttributeSignature, sel != ListPopupMenu::mt_Hide_Attribute_Signature_Selection
+ );
+ break;
+
+ case ListPopupMenu::mt_Show_Packages_Selection:
+ case ListPopupMenu::mt_Hide_Packages_Selection:
+ umlScene()->selectionSetVisualProperty(
+ ClassifierWidget::ShowPackage, sel != ListPopupMenu::mt_Hide_Packages_Selection
+ );
+ break;
+
+ case ListPopupMenu::mt_Show_Stereotypes_Selection:
+ case ListPopupMenu::mt_Hide_Stereotypes_Selection:
+ umlScene()->selectionSetVisualProperty(
+ ClassifierWidget::ShowStereotype, sel != ListPopupMenu::mt_Hide_Stereotypes_Selection
+ );
+ break;
+
+ case ListPopupMenu::mt_Hide_NonPublic_Selection:
+ case ListPopupMenu::mt_Show_NonPublic_Selection:
+ umlScene()->selectionSetVisualProperty(
+ ClassifierWidget::ShowPublicOnly, sel != ListPopupMenu::mt_Show_NonPublic_Selection
+ );
+ break;
+
+
+ case ListPopupMenu::mt_ViewCode: {
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(umlObject());
+ if (c) {
+ UMLApp::app()->viewCodeDocument(c);
+ }
+ break;
+ }
+
+ case ListPopupMenu::mt_Delete:
+ umlScene()->deleteSelection();
+ break;
+
+ case ListPopupMenu::mt_Change_Font:
+ case ListPopupMenu::mt_Change_Font_Selection: {
+#if QT_VERSION >= 0x050000
+ bool ok = false;
+ QFont newFont = QFontDialog::getFont(&ok, font());
+ if (ok) {
+#else
+ QFont newFont = font();
+ if (KFontDialog::getFont(newFont, KFontChooser::NoDisplayFlags, 0) == KFontDialog::Accepted) {
+#endif
+ if (sel == ListPopupMenu::mt_Change_Font_Selection) {
+ m_scene->selectionSetFont(newFont);
+ } else {
+ setFont(newFont);
+ }
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Cut:
+ umlScene()->setStartedCut();
+ UMLApp::app()->slotEditCut();
+ break;
+
+ case ListPopupMenu::mt_Copy:
+ UMLApp::app()->slotEditCopy();
+ break;
+
+ case ListPopupMenu::mt_Paste:
+ UMLApp::app()->slotEditPaste();
+ break;
+
+ case ListPopupMenu::mt_Refactoring:
+ //check if we are operating on a classifier, or some other kind of UMLObject
+ if (dynamic_cast<UMLClassifier*>(umlObject())) {
+ UMLApp::app()->refactor(static_cast<UMLClassifier*>(umlObject()));
+ }
+ break;
+
+ case ListPopupMenu::mt_Clone:
+ {
+ foreach (UMLWidget* widget, umlScene()->selectedWidgets()) {
+ if (Model_Utils::isCloneable(widget->baseType())) {
+ UMLObject *clone = widget->umlObject()->clone();
+ umlScene()->addObject(clone);
+ }
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Rename_MultiA:
+ case ListPopupMenu::mt_Rename_MultiB:
+ case ListPopupMenu::mt_Rename_Name:
+ case ListPopupMenu::mt_Rename_RoleAName:
+ case ListPopupMenu::mt_Rename_RoleBName: {
+ FloatingTextWidget *ft = static_cast<FloatingTextWidget*>(this);
+ ft->handleRename();
+ break;
+ }
+ case ListPopupMenu::mt_Align_Right:
+ umlScene()->alignRight();
+ break;
+ case ListPopupMenu::mt_Align_Left:
+ umlScene()->alignLeft();
+ break;
+ case ListPopupMenu::mt_Align_Top:
+ umlScene()->alignTop();
+ break;
+ case ListPopupMenu::mt_Align_Bottom:
+ umlScene()->alignBottom();
+ break;
+ case ListPopupMenu::mt_Align_VerticalMiddle:
+ umlScene()->alignVerticalMiddle();
+ break;
+ case ListPopupMenu::mt_Align_HorizontalMiddle:
+ umlScene()->alignHorizontalMiddle();
+ break;
+ case ListPopupMenu::mt_Align_VerticalDistribute:
+ umlScene()->alignVerticalDistribute();
+ break;
+ case ListPopupMenu::mt_Align_HorizontalDistribute:
+ umlScene()->alignHorizontalDistribute();
+ break;
+ default:
+ uDebug() << "MenuType " << ListPopupMenu::toString(sel) << " not implemented";
+ break;
+ }
+}
+
+/**
+ * Helper function for debug output.
+ * Returns the given enum value as string.
+ * @param wt WidgetType of which a string representation is wanted
+ * @return the WidgetType as string
+ */
+QString WidgetBase::toString(WidgetType wt)
+{
+ return QLatin1String(ENUM_NAME(WidgetBase, WidgetType, wt));
+}
+
+/**
+ * Returns the given enum value as localized string.
+ * @param wt WidgetType of which a string representation is wanted
+ * @return the WidgetType as localized string
+ */
+QString WidgetBase::toI18nString(WidgetType wt)
+{
+ QString name;
+
+ switch (wt) {
+ case wt_Activity:
+ name = i18n("Activity");
+ break;
+ case wt_Actor:
+ name = i18n("Actor");
+ break;
+ case wt_Artifact:
+ name = i18n("Artifact");
+ break;
+ case wt_Association:
+ name = i18n("Association");
+ break;
+ case wt_Box:
+ name = i18n("Box");
+ break;
+ case wt_Category:
+ name = i18n("Category");
+ break;
+ case wt_CombinedFragment:
+ name = i18n("CombinedFragment");
+ break;
+ case wt_Component:
+ name = i18n("Component");
+ break;
+ case wt_Class:
+ name = i18n("Class");
+ break;
+ case wt_Datatype:
+ name = i18n("Datatype");
+ break;
+ case wt_Entity:
+ name = i18n("Entity");
+ break;
+ case wt_Enum:
+ name = i18n("Enum");
+ break;
+ case wt_FloatingDashLine:
+ name = i18n("FloatingDashLine");
+ break;
+ case wt_ForkJoin:
+ name = i18n("ForkJoin");
+ break;
+ case wt_Interface:
+ name = i18n("Interface");
+ break;
+ case wt_Message:
+ name = i18n("Message");
+ break;
+ case wt_Node:
+ name = i18n("Node");
+ break;
+ case wt_Note:
+ name = i18n("Note");
+ break;
+ case wt_Object:
+ name = i18n("Object");
+ break;
+ case wt_ObjectNode:
+ name = i18n("ObjectNode");
+ break;
+ case wt_Package:
+ name = i18n("Package");
+ break;
+ case wt_Pin:
+ name = i18n("Pin");
+ break;
+ case wt_Port:
+ name = i18n("Port");
+ break;
+ case wt_Precondition:
+ name = i18n("Precondition");
+ break;
+ case wt_Region:
+ name = i18n("Region");
+ break;
+ case wt_Signal:
+ name = i18n("Signal");
+ break;
+ case wt_State:
+ name = i18n("State");
+ break;
+ case wt_Text:
+ name = i18n("Text");
+ break;
+ case wt_UseCase:
+ name = i18n("UseCase");
+ break;
+ default:
+ name = QLatin1String("<unknown> &name:");
+ uWarning() << "unknown widget type";
+ break;
+ }
+ return name;
+}
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widgetbase.h umbrello-kf6-15.08.1/umbrello/umlwidgets/widgetbase.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widgetbase.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/widgetbase.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,192 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef WIDGETBASE_H
+#define WIDGETBASE_H
+
+#include "basictypes.h"
+
+#include <QColor>
+#include <QDomDocument>
+#include <QFont>
+#include <QGraphicsObject>
+#include <QObject>
+#include <QPainter>
+
+// forward declarations
+class QAction;
+class UMLDoc;
+class UMLObject;
+class UMLScene;
+class UMLWidget; // required by function onWidget()
+
+/**
+ * @short Common base class for UMLWidget and AssociationWidget
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+class WidgetBase : public QGraphicsObject
+{
+ Q_OBJECT
+ Q_ENUMS(WidgetType)
+
+public:
+ enum WidgetType
+ {
+ wt_UMLWidget = 300, // does not have UMLObject representation
+ wt_Actor, // has UMLObject representation
+ wt_UseCase, // has UMLObject representation
+ wt_Class, // has UMLObject representation
+ wt_Interface, // has UMLObject representation
+ wt_Datatype, // has UMLObject representation
+ wt_Enum, // has UMLObject representation
+ wt_Entity, // has UMLObject representation
+ wt_Package, // has UMLObject representation
+ wt_Object, // has UMLObject representation
+ wt_Note, // does not have UMLObject representation
+ wt_Box, // does not have UMLObject representation
+ wt_Message, // does not have UMLObject representation
+ wt_Text, // does not have UMLObject representation
+ wt_State, // does not have UMLObject representation
+ wt_Activity, // does not have UMLObject representation
+ wt_Component, // has UMLObject representation
+ wt_Artifact, // has UMLObject representation
+ wt_Node, // has UMLObject representation
+ wt_Association, // has UMLObject representation
+ wt_ForkJoin, // does not have UMLObject representation
+ wt_Precondition, // does not have UMLObject representation
+ wt_CombinedFragment, // does not have UMLObject representation
+ wt_FloatingDashLine, // does not have UMLObject representation
+ wt_Signal, // does not have UMLObject representation
+ wt_Pin,
+ wt_ObjectNode,
+ wt_Region,
+ wt_Category, // has UMLObject representation
+ wt_Port // has UMLObject representation
+ };
+
+ static QString toString(WidgetType wt);
+ static QString toI18nString(WidgetType wt);
+
+ explicit WidgetBase(UMLScene * scene, WidgetType type= wt_UMLWidget);
+ virtual ~WidgetBase();
+
+ UMLObject* umlObject() const;
+ virtual void setUMLObject(UMLObject *obj);
+
+ Uml::ID::Type id() const;
+ void setID(Uml::ID::Type id);
+
+ WidgetType baseType() const;
+ QLatin1String baseTypeStr() const;
+
+ virtual void setSelected(bool select);
+
+ UMLScene* umlScene() const;
+ UMLDoc* umlDoc() const;
+
+ QString documentation() const;
+ bool hasDocumentation();
+ virtual void setDocumentation(const QString& doc);
+
+ QString name() const;
+ virtual void setName(const QString &strName);
+
+ QColor lineColor() const;
+ virtual void setLineColor(const QColor& color);
+
+ uint lineWidth() const;
+ virtual void setLineWidth(uint width);
+
+ QColor textColor() const;
+ virtual void setTextColor(const QColor& color);
+
+ QColor fillColor() const;
+ virtual void setFillColor(const QColor& color);
+
+ bool usesDiagramLineColor() const;
+ void setUsesDiagramLineColor(bool state);
+
+ bool usesDiagramLineWidth() const;
+ void setUsesDiagramLineWidth(bool state);
+
+ bool useFillColor();
+ virtual void setUseFillColor(bool state);
+
+ bool usesDiagramTextColor() const;
+ void setUsesDiagramTextColor(bool state);
+
+ bool usesDiagramFillColor() const;
+ void setUsesDiagramFillColor(bool state);
+
+ bool usesDiagramUseFillColor() const;
+ void setUsesDiagramUseFillColor(bool state);
+
+ virtual QFont font() const;
+ virtual void setFont(const QFont& font);
+
+ virtual void showPropertiesDialog();
+
+ virtual bool loadFromXMI(QDomElement &qElement);
+ virtual void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
+
+ WidgetBase& operator=(const WidgetBase& other);
+
+ QRectF rect() const;
+ void setRect(const QRectF& rect);
+ void setRect(qreal x, qreal y, qreal width, qreal height);
+
+ virtual QRectF boundingRect() const;
+
+ virtual UMLWidget* onWidget(const QPointF &p);
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+public Q_SLOTS:
+ virtual void slotMenuSelection(QAction *trigger);
+
+protected:
+ virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
+
+ WidgetType m_baseType; ///< Type of widget.
+ UMLScene *m_scene;
+ UMLObject *m_umlObject;
+ QString m_Doc; ///< Only used if m_umlObject is not set.
+ QString m_Text;
+ QRectF m_rect; ///< widget size
+
+ /**
+ * This ID is only used when the widget does not have a
+ * corresponding UMLObject (i.e. the m_umlObject pointer is NULL.)
+ * For UMLObjects, the ID from the UMLObject is used.
+ */
+ Uml::ID::Type m_nId;
+
+ QColor m_textColor; ///< Color of the text of the widget. Is saved to XMI.
+ QColor m_lineColor; ///< Color of the lines of the widget. Is saved to XMI.
+ QColor m_fillColor; ///< color of the background of the widget
+ QBrush m_brush;
+ QFont m_font;
+ uint m_lineWidth; ///< Width of the lines of the widget. Is saved to XMI.
+ bool m_useFillColor; ///< flag indicates if the UMLWidget uses the Diagram FillColour
+
+ /**
+ * true by default, false if the colors have
+ * been explicitly set for this widget.
+ * These are saved to XMI.
+ */
+ bool m_usesDiagramTextColor;
+ bool m_usesDiagramLineColor;
+ bool m_usesDiagramFillColor;
+ bool m_usesDiagramUseFillColor;
+ bool m_usesDiagramLineWidth;
+};
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widget_factory.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/widget_factory.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widget_factory.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/widget_factory.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,298 @@
+/***************************************************************************
+ * 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) 2006-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "widget_factory.h"
+
+// app includes
+#include "activitywidget.h"
+#include "actor.h"
+#include "actorwidget.h"
+#include "artifact.h"
+#include "artifactwidget.h"
+#include "associationwidget.h"
+#include "boxwidget.h"
+#include "category.h"
+#include "categorywidget.h"
+#include "classifier.h"
+#include "classifierwidget.h"
+#include "cmds.h"
+#include "combinedfragmentwidget.h"
+#include "component.h"
+#include "componentwidget.h"
+#include "datatypewidget.h"
+#include "debug_utils.h"
+#include "entity.h"
+#include "entitywidget.h"
+#include "enum.h"
+#include "enumwidget.h"
+#include "floatingdashlinewidget.h"
+#include "floatingtextwidget.h"
+#include "folder.h"
+#include "forkjoinwidget.h"
+#include "messagewidget.h"
+#include "node.h"
+#include "nodewidget.h"
+#include "notewidget.h"
+#include "object_factory.h"
+#include "objectnodewidget.h"
+#include "objectwidget.h"
+#include "package.h"
+#include "packagewidget.h"
+#include "pinwidget.h"
+#include "port.h"
+#include "portwidget.h"
+#include "preconditionwidget.h"
+#include "regionwidget.h"
+#include "signalwidget.h"
+#include "statewidget.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlscene.h"
+#include "umlview.h"
+#include "usecase.h"
+#include "usecasewidget.h"
+
+namespace Widget_Factory {
+
+/**
+ * Create a UMLWidget in the given view and representing the given document object.
+ */
+UMLWidget *createWidget(UMLScene *scene, UMLObject *o)
+{
+ QPointF pos = scene->pos();
+ int y = pos.y();
+ Uml::DiagramType::Enum diagramType = scene->type();
+ UMLObject::ObjectType type = o->baseType();
+ UMLWidget *newWidget = NULL;
+ switch (type) {
+ case UMLObject::ot_Actor:
+ if (diagramType == Uml::DiagramType::Sequence) {
+ ObjectWidget *ow = new ObjectWidget(scene, o);
+ ow->setDrawAsActor(true);
+ y = ow->topMargin();
+ newWidget = ow;
+ } else
+ newWidget = new ActorWidget(scene, static_cast<UMLActor*>(o));
+ break;
+ case UMLObject::ot_UseCase:
+ newWidget = new UseCaseWidget(scene, static_cast<UMLUseCase*>(o));
+ break;
+ case UMLObject::ot_Folder:
+ newWidget = new PackageWidget(scene, static_cast<UMLPackage*>(o));
+ break;
+ case UMLObject::ot_Package:
+ newWidget = new ClassifierWidget(scene, static_cast<UMLPackage*>(o));
+ break;
+ case UMLObject::ot_Component:
+ newWidget = new ComponentWidget(scene, static_cast<UMLComponent*>(o));
+ if (diagramType == Uml::DiagramType::Deployment) {
+ newWidget->setIsInstance(true);
+ }
+ break;
+ case UMLObject::ot_Port:
+ {
+ PinPortBase *pw = new PortWidget(scene, static_cast<UMLPort*>(o));
+ pw->attachToOwner();
+ newWidget = pw;
+ }
+ break;
+ case UMLObject::ot_Node:
+ newWidget = new NodeWidget(scene, static_cast<UMLNode*>(o));
+ break;
+ case UMLObject::ot_Artifact:
+ newWidget = new ArtifactWidget(scene, static_cast<UMLArtifact*>(o));
+ break;
+ case UMLObject::ot_Datatype:
+ newWidget = new DatatypeWidget(scene, static_cast<UMLClassifier*>(o));
+ break;
+ case UMLObject::ot_Enum:
+ newWidget = new EnumWidget(scene, static_cast<UMLEnum*>(o));
+ break;
+ case UMLObject::ot_Entity:
+ newWidget = new EntityWidget(scene, static_cast<UMLEntity*>(o));
+ break;
+ case UMLObject::ot_Interface:
+ if (diagramType == Uml::DiagramType::Sequence || diagramType == Uml::DiagramType::Collaboration) {
+ ObjectWidget *ow = new ObjectWidget(scene, o);
+ if (diagramType == Uml::DiagramType::Sequence) {
+ y = ow->topMargin();
+ }
+ newWidget = ow;
+ } else {
+ UMLClassifier *c = static_cast<UMLClassifier*>(o);
+ ClassifierWidget* interfaceWidget = new ClassifierWidget(scene, c);
+ if (diagramType == Uml::DiagramType::Component || diagramType == Uml::DiagramType::Deployment) {
+ interfaceWidget->setDrawAsCircle(true);
+ }
+ newWidget = interfaceWidget;
+ }
+ break;
+ case UMLObject::ot_Class:
+ //see if we really want an object widget or class widget
+ if (diagramType == Uml::DiagramType::Class || diagramType == Uml::DiagramType::Component) {
+ UMLClassifier *c = static_cast<UMLClassifier*>(o);
+ ClassifierWidget *cw = new ClassifierWidget(scene, c);
+ if (diagramType == Uml::DiagramType::Component)
+ cw->setDrawAsCircle(true);
+ newWidget = cw;
+ } else {
+ ObjectWidget *ow = new ObjectWidget(scene, o);
+ if (diagramType == Uml::DiagramType::Sequence) {
+ y = ow->topMargin();
+ }
+ newWidget = ow;
+ }
+ break;
+ case UMLObject::ot_Category:
+ newWidget = new CategoryWidget(scene, static_cast<UMLCategory*>(o));
+ break;
+ default:
+ uWarning() << "trying to create an invalid widget (" << UMLObject::toString(type) << ")";
+ }
+
+ if (newWidget) {
+ newWidget->setX(pos.x());
+ newWidget->setY(y);
+ }
+
+ return newWidget;
+}
+
+bool validateObjType(UMLObject::ObjectType expected, UMLObject* &o, Uml::ID::Type id)
+{
+ if (o == NULL) {
+ uDebug() << "Widget_Factory::validateObjType: creating new object of type "
+ << expected;
+ QString artificialName = QLatin1String("LOST_") + Uml::ID::toString(id);
+ o = Object_Factory::createUMLObject(expected, artificialName, NULL, false);
+ if (o == NULL)
+ return false;
+ o->setID(id);
+ UMLPackage *parentPkg = o->umlPackage();
+ parentPkg->addObject(o);
+ return true;
+ }
+ UMLObject::ObjectType actual = o->baseType();
+ if (actual == expected)
+ return true;
+ uError() << "validateObjType(" << o->name()
+ << "): expected type " << UMLObject::toString(expected) << ", actual type "
+ << UMLObject::toString(actual);
+ return false;
+}
+
+/**
+ * Create a UMLWidget according to the given XMI tag.
+ */
+UMLWidget* makeWidgetFromXMI(const QString& tag,
+ const QString& idStr, UMLScene *scene)
+{
+ UMLWidget *widget = NULL;
+
+ // Loading of widgets which do NOT represent any UMLObject,
+ // just graphic stuff with no real model information
+ //FIXME while boxes and texts are just diagram objects, activities and
+ // states should be UMLObjects
+ if (tag == QLatin1String("statewidget") || tag == QLatin1String("UML:StateWidget")) {
+ widget = new StateWidget(scene, StateWidget::Normal, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("notewidget") || tag == QLatin1String("UML:NoteWidget")) {
+ widget = new NoteWidget(scene, NoteWidget::Normal, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("boxwidget")) {
+ widget = new BoxWidget(scene, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("floatingtext") || tag == QLatin1String("UML:FloatingTextWidget")) {
+ widget = new FloatingTextWidget(scene, Uml::TextRole::Floating, QString(), Uml::ID::Reserved);
+ } else if (tag == QLatin1String("activitywidget") || tag == QLatin1String("UML:ActivityWidget")) {
+ widget = new ActivityWidget(scene, ActivityWidget::Initial, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("messagewidget")) {
+ widget = new MessageWidget(scene, Uml::SequenceMessage::Asynchronous, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("forkjoin")) {
+ widget = new ForkJoinWidget(scene, Qt::Vertical, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("preconditionwidget")) {
+ widget = new PreconditionWidget(scene, NULL, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("combinedFragmentwidget")) {
+ widget = new CombinedFragmentWidget(scene, CombinedFragmentWidget::Ref, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("signalwidget")) {
+ widget = new SignalWidget(scene, SignalWidget::Send, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("floatingdashlinewidget")) {
+ widget = new FloatingDashLineWidget(scene, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("objectnodewidget")) {
+ widget = new ObjectNodeWidget(scene, ObjectNodeWidget::Normal, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("regionwidget")) {
+ widget = new RegionWidget(scene, Uml::ID::Reserved);
+ } else if (tag == QLatin1String("pinwidget")) {
+ PinPortBase *pw = new PinWidget(scene, NULL, Uml::ID::Reserved);
+ pw->attachToOwner();
+ widget = pw;
+ }
+ else
+ {
+ // Loading of widgets which represent an UMLObject
+
+ // Find the UMLObject and create the Widget to represent it
+ Uml::ID::Type id = Uml::ID::fromString(idStr);
+ UMLDoc *umldoc = UMLApp::app()->document();
+ UMLObject *o = umldoc->findObjectById(id);
+ if (o == NULL) {
+ uDebug() << "makeWidgetFromXMI: cannot find object with id "
+ << Uml::ID::toString(id);
+ }
+
+ if (tag == QLatin1String("actorwidget") || tag == QLatin1String("UML:ActorWidget")) {
+ if (validateObjType(UMLObject::ot_Actor, o, id))
+ widget = new ActorWidget(scene, static_cast<UMLActor*>(o));
+ } else if (tag == QLatin1String("usecasewidget") || tag == QLatin1String("UML:UseCaseWidget")) {
+ if (validateObjType(UMLObject::ot_UseCase, o, id))
+ widget = new UseCaseWidget(scene, static_cast<UMLUseCase*>(o));
+ } else if (tag == QLatin1String("classwidget") ||
+ tag == QLatin1String("UML:ClassWidget") || tag == QLatin1String("UML:ConceptWidget")) {
+ if (validateObjType(UMLObject::ot_Class, o, id) || validateObjType(UMLObject::ot_Package, o, id))
+ widget = new ClassifierWidget(scene, static_cast<UMLClassifier*>(o));
+ } else if (tag == QLatin1String("packagewidget")) {
+ if (validateObjType(UMLObject::ot_Package, o, id))
+ widget = new ClassifierWidget(scene, static_cast<UMLPackage*>(o));
+ } else if (tag == QLatin1String("componentwidget")) {
+ if (validateObjType(UMLObject::ot_Component, o, id))
+ widget = new ComponentWidget(scene, static_cast<UMLComponent*>(o));
+ } else if (tag == QLatin1String("portwidget")) {
+ if (validateObjType(UMLObject::ot_Port, o, id))
+ widget = new PortWidget(scene, static_cast<UMLPort*>(o));
+ } else if (tag == QLatin1String("nodewidget")) {
+ if (validateObjType(UMLObject::ot_Node, o, id))
+ widget = new NodeWidget(scene, static_cast<UMLNode*>(o));
+ } else if (tag == QLatin1String("artifactwidget")) {
+ if (validateObjType(UMLObject::ot_Artifact, o, id))
+ widget = new ArtifactWidget(scene, static_cast<UMLArtifact*>(o));
+ } else if (tag == QLatin1String("interfacewidget")) {
+ if (validateObjType(UMLObject::ot_Interface, o, id))
+ widget = new ClassifierWidget(scene, static_cast<UMLClassifier*>(o));
+ } else if (tag == QLatin1String("datatypewidget")) {
+ if (validateObjType(UMLObject::ot_Datatype, o, id))
+ widget = new DatatypeWidget(scene, static_cast<UMLClassifier*>(o));
+ } else if (tag == QLatin1String("enumwidget")) {
+ if (validateObjType(UMLObject::ot_Enum, o, id))
+ widget = new EnumWidget(scene, static_cast<UMLEnum*>(o));
+ } else if (tag == QLatin1String("entitywidget")) {
+ if (validateObjType(UMLObject::ot_Entity, o, id))
+ widget = new EntityWidget(scene, static_cast<UMLEntity*>(o));
+ } else if (tag == QLatin1String("categorywidget")) {
+ if (validateObjType(UMLObject::ot_Category, o, id))
+ widget = new CategoryWidget(scene, static_cast<UMLCategory*>(o));
+ } else if (tag == QLatin1String("objectwidget") || tag == QLatin1String("UML:ObjectWidget")) {
+ widget = new ObjectWidget(scene, o);
+ } else {
+ uWarning() << "Trying to create an unknown widget:" << tag;
+ }
+ }
+ return widget;
+}
+
+} // end namespace Widget_Factory
+
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widget_factory.h umbrello-kf6-15.08.1/umbrello/umlwidgets/widget_factory.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widget_factory.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/widget_factory.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * 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) 2006-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef WIDGET_FACTORY_H
+#define WIDGET_FACTORY_H
+
+#include <QString>
+
+// forward declarations
+class UMLObject;
+class UMLScene;
+class UMLWidget;
+
+/**
+ * Widget factory methods.
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+namespace Widget_Factory {
+
+ UMLWidget *createWidget(UMLScene *scene, UMLObject *docObj);
+
+ UMLWidget* makeWidgetFromXMI(const QString& tag,
+ const QString& idStr, UMLScene *scene);
+
+} // end namespace Widget_Factory
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widgetlist_utils.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/widgetlist_utils.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widgetlist_utils.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/widgetlist_utils.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,157 @@
+/***************************************************************************
+ * 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) 2009-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "widgetlist_utils.h"
+
+// app includes
+#include "debug_utils.h"
+#include "umlwidget.h"
+
+// qt/kde includes
+#include <QVector>
+
+namespace WidgetList_Utils
+{
+
+/**
+ * Looks for the smallest x-value of the given UMLWidgets.
+ * @param widgetList A list with UMLWidgets.
+ * @return The smallest X position.
+ */
+qreal getSmallestX(const UMLWidgetList &widgetList)
+{
+ qreal smallestX = 0;
+
+ int i = 1;
+ foreach(UMLWidget *widget, widgetList) {
+ if (i == 1) {
+ smallestX = widget->x();
+ } else {
+ if (smallestX > widget->x())
+ smallestX = widget->x();
+ }
+ i++;
+ }
+
+ return smallestX;
+}
+
+/**
+ * Looks for the smallest y-value of the given UMLWidgets.
+ * @param widgetList A list with UMLWidgets.
+ * @return The smallest Y position.
+ */
+qreal getSmallestY(const UMLWidgetList &widgetList)
+{
+ if (widgetList.isEmpty())
+ return -1;
+
+ qreal smallestY = 0;
+
+ int i = 1;
+ foreach(UMLWidget *widget, widgetList) {
+ if (i == 1) {
+ smallestY = widget->y();
+ } else {
+ if (smallestY > widget->y())
+ smallestY = widget->y();
+ }
+ i++;
+ }
+
+ return smallestY;
+}
+
+/**
+ * Looks for the biggest x-value of the given UMLWidgets.
+ * @param widgetList A list with UMLWidgets.
+ * @return The biggest X position.
+ */
+qreal getBiggestX(const UMLWidgetList &widgetList)
+{
+ if (widgetList.isEmpty())
+ return -1;
+
+ qreal biggestX = 0;
+
+ int i = 1;
+ foreach(UMLWidget *widget, widgetList) {
+ if (i == 1) {
+ biggestX = widget->x();
+ biggestX += widget->width();
+ } else {
+ if (biggestX < widget->x() + widget->width())
+ biggestX = widget->x() + widget->width();
+ }
+ i++;
+ }
+
+ return biggestX;
+}
+
+/**
+ * Looks for the biggest y-value of the given UMLWidgets.
+ * @param widgetList A list with UMLWidgets.
+ * @return The biggest Y position.
+ */
+qreal getBiggestY(const UMLWidgetList &widgetList)
+{
+ if (widgetList.isEmpty())
+ return -1;
+
+ qreal biggestY = 0;
+
+ int i = 1;
+ foreach(UMLWidget *widget, widgetList) {
+ if (i == 1) {
+ biggestY = widget->y();
+ biggestY += widget->height();
+ } else {
+ if (biggestY < widget->y() + widget->height())
+ biggestY = widget->y() + widget->height();
+ }
+ i++;
+ }
+
+ return biggestY;
+}
+
+/**
+ * Returns the sum of the heights of the given UMLWidgets
+ * @param widgetList A list with UMLWidgets.
+ */
+qreal getHeightsSum(const UMLWidgetList &widgetList)
+{
+ qreal heightsSum = 0;
+
+ foreach(UMLWidget *widget, widgetList) {
+ heightsSum += widget->height();
+ }
+
+ return heightsSum;
+}
+
+/**
+ * Returns the sum of the widths of the given UMLWidgets.
+ * @param widgetList A list with UMLWidgets.
+ */
+qreal getWidthsSum(const UMLWidgetList &widgetList)
+{
+ qreal widthsSum = 0;
+
+ foreach(UMLWidget *widget, widgetList) {
+ widthsSum += widget->width();
+ }
+
+ return widthsSum;
+}
+
+} // namespace WidgetList_Utils
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widgetlist_utils.h umbrello-kf6-15.08.1/umbrello/umlwidgets/widgetlist_utils.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widgetlist_utils.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/widgetlist_utils.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,30 @@
+/***************************************************************************
+ * 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) 2009-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef WIDGETLIST_UTILS_H
+#define WIDGETLIST_UTILS_H
+
+#include "umlwidgetlist.h"
+
+/**
+ * General purpose-kf6 widget list utilities.
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+namespace WidgetList_Utils
+{
+ qreal getSmallestX(const UMLWidgetList &widgetList);
+ qreal getSmallestY(const UMLWidgetList &widgetList);
+ qreal getBiggestX(const UMLWidgetList &widgetList);
+ qreal getBiggestY(const UMLWidgetList &widgetList);
+ qreal getHeightsSum(const UMLWidgetList &widgetList);
+ qreal getWidthsSum(const UMLWidgetList &widgetList);
+} // namespace WidgetList_Utils
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widget_utils.cpp umbrello-kf6-15.08.1/umbrello/umlwidgets/widget_utils.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widget_utils.cpp 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/widget_utils.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +1,827 @@
+/***************************************************************************
+ * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+// own header
+#include "widget_utils.h"
+
+// app includes
+#include "debug_utils.h"
+#include "objectwidget.h"
+#include "messagewidget.h"
+#include "umlwidget.h"
+
+// qt includes
+#include <QBuffer>
+#include <QImageReader>
+#include <QGraphicsItem>
+#include <QGraphicsRectItem>
+#include <QPolygonF>
+
+// c++ include
+#include <cmath>
+
+namespace Widget_Utils
+{
+
+ /**
+ * Find the widget identified by the given ID in the given widget
+ * or message list.
+ *
+ * @param id The unique ID to find.
+ * @param widgets The UMLWidgetList to search in.
+ * @param messages Optional pointer to a MessageWidgetList to search in.
+ */
+ UMLWidget* findWidget(Uml::ID::Type id,
+ const UMLWidgetList& widgets,
+ const MessageWidgetList* messages /* = 0 */)
+ {
+ foreach (UMLWidget* obj, widgets) {
+ if (obj->baseType() == WidgetBase::wt_Object) {
+ if (static_cast<ObjectWidget *>(obj)->localID() == id)
+ return obj;
+ } else if (obj->id() == id) {
+ return obj;
+ }
+ }
+
+ if (messages) {
+ foreach (UMLWidget* obj, *messages) {
+ if (obj->id() == id)
+ return obj;
+ }
+ }
+ return NULL;
+ }
+
+ /**
+ * Creates the decoration point.
+ * @param p base point to decorate
+ * @param parent parent item
+ * @return decoration point
+ */
+ QGraphicsRectItem* decoratePoint(const QPointF &p, QGraphicsItem* parent)
+ {
+ const qreal SIZE = 4.0;
+ const qreal SIZE_HALF = SIZE / 2.0;
+ QGraphicsRectItem *rect = new QGraphicsRectItem(p.x() - SIZE_HALF,
+ p.y() - SIZE_HALF,
+ SIZE, SIZE,
+ parent);
+ rect->setBrush(QBrush(Qt::blue));
+ rect->setPen(QPen(Qt::blue));
+ return rect;
+ }
+
+ /**
+ * Calculates and draws a cross inside an ellipse
+ * @param p Pointer to a QPainter object.
+ * @param r The rectangle describing the ellipse.
+ */
+ void drawCrossInEllipse(QPainter *p, const QRectF& r)
+ {
+ QRectF ellipse = r;
+ ellipse.moveCenter(QPointF(0, 0));
+ qreal a = ellipse.width() * 0.5;
+ qreal b = ellipse.height() * .5;
+ qreal xc = ellipse.center().x();
+ qreal yc = ellipse.center().y();
+
+ // The first point's x value is chosen to be center.x() + 70% of x radius.
+ qreal x1 = ellipse.center().x() + .7 * .5 * ellipse.width();
+ // Calculate y1 corresponding to x1 using formula.
+ qreal y1_sqr = b*b*(1 - (x1 * x1) / (a*a));
+ qreal y1 = std::sqrt(y1_sqr);
+
+ // Mirror x1, y1 along both the axes to get 4 points for the cross.
+ QPointF p1(xc + x1, yc + y1);
+ QPointF p2(xc - x1, yc + y1);
+ QPointF p3(xc + x1, yc - y1);
+ QPointF p4(xc - x1, yc - y1);
+
+ // Translate as we calculate for ellipse with (0, 0) as center.
+ p->translate(r.center().x(), r.center().y());
+
+ // Draw the cross now
+ p->drawLine(QLineF(p1, p4));
+ p->drawLine(QLineF(p2, p3));
+
+ // Restore the translate on painter.
+ p->translate(-r.center().x(), -r.center().y());
+ }
+
+ /**
+ * Draws a polygon which is almost rectangular except for the top
+ * right corner. A triangle is drawn in top right corner of the
+ * rectangle.
+ *
+ * @param painter The painter with which this shape is to be drawn.
+ * @param rect The rectangle dimensions.
+ * @param triSize The size of the triangle in the top-right corner.
+ */
+ void drawTriangledRect(QPainter *painter,
+ const QRectF &rect, const QSizeF &triSize)
+ {
+ // Draw outer boundary defined by polygon "poly".
+ QPolygonF poly(5);
+ poly[0] = rect.topLeft();
+ poly[1] = rect.topRight() - QPointF(triSize.width(), 0);
+ poly[2] = rect.topRight() + QPointF(0, triSize.height());
+ poly[3] = rect.bottomRight();
+ poly[4] = rect.bottomLeft();
+ painter->drawPolygon(poly);
+
+ // Now draw the triangle base and height edges.
+ QLineF heightEdge(poly[1], poly[1] + QPointF(0, triSize.height()));
+ painter->drawLine(heightEdge);
+ QLineF baseEdge(heightEdge.p2(), poly[2]);
+ painter->drawLine(baseEdge);
+ }
+
+// /**
+// * Draws an arrow head with the given painter, with the arrow
+// * sharp point at \a headPos.
+// *
+// * param painter The painter with which this arrow should be drawn.
+// * param headPos The position where the head of the arrow should lie.
+// * param arrowSize This indicates the size of the arrow head.
+// * param arrowType This indicates direction of arrow as in LeftArrow, RightArrow..
+// * param solid-kf6 If true, a solid-kf6 head is drawn. Otherwise 2 lines are drawn.
+// */
+// void drawArrowHead(QPainter *painter, const QPointF &arrowPos,
+// const QSizeF& arrowSize, Qt::ArrowType arrowType,
+// bool solid-kf6)
+// {
+// QPolygonF poly;
+// if (arrowType == Qt::LeftArrow) {
+// poly << QPointF(arrowPos.x() + arrowSize.width(), arrowPos.y() - .5 * arrowSize.height())
+// << arrowPos
+// << QPointF(arrowPos.x() + arrowSize.width(), arrowPos.y() + .5 * arrowSize.height());
+// }
+// else if (arrowType == Qt::RightArrow) {
+// poly << QPointF(arrowPos.x() - arrowSize.width(), arrowPos.y() - .5 * arrowSize.height())
+// << arrowPos
+// << QPointF(arrowPos.x() - arrowSize.width(), arrowPos.y() + .5 * arrowSize.height());
+// }
+
+// if (solid-kf6) {
+// painter->drawPolygon(poly);
+// }
+// else {
+// painter->drawPolyline(poly);
+// }
+// }
+
+// /**
+// * Draws a rounded rect rounded at specified corners.
+// *
+// * param painter The painter with which this round rect should be drawn.
+// * param rect The rectangle to be drawn.
+// * param xRadius The x radius of rounded corner.
+// * param yRadius The y radius of rounded corner.
+// * param corners The corners to be rounded.
+// */
+// void drawRoundedRect(QPainter *painter, const QRectF& rect, qreal xRadius,
+// qreal yRadius, Uml::Corners corners)
+// {
+// if (xRadius < 0 || yRadius < 0) {
+// painter->drawRect(rect);
+// return;
+// }
+// QRectF arcRect(0, 0, 2 * xRadius, 2 * yRadius);
+
+// QPainterPath path;
+// path.moveTo(rect.left(), rect.top() + yRadius);
+// if (corners.testFlag(Uml::Corner::TopLeft)) {
+// arcRect.moveTopLeft(rect.topLeft());
+// path.arcTo(arcRect, 180, -90);
+// } else {
+// path.lineTo(rect.topLeft());
+// }
+
+// path.lineTo(rect.right() - xRadius, rect.top());
+
+// if (corners.testFlag(Uml::Corner::TopRight)) {
+// arcRect.moveTopRight(rect.topRight());
+// path.arcTo(arcRect, 90, -90);
+// } else {
+// path.lineTo(rect.topRight());
+// }
+
+// path.lineTo(rect.right(), rect.bottom() - yRadius);
+
+// if (corners.testFlag(Uml::Corner::BottomRight)) {
+// arcRect.moveBottomRight(rect.bottomRight());
+// path.arcTo(arcRect, 0, -90);
+// } else {
+// path.lineTo(rect.bottomRight());
+// }
+
+// path.lineTo(rect.left() + xRadius, rect.bottom());
+
+// if (corners.testFlag(Uml::Corner::BottomLeft)) {
+// arcRect.moveBottomLeft(rect.bottomLeft());
+// path.arcTo(arcRect, 270, 90);
+// } else {
+// path.lineTo(rect.bottomLeft());
+// }
+
+// path.closeSubpath();
+// painter->drawPath(path);
+// }
+
+ /**
+ * Converts a point to a comma separated string i.e "x,y"
+ * @param point The QPointF to convert.
+ */
+ QString pointToString(const QPointF& point)
+ {
+ return QString::fromLatin1("%1,%2").arg(point.x()).arg(point.y());
+ }
+
+ /**
+ * Converts a comma separated string to point.
+ */
+ QPointF stringToPoint(const QString& str)
+ {
+ QPointF retVal;
+ QStringList list = str.split(QLatin1Char(','));
+
+ if(list.size() == 2) {
+ retVal.setX(list.first().toDouble());
+ retVal.setY(list.last().toDouble());
+ }
+ return retVal;
+ }
+
+ /**
+ * Loads pixmap from xmi.
+ *
+ * @param pixEle The dom element from which pixmap should be loaded.
+ *
+ * @param pixmap The pixmap into which the image should be loaded.
+ *
+ * @return True or false based on success or failure of this method.
+ */
+ bool loadPixmapFromXMI(QDomElement &pixEle, QPixmap &pixmap)
+ {
+ if (pixEle.isNull()) {
+ return false;
+ }
+ QDomElement xpmElement = pixEle.firstChildElement(QLatin1String("xpm"));
+
+ QByteArray xpmData = xpmElement.text().toLatin1();
+ QBuffer buffer(&xpmData);
+ buffer.open(QIODevice::ReadOnly);
+
+ QImageReader reader(&buffer, "xpm");
+ QImage image;
+ if (!reader.read(&image)) {
+ return false;
+ }
+
+ pixmap = QPixmap::fromImage(image);
+ return true;
+ }
+
+ /**
+ * Saves pixmap information into DOM element \a qElement.
+ *
+ * @param qDoc The DOM document object.
+ *
+ * @param qElement The DOM element into which the pixmap should be
+ * saved.
+ *
+ * @param pixmap The pixmap to be saved.
+ */
+ void savePixmapToXMI(QDomDocument &qDoc, QDomElement &qElement, const QPixmap& pixmap)
+ {
+ QDomElement pixmapElement = qDoc.createElement(QLatin1String("pixmap"));
+
+ QDomElement xpmElement = qDoc.createElement(QLatin1String("xpm"));
+ pixmapElement.appendChild(xpmElement);
+
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ pixmap.save(&buffer, "xpm");
+ buffer.close();
+
+ xpmElement.appendChild(qDoc.createTextNode(QString::fromLatin1(buffer.data())));
+
+ qElement.appendChild(pixmapElement);
+ }
+
+ /**
+ * Loads gradient from xmi. The gradient pointer should be null
+ * and the new gradient object will be created inside this method.
+ * The gradient should later be deleted externally.
+ *
+ * @param gradientElement The DOM element from which gradient should be
+ * loaded.
+ *
+ * @param gradient The pointer to gradient into which the gradient
+ * should be loaded. (Allocated inside this
+ * method)
+ *
+ * @return True or false based on success or failure of this method.
+ */
+ bool loadGradientFromXMI(QDomElement &gradientElement, QGradient *&gradient)
+ {
+ if(gradientElement.isNull()) {
+ return false;
+ }
+
+ int type_as_int;
+ QGradient::Type type;
+ QGradientStops stops;
+ QGradient::CoordinateMode cmode = QGradient::LogicalMode;
+ QGradient::Spread spread = QGradient::PadSpread;
+
+ type_as_int = gradientElement.attribute(QLatin1String("type")).toInt();
+ type = QGradient::Type(type_as_int);
+ type_as_int = gradientElement.attribute(QLatin1String("spread")).toInt();
+ spread = QGradient::Spread(type_as_int);
+ type_as_int = gradientElement.attribute(QLatin1String("coordinatemode")).toInt();
+ cmode = QGradient::CoordinateMode(type_as_int);
+
+ QDomElement stopElement = gradientElement.firstChildElement(QLatin1String("stops"));
+ if(stopElement.isNull()) {
+ return false;
+ }
+ for(QDomNode node = stopElement.firstChild(); !node.isNull(); node = node.nextSibling()) {
+ QDomElement ele = node.toElement();
+ if(ele.tagName() != QLatin1String("stop")) {
+ continue;
+ }
+
+ qreal posn = ele.attribute(QLatin1String("position")).toDouble();
+ QColor color = QColor(ele.attribute(QLatin1String("color")));
+ stops << QGradientStop(posn, color);
+ }
+
+ if (type == QGradient::LinearGradient) {
+ QPointF p1 = stringToPoint(gradientElement.attribute(QLatin1String("start")));
+ QPointF p2 = stringToPoint(gradientElement.attribute(QLatin1String("finalstop")));
+ gradient = new QLinearGradient(p1, p2);
+ }
+ else if (type == QGradient::RadialGradient) {
+ QPointF center = stringToPoint(gradientElement.attribute(QLatin1String("center")));
+ QPointF focal = stringToPoint(gradientElement.attribute(QLatin1String("focalpoint")));
+ double radius = gradientElement.attribute(QLatin1String("radius")).toDouble();
+ gradient = new QRadialGradient(center, radius, focal);
+ }
+ else { // type == QGradient::ConicalGradient
+ QPointF center = stringToPoint(gradientElement.attribute(QLatin1String("center")));
+ double angle = gradientElement.attribute(QLatin1String("angle")).toDouble();
+ gradient = new QConicalGradient(center, angle);
+ }
+
+ if(gradient) {
+ gradient->setStops(stops);
+ gradient->setSpread(spread);
+ gradient->setCoordinateMode(cmode);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Saves gradient information into DOM element \a qElement.
+ *
+ * @param qDoc The DOM document object.
+ *
+ * @param qElement The DOM element into which the gradient should be
+ * saved.
+ *
+ * @param gradient The gradient to be saved.
+ */
+ void saveGradientToXMI(QDomDocument &qDoc, QDomElement &qElement, const QGradient *gradient)
+ {
+ QDomElement gradientElement = qDoc.createElement(QLatin1String("gradient"));
+
+ gradientElement.setAttribute(QLatin1String("type"), int(gradient->type()));
+ gradientElement.setAttribute(QLatin1String("spread"), int(gradient->spread()));
+ gradientElement.setAttribute(QLatin1String("coordinatemode"), int(gradient->coordinateMode()));
+
+ QDomElement stopsElement = qDoc.createElement(QLatin1String("stops"));
+ gradientElement.appendChild(stopsElement);
+
+ foreach(const QGradientStop& stop, gradient->stops()) {
+ QDomElement ele = qDoc.createElement(QLatin1String("stop"));
+ ele.setAttribute(QLatin1String("position"), stop.first);
+ ele.setAttribute(QLatin1String("color"), stop.second.name());
+ stopsElement.appendChild(ele);
+ }
+
+ QGradient::Type type = gradient->type();
+
+ if(type == QGradient::LinearGradient) {
+ const QLinearGradient *lg = static_cast<const QLinearGradient*>(gradient);
+ gradientElement.setAttribute(QLatin1String("start"), pointToString(lg->start()));
+ gradientElement.setAttribute(QLatin1String("finalstop"), pointToString(lg->finalStop()));
+ }
+ else if(type == QGradient::RadialGradient) {
+ const QRadialGradient *rg = static_cast<const QRadialGradient*>(gradient);
+ gradientElement.setAttribute(QLatin1String("center"), pointToString(rg->center()));
+ gradientElement.setAttribute(QLatin1String("focalpoint"), pointToString(rg->focalPoint()));
+ gradientElement.setAttribute(QLatin1String("radius"), rg->radius());
+ }
+ else { //type == QGradient::ConicalGradient
+ const QConicalGradient *cg = static_cast<const QConicalGradient*>(gradient);
+ gradientElement.setAttribute(QLatin1String("center"), pointToString(cg->center()));
+ gradientElement.setAttribute(QLatin1String("angle"), cg->angle());
+ }
+
+ qElement.appendChild(gradientElement);
+ }
+
+ /**
+ * Extracts the QBrush properties into brush from the XMI xml
+ * element qElement.
+ *
+ * @param qElement The DOM element from which the xmi info should
+ * be extracted.
+ *
+ * @param brush The QBrush object into which brush details should
+ * be read into.
+ */
+ bool loadBrushFromXMI(QDomElement &qElement, QBrush &brush)
+ {
+ if(qElement.isNull()) {
+ return false;
+ }
+
+ quint8 style = qElement.attribute(QLatin1String("style")).toShort();
+ const QString colorString = qElement.attribute(QLatin1String("color"));
+ QColor color;
+ color.setNamedColor(colorString);
+
+ if(style == Qt::TexturePattern) {
+ QPixmap pixmap;
+ QDomElement pixElement = qElement.firstChildElement(QLatin1String("pixmap"));
+ if(!loadPixmapFromXMI(pixElement, pixmap)) {
+ return false;
+ }
+ brush = QBrush(color, pixmap);
+ }
+
+ else if(style == Qt::LinearGradientPattern
+ || style == Qt::RadialGradientPattern
+ || style == Qt::ConicalGradientPattern) {
+ QGradient *gradient = 0;
+ QDomElement gradElement = qElement.firstChildElement(QLatin1String("gradient"));
+
+ if(!loadGradientFromXMI(gradElement, gradient) || !gradient) {
+ delete gradient;
+ return false;
+ }
+
+ brush = QBrush(*gradient);
+ delete gradient;
+ }
+
+ else {
+ brush = QBrush(color, (Qt::BrushStyle)style);
+ }
+
+ //TODO: Checks if transform needs to be loaded.
+
+ return true;
+ }
+
+ /**
+ * Saves the brush info as xmi into the DOM element \a qElement.
+ *
+ * @param qDoc The QDomDocument object pointing to the xmi document.
+ *
+ * @param qElement The element into which the pen, brush and font
+ * info should be saved.
+ *
+ * @param brush The QBrush whose details should be saved.
+ */
+ void saveBrushToXMI(QDomDocument &qDoc, QDomElement &qElement,
+ const QBrush& brush)
+ {
+ QDomElement brushElement = qDoc.createElement(QLatin1String("brush"));
+
+ brushElement.setAttribute(QLatin1String("style"), (quint8)brush.style());
+ brushElement.setAttribute(QLatin1String("color"), brush.color().name());
+
+ if(brush.style() == Qt::TexturePattern) {
+ savePixmapToXMI(qDoc, brushElement, brush.texture());
+ }
+ else if(brush.style() == Qt::LinearGradientPattern
+ || brush.style() == Qt::RadialGradientPattern
+ || brush.style() == Qt::ConicalGradientPattern) {
+ saveGradientToXMI(qDoc, brushElement, brush.gradient());
+ }
+
+ //TODO: Check if transform of this brush needs to be saved.
+ qElement.appendChild(brushElement);
+ }
+
+ /**
+ * Returns true if the first widget's X is smaller than second's.
+ * Used for sorting the UMLWidgetList.
+ * @param widget1 The widget to compare.
+ * @param widget2 The widget to compare with.
+ */
+ bool hasSmallerX(const UMLWidget* widget1, const UMLWidget* widget2)
+ {
+ return widget1->x() < widget2->x();
+ }
+
+ /**
+ * Returns true if the first widget's Y is smaller than second's.
+ * Used for sorting the UMLWidgetList.
+ * @param widget1 The widget to compare.
+ * @param widget2 The widget to compare with.
+ */
+ bool hasSmallerY(const UMLWidget* widget1, const UMLWidget* widget2)
+ {
+ return widget1->y() < widget2->y();
+ }
+
+ /**
+ * Find the region in which the rectangle \a other lies with respect to
+ * the rectangle \a self.
+ * Beware that the Qt coordinate system has its origin point (0,0) in
+ * the upper left corner with Y values growing downwards, thus the Y
+ * related comparisons might look inverted if your are used to the
+ * natural coordinate system with (0,0) in the lower left corner.
+ */
+ Uml::Region::Enum findRegion(const QRectF& self, const QRectF &other)
+ {
+ const qreal ownX = self.x();
+ const qreal ownY = self.y();
+ const qreal ownWidth = self.width();
+ const qreal ownHeight = self.height();
+ const qreal otherX = other.x();
+ const qreal otherY = other.y();
+ const qreal otherWidth = other.width();
+ const qreal otherHeight = other.height();
+ Uml::Region::Enum region = Uml::Region::Center;
+ if (otherX + otherWidth < ownX) {
+ if (otherY + otherHeight < ownY)
+ region = Uml::Region::NorthWest;
+ else if (otherY > ownY + ownHeight)
+ region = Uml::Region::SouthWest;
+ else
+ region = Uml::Region::West;
+ } else if (otherX > ownX + ownWidth) {
+ if (otherY + otherHeight < ownY)
+ region = Uml::Region::NorthEast;
+ else if (otherY > ownY + ownHeight)
+ region = Uml::Region::SouthEast;
+ else
+ region = Uml::Region::East;
+ } else {
+ if (otherY + otherHeight < ownY)
+ region = Uml::Region::North;
+ else if (otherY > ownY + ownHeight)
+ region = Uml::Region::South;
+ else
+ region = Uml::Region::Center;
+ }
+ return region;
+ }
+
+ /**
+ * Return the point in \a poly which precedes the point at index \a index.
+ * If \a index is 0 then return the last (or, if \a poly.isClosed() is
+ * true, the second to last) point.
+ */
+ QPointF prevPoint(int index, const QPolygonF& poly) {
+ if (poly.size() < 3 || index >= poly.size())
+ return QPoint();
+ if (index == 0)
+ return poly.at(poly.size() - 1 - (int)poly.isClosed());
+ return poly.at(index - 1);
+ }
+
+ /**
+ * Return the point in \a poly which follows the point at index \a index.
+ * If \a index is the last index then return the first (or, if
+ * \a poly.isClosed() is true, the second) point.
+ */
+ QPointF nextPoint(int index, const QPolygonF& poly) {
+ if (poly.size() < 3 || index >= poly.size())
+ return QPoint();
+ if (index == poly.size() - 1)
+ return poly.at((int)poly.isClosed());
+ return poly.at(index + 1);
+ }
+
+ /**
+ * Return the middle value between \a a and \a b.
+ */
+ qreal middle(qreal a, qreal b)
+ {
+ return (a + b) / 2.0;
+ }
+
+ /**
+ * Auxiliary type for function findLine()
+ */
+ enum Axis_Type { X , Y };
+
+ /**
+ * Auxiliary type for function findLine()
+ */
+ enum Comparison_Type { Smallest, Largest };
+
+ /**
+ * Find the line of \a poly with the smallest or largest value (controlled by \a seek)
+ * along the axis controlled by \a axis.
+ * In case \a axis is X, do not consider lines whose Y values lie outside the Y values
+ * defined by \a boundingRect.
+ * In case \a axis is Y, do not consider lines whose X values lie outside the X values
+ * defined by \a boundingRect.
+ */
+ QLineF findLine(const QPolygonF& poly, Axis_Type axis, Comparison_Type seek, const QRectF& boundingRect)
+ {
+ const int lastIndex = poly.size() - 1 - (int)poly.isClosed();
+ QPointF prev = poly.at(lastIndex), curr;
+ QPointF p1(seek == Smallest ? QPointF(1.0e6, 1.0e6) : QPointF(-1.0e6, -1.0e6));
+ QPointF p2;
+ for (int i = 0; i <= lastIndex; i++) {
+ curr = poly.at(i);
+ // uDebug() << " poly[" << i << "] = " << curr;
+ if (axis == X) {
+ if (fmin(prev.y(), curr.y()) > boundingRect.y() + boundingRect.height() ||
+ fmax(prev.y(), curr.y()) < boundingRect.y()) {
+ // line is outside Y-axis range defined by boundingRect
+ } else if ((seek == Smallest && curr.x() <= p1.x()) ||
+ (seek == Largest && curr.x() >= p1.x())) {
+ p1 = curr;
+ p2 = prev;
+ }
+ } else {
+ if (fmin(prev.x(), curr.x()) > boundingRect.x() + boundingRect.width() ||
+ fmax(prev.x(), curr.x()) < boundingRect.x()) {
+ // line is outside X-axis range defined by boundingRect
+ } else if ((seek == Smallest && curr.y() <= p1.y()) ||
+ (seek == Largest && curr.y() >= p1.y())) {
+ p1 = curr;
+ p2 = prev;
+ }
+ }
+ prev = curr;
+ }
+ return QLineF(p1, p2);
+ }
+
+ /**
+ * Determine the approximate closest points of two polygons.
+ * @param self First QPolygonF.
+ * @param other Second QPolygonF.
+ * @return QLineF::p1() returns point of \a self;
+ * QLineF::p2() returns point of \a other.
+ */
+ QLineF closestPoints(const QPolygonF& self, const QPolygonF& other)
+ {
+ const QRectF& selfRect = self.boundingRect();
+ const QRectF& otherRect = other.boundingRect();
+ Uml::Region::Enum region = findRegion(selfRect, otherRect);
+ if (region == Uml::Region::Center)
+ return QLineF();
+ if (self.size() < 3 || other.size() < 3)
+ return QLineF();
+ QLineF result;
+ const int selfLastIndex = self.size() - 1 - (int)self.isClosed();
+ const int otherLastIndex = other.size() - 1 - (int)other.isClosed();
+ QPointF selfPoint(self.at(selfLastIndex));
+ QPointF otherPoint(other.at(otherLastIndex));
+ QLineF selfLine, otherLine;
+ int i;
+
+ switch (region) {
+
+ case Uml::Region::North:
+ // Find other's line with largest Y values
+ otherLine = findLine(other, Y, Largest, selfRect);
+ // Find own line with smallest Y values
+ selfLine = findLine(self, Y, Smallest, otherRect);
+ // Use the middle value of the X values
+ result.setLine(middle(selfLine.p2().x(), selfLine.p1().x()), selfLine.p1().y(),
+ middle(otherLine.p2().x(), otherLine.p1().x()), otherLine.p1().y());
+ break;
+
+ case Uml::Region::South:
+ // Find other's line with smallest Y values
+ otherLine = findLine(other, Y, Smallest, selfRect);
+ // Find own line with largest Y values
+ selfLine = findLine(self, Y, Largest, otherRect);
+ // Use the middle value of the X values
+ result.setLine(middle(selfLine.p2().x(), selfLine.p1().x()), selfLine.p1().y(),
+ middle(otherLine.p2().x(), otherLine.p1().x()), otherLine.p1().y());
+ break;
+
+ case Uml::Region::West:
+ // Find other's line with largest X values
+ otherLine = findLine(other, X, Largest, selfRect);
+ // Find own line with smallest X values
+ selfLine = findLine(self, X, Smallest, otherRect);
+ // Use the middle value of the Y values
+ result.setLine(selfLine.p1().x(), middle(selfLine.p2().y(), selfLine.p1().y()),
+ otherLine.p1().x(), middle(otherLine.p2().y(), otherLine.p1().y()));
+ break;
+
+ case Uml::Region::East:
+ // Find other's line with smallest X values
+ otherLine = findLine(other, X, Smallest, selfRect);
+ // Find own line with largest X values
+ selfLine = findLine(self, X, Largest, otherRect);
+ // Use the middle value of the Y values
+ result.setLine(selfLine.p1().x(), middle(selfLine.p2().y(), selfLine.p1().y()),
+ otherLine.p1().x(), middle(otherLine.p2().y(), otherLine.p1().y()));
+ break;
+
+ case Uml::Region::NorthWest:
+ // Find other's point with largest X and largest Y value
+ for (i = 0; i < otherLastIndex; ++i) {
+ QPointF current(other.at(i));
+ if (current.x() + current.y() >= otherPoint.x() + otherPoint.y()) {
+ otherPoint = current;
+ }
+ }
+ // Find own point with smallest X and smallest Y value
+ for (i = 0; i < selfLastIndex; ++i) {
+ QPointF current(self.at(i));
+ if (current.x() + current.y() <= selfPoint.x() + selfPoint.y()) {
+ selfPoint = current;
+ }
+ }
+ result.setPoints(selfPoint, otherPoint);
+ break;
+
+ case Uml::Region::SouthWest:
+ // Find other's point with largest X and smallest Y value
+ for (i = 0; i < otherLastIndex; ++i) {
+ QPointF current(other.at(i));
+ if (current.x() >= otherPoint.x() && current.y() <= otherPoint.y()) {
+ otherPoint = current;
+ }
+ }
+ // Find own point with smallest X and largest Y value
+ for (i = 0; i < selfLastIndex; ++i) {
+ QPointF current(self.at(i));
+ if (current.x() <= selfPoint.x() && current.y() >= selfPoint.y()) {
+ selfPoint = current;
+ }
+ }
+ result.setPoints(selfPoint, otherPoint);
+ break;
+
+ case Uml::Region::NorthEast:
+ // Find other's point with smallest X and largest Y value
+ for (i = 0; i < otherLastIndex; ++i) {
+ QPointF current(other.at(i));
+ if (current.x() <= otherPoint.x() && current.y() >= otherPoint.y()) {
+ otherPoint = current;
+ }
+ }
+ // Find own point with largest X and smallest Y value
+ for (i = 0; i < selfLastIndex; ++i) {
+ QPointF current(self.at(i));
+ if (current.x() >= selfPoint.x() && current.y() <= selfPoint.y()) {
+ selfPoint = current;
+ }
+ }
+ result.setPoints(selfPoint, otherPoint);
+ break;
+
+ case Uml::Region::SouthEast:
+ // Find other's point with smallest X and smallest Y value
+ for (i = 0; i < otherLastIndex; ++i) {
+ QPointF current(other.at(i));
+ if (current.x() + current.y() <= otherPoint.x() + otherPoint.y()) {
+ otherPoint = current;
+ }
+ }
+ // Find own point with largest X and largest Y value
+ for (i = 0; i < selfLastIndex; ++i) {
+ QPointF current(self.at(i));
+ if (current.x() + current.y() >= selfPoint.x() + selfPoint.y()) {
+ selfPoint = current;
+ }
+ }
+ result.setPoints(selfPoint, otherPoint);
+ break;
+
+ default:
+ // Error
+ break;
+ }
+
+ return result;
+ }
+
+} // namespace Widget_Utils
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widget_utils.h umbrello-kf6-15.08.1/umbrello/umlwidgets/widget_utils.h
--- umbrello-kf6-15.08.1.orig/umbrello/umlwidgets/widget_utils.h 1970-01-01 02:00:00.000000000 +0200
+++ umbrello-kf6-15.08.1/umbrello/umlwidgets/widget_utils.h 2015-10-08 11:48:59.553089025 +0300
@@ -0,0 +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) 2004-2014 *
+ * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
+ ***************************************************************************/
+
+#ifndef WIDGET_UTILS_H
+#define WIDGET_UTILS_H
+
+#include "basictypes.h"
+#include "messagewidgetlist.h"
+#include "umlwidgetlist.h"
+
+#include <QBrush>
+#include <QDomDocument>
+#include <QPointF>
+#include <QLineF>
+#include <QPolygonF>
+
+class QGraphicsItem;
+class QGraphicsRectItem;
+
+/**
+ * General purpose-kf6 widget utilities.
+ * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
+ */
+namespace Widget_Utils
+{
+ UMLWidget* findWidget(Uml::ID::Type id,
+ const UMLWidgetList& widgets,
+ const MessageWidgetList* messages = 0);
+
+ QGraphicsRectItem* decoratePoint(const QPointF& p, QGraphicsItem* parent = 0);
+
+ void drawCrossInEllipse(QPainter *p, const QRectF& ellipse);
+ void drawTriangledRect(QPainter *painter, const QRectF& rect, const QSizeF& triSize);
+// void drawArrowHead(QPainter *painter, const QPointF& arrowPos,
+// const QSizeF& arrowSize, Qt::ArrowType arrowType,
+// bool solid-kf6 = false);
+// void drawRoundedRect(QPainter *painter, const QRectF& rect, qreal xRadius,
+// qreal yRadius, Uml::Corners corners);
+
+ QString pointToString(const QPointF& point);
+ QPointF stringToPoint(const QString& str);
+
+ bool loadPixmapFromXMI(QDomElement &qElement, QPixmap &pixmap);
+ void savePixmapToXMI(QDomDocument &qDoc, QDomElement &qElement, const QPixmap& pixmap);
+
+ bool loadGradientFromXMI(QDomElement &qElement, QGradient *&gradient);
+ void saveGradientToXMI(QDomDocument &qDoc, QDomElement &qElement, const QGradient *gradient);
+
+ bool loadBrushFromXMI(QDomElement &qElement, QBrush &brush);
+ void saveBrushToXMI(QDomDocument &qDoc, QDomElement &qElement,
+ const QBrush& brush);
+
+ bool hasSmallerX(const UMLWidget* widget1, const UMLWidget* widget2);
+ bool hasSmallerY(const UMLWidget* widget1, const UMLWidget* widget2);
+
+ QLineF closestPoints(const QPolygonF& self, const QPolygonF& other);
+}
+
+#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/uniqueconstraint.cpp umbrello-kf6-15.08.1/umbrello/uniqueconstraint.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/uniqueconstraint.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/uniqueconstraint.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,325 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-//own header
-#include "uniqueconstraint.h"
-
-// app includes
-#include "debug_utils.h"
-#include "entity.h"
-#include "entityattribute.h"
-#include "umldoc.h"
-#include "uml.h"
-#include "umlattributedialog.h"
-#include "umluniqueconstraintdialog.h"
-#include "object_factory.h"
-
-/**
- * Sets up a constraint.
- *
- * @param parent The parent of this UMLUniqueConstraint.
- * @param name The name of this UMLUniqueConstraint.
- * @param id The unique id given to this UMLUniqueConstraint.
- */
-UMLUniqueConstraint::UMLUniqueConstraint(UMLObject *parent, const QString& name, Uml::ID::Type id)
- : UMLEntityConstraint(parent, name, id)
-{
- init();
-}
-
-/**
- * Sets up a constraint.
- *
- * @param parent The parent of this UMLUniqueConstraint.
- */
-UMLUniqueConstraint::UMLUniqueConstraint(UMLObject *parent)
- : UMLEntityConstraint(parent)
-{
- init();
-}
-
-/**
- * Overloaded '==' operator
- */
-bool UMLUniqueConstraint::operator==(const UMLUniqueConstraint &rhs) const
-{
- if(this == &rhs)
- return true;
-
- if(!UMLObject::operator==(rhs))
- return false;
-
- return true;
-}
-
-/**
- * Destructor.
- */
-UMLUniqueConstraint::~UMLUniqueConstraint()
-{
-}
-
-/**
- * Copy the internal presentation of this object into the UMLUniqueConstraint
- * object.
- */
-void UMLUniqueConstraint::copyInto(UMLObject *lhs) const
-{
- UMLUniqueConstraint *target = static_cast<UMLUniqueConstraint*>(lhs);
-
- // call the parent first.
- UMLEntityConstraint::copyInto(target);
-
- // Copy all datamembers
- target->m_EntityAttributeList.clear();
- bool valid = true;
- foreach(UMLEntityAttribute* attr, m_EntityAttributeList) {
- if (!valid)
- break;
- valid = target->addEntityAttribute(attr);
- }
-
- if (!valid) {
- target->m_EntityAttributeList.clear();
- uDebug() <<"Copying Attributes Failed : Target list cleared instead";
- }
-}
-
-/**
- * Make a clone of the UMLUniqueConstraint.
- */
-UMLObject* UMLUniqueConstraint::clone() const
-{
- //FIXME: The new attribute should be slaved to the NEW parent not the old.
- UMLUniqueConstraint *clone = new UMLUniqueConstraint(static_cast<UMLObject*>(parent()));
- copyInto(clone);
- return clone;
-}
-
-/**
- * Returns a string representation of the UMLUniqueConstraint.
- *
- * @param sig If true will show the attribute type and initial value.
- * @return Returns a string representation of the UMLAttribute.
- */
-QString UMLUniqueConstraint::toString(Uml::SignatureType::Enum sig)
-{
- QString s;
-
- if (sig == Uml::SignatureType::ShowSig || sig == Uml::SignatureType::SigNoVis) {
- s = name() + QLatin1Char(':');
-
- if (static_cast<UMLEntity*>(parent())->isPrimaryKey(this)) {
- s += QLatin1String("Primary Key (");
- } else {
- s += QLatin1String("Unique (");
- }
-
- bool first = true;
- foreach(UMLEntityAttribute* att, m_EntityAttributeList) {
- if (first) {
- first = false;
- } else
- s += QLatin1Char(',');
- s += att->name();
- }
- s += QLatin1Char(')') ;
- }
-
- return s;
-}
-
-QString UMLUniqueConstraint::getFullyQualifiedName(const QString& separator,
- bool includeRoot) const
-{
- Q_UNUSED(separator); Q_UNUSED(includeRoot);
- return this->name();
-}
-
-/**
- * Creates the <UML:UniqueConstraint> XMI element.
- */
-void UMLUniqueConstraint::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement uniqueConstraintElement = UMLObject::save(QLatin1String("UML:UniqueConstraint"), qDoc);
-
- UMLEntity* parentEnt = static_cast<UMLEntity*>(parent());
- if (parentEnt->isPrimaryKey(this)) {
- uniqueConstraintElement.setAttribute(QLatin1String("isPrimary"), QLatin1String("1"));
- } else {
- uniqueConstraintElement.setAttribute(QLatin1String("isPrimary"), QLatin1String("0"));
- }
-
- foreach(UMLEntityAttribute* att, m_EntityAttributeList) {
- att->saveToXMI(qDoc, uniqueConstraintElement);
- }
-
- qElement.appendChild(uniqueConstraintElement);
-}
-
-/**
- * Display the properties configuration dialog for the attribute.
- */
-bool UMLUniqueConstraint::showPropertiesDialog(QWidget* parent)
-{
- UMLUniqueConstraintDialog dialog(parent, this);
- return dialog.exec();
-}
-
-/**
- * Loads the <UML:UniqueConstraint> XMI element.
- */
-bool UMLUniqueConstraint::load(QDomElement & element)
-{
- int isPrimary = element.attribute(QLatin1String("isPrimary"), QLatin1String("0")).toInt();
- UMLEntity* parentEnt = static_cast<UMLEntity*>(parent());
-
- if (isPrimary == 1) {
- parentEnt->setAsPrimaryKey(this);
- }
-
- QDomNode node = element.firstChild();
- while (!node.isNull()) {
- if (node.isComment()) {
- node = node.nextSibling();
- continue;
- }
- QDomElement tempElement = node.toElement();
- QString tag = tempElement.tagName();
- if (UMLDoc::tagEq(tag, QLatin1String("EntityAttribute"))) {
-
- QString attName = tempElement.attribute(QLatin1String("name"));
- UMLObject* obj = parentEnt->findChildObject(attName);
-
- UMLEntityAttribute* entAtt = static_cast<UMLEntityAttribute*>(obj);
- if (entAtt == NULL)
- continue;
-
- m_EntityAttributeList.append(entAtt);
-
- } else {
- uWarning() << "unknown child type in UMLUniqueConstraint::load";
- }
-
- node = node.nextSibling();
- }
-
- return true;
-}
-
-
-/**
- * Check if a entity attribute is present in m_entityAttributeList
- *
- * @param attr The Entity Attribute to check for existence in list
- * @return true if it exists in the list, else false
- */
-bool UMLUniqueConstraint::hasEntityAttribute(UMLEntityAttribute* attr)
-{
- if (m_EntityAttributeList.indexOf(attr) == -1) {
- //not present
- return false;
- }
-
- // else present
- return true;
-}
-
-/**
- * Adds a UMLEntityAttribute to the list.
- * The UMLEntityAttribute should already exist and should
- * belong to the parent UMLEntity.
- *
- * @param attr The UMLEntityAttribute to add
- * @return false if it failed to add, else true
- */
-bool UMLUniqueConstraint::addEntityAttribute(UMLEntityAttribute* attr)
-{
- UMLEntity *owningParent = dynamic_cast<UMLEntity*>(parent());
-
- if (hasEntityAttribute(attr)) {
- uDebug() << "Unique Constraint already contains" << attr->name();
- return false;
-
- }
- if (owningParent == NULL) {
- uError() << name() << ": parent is not a UMLEntity";
- return false;
- }
-
- if (owningParent->findChildObjectById(attr->id()) == NULL) {
- uError()
- << " parent " << owningParent->name()
- << " does not contain attribute " << attr->name();
- return false;
- }
-
- //else add the attribute to the Entity Attribute List
- m_EntityAttributeList.append(attr);
-
- return true;
-}
-
-/**
- * Removes a UMLEntityAttribute from the list
- *
- * @param attr The UMLEntityAttribute to remove from list
- * @return false if it failed to remove the attribute from the list
- */
-bool UMLUniqueConstraint::removeEntityAttribute(UMLEntityAttribute* attr)
-{
- UMLEntity *owningParent = dynamic_cast<UMLEntity*>(parent());
-
- if (owningParent == NULL) {
- uError() << name() << ": parent is not a UMLEntity";
- return false;
- }
-
- /*
- * The attribute may already be removed from the Entity when this function
- * is called. So checking this is not right
- *
- * if (owningParent->findChildObjectById(attr->ID()) == NULL) {
- * uError()
- * << " parent " << owningParent->getName()
- * << " does not contain attribute " << attr->getName();
- * return false;
- * }
- */
-
- //else remove the attribute from the Entity Attribute List
- if (m_EntityAttributeList.removeAll(attr)) {
- return true;
- }
-
- return false;
-}
-
-/**
- * Get the Entity Attributes List.
- */
-UMLEntityAttributeList UMLUniqueConstraint::getEntityAttributeList() const
-{
- return m_EntityAttributeList;
-}
-
-void UMLUniqueConstraint::init()
-{
- m_BaseType = UMLObject::ot_UniqueConstraint;
-}
-
-/**
- * Clear the list of attributes contained in this UniqueConstraint
- */
-void UMLUniqueConstraint::clearAttributeList()
-{
- m_EntityAttributeList.clear();
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/uniqueconstraint.h umbrello-kf6-15.08.1/umbrello/uniqueconstraint.h
--- umbrello-kf6-15.08.1.orig/umbrello/uniqueconstraint.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/uniqueconstraint.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,77 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UNIQUECONSTRAINT_H
-#define UNIQUECONSTRAINT_H
-
-#include "basictypes.h"
-#include "classifierlistitem.h"
-#include "entityconstraint.h"
-#include "umlclassifierlist.h"
-#include "umlentityattributelist.h"
-
-/**
- * This class is used to set up information for a unique entity constraint.
- *
- * @short Sets up Unique entity constraint information.
- * @author Sharan Rao
- * @see UMLObject UMLClassifierListItem UMLEntityConstraint
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLUniqueConstraint : public UMLEntityConstraint
-{
-public:
-
- UMLUniqueConstraint(UMLObject *parent, const QString& name,
- Uml::ID::Type id = Uml::ID::None);
- explicit UMLUniqueConstraint(UMLObject *parent);
- virtual ~UMLUniqueConstraint();
-
- bool operator==(const UMLUniqueConstraint &rhs) const;
-
- virtual void copyInto(UMLObject *lhs) const;
-
- virtual UMLObject* clone() const;
-
- QString toString(Uml::SignatureType::Enum sig = Uml::SignatureType::NoSig);
-
- QString getFullyQualifiedName(const QString& separator = QString(),
- bool includeRoot = false) const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- virtual bool showPropertiesDialog(QWidget* parent = 0);
-
- bool hasEntityAttribute(UMLEntityAttribute* attr);
-
- bool addEntityAttribute(UMLEntityAttribute* attr);
-
- bool removeEntityAttribute(UMLEntityAttribute* attr);
-
- UMLEntityAttributeList getEntityAttributeList() const;
-
- void clearAttributeList();
-
-protected:
-
- bool load(QDomElement & element);
-
-private:
-
- void init();
-
- /**
- * The list of entity attributes that together make up the unique constraint.
- */
- UMLEntityAttributeList m_EntityAttributeList;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/usecase.cpp umbrello-kf6-15.08.1/umbrello/usecase.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/usecase.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/usecase.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,67 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "usecase.h"
-
-/**
- * Creates a UseCase object
- *
- * @param name The name of the object.
- * @param id The id of the object.
- */
-UMLUseCase::UMLUseCase(const QString & name, Uml::ID::Type id)
- : UMLCanvasObject(name, id)
-{
- init();
-}
-
-/**
- * Standard decstructor.
- */
-UMLUseCase::~UMLUseCase()
-{
-}
-
-/**
- * Initializes key variables of the class.
- */
-void UMLUseCase::init()
-{
- m_BaseType = UMLObject::ot_UseCase;
-}
-
-/**
- * Make a clone of this object.
- */
-UMLObject* UMLUseCase::clone() const
-{
- UMLUseCase *clone = new UMLUseCase();
- UMLObject::copyInto(clone);
- return clone;
-}
-
-/**
- * Creates the <UML:UseCase> element.
- */
-void UMLUseCase::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement usecaseElement = UMLObject::save(QLatin1String("UML:UseCase"), qDoc);
- qElement.appendChild(usecaseElement);
-}
-
-/**
- * Loads the <UML:UseCase> element (TODO).
- */
-bool UMLUseCase::load(QDomElement&)
-{
- return true;
-}
-
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/usecase.h umbrello-kf6-15.08.1/umbrello/usecase.h
--- umbrello-kf6-15.08.1.orig/umbrello/usecase.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/usecase.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,40 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef USECASE_H
-#define USECASE_H
-
-#include "umlcanvasobject.h"
-
-/**
- * This class contains the non-graphical information required for a UML UseCase.
- * This class inherits from @ref UMLCanvasObject which contains most of the information.
- *
- * @short Information for a non-graphical UML UseCase.
- * @author Paul Hensgen <phensgen@techie.com>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLUseCase : public UMLCanvasObject
-{
-public:
- explicit UMLUseCase(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None);
- ~UMLUseCase();
-
- virtual void init();
-
- virtual UMLObject* clone() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
-protected:
- bool load(QDomElement & element);
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/activitywidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/activitywidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/activitywidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/activitywidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,457 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "activitywidget.h"
-
-// app includes
-#include "activitydialog.h"
-#include "debug_utils.h"
-#include "docwindow.h"
-#include "listpopupmenu.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-// kde includes
-#include <KLocalizedString>
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-#include <QPointer>
-/**
- * Creates a Activity widget.
- *
- * @param scene The parent of the widget.
- * @param activityType The type of activity.
- * @param id The ID to assign (-1 will prompt a new ID.)
- */
-ActivityWidget::ActivityWidget(UMLScene * scene, ActivityType activityType, Uml::ID::Type id)
- : UMLWidget(scene, WidgetBase::wt_Activity, id),
- m_activityType(activityType)
-{
- // set non zero size to avoid crash on painting
- setSize(1, 1);
-}
-
-/**
- * Destructor.
- */
-ActivityWidget::~ActivityWidget()
-{
-}
-
-/**
- * Returns the type of activity.
- */
-ActivityWidget::ActivityType ActivityWidget::activityType() const
-{
- return m_activityType;
-}
-
-/**
- * Returns the type string of activity.
- */
-QString ActivityWidget::activityTypeStr() const
-{
- return QLatin1String(ENUM_NAME(ActivityWidget, ActivityType, m_activityType));
-}
-
-/**
- * Sets the type of activity.
- */
-void ActivityWidget::setActivityType(ActivityType activityType)
-{
- m_activityType = activityType;
- updateGeometry();
- UMLWidget::m_resizable = true;
-}
-
-/**
- * Determines whether a toolbar button represents an Activity.
- * CHECK: currently unused - can this be removed?
- *
- * @param tbb The toolbar button enum input value.
- * @param resultType The ActivityType corresponding to tbb.
- * This is only set if tbb is an Activity.
- * @return True if tbb represents an Activity.
- */
-bool ActivityWidget::isActivity(WorkToolBar::ToolBar_Buttons tbb,
- ActivityType& resultType)
-{
- bool status = true;
- switch (tbb) {
- case WorkToolBar::tbb_Initial_Activity:
- resultType = Initial;
- break;
- case WorkToolBar::tbb_Activity:
- resultType = Normal;
- break;
- case WorkToolBar::tbb_End_Activity:
- resultType = End;
- break;
- case WorkToolBar::tbb_Final_Activity:
- resultType = Final;
- break;
- case WorkToolBar::tbb_Branch:
- resultType = Branch;
- break;
- default:
- status = false;
- break;
- }
- return status;
-}
-
-/**
- * This method get the name of the preText attribute.
- */
-QString ActivityWidget::preconditionText() const
-{
- return m_preconditionText;
-}
-
-/**
- * This method set the name of the preText attribute
- */
-void ActivityWidget::setPreconditionText(const QString& aPreText)
-{
- m_preconditionText = aPreText;
- updateGeometry();
- adjustAssocs(x(), y());
-}
-
-/**
- * This method get the name of the postText attribute.
- */
-QString ActivityWidget::postconditionText() const
-{
- return m_postconditionText;
-}
-
-/**
- * This method set the name of the postText attribute
- */
-void ActivityWidget::setPostconditionText(const QString& aPostText)
-{
- m_postconditionText = aPostText;
- updateGeometry();
- adjustAssocs(x(), y());
-}
-
-/**
- * Reimplemented from UMLWidget::showPropertiesDialog to show a
- * properties dialog for an ActivityWidget.
- */
-void ActivityWidget::showPropertiesDialog()
-{
- UMLApp::app()->docWindow()->updateDocumentation(false);
-
- QPointer<ActivityDialog> dialog = new ActivityDialog(umlScene()->activeView(), this);
- if (dialog->exec() && dialog->getChangesMade()) {
- UMLApp::app()->docWindow()->showDocumentation(this, true);
- UMLApp::app()->document()->setModified(true);
- }
- delete dialog;
-}
-
-/**
- * Overrides the standard paint event.
- */
-void ActivityWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
- int w = width();
- int h = height();
-
- // Only for the final activity
- float x;
- float y;
- QPen pen = painter->pen();
-
- switch (m_activityType)
- {
- case Normal:
- UMLWidget::setPenFromSettings(painter);
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- }
- {
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- int textStartY = (h / 2) - (fontHeight / 2);
- painter->drawRoundRect(0, 0, w, h, (h * 60) / w, 60);
- painter->setPen(textColor());
- painter->setFont(UMLWidget::font());
- painter->drawText(ACTIVITY_MARGIN, textStartY,
- w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
- }
- break;
-
- case Initial:
- painter->setPen(QPen(WidgetBase::lineColor(), 1));
- painter->setBrush(WidgetBase::lineColor());
- painter->drawEllipse(0, 0, w, h);
- break;
-
- case Final:
- UMLWidget::setPenFromSettings(painter);
- painter->setBrush(Qt::white);
- pen.setWidth(2);
- pen.setColor (Qt::red);
- painter->setPen(pen);
- painter->drawEllipse(0, 0, w, h);
- x = w/2 ;
- y = h/2 ;
- {
- const float w2 = 0.7071 * (float)w / 2.0;
- painter->drawLine((int)(x - w2 + 1), (int)(y - w2 + 1), (int)(x + w2), (int)(y + w2));
- painter->drawLine((int)(x + w2 - 1), (int)(y - w2 + 1), (int)(x - w2), (int)(y + w2));
- }
- break;
-
- case End:
- painter->setPen(QPen(WidgetBase::lineColor(), 1));
- painter->setBrush(WidgetBase::lineColor());
- painter->drawEllipse(0, 0, w, h);
- painter->setBrush(Qt::white);
- painter->drawEllipse(1, 1, w - 2, h - 2);
- painter->setBrush(WidgetBase::lineColor());
- painter->drawEllipse(3, 3, w - 6, h - 6);
- break;
-
- case Branch:
- UMLWidget::setPenFromSettings(painter);
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- }
- {
- QPolygon array(4);
- array[ 0 ] = QPoint(w / 2, 0);
- array[ 1 ] = QPoint(w, h / 2);
- array[ 2 ] = QPoint(w / 2, h);
- array[ 3 ] = QPoint(0, h / 2);
- painter->drawPolygon(array);
- painter->drawPolyline(array);
- }
- break;
-
- case Invok:
- UMLWidget::setPenFromSettings(painter);
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- }
- {
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- int textStartY = (h / 2) - (fontHeight / 2);
- painter->drawRoundRect(0, 0, w, h, (h * 60) / w, 60);
- painter->setPen(textColor());
- painter->setFont(UMLWidget::font());
- painter->drawText(ACTIVITY_MARGIN, textStartY,
- w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
-
- }
- x = w - (w/5);
- y = h - (h/3);
-
- painter->drawLine((int)x, (int) y, (int)x, (int)(y + 20));
- painter->drawLine((int)(x - 10), (int)(y + 10), (int)(x + 10), (int)(y + 10));
- painter->drawLine((int)(x - 10), (int)(y + 10), (int)(x - 10), (int)(y + 20));
- painter->drawLine((int)(x + 10), (int)(y + 10), (int)(x + 10), (int)(y + 20));
- break;
-
- case Param:
- UMLWidget::setPenFromSettings(painter);
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- }
- {
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- QString preCond= QLatin1String("<<precondition>> ") + preconditionText();
- QString postCond= QLatin1String("<<postcondition>> ") + postconditionText();
- //int textStartY = (h / 2) - (fontHeight / 2);
- painter->drawRoundRect(0, 0, w, h, (h * 60) / w, 60);
- painter->setPen(textColor());
- painter->setFont(UMLWidget::font());
- painter->drawText(ACTIVITY_MARGIN, fontHeight + 10,
- w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, preCond);
- painter->drawText(ACTIVITY_MARGIN, fontHeight * 2 + 10,
- w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, postCond);
- painter->drawText(ACTIVITY_MARGIN, (fontHeight / 2),
- w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
- }
-
- break;
- }
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overridden from UMLWidget due to emission of signal sigActMoved()
- */
-void ActivityWidget::moveWidgetBy(qreal diffX, qreal diffY)
-{
- UMLWidget::moveWidgetBy(diffX, diffY);
- emit sigActMoved(diffX, diffY);
-}
-
-/**
- * Loads the widget from the "activitywidget" XMI element.
- */
-bool ActivityWidget::loadFromXMI(QDomElement& qElement)
-{
- if(!UMLWidget::loadFromXMI(qElement))
- return false;
- setName(qElement.attribute(QLatin1String("activityname")));
- setDocumentation(qElement.attribute(QLatin1String("documentation")));
- setPreconditionText(qElement.attribute(QLatin1String("precondition")));
- setPostconditionText(qElement.attribute(QLatin1String("postcondition")));
-
- QString type = qElement.attribute(QLatin1String("activitytype"), QLatin1String("1"));
- setActivityType((ActivityType)type.toInt());
-
- return true;
-}
-
-/**
- * Saves the widget to the "activitywidget" XMI element.
- */
-void ActivityWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement activityElement = qDoc.createElement(QLatin1String("activitywidget"));
- UMLWidget::saveToXMI(qDoc, activityElement);
- activityElement.setAttribute(QLatin1String("activityname"), name());
- activityElement.setAttribute(QLatin1String("documentation"), documentation());
- activityElement.setAttribute(QLatin1String("precondition"), preconditionText());
- activityElement.setAttribute(QLatin1String("postcondition"), postconditionText());
- activityElement.setAttribute(QLatin1String("activitytype"), m_activityType);
- qElement.appendChild(activityElement);
-}
-
-/**
- * Overrides Method from UMLWidget.
- */
-void ActivityWidget::constrain(qreal& width, qreal& height)
-{
- if (m_activityType == Normal || m_activityType == Invok || m_activityType == Param) {
- UMLWidget::constrain(width, height);
- return;
- }
-
- if (width > height)
- width = height;
- else if (height > width)
- height = width;
-
- UMLWidget::constrain(width, height);
-}
-
-/**
- * Captures any popup menu signals for menus it created.
- */
-void ActivityWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
-
- switch(sel) {
- case ListPopupMenu::mt_Rename:
- {
- bool ok = false;
- QString n = name();
-#if QT_VERSION >= 0x050000
- n = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter Activity Name"),
- i18n("Enter the name of the new activity:"),
- QLineEdit::Normal,
- n, &ok);
-#else
- n = KInputDialog::getText(i18n("Enter Activity Name"),
- i18n("Enter the name of the new activity:"),
- n, &ok);
-#endif
- if (ok && !n.isEmpty()) {
- setName(n);
- }
- }
- break;
-
- case ListPopupMenu::mt_Properties:
- showPropertiesDialog();
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- }
-}
-
-/**
- * Overrides method from UMLWidget
- */
-QSizeF ActivityWidget::minimumSize() const
-{
- if (m_activityType == Normal || m_activityType == Invok || m_activityType == Param) {
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
-
- int textWidth = fm.width(name());
- int height = fontHeight;
- height = height > ACTIVITY_HEIGHT ? height : ACTIVITY_HEIGHT;
- height += ACTIVITY_MARGIN * 2;
-
- textWidth = textWidth > ACTIVITY_WIDTH ? textWidth : ACTIVITY_WIDTH;
-
- if (m_activityType == Invok) {
- height += 40;
- } else if (m_activityType == Param) {
- QString maxSize;
-
- maxSize = name().length() > postconditionText().length() ? name() : postconditionText();
- maxSize = maxSize.length() > preconditionText().length() ? maxSize : preconditionText();
-
- textWidth = fm.width(maxSize);
- textWidth = textWidth + 50;
- height += 100;
- }
-
- int width = textWidth > ACTIVITY_WIDTH ? textWidth : ACTIVITY_WIDTH;
-
- width += ACTIVITY_MARGIN * 4;
- return QSizeF(width, height);
- }
- else if (m_activityType == Branch) {
- return QSizeF(20, 20);
- }
- return QSizeF(15, 15);
-}
-
-/**
- * Overrides method from UMLWidget
- */
-QSizeF ActivityWidget::maximumSize()
-{
- if (m_activityType == Normal || m_activityType == Invok || m_activityType == Param) {
- return UMLWidget::maximumSize();
- }
- if (m_activityType == Branch) {
- return QSizeF(50, 50);
- }
- return QSizeF(30, 30);
-}
-
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/activitywidget.h umbrello-kf6-15.08.1/umbrello/widgets/activitywidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/activitywidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/activitywidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,98 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ACTIVITYWIDGET_H
-#define ACTIVITYWIDGET_H
-
-#include "umlwidget.h"
-#include "worktoolbar.h"
-
-#define ACTIVITY_MARGIN 5
-#define ACTIVITY_WIDTH 30
-#define ACTIVITY_HEIGHT 10
-
-/**
- * This class is the graphical version of a UML Activity. A ActivityWidget is created
- * by a @ref UMLView. An ActivityWidget belongs to only one @ref UMLView instance.
- * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
- *
- * The ActivityWidget class inherits from the @ref UMLWidget class which adds most of the functionality
- * to this class.
- *
- * @short A graphical version of a UML Activity.
- * @author Paul Hensgen <phensgen@techie.com>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class ActivityWidget : public UMLWidget
-{
- Q_OBJECT
- Q_ENUMS(ActivityType)
-public:
- enum ActivityType
- {
- Initial = 0,
- Normal,
- End,
- Final,
- Branch,
- Invok,
- Param
- };
-
- explicit ActivityWidget(UMLScene * scene, ActivityType activityType = Normal, Uml::ID::Type id = Uml::ID::None);
- virtual ~ActivityWidget();
-
- ActivityType activityType() const;
- QString activityTypeStr() const;
- void setActivityType(ActivityType activityType);
-
- static bool isActivity(WorkToolBar::ToolBar_Buttons tbb,
- ActivityType& resultType);
-
- QString preconditionText() const;
- void setPreconditionText(const QString&);
-
- QString postconditionText() const;
- void setPostconditionText(const QString&);
-
- virtual void showPropertiesDialog();
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
- virtual void moveWidgetBy(qreal diffX, qreal diffY);
-
- virtual bool loadFromXMI(QDomElement & qElement);
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- void constrain(qreal& width, qreal& height);
-
-signals:
- /**
- * Emitted when the activity widget is moved.
- * Provides the delta X and delta Y amount by which the widget was moved
- * relative to the previous position.
- * Slots into PinWidget::slotActMoved()
- * @param diffX The difference between previous and new X value.
- * @param diffY The difference between previous and new Y value.
- */
- void sigActMoved(qreal diffX, qreal diffY);
-
-public Q_SLOTS:
- virtual void slotMenuSelection(QAction* action);
-
-protected:
- virtual QSizeF minimumSize() const;
- virtual QSizeF maximumSize();
-
- ActivityType m_activityType; ///< Type of activity.
-
- QString m_preconditionText;
- QString m_postconditionText;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/actorwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/actorwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/actorwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/actorwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,104 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header file
-#include "actorwidget.h"
-
-// local includes
-#include "actor.h"
-#include "umlview.h"
-
-/**
- * Constructs an ActorWidget.
- *
- * @param scene The parent of this ActorWidget.
- * @param a The Actor class this ActorWidget will display.
- */
-ActorWidget::ActorWidget(UMLScene * scene, UMLActor *a)
- : UMLWidget(scene, WidgetBase::wt_Actor, a)
-{
- setFixedAspectRatio(true);
-}
-
-/**
- * Destructor.
- */
-ActorWidget::~ActorWidget()
-{
-}
-
-/**
- * Overrides the standard paint event.
- */
-void ActorWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
- UMLWidget::setPenFromSettings(painter);
- if(UMLWidget::useFillColor())
- painter->setBrush(UMLWidget::fillColor());
- const int w = width();
- const int h = height();
- painter->setFont(UMLWidget::font());
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- bool drawStereotype = umlObject() && !umlObject()->stereotype().isEmpty();
- const int a_height = h - (drawStereotype ? 2 * fontHeight : fontHeight) - A_MARGIN;
- const int h2 = a_height / 2;
- const int a_width = (h2);
- const int middleX = w / 2;
- const int thirdY = a_height / 3;
-
- //draw actor
- painter->drawEllipse(middleX - a_width / 2, 0, a_width, thirdY); //head
- painter->drawLine(middleX, thirdY,
- middleX, thirdY * 2); //body
- painter->drawLine(middleX, 2 * thirdY,
- middleX - a_width / 2, a_height); //left leg
- painter->drawLine(middleX, 2 * thirdY,
- middleX + a_width / 2, a_height); //right leg
- painter->drawLine(middleX - a_width / 2, thirdY + thirdY / 2,
- middleX + a_width / 2, thirdY + thirdY / 2); //arms
- //draw text
- painter->setPen(textColor());
- if (drawStereotype)
- painter->drawText(A_MARGIN, h - 2 * fontHeight, w - A_MARGIN * 2, fontHeight, Qt::AlignCenter, umlObject()->stereotype(true));
- painter->drawText(A_MARGIN, h - fontHeight,
- w - A_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Saves the widget to the "actorwidget" XMI element.
- * Note: For loading from XMI, the inherited parent method is used.
- */
-void ActorWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement actorElement = qDoc.createElement(QLatin1String("actorwidget"));
- UMLWidget::saveToXMI(qDoc, actorElement);
- qElement.appendChild(actorElement);
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF ActorWidget::minimumSize() const
-{
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- const int textWidth = fm.width(name());
- bool drawStereotype = umlObject() && !umlObject()->stereotype().isEmpty();
- int width = textWidth > A_WIDTH ? textWidth : A_WIDTH;
- int height = A_HEIGHT + (drawStereotype ? 2 * fontHeight : fontHeight) + A_MARGIN;
- width += A_MARGIN * 2;
- return QSizeF(width, height);
-}
-
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/actorwidget.h umbrello-kf6-15.08.1/umbrello/widgets/actorwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/actorwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/actorwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,55 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ACTORWIDGET_H
-#define ACTORWIDGET_H
-
-#include "umlwidget.h"
-
-#define A_WIDTH 20
-#define A_HEIGHT 40
-#define A_MARGIN 5
-
-class UMLActor;
-
-/**
- * This class is the graphical version of a UML Actor.
- * An ActorWidget is created by a @ref UMLView. An ActorWidget belongs to only
- * one @ref UMLView instance.
- * When the @ref UMLView instance that this class belongs to is destroyed, the
- * ActorWidget will be automatically deleted.
- *
- * If the UMLActor class that this ActorWidget is displaying is deleted, the
- * @ref UMLView will make sure that this instance is also deleted.
- *
- * The ActorWidget class inherits from the @ref UMLWidget class
- * which adds most of the functionality to this class.
- *
- * @short A graphical version of a UML Actor.
- * @author Paul Hensgen <phensgen@techie.com>
- * @see UMLWidget
- * @see UMLView
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class ActorWidget : public UMLWidget
-{
-public:
- ActorWidget(UMLScene * scene, UMLActor *o);
- virtual ~ActorWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
-protected:
- QSizeF minimumSize() const;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/artifactwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/artifactwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/artifactwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/artifactwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,293 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "artifactwidget.h"
-
-// app includes
-#include "artifact.h"
-#include "debug_utils.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-/**
- * Constructs a ArtifactWidget.
- *
- * @param scene The parent of this ArtifactWidget.
- * @param a The Artifact this widget will be representing.
- */
-ArtifactWidget::ArtifactWidget(UMLScene *scene, UMLArtifact *a)
- : UMLWidget(scene, WidgetBase::wt_Artifact, a)
-{
- setSize(100, 30);
-}
-
-/**
- * Destructor.
- */
-ArtifactWidget::~ArtifactWidget()
-{
-}
-
-/**
- * Reimplemented to paint the articraft widget. Some part of specific
- * drawing is delegeted to private method like drawAsFile..
- */
-void ArtifactWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- UMLWidget::setPenFromSettings(painter);
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- } else {
- painter->setBrush(m_scene->backgroundColor());
- }
-
- if (umlObject()) {
- UMLArtifact *umlart = static_cast<UMLArtifact*>(m_umlObject);
- UMLArtifact::Draw_Type drawType = umlart->getDrawAsType();
- switch (drawType) {
- case UMLArtifact::defaultDraw:
- paintAsNormal(painter, option);
- break;
- case UMLArtifact::file:
- paintAsFile(painter, option);
- break;
- case UMLArtifact::library:
- paintAsLibrary(painter, option);
- break;
- case UMLArtifact::table:
- paintAsTable(painter, option);
- break;
- default:
- uWarning() << "Artifact drawn as unknown type";
- break;
- }
- }
- else {
- uWarning() << "Cannot draw as there is no UMLArtifact for this widget.";
- }
-}
-
-/**
- * Reimplemented from WidgetBase::saveToXMI to save the widget to
- * the "artifactwidget" XMI element.
- */
-void ArtifactWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement conceptElement = qDoc.createElement(QLatin1String("artifactwidget"));
- UMLWidget::saveToXMI(qDoc, conceptElement);
- qElement.appendChild(conceptElement);
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF ArtifactWidget::minimumSize() const
-{
- if (!m_umlObject) {
- return UMLWidget::minimumSize();
- }
- UMLArtifact *umlart = static_cast<UMLArtifact*>(m_umlObject);
- if (umlart->getDrawAsType() == UMLArtifact::defaultDraw) {
- return calculateNormalSize();
- } else {
- return calculateIconSize();
- }
-}
-
-/**
- * calculates the size when drawing as an icon (it's the same size for all icons)
- */
-QSize ArtifactWidget::calculateIconSize() const
-{
- const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
- const int fontHeight = fm.lineSpacing();
-
- int width = fm.width(m_umlObject->name());
-
- width = width<50 ? 50 : width;
-
- int height = 50 + fontHeight;
-
- return QSize(width, height);
-}
-
-/**
- * calculates the size for drawing as a box
- */
-QSize ArtifactWidget::calculateNormalSize() const
-{
- const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
- const int fontHeight = fm.lineSpacing();
-
- int width = fm.width(m_umlObject->name());
-
- int tempWidth = 0;
- if(!m_umlObject->stereotype().isEmpty()) {
- tempWidth = fm.width(m_umlObject->stereotype(true));
- }
- width = tempWidth>width ? tempWidth : width;
- width += ARTIFACT_MARGIN * 2;
-
- int height = (2*fontHeight) + (ARTIFACT_MARGIN * 2);
-
- return QSize(width, height);
-}
-
-/**
- * draw as a file icon
- */
-void ArtifactWidget::paintAsFile(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- const int w = width();
- const int h = height();
- QFont font = UMLWidget::font();
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
-
- int startX = (w/2) - 25;
- int iconHeight = h - fontHeight;
- QPolygon pointArray(5);
- pointArray.setPoint(0, startX, 0);
- pointArray.setPoint(1, startX + 40, 0);
- pointArray.setPoint(2, startX + 50, 10);
- pointArray.setPoint(3, startX + 50, iconHeight);
- pointArray.setPoint(4, startX, iconHeight);
- painter->drawPolygon(pointArray);
-
- painter->drawLine(startX + 40, 0, startX + 40, 10);
- painter->drawLine(startX + 40, 10, startX + 50, 10);
- painter->drawLine(startX + 40, 0, startX + 50, 10);
-
- painter->setPen(textColor());
- painter->setFont(font);
-
- painter->drawText(0, h - fontHeight,
- w, fontHeight, Qt::AlignCenter, name());
-
- UMLWidget::paint(painter, option);
-}
-
-/**
- * draw as a library file icon
- */
-void ArtifactWidget::paintAsLibrary(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- //FIXME this should have gears on it
- const int w = width();
- const int h = height();
- const QFont font = UMLWidget::font();
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
-
- const int startX = (w/2) - 25;
- const int iconHeight = h - fontHeight;
- QPolygon pointArray(5);
- pointArray.setPoint(0, startX, 0);
- pointArray.setPoint(1, startX + 40, 0);
- pointArray.setPoint(2, startX + 50, 10);
- pointArray.setPoint(3, startX + 50, iconHeight);
- pointArray.setPoint(4, startX, iconHeight);
- painter->drawPolygon(pointArray);
-
- painter->drawLine(startX + 40, 0, startX + 40, 10);
- painter->drawLine(startX + 40, 10, startX + 50, 10);
- painter->drawLine(startX + 40, 0, startX + 50, 10);
-
- painter->setPen(textColor());
- painter->setFont(font);
-
- painter->drawText(0, h - fontHeight,
- w, fontHeight, Qt::AlignCenter, name());
-
- UMLWidget::paint(painter, option);
-}
-
-/**
- * draw as a database table icon
- */
-void ArtifactWidget::paintAsTable(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- const int w = width();
- const int h = height();
- const QFont font = UMLWidget::font();
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
-
- const int startX = (w/2) - 25;
- const int iconHeight = h - fontHeight;
-
- painter->drawRect(startX, 0, 50, h - fontHeight + 1);
- painter->drawLine(startX + 20, 0, startX + 20, iconHeight);
- painter->drawLine(startX + 30, 0, startX + 30, iconHeight);
- painter->drawLine(startX + 40, 0, startX + 40, iconHeight);
- painter->drawLine(startX, (iconHeight/2), startX + 49, (iconHeight/2));
- painter->drawLine(startX, (iconHeight/2) + (iconHeight/4),
- startX + 49, (iconHeight/2) + (iconHeight/4));
-
- QPen thickerPen = painter->pen();
- thickerPen.setWidth(2);
- painter->setPen(thickerPen);
- painter->drawLine(startX + 10, 0, startX + 10, iconHeight);
- painter->drawLine(startX, (iconHeight/4), startX + 50, (iconHeight/4));
-
- painter->setPen(textColor());
- painter->setFont(font);
-
- painter->drawText(0, h - fontHeight,
- w, fontHeight, Qt::AlignCenter, name());
-
- UMLWidget::paint(painter, option);
-}
-
-/**
- * draw as a box
- */
-void ArtifactWidget::paintAsNormal(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- int w = width();
- int h = height();
- QFont font = UMLWidget::font();
- font.setBold(true);
- const QFontMetrics &fm = getFontMetrics(FT_BOLD);
- const int fontHeight = fm.lineSpacing();
- QString stereotype = m_umlObject->stereotype();
-
- painter->drawRect(0, 0, w, h);
-
- painter->setPen(textColor());
- painter->setFont(font);
-
- if (!stereotype.isEmpty()) {
- painter->drawText(ARTIFACT_MARGIN, (h/2) - fontHeight,
- w, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true));
- }
-
- int lines;
- if (!stereotype.isEmpty()) {
- lines = 2;
- } else {
- lines = 1;
- }
-
- if (lines == 1) {
- painter->drawText(0, (h/2) - (fontHeight/2),
- w, fontHeight, Qt::AlignCenter, name());
- } else {
- painter->drawText(0, (h/2),
- w, fontHeight, Qt::AlignCenter, name());
- }
-
- UMLWidget::paint(painter, option);
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/artifactwidget.h umbrello-kf6-15.08.1/umbrello/widgets/artifactwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/artifactwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/artifactwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,55 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ARTIFACTWIDGET_H
-#define ARTIFACTWIDGET_H
-
-#include "umlwidget.h"
-
-class UMLScene;
-class UMLArtifact;
-
-#define ARTIFACT_MARGIN 5
-
-/**
- * Defines a graphical version of the @ref UMLArtifact.
- * Most of the functionality will come from the @ref UMLWidget class.
- *
- * @short A graphical version of a Artifact.
- * @author Jonathan Riddell
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class ArtifactWidget : public UMLWidget
-{
-public:
- ArtifactWidget(UMLScene *scene, UMLArtifact *a);
- virtual ~ArtifactWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- // Note: For loading from XMI, the inherited parent method is used.
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
-protected:
- QSizeF minimumSize() const;
-
-private:
- void paintAsFile(QPainter *painter, const QStyleOptionGraphicsItem *option);
- void paintAsLibrary(QPainter *painter, const QStyleOptionGraphicsItem *option);
- void paintAsTable(QPainter *painter, const QStyleOptionGraphicsItem *option);
- void paintAsNormal(QPainter *painter, const QStyleOptionGraphicsItem *option);
-
- QSize calculateIconSize() const;
- QSize calculateNormalSize() const;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/associationline.cpp umbrello-kf6-15.08.1/umbrello/widgets/associationline.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/associationline.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/associationline.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,1404 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "associationline.h"
-
-// application includes
-#include "associationwidget.h"
-#include "debug_utils.h"
-#include "umlwidget.h"
-
-// qt includes
-#include <QDomDocument>
-#include <QPainter>
-
-// system includes
-#include <cstdlib>
-#include <cmath>
-
-DEBUG_REGISTER_DISABLED(AssociationLine)
-
-// Initialize static variables.
-const qreal AssociationLine::Delta = 5;
-const qreal AssociationLine::SelectedPointDiameter = 4;
-const qreal AssociationLine::SelfAssociationMinimumHeight = 30;
-
-/**
- * Constructor.
- * Constructs an AssociationLine item with its parent being \a parent.
- */
-AssociationLine::AssociationLine(AssociationWidget *association)
- : QGraphicsObject(association),
- m_associationWidget(association),
- m_activePointIndex(-1),
- m_activeSegmentIndex(-1),
- m_startSymbol(0),
- m_endSymbol(0),
- m_subsetSymbol(0),
- m_collaborationLineItem(0),
- m_collaborationLineHead(0),
- m_layout(Polyline)
-{
- Q_ASSERT(association);
- setFlag(QGraphicsLineItem::ItemIsSelectable);
- setAcceptHoverEvents(true);
- setZValue(3);
-}
-
-/**
- * Destructor.
- */
-AssociationLine::~AssociationLine()
-{
-}
-
-/**
- * Returns the point at the point index.
- * @return point at given index
- */
-QPointF AssociationLine::point(int index) const
-{
- if ((index < 0) | (index >= m_points.size())) {
- uWarning() << "Index " << index << " out of range [0.." << m_points.size() - 1 << "].";
- return QPointF(-1.0, -1.0);
- }
- return m_points.at(index);
-}
-
-/**
- * Sets the point value at given index to \a point.
- */
-bool AssociationLine::setPoint(int index, const QPointF &point)
-{
- if ((index < 0) | (index >= m_points.size())) {
- uWarning() << "Index " << index << " out of range [0.." << m_points.size() - 1 << "].";
- return false;
- }
- if (m_points.at(index) == point) {
- return false; // nothing to change
- }
- prepareGeometryChange();
- m_points[index] = point;
- alignSymbols();
- return true;
-}
-
-/**
- * Shortcut for point(0).
- */
-QPointF AssociationLine::startPoint() const
-{
- return m_points.at(0);
-}
-
-/**
- * Shortcut for end point.
- */
-QPointF AssociationLine::endPoint() const
-{
- return m_points.at(m_points.size()-1);
-}
-
-/**
- * Inserts the passed in \a point at the \a index passed in and
- * recalculates the bounding rect.
- */
-void AssociationLine::insertPoint(int index, const QPointF &point)
-{
- prepareGeometryChange();
- m_points.insert(index, point);
- alignSymbols();
-}
-
-/**
- * Removes the point at \a index passed in.
- * @see removeNonEndPoint
- */
-void AssociationLine::removePoint(int index)
-{
- prepareGeometryChange();
- m_points.remove(index);
- alignSymbols();
-}
-
-/**
- * Returns the amount of POINTS on the line.
- * Includes start and end points.
- * @return number of points in the AssociationLine
- */
-int AssociationLine::count() const
-{
- return m_points.size();
-}
-
-/**
- * Removes all the points and signals a geometry update.
- */
-void AssociationLine::cleanup()
-{
- if (!m_points.isEmpty()) {
- prepareGeometryChange();
- m_points.clear();
- alignSymbols();
- }
-}
-
-/**
- * This method optimizes the number of points in the
- * AssociationLine. This can be used to reduce the clutter caused
- * due to too many points.
- * TODO: Use delta comparison 'closestPointIndex' instead of exact comparison.
- * TODO: Not used anywhere.
- */
-void AssociationLine::optimizeLinePoints()
-{
- int i = 1;
- prepareGeometryChange();
- while (i < m_points.size()) {
- if (m_points.at(i) == m_points.at(i-1)) {
- m_points.remove(i);
- }
- else {
- ++i;
- }
- }
- alignSymbols();
-}
-
-/**
- * Return index of point closer a given delta.
- *
- * @param point The point which is to be tested for closeness.
- * @param delta The distance the point should be closer to.
- *
- * @retval "Index" of the first line point closer to the \a point passed.
- * @retval -1 If no line point is closer to passed in \a point.
- */
-int AssociationLine::closestPointIndex(const QPointF &point, qreal delta) const
-{
- for(int i = 0; i < m_points.size(); ++i) {
- const QPointF& linePoint = m_points.at(i);
- // Apply distance formula to see point closeness.
- qreal deltaXSquare = (point.x() - linePoint.x()) * (point.x() - linePoint.x());
- qreal deltaYSquare = (point.y() - linePoint.y()) * (point.y() - linePoint.y());
-
- qreal lhs = deltaXSquare + deltaYSquare;
- qreal rhs = delta * delta;
-
- if (lhs <= rhs) {
- return i;
- }
- }
- return -1;
-}
-
-/**
- * Return index of closest segment.
- *
- * @param point The point which is to be tested for closeness.
- *
- * @return Index of the line segment closest to the \a point passed;
- * -1 if no line segment is closer to passed in \a point.
- */
-int AssociationLine::closestSegmentIndex(const QPointF &point, qreal delta) const
-{
- QPainterPathStroker stroker;
- stroker.setWidth(delta);
-
- for(int i = 1; i < m_points.size(); ++i) {
- QLineF segment(m_points[i-1], m_points[i]);
-
- QPainterPath path;
- path.moveTo(segment.p1());
- path.lineTo(segment.p2());
-
- path = stroker.createStroke(path);
-
- if (path.contains(point)) {
- return i-1;
- }
- }
- return -1;
-}
-
-/**
- * Retval True If point at \a index is start or end.
- */
-bool AssociationLine::isEndPointIndex(int index) const
-{
- const int size = m_points.size();
- Q_ASSERT(index >= 0 && index < size);
-
- return (index == 0 || index == (size - 1));
-}
-
-/**
- * Retval True If segment at \a index is start or end.
- */
-bool AssociationLine::isEndSegmentIndex(int index) const
-{
- // num of seg = num of points - 1
- const int size = m_points.size() - 1;
- Q_ASSERT(index >= 0 && index < size);
-
- return (index == 0 || index == (size - 1));
-}
-
-/**
- * Sets the start and end points.
- */
-bool AssociationLine::setEndPoints(const QPointF &start, const QPointF &end)
-{
- const int size = m_points.size();
-
- prepareGeometryChange();
-
- if (size == 0) {
- m_points.insert(0, start);
- m_points.insert(1, end);
- }
- else if (size == 1) {
- m_points[0] = start;
- m_points.insert(1, end);
- }
- else {
- m_points[0] = start;
- m_points[size-1] = end;
- }
-
- alignSymbols();
- return true;
-}
-
-/**
- * Debug helper method to write out the points.
- */
-void AssociationLine::dumpPoints()
-{
- for (int i = 1; i < m_points.size(); ++i) {
- QPointF p = m_points.at(i);
- DEBUG(DBG_SRC) << i << ". point x:" << p.x() << " / y:" << p.y();
- }
-}
-
-/**
- * Loads AssociationLine information saved in \a qElement XMI element.
- */
-bool AssociationLine::loadFromXMI(QDomElement &qElement)
-{
- QString layout = qElement.attribute(QLatin1String("layout"), QLatin1String("polyline"));
- m_layout = fromString(layout);
-
- QDomNode node = qElement.firstChild();
-
- m_points.clear();
-
- QDomElement startElement = node.toElement();
- if(startElement.isNull() || startElement.tagName() != QLatin1String("startpoint")) {
- return false;
- }
- QString x = startElement.attribute(QLatin1String("startx"), QLatin1String("0"));
- qreal nX = x.toFloat();
- QString y = startElement.attribute(QLatin1String("starty"), QLatin1String("0"));
- qreal nY = y.toFloat();
- QPointF startPoint(nX, nY);
-
- node = startElement.nextSibling();
- QDomElement endElement = node.toElement();
- if(endElement.isNull() || endElement.tagName() != QLatin1String("endpoint")) {
- return false;
- }
- x = endElement.attribute(QLatin1String("endx"), QLatin1String("0"));
- nX = x.toFloat();
- y = endElement.attribute(QLatin1String("endy"), QLatin1String("0"));
- nY = y.toFloat();
- QPointF endPoint(nX, nY);
- setEndPoints(startPoint, endPoint);
- QPointF point;
- node = endElement.nextSibling();
- QDomElement element = node.toElement();
- int i = 1;
- while(!element.isNull()) {
- if(element.tagName() == QLatin1String("point")) {
- x = element.attribute(QLatin1String("x"), QLatin1String("0"));
- y = element.attribute(QLatin1String("y"), QLatin1String("0"));
- point.setX(x.toFloat());
- point.setY(y.toFloat());
- insertPoint(i++, point);
- }
- node = element.nextSibling();
- element = node.toElement();
- }
-
- return true;
-}
-
-/**
- * Saves association line information into XMI element named "linepath".
- * @note Stored as linepath for backwared compatibility
- */
-void AssociationLine::saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
-{
- QPointF point = m_associationWidget->mapToScene(startPoint());
- QDomElement lineElement = qDoc.createElement(QLatin1String("linepath"));
- lineElement.setAttribute(QLatin1String("layout"), toString(m_layout));
- QDomElement startElement = qDoc.createElement(QLatin1String("startpoint"));
- startElement.setAttribute(QLatin1String("startx"), point.x());
- startElement.setAttribute(QLatin1String("starty"), point.y());
- lineElement.appendChild(startElement);
- QDomElement endElement = qDoc.createElement(QLatin1String("endpoint"));
- point = m_associationWidget->mapToScene(endPoint());
- endElement.setAttribute(QLatin1String("endx"), point.x());
- endElement.setAttribute(QLatin1String("endy"), point.y());
- lineElement.appendChild(endElement);
- for(int i = 1; i < count()-1; ++i) {
- QDomElement pointElement = qDoc.createElement(QLatin1String("point"));
- point = m_associationWidget->mapToScene(this->point(i));
- pointElement.setAttribute(QLatin1String("x"), point.x());
- pointElement.setAttribute(QLatin1String("y"), point.y());
- lineElement.appendChild(pointElement);
- }
- qElement.appendChild(lineElement);
-}
-
-/**
- * Returns the type of brush to use depending on the type of Association.
- */
-QBrush AssociationLine::brush() const
-{
- QBrush brush(Qt::solid-kf6Pattern);
- Uml::AssociationType::Enum type = m_associationWidget->associationType();
- if (type == Uml::AssociationType::Aggregation ||
- type == Uml::AssociationType::Generalization ||
- type == Uml::AssociationType::Realization) {
- brush.setColor(Qt::white);
- }
- if (type == Uml::AssociationType::Composition) {
- brush.setColor(m_associationWidget->lineColor());
- }
- return brush;
-}
-
-/**
- * Returns the type of pen to use depending on the type of Association.
- */
-QPen AssociationLine::pen() const
-{
- QPen pen(m_associationWidget->lineColor(),
- m_associationWidget->lineWidth(),
- Qt::solid-kf6Line,
- Qt::RoundCap,
- Qt::RoundJoin);
- Uml::AssociationType::Enum type = m_associationWidget->associationType();
- if (type == Uml::AssociationType::Dependency ||
- type == Uml::AssociationType::Realization ||
- type == Uml::AssociationType::Anchor) {
- pen.setStyle(Qt::DashLine);
- }
- return pen;
-}
-
-/**
- * This method simply ensures presence of two points and
- * adds the needed points for self associations.
- */
-void AssociationLine::calculateInitialEndPoints()
-{
- if (m_associationWidget->isSelf() && count() < 4) {
- for (int i = count(); i < 4; ++i) {
- insertPoint(i, QPointF());
- }
- UMLWidget *wid = m_associationWidget->widgetForRole(Uml::RoleType::B);
- if (!wid) {
- uError() << "AssociationWidget is partially constructed."
- "UMLWidget for role B is null.";
- return;
- }
- const QRectF rect = m_associationWidget->mapFromScene(
- mapToScene(wid->rect()).boundingRect()).boundingRect();
-
- qreal l = rect.left() + .25 * rect.width();
- qreal r = rect.left() + .75 * rect.width();
- bool drawAbove = rect.top() >= SelfAssociationMinimumHeight;
- qreal y = drawAbove ? rect.top() : rect.bottom();
- qreal yOffset = SelfAssociationMinimumHeight;
- if (drawAbove) {
- yOffset *= -1.0;
- }
-
- setPoint(0, QPointF(l, y));
- setPoint(1, QPointF(l, y + yOffset));
- setPoint(2, QPointF(r, y + yOffset));
- setPoint(3, QPointF(r, y));
- } else if (!m_associationWidget->isSelf() && count() < 2) {
- setEndPoints(QPointF(), QPointF());
- }
-}
-
-/**
- * This method creates, deletes symbols and collaboration lines based on
- * m_associationWidget->associationType().
- *
- * Call this method when associationType of m_associationWidget changes.
- */
-void AssociationLine::reconstructSymbols()
-{
- switch( m_associationWidget->associationType() ) {
- case Uml::AssociationType::State:
- case Uml::AssociationType::Activity:
- case Uml::AssociationType::Exception:
- case Uml::AssociationType::UniAssociation:
- case Uml::AssociationType::Dependency:
- setStartSymbol(Symbol::None);
- setEndSymbol(Symbol::OpenArrow);
- removeSubsetSymbol();
- removeCollaborationLine();
- break;
-
- case Uml::AssociationType::Relationship:
- setStartSymbol(Symbol::None);
- setEndSymbol(Symbol::CrowFeet);
- removeSubsetSymbol();
- removeCollaborationLine();
- break;
-
- case Uml::AssociationType::Generalization:
- case Uml::AssociationType::Realization:
- setStartSymbol(Symbol::None);
- setEndSymbol(Symbol::ClosedArrow);
- removeSubsetSymbol();
- removeCollaborationLine();
- break;
-
- case Uml::AssociationType::Composition:
- case Uml::AssociationType::Aggregation:
- setStartSymbol(Symbol::Diamond);
- setEndSymbol(Symbol::None);
- removeSubsetSymbol();
- removeCollaborationLine();
- break;
-
- case Uml::AssociationType::Containment:
- setStartSymbol(Symbol::Circle);
- setEndSymbol(Symbol::None);
- removeSubsetSymbol();
- removeCollaborationLine();
- break;
-
- case Uml::AssociationType::Child2Category:
- setStartSymbol(Symbol::None);
- setEndSymbol(Symbol::None);
- createSubsetSymbol();
- removeCollaborationLine();
- break;
-
- case Uml::AssociationType::Coll_Message_Synchronous:
- case Uml::AssociationType::Coll_Message_Asynchronous:
- case Uml::AssociationType::Coll_Message_Self:
- setStartSymbol(Symbol::None);
- setEndSymbol(Symbol::None);
- removeSubsetSymbol();
- createCollaborationLine();
- break;
-
- default:
- break;
- }
- alignSymbols();
-}
-
-/**
- * Sets the Symbol to appear at the first line segment to \a symbol.
- *
- * If symbol == Symbol::None , then it deletes the symbol item.
- */
-void AssociationLine::setStartSymbol(Symbol::SymbolType symbolType)
-{
- Q_ASSERT(symbolType != Symbol::Count);
- if (symbolType == Symbol::None) {
- delete m_startSymbol;
- m_startSymbol = 0;
- return;
- }
-
- if (m_startSymbol) {
- m_startSymbol->setSymbolType(symbolType);
- }
- else {
- m_startSymbol = new Symbol(symbolType, m_associationWidget);
- }
- m_startSymbol->setPen(pen());
- m_startSymbol->setBrush(brush());
-}
-
-/**
- * Sets the Symbol to appear at the last line segment to \a symbol.
- *
- * If symbol == Symbol::None , then it deletes the symbol item.
- */
-void AssociationLine::setEndSymbol(Symbol::SymbolType symbolType)
-{
- Q_ASSERT(symbolType != Symbol::Count);
- if (symbolType == Symbol::None) {
- delete m_endSymbol;
- m_endSymbol = 0;
- return;
- }
-
- if (m_endSymbol) {
- m_endSymbol->setSymbolType(symbolType);
- }
- else {
- m_endSymbol = new Symbol(symbolType, m_associationWidget);
- }
- m_endSymbol->setPen(pen());
- m_endSymbol->setBrush(brush());
-}
-
-/**
- * Constructs a new subset symbol.
- */
-void AssociationLine::createSubsetSymbol()
-{
- delete m_subsetSymbol; // recreate
- m_subsetSymbol = new Symbol(Symbol::Subset, m_associationWidget);
- m_subsetSymbol->setPen(pen());
- m_subsetSymbol->setBrush(brush());
-}
-
-/**
- * Removes the subset symbol if it existed by deleting appropriate items.
- */
-void AssociationLine::removeSubsetSymbol()
-{
- delete m_subsetSymbol;
- m_subsetSymbol = 0;
-}
-
-/**
- * Constructs the open arrow symbol and arrow line, that would represent Collaboration line.
- */
-void AssociationLine::createCollaborationLine()
-{
- const QPen p = pen();
-
- // recreate
- delete m_collaborationLineItem;
- delete m_collaborationLineHead;
-
- m_collaborationLineItem = new QGraphicsLineItem(m_associationWidget);
- m_collaborationLineItem->setPen(p);
-
- if (m_associationWidget->associationType() == Uml::AssociationType::Coll_Message_Synchronous) {
- m_collaborationLineHead = new Symbol(Symbol::ClosedArrow, m_associationWidget);
- m_collaborationLineHead->setBrush(p.color());
- }
- else
- m_collaborationLineHead = new Symbol(Symbol::OpenArrow, m_associationWidget);
- m_collaborationLineHead->setPen(p);
-}
-
-/**
- * Removes collaboration line by deleting the head and line item.
- */
-void AssociationLine::removeCollaborationLine()
-{
- delete m_collaborationLineItem;
- m_collaborationLineItem = 0;
-
- delete m_collaborationLineHead;
- m_collaborationLineHead = 0;
-}
-
-/**
- * This method aligns both the \b "start" and \b "end" symbols to
- * the current angles of the \b "first" and the \b "last" line
- * segment respectively.
- */
-void AssociationLine::alignSymbols()
-{
- const int sz = m_points.size();
- if (sz < 2) {
- // cannot align if there is no line (one line = 2 points)
- return;
- }
-
- QList<QPolygonF> polygons = path().toSubpathPolygons();
-
- if (m_startSymbol) {
- QPolygonF firstLine = polygons.first();
- QLineF segment(firstLine.at(1), firstLine.at(0));
- m_startSymbol->alignTo(segment);
- }
-
- if (m_endSymbol) {
- QPolygonF lastLine = polygons.last();
- int maxIndex = lastLine.size();
- QLineF segment(lastLine.at(maxIndex-2), lastLine.at(maxIndex-1));
- m_endSymbol->alignTo(segment);
- }
-
- if (m_subsetSymbol) {
- QPointF p1 = path().pointAtPercent(0.4);
- QPointF p2 = path().pointAtPercent(0.5);
- QLineF segment(p1, p2);
- m_subsetSymbol->alignTo(segment);
- }
-
- if (m_collaborationLineItem) {
- const qreal distance = 10;
- const int midSegmentIndex = (sz - 1) / 2;
-
- const QPointF a = m_points.at(midSegmentIndex);
- const QPointF b = m_points.at(midSegmentIndex + 1);
-
- if (a == b)
- return;
-
- const QPointF p1 = (a + b) / 2.0;
- const QPointF p2 = (p1 + b) / 2.0;
-
- // Reversed line as we want normal in opposite direction.
- QLineF segment(p2, p1);
- QLineF normal = segment.normalVector().unitVector();
- normal.setLength(distance);
-
- QLineF actualLine;
- actualLine.setP2(normal.p2());
-
- normal.translate(p1 - p2);
- actualLine.setP1(normal.p2());
-
- m_collaborationLineItem->setLine(actualLine);
- m_collaborationLineHead->alignTo(actualLine);
- }
-}
-
-/**
- * @return The path of the AssociationLine.
- */
-QPainterPath AssociationLine::path() const
-{
- if (m_points.count() > 0) {
- QPainterPath path;
- switch (m_layout) {
- case Direct:
- path.moveTo(m_points.first());
- path.lineTo(m_points.last());
- break;
-
- case Spline:
- path = createBezierCurve(m_points);
- break;
-
- case Orthogonal:
- path = createOrthogonalPath(m_points);
- break;
-
- case Polyline:
- default:
- QPolygonF polygon(m_points);
- path.addPolygon(polygon);
- break;
- }
- return path;
- }
- else {
- return QPainterPath();
- }
-}
-
-/**
- * The points are used for the bounding rect. The reason is,
- * that for splines the control points are further away from the path.
- * @return The bounding rectangle for the AssociationLine.
- */
-QRectF AssociationLine::boundingRect() const
-{
- QPolygonF polygon(m_points);
- QRectF rect = polygon.boundingRect();
- const qreal margin(5.0);
- rect.adjust(-margin, -margin, margin, margin);
- return rect;
-}
-
-/**
- * @return The shape of the AssociationLine.
- */
-QPainterPath AssociationLine::shape() const
-{
- QPainterPathStroker stroker;
- stroker.setWidth(qMax<qreal>(2*SelectedPointDiameter, pen().widthF()) + 2.0); // allow delta region
- stroker.setCapStyle(Qt::FlatCap);
- return stroker.createStroke(path());
-}
-
-/**
- * Convert enum LayoutType to string.
- */
-QString AssociationLine::toString(LayoutType layout)
-{
- return QLatin1String(ENUM_NAME(AssociationLine, LayoutType, layout));
-}
-
-/**
- * Convert string to enum LayoutType.
- */
-AssociationLine::LayoutType AssociationLine::fromString(const QString &layout)
-{
- if (layout == QLatin1String("Direct"))
- return Direct;
- if (layout == QLatin1String("Spline"))
- return Spline;
- if (layout == QLatin1String("Orthogonal"))
- return Orthogonal;
- return Polyline;
-}
-
-/**
- * Return the layout type of the association line.
- * @return the currently used layout
- */
-AssociationLine::LayoutType AssociationLine::layout() const
-{
- return m_layout;
-}
-
-/**
- * Set the layout type of the association line.
- * @param layout the desired layout to set
- */
-void AssociationLine::setLayout(LayoutType layout)
-{
- prepareGeometryChange();
- m_layout = layout;
- DEBUG(DBG_SRC) << "new layout = " << toString(m_layout);
- if (m_layout == Spline) {
- createSplinePoints();
- }
- alignSymbols();
-}
-
-/**
- * For a cubic Bezier curve at least four points are needed.
- * If there are less, the missing points will be created.
- * Note: Implementation is only for two points.
- */
-void AssociationLine::createSplinePoints()
-{
- if (m_points.size() == 2) { // create two points
- QPointF p1 = m_points.first(); // start point
- QPointF p2 = m_points.last(); // end point
- qreal dx = p2.x() - p1.x();
- qreal dy = p2.y() - p1.y();
- qreal oneThirdX = 0.33 * dx;
- qreal oneThirdY = 0.33 * dy;
- QPointF c1(p1.x() + oneThirdX, // control point 1
- p1.y() - oneThirdY);
- QPointF c2(p2.x() - oneThirdX, // control point 2
- p2.y() + oneThirdY);
- insertPoint(1, c1);
- insertPoint(2, c2);
- }
- if (m_points.size() == 3) { // create one point
- // insertPoint(1 or 2, );
- // Note: For now we use a quadratic Bezier curve in createBezierCurve(...).
- }
-}
-
-/**
- * Returns a Bézier path from given points.
- * @param points points which define the Bézier curve
- * @return cubic Bézier spline
- */
-QPainterPath AssociationLine::createBezierCurve(QVector<QPointF> points)
-{
- QPainterPath path;
- if (points.size() > 3) { // cubic Bezier curve(s)
- path.moveTo(points.at(0));
- int i = 1;
- while (i + 2 < points.size()) {
- path.cubicTo(points.at(i), points.at(i+1), points.at(i+2));
- i += 3;
- }
- while (i < points.size()) { // draw a line if points are not modulo 3
- path.lineTo(points.at(i));
- ++i;
- }
- }
- else {
- if (points.size() == 3) { // quadratic Bezier curve
- path.moveTo(points.at(0));
- path.quadTo(points.at(1), points.at(2));
- }
- else { // should not be reached
- QPolygonF polygon(points);
- path.addPolygon(polygon);
- }
- }
- return path;
-}
-
-/**
- * Returns an orthogonal path constructed of vertical and horizontal segments
- * through the given points.
- * @param points base points for the path
- * @return orthogonal path
- */
-QPainterPath AssociationLine::createOrthogonalPath(QVector<QPointF> points)
-{
- QPainterPath path;
- if (points.size() > 1) {
- QPointF start = points.first();
- QPointF end = points.last();
- qreal deltaX = fabs(start.x() - end.x());
- qreal deltaY = fabs(start.y() - end.y());
- // DEBUG("AssociationLine") << "start=" << start << " / end=" << end
- // << " / deltaX=" << deltaX << " / deltaY=" << deltaY;
- QVector<QPointF> vector;
- for (int i = 0; i < points.size() - 1; ++i) {
- QPointF curr = points.at(i);
- QPointF next = points.at(i+1);
- QPointF center = (next + curr)/2.0;
-
- vector.append(curr);
- if (deltaX < deltaY) {
- // go vertical first
- vector.append(QPointF(curr.x(), center.y()));
- vector.append(QPointF(next.x(), center.y()));
- }
- else {
- // go horizontal first
- vector.append(QPointF(center.x(), curr.y()));
- vector.append(QPointF(center.x(), next.y()));
- }
- vector.append(next);
- }
-
- QPolygonF rectLine(vector);
- path.addPolygon(rectLine);
- }
- else {
- QPolygonF polygon(points);
- path.addPolygon(polygon);
- }
- return path;
-}
-
-/**
- * Reimplemented from QGraphicsItem::paint.
- * Draws the AssociationLine and also takes care of highlighting active point or line.
- */
-void AssociationLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
-{
- Q_UNUSED(widget)
- QPen _pen = pen();
- const QColor orig = _pen.color().lighter();
- QColor invertedColor(orig.green(), orig.blue(), orig.red());
- if (invertedColor == _pen.color()) {
- // Ensure different color.
- invertedColor.setRed((invertedColor.red() + 50) % 256);
- }
- invertedColor.setAlpha(150);
-
- int sz = m_points.size();
- if (sz < 1) {
- // not enough points - do nothing
- return;
- }
-
- QPointF savedStart = m_points.first();
- QPointF savedEnd = m_points.last();
-
- // modify the m_points array not to include the Symbol, the value depends on Symbol
- if (m_startSymbol) {
- QPointF newStart = m_startSymbol->mapToParent(m_startSymbol->symbolEndPoints().first);
- m_points[0] = newStart;
- }
-
- if (m_endSymbol) {
- QPointF newEnd = m_endSymbol->mapToParent(m_endSymbol->symbolEndPoints().first);
- m_points[sz - 1] = newEnd;
- }
-
- painter->setPen(_pen);
- painter->setBrush(Qt::NoBrush);
- painter->drawPath(path());
-
- if (option->state & QStyle::State_Selected) {
- // make the association broader in the selected state
- QPainterPathStroker stroker;
- stroker.setWidth(3.0);
- QPainterPath outline = stroker.createStroke(path());
- QColor shadowColor(Qt::lightGray);
- shadowColor.setAlpha(80);
- QBrush shadowBrush(shadowColor);
- painter->setBrush(shadowBrush);
- painter->setPen(Qt::NoPen);
- painter->drawPath(outline);
-
- // set color for selected painting
- _pen.setColor(Qt::blue);
- QRectF circle(0, 0, SelectedPointDiameter, SelectedPointDiameter);
- painter->setBrush(_pen.color());
- painter->setPen(Qt::NoPen);
-
- // draw points
- circle.moveCenter(savedStart);
- painter->drawRect(circle);
- for (int i = 1; i < sz-1; ++i) {
- if (i != m_activePointIndex) {
- circle.moveCenter(m_points.at(i));
- painter->drawRect(circle);
- }
- }
- circle.moveCenter(savedEnd);
- painter->drawRect(circle);
-
- if (m_activePointIndex != -1) {
- painter->setBrush(invertedColor);
- painter->setPen(Qt::NoPen);
- circle.setWidth(1.5*SelectedPointDiameter);
- circle.setHeight(1.5*SelectedPointDiameter);
- circle.moveCenter(m_points.at(m_activePointIndex));
- painter->drawEllipse(circle);
- }
- else if (m_activeSegmentIndex != -1) {
- if (m_layout == Polyline) {
- painter->setPen(QPen(invertedColor, _pen.widthF() + 1));
- painter->setBrush(Qt::NoBrush);
-
- QLineF segmentLine(m_points[m_activeSegmentIndex], m_points[m_activeSegmentIndex + 1]);
- painter->drawLine(segmentLine);
- }
- }
- // debug info
- if (Tracer::instance()->isEnabled(QString::fromLatin1(metaObject()->className()))) {
- painter->setPen(Qt::green);
- painter->setBrush(Qt::NoBrush);
- painter->drawPath(shape());
- painter->setPen(Qt::red);
- painter->drawRect(boundingRect());
- // origin
- painter->drawLine(-10, 0, 10, 0);
- painter->drawLine(0, -10, 0, 10);
- }
-
- }
-
- // now restore the points array
- m_points[0] = savedStart;
- m_points[sz - 1] = savedEnd;
-}
-
-/**
- * Determines the active point or segment, the latter being given more priority.
- */
-void AssociationLine::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
- DEBUG(DBG_SRC) << "at " << event->scenePos();
- if (event->buttons() & Qt::LeftButton) {
- m_activePointIndex = closestPointIndex(event->scenePos());
- if (m_activePointIndex != -1 && isEndPointIndex(m_activePointIndex)) {
- // end points are not drawn and hence not active
- m_activePointIndex = -1;
- }
- // calculate only if active point index is -1
- m_activeSegmentIndex = (m_activePointIndex != -1) ? -1 : closestSegmentIndex(event->scenePos());
- }
- else if (event->buttons() & Qt::RightButton) {
- DEBUG(DBG_SRC) << "call context menu of association widget at " << event->scenePos();
- }
- else {
- m_activePointIndex = -1;
- m_activeSegmentIndex = -1;
- }
-}
-
-/**
- * Moves the point or line if active.
- */
-void AssociationLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
-{
- UMLScene* scene = m_associationWidget->umlScene();
-
- QPointF oldPos = event->scenePos();
- QPointF newPos(
- scene->snappedX(oldPos.x()),
- scene->snappedY(oldPos.y())
- );
-
- // Prevent the moving vertex from disappearing underneath a widget
- // (else there's no way to get it back.)
- UMLWidget *onW = scene->widgetAt(newPos);
- if (onW && onW->baseType() != WidgetBase::wt_Box) { // boxes are transparent
- const qreal pX = newPos.x();
- const qreal pY = newPos.y();
- const qreal wX = onW->x();
- const qreal wY = onW->y();
- const qreal wWidth = onW->width();
- const qreal wHeight = onW->height();
- if (pX > wX && pX < wX + wWidth) {
- const qreal midX = wX + wWidth / 2.0;
- if (pX <= midX)
- newPos.setX(wX);
- else
- newPos.setX(wX + wWidth);
- }
- if (pY > wY && pY < wY + wHeight) {
- const qreal midY = wY + wHeight / 2.0;
- if (pY <= midY)
- newPos.setY(wY);
- else
- newPos.setY(wY + wHeight);
- }
- }
-
- if (m_activePointIndex != -1) {
- // Move a single point (snap behaviour)
- setPoint(m_activePointIndex, newPos);
- }
- else if (m_activeSegmentIndex != -1 && !isEndSegmentIndex(m_activeSegmentIndex)) {
- // Move a segment (between two points, snap behaviour not implemented)
- QPointF delta = event->scenePos() - event->lastScenePos();
- setPoint(m_activeSegmentIndex, m_points[m_activeSegmentIndex] + delta);
- setPoint(m_activeSegmentIndex + 1, m_points[m_activeSegmentIndex + 1] + delta);
- }
-}
-
-/**
- * Reset active indices and also push undo command.
- */
-void AssociationLine::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
-{
- if (event->buttons() & Qt::LeftButton) {
- m_activeSegmentIndex = -1;
- m_activePointIndex = -1;
- }
-}
-
-/**
- * Calculates the "to be highlighted" point and segment indicies
- * and updates if necessary.
- */
-void AssociationLine::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
-{
- DEBUG(DBG_SRC) << "at " << event->scenePos();
- int oldPointIndex = m_activePointIndex;
- int oldSegmentIndex = m_activeSegmentIndex;
-
- m_activePointIndex = closestPointIndex(event->scenePos());
- // End points are not drawn and hence not active.
- if (m_activePointIndex != -1 && isEndPointIndex(m_activePointIndex)) {
- m_activePointIndex = -1;
- }
- // Activate segment index only if point index is -1
- m_activeSegmentIndex = (m_activePointIndex != -1) ? -1 : closestSegmentIndex(event->scenePos());
-
- bool isChanged = (oldSegmentIndex != m_activeSegmentIndex || oldPointIndex != m_activePointIndex);
- if (isChanged) {
- m_associationWidget->update();
- }
-}
-
-/**
- * Calculates the "to be highlighted" point and segment indicies
- * and updates if necessary.
- */
-void AssociationLine::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
-{
- int oldPointIndex = m_activePointIndex;
- int oldSegmentIndex = m_activeSegmentIndex;
-
- m_activePointIndex = closestPointIndex(event->scenePos());
- // End points are not drawn and hence not active.
- if (m_activePointIndex != -1 && isEndPointIndex(m_activePointIndex)) {
- m_activePointIndex = -1;
- }
- // Activate segment index only if point index is -1
- m_activeSegmentIndex = (m_activePointIndex != -1) ? -1 : closestSegmentIndex(event->scenePos());
-
- bool isChanged = (oldSegmentIndex != m_activeSegmentIndex || oldPointIndex != m_activePointIndex);
- if (isChanged) {
- m_associationWidget->update();
- }
-}
-
-/**
- * Reset active indicies and updates.
- */
-void AssociationLine::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
-{
- DEBUG(DBG_SRC) << "at " << event->scenePos();
- //Q_UNUSED(event)
- m_activePointIndex = -1;
- m_activeSegmentIndex = -1;
- m_associationWidget->update();
-}
-
-//-----------------------------------------------------------------------------
-
-/**
- * SymbolEndPoints:
- * The first point is where the AssociationLine's visible line is
- * supposed to end.
- * The second points is where the actual symbol part is to appear.
- */
-Symbol::SymbolProperty Symbol::symbolTable[Count] =
-{
- {
- QRectF(-6, 0, 12, 10), QPainterPath(), QLineF(0, 0, 0, 10),
- SymbolEndPoints(QPointF(0, 10), QPointF(0, 10))
- },
- {
- QRectF(-6, 0, 12, 10), QPainterPath(), QLineF(0, 0, 0, 10),
- SymbolEndPoints(QPointF(0, 0), QPointF(0, 10))
- },
- {
- QRectF(-6, 0, 12, 10), QPainterPath(), QLineF(0, 0, 0, 10),
- SymbolEndPoints(QPointF(0, 10), QPointF(0, 10))
- },
- {
- QRectF(-5, -10, 10, 20), QPainterPath(), QLineF(0, -10, 0, 10),
- SymbolEndPoints(QPointF(0, -10), QPointF(0, 10))
- },
- {
- QRectF(-15, -10, 30, 20), QPainterPath(), QLineF(-10, 0, 0, 0),
- SymbolEndPoints(QPointF(0, 0), QPointF(0, 0))
- },
- {
- QRectF(-8, -8, 16, 16), QPainterPath(), QLineF(0, -8, 0, 8),
- SymbolEndPoints(QPointF(0, -8), QPointF(0, 8))
- }
-
-};
-
-/**
- * @internal A convenience method to setup shapes of all symbols.
- */
-void Symbol::setupSymbolTable()
-{
- SymbolProperty &openArrow = symbolTable[OpenArrow];
- if (openArrow.shape.isEmpty()) {
- QRectF rect = openArrow.boundRect;
- // Defines a 'V' shape arrow fitting in the bound rect.
- openArrow.shape.moveTo(rect.topLeft());
- openArrow.shape.lineTo(rect.center().x(), rect.bottom());
- openArrow.shape.lineTo(rect.topRight());
- }
-
- SymbolProperty &closedArrow = symbolTable[ClosedArrow];
- if (closedArrow.shape.isEmpty()) {
- QRectF rect = closedArrow.boundRect;
- // Defines a 'V' shape arrow fitting in the bound rect.
- closedArrow.shape.moveTo(rect.topLeft());
- closedArrow.shape.lineTo(rect.center().x(), rect.bottom());
- closedArrow.shape.lineTo(rect.topRight());
- closedArrow.shape.lineTo(rect.topLeft());
- }
-
- SymbolProperty &crowFeet = symbolTable[CrowFeet];
- if (crowFeet.shape.isEmpty()) {
- QRectF rect = crowFeet.boundRect;
- // Defines a crowFeet fitting in the bound rect.
- QPointF topMid(rect.center().x(), rect.top());
-
- // left leg
- crowFeet.shape.moveTo(rect.bottomLeft());
- crowFeet.shape.lineTo(topMid);
-
- // middle leg
- crowFeet.shape.moveTo(rect.center().x(), rect.bottom());
- crowFeet.shape.lineTo(topMid);
-
- // right leg
- crowFeet.shape.moveTo(rect.bottomRight());
- crowFeet.shape.lineTo(topMid);
- }
-
- SymbolProperty &diamond = symbolTable[Diamond];
- if (diamond.shape.isEmpty()) {
- QRectF rect = diamond.boundRect;
- // Defines a 'diamond' shape fitting in the bound rect.
- diamond.shape.moveTo(rect.center().x(), rect.top());
- diamond.shape.lineTo(rect.left(), rect.center().y());
- diamond.shape.lineTo(rect.center().x(), rect.bottom());
- diamond.shape.lineTo(rect.right(), rect.center().y());
- diamond.shape.lineTo(rect.center().x(), rect.top());
- }
-
- SymbolProperty &subset = symbolTable[Subset];
- if (subset.shape.isEmpty()) {
- QRectF rect = subset.boundRect;
- // Defines an arc fitting in bound rect.
- qreal start = 90, span = 180;
- subset.shape.arcMoveTo(rect, start);
- subset.shape.arcTo(rect, start, span);
- }
-
- SymbolProperty &circle = symbolTable[Circle];
- if (circle.shape.isEmpty()) {
- QRectF rect = circle.boundRect;
- // Defines a circle with a horizontal-vertical cross lines.
- circle.shape.addEllipse(rect);
-
- circle.shape.moveTo(rect.center().x(), rect.top());
- circle.shape.lineTo(rect.center().x(), rect.bottom());
-
- circle.shape.moveTo(rect.left(), rect.center().y());
- circle.shape.lineTo(rect.right(), rect.center().y());
- }
-
-}
-
-/**
- * Constructs a Symbol with current symbol being \a symbol and
- * parented to \a parent.
- */
-Symbol::Symbol(SymbolType symbolType, QGraphicsItem *parent)
- : QGraphicsItem(parent),
- m_symbolType(symbolType)
-{
- // ensure SymbolTable is validly initialized
- setupSymbolTable();
-}
-
-/**
- * Destructor.
- */
-Symbol::~Symbol()
-{
-}
-
-/**
- * @return The current symbol being represented.
- */
-Symbol::SymbolType Symbol::symbolType() const
-{
- return m_symbolType;
-}
-
-/**
- * Sets the current symbol type to \a symbol and updates the geometry.
- */
-void Symbol::setSymbolType(SymbolType symbolType)
-{
- prepareGeometryChange(); // calls update implicitly
- m_symbolType = symbolType;
-}
-
-/**
- * Draws the current symbol using the QPainterPath stored for the current
- * symbol.
- */
-void Symbol::paint(QPainter *painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
-{
- Q_UNUSED(option) Q_UNUSED(widget)
- painter->setPen(m_pen);
- switch (m_symbolType) {
- case ClosedArrow:
- case CrowFeet:
- case Diamond:
- painter->setBrush(m_brush);
- break;
- default:
- break;
- }
- painter->drawPath(Symbol::symbolTable[m_symbolType].shape);
-}
-
-/**
- * @return The bound rectangle for this based on current symbol.
- */
-QRectF Symbol::boundingRect() const
-{
- const qreal adj = .5 * m_pen.widthF();
- return Symbol::symbolTable[m_symbolType].boundRect.
- adjusted(-adj, -adj, adj, adj);
-}
-
-/**
- * @return The path for this based on current symbol.
- */
-QPainterPath Symbol::shape() const
-{
- QPainterPath path;
- path.addRect(boundingRect());
- return path;
-}
-
-/**
- * This method aligns *this* Symbol to the line being
- * passed. That is, it ensures that the axis of this symbol aligns
- * exactly with the \a "to" line passed.
- *
- * Also this item is moved such that the second end point of the
- * SymbolEndPoints for the current symbol *collides* with the second end
- * point of \a "to" line.
- */
-void Symbol::alignTo(const QLineF& to)
-{
- QLineF toMapped(mapFromParent(to.p1()), mapFromParent(to.p2()));
-
- QLineF origAxis = Symbol::symbolTable[m_symbolType].axisLine;
- QLineF translatedAxis = origAxis.translated(toMapped.p2() - origAxis.p2());
-
- qreal angle = translatedAxis.angleTo(toMapped);
- setRotation(rotation() - angle);
-
- QPointF delta = to.p2() - mapToParent(symbolEndPoints().second);
- moveBy(delta.x(), delta.y());
-}
-
-/**
- * @return The end points for the symbol.
- */
-Symbol::SymbolEndPoints Symbol::symbolEndPoints() const
-{
- return Symbol::symbolTable[m_symbolType].endPoints;
-}
-
-/**
- * @return The pen used to draw symbol.
- */
-QPen Symbol::pen() const
-{
- return m_pen;
-}
-
-/**
- * Sets the pen used to draw the symbol.
- */
-void Symbol::setPen(const QPen& pen)
-{
- prepareGeometryChange();
- m_pen = pen;
- if (m_symbolType == ClosedArrow)
- m_pen.setStyle(Qt::solid-kf6Line);
-}
-
-/**
- * @return The brush used to fill symbol.
- */
-QBrush Symbol::brush() const
-{
- return m_brush;
-}
-
-/**
- * Sets the brush used to fill symbol.
- */
-void Symbol::setBrush(const QBrush &brush)
-{
- m_brush = brush;
- update();
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/associationline.h umbrello-kf6-15.08.1/umbrello/widgets/associationline.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/associationline.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/associationline.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,207 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ASSOCIATIONLINE_H
-#define ASSOCIATIONLINE_H
-
-#include "basictypes.h"
-
-#include <QGraphicsObject>
-#include <QList>
-#include <QPen>
-#include <QPoint>
-
-// forward declarations
-class AssociationWidget;
-class QDomDocument;
-class QDomElement;
-class QPainter;
-
-/**
- * This class provides with various symbols that can be embedded in
- * AssociationLine. It also provides with convenience methods to align
- * the symbol to AssociationLine.
- */
-class Symbol : public QGraphicsItem
-{
- public:
- typedef QPair<QPointF, QPointF> SymbolEndPoints;
-
- /**
- * This enumeration lists all the symbols that can be used as
- * embedded on AssociationLine.
- */
- enum SymbolType {
- None = -1,
- OpenArrow,
- ClosedArrow,
- CrowFeet,
- Diamond,
- Subset,
- Circle,
- Count
- };
-
- explicit Symbol(SymbolType symbolType, QGraphicsItem *parent = 0);
- virtual ~Symbol();
-
- SymbolType symbolType() const;
- void setSymbolType(SymbolType symbolType);
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
-
- virtual QRectF boundingRect() const;
- virtual QPainterPath shape() const;
-
- void alignTo(const QLineF& line);
- SymbolEndPoints symbolEndPoints() const;
-
- QPen pen() const;
- void setPen(const QPen &pen);
-
- QBrush brush() const;
- void setBrush(const QBrush& brush);
-
- private:
- QPen m_pen; ///< pen used to draw Symbol
- QBrush m_brush; ///< brush used to fill Symbol
- SymbolType m_symbolType; ///< current symbol being represented by this item
-
- /// A structure to hold a table of values for all symbols.
- struct SymbolProperty {
- QRectF boundRect;
- QPainterPath shape;
- QLineF axisLine;
- SymbolEndPoints endPoints;
- };
-
- static SymbolProperty symbolTable[Symbol::Count]; ///< a table which stores all symbol properties
- static void setupSymbolTable();
-};
-
-/**
- * A convenience class that encapsulates geometry management, handles
- * mouse and hover events, embeds and aligns symbols and finally draws the
- * lines and points.
- * Context menu events are handled in AssociationWidget.
- *
- * This class is infact a draw and event handling proxy for
- * AssociationWidget.
- *
- * @note m_activePointIndex and m_activeSegmentIndex can't be
- * active at same time!
- *
- * @author Gopala Krishna
- * @author Andi Fischer
- * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
- */
-class AssociationLine : public QGraphicsObject
-{
- Q_OBJECT
- Q_ENUMS(LayoutType)
-public:
- enum LayoutType {
- Direct = 1,
- Orthogonal,
- Polyline,
- Spline
- };
-
- static QString toString(LayoutType layout);
- static LayoutType fromString(const QString& layout);
-
- explicit AssociationLine(AssociationWidget *association);
- virtual ~AssociationLine();
-
- QPointF point(int index) const;
- bool setPoint(int index, const QPointF& point);
- QPointF startPoint() const;
- QPointF endPoint() const;
-
- void insertPoint(int index, const QPointF& point);
- void removePoint(int index);
-
- int count() const;
- void cleanup();
-
- void optimizeLinePoints();
-
- int closestPointIndex(const QPointF& point, qreal delta = Delta) const;
- int closestSegmentIndex(const QPointF& point, qreal delta = Delta) const;
-
- bool isEndPointIndex(int index) const;
- bool isEndSegmentIndex(int index) const;
-
- bool setEndPoints(const QPointF &start, const QPointF &end);
-
- void dumpPoints();
-
- bool loadFromXMI(QDomElement &qElement);
- void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
-
- QBrush brush() const;
- QPen pen() const;
-
- virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
-
- QPainterPath path() const;
-
- QRectF boundingRect() const;
- QPainterPath shape() const;
-
- LayoutType layout() const;
- void setLayout(LayoutType layout);
-
- void mousePressEvent(QGraphicsSceneMouseEvent *event);
- void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
- void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
-
- void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
- void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
- void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
-
- void calculateInitialEndPoints();
-
- void reconstructSymbols();
-
-private:
- void setStartSymbol(Symbol::SymbolType symbolType);
- void setEndSymbol(Symbol::SymbolType symbolType);
-
- void createSubsetSymbol();
- void removeSubsetSymbol();
-
- void createCollaborationLine();
- void removeCollaborationLine();
-
- void alignSymbols();
-
- void createSplinePoints();
-
- AssociationWidget *m_associationWidget; ///< association widget for which this line represents
- QVector<QPointF> m_points; ///< points representing the association line
- int m_activePointIndex; ///< index of active point which can be dragged to modify association line
- int m_activeSegmentIndex; ///< index of active segment
- Symbol *m_startSymbol; ///< symbol drawn at the end of "first" line segment
- Symbol *m_endSymbol; ///< symbol drawn at the end of "last" line segment
- Symbol *m_subsetSymbol; ///< subset symbol
- QGraphicsLineItem *m_collaborationLineItem; ///< parallel arrow line drawn in case of collaboration message
- Symbol *m_collaborationLineHead; ///< arrow head drawn at end of m_collaborationLineItem
- LayoutType m_layout;
-
- static QPainterPath createBezierCurve(QVector<QPointF> points);
- static QPainterPath createOrthogonalPath(QVector<QPointF> points);
-
- static const qreal Delta; ///< default delta for fuzzy recognition of points closer to point
- static const qreal SelectedPointDiameter; ///< radius of circles drawn to show "selection"
- static const qreal SelfAssociationMinimumHeight; ///< minimum height for self association's loop
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/associationwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/associationwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/associationwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/associationwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,4407 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "associationwidget.h"
-
-// app includes
-#include "association.h"
-#include "associationline.h"
-#include "associationpropertiesdialog.h"
-#include "assocrules.h"
-#include "attribute.h"
-#include "classifier.h"
-#include "classifierwidget.h"
-#include "debug_utils.h"
-#include "docwindow.h"
-#include "entity.h"
-#include "floatingtextwidget.h"
-#include "listpopupmenu.h"
-#include "messagewidget.h"
-#include "objectwidget.h"
-#include "operation.h"
-#include "optionstate.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-#include "umlwidget.h"
-#include "widget_utils.h"
-
-// kde includes
-#if QT_VERSION < 0x050000
-#include <kcolordialog.h>
-#include <kfontdialog.h>
-#include <kinputdialog.h>
-#endif
-#include <KLocalizedString>
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QColorDialog>
-#include <QFontDialog>
-#include <QInputDialog>
-#endif
-#include <QPainterPath>
-#include <QPointer>
-#include <QRegExpValidator>
-#include <QApplication>
-
-// system includes
-#include <cmath>
-
-#define DBG_AW() DEBUG(QLatin1String("AssociationWidget"))
-DEBUG_REGISTER_DISABLED(AssociationWidget)
-
-using namespace Uml;
-
-/**
- * Constructor is private because the static create() methods shall
- * be used for constructing AssociationWidgets.
- *
- * @param scene The parent view of this widget.
- */
-AssociationWidget::AssociationWidget(UMLScene *scene)
- : WidgetBase(scene, WidgetBase::wt_Association),
- m_positions_len(0),
- m_activated(false),
- m_unNameLineSegment(-1),
- m_nLinePathSegmentIndex(-1),
- m_pAssocClassLine(0),
- m_pAssocClassLineSel0(0),
- m_pAssocClassLineSel1(0),
- m_associationLine(new AssociationLine(this)),
- m_associationClass(0),
- m_associationType(Uml::AssociationType::Association),
- m_nameWidget(0)
-{
- // floating text widgets objects owned by this association
- m_role[RoleType::A].changeabilityWidget = 0;
- m_role[RoleType::B].changeabilityWidget = 0;
- m_role[RoleType::A].multiplicityWidget = 0;
- m_role[RoleType::B].multiplicityWidget = 0;
- m_role[RoleType::A].roleWidget = 0;
- m_role[RoleType::B].roleWidget = 0;
- m_role[RoleType::A].umlWidget = 0;
- m_role[RoleType::B].umlWidget = 0;
-
- // associationwidget attributes
- m_role[RoleType::A].m_WidgetRegion = Uml::Region::Error;
- m_role[RoleType::B].m_WidgetRegion = Uml::Region::Error;
- m_role[RoleType::A].m_nIndex = 0;
- m_role[RoleType::B].m_nIndex = 0;
- m_role[RoleType::A].m_nTotalCount = 0;
- m_role[RoleType::B].m_nTotalCount = 0;
- m_role[RoleType::A].visibility = Uml::Visibility::Public;
- m_role[RoleType::B].visibility = Uml::Visibility::Public;
- m_role[RoleType::A].changeability = Uml::Changeability::Changeable;
- m_role[RoleType::B].changeability = Uml::Changeability::Changeable;
-
- setFlag(QGraphicsLineItem::ItemIsSelectable);
- setAcceptHoverEvents(true);
-}
-
-/**
- * This constructor is really only for loading from XMI, otherwise it
- * should not be allowed as it creates an incomplete associationwidget.
- *
- * @param scene The parent view of this widget.
- */
-AssociationWidget* AssociationWidget::create(UMLScene *scene)
-{
- AssociationWidget* instance = new AssociationWidget(scene);
- return instance;
-}
-
-/**
- * Preferred constructor (static factory method.)
- *
- * @param scene The parent view of this widget.
- * @param pWidgetA Pointer to the role A widget for the association.
- * @param assocType The AssociationType::Enum for this association.
- * @param pWidgetB Pointer to the role B widget for the association.
- * @param umlobject Pointer to the underlying UMLObject (if applicable.)
- */
-AssociationWidget* AssociationWidget::create
- (UMLScene *scene, UMLWidget* pWidgetA,
- Uml::AssociationType::Enum assocType, UMLWidget* pWidgetB,
- UMLObject *umlobject /* = NULL */)
-{
- AssociationWidget* instance = new AssociationWidget(scene);
- if (umlobject) {
- instance->setUMLObject(umlobject);
- } else {
- // set up UMLAssociation obj if assoc is represented and both roles are UML objects
- if (Uml::AssociationType::hasUMLRepresentation(assocType)) {
- UMLObject* umlRoleA = pWidgetA->umlObject();
- UMLObject* umlRoleB = pWidgetB->umlObject();
- if (umlRoleA != NULL && umlRoleB != NULL) {
- bool swap;
-
- // This is not correct. We could very easily have more than one
- // of the same type of association between the same two objects.
- // Just create the association. This search should have been
- // done BEFORE creation of the widget, if it mattered to the code.
- // But lets leave check in here for the time being so that debugging
- // output is shown, in case there is a collision with code elsewhere.
- UMLDoc *doc = UMLApp::app()->document();
- UMLAssociation *myAssoc = doc->findAssociation(assocType, umlRoleA, umlRoleB, &swap);
- if (myAssoc != NULL) {
- switch (assocType) {
- case Uml::AssociationType::Generalization:
- case Uml::AssociationType::Dependency:
- case Uml::AssociationType::Association_Self:
- case Uml::AssociationType::Coll_Message_Self:
- case Uml::AssociationType::Seq_Message_Self:
- case Uml::AssociationType::Containment:
- case Uml::AssociationType::Realization:
- DBG_AW() << "Ignoring second construction of same assoctype "
- << assocType << " between " << umlRoleA->name()
- << " and " << umlRoleB->name();
- break;
- default:
- DBG_AW() << "constructing a similar or exact same assoctype "
- << assocType << " between " << umlRoleA->name() << " and "
- << umlRoleB->name() << "as an already existing assoc (swap="
- << swap << ")";
- // now, just create a new association anyways
- myAssoc = NULL;
- break;
- }
- }
- if (myAssoc == NULL) {
- myAssoc = new UMLAssociation(assocType, umlRoleA, umlRoleB);
- // CHECK: myAssoc is not yet inserted at any parent UMLPackage -
- // need to check carefully that all callers do this, lest it be
- // orphaned.
- // ToolBarStateAssociation::addAssociationInViewAndDoc() is
- // okay in this regard.
- }
- instance->setUMLAssociation(myAssoc);
- }
- }
- }
-
- instance->setWidgetForRole(pWidgetA, RoleType::A);
- instance->setWidgetForRole(pWidgetB, RoleType::B);
-
- instance->setAssociationType(assocType);
-
- instance->calculateEndingPoints();
-
- instance->associationLine()->calculateInitialEndPoints();
- instance->associationLine()->reconstructSymbols();
-
- //The AssociationWidget is set to Activated because it already has its side widgets
- instance->setActivated(true);
-
- // sync UML meta-data to settings here
- instance->mergeAssociationDataIntoUMLRepresentation();
-
- // Collaboration messages need a name label because it's that
- // which lets operator== distinguish them, which in turn
- // permits us to have more than one message between two objects.
- if (instance->isCollaboration()) {
- // Create a temporary name to bring on setName()
- int collabID = instance->m_scene->generateCollaborationId();
- instance->setName(QLatin1Char('m') + QString::number(collabID));
- }
-
- return instance;
-}
-
-/**
- * Destructor.
- */
-AssociationWidget::~AssociationWidget()
-{
- delete m_associationLine;
-}
-
-/**
- * Overriding the method from WidgetBase because we need to do
- * something extra in case this AssociationWidget represents
- * an attribute of a classifier.
- */
-void AssociationWidget::setUMLObject(UMLObject *obj)
-{
- WidgetBase::setUMLObject(obj);
- if (obj == NULL)
- return;
- UMLClassifier *klass = NULL;
- UMLAttribute *attr = NULL;
- UMLEntity *ent = NULL;
- const UMLObject::ObjectType ot = obj->baseType();
- switch (ot) {
- case UMLObject::ot_Association:
- setUMLAssociation(dynamic_cast<UMLAssociation*>(obj));
- break;
- case UMLObject::ot_Operation:
- setOperation(dynamic_cast<UMLOperation*>(obj));
- break;
- case UMLObject::ot_Attribute:
- klass = static_cast<UMLClassifier*>(obj->parent());
- connect(klass, SIGNAL(attributeRemoved(UMLClassifierListItem*)),
- this, SLOT(slotClassifierListItemRemoved(UMLClassifierListItem*)));
- attr = static_cast<UMLAttribute*>(obj);
- connect(attr, SIGNAL(attributeChanged()), this, SLOT(slotAttributeChanged()));
- break;
- case UMLObject::ot_EntityAttribute:
- ent = static_cast<UMLEntity*>(obj->parent());
- connect(ent, SIGNAL(entityAttributeRemoved(UMLClassifierListItem*)),
- this, SLOT(slotClassifierListItemRemoved(UMLClassifierListItem*)));
- break;
- case UMLObject::ot_ForeignKeyConstraint:
- ent = static_cast<UMLEntity*>(obj->parent());
- connect(ent, SIGNAL(entityConstraintRemoved(UMLClassifierListItem*)),
- this, SLOT(slotClassifierListItemRemoved(UMLClassifierListItem*)));
- break;
- default:
- uError() << "cannot associate UMLObject of type " << UMLObject::toString(ot);
- break;
- }
-}
-
-/**
- * Set all 'owned' child widgets to this font.
- */
-void AssociationWidget::lwSetFont (QFont font)
-{
- if (m_nameWidget) {
- m_nameWidget->setFont(font);
- }
- if (m_role[RoleType::A].roleWidget) {
- m_role[RoleType::A].roleWidget->setFont(font);
- }
- if (m_role[RoleType::B].roleWidget) {
- m_role[RoleType::B].roleWidget->setFont(font);
- }
- if (m_role[RoleType::A].multiplicityWidget) {
- m_role[RoleType::A].multiplicityWidget->setFont(font);
- }
- if (m_role[RoleType::B].multiplicityWidget) {
- m_role[RoleType::B].multiplicityWidget->setFont(font);
- }
- if (m_role[RoleType::A].changeabilityWidget)
- m_role[RoleType::A].changeabilityWidget->setFont(font);
- if (m_role[RoleType::B].changeabilityWidget)
- m_role[RoleType::B].changeabilityWidget->setFont(font);
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- * @todo Move to LinkWidget.
- */
-UMLClassifier *AssociationWidget::operationOwner()
-{
- Uml::RoleType::Enum role = (isCollaboration() ? Uml::RoleType::B : Uml::RoleType::A);
- UMLObject *o = widgetForRole(role)->umlObject();
- if (!o) {
- return 0;
- }
- UMLClassifier *c = dynamic_cast<UMLClassifier*>(o);
- if (!c) {
- uError() << "widgetForRole(" << role << ") is not a classifier";
- }
- return c;
-}
-
-/**
- * Implements operation from LinkWidget.
- * Motivated by FloatingTextWidget.
- */
-UMLOperation *AssociationWidget::operation()
-{
- return dynamic_cast<UMLOperation*>(m_umlObject);
-}
-
-/**
- * Implements operation from LinkWidget.
- * Motivated by FloatingTextWidget.
- */
-void AssociationWidget::setOperation(UMLOperation *op)
-{
- if (m_umlObject)
- disconnect(m_umlObject, SIGNAL(modified()), m_nameWidget, SLOT(setMessageText()));
- m_umlObject = op;
- if (m_umlObject)
- connect(m_umlObject, SIGNAL(modified()), m_nameWidget, SLOT(setMessageText()));
- if (m_nameWidget)
- m_nameWidget->setMessageText();
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- */
-QString AssociationWidget::customOpText()
-{
- return name();
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- */
-void AssociationWidget::setCustomOpText(const QString &opText)
-{
- setName(opText);
-}
-
-/**
- * Calls setTextPosition on all the labels.
- * Overrides operation from LinkWidget.
- */
-void AssociationWidget::resetTextPositions()
-{
- if (m_role[RoleType::A].multiplicityWidget) {
- setTextPosition(TextRole::MultiA);
- }
- if (m_role[RoleType::B].multiplicityWidget) {
- setTextPosition(Uml::TextRole::MultiB);
- }
- if (m_role[RoleType::A].changeabilityWidget) {
- setTextPosition(Uml::TextRole::ChangeA);
- }
- if (m_role[RoleType::B].changeabilityWidget) {
- setTextPosition(Uml::TextRole::ChangeB);
- }
- if (m_nameWidget) {
- setTextPosition(Uml::TextRole::Name);
- }
- if (m_role[RoleType::A].roleWidget) {
- setTextPosition(Uml::TextRole::RoleAName);
- }
- if (m_role[RoleType::B].roleWidget) {
- setTextPosition(Uml::TextRole::RoleBName);
- }
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- *
- * @param ft The text widget which to update.
- */
-void AssociationWidget::setMessageText(FloatingTextWidget *ft)
-{
- if (isCollaboration()) {
- ft->setSequenceNumber(m_SequenceNumber);
- if (m_umlObject != NULL) {
- ft->setText(operationText(m_scene));
- } else {
- ft->setText(name());
- }
- } else {
- ft->setText(name());
- }
-}
-
-/**
- * Sets the text of the given FloatingTextWidget.
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- */
-void AssociationWidget::setText(FloatingTextWidget *ft, const QString &text)
-{
- Uml::TextRole::Enum role = ft->textRole();
- switch (role) {
- case Uml::TextRole::Name:
- setName(text);
- break;
- case Uml::TextRole::RoleAName:
- setRoleName(text, RoleType::A);
- break;
- case Uml::TextRole::RoleBName:
- setRoleName(text, RoleType::B);
- break;
- case Uml::TextRole::MultiA:
- setMultiplicity(text, RoleType::A);
- break;
- case Uml::TextRole::MultiB:
- setMultiplicity(text, RoleType::B);
- break;
- default:
- uWarning() << "Unhandled TextRole: " << Uml::TextRole::toString(role);
- break;
- }
-}
-
-/**
- * Shows the association properties dialog and updates the
- * corresponding texts if its execution is successful.
- */
-void AssociationWidget::showPropertiesDialog()
-{
- UMLApp::app()->docWindow()->updateDocumentation();
- QPointer<AssociationPropertiesDialog> dlg = new AssociationPropertiesDialog(static_cast<QWidget*>(m_scene->activeView()), this);
- if (dlg->exec()) {
- //rules built into these functions to stop updating incorrect values
- setName(name());
-
- setRoleName(roleName(RoleType::A), RoleType::A);
- setRoleName(roleName(RoleType::B), RoleType::B);
-
- setDocumentation(documentation());
-
- setRoleDocumentation(roleDocumentation(RoleType::A), RoleType::A);
- setRoleDocumentation(roleDocumentation(RoleType::B), RoleType::B);
-
- setMultiplicity(multiplicity(RoleType::A), RoleType::A);
- setMultiplicity(multiplicity(RoleType::B), RoleType::B);
-
- setVisibility(visibility(RoleType::A), RoleType::A);
- setVisibility(visibility(RoleType::B), RoleType::B);
-
- setChangeability(changeability(RoleType::A), RoleType::A);
- setChangeability(changeability(RoleType::B), RoleType::B);
-
- UMLApp::app()->docWindow()->showDocumentation(this, true);
- }
- delete dlg;
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- *
- * @param op Return this AssociationWidget's operation string.
- */
-QString AssociationWidget::lwOperationText()
-{
- return name();
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- *
- * @return classifier
- */
-UMLClassifier* AssociationWidget::lwClassifier()
-{
- UMLObject *o = widgetForRole(RoleType::B)->umlObject();
- UMLClassifier *c = dynamic_cast<UMLClassifier*>(o);
- return c;
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- *
- * @param op The new operation string to set.
- */
-void AssociationWidget::setOperationText(const QString &op)
-{
- if (!op.isEmpty()) {
- setName(op);
- }
-}
-
-/**
- * Calculates the m_unNameLineSegment value according to the new
- * NameText topleft corner PT.
- * It iterates through all AssociationLine's segments and for each one
- * calculates the sum of PT's distance to the start point + PT's
- * distance to the end point. The segment with the smallest sum will
- * be the RoleTextSegment (if this segment moves then the RoleText
- * will move with it). It sets m_unNameLineSegment to the start point
- * of the chosen segment.
- *
- * Overrides operation from LinkWidget (i.e. this method is also
- * required by FloatingTextWidget.)
- */
-void AssociationWidget::calculateNameTextSegment()
-{
- if (!m_nameWidget) {
- return;
- }
- //changed to use the middle of the text
- //i think this will give a better result.
- //never know what sort of lines people come up with
- //and text could be long to give a false reading
- qreal xt = m_nameWidget->x();
- qreal yt = m_nameWidget->y();
- xt += m_nameWidget->width() / 2;
- yt += m_nameWidget->height() / 2;
- int size = m_associationLine->count();
- //sum of length(PTP1) and length(PTP2)
- qreal total_length = 0;
- qreal smallest_length = 0;
- for (int i = 0; i < size - 1; ++i) {
- QPointF pi = m_associationLine->point( i );
- QPointF pj = m_associationLine->point( i+1 );
- qreal xtiDiff = xt - pi.x();
- qreal xtjDiff = xt - pj.x();
- qreal ytiDiff = yt - pi.y();
- qreal ytjDiff = yt - pj.y();
- total_length = sqrt( double(xtiDiff * xtiDiff + ytiDiff * ytiDiff) )
- + sqrt( double(xtjDiff * xtjDiff + ytjDiff * ytjDiff) );
- //this gives the closest point
- if (total_length < smallest_length || i == 0) {
- smallest_length = total_length;
- m_unNameLineSegment = i;
- }
- }
-}
-
-/**
- * Returns the UMLAssociation representation of this object.
- *
- * @return Pointer to the UMLAssociation that is represented by
- * this AsociationWidget.
- */
-UMLAssociation* AssociationWidget::association() const
-{
- if (m_umlObject == NULL || m_umlObject->baseType() != UMLObject::ot_Association)
- return NULL;
- return static_cast<UMLAssociation*>(m_umlObject);
-}
-
-/**
- * Returns the UMLAttribute representation of this object.
- *
- * @return Pointer to the UMLAttribute that is represented by
- * this AsociationWidget.
- */
-UMLAttribute* AssociationWidget::attribute() const
-{
- if (m_umlObject == NULL)
- return NULL;
- UMLObject::ObjectType ot = m_umlObject->baseType();
- if (ot != UMLObject::ot_Attribute && ot != UMLObject::ot_EntityAttribute)
- return NULL;
- return static_cast<UMLAttribute*>(m_umlObject);
-}
-
-#if 0 //:TODO:
-/**
- * Overrides the assignment operator.
- */
-AssociationWidget& AssociationWidget::operator=(const AssociationWidget& other)
-{
- *m_associationLine = *other.m_associationLine;
-
- if (other.m_nameWidget) {
- m_nameWidget = new FloatingTextWidget(m_scene);
- *m_nameWidget = *(other.m_nameWidget);
- } else {
- m_nameWidget = NULL;
- }
-
- for (unsigned r = (unsigned)A; r <= (unsigned)B; ++r) {
- WidgetRole& lhs = m_role[r];
- const WidgetRole& rhs = other.m_role[r];
- lhs.m_nIndex = rhs.m_nIndex;
- lhs.m_nTotalCount = rhs.m_nTotalCount;
-
- if (rhs.multiplicityWidget) {
- lhs.multiplicityWidget = new FloatingTextWidget(m_scene);
- *(lhs.multiplicityWidget) = *(rhs.multiplicityWidget);
- } else {
- lhs.multiplicityWidget = NULL;
- }
-
- if (rhs.roleWidget) {
- lhs.roleWidget = new FloatingTextWidget(m_scene);
- *(lhs.roleWidget) = *(rhs.roleWidget);
- } else {
- lhs.roleWidget = NULL;
- }
-
- if (rhs.changeabilityWidget) {
- lhs.changeabilityWidget = new FloatingTextWidget(m_scene);
- *(lhs.changeabilityWidget) = *(rhs.changeabilityWidget);
- } else {
- lhs.changeabilityWidget = NULL;
- }
-
- lhs.umlWidget = rhs.umlWidget;
- lhs.m_WidgetRegion = rhs.m_WidgetRegion;
- }
-
- m_activated = other.m_activated;
- m_unNameLineSegment = other.m_unNameLineSegment;
- m_pMenu = other.m_pMenu;
- setUMLAssociation(other.association());
- setSelected(other.isSelected());
-
- return *this;
-}
-#endif //:TODO:
-
-/**
- * Overrides the equality test operator.
- */
-bool AssociationWidget::operator==(const AssociationWidget& other) const
-{
- if (this == &other)
- return true;
-
- // if no model representation exists, then the widgets are not equal
- if (association() == NULL && other.association() == NULL)
- return false;
-
- if (!m_umlObject || !other.m_umlObject ) {
- if (!other.m_umlObject && m_umlObject)
- return false;
- if (other.m_umlObject && !m_umlObject)
- return false;
-
- } else if (m_umlObject != other.m_umlObject)
- return false;
-
- if (associationType() != other.associationType())
- return false;
-
- if (widgetIDForRole(RoleType::A) != other.widgetIDForRole(RoleType::A))
- return false;
-
- if (widgetIDForRole(RoleType::B) != other.widgetIDForRole(RoleType::B))
- return false;
-
- if (widgetForRole(RoleType::A)->baseType() == WidgetBase::wt_Object &&
- other.widgetForRole(RoleType::A)->baseType() == WidgetBase::wt_Object) {
- ObjectWidget *ownA = static_cast<ObjectWidget*>(widgetForRole(RoleType::A));
- ObjectWidget *otherA = static_cast<ObjectWidget*>(other.widgetForRole(RoleType::A));
- if (ownA->localID() != otherA->localID())
- return false;
- }
-
- if (widgetForRole(RoleType::B)->baseType() == WidgetBase::wt_Object &&
- other.widgetForRole(RoleType::B)->baseType() == WidgetBase::wt_Object) {
- ObjectWidget *ownB = static_cast<ObjectWidget*>(widgetForRole(RoleType::B));
- ObjectWidget *otherB = static_cast<ObjectWidget*>(other.widgetForRole(RoleType::B));
- if (ownB->localID() != otherB->localID())
- return false;
- }
-
- // Two objects in a collaboration can have multiple messages between each other.
- // Here we depend on the messages having names, and the names must be different.
- // That is the reason why collaboration messages have strange initial names like
- // "m29997" or similar.
- return (name() == other.name());
-}
-
-/**
- * Overrides the != operator.
- */
-bool AssociationWidget::operator!=(AssociationWidget& other) const
-{
- return !(*this == other);
-}
-
-/**
- * Returns a pointer to the association widget's line path.
- */
-AssociationLine* AssociationWidget::associationLine() const
-{
- return m_associationLine;
-}
-
-/**
- * Activates the AssociationWidget after a load.
- *
- * @return true for success
- */
-bool AssociationWidget::activate()
-{
- if (m_umlObject == NULL &&
- AssociationType::hasUMLRepresentation(m_associationType)) {
- UMLObject *myObj = umlDoc()->findObjectById(m_nId);
- if (myObj == NULL) {
- uError() << "cannot find UMLObject " << Uml::ID::toString(m_nId);
- return false;
- } else {
- const UMLObject::ObjectType ot = myObj->baseType();
- if (ot == UMLObject::ot_Association) {
- UMLAssociation * myAssoc = static_cast<UMLAssociation*>(myObj);
- setUMLAssociation(myAssoc);
- } else {
- setUMLObject(myObj);
- setAssociationType(m_associationType);
- }
- }
- }
-
- if (m_activated)
- return true;
-
- Uml::AssociationType::Enum type = associationType();
-
- if (m_role[RoleType::A].umlWidget == NULL)
- setWidgetForRole(m_scene->findWidget(widgetIDForRole(RoleType::A)), RoleType::A);
- if (m_role[RoleType::B].umlWidget == NULL)
- setWidgetForRole(m_scene->findWidget(widgetIDForRole(RoleType::B)), RoleType::B);
-
- if (!m_role[RoleType::A].umlWidget || !m_role[RoleType::B].umlWidget) {
- DEBUG(DBG_SRC) << "Cannot make association!";
- return false;
- }
-
- calculateEndingPoints();
-
- if (AssocRules::allowRole(type)) {
- for (unsigned r = RoleType::A; r <= RoleType::B; ++r) {
- WidgetRole& robj = m_role[r];
- if (robj.roleWidget == NULL)
- continue;
- robj.roleWidget->setLink(this);
- TextRole::Enum tr = (r == RoleType::A ? TextRole::RoleAName : TextRole::RoleBName);
- robj.roleWidget->setTextRole(tr);
- Uml::Visibility::Enum vis = visibility(Uml::RoleType::fromInt(r));
- robj.roleWidget->setPreText(Uml::Visibility::toString(vis, true));
-
- if (FloatingTextWidget::isTextValid(robj.roleWidget->text()))
- robj.roleWidget->show();
- else
- robj.roleWidget->hide();
- if (m_scene->type() == DiagramType::Collaboration)
- robj.roleWidget->setUMLObject(robj.umlWidget->umlObject());
- robj.roleWidget->activate();
- }
- }
-
- if (m_nameWidget != NULL) {
- m_nameWidget->setLink(this);
- m_nameWidget->setTextRole(calculateNameType(TextRole::Name));
-
- if (FloatingTextWidget::isTextValid(m_nameWidget->text())) {
- m_nameWidget->show();
- } else {
- m_nameWidget->hide();
- }
- m_nameWidget->activate();
- calculateNameTextSegment();
- }
-
- for (unsigned r = RoleType::A; r <= RoleType::B; ++r) {
- WidgetRole& robj = m_role[r];
-
- FloatingTextWidget* pMulti = robj.multiplicityWidget;
- if (pMulti != NULL &&
- AssocRules::allowMultiplicity(type, robj.umlWidget->baseType())) {
- pMulti->setLink(this);
- TextRole::Enum tr = (r == RoleType::A ? TextRole::MultiA : TextRole::MultiB);
- pMulti->setTextRole(tr);
- if (FloatingTextWidget::isTextValid(pMulti->text()))
- pMulti->show();
- else
- pMulti->hide();
- pMulti->activate();
- }
-
- FloatingTextWidget* pChangeWidget = robj.changeabilityWidget;
- if (pChangeWidget != NULL) {
- pChangeWidget->setLink(this);
- TextRole::Enum tr = (r == RoleType::A ? TextRole::ChangeA : TextRole::ChangeB);
- pChangeWidget->setTextRole(tr);
- if (FloatingTextWidget::isTextValid(pChangeWidget->text()))
- pChangeWidget->show();
- else
- pChangeWidget->hide ();
- pChangeWidget->activate();
- }
- }
-
- // Prepare the association class line if needed.
- if (m_associationClass && !m_pAssocClassLine) {
- createAssocClassLine();
- }
-
- m_activated = true;
- return true;
-}
-
-/**
- * Set the widget of the given role.
- * Add this AssociationWidget at the widget.
- * If this AssociationWidget has an underlying UMLAssociation then set
- * the widget's underlying UMLObject at the UMLAssociation's role object.
- *
- * @param widget Pointer to the UMLWidget.
- * @param role Role for which to set the widget.
- */
-void AssociationWidget::setWidgetForRole(UMLWidget* widget, Uml::RoleType::Enum role)
-{
- m_role[role].umlWidget = widget;
- if (widget) {
- m_role[role].umlWidget->addAssoc(this);
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association)
- association()->setObject(widget->umlObject(), role);
- }
-}
-
-/**
- * Return the multiplicity FloatingTextWidget widget of the given role.
- *
- * @return Pointer to the multiplicity FloatingTextWidget object.
- */
-FloatingTextWidget* AssociationWidget::multiplicityWidget(Uml::RoleType::Enum role) const
-{
- return m_role[role].multiplicityWidget;
-}
-
-/**
- * Read property of FloatingTextWidget* m_nameWidget.
- *
- * @return Pointer to the FloatingTextWidget name widget.
- */
-FloatingTextWidget* AssociationWidget::nameWidget() const
-{
- return m_nameWidget;
-}
-
-/**
- * Return the given role's FloatingTextWidget object.
- *
- * @return Pointer to the role's FloatingTextWidget widget.
- */
-FloatingTextWidget* AssociationWidget::roleWidget(Uml::RoleType::Enum role) const
-{
- return m_role[role].roleWidget;
-}
-
-/**
- * Return the given role's changeability FloatingTextWidget widget.
- */
-FloatingTextWidget* AssociationWidget::changeabilityWidget(Uml::RoleType::Enum role) const
-{
- return m_role[role].changeabilityWidget;
-}
-
-/**
- * Return the FloatingTextWidget object indicated by the given TextRole::Enum.
- *
- * @return Pointer to the text role's FloatingTextWidget widget.
- */
-FloatingTextWidget* AssociationWidget::textWidgetByRole(Uml::TextRole::Enum tr) const
-{
- switch (tr) {
- case Uml::TextRole::MultiA:
- return m_role[RoleType::A].multiplicityWidget;
- case Uml::TextRole::MultiB:
- return m_role[RoleType::B].multiplicityWidget;
- case Uml::TextRole::Name:
- case Uml::TextRole::Coll_Message:
- return m_nameWidget;
- case Uml::TextRole::RoleAName:
- return m_role[RoleType::A].roleWidget;
- case Uml::TextRole::RoleBName:
- return m_role[RoleType::B].roleWidget;
- case Uml::TextRole::ChangeA:
- return m_role[RoleType::A].changeabilityWidget;
- case Uml::TextRole::ChangeB:
- return m_role[RoleType::B].changeabilityWidget;
- default:
- break;
- }
- return NULL;
-}
-
-/**
- * Returns the m_nameWidget's text.
- *
- * @return Text of the FloatingTextWidget name widget.
- */
-QString AssociationWidget::name() const
-{
- if (m_nameWidget == NULL)
- return QString();
- return m_nameWidget->text();
-}
-
-/**
- * Sets the text in the FloatingTextWidget widget representing the Name
- * of this association.
- */
-void AssociationWidget::setName(const QString &strName)
-{
- // set attribute of UMLAssociation associated with this associationwidget
- UMLAssociation *umla = association();
- if (umla)
- umla->setName(strName);
-
- bool newLabel = false;
- if (!m_nameWidget) {
- // Don't construct the FloatingTextWidget if the string is empty.
- if (! FloatingTextWidget::isTextValid(strName))
- return;
-
- newLabel = true;
- m_nameWidget = new FloatingTextWidget(m_scene, calculateNameType(Uml::TextRole::Name), strName);
- m_nameWidget->setParentItem(this);
- m_nameWidget->setLink(this);
- } else {
- m_nameWidget->setText(strName);
- if (! FloatingTextWidget::isTextValid(strName)) {
- //m_nameWidget->hide();
- m_scene->removeWidget(m_nameWidget);
- m_nameWidget = NULL;
- return;
- }
- }
-
- setTextPosition(Uml::TextRole::Name);
- if (newLabel) {
- m_nameWidget->setActivated();
- m_scene->addFloatingTextWidget(m_nameWidget);
- }
-
- m_nameWidget->show();
-}
-
-void AssociationWidget::setStereotype(const QString &stereo) {
- UMLAssociation *umlassoc = association();
- if (umlassoc) {
- umlassoc->setStereotype(stereo);
- if (m_nameWidget) {
- m_nameWidget->setText(umlassoc->stereotype(true));
- } else {
- uDebug() << "not setting " << stereo << " because m_nameWidget is NULL";
- }
- } else {
- uDebug() << "not setting " << stereo << " because association is NULL";
- }
-}
-
-/**
- * Return the given role's FloatingTextWidget widget text.
- *
- * @return The name set at the FloatingTextWidget.
- */
-QString AssociationWidget::roleName(Uml::RoleType::Enum role) const
-{
- if (m_role[role].roleWidget == NULL)
- return QString();
- return m_role[role].roleWidget->text();
-}
-
-/**
- * Sets the text to the FloatingTextWidget that display the Role text of this
- * association.
- * For this function to work properly, the associated widget
- * should already be set.
- */
-void AssociationWidget::setRoleName(const QString &strRole, Uml::RoleType::Enum role)
-{
- Uml::AssociationType::Enum type = associationType();
- //if the association is not supposed to have a Role FloatingTextWidget
- if (!AssocRules::allowRole(type)) {
- return;
- }
-
- TextRole::Enum tr = (role == RoleType::A ? TextRole::RoleAName : TextRole::RoleBName);
- setFloatingText(tr, strRole, m_role[role].roleWidget);
- if (m_role[role].roleWidget) {
- Uml::Visibility::Enum vis = visibility(role);
- if (FloatingTextWidget::isTextValid(m_role[role].roleWidget->text())) {
- m_role[role].roleWidget->setPreText(Uml::Visibility::toString(vis, true));
- //m_role[role].roleWidget->show();
- } else {
- m_role[role].roleWidget->setPreText(QString());
- //m_role[role].roleWidget->hide();
- }
- }
-
- // set attribute of UMLAssociation associated with this associationwidget
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association)
- association()->setRoleName(strRole, role);
-}
-
-/**
- * Set the documentation on the given role.
- */
-void AssociationWidget::setRoleDocumentation(const QString &doc, Uml::RoleType::Enum role)
-{
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association)
- association()->setRoleDoc(doc, role);
- else
- m_role[role].roleDocumentation = doc;
-}
-
-/**
- * Returns the given role's documentation.
- */
-QString AssociationWidget::roleDocumentation(Uml::RoleType::Enum role) const
-{
- if (m_umlObject == NULL || m_umlObject->baseType() != UMLObject::ot_Association)
- return QString();
- UMLAssociation *umla = static_cast<UMLAssociation*>(m_umlObject);
- return umla->getRoleDoc(role);
-}
-
-/**
- * Change, create, or delete the FloatingTextWidget indicated by the given TextRole::Enum.
- *
- * @param tr TextRole::Enum of the FloatingTextWidget to change or create.
- * @param text Text string that controls the action:
- * If empty and ft is NULL then setFloatingText() is a no-op.
- * If empty and ft is non-NULL then the existing ft is deleted.
- * If non-empty and ft is NULL then a new FloatingTextWidget is created
- * and returned in ft with the text set.
- * If non-empty and ft is non-NULL then the existing ft text is modified.
- * @param ft Reference to the pointer to FloatingTextWidget to change or create.
- * On creation/deletion, the pointer value will be changed.
- */
-void AssociationWidget::setFloatingText(Uml::TextRole::Enum role,
- const QString &text,
- FloatingTextWidget* &ft)
-{
- if (! FloatingTextWidget::isTextValid(text)) {
- if (ft) {
- // Remove preexisting FloatingTextWidget
- m_scene->removeWidget(ft); // physically deletes ft
- ft = NULL;
- }
- return;
- }
-
- if (ft == NULL) {
- ft = new FloatingTextWidget(m_scene, role, text);
- ft->setParentItem(this);
- ft->setLink(this);
- ft->activate();
- setTextPosition(role);
- m_scene->addFloatingTextWidget(ft);
- } else {
- bool newLabel = ft->text().isEmpty();
- ft->setText(text);
- if (newLabel)
- setTextPosition(role);
- }
-
- ft->show();
-}
-
-/**
- * Return the given role's multiplicity text.
- *
- * @return Text of the given role's multiplicity widget.
- */
-QString AssociationWidget::multiplicity(Uml::RoleType::Enum role) const
-{
- if (m_role[role].multiplicityWidget == NULL)
- return QString();
- return m_role[role].multiplicityWidget->text();
-}
-
-/**
- * Sets the text in the FloatingTextWidget representing the multiplicity
- * at the given side of the association.
- */
-void AssociationWidget::setMultiplicity(const QString& text, Uml::RoleType::Enum role)
-{
- TextRole::Enum tr = (role == RoleType::A ? TextRole::MultiA : TextRole::MultiB);
-
- setFloatingText(tr, text, m_role[role].multiplicityWidget);
-
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association)
- association()->setMultiplicity(text, role);
-}
-
-/**
- * Gets the visibility on the given role of the association.
- */
-Visibility::Enum AssociationWidget::visibility(Uml::RoleType::Enum role) const
-{
- const UMLAssociation *assoc = association();
- if (assoc)
- return assoc->visibility(role);
- const UMLAttribute *attr = attribute();
- if (attr)
- return attr->visibility();
- return m_role[role].visibility;
-}
-
-/**
- * Sets the visibility on the given role of the association.
- */
-void AssociationWidget::setVisibility(Visibility::Enum value, Uml::RoleType::Enum role)
-{
- if (value == visibility(role)) {
- return;
- }
- if (m_umlObject) {
- // update our model object
- const UMLObject::ObjectType ot = m_umlObject->baseType();
- if (ot == UMLObject::ot_Association)
- association()->setVisibility(value, role);
- else if (ot == UMLObject::ot_Attribute)
- attribute()->setVisibility(value);
- }
- m_role[role].visibility = value;
- // update role pre-text attribute as appropriate
- if (m_role[role].roleWidget) {
- QString scopeString = Visibility::toString(value, true);
- m_role[role].roleWidget->setPreText(scopeString);
- }
-}
-
-/**
- * Gets the changeability on the given end of the Association.
- */
-Uml::Changeability::Enum AssociationWidget::changeability(Uml::RoleType::Enum role) const
-{
- if (m_umlObject == NULL || m_umlObject->baseType() != UMLObject::ot_Association)
- return m_role[role].changeability;
- UMLAssociation *umla = static_cast<UMLAssociation*>(m_umlObject);
- return umla->changeability(role);
-}
-
-/**
- * Sets the changeability on the given end of the Association.
- */
-void AssociationWidget::setChangeability(Uml::Changeability::Enum value, Uml::RoleType::Enum role)
-{
- if (value == changeability(role))
- return;
- QString changeString = Uml::Changeability::toString(value);
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) // update our model object
- association()->setChangeability(value, role);
- m_role[role].changeability = value;
- // update our string representation
- setChangeWidget(changeString, role);
-}
-
-/**
- * For internal purpose-kf6s only.
- * Other classes/users should use setChangeability() instead.
- */
-void AssociationWidget::setChangeWidget(const QString &strChangeWidget, Uml::RoleType::Enum role)
-{
- bool newLabel = false;
- TextRole::Enum tr = (role == RoleType::A ? TextRole::ChangeA : TextRole::ChangeB);
-
- if (!m_role[role].changeabilityWidget) {
- // Don't construct the FloatingTextWidget if the string is empty.
- if (strChangeWidget.isEmpty())
- return;
-
- newLabel = true;
- m_role[role].changeabilityWidget = new FloatingTextWidget(m_scene, tr, strChangeWidget);
- m_role[role].changeabilityWidget->setParentItem(this);
- m_role[role].changeabilityWidget->setLink(this);
- m_scene->addFloatingTextWidget(m_role[role].changeabilityWidget);
- m_role[role].changeabilityWidget->setPreText(QLatin1String("{")); // all types have this
- m_role[role].changeabilityWidget->setPostText(QLatin1String("}")); // all types have this
- } else {
- if (m_role[role].changeabilityWidget->text().isEmpty()) {
- newLabel = true;
- }
- m_role[role].changeabilityWidget->setText(strChangeWidget);
- }
- m_role[role].changeabilityWidget->setActivated();
-
- if (newLabel) {
- setTextPosition(tr);
- }
-
- if (FloatingTextWidget::isTextValid(m_role[role].changeabilityWidget->text()))
- m_role[role].changeabilityWidget->show();
- else
- m_role[role].changeabilityWidget->hide();
-}
-
-/**
- * Returns true if the line path starts at the given widget.
- */
-bool AssociationWidget::linePathStartsAt(const UMLWidget* widget)
-{
-//:TODO:
-// QPointF lpStart = m_associationLine->point(0);
-// int startX = lpStart.x();
-// int startY = lpStart.y();
-// int wX = widget->x();
-// int wY = widget->y();
-// int wWidth = widget->width();
-// int wHeight = widget->height();
-// bool result = (startX >= wX && startX <= wX + wWidth &&
-// startY >= wY && startY <= wY + wHeight);
-// return result;
- bool result = widget->contains(m_associationLine->point(0));
- DEBUG(DBG_SRC) << "widget=" << widget->name() << " / result=" << result;
- return result;
-}
-
-/**
- * This function calculates which role should be set for the m_nameWidget FloatingTextWidget.
- */
-Uml::TextRole::Enum AssociationWidget::calculateNameType(Uml::TextRole::Enum defaultRole)
-{
- TextRole::Enum result = defaultRole;
- if (m_scene->type() == DiagramType::Collaboration) {
- if (m_role[RoleType::A].umlWidget == m_role[RoleType::B].umlWidget) {
- result = TextRole::Coll_Message;//for now same as other Coll_Message
- } else {
- result = TextRole::Coll_Message;
- }
- } else if (m_scene->type() == DiagramType::Sequence) {
- if (m_role[RoleType::A].umlWidget == m_role[RoleType::B].umlWidget) {
- result = TextRole::Seq_Message_Self;
- } else {
- result = TextRole::Seq_Message;
- }
- }
-
- return result;
-}
-
-/**
- * Gets the given role widget.
- *
- * @return Pointer to the role's UMLWidget.
- */
-UMLWidget* AssociationWidget::widgetForRole(Uml::RoleType::Enum role) const
-{
- return m_role[role].umlWidget;
-}
-
-/**
- * Sets the associated widgets.
- *
- * @param widgetA Pointer the role A widget for the association.
- * @param assocType The AssociationType::Enum for this association.
- * @param widgetB Pointer the role B widget for the association.
- */
-bool AssociationWidget::setWidgets(UMLWidget* widgetA,
- Uml::AssociationType::Enum assocType,
- UMLWidget* widgetB)
-{
- //if the association already has a WidgetB or WidgetA associated, then
- //it cannot be changed to other widget, that would require a deletion
- //of the association and the creation of a new one
- if ((m_role[RoleType::A].umlWidget && (m_role[RoleType::A].umlWidget != widgetA)) ||
- (m_role[RoleType::B].umlWidget && (m_role[RoleType::B].umlWidget != widgetB))) {
- return false;
- }
- setWidgetForRole(widgetA, RoleType::A);
- setAssociationType(assocType);
- setWidgetForRole(widgetB, RoleType::B);
-
- calculateEndingPoints();
- return true;
-}
-
-/**
- * CleansUp all the association's data in the related widgets.
- */
-void AssociationWidget::cleanup()
-{
- //let any other associations know we are going so they can tidy their positions up
- if (m_role[RoleType::A].m_nTotalCount > 2)
- updateAssociations(m_role[RoleType::A].m_nTotalCount - 1, m_role[RoleType::A].m_WidgetRegion, RoleType::A);
- if (m_role[RoleType::B].m_nTotalCount > 2)
- updateAssociations(m_role[RoleType::B].m_nTotalCount - 1, m_role[RoleType::B].m_WidgetRegion, RoleType::B);
-
- for (unsigned r = RoleType::A; r <= RoleType::B; ++r) {
- WidgetRole& robj = m_role[r];
-
- if (robj.umlWidget) {
- robj.umlWidget->removeAssoc(this);
- robj.umlWidget = 0;
- }
- if (robj.roleWidget) {
- m_scene->removeWidget(robj.roleWidget);
- robj.roleWidget = 0;
- }
- if (robj.multiplicityWidget) {
- m_scene->removeWidget(robj.multiplicityWidget);
- robj.multiplicityWidget = 0;
- }
- if (robj.changeabilityWidget) {
- m_scene->removeWidget(robj.changeabilityWidget);
- robj.changeabilityWidget = 0;
- }
- }
-
- if (m_nameWidget) {
- m_scene->removeWidget(m_nameWidget);
- m_nameWidget = 0;
- }
-
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
- /*
- We do not remove the UMLAssociation from the document.
- Why? - Well, for example we might be in the middle of
- a cut/paste. If the UMLAssociation is removed by the cut
- then upon pasteing we have a problem.
- This is not quite clean yet - there should be a way to
- explicitly delete a UMLAssociation. The Right Thing would
- be to have a ListView representation for UMLAssociation.
- `
- IF we are cut n pasting, why are we handling this association as a pointer?
- We should be using the XMI representation for a cut and paste. This
- allows us to be clean here, AND a choice of recreating the object
- w/ same id IF its a "cut", or a new object if its a "copy" operation
- (in which case we wouldnt be here, in cleanup()).
- */
- setUMLAssociation(0);
- }
-
- m_associationLine->cleanup();
- removeAssocClassLine();
-}
-
-/**
- * @brief Return state if the assocation line point in the near of the last context
- * menu event position is addable or not.
- * A point is addable if the association is not an Exception and there is no point in the near.
- *
- * @return true if point is addable
- */
-bool AssociationWidget::isPointAddable()
-{
- if (!isSelected() || associationType() == Uml::AssociationType::Exception)
- return false;
- int i = m_associationLine->closestPointIndex(m_eventScenePos);
- return i == -1;
-}
-
-/**
- * @brief Return state if the assocation line point in the near of the last context
- * menu event position is removable or not.
- * A point is removable if the association is not an Exception and is not the start or end point.
- *
- * @return true if point is removable
- */
-bool AssociationWidget::isPointRemovable()
-{
- if (!isSelected() || associationType() == Uml::AssociationType::Exception || m_associationLine->count() <= 2)
- return false;
- int i = m_associationLine->closestPointIndex(m_eventScenePos);
- return i > 0 && i < m_associationLine->count() - 1;
-}
-
-/**
- * Set our internal umlAssociation.
- */
-void AssociationWidget::setUMLAssociation (UMLAssociation * assoc)
-{
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
- UMLAssociation *umla = association();
-
- // safety check. Did some num-nuts try to set the existing
- // association again? If so, just bail here
- if (umla == assoc)
- return;
-
- //umla->disconnect(this); //Qt does disconnect automatically upon destruction.
- umla->nrof_parent_widgets--;
-
- // ANSWER: This is the wrong treatment of cut and paste. Associations that
- // are being cut/n pasted should be serialized to XMI, then reconstituted
- // (IF a paste operation) rather than passing around object pointers. Its
- // just too hard otherwise to prevent problems in the code. Bottom line: we need to
- // delete orphaned associations or we well get code crashes and memory leaks.
- if (umla->nrof_parent_widgets <= 0) {
- //umla->deleteLater();
- }
-
- m_umlObject = NULL;
- }
-
- if (assoc) {
- m_umlObject = assoc;
-
- // move counter to "0" from "-1" (which means, no assocwidgets)
- if (assoc->nrof_parent_widgets < 0)
- assoc->nrof_parent_widgets = 0;
-
- assoc->nrof_parent_widgets++;
- connect(assoc, SIGNAL(modified()), this, SLOT(syncToModel()));
- }
-
-}
-
-/**
- * Returns true if the Widget is either at the starting or ending side of the association.
- */
-bool AssociationWidget::containsAsEndpoint(UMLWidget* widget)
-{
- return (widget == m_role[RoleType::A].umlWidget || widget == m_role[RoleType::B].umlWidget);
-}
-
-/**
- * Returns true if this AssociationWidget represents a collaboration message.
- */
-bool AssociationWidget::isCollaboration() const
-{
- Uml::AssociationType::Enum at = associationType();
- return (at == AssociationType::Coll_Message_Synchronous
- || at == AssociationType::Coll_Message_Asynchronous
- || at == AssociationType::Coll_Message_Self);
-}
-
-/**
- * Returns true if this AssociationWidget represents a self message.
- */
-bool AssociationWidget::isSelf() const
-{
- return widgetForRole(Uml::RoleType::A) == widgetForRole(Uml::RoleType::B);
-}
-
-/**
- * Gets the association's type.
- *
- * @return This AssociationWidget's AssociationType::Enum.
- */
-Uml::AssociationType::Enum AssociationWidget::associationType() const
-{
- if (m_umlObject == NULL || m_umlObject->baseType() != UMLObject::ot_Association)
- return m_associationType;
- UMLAssociation *umla = static_cast<UMLAssociation*>(m_umlObject);
- return umla->getAssocType();
-}
-
-/**
- * Sets the association's type.
- *
- * @param type The AssociationType::Enum to set.
- */
-void AssociationWidget::setAssociationType(Uml::AssociationType::Enum type)
-{
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
- association()->setAssociationType(type);
- }
- m_associationType = type;
- // If the association new type is not supposed to have Multiplicity
- // FloatingTexts and a Role FloatingTextWidget then set the texts
- // to empty.
- // NB We do not physically delete the floatingtext widgets here because
- // those widgets are also stored in the UMLView::m_WidgetList.
- if (!AssocRules::allowMultiplicity(type, widgetForRole(RoleType::A)->baseType())) {
- if (m_role[RoleType::A].multiplicityWidget) {
- m_role[RoleType::A].multiplicityWidget->setName(QString());
- }
- if (m_role[RoleType::B].multiplicityWidget) {
- m_role[RoleType::B].multiplicityWidget->setName(QString());
- }
- }
- if (!AssocRules::allowRole(type)) {
- if (m_role[RoleType::A].roleWidget) {
- m_role[RoleType::A].roleWidget->setName(QString());
- }
- if (m_role[RoleType::B].roleWidget) {
- m_role[RoleType::B].roleWidget->setName(QString());
- }
- setRoleDocumentation(QString(), RoleType::A);
- setRoleDocumentation(QString(), RoleType::B);
- }
- m_associationLine->reconstructSymbols();
-}
-
-/**
- * Gets the ID of the given role widget.
- */
-Uml::ID::Type AssociationWidget::widgetIDForRole(Uml::RoleType::Enum role) const
-{
- if (m_role[role].umlWidget == NULL) {
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
- UMLAssociation *umla = static_cast<UMLAssociation*>(m_umlObject);
- return umla->getObjectId(role);
- }
- uError() << "umlWidget is NULL";
- return Uml::ID::None;
- }
- if (m_role[role].umlWidget->baseType() == WidgetBase::wt_Object)
- return static_cast<ObjectWidget*>(m_role[role].umlWidget)->localID();
- Uml::ID::Type id = m_role[role].umlWidget->id();
- return id;
-}
-
-/**
- * Gets the local ID of the given role widget.
- */
-Uml::ID::Type AssociationWidget::widgetLocalIDForRole(Uml::RoleType::Enum role) const
-{
- if (m_role[role].umlWidget == NULL) {
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
- UMLAssociation *umla = static_cast<UMLAssociation*>(m_umlObject);
- return umla->getObjectId(role);
- }
- uError() << "umlWidget is NULL";
- return Uml::ID::None;
- }
- if (m_role[role].umlWidget->baseType() == WidgetBase::wt_Object)
- return static_cast<ObjectWidget*>(m_role[role].umlWidget)->localID();
- Uml::ID::Type id = m_role[role].umlWidget->localID();
- return id;
-}
-
-/**
- * Returns a QString Object representing this AssociationWidget.
- */
-QString AssociationWidget::toString() const
-{
- QString string;
- static const QChar colon(QLatin1Char(':'));
-
- if (widgetForRole(RoleType::A)) {
- string = widgetForRole(RoleType::A)->name();
- }
- string.append(colon);
-
- if (m_role[RoleType::A].roleWidget) {
- string += m_role[RoleType::A].roleWidget->text();
- }
- string.append(colon);
- string.append(Uml::AssociationType::toStringI18n(associationType()));
- string.append(colon);
-
- if (widgetForRole(RoleType::B)) {
- string += widgetForRole(RoleType::B)->name();
- }
-
- string.append(colon);
- if (m_role[RoleType::B].roleWidget) {
- string += m_role[RoleType::B].roleWidget->text();
- }
-
- return string;
-}
-
-/**
- * Adds a break point (if left mouse button).
- */
-void AssociationWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
-{
- if (event->button() == Qt::LeftButton) {
- uDebug() << "widget = " << name() << " / type = " << baseTypeStr();
- showPropertiesDialog();
- event->accept();
- }
-}
-
-/**
- * Overrides moveEvent.
- */
-void AssociationWidget::moveEvent(QGraphicsSceneMouseEvent *me)
-{
- // 2004-04-30: Achim Spangler
- // Simple Approach to block moveEvent during load of XMI
- /// @todo avoid trigger of this event during load
-
- if (umlDoc()->loading()) {
- // hmmh - change of position during load of XMI
- // -> there is something wrong
- // -> avoid movement during opening
- // -> print warn and stay at old position
- uWarning() << "called during load of XMI for ViewType: "
- << m_scene->type() << ", and BaseType: " << baseType();
- return;
- }
- /*to be here a line segment has moved.
- we need to see if the three text widgets needs to be moved.
- there are a few things to check first though:
-
- 1) Do they exist
- 2) does it need to move:
- 2a) for the multi widgets only move if they changed region, otherwise they are close enough
- 2b) for role name move if the segment it is on moves.
- */
- //first see if either the first or last segments moved, else no need to recalculate their point positions
-
- QPointF oldNamePoint = calculateTextPosition(TextRole::Name);
- QPointF oldMultiAPoint = calculateTextPosition(TextRole::MultiA);
- QPointF oldMultiBPoint = calculateTextPosition(TextRole::MultiB);
- QPointF oldChangeAPoint = calculateTextPosition(TextRole::ChangeA);
- QPointF oldChangeBPoint = calculateTextPosition(TextRole::ChangeB);
- QPointF oldRoleAPoint = calculateTextPosition(TextRole::RoleAName);
- QPointF oldRoleBPoint = calculateTextPosition(TextRole::RoleBName);
-
- int movingPoint = m_associationLine->closestPointIndex(me->scenePos());
- if (movingPoint != -1)
- m_associationLine->setPoint(movingPoint, me->scenePos());
- int pos = m_associationLine->count() - 1;//set to last point for widget b
-
- if ( movingPoint == 1 || (movingPoint == pos-1) ) {
- calculateEndingPoints();
- }
- if (m_role[RoleType::A].changeabilityWidget && (movingPoint == 1)) {
- setTextPositionRelatively(TextRole::ChangeA, oldChangeAPoint);
- }
- if (m_role[RoleType::B].changeabilityWidget && (movingPoint == 1)) {
- setTextPositionRelatively(TextRole::ChangeB, oldChangeBPoint);
- }
- if (m_role[RoleType::A].multiplicityWidget && (movingPoint == 1)) {
- setTextPositionRelatively(TextRole::MultiA, oldMultiAPoint);
- }
- if (m_role[RoleType::B].multiplicityWidget && (movingPoint == pos-1)) {
- setTextPositionRelatively(TextRole::MultiB, oldMultiBPoint);
- }
-
- if (m_nameWidget) {
- if (movingPoint == m_unNameLineSegment ||
- movingPoint - 1 == m_unNameLineSegment) {
- setTextPositionRelatively(TextRole::Name, oldNamePoint);
- }
- }
-
- if (m_role[RoleType::A].roleWidget) {
- setTextPositionRelatively(TextRole::RoleAName, oldRoleAPoint);
- }
- if (m_role[RoleType::B].roleWidget) {
- setTextPositionRelatively(TextRole::RoleBName, oldRoleBPoint);
- }
-
- if (m_pAssocClassLine) {
- computeAssocClassLine();
- }
-}
-
-/**
- * Calculates and sets the first and last point in the Association's AssociationLine.
- * Each point is a middle point of its respecting UMLWidget's Bounding rectangle
- * or a corner of it.
- * This method picks which sides to use for the association.
- */
-void AssociationWidget::calculateEndingPoints()
-{
- /*
- * For each UMLWidget the diagram is divided in four regions by its diagonals
- * as indicated below
- * Region 2
- * \ /
- * \ /
- * +--------+
- * | \ / |
- * Region 1 | >< | Region 3
- * | / \ |
- * +--------+
- * / \
- * / \
- * Region 4
- *
- * Each diagonal is defined by two corners of the bounding rectangle
- *
- * To calculate the first point in the AssociationLine we have to find out in which
- * Region (defined by WidgetA's diagonals) is WidgetB's center
- * (let's call it Region M.) After that the first point will be the middle
- * point of the rectangle's side contained in Region M.
- *
- * To calculate the last point in the AssociationLine we repeat the above but
- * in the opposite direction (from widgetB to WidgetA)
- */
-
- UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
- UMLWidget *pWidgetB = m_role[RoleType::B].umlWidget;
- if (!pWidgetA || !pWidgetB) {
- uWarning() << "Returning - one of the role widgets is not set.";
- return;
- }
-
- int size = m_associationLine->count();
- if (size < 2) {
- QPointF pA = pWidgetA->pos();
- QPointF pB = pWidgetB->pos();
- QPolygonF polyA = pWidgetA->shape().toFillPolygon().translated(pA);
- QPolygonF polyB = pWidgetB->shape().toFillPolygon().translated(pB);
- QLineF nearestPoints = Widget_Utils::closestPoints(polyA, polyB);
- if (nearestPoints.isNull()) {
- uError() << "Widget_Utils::closestPoints failed, falling back to simple widget positions";
- } else {
- pA = nearestPoints.p1();
- pB = nearestPoints.p2();
- }
- m_associationLine->setEndPoints(pA, pB);
- }
-
- // See if an association to self.
- // See if it needs to be set up before we continue:
- // If self association/message and doesn't have the minimum 4 points
- // then create it. Make sure no points are out of bounds of viewing area.
- // This only happens on first time through that we are worried about.
- if (isSelf() && size < 4) {
- createPointsSelfAssociation();
- return;
- }
-
- if (associationType() == AssociationType::Exception && size < 4) {
- createPointsException();
- updatePointsException();
- return;
- }
-
- // If the line has more than one segment change the values to calculate
- // from widget to point 1.
- qreal xB = pWidgetB->x() + pWidgetB->width() / 2;
- qreal yB = pWidgetB->y() + pWidgetB->height() / 2;
- if (size > 2) {
- QPointF p = m_associationLine->point(1);
- xB = p.x();
- yB = p.y();
- }
- doUpdates(QPointF(xB, yB), RoleType::A);
-
- // Now do the same for widgetB.
- // If the line has more than one segment change the values to calculate
- // from widgetB to the last point away from it.
- qreal xA = pWidgetA->x() + pWidgetA->width() / 2;
- qreal yA = pWidgetA->y() + pWidgetA->height() / 2;
- if (size > 2 ) {
- QPointF p = m_associationLine->point(size - 2);
- xA = p.x();
- yA = p.y();
- }
- doUpdates(QPointF(xA, yA), RoleType::B);
-
- computeAssocClassLine();
-}
-
-/**
- * Used by @ref calculateEndingPoints.
- */
-void AssociationWidget::doUpdates(const QPointF &otherP, RoleType::Enum role)
-{
- // Find widget region.
- Uml::Region::Enum oldRegion = m_role[role].m_WidgetRegion;
- UMLWidget *pWidget = m_role[role].umlWidget;
- QRectF rc(pWidget->x(), pWidget->y(),
- pWidget->width(), pWidget->height());
- Uml::Region::Enum region = m_role[role].m_WidgetRegion; // alias for brevity
- region = findPointRegion(rc, otherP);
- // Move some regions to the standard ones.
- switch( region ) {
- case Uml::Region::NorthWest:
- region = Uml::Region::North;
- break;
- case Uml::Region::NorthEast:
- region = Uml::Region::East;
- break;
- case Uml::Region::SouthEast:
- region = Uml::Region::South;
- break;
- case Uml::Region::SouthWest:
- case Uml::Region::Center:
- region = Uml::Region::West;
- break;
- default:
- break;
- }
- int regionCount = getRegionCount(region, role) + 2; //+2 = (1 for this one and one to halve it)
- int totalCount = m_role[role].m_nTotalCount;
- if (oldRegion != region) {
- updateRegionLineCount(regionCount - 1, regionCount, region, role);
- updateAssociations(totalCount - 1, oldRegion, role);
- } else if (totalCount != regionCount) {
- updateRegionLineCount(regionCount - 1, regionCount, region, role);
- } else {
- updateRegionLineCount(m_role[role].m_nIndex, totalCount, region, role);
- }
- updateAssociations(regionCount, region, role);
-}
-
-/**
- * Read property of bool m_activated.
- */
-bool AssociationWidget::isActivated() const
-{
- return m_activated;
-}
-
-/**
- * Set the m_activated flag of a widget but does not perform the Activate method.
- */
-void AssociationWidget::setActivated(bool active)
-{
- m_activated = active;
-}
-
-/**
- * Synchronize this widget from the UMLAssociation.
- */
-void AssociationWidget::syncToModel()
-{
- UMLAssociation *uml = association();
-
- if (uml == NULL) {
- UMLAttribute *attr = attribute();
- if (attr == NULL)
- return;
- setVisibility(attr->visibility(), RoleType::B);
- setRoleName(attr->name(), RoleType::B);
- return;
- }
- // block signals until finished
- uml->blockSignals(true);
-
- setName(uml->name());
- setRoleName(uml->getRoleName(RoleType::A), RoleType::A);
- setRoleName(uml->getRoleName(RoleType::B), RoleType::B);
- setVisibility(uml->visibility(RoleType::A), RoleType::A);
- setVisibility(uml->visibility(RoleType::B), RoleType::B);
- setChangeability(uml->changeability(RoleType::A), RoleType::A);
- setChangeability(uml->changeability(RoleType::B), RoleType::B);
- setMultiplicity(uml->getMultiplicity(RoleType::A), RoleType::A);
- setMultiplicity(uml->getMultiplicity(RoleType::B), RoleType::B);
-
- uml->blockSignals(false);
-}
-
-/**
- * Merges/syncs the association widget data into UML object
- * representation.
- * This will synchronize UMLAssociation w/ this new Widget
- * CHECK: Can we get rid of this.
- */
-void AssociationWidget::mergeAssociationDataIntoUMLRepresentation()
-{
- UMLAssociation *umlassoc = association();
- UMLAttribute *umlattr = attribute();
- if (umlassoc == NULL && umlattr == NULL)
- return;
-
- // block emit modified signal, or we get a horrible loop
- m_umlObject->blockSignals(true);
-
- // would be desirable to do the following
- // so that we can be sure its back to initial state
- // in case we missed something here.
- //uml->init();
-
- // floating text widgets
- FloatingTextWidget *text = nameWidget();
- if (text)
- m_umlObject->setName(text->text());
-
- text = roleWidget(RoleType::A);
- if (text && umlassoc)
- umlassoc->setRoleName(text->text(), RoleType::A);
-
- text = roleWidget(RoleType::B);
- if (text) {
- if (umlassoc)
- umlassoc->setRoleName(text->text(), RoleType::B);
- else if (umlattr)
- umlattr->setName(text->text());
- }
-
- text = multiplicityWidget(RoleType::A);
- if (text && umlassoc)
- umlassoc->setMultiplicity(text->text(), RoleType::A);
-
- text = multiplicityWidget(RoleType::B);
- if (text && umlassoc)
- umlassoc->setMultiplicity(text->text(), RoleType::B);
-
- // unblock
- m_umlObject->blockSignals(false);
-}
-
-/**
- * Auxiliary method for widgetMoved():
- * Saves all ideally computed floatingtext positions before doing any
- * kind of change. This is necessary because a single invocation of
- * calculateEndingPoints() modifies the AssociationLine ending points on ALL
- * AssociationWidgets. This means that if we don't save the old ideal
- * positions then they are irretrievably lost as soon as
- * calculateEndingPoints() is invoked.
- */
-void AssociationWidget::saveIdealTextPositions()
-{
- m_oldNamePoint = calculateTextPosition(TextRole::Name);
- m_oldMultiAPoint = calculateTextPosition(TextRole::MultiA);
- m_oldMultiBPoint = calculateTextPosition(TextRole::MultiB);
- m_oldChangeAPoint = calculateTextPosition(TextRole::ChangeA);
- m_oldChangeBPoint = calculateTextPosition(TextRole::ChangeB);
- m_oldRoleAPoint = calculateTextPosition(TextRole::RoleAName);
- m_oldRoleBPoint = calculateTextPosition(TextRole::RoleBName);
-}
-
-/**
- * Adjusts the ending point of the association that connects to Widget.
- */
-void AssociationWidget::widgetMoved(UMLWidget* widget, qreal dx, qreal dy)
-{
- Q_UNUSED(dx); Q_UNUSED(dy);
-
- // Simple Approach to block moveEvent during load of XMI
- /// @todo avoid trigger of this event during load
- if (umlDoc()->loading()) {
- // change of position during load of XMI
- // -> there is something wrong
- // -> avoid movement during opening
- // -> print warn and stay at old position
- DEBUG(DBG_SRC) << "called during load of XMI for ViewType: " << m_scene->type()
- << ", and BaseType: " << baseTypeStr();
- return;
- }
-
- DEBUG(DBG_SRC) << "association type=" << Uml::AssociationType::toString(associationType());
- if (associationType() == AssociationType::Exception) {
- updatePointsException();
- setTextPosition(TextRole::Name);
- }
- else {
- calculateEndingPoints();
- computeAssocClassLine();
- }
-
- // Assoc to self - move all points:
- if (isSelf()) {
- updatePointsSelfAssociation();
-
- if (m_nameWidget && !m_nameWidget->isSelected()) {
- setTextPositionRelatively(TextRole::Name, m_oldNamePoint);
- }
-
- }//end if widgetA = widgetB
- else if (m_role[RoleType::A].umlWidget == widget) {
- if (m_nameWidget && m_unNameLineSegment == 0 && !m_nameWidget->isSelected() ) {
- //only calculate position and move text if the segment it is on is moving
- setTextPositionRelatively(TextRole::Name, m_oldNamePoint);
- }
- }//end if widgetA moved
- else if (m_role[RoleType::B].umlWidget == widget) {
- const int size = m_associationLine->count();
- if (m_nameWidget && (m_unNameLineSegment == size-2) && !m_nameWidget->isSelected() ) {
- //only calculate position and move text if the segment it is on is moving
- setTextPositionRelatively(TextRole::Name, m_oldNamePoint);
- }
- }//end if widgetB moved
-
- if (m_role[RoleType::A].roleWidget && !m_role[RoleType::A].roleWidget->isSelected()) {
- setTextPositionRelatively(TextRole::RoleAName, m_oldRoleAPoint);
- }
- if (m_role[RoleType::B].roleWidget && !m_role[RoleType::B].roleWidget->isSelected()) {
- setTextPositionRelatively(TextRole::RoleBName, m_oldRoleBPoint);
- }
- if (m_role[RoleType::A].multiplicityWidget && !m_role[RoleType::A].multiplicityWidget->isSelected()) {
- setTextPositionRelatively(TextRole::MultiA, m_oldMultiAPoint);
- }
- if (m_role[RoleType::B].multiplicityWidget && !m_role[RoleType::B].multiplicityWidget->isSelected()) {
- setTextPositionRelatively(TextRole::MultiB, m_oldMultiBPoint);
- }
- if (m_role[RoleType::A].changeabilityWidget && !m_role[RoleType::A].changeabilityWidget->isSelected()) {
- setTextPositionRelatively(TextRole::ChangeA, m_oldChangeAPoint);
- }
- if (m_role[RoleType::B].changeabilityWidget && !m_role[RoleType::B].changeabilityWidget->isSelected()) {
- setTextPositionRelatively(TextRole::ChangeB, m_oldChangeBPoint);
- }
-}
-
-/**
- * Creates the points of the self association.
- * Method called when a widget end points are calculated by calculateEndingPoints().
- */
-void AssociationWidget::createPointsSelfAssociation()
-{
- UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
-
- const int DISTANCE = 50;
- qreal x = pWidgetA->x();
- qreal y = pWidgetA->y();
- qreal h = pWidgetA->height();
- qreal w = pWidgetA->width();
- // see if above widget ok to start
- if (y - DISTANCE > 0) {
- m_associationLine->setEndPoints(QPointF(x + w / 4, y) , QPointF(x + w * 3 / 4, y));
- m_associationLine->insertPoint(1, QPointF(x + w / 4, y - DISTANCE));
- m_associationLine->insertPoint(2, QPointF(x + w * 3 / 4, y - DISTANCE));
- m_role[RoleType::A].m_WidgetRegion = m_role[RoleType::B].m_WidgetRegion = Uml::Region::North;
- } else {
- m_associationLine->setEndPoints(QPointF(x + w / 4, y + h), QPointF(x + w * 3 / 4, y + h));
- m_associationLine->insertPoint(1, QPointF(x + w / 4, y + h + DISTANCE));
- m_associationLine->insertPoint(2, QPointF(x + w * 3 / 4, y + h + DISTANCE));
- m_role[RoleType::A].m_WidgetRegion = m_role[RoleType::B].m_WidgetRegion = Uml::Region::South;
- }
-}
-
-/**
- * Adjusts the points of the self association.
- * Method called when a widget was moved by widgetMoved(widget, x, y).
- */
-void AssociationWidget::updatePointsSelfAssociation()
-{
- UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
-
- const int DISTANCE = 50;
- qreal x = pWidgetA->x();
- qreal y = pWidgetA->y();
- qreal h = pWidgetA->height();
- qreal w = pWidgetA->width();
- // see if above widget ok to start
- if (y - DISTANCE > 0) {
- m_associationLine->setEndPoints(QPointF(x + w / 4, y) , QPointF(x + w * 3 / 4, y));
- m_associationLine->setPoint(1, QPointF(x + w / 4, y - DISTANCE));
- m_associationLine->setPoint(2, QPointF(x + w * 3 / 4, y - DISTANCE));
- m_role[RoleType::A].m_WidgetRegion = m_role[RoleType::B].m_WidgetRegion = Uml::Region::North;
- } else {
- m_associationLine->setEndPoints(QPointF(x + w / 4, y + h), QPointF(x + w * 3 / 4, y + h));
- m_associationLine->setPoint(1, QPointF(x + w / 4, y + h + DISTANCE));
- m_associationLine->setPoint(2, QPointF(x + w * 3 / 4, y + h + DISTANCE));
- m_role[RoleType::A].m_WidgetRegion = m_role[RoleType::B].m_WidgetRegion = Uml::Region::South;
- }
-}
-
-/**
- * Creates the points of the association exception.
- * Method called when a widget end points are calculated by calculateEndingPoints().
- */
-void AssociationWidget::createPointsException()
-{
- UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
- UMLWidget *pWidgetB = m_role[RoleType::B].umlWidget;
-
- qreal xa = pWidgetA->x();
- qreal ya = pWidgetA->y();
- qreal ha = pWidgetA->height();
- qreal wa = pWidgetA->width();
-
- qreal xb = pWidgetB->x();
- qreal yb = pWidgetB->y();
- qreal hb = pWidgetB->height();
- //qreal wb = pWidgetB->width();
-
- m_associationLine->setEndPoints(QPointF(xa + wa , ya + ha/2) , QPointF(xb , yb + hb/2));
- m_associationLine->insertPoint(1, QPointF(xa + wa , ya + ha/2));
- m_associationLine->insertPoint(2, QPointF(xb , yb + hb/2));
-}
-
-/**
- * Adjusts the points of the association exception.
- * Method called when a widget was moved by widgetMoved(widget, x, y).
- */
-void AssociationWidget::updatePointsException()
-{
- UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
- UMLWidget *pWidgetB = m_role[RoleType::B].umlWidget;
-
- qreal xa = pWidgetA->x();
- qreal ya = pWidgetA->y();
- qreal ha = pWidgetA->height();
- qreal wa = pWidgetA->width();
-
- qreal xb = pWidgetB->x();
- qreal yb = pWidgetB->y();
- qreal hb = pWidgetB->height();
- qreal wb = pWidgetB->width();
- qreal xmil, ymil;
- qreal xdeb, ydeb;
- qreal xfin, yfin;
- qreal ESPACEX, ESPACEY;
- QPointF p1;
- QPointF p2;
- //calcul des coordonnées au milieu de la flèche eclair
- if (xb - xa - wa >= 45) {
- ESPACEX = 0;
- xdeb = xa + wa;
- xfin = xb;
- } else if (xa - xb - wb > 45) {
- ESPACEX = 0;
- xdeb = xa;
- xfin = xb + wb;
- } else {
- ESPACEX = 15;
- xdeb = xa + wa/2;
- xfin = xb + wb/2;
- }
-
- xmil = xdeb + (xfin - xdeb)/2;
-
- if (yb - ya - ha >= 45) {
- ESPACEY = 0;
- ydeb = ya + ha;
- yfin = yb;
- } else if (ya - yb - hb > 45) {
- ESPACEY = 0;
- ydeb = ya;
- yfin = yb + hb;
- } else {
- ESPACEY = 15;
- ydeb = ya + ha/2;
- yfin = yb + hb/2;
- }
-
- ymil = ydeb + (yfin - ydeb)/2;
-
- p1.setX(xmil + (xfin - xmil)*1/2); p1.setY(ymil + (yfin - ymil)*1/3);
- p2.setX(xmil - (xmil - xdeb)*1/2); p2.setY(ymil - (ymil - ydeb)*1/3);
-
- if (abs(p1.x() - p2.x()) <= 10)
- ESPACEX = 15;
- if (abs(p1.y() - p2.y()) <= 10)
- ESPACEY = 15;
-
- m_associationLine->setEndPoints(QPointF(xdeb, ydeb), QPointF(xfin, yfin));
- m_associationLine->setPoint(1, QPointF(p1.x() + ESPACEX, p1.y() + ESPACEY));
- m_associationLine->setPoint(2, QPointF(p2.x() - ESPACEX, p2.y() - ESPACEY));
-
- m_role[RoleType::A].m_WidgetRegion = m_role[RoleType::B].m_WidgetRegion = Uml::Region::North;
-}
-
-/**
- * Finds out which region of rectangle 'rect' contains the point 'pos' and returns the region
- * number:
- * 1 = Region 1
- * 2 = Region 2
- * 3 = Region 3
- * 4 = Region 4
- * 5 = On diagonal 2 between Region 1 and 2
- * 6 = On diagonal 1 between Region 2 and 3
- * 7 = On diagonal 2 between Region 3 and 4
- * 8 = On diagonal 1 between Region 4 and 1
- * 9 = On diagonal 1 and On diagonal 2 (the center)
- */
-Uml::Region::Enum AssociationWidget::findPointRegion(const QRectF& rect, const QPointF &pos)
-{
- qreal w = rect.width();
- qreal h = rect.height();
- qreal x = rect.x();
- qreal y = rect.y();
- qreal slope2 = w / h;
- qreal slope1 = slope2 *(-1.0);
- qreal b1 = x + w - (slope1 * y);
- qreal b2 = x - (slope2 * y);
-
- qreal eval1 = slope1 * pos.y() + b1;
- qreal eval2 = slope2 * pos.y() + b2;
-
- Uml::Region::Enum result = Uml::Region::Error;
- //if inside region 1
- if (eval1 > pos.x() && eval2 > pos.x()) {
- result = Uml::Region::West;
- }
- //if inside region 2
- else if (eval1 > pos.x() && eval2 < pos.x()) {
- result = Uml::Region::North;
- }
- //if inside region 3
- else if (eval1 < pos.x() && eval2 < pos.x()) {
- result = Uml::Region::East;
- }
- //if inside region 4
- else if (eval1 < pos.x() && eval2 > pos.x()) {
- result = Uml::Region::South;
- }
- //if inside region 5
- else if (eval1 == pos.x() && eval2 < pos.x()) {
- result = Uml::Region::NorthWest;
- }
- //if inside region 6
- else if (eval1 < pos.x() && eval2 == pos.x()) {
- result = Uml::Region::NorthEast;
- }
- //if inside region 7
- else if (eval1 == pos.x() && eval2 > pos.x()) {
- result = Uml::Region::SouthEast;
- }
- //if inside region 8
- else if (eval1 > pos.x() && eval2 == pos.x()) {
- result = Uml::Region::SouthWest;
- }
- //if inside region 9
- else if (eval1 == pos.x() && eval2 == pos.x()) {
- result = Uml::Region::Center;
- }
- return result;
-}
-
-/**
- * Returns a point with interchanged X and Y coordinates.
- */
-QPointF AssociationWidget::swapXY(const QPointF &p)
-{
- QPointF swapped( p.y(), p.x() );
- return swapped;
-}
-
-#if 0 // not used at the moment
-/**
- * Calculates which point of segment P1P2 has a distance equal to
- * Distance from P1.
- * Let's say such point is PX, the distance from P1 to PX must be equal
- * to Distance and if PX is not a point of the segment P1P2 then the
- * function returns (-1, -1).
- */
-QPointF AssociationWidget::calculatePointAtDistance(const QPointF &P1, const QPointF &P2, float Distance)
-{
- /*
- the distance D between points (x1, y1) and (x3, y3) has the following formula:
- --- ------------------------------
- D = \ / 2 2
- \ / (x3 - x1) + (y3 - y1)
-
- D, x1 and y1 are known and the point (x3, y3) is inside line (x1, y1)(x2, y2), so if the
- that line has the formula y = mx + b
- then y3 = m*x3 + b
-
- 2 2 2
- D = (x3 - x1) + (y3 - y1)
-
- 2 2 2 2 2
- D = x3 - 2*x3*x1 + x1 + y3 - 2*y3*y1 + y1
-
- 2 2 2 2 2
- D - x1 - y1 = x3 - 2*x3*x1 + y3 - 2*y3*y1
-
- 2 2 2 2 2
- D - x1 - y1 = x3 - 2*x3*x1 + (m*x3 + b) - 2*(m*x3 + b)*y1
-
- 2 2 2 2 2 2
- D - x1 - y1 + 2*b*y1 - b = (m + 1)*x3 + (-2*x1 + 2*m*b -2*m*y1)*x3
-
- 2 2 2 2
- C = - D + x1 + y1 - 2*b*y1 + b
-
-
- 2
- A = (m + 1)
-
- B = (-2*x1 + 2*m*b -2*m*y1)
-
- and we have
- 2
- A * x3 + B * x3 - C = 0
-
- ---------------
- -B + --- / 2
- \/ B - 4*A*C
- sol_1 = --------------------------------
- 2*A
-
-
- ---------------
- -B - --- / 2
- \/ B - 4*A*C
- sol_2 = --------------------------------
- 2*A
-
-
- then in the distance formula we have only one variable x3 and that is easy
- to calculate
- */
- int x1 = P1.y();
- int y1 = P1.x();
- int x2 = P2.y();
- int y2 = P2.x();
-
- if (x2 == x1) {
- return QPointF(x1, y1 + (int)Distance);
- }
- float slope = ((float)y2 - (float)y1) / ((float)x2 - (float)x1);
- float b = (y1 - slope*x1);
- float A = (slope * slope) + 1;
- float B = (2*slope*b) - (2*x1) - (2*slope*y1);
- float C = (b*b) - (Distance*Distance) + (x1*x1) + (y1*y1) - (2*b*y1);
- float t = B*B - 4*A*C;
-
- if (t < 0) {
- return QPointF(-1, -1);
- }
- float sol_1 = ((-1* B) + sqrt(t)) / (2*A);
- float sol_2 = ((-1*B) - sqrt(t)) / (2*A);
-
- if (sol_1 < 0.0 && sol_2 < 0.0) {
- return QPointF(-1, -1);
- }
- QPointF sol1Point((int)(slope*sol_1 + b), (int)(sol_1));
- QPointF sol2Point((int)(slope*sol_2 + b), (int)(sol_2));
- if (sol_1 < 0 && sol_2 >=0) {
- if (x2 > x1) {
- if (x1 <= sol_2 && sol_2 <= x2)
- return sol2Point;
- } else {
- if (x2 <= sol_2 && sol_2 <= x1)
- return sol2Point;
- }
- } else if (sol_1 >= 0 && sol_2 < 0) {
- if (x2 > x1) {
- if (x1 <= sol_1 && sol_1 <= x2)
- return sol1Point;
- } else {
- if (x2 <= sol_1 && sol_1 <= x1)
- return sol1Point;
- }
- } else {
- if (x2 > x1) {
- if (x1 <= sol_1 && sol_1 <= x2)
- return sol1Point;
- if (x1 <= sol_2 && sol_2 <= x2)
- return sol2Point;
- } else {
- if (x2 <= sol_1 && sol_1 <= x1)
- return sol1Point;
- if (x2 <= sol_2 && sol_2 <= x1)
- return sol2Point;
- }
- }
- return QPointF(-1, -1);
-}
-
-/**
- * Calculates which point of a perpendicular line to segment P1P2 that contains P2
- * has a distance equal to Distance from P2,
- * Lets say such point is P3, the distance from P2 to P3 must be equal to Distance
- */
-QPointF AssociationWidget::calculatePointAtDistanceOnPerpendicular(const QPointF &P1, const QPointF &P2, float Distance)
-{
- /*
- the distance D between points (x2, y2) and (x3, y3) has the following formula:
-
- --- ------------------------------
- D = \ / 2 2
- \ / (x3 - x2) + (y3 - y2)
-
- D, x2 and y2 are known and line P2P3 is perpendicular to line (x1, y1)(x2, y2), so if the
- line P1P2 has the formula y = m*x + b,
- then (x1 - x2)
- m = -----------, because it is perpendicular to line P1P2
- (y2 - y1)
-
- also y2 = m*x2 + b
- => b = y2 - m*x2
-
- then P3 = (x3, m*x3 + b)
-
- 2 2 2
- D = (x3 - x2) + (y3 - y2)
-
- 2 2 2 2 2
- D = x3 - 2*x3*x2 + x2 + y3 - 2*y3*y2 + y2
-
- 2 2 2 2 2
- D - x2 - y2 = x3 - 2*x3*x2 + y3 - 2*y3*y2
-
-
-
- 2 2 2 2 2
- D - x2 - y2 = x3 - 2*x3*x2 + (m*x3 + b) - 2*(m*x3 + b)*y2
-
- 2 2 2 2 2 2
- D - x2 - y2 + 2*b*y2 - b = (m + 1)*x3 + (-2*x2 + 2*m*b -2*m*y2)*x3
-
- 2 2 2 2
- C = - D + x2 + y2 - 2*b*y2 + b
-
- 2
- A = (m + 1)
-
- B = (-2*x2 + 2*m*b -2*m*y2)
-
- and we have
- 2
- A * x3 + B * x3 - C = 0
-
-
- ---------------
- --- / 2
- -B + \/ B - 4*A*C
- sol_1 = --------------------------------
- 2*A
-
-
- ---------------
- --- / 2
- -B - \/ B - 4*A*C
- sol_2 = --------------------------------
- 2*A
-
- then in the distance formula we have only one variable x3 and that is easy
- to calculate
- */
- if (P1.x() == P2.x()) {
- return QPointF((int)(P2.x() + Distance), P2.y());
- }
- const int x1 = P1.y();
- const int y1 = P1.x();
- const int x2 = P2.y();
- const int y2 = P2.x();
-
- float slope = ((float)x1 - (float)x2) / ((float)y2 - (float)y1);
- float b = (y2 - slope*x2);
- float A = (slope * slope) + 1;
- float B = (2*slope*b) - (2*x2) - (2*slope*y2);
- float C = (b*b) - (Distance*Distance) + (x2*x2) + (y2*y2) - (2*b*y2);
- float t = B*B - 4*A*C;
- if (t < 0) {
- return QPointF(-1, -1);
- }
- float sol_1 = ((-1* B) + sqrt(t)) / (2*A);
-
- float sol_2 = ((-1*B) - sqrt(t)) / (2*A);
-
- if (sol_1 < 0 && sol_2 < 0) {
- return QPointF(-1, -1);
- }
- QPointF sol1Point((int)(slope*sol_1 + b), (int)sol_1);
- QPointF sol2Point((int)(slope*sol_2 + b), (int)sol_2);
- if (sol_1 < 0 && sol_2 >=0) {
- return sol2Point;
- } else if (sol_1 >= 0 && sol_2 < 0) {
- return sol1Point;
- } else { // Choose one solution, either will work fine
- if (slope >= 0) {
- if (sol_1 <= sol_2)
- return sol2Point;
- else
- return sol1Point;
- } else {
- if (sol_1 <= sol_2)
- return sol1Point;
- else
- return sol2Point;
- }
-
- }
- return QPointF(-1, -1); // never reached, just keep compilers happy
-}
-
-/**
- * Calculates the intersection (PS) between line P1P2 and a perpendicular line containing
- * P3, the result is returned in ResultingPoint. and result value represents the distance
- * between ResultingPoint and P3; if this value is negative an error ocurred.
- */
-float AssociationWidget::perpendicularProjection(const QPointF& P1, const QPointF& P2, const QPointF& P3,
- QPointF& ResultingPoint)
-{
- //line P1P2 is Line 1 = y=slope1*x + b1
-
- //line P3PS is Line 1 = y=slope2*x + b2
-
- float slope2 = 0;
- float slope1 = 0;
- float sx = 0, sy = 0;
- int y2 = P2.x();
- int y1 = P1.x();
- int x2 = P2.y();
- int x1 = P1.y();
- int y3 = P3.x();
- int x3 = P3.y();
- float distance = 0;
- float b1 = 0;
-
- float b2 = 0;
-
- if (x2 == x1) {
- sx = x2;
- sy = y3;
- } else if (y2 == y1) {
- sy = y2;
- sx = x3;
- } else {
- slope1 = (y2 - y1)/ (x2 - x1);
- slope2 = (x1 - x2)/ (y2 - y1);
- b1 = y2 - (slope1 * x2);
- b2 = y3 - (slope2 * x3);
- sx = (b2 - b1) / (slope1 - slope2);
- sy = slope1*sx + b1;
- }
- distance = (int)(sqrt(((x3 - sx)*(x3 - sx)) + ((y3 - sy)*(y3 - sy))));
-
- ResultingPoint.setX((int)sy);
- ResultingPoint.setY((int)sx);
-
- return distance;
-}
-#endif
-
-/**
- * Calculates the position of the text widget depending on the role
- * that widget is playing.
- * Returns the point at which to put the widget.
- */
-QPointF AssociationWidget::calculateTextPosition(Uml::TextRole::Enum role)
-{
- const int SPACE = 2;
- QPointF p(-1, -1), q(-1, -1);
-
- // used to find out if association end point (p)
- // is at top or bottom edge of widget.
-
- if (role == TextRole::MultiA || role == TextRole::ChangeA || role == TextRole::RoleAName) {
- p = m_associationLine->point(0);
- q = m_associationLine->point(1);
- } else if (role == TextRole::MultiB || role == TextRole::ChangeB || role == TextRole::RoleBName) {
- const int lastSegment = m_associationLine->count() - 1;
- p = m_associationLine->point(lastSegment);
- q = m_associationLine->point(lastSegment - 1);
- } else if (role != TextRole::Name) {
- uError() << "called with unsupported TextRole::Enum " << role;
- return QPointF(-1, -1);
- }
-
- FloatingTextWidget *text = textWidgetByRole(role);
- int textW = 0, textH = 0;
- if (text) {
- textW = text->width();
- textH = text->height();
- }
-
- qreal x = 0.0, y = 0.0;
-
- if (role == TextRole::MultiA || role == TextRole::MultiB) {
- const bool isHorizontal = (p.y() == q.y());
- const int atBottom = p.y() + SPACE;
- const int atTop = p.y() - SPACE - textH;
- const int atLeft = p.x() - SPACE - textW;
- const int atRight = p.x() + SPACE;
- y = (p.y() > q.y()) == isHorizontal ? atBottom : atTop;
- x = (p.x() < q.x()) == isHorizontal ? atRight : atLeft;
-
- } else if (role == TextRole::ChangeA || role == TextRole::ChangeB) {
-
- if (p.y() > q.y())
- y = p.y() - SPACE - (textH * 2);
- else
- y = p.y() + SPACE + textH;
-
- if (p.x() < q.x())
- x = p.x() + SPACE;
- else
- x = p.x() - SPACE - textW;
-
- } else if (role == TextRole::RoleAName || role == TextRole::RoleBName) {
-
- if (p.y() > q.y())
- y = p.y() - SPACE - textH;
- else
- y = p.y() + SPACE;
-
- if (p.x() < q.x())
- x = p.x() + SPACE;
- else
- x = p.x() - SPACE - textW;
-
- } else if (role == TextRole::Name) {
-
- calculateNameTextSegment();
- if (m_unNameLineSegment == -1) {
- uWarning() << "TODO:negative line segment index";
- m_unNameLineSegment = 0;
- }
- x = ( m_associationLine->point(m_unNameLineSegment).x() +
- m_associationLine->point(m_unNameLineSegment + 1).x() ) / 2;
- y = ( m_associationLine->point(m_unNameLineSegment).y() +
- m_associationLine->point(m_unNameLineSegment + 1).y() ) / 2;
- }
-
- if (text) {
- constrainTextPos(x, y, textW, textH, role);
- }
- p = QPointF( x, y );
- return p;
-}
-
-/**
- * Return the mid point between p0 and p1
- */
-QPointF AssociationWidget::midPoint(const QPointF& p0, const QPointF& p1)
-{
- QPointF midP;
- if (p0.x() < p1.x())
- midP.setX(p0.x() + (p1.x() - p0.x()) / 2);
- else
- midP.setX(p1.x() + (p0.x() - p1.x()) / 2);
- if (p0.y() < p1.y())
- midP.setY(p0.y() + (p1.y() - p0.y()) / 2);
- else
- midP.setY(p1.y() + (p0.y() - p1.y()) / 2);
- return midP;
-}
-
-/**
- * Constrains the FloatingTextWidget X and Y values supplied.
- * Implements the abstract operation from LinkWidget.
- *
- * @param textX Candidate X value (may be modified by the constraint.)
- * @param textY Candidate Y value (may be modified by the constraint.)
- * @param textWidth Width of the text.
- * @param textHeight Height of the text.
- * @param tr Uml::Text_Role of the text.
- */
-void AssociationWidget::constrainTextPos(qreal &textX, qreal &textY,
- qreal textWidth, qreal textHeight,
- Uml::TextRole::Enum tr)
-{
- const int textCenterX = textX + textWidth / 2;
- const int textCenterY = textY + textHeight / 2;
- const int lastSegment = m_associationLine->count() - 1;
- QPointF p0, p1;
- switch (tr) {
- case TextRole::RoleAName:
- case TextRole::MultiA:
- case TextRole::ChangeA:
- p0 = m_associationLine->point(0);
- p1 = m_associationLine->point(1);
- // If we are dealing with a single line then tie the
- // role label to the proper half of the line, i.e.
- // the role label must be closer to the "other"
- // role object.
- if (lastSegment == 1)
- p1 = midPoint(p0, p1);
- break;
- case TextRole::RoleBName:
- case TextRole::MultiB:
- case TextRole::ChangeB:
- p0 = m_associationLine->point(lastSegment - 1);
- p1 = m_associationLine->point(lastSegment);
- if (lastSegment == 1)
- p0 = midPoint(p0, p1);
- break;
- case TextRole::Name:
- case TextRole::Coll_Message: // CHECK: collab.msg texts seem to be TextRole::Name
- case TextRole::State: // CHECK: is this used?
- // Find the linepath segment to which the (textX, textY) is closest
- // and constrain to the corridor of that segment (see farther below)
- {
- int minDistSquare = 100000; // utopian initial value
- int lpIndex = 0;
- for (int i = 0; i < lastSegment; ++i) {
- p0 = m_associationLine->point(i);
- p1 = m_associationLine->point(i + 1);
- QPointF midP = midPoint(p0, p1);
- const int deltaX = textCenterX - midP.x();
- const int deltaY = textCenterY - midP.y();
- const int cSquare = deltaX * deltaX + deltaY * deltaY;
- if (cSquare < minDistSquare) {
- minDistSquare = cSquare;
- lpIndex = i;
- }
- }
- p0 = m_associationLine->point(lpIndex);
- p1 = m_associationLine->point(lpIndex + 1);
- }
- break;
- default:
- uError() << "unexpected TextRole::Enum " << tr;
- return;
- break;
- }
- /* Constraint:
- The midpoint between p0 and p1 is taken to be the center of a circle
- with radius D/2 where D is the distance between p0 and p1.
- The text center needs to be within this circle else it is constrained
- to the nearest point on the circle.
- */
- p0 = swapXY(p0); // go to the natural coordinate system
- p1 = swapXY(p1); // with (0,0) in the lower left corner
- QPointF midP = midPoint(p0, p1);
- // If (textX,textY) is not inside the circle around midP then
- // constrain (textX,textY) to the nearest point on that circle.
- const int x0 = p0.x();
- const int y0 = p0.y();
- const int x1 = p1.x();
- const int y1 = p1.y();
- double r = sqrt((double)((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0))) / 2;
- if (textWidth > r)
- r = textWidth;
- // swap textCenter{X,Y} to convert from Qt coord.system.
- const QPointF origTextCenter(textCenterY, textCenterX);
- const int relX = abs(origTextCenter.x() - midP.x());
- const int relY = abs(origTextCenter.y() - midP.y());
- const double negativeWhenInsideCircle = relX * relX + relY * relY - r * r;
- if (negativeWhenInsideCircle <= 0.0) {
- return;
- }
- /*
- The original constraint was to snap the text position to the
- midpoint but that creates unpleasant visual jitter:
- textX = midP.y() - textWidth / 2; // go back to Qt coord.sys.
- textY = midP.x() - textHeight / 2; // go back to Qt coord.sys.
-
- Rather, we project the text position onto the closest point
- on the circle:
-
- Circle equation:
- relX^2 + relY^2 - r^2 = 0, or in other words
- relY^2 = r^2 - relX^2, or
- relY = sqrt(r^2 - relX^2)
- Line equation:
- relY = a * relX + b
- We can omit "b" because relX and relY are already relative to
- the circle origin, therefore we can also write:
- a = relY / relX
- To obtain the point of intersection between the circle of radius r
- and the line connecting the circle origin with the point (relX, relY),
- we equate the relY:
- a * x = sqrt(r^2 - x^2), or in other words
- a^2 * x^2 = r^2 - x^2, or
- x^2 * (a^2 + 1) = r^2, or
- x^2 = r^2 / (a^2 + 1), or
- x = sqrt(r^2 / (a^2 + 1))
- and then
- y = a * x
- The resulting x and y are relative to the circle origin so we just add
- the circle origin (X, Y) to obtain the constrained (textX, textY).
- */
- // Handle the special case, relX = 0.
- if (relX == 0) {
- if (origTextCenter.y() > midP.y())
- textX = midP.y() + (int)r; // go back to Qt coord.sys.
- else
- textX = midP.y() - (int)r; // go back to Qt coord.sys.
- textX -= textWidth / 2;
- return;
- }
- const double a = (double)relY / (double)relX;
- const double x = sqrt(r*r / (a*a + 1));
- const double y = a * x;
- if (origTextCenter.x() > midP.x())
- textY = midP.x() + (int)x; // go back to Qt coord.sys.
- else
- textY = midP.x() - (int)x; // go back to Qt coord.sys.
- textY -= textHeight / 2;
- if (origTextCenter.y() > midP.y())
- textX = midP.y() + (int)y; // go back to Qt coord.sys.
- else
- textX = midP.y() - (int)y; // go back to Qt coord.sys.
- textX -= textWidth / 2;
-}
-
-/**
- * Puts the text widget with the given role at the given position.
- * This method calls @ref calculateTextPostion to get the needed position.
- * I.e. the line segment it is on has moved and it should move the same
- * amount as the line.
- */
-void AssociationWidget::setTextPosition(Uml::TextRole::Enum role)
-{
- bool startMove = false;
- if (m_role[RoleType::A].multiplicityWidget && m_role[RoleType::A].multiplicityWidget->getStartMove())
- startMove = true;
- else if (m_role[RoleType::B].multiplicityWidget && m_role[RoleType::B].multiplicityWidget->getStartMove())
- startMove = true;
- else if (m_role[RoleType::A].changeabilityWidget && m_role[RoleType::A].changeabilityWidget->getStartMove())
- startMove = true;
- else if (m_role[RoleType::B].changeabilityWidget && m_role[RoleType::B].changeabilityWidget->getStartMove())
- startMove = true;
- else if (m_role[RoleType::A].roleWidget && m_role[RoleType::A].roleWidget->getStartMove())
- startMove = true;
- else if (m_role[RoleType::B].roleWidget && m_role[RoleType::B].roleWidget->getStartMove())
- startMove = true;
- else if (m_nameWidget && m_nameWidget->getStartMove())
- startMove = true;
- if (startMove) {
- return;
- }
- FloatingTextWidget *ft = textWidgetByRole(role);
- if (ft == NULL)
- return;
- QPointF pos = calculateTextPosition(role);
- ft->setX(pos.x());
- ft->setY(pos.y());
-}
-
-/**
- * Moves the text widget with the given role by the difference between
- * the two points.
- */
-void AssociationWidget::setTextPositionRelatively(Uml::TextRole::Enum role, const QPointF &oldPosition)
-{
- bool startMove = false;
- if (m_role[RoleType::A].multiplicityWidget && m_role[RoleType::A].multiplicityWidget->getStartMove())
- startMove = true;
- else if (m_role[RoleType::B].multiplicityWidget && m_role[RoleType::B].multiplicityWidget->getStartMove())
- startMove = true;
- else if (m_role[RoleType::A].changeabilityWidget && m_role[RoleType::A].changeabilityWidget->getStartMove())
- startMove = true;
- else if (m_role[RoleType::B].changeabilityWidget && m_role[RoleType::B].changeabilityWidget->getStartMove())
- startMove = true;
- else if (m_role[RoleType::A].roleWidget && m_role[RoleType::A].roleWidget->getStartMove())
- startMove = true;
- else if (m_role[RoleType::B].roleWidget && m_role[RoleType::B].roleWidget->getStartMove())
- startMove = true;
- else if (m_nameWidget && m_nameWidget->getStartMove())
- startMove = true;
-
- if (startMove) {
- return;
- }
- FloatingTextWidget *ft = textWidgetByRole(role);
- if (ft == NULL)
- return;
- qreal ftX = ft->x();
- qreal ftY = ft->y();
-
- QPointF pos = calculateTextPosition(role);
- int relX = pos.x() - oldPosition.x();
- int relY = pos.y() - oldPosition.y();
- qreal ftNewX = ftX + relX;
- qreal ftNewY = ftY + relY;
-
- bool oldIgnoreSnapToGrid = ft->getIgnoreSnapToGrid();
- ft->setIgnoreSnapToGrid(true);
- ft->setX(ftNewX);
- ft->setY(ftNewY);
- ft->setIgnoreSnapToGrid(oldIgnoreSnapToGrid);
-}
-
-/**
- * Remove dashed connecting line for association class.
- */
-void AssociationWidget::removeAssocClassLine()
-{
- delete m_pAssocClassLineSel0;
- m_pAssocClassLineSel0 = 0;
- delete m_pAssocClassLineSel1;
- m_pAssocClassLineSel1 = 0;
- delete m_pAssocClassLine;
- m_pAssocClassLine = 0;
- if (m_associationClass) {
- m_associationClass->setClassAssociationWidget(0);
- m_associationClass = 0;
- }
-}
-
-/**
- * Creates the association class connecting line.
- */
-void AssociationWidget::createAssocClassLine()
-{
- if (m_pAssocClassLine == NULL) {
- m_pAssocClassLine = new QGraphicsLineItem(this);
- }
- QPen pen(lineColor(), lineWidth(), Qt::DashLine);
- m_pAssocClassLine->setPen(pen);
- // decoration points
- m_pAssocClassLineSel0 = Widget_Utils::decoratePoint(m_pAssocClassLine->line().p1(),
- m_pAssocClassLine);
- m_pAssocClassLineSel1 = Widget_Utils::decoratePoint(m_pAssocClassLine->line().p2(),
- m_pAssocClassLine);
- computeAssocClassLine();
- selectAssocClassLine(false);
-}
-
-/**
- * Creates the association class connecting line using the specified
- * ClassifierWidget.
- *
- * @param classifier The ClassifierWidget to use.
- * @param linePathSegmentIndex The index of the segment where the
- * association class is created.
- */
-void AssociationWidget::createAssocClassLine(ClassifierWidget* classifier,
- int linePathSegmentIndex)
-{
- m_nLinePathSegmentIndex = linePathSegmentIndex;
-
- if (m_nLinePathSegmentIndex < 0) {
- return;
- }
-
- m_associationClass = classifier;
- m_associationClass->setClassAssociationWidget(this);
- m_associationClass->addAssoc(this); // to get widgetMoved(...) for association classes
-
- createAssocClassLine();
-}
-
-/**
- * Compute the end points of m_pAssocClassLine in case this
- * association has an attached association class.
- * TODO: The decoration points make no sense for now, because they are not movable.
- */
-void AssociationWidget::computeAssocClassLine()
-{
- if (m_associationClass == NULL || m_pAssocClassLine == NULL) {
- return;
- }
- if (m_nLinePathSegmentIndex < 0) {
- uError() << "m_nLinePathSegmentIndex is not set";
- return;
- }
-
- QPointF segStart = m_associationLine->point(m_nLinePathSegmentIndex);
- QPointF segEnd = m_associationLine->point(m_nLinePathSegmentIndex + 1);
- const qreal midSegX = segStart.x() + (segEnd.x() - segStart.x()) / 2.0;
- const qreal midSegY = segStart.y() + (segEnd.y() - segStart.y()) / 2.0;
- QPointF segmentMidPoint(midSegX, midSegY);
-
- QLineF possibleAssocLine = QLineF(segmentMidPoint,
- m_associationClass->mapRectToScene(m_associationClass->rect()).center());
- QPointF intersectionPoint;
- QLineF::IntersectType type = intersect(m_associationClass->mapRectToScene(m_associationClass->boundingRect()),
- possibleAssocLine,
- &intersectionPoint);
- // DEBUG(DBG_SRC) << "intersect type=" << type << " / point=" << intersectionPoint;
-
- if (type == QLineF::BoundedIntersection) {
- m_pAssocClassLine->setLine(midSegX, midSegY,
- intersectionPoint.x(), intersectionPoint.y());
-
- if (m_pAssocClassLineSel0 && m_pAssocClassLineSel1) {
- m_pAssocClassLineSel0->setPos(m_pAssocClassLine->line().p1());
- m_pAssocClassLineSel1->setPos(m_pAssocClassLine->line().p2());
- }
- }
-}
-
-/**
- * Renders the association class connecting line selected.
- */
-void AssociationWidget::selectAssocClassLine(bool sel)
-{
- if (m_pAssocClassLineSel0 && m_pAssocClassLineSel1) {
- m_pAssocClassLineSel0->setVisible(sel);
- m_pAssocClassLineSel1->setVisible(sel);
- }
-}
-
-/**
- * Sets the association to be selected.
- */
-void AssociationWidget::mousePressEvent(QGraphicsSceneMouseEvent * me)
-{
- // clear other selected stuff on the screen of ShiftKey
- if (me->modifiers() != Qt::ShiftModifier) {
- m_scene->clearSelected();
- }
-
- if (me->button() == Qt::LeftButton && me->modifiers() == Qt::ControlModifier) {
- if (checkRemovePoint(me->scenePos()))
- return;
- }
-
- // make sure we should be here depending on the button
- if (me->button() != Qt::RightButton && me->button() != Qt::LeftButton) {
- return;
- }
- QPointF mep = me->scenePos();
- // see if `mep' is on the connecting line to the association class
- if (onAssocClassLine(mep)) {
- setSelected(true);
- selectAssocClassLine();
- return;
- }
- setSelected(!isSelected());
- associationLine()->mousePressEvent(me);
-}
-
-/**
- * Displays the right mouse buttom menu if right button is pressed.
- */
-void AssociationWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent * me)
-{
- associationLine()->mouseReleaseEvent(me);
-}
-
-/**
- * Handles the selection from the popup menu.
- */
-void AssociationWidget::slotMenuSelection(QAction* action)
-{
- QString oldText, newText;
- QRegExpValidator v(QRegExp(QLatin1String(".*")), 0);
- Uml::AssociationType::Enum atype = associationType();
- Uml::RoleType::Enum r = RoleType::B;
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- DEBUG(DBG_SRC) << "menu selection = " << ListPopupMenu::toString(sel);
-
- // if it's a collaboration message we now just use the code in floatingtextwidget
- // this means there's some redundant code below but that's better than duplicated code
- if (isCollaboration() && sel != ListPopupMenu::mt_Delete) {
- m_nameWidget->slotMenuSelection(action);
- return;
- }
-
- switch(sel) {
- case ListPopupMenu::mt_Properties:
- if (atype == AssociationType::Seq_Message || atype == AssociationType::Seq_Message_Self) {
- // show op dlg for seq. diagram here
- // don't worry about here, I don't think it can get here as
- // line is widget on seq. diagram
- // here just in case - remove later after testing
- DEBUG(DBG_SRC) << "mt_Properties: assoctype is " << atype;
- } else { //standard assoc dialog
- UMLApp::app()->docWindow()->updateDocumentation(false);
- showPropertiesDialog();
- }
- break;
-
- case ListPopupMenu::mt_Add_Point:
- checkAddPoint(m_eventScenePos);
- break;
-
- case ListPopupMenu::mt_Delete_Point:
- checkRemovePoint(m_eventScenePos);
- break;
-
- case ListPopupMenu::mt_Delete:
- if (m_pAssocClassLineSel0)
- removeAssocClassLine();
- else if (association())
- m_scene->removeAssocInViewAndDoc(this);
- else
- m_scene->removeAssoc(this);
- break;
-
- case ListPopupMenu::mt_Rename_MultiA:
- r = RoleType::A; // fall through
- case ListPopupMenu::mt_Rename_MultiB:
- if (m_role[r].multiplicityWidget)
- oldText = m_role[r].multiplicityWidget->text();
- else
- oldText = QString();
-#if QT_VERSION >= 0x050000
- newText = QInputDialog::getText(m_scene->activeView(),
- i18n("Multiplicity"),
- i18n("Enter multiplicity:"),
- QLineEdit::Normal,
- oldText, NULL);
-#else
- newText = KInputDialog::getText(i18n("Multiplicity"),
- i18n("Enter multiplicity:"),
- oldText, NULL, m_scene->activeView(), &v);
-#endif
- if (newText != oldText) {
- if (FloatingTextWidget::isTextValid(newText)) {
- setMultiplicity(newText, r);
- } else {
- m_scene->removeWidget(m_role[r].multiplicityWidget);
- m_role[r].multiplicityWidget = NULL;
- }
- }
- break;
-
- case ListPopupMenu::mt_Rename_Name:
- if (m_nameWidget)
- oldText = m_nameWidget->text();
- else
- oldText = QString();
-#if QT_VERSION >= 0x050000
- newText = QInputDialog::getText(m_scene->activeView(),
- i18n("Association Name"),
- i18n("Enter association name:"),
- QLineEdit::Normal,
- oldText, NULL);
-#else
- newText = KInputDialog::getText(i18n("Association Name"),
- i18n("Enter association name:"),
- oldText, NULL, m_scene->activeView(), &v);
-#endif
- if (newText != oldText) {
- if (FloatingTextWidget::isTextValid(newText)) {
- setName(newText);
- } else {
- m_scene->removeWidget(m_nameWidget);
- m_nameWidget = NULL;
- }
- }
- break;
-
- case ListPopupMenu::mt_Rename_RoleAName:
- r = RoleType::A; // fall through
- case ListPopupMenu::mt_Rename_RoleBName:
- if (m_role[r].roleWidget)
- oldText = m_role[r].roleWidget->text();
- else
- oldText = QString();
-#if QT_VERSION >= 0x050000
- newText = QInputDialog::getText(m_scene->activeView(),
- i18n("Role Name"),
- i18n("Enter role name:"),
- QLineEdit::Normal,
- oldText, NULL);
-#else
- newText = KInputDialog::getText(i18n("Role Name"),
- i18n("Enter role name:"),
- oldText, NULL, m_scene->activeView(), &v);
-#endif
- if (newText != oldText) {
- if (FloatingTextWidget::isTextValid(newText)) {
- setRoleName(newText, r);
- } else {
- m_scene->removeWidget(m_role[r].roleWidget);
- m_role[r].roleWidget = NULL;
- }
- }
- break;
-
- case ListPopupMenu::mt_Change_Font:
- {
-#if QT_VERSION >= 0x050000
- bool ok = false;
- QFont fnt = QFontDialog::getFont(&ok, font(), m_scene->activeView());
- if (ok)
-#else
- QFont fnt = font();
- if (KFontDialog::getFont(fnt, KFontChooser::NoDisplayFlags, m_scene->activeView()))
-#endif
- lwSetFont(fnt);
- }
- break;
-
- case ListPopupMenu::mt_Line_Color:
- {
-#if QT_VERSION >= 0x050000
- QColor newColor = QColorDialog::getColor(lineColor());
- if (newColor != lineColor()) {
-#else
- QColor newColor;
- if (KColorDialog::getColor(newColor)) {
-#endif
- m_scene->selectionSetLineColor(newColor);
- umlDoc()->setModified(true);
- }
- }
- break;
-
- case ListPopupMenu::mt_Cut:
- m_scene->setStartedCut();
- UMLApp::app()->slotEditCut();
- break;
-
- case ListPopupMenu::mt_Copy:
- UMLApp::app()->slotEditCopy();
- break;
-
- case ListPopupMenu::mt_Paste:
- UMLApp::app()->slotEditPaste();
- break;
-
- case ListPopupMenu::mt_Reset_Label_Positions:
- resetTextPositions();
- break;
-
- case ListPopupMenu::mt_LayoutDirect:
- m_associationLine->setLayout(AssociationLine::Direct);
- break;
- case ListPopupMenu::mt_LayoutSpline:
- m_associationLine->setLayout(AssociationLine::Spline);
- break;
- case ListPopupMenu::mt_LayoutOrthogonal:
- m_associationLine->setLayout(AssociationLine::Orthogonal);
- break;
- case ListPopupMenu::mt_LayoutPolyline:
- m_associationLine->setLayout(AssociationLine::Polyline);
- break;
-
- default:
- DEBUG(DBG_SRC) << "MenuType " << ListPopupMenu::toString(sel) << " not implemented";
- break;
- }//end switch
-}
-
-/**
- * Return the first font found being used by any child widget. (They
- * could be different fonts, so this is a slightly misleading method.)
- */
-QFont AssociationWidget::font() const
-{
- //:TODO: find a general font for the association
- QFont font;
-
- if (m_role[RoleType::A].roleWidget)
- font = m_role[RoleType::A].roleWidget->font();
- else if (m_role[RoleType::B].roleWidget)
- font = m_role[RoleType::B].roleWidget->font();
- else if (m_role[RoleType::A].multiplicityWidget)
- font = m_role[RoleType::A].multiplicityWidget->font();
- else if (m_role[RoleType::B].multiplicityWidget)
- font = m_role[RoleType::B].multiplicityWidget->font();
- else if (m_role[RoleType::A].changeabilityWidget)
- font = m_role[RoleType::A].changeabilityWidget->font();
- else if (m_role[RoleType::B].changeabilityWidget)
- font = m_role[RoleType::B].changeabilityWidget->font();
- else if (m_nameWidget)
- font = m_nameWidget->font();
- else
- font = m_role[RoleType::A].umlWidget->font();
-
- return font;
-}
-
-/**
- * Set all 'owned' child widgets to this text color.
- */
-void AssociationWidget::setTextColor(const QColor &color)
-{
- WidgetBase::setTextColor(color);
- if (m_nameWidget) {
- m_nameWidget->setTextColor(color);
- }
- if (m_role[RoleType::A].roleWidget) {
- m_role[RoleType::A].roleWidget->setTextColor(color);
- }
- if (m_role[RoleType::B].roleWidget) {
- m_role[RoleType::B].roleWidget->setTextColor(color);
- }
- if (m_role[RoleType::A].multiplicityWidget) {
- m_role[RoleType::A].multiplicityWidget->setTextColor(color);
- }
- if (m_role[RoleType::B].multiplicityWidget) {
- m_role[RoleType::B].multiplicityWidget->setTextColor(color);
- }
- if (m_role[RoleType::A].changeabilityWidget)
- m_role[RoleType::A].changeabilityWidget->setTextColor(color);
- if (m_role[RoleType::B].changeabilityWidget)
- m_role[RoleType::B].changeabilityWidget->setTextColor(color);
-}
-
-bool AssociationWidget::checkAddPoint(const QPointF &scenePos)
-{
- if (associationType() == AssociationType::Exception) {
- return false;
- }
-
- // if there is no point around the mouse pointer, we insert a new one
- if (m_associationLine->closestPointIndex(scenePos) < 0) {
- int i = m_associationLine->closestSegmentIndex(scenePos);
- if (i < 0) {
- DEBUG(DBG_SRC) << "no closest segment found!";
- return false;
- }
- m_associationLine->insertPoint(i + 1, scenePos);
- if (m_nLinePathSegmentIndex == i) {
- QPointF segStart = m_associationLine->point(i);
- QPointF segEnd = m_associationLine->point(i + 2);
- const int midSegX = segStart.x() + (segEnd.x() - segStart.x()) / 2;
- const int midSegY = segStart.y() + (segEnd.y() - segStart.y()) / 2;
- /*
- DEBUG(DBG_SRC) << "segStart=" << segStart << ", segEnd=" << segEnd
- << ", midSeg=(" << midSegX << "," << midSegY
- << "), mp=" << mp;
- */
- if (midSegX > scenePos.x() || midSegY < scenePos.y()) {
- m_nLinePathSegmentIndex++;
- DEBUG(DBG_SRC) << "setting m_nLinePathSegmentIndex to "
- << m_nLinePathSegmentIndex;
- computeAssocClassLine();
- }
- m_associationLine->update();
- calculateNameTextSegment();
- umlDoc()->setModified(true);
- setSelected(true);
- }
- return true;
- }
- else {
- DEBUG(DBG_SRC) << "found point already close enough!";
- return false;
- }
-}
-
-/**
- * Remove point close to the given point and redraw the association.
- * @param scenePos point which should be removed
- * @return success status of the remove action
- */
-bool AssociationWidget::checkRemovePoint(const QPointF &scenePos)
-{
- int i = m_associationLine->closestPointIndex(scenePos);
- if (i == -1)
- return false;
-
- m_associationLine->setSelected(false);
-
- // there was a point so we remove the point
- m_associationLine->removePoint(i);
-
- // Maybe reattach association class connecting line
- // to different association linepath segment.
- const int numberOfLines = m_associationLine->count() - 1;
- if (m_nLinePathSegmentIndex >= numberOfLines) {
- m_nLinePathSegmentIndex = numberOfLines - 1;
- }
- calculateEndingPoints();
-
- // select the line path
- m_associationLine->setSelected(true);
-
- m_associationLine->update();
-
- calculateNameTextSegment();
- umlDoc()->setModified(true);
- return true;
-}
-
-/**
- * Moves the break point being dragged.
- */
-void AssociationWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* me)
-{
- if (me->buttons() != Qt::LeftButton) {
- return;
- }
-
- setSelected(true);
-
- associationLine()->mouseMoveEvent(me);
- moveEvent(me);
- m_scene->resizeSceneToItems();
-}
-
-/**
- * Returns the Region the widget to line intersection is for the given
- * widget in this Association. If the given widget is not in the
- * Association then Region::Error is returned.
- * Used by @ref calculateEndingPoints to work these positions out for
- * another Association - since the number of Associations on the same
- * region for the same widget will mean the lines will need to be
- * spread out across the region.
- */
-//Uml::Region::Enum AssociationWidget::getWidgetRegion(AssociationWidget * widget) const
-//{
-// if (widget->widgetForRole(RoleType::A) == m_role[RoleType::A].umlWidget)
-// return m_role[RoleType::A].m_WidgetRegion;
-// if (widget->widgetForRole(RoleType::B) == m_role[RoleType::B].umlWidget)
-// return m_role[RoleType::B].m_WidgetRegion;
-// return Uml::Region::Error;
-//}
-
-/**
- * Returns the number of lines there are on the given region for
- * either widget A or B of the association.
- */
-int AssociationWidget::getRegionCount(Uml::Region::Enum region, Uml::RoleType::Enum role)
-{
- if ((region == Uml::Region::Error) | (umlScene() == NULL)) {
- return 0;
- }
- int widgetCount = 0;
- AssociationWidgetList list = m_scene->associationList();
- foreach (AssociationWidget* assocwidget, list) {
- //don't count this association
- if (assocwidget == this)
- continue;
- const WidgetRole& otherA = assocwidget->m_role[RoleType::A];
- const WidgetRole& otherB = assocwidget->m_role[RoleType::B];
- const UMLWidget *a = otherA.umlWidget;
- const UMLWidget *b = otherB.umlWidget;
- /*
- //don't count associations to self if both of their end points are on the same region
- //they are different and placement won't interfere with them
- if (a == b && otherA.m_WidgetRegion == otherB.m_WidgetRegion)
- continue;
- */
- if (m_role[role].umlWidget == a && region == otherA.m_WidgetRegion)
- widgetCount++;
- else if (m_role[role].umlWidget == b && region == otherB.m_WidgetRegion)
- widgetCount++;
- }//end foreach
- return widgetCount;
-}
-
-/**
- * Find the border point of the given rect when a line is drawn from the
- * given point to the rect.
- * @param rect rect of a classifier
- * @param line a line to the rect
- * @param intersectionPoint the intercept point on the border of the rect
- * @return the type of the intersection @ref QLineF::IntersectType
- */
-QLineF::IntersectType AssociationWidget::intersect(const QRectF &rect, const QLineF &line,
- QPointF* intersectionPoint)
-{
- QList<QLineF> lines;
- lines << QLineF(rect.topLeft(), rect.topRight());
- lines << QLineF(rect.topRight(), rect.bottomRight());
- lines << QLineF(rect.bottomRight(), rect.bottomLeft());
- lines << QLineF(rect.bottomLeft(), rect.topLeft());
- foreach (const QLineF& rectLine, lines) {
- QLineF::IntersectType type = rectLine.intersect(line, intersectionPoint);
- if (type == QLineF::BoundedIntersection) {
- return type;
- }
- }
- return QLineF::NoIntersection;
-}
-
-/**
- * Given a rectangle and a point, findInterceptOnEdge computes the
- * connecting line between the middle point of the rectangle and
- * the point, and returns the intercept of this line with the
- * the edge of the rectangle identified by `region'.
- * When the region is North or South, the X value is returned (Y is
- * constant.)
- * When the region is East or West, the Y value is returned (X is
- * constant.)
- * @todo This is buggy. Try replacing by intersect()
- */
-qreal AssociationWidget::findInterceptOnEdge(const QRectF &rect,
- Uml::Region::Enum region,
- const QPointF &point)
-{
- // The Qt coordinate system has (0, 0) in the top left corner.
- // In order to go to the regular XY coordinate system with (0, 0)
- // in the bottom left corner, we swap the X and Y axis.
- // That's why the following assignments look twisted.
- const qreal rectHalfWidth = rect.height() / 2.0;
- const qreal rectHalfHeight = rect.width() / 2.0;
- const qreal rectMidX = rect.y() + rectHalfWidth;
- const qreal rectMidY = rect.x() + rectHalfHeight;
- const qreal dX = rectMidX - point.y();
- const qreal dY = rectMidY - point.x();
- switch (region) {
- case Uml::Region::West:
- region = Uml::Region::South;
- break;
- case Uml::Region::North:
- region = Uml::Region::West;
- break;
- case Uml::Region::East:
- region = Uml::Region::North;
- break;
- case Uml::Region::South:
- region = Uml::Region::East;
- break;
- default:
- break;
- }
- // Now we have regular coordinates with the point (0, 0) in the
- // bottom left corner.
- if (region == Uml::Region::North || region == Uml::Region::South) {
- if (dX == 0)
- return rectMidY;
- // should be rectMidX, but we go back to Qt coord.sys.
- if (dY == 0) {
- uError() << "usage error: " << "North/South (dY == 0)";
- return -1.0;
- }
- const qreal m = dY / dX;
- qreal relativeX;
- if (region == Uml::Region::North)
- relativeX = rectHalfHeight / m;
- else
- relativeX = -rectHalfHeight / m;
- return (rectMidY + relativeX);
- // should be rectMidX, but we go back to Qt coord.sys.
- } else {
- if (dY == 0)
- return rectMidX;
- // should be rectMidY, but we go back to Qt coord.sys.
- if (dX == 0) {
- uError() << "usage error: " << "East/West (dX == 0)";
- return -1.0;
- }
- const qreal m = dY / dX;
- qreal relativeY = m * rectHalfWidth;
- if (region == Uml::Region::West)
- relativeY = -relativeY;
- return (rectMidX + relativeY);
- // should be rectMidY, but we go back to Qt coord.sys.
- }
-}
-
-/**
- * Auxiliary method for updateAssociations():
- * Put position into m_positions and assoc into m_ordered at the
- * correct index.
- * m_positions and m_ordered move in parallel and are sorted by
- * ascending position.
- */
-void AssociationWidget::insertIntoLists(qreal position, const AssociationWidget* assoc)
-{
- bool did_insertion = false;
- for (int index = 0; index < m_positions_len; ++index) {
- if (position < m_positions[index]) {
- for (int moveback = m_positions_len; moveback > index; moveback--)
- m_positions[moveback] = m_positions[moveback - 1];
- m_positions[index] = position;
- m_ordered.insert(index, const_cast<AssociationWidget*>(assoc));
- did_insertion = true;
- break;
- }
- }
- if (! did_insertion) {
- m_positions[m_positions_len] = position;
- m_ordered.append(const_cast<AssociationWidget*>(assoc));
- }
- m_positions_len++;
-}
-
-/**
- * Tells all the other view associations the new count for the
- * given widget on a certain region. And also what index they should be.
- */
-void AssociationWidget::updateAssociations(int totalCount,
- Uml::Region::Enum region,
- Uml::RoleType::Enum role)
-{
- if ((region == Uml::Region::Error) | (umlScene() == NULL)) {
- return;
- }
- AssociationWidgetList list = m_scene->associationList();
-
- UMLWidget *ownWidget = m_role[role].umlWidget;
- m_positions_len = 0;
- m_ordered.clear();
- // we order the AssociationWidget list by region and x/y value
- foreach (AssociationWidget* assocwidget, list) {
- WidgetRole *roleA = &assocwidget->m_role[RoleType::A];
- WidgetRole *roleB = &assocwidget->m_role[RoleType::B];
- UMLWidget *wA = roleA->umlWidget;
- UMLWidget *wB = roleB->umlWidget;
- // Skip self associations.
- if (wA == wB)
- continue;
- // Now we must find out with which end the assocwidget connects
- // to the input widget (ownWidget).
- bool inWidgetARegion = (ownWidget == wA &&
- region == roleA->m_WidgetRegion);
- bool inWidgetBRegion = (ownWidget == wB &&
- region == roleB->m_WidgetRegion);
- if (!inWidgetARegion && !inWidgetBRegion)
- continue;
- // Determine intercept position on the edge indicated by `region'.
- UMLWidget * otherWidget = (inWidgetARegion ? wB : wA);
- AssociationLine *linepath = assocwidget->associationLine();
- QPointF refpoint;
- if (assocwidget->linePathStartsAt(otherWidget))
- refpoint = linepath->point(linepath->count() - 2);
- else
- refpoint = linepath->point(1);
- // The point is authoritative if we're called for the second time
- // (i.e. role==B) or it is a waypoint on the line path.
- bool pointIsAuthoritative = (role == RoleType::B || linepath->count() > 2);
- if (! pointIsAuthoritative) {
- // If the point is not authoritative then we use the other
- // widget's center.
- refpoint.setX(otherWidget->x() + otherWidget->width() / 2);
- refpoint.setY(otherWidget->y() + otherWidget->height() / 2);
- }
- qreal intercept = findInterceptOnEdge(ownWidget->rect(), region, refpoint);
- if (intercept < 0) {
- DEBUG(DBG_SRC) << "error from findInterceptOnEdge for"
- << " assocType=" << assocwidget->associationType()
- << " ownWidget=" << ownWidget->name()
- << " otherWidget=" << otherWidget->name();
- continue;
- }
- insertIntoLists(intercept, assocwidget);
- } // while ((assocwidget = assoc_it.current()))
-
- // we now have an ordered list and we only have to call updateRegionLineCount
- int index = 1;
- foreach (AssociationWidget* assocwidget, m_ordered ) {
- if (ownWidget == assocwidget->widgetForRole(RoleType::A)) {
- assocwidget->updateRegionLineCount(index++, totalCount, region, RoleType::A);
- } else if (ownWidget == assocwidget->widgetForRole(RoleType::B)) {
- assocwidget->updateRegionLineCount(index++, totalCount, region, RoleType::B);
- }
- } // for (assocwidget = ordered.first(); ...)
-}
-
-/**
- * Called to tell the association that another association has added
- * a line to the region of one of its widgets. The widget is identified
- * by its role (A or B).
- *
- * Called by @ref updateAssociations which is called by
- * @ref calculateEndingPoints when required.
- */
-void AssociationWidget::updateRegionLineCount(int index, int totalCount,
- Uml::Region::Enum region,
- Uml::RoleType::Enum role)
-{
- if ((region == Uml::Region::Error) | (umlScene() == NULL)) {
- return;
- }
- // If the association is to self and the line ends are on the same region then
- // use a different calculation.
- if (isSelf() &&
- m_role[RoleType::A].m_WidgetRegion == m_role[RoleType::B].m_WidgetRegion) {
- UMLWidget * pWidget = m_role[RoleType::A].umlWidget;
- qreal x = pWidget->x();
- qreal y = pWidget->y();
- qreal wh = pWidget->height();
- qreal ww = pWidget->width();
- int size = m_associationLine->count();
- // See if above widget ok to place assoc.
- switch( m_role[RoleType::A].m_WidgetRegion ) {
- case Uml::Region::North:
- m_associationLine->setPoint( 0, QPointF( x + ( ww / 4 ), y ) );
- m_associationLine->setPoint( size - 1, QPointF(x + ( ww * 3 / 4 ), y ) );
- break;
-
- case Uml::Region::South:
- m_associationLine->setPoint( 0, QPointF( x + ( ww / 4 ), y + wh ) );
- m_associationLine->setPoint( size - 1, QPointF( x + ( ww * 3 / 4 ), y + wh ) );
- break;
-
- case Uml::Region::East:
- m_associationLine->setPoint( 0, QPointF( x + ww, y + ( wh / 4 ) ) );
- m_associationLine->setPoint( size - 1, QPointF( x + ww, y + ( wh * 3 / 4 ) ) );
- break;
-
- case Uml::Region::West:
- m_associationLine->setPoint( 0, QPointF( x, y + ( wh / 4 ) ) );
- m_associationLine->setPoint( size - 1, QPointF( x, y + ( wh * 3 / 4 ) ) );
- break;
- default:
- break;
- }//end switch
-
- return;
- }
-
- WidgetRole& robj = m_role[role];
- UMLWidget * pWidget = robj.umlWidget;
-
- robj.m_nIndex = index;
- robj.m_nTotalCount = totalCount;
- qreal x = pWidget->x();
- qreal y = pWidget->y();
- qreal ww = pWidget->width();
- qreal wh = pWidget->height();
- const bool angular = Settings::optionState().generalState.angularlines;
- qreal ch = 0;
- qreal cw = 0;
- if (angular) {
- uint nind = (role == RoleType::A ? 1 : m_associationLine->count() - 2);
- QPointF neighbour = m_associationLine->point(nind);
- if (neighbour.x() < x)
- cw = 0;
- else if (neighbour.x() > x + ww)
- cw = 0 + ww;
- else
- cw = neighbour.x() - x;
- if (neighbour.y() < y)
- ch = 0;
- else if (neighbour.y() > y + wh)
- ch = 0 + wh;
- else
- ch = neighbour.y() - y;
- } else {
- ch = wh * index / totalCount;
- cw = ww * index / totalCount;
- }
-
- qreal newX = x + cw;
- qreal newY = y + ch;
-
- QPointF pt;
- if (angular) {
- pt = QPointF(newX, newY);
- } else {
- UMLWidget *pWidgetA = m_role[RoleType::A].umlWidget;
- UMLWidget *pWidgetB = m_role[RoleType::B].umlWidget;
- QList<QPolygonF> polyListA = pWidgetA->shape().toSubpathPolygons();
- QPolygonF polyA = polyListA.at(0);
- if (polyListA.size() > 1) {
- for (int i = 1; i < polyListA.size(); i++) {
- polyA = polyA.united(polyListA.at(i));
- }
- }
- polyA = polyA.translated(pWidgetA->pos());
- QList<QPolygonF> polyListB = pWidgetB->shape().toSubpathPolygons();
- QPolygonF polyB = polyListB.at(0);
- if (polyListB.size() > 1) {
- for (int i = 1; i < polyListB.size(); i++) {
- polyB = polyB.united(polyListB.at(i));
- }
- }
- polyB = polyB.translated(pWidgetB->pos());
- QLineF nearestPoints = Widget_Utils::closestPoints(polyA, polyB);
- if (nearestPoints.isNull()) {
- uError() << "Widget_Utils::closestPoints failed, falling back to simple widget positions";
- switch(region) {
- case Uml::Region::West:
- pt.setX(x);
- pt.setY(newY);
- break;
- case Uml::Region::North:
- pt.setX(newX);
- pt.setY(y);
- break;
- case Uml::Region::East:
- pt.setX(x + ww);
- pt.setY(newY);
- break;
- case Uml::Region::South:
- pt.setX(newX);
- pt.setY(y + wh);
- break;
- case Uml::Region::Center:
- pt.setX(x + ww / 2);
- pt.setY(y + wh / 2);
- break;
- default:
- break;
- }
- } else {
- if (role == RoleType::A)
- pt = nearestPoints.p1();
- else
- pt = nearestPoints.p2();
- }
- }
- if (role == RoleType::A) {
- m_associationLine->setPoint(0, pt);
- }
- else {
- m_associationLine->setPoint(m_associationLine->count() - 1, pt);
- }
-}
-
-/**
- * Sets the state of whether the widget is selected.
- *
- * @param _select The state of whether the widget is selected.
- */
-void AssociationWidget::setSelected(bool _select /* = true */)
-{
- WidgetBase::setSelected(_select);
- if ( m_nameWidget)
- m_nameWidget->setSelected( _select );
- if ( m_role[RoleType::A].roleWidget )
- m_role[RoleType::A].roleWidget->setSelected( _select );
- if ( m_role[RoleType::B].roleWidget )
- m_role[RoleType::B].roleWidget->setSelected( _select );
- if ( m_role[RoleType::A].multiplicityWidget )
- m_role[RoleType::A].multiplicityWidget->setSelected( _select );
- if ( m_role[RoleType::B].multiplicityWidget )
- m_role[RoleType::B].multiplicityWidget->setSelected( _select );
- if ( m_role[RoleType::A].changeabilityWidget)
- m_role[RoleType::A].changeabilityWidget->setSelected( _select );
- if ( m_role[RoleType::B].changeabilityWidget)
- m_role[RoleType::B].changeabilityWidget->setSelected( _select );
-
- // Update the docwindow for this association.
- // This is done last because each of the above setSelected calls
- // overwrites the docwindow, but we want the main association doc
- // to win.
- if (_select) {
- if (m_scene->selectedCount() == 0)
- UMLApp::app()->docWindow()->showDocumentation(this, false);
- } else
- UMLApp::app()->docWindow()->updateDocumentation(true);
-
- m_associationLine->setSelected(_select);
- if (! _select) {
- // For now, if _select is true we don't make the assoc class line
- // selected. But that's certainly open for discussion.
- // At any rate, we need to deselect the assoc class line
- // if _select is false.
- selectAssocClassLine(false);
- }
- UMLApp::app()->document()->writeToStatusBar(_select ? i18n("Press Ctrl with left mouse click to delete a point") : QString());
-}
-
-/**
- * Reimplement method from WidgetBase in order to check owned floating texts.
- *
- * @param p Point to be checked.
- *
- * @return m_nameWidget if m_nameWidget is non NULL and m_nameWidget->onWidget(p) returns non NULL;
- * m_role[0].(multiplicity|changeability|role)Widget if the resp. widget is non NULL and
- * its onWidget(p) returns non NULL;
- * m_role[1].(multiplicity|changeability|role)Widget if the resp. widget is non NULL and
- * its onWidget(p) returns non NULL;
- * else NULL.
- */
-UMLWidget* AssociationWidget::onWidget(const QPointF &p)
-{
- if (m_nameWidget && m_nameWidget->onWidget(p)) {
- return m_nameWidget;
- }
- for (int i = 0; i <= 1; i++) {
- const WidgetRole& r = m_role[i];
- if (r.multiplicityWidget && r.multiplicityWidget->onWidget(p))
- return r.multiplicityWidget;
- if (r.changeabilityWidget && r.changeabilityWidget->onWidget(p))
- return r.changeabilityWidget;
- if (r.roleWidget && r.roleWidget->onWidget(p))
- return r.roleWidget;
- }
- return NULL;
-}
-
-/**
- * Returns true if the given point is on the connecting line to
- * the association class. Returns false if there is no association
- * class attached, or if the given point is not on the connecting
- * line.
- */
-bool AssociationWidget::onAssocClassLine(const QPointF &point)
-{
- bool onLine = false;
- if (m_pAssocClassLine) {
-//:TODO:
-// const QPointF mapped = m_pAssocClassLine->mapFromParent(point);
-// bool onLine = m_pAssocClassLine->contains(mapped);
-// return onLine;
- UMLSceneItemList list = m_scene->collisions(point);
- UMLSceneItemList::iterator end(list.end());
- for (UMLSceneItemList::iterator item_it(list.begin()); item_it != end; ++item_it) {
- if (*item_it == m_pAssocClassLine) {
- onLine = true;
- break;
- }
- }
- }
- DEBUG(DBG_SRC) << onLine;
- return onLine;
-}
-
-/**
- * Returns true if the given point is on the association line.
- * A circle (rectangle) around the point is used to obtain more tolerance.
- * @param point the point to check
- * @return flag whether point is on association line
- */
-bool AssociationWidget::onAssociation(const QPointF& point)
-{
- // check the path
- const qreal diameter(4.0);
- QPainterPath path = m_associationLine->shape();
- if (path.contains(point)) {
- DEBUG(DBG_SRC) << "on path";
- return true;
- }
- // check also the points
- if (m_associationLine->layout() == AssociationLine::Spline) {
- if (m_associationLine->closestPointIndex(point, diameter) > -1) {
- DEBUG(DBG_SRC) << "on spline point";
- return true;
- }
- }
- return onAssocClassLine(point);
-}
-
-/**
- * Set all association points to x coordinate.
- */
-void AssociationWidget::setXEntireAssoc(qreal x)
-{
- for (int i = 0; i < m_associationLine->count(); ++i) {
- QPointF p = m_associationLine->point(i);
- p.setX(x);
- m_associationLine->setPoint(i, p);
- }
-}
-
-/**
- * Set all association points to y coordinate.
- */
-void AssociationWidget::setYEntireAssoc(qreal y)
-{
- for (int i = 0; i < m_associationLine->count(); ++i) {
- QPointF p = m_associationLine->point(i);
- p.setY(y);
- m_associationLine->setPoint(i, p);
- }
-}
-
-/**
- * Moves all the mid points (all expcept start /end) by the given amount.
- */
-void AssociationWidget::moveMidPointsBy(qreal x, qreal y)
-{
- int pos = m_associationLine->count() - 1;
- for (int i = 1; i < (int)pos; ++i) {
- QPointF p = m_associationLine->point( i );
- qreal newX = p.x() + x;
- qreal newY = p.y() + y;
- p.setX( newX );
- p.setY( newY );
- m_associationLine->setPoint( i, p );
- }
-}
-
-/**
- * Moves the entire association by the given offset.
- */
-void AssociationWidget::moveEntireAssoc(qreal x, qreal y)
-{
- //TODO: ADD SUPPORT FOR ASSOC. ON SEQ. DIAGRAMS WHEN NOTES BACK IN.
- moveMidPointsBy(x, y);
- calculateEndingPoints();
- calculateNameTextSegment();
- resetTextPositions();
-}
-
-/**
- * Returns the bounding rectangle of all segments of the association.
- */
-QRectF AssociationWidget::boundingRect() const
-{
- return m_associationLine->boundingRect();
-}
-
-/**
- * Returns the shape of all segments of the association.
- */
-QPainterPath AssociationWidget::shape() const
-{
- return m_associationLine->shape();
-}
-
-/**
- * Connected to UMLClassifier::attributeRemoved() or UMLEntity::constraintRemoved()
- * in case this AssociationWidget is linked to a clasifier list item
- * (an attribute or a foreign key constraint)
- *
- * @param obj The UMLClassifierListItem removed.
- */
-void AssociationWidget::slotClassifierListItemRemoved(UMLClassifierListItem* obj)
-{
- if (obj != m_umlObject) {
- DEBUG(DBG_SRC) << "obj=" << obj << ": m_umlObject=" << m_umlObject;
- return;
- }
- m_umlObject = 0;
- m_scene->removeAssoc(this);
-}
-
-/**
- * Connected to UMLObject::modified() in case this
- * AssociationWidget is linked to a classifer's attribute type.
- */
-void AssociationWidget::slotAttributeChanged()
-{
- UMLAttribute *attr = attribute();
- if (attr == NULL) {
- uError() << "attribute() returns NULL";
- return;
- }
- setVisibility(attr->visibility(), RoleType::B);
- setRoleName(attr->name(), RoleType::B);
-}
-
-void AssociationWidget::clipSize()
-{
- if (m_nameWidget)
- m_nameWidget->clipSize();
-
- if (m_role[RoleType::A].multiplicityWidget)
- m_role[RoleType::A].multiplicityWidget->clipSize();
-
- if (m_role[RoleType::B].multiplicityWidget)
- m_role[RoleType::B].multiplicityWidget->clipSize();
-
- if (m_role[RoleType::A].roleWidget)
- m_role[RoleType::A].roleWidget->clipSize();
-
- if (m_role[RoleType::B].roleWidget)
- m_role[RoleType::B].roleWidget->clipSize();
-
- if (m_role[RoleType::A].changeabilityWidget)
- m_role[RoleType::A].changeabilityWidget->clipSize();
-
- if (m_role[RoleType::B].changeabilityWidget)
- m_role[RoleType::B].changeabilityWidget->clipSize();
-
- if (m_associationClass)
- m_associationClass->clipSize();
-}
-
-/**
- * Event handler for context menu events, called from the line segments.
- */
-void AssociationWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
-{
- const Uml::AssociationType::Enum type = associationType();
- ListPopupMenu::MenuType menuType = ListPopupMenu::mt_Association_Selected;
- if ((type == Uml::AssociationType::Anchor) ||
- onAssocClassLine(event->scenePos())) {
- menuType = ListPopupMenu::mt_Anchor;
- } else if (isCollaboration()) {
- menuType = ListPopupMenu::mt_Collaboration_Message;
- } else if (!association()) {
- menuType = ListPopupMenu::mt_AttributeAssociation;
- } else if (AssocRules::allowRole(type)) {
- menuType = ListPopupMenu::mt_FullAssociation;
- }
-
- event->accept();
- DEBUG(DBG_SRC) << "menue type = " << ListPopupMenu::toString(menuType)
- << " / association = " << Uml::AssociationType::toString(type);
-
- UMLScene *scene = umlScene();
- QWidget *parent = 0;
- if (scene) {
- parent = scene->activeView();
- }
-
- if (!isSelected() && scene && !scene->selectedItems().isEmpty()) {
- Qt::KeyboardModifiers forSelection = (Qt::ControlModifier | Qt::ShiftModifier);
- if ((event->modifiers() & forSelection) == 0) {
- scene->clearSelection();
- }
- }
- setSelected(true);
- m_eventScenePos = event->scenePos();
- ListPopupMenu popup(parent, menuType, this);
- QAction *triggered = popup.exec(event->screenPos());
- ListPopupMenu *parentMenu = ListPopupMenu::menuFromAction(triggered);
-
- if (!parentMenu) {
- uWarning() << "Action's data field does not contain ListPopupMenu pointer";
- return;
- }
-
- WidgetBase *ownerWidget = parentMenu->ownerWidget();
- // assert because logic is based on only WidgetBase being the owner of
- // ListPopupMenu actions executed in this context menu.
- Q_ASSERT_X(ownerWidget != 0, "AssociationWidget::contextMenuEvent",
- "ownerWidget is null which means action belonging to UMLView, UMLScene"
- " or UMLObject is the one triggered in ListPopupMenu");
-
- ownerWidget->slotMenuSelection(triggered);
-}
-
-/**
- * Reimplemented event handler for hover enter events.
- */
-void AssociationWidget::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
-{
- associationLine()->hoverEnterEvent(event);
-}
-
-/**
- * Reimplemented event handler for hover leave events.
- */
-void AssociationWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
-{
- associationLine()->hoverLeaveEvent(event);
-}
-
-/**
- * Reimplemented event handler for hover move events.
- */
-void AssociationWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
-{
- associationLine()->hoverMoveEvent(event);
-}
-
-/**
- * Saves this widget to the "assocwidget" XMI element.
- */
-void AssociationWidget::saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
-{
- QDomElement assocElement = qDoc.createElement(QLatin1String("assocwidget"));
-
- WidgetBase::saveToXMI(qDoc, assocElement);
- LinkWidget::saveToXMI(qDoc, assocElement);
- if (m_umlObject) {
- assocElement.setAttribute(QLatin1String("xmi.id"), Uml::ID::toString(m_umlObject->id()));
- }
- assocElement.setAttribute(QLatin1String("type"), associationType());
- if (!association()) {
- assocElement.setAttribute(QLatin1String("visibilityA"), visibility(RoleType::A));
- assocElement.setAttribute(QLatin1String("visibilityB"), visibility(RoleType::B));
- assocElement.setAttribute(QLatin1String("changeabilityA"), changeability(RoleType::A));
- assocElement.setAttribute(QLatin1String("changeabilityB"), changeability(RoleType::B));
- if (m_umlObject == NULL) {
- assocElement.setAttribute(QLatin1String("roleAdoc"), roleDocumentation(RoleType::A));
- assocElement.setAttribute(QLatin1String("roleBdoc"), roleDocumentation(RoleType::B));
- assocElement.setAttribute(QLatin1String("documentation"), documentation());
- }
- }
- assocElement.setAttribute(QLatin1String("widgetaid"), Uml::ID::toString(widgetIDForRole(RoleType::A)));
- assocElement.setAttribute(QLatin1String("widgetbid"), Uml::ID::toString(widgetIDForRole(RoleType::B)));
- assocElement.setAttribute(QLatin1String("indexa"), m_role[RoleType::A].m_nIndex);
- assocElement.setAttribute(QLatin1String("indexb"), m_role[RoleType::B].m_nIndex);
- assocElement.setAttribute(QLatin1String("totalcounta"), m_role[RoleType::A].m_nTotalCount);
- assocElement.setAttribute(QLatin1String("totalcountb"), m_role[RoleType::B].m_nTotalCount);
- m_associationLine->saveToXMI(qDoc, assocElement);
-
- if (m_nameWidget) {
- m_nameWidget->saveToXMI(qDoc, assocElement);
- }
-
- if (multiplicityWidget(RoleType::A)) {
- multiplicityWidget(RoleType::A)->saveToXMI(qDoc, assocElement);
- }
-
- if (multiplicityWidget(RoleType::B)) {
- multiplicityWidget(RoleType::B)->saveToXMI(qDoc, assocElement);
- }
-
- if (roleWidget(RoleType::A)) {
- roleWidget(RoleType::A)->saveToXMI(qDoc, assocElement);
- }
-
- if (roleWidget(RoleType::B)) {
- roleWidget(RoleType::B)->saveToXMI(qDoc, assocElement);
- }
-
- if (changeabilityWidget(RoleType::A)) {
- changeabilityWidget(RoleType::A)->saveToXMI(qDoc, assocElement);
- }
-
- if (changeabilityWidget(RoleType::B)) {
- changeabilityWidget(RoleType::B)->saveToXMI(qDoc, assocElement);
- }
-
- if (m_associationClass) {
- QString acid = Uml::ID::toString(m_associationClass->id());
- assocElement.setAttribute(QLatin1String("assocclass"), acid);
- assocElement.setAttribute(QLatin1String("aclsegindex"), m_nLinePathSegmentIndex);
- }
-
- qElement.appendChild(assocElement);
-}
-
-/**
- * Uses the supplied widgetList for resolving
- * the role A and role B widgets. (The other loadFromXMI() queries
- * the UMLView for these widgets.)
- * Required for clipboard operations.
- */
-bool AssociationWidget::loadFromXMI(QDomElement& qElement,
- const UMLWidgetList& widgets,
- const MessageWidgetList* messages)
-{
- if (!WidgetBase::loadFromXMI(qElement)) {
- return false;
- }
-
- if (!LinkWidget::loadFromXMI(qElement)) {
- return false;
- }
-
- // load child widgets first
- QString widgetaid = qElement.attribute(QLatin1String("widgetaid"), QLatin1String("-1"));
- QString widgetbid = qElement.attribute(QLatin1String("widgetbid"), QLatin1String("-1"));
- Uml::ID::Type aId = Uml::ID::fromString(widgetaid);
- Uml::ID::Type bId = Uml::ID::fromString(widgetbid);
- UMLWidget *pWidgetA = Widget_Utils::findWidget(aId, widgets, messages);
- if (!pWidgetA) {
- uError() << "cannot find widget for roleA id " << Uml::ID::toString(aId);
- return false;
- }
- UMLWidget *pWidgetB = Widget_Utils::findWidget(bId, widgets, messages);
- if (!pWidgetB) {
- uError() << "cannot find widget for roleB id " << Uml::ID::toString(bId);
- return false;
- }
- setWidgetForRole(pWidgetA, RoleType::A);
- setWidgetForRole(pWidgetB, RoleType::B);
-
- QString type = qElement.attribute(QLatin1String("type"), QLatin1String("-1"));
- Uml::AssociationType::Enum aType = Uml::AssociationType::fromInt(type.toInt());
-
- QString id = qElement.attribute(QLatin1String("xmi.id"), QLatin1String("-1"));
- bool oldStyleLoad = false;
- if (id == QLatin1String("-1")) {
- // xmi.id not present, ergo either a pure widget association,
- // or old (pre-1.2) style:
- // Everything is loaded from the AssociationWidget.
- // UMLAssociation may or may not be saved - if it is, it's a dummy.
- // Create the UMLAssociation if both roles are UML objects;
- // else load the info locally.
-
- if (Uml::AssociationType::hasUMLRepresentation(aType)) {
- // lack of an association in our widget AND presence of
- // both uml objects for each role clearly identifies this
- // as reading in an old-school file. Note it as such, and
- // create, and add, the UMLAssociation for this widget.
- // Remove this special code when backwards compatibility
- // with older files isn't important anymore. -b.t.
- UMLObject* umlRoleA = pWidgetA->umlObject();
- UMLObject* umlRoleB = pWidgetB->umlObject();
- if (!m_umlObject && umlRoleA && umlRoleB) {
- oldStyleLoad = true; // flag for further special config below
- if (aType == AssociationType::Aggregation || aType == AssociationType::Composition) {
- uWarning()<<" Old Style save file? swapping roles on association widget"<<this;
- // We have to swap the A and B widgets to compensate
- // for the long standing bug in AssociationLine of drawing
- // the diamond at the wrong end which was fixed
- // just before the 1.2 release.
- // The logic here is that the user has understood
- // that the diamond belongs at the SOURCE end of the
- // the association (i.e. at the container, not at the
- // contained), and has compensated for this anomaly
- // by drawing the aggregations/compositions from
- // target to source.
- UMLWidget *tmpWidget = pWidgetA;
- pWidgetA = pWidgetB;
- pWidgetB = tmpWidget;
- setWidgetForRole(pWidgetA, RoleType::A);
- setWidgetForRole(pWidgetB, RoleType::B);
- umlRoleA = pWidgetA->umlObject();
- umlRoleB = pWidgetB->umlObject();
- }
-
- setUMLAssociation(umlDoc()->createUMLAssociation(umlRoleA, umlRoleB, aType));
- }
- }
-
- setDocumentation(qElement.attribute(QLatin1String("documentation")));
- setRoleDocumentation(qElement.attribute(QLatin1String("roleAdoc")), RoleType::A);
- setRoleDocumentation(qElement.attribute(QLatin1String("roleBdoc")), RoleType::B);
-
- // visibility defaults to Public if it cant set it here..
- QString visibilityA = qElement.attribute(QLatin1String("visibilityA"), QLatin1String("0"));
- int vis = visibilityA.toInt();
- if (vis >= 200) { // bkwd compat.
- vis -= 200;
- }
- setVisibility((Uml::Visibility::Enum)vis, RoleType::A);
-
- QString visibilityB = qElement.attribute(QLatin1String("visibilityB"), QLatin1String("0"));
- vis = visibilityB.toInt();
- if (vis >= 200) { // bkwd compat.
- vis -= 200;
- }
- setVisibility((Uml::Visibility::Enum)vis, RoleType::B);
-
- // Changeability defaults to "Changeable" if it cant set it here..
- QString changeabilityA = qElement.attribute(QLatin1String("changeabilityA"), QLatin1String("0"));
- if (changeabilityA.toInt() > 0)
- setChangeability(Uml::Changeability::fromInt(changeabilityA.toInt()), RoleType::A);
-
- QString changeabilityB = qElement.attribute(QLatin1String("changeabilityB"), QLatin1String("0"));
- if (changeabilityB.toInt() > 0)
- setChangeability(Uml::Changeability::fromInt(changeabilityB.toInt()), RoleType::B);
-
- } else {
-
- // we should disconnect any prior association (can this happen??)
- if (m_umlObject && m_umlObject->baseType() == UMLObject::ot_Association) {
- UMLAssociation *umla = association();
- umla->disconnect(this);
- umla->nrof_parent_widgets--;
- }
-
- // New style: The xmi.id is a reference to the UMLAssociation.
- // If the UMLObject is not found right now, we try again later
- // during the type resolution pass - see activate().
- m_nId = Uml::ID::fromString(id);
- UMLObject *myObj = umlDoc()->findObjectById(m_nId);
- if (myObj) {
- const UMLObject::ObjectType ot = myObj->baseType();
- if (ot != UMLObject::ot_Association) {
- setUMLObject(myObj);
- } else {
- UMLAssociation * myAssoc = static_cast<UMLAssociation*>(myObj);
- setUMLAssociation(myAssoc);
- if (type == QLatin1String("-1"))
- aType = myAssoc->getAssocType();
- }
- }
- }
-
- setAssociationType(aType);
-
- QString indexa = qElement.attribute(QLatin1String("indexa"), QLatin1String("0"));
- QString indexb = qElement.attribute(QLatin1String("indexb"), QLatin1String("0"));
- QString totalcounta = qElement.attribute(QLatin1String("totalcounta"), QLatin1String("0"));
- QString totalcountb = qElement.attribute(QLatin1String("totalcountb"), QLatin1String("0"));
- m_role[RoleType::A].m_nIndex = indexa.toInt();
- m_role[RoleType::B].m_nIndex = indexb.toInt();
- m_role[RoleType::A].m_nTotalCount = totalcounta.toInt();
- m_role[RoleType::B].m_nTotalCount = totalcountb.toInt();
-
- QString assocclassid = qElement.attribute(QLatin1String("assocclass"));
- if (! assocclassid.isEmpty()) {
- Uml::ID::Type acid = Uml::ID::fromString(assocclassid);
- UMLWidget *w = Widget_Utils::findWidget(acid, widgets);
- if (w) {
- ClassifierWidget* aclWidget = static_cast<ClassifierWidget*>(w);
- QString aclSegIndex = qElement.attribute(QLatin1String("aclsegindex"), QLatin1String("0"));
- createAssocClassLine(aclWidget, aclSegIndex.toInt());
- } else {
- uError() << "cannot find assocclass " << assocclassid;
- }
- }
-
- //now load child elements
- QDomNode node = qElement.firstChild();
- QDomElement element = node.toElement();
- while (!element.isNull()) {
- QString tag = element.tagName();
- if (tag == QLatin1String("linepath")) {
- if (!m_associationLine->loadFromXMI(element)) {
- return false;
- }
- } else if (tag == QLatin1String("floatingtext") ||
- tag == QLatin1String("UML:FloatingTextWidget")) { // for bkwd compatibility
- QString r = element.attribute(QLatin1String("role"), QLatin1String("-1"));
- if (r == QLatin1String("-1"))
- return false;
- Uml::TextRole::Enum role = Uml::TextRole::fromInt(r.toInt());
- FloatingTextWidget *ft = new FloatingTextWidget(m_scene, role, QString(), Uml::ID::Reserved);
- if (! ft->loadFromXMI(element)) {
- // Most likely cause: The FloatingTextWidget is empty.
- delete ft;
- node = element.nextSibling();
- element = node.toElement();
- continue;
- }
- // always need this
- ft->setParentItem(this);
- ft->setLink(this);
- ft->setSequenceNumber(m_SequenceNumber);
- ft->setFontCmd(ft->font());
-
- switch(role) {
- case Uml::TextRole::MultiA:
- m_role[RoleType::A].multiplicityWidget = ft;
- if (oldStyleLoad)
- setMultiplicity(m_role[RoleType::A].multiplicityWidget->text(), RoleType::A);
- break;
-
- case Uml::TextRole::MultiB:
- m_role[RoleType::B].multiplicityWidget = ft;
- if (oldStyleLoad)
- setMultiplicity(m_role[RoleType::B].multiplicityWidget->text(), RoleType::B);
- break;
-
- case Uml::TextRole::ChangeA:
- m_role[RoleType::A].changeabilityWidget = ft;
- break;
-
- case Uml::TextRole::ChangeB:
- m_role[RoleType::B].changeabilityWidget = ft;
- break;
-
- case Uml::TextRole::Name:
- m_nameWidget = ft;
- if (oldStyleLoad)
- setName(m_nameWidget->text());
- break;
-
- case Uml::TextRole::Coll_Message:
- case Uml::TextRole::Coll_Message_Self:
- m_nameWidget = ft;
- ft->setLink(this);
- ft->setActivated();
- if (FloatingTextWidget::isTextValid(ft->text()))
- ft->show();
- else
- ft->hide();
- break;
-
- case Uml::TextRole::RoleAName:
- m_role[RoleType::A].roleWidget = ft;
- setRoleName(ft->text(), RoleType::A);
- break;
- case Uml::TextRole::RoleBName:
- m_role[RoleType::B].roleWidget = ft;
- setRoleName(ft->text(), RoleType::B);
- break;
- default:
- DEBUG(DBG_SRC) << "unexpected FloatingTextWidget (TextRole::Enum " << role << ")";
- delete ft;
- break;
- }
- }
- node = element.nextSibling();
- element = node.toElement();
- }
-
- return true;
-}
-
-/**
- * Queries the UMLView for resolving the role A and role B widgets.
- * ....
- */
-bool AssociationWidget::loadFromXMI(QDomElement& qElement)
-{
- UMLScene *scene = umlScene();
- if (scene) {
- const UMLWidgetList& widgetList = scene->widgetList();
- const MessageWidgetList& messageList = scene->messageList();
- return loadFromXMI(qElement, widgetList, &messageList);
- }
- else {
- DEBUG(DBG_SRC) << "This isn't on UMLScene yet, so can neither fetch"
- "messages nor widgets on umlscene";
- return false;
- }
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/associationwidget.h umbrello-kf6-15.08.1/umbrello/widgets/associationwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/associationwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/associationwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,328 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ASSOCIATIONWIDGET_H
-#define ASSOCIATIONWIDGET_H
-
-#include "associationwidgetlist.h"
-#include "linkwidget.h"
-#include "messagewidgetlist.h"
-#include "umlwidgetlist.h"
-#include "widgetbase.h"
-
-class AssociationLine;
-class ClassifierWidget;
-class UMLScene;
-class UMLAssociation;
-class UMLAttribute;
-class UMLClassifierListItem;
-class UMLOperation;
-
-/**
- * This class represents an association inside a diagram.
- *
- * Constructor is made non accessible:
- * Users shall use the static create() methods for constructing AssociationWidgets.
- *
- * Associations exist not only between UML objects. For example, when a Note is
- * attached to a UML object, the Note itself is not a UML object.
- * This class supports both kinds of associations. An association where one or
- * both roles are not a UML object is called a "pure widget association".
- *
- * An AssociationWidget where both roles are UML objects has a corresponding
- * UMLAssociation. The UMLAssociation can be retrieved using the getAssociation
- * method.
- * A pure widget association does not have a corresponding UMLAssociation.
- * The getAssociation method returns NULL in this case.
- *
- * @author Gustavo Madrigal
- * @author Gopala Krishna
- * @short This class represents an association inside a diagram.
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class AssociationWidget : public WidgetBase, public LinkWidget
-{
- Q_OBJECT
-public:
- static AssociationWidget* create(UMLScene *scene);
- static AssociationWidget* create
- (UMLScene *scene, UMLWidget* WidgetA,
- Uml::AssociationType::Enum assocType, UMLWidget* WidgetB,
- UMLObject *umlobject = NULL);
-
- virtual ~AssociationWidget();
-
- virtual void setUMLObject(UMLObject *obj);
-
- //---------- LinkWidget Interface methods implementation from now on.
-
- virtual void lwSetFont(QFont font);
- virtual UMLClassifier *operationOwner();
-
- virtual UMLOperation *operation();
- virtual void setOperation(UMLOperation *op);
-
- virtual QString customOpText();
- virtual void setCustomOpText(const QString &opText);
-
- virtual void resetTextPositions();
-
- virtual void setMessageText(FloatingTextWidget *ft);
- virtual void setText(FloatingTextWidget *ft, const QString &newText);
-
- virtual void showPropertiesDialog();
-
- virtual QString lwOperationText();
- virtual UMLClassifier *lwClassifier();
- virtual void setOperationText(const QString &op);
-
- virtual void constrainTextPos(qreal &textX, qreal &textY,
- qreal textWidth, qreal textHeight,
- Uml::TextRole::Enum tr);
-
- virtual void calculateNameTextSegment();
-
- //---------- End LinkWidget Interface methods implementation.
-
- UMLAssociation* association() const;
- UMLAttribute* attribute() const;
-
-// AssociationWidget& operator=(const AssociationWidget& other);
- bool operator==(const AssociationWidget& other) const;
- bool operator!=(AssociationWidget& other) const;
-
- FloatingTextWidget* textWidgetByRole(Uml::TextRole::Enum tr) const;
-
- FloatingTextWidget* nameWidget() const;
- QString name() const;
- void setName(const QString &strRole);
- void setStereotype(const QString &stereo);
-
- FloatingTextWidget* roleWidget(Uml::RoleType::Enum role) const;
- QString roleName(Uml::RoleType::Enum role) const;
- void setRoleName(const QString &strRole, Uml::RoleType::Enum role);
-
- QString roleDocumentation(Uml::RoleType::Enum role) const;
- void setRoleDocumentation(const QString& doc, Uml::RoleType::Enum role);
-
- FloatingTextWidget* multiplicityWidget(Uml::RoleType::Enum role) const;
- QString multiplicity(Uml::RoleType::Enum role) const;
- void setMultiplicity(const QString& text, Uml::RoleType::Enum role);
-
- Uml::Visibility::Enum visibility(Uml::RoleType::Enum role) const;
- void setVisibility(Uml::Visibility::Enum value, Uml::RoleType::Enum role);
-
- FloatingTextWidget* changeabilityWidget(Uml::RoleType::Enum role) const;
- Uml::Changeability::Enum changeability(Uml::RoleType::Enum role) const;
- void setChangeability(Uml::Changeability::Enum value, Uml::RoleType::Enum role);
-
- Uml::ID::Type widgetIDForRole(Uml::RoleType::Enum role) const;
- Uml::ID::Type widgetLocalIDForRole(Uml::RoleType::Enum role) const;
- UMLWidget* widgetForRole(Uml::RoleType::Enum role) const;
- void setWidgetForRole(UMLWidget* widget, Uml::RoleType::Enum role);
-
- bool setWidgets(UMLWidget* widgetA, Uml::AssociationType::Enum assocType, UMLWidget* widgetB);
-
- bool containsAsEndpoint(UMLWidget* widget);
-
- Uml::AssociationType::Enum associationType() const;
- void setAssociationType(Uml::AssociationType::Enum type);
-
- bool isCollaboration() const;
- bool isSelf() const;
-
- QString toString() const;
-
- bool isActivated() const;
- void setActivated(bool active);
-
- AssociationLine* associationLine() const;
-
- virtual bool activate();
- virtual QRectF boundingRect() const;
- virtual QPainterPath shape() const;
-
- void widgetMoved(UMLWidget* widget, qreal x, qreal y);
-
- void saveIdealTextPositions();
-
- UMLWidget* onWidget(const QPointF &p);
- bool onAssociation(const QPointF& point);
- bool onAssocClassLine(const QPointF& point);
-
- void createAssocClassLine();
- void createAssocClassLine(ClassifierWidget* classifierWidget,
- int linePathSegmentIndex);
-
- void selectAssocClassLine(bool sel = true);
- void removeAssocClassLine();
- void computeAssocClassLine();
-
- void setXEntireAssoc(qreal x);
- void setYEntireAssoc(qreal y);
-
- void moveMidPointsBy(qreal x, qreal y);
- void moveEntireAssoc(qreal x, qreal y);
-
- QFont font() const;
-
- virtual void setTextColor(const QColor &color);
-
- void calculateEndingPoints();
-
- void clipSize();
-
- bool loadFromXMI(QDomElement& qElement, const UMLWidgetList& widgets,
- const MessageWidgetList* messages);
- virtual bool loadFromXMI(QDomElement& qElement);
- virtual void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
-
- void cleanup();
-
- bool isPointAddable();
- bool isPointRemovable();
-
- //:TODO: the following four methods should be protected
- virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
- virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
- virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
- virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
-
- virtual void setSelected(bool _select);
-public Q_SLOTS: //:TODO: all virtual?
- virtual void slotMenuSelection(QAction* action);
- void slotClassifierListItemRemoved(UMLClassifierListItem* obj);
- void slotAttributeChanged();
-
- void syncToModel();
-
-protected:
- virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
-
- virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
- virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
- virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
-
-private:
- QPointF calculateTextPosition(Uml::TextRole::Enum role);
- void setTextPosition(Uml::TextRole::Enum role);
- void setTextPositionRelatively(Uml::TextRole::Enum role, const QPointF &oldPosition);
- void setFloatingText(Uml::TextRole::Enum role, const QString& text, FloatingTextWidget* &ft);
-
- AssociationWidget(UMLScene *scene);
-
- void setUMLAssociation(UMLAssociation * assoc);
-
- void mergeAssociationDataIntoUMLRepresentation();
-
- static Uml::Region::Enum findPointRegion(const QRectF& rect, const QPointF& pos);
- static qreal findInterceptOnEdge(const QRectF &rect, Uml::Region::Enum region, const QPointF &point);
- static QLineF::IntersectType intersect(const QRectF &rect, const QLineF &line,
- QPointF* intersectionPoint);
-
- void moveEvent(QGraphicsSceneMouseEvent *me);
-
- Uml::TextRole::Enum calculateNameType(Uml::TextRole::Enum defaultRoleType);
-
- static QPointF swapXY(const QPointF &p);
-
- // not used at the moment
- // static QPointF calculatePointAtDistance(const QPointF &P1, const QPointF &P2, float Distance);
- // static QPointF calculatePointAtDistanceOnPerpendicular(const QPointF &P1, const QPointF &P2, float Distance);
- // static float perpendicularProjection(const QPointF& P1, const QPointF& P2, const QPointF& P3, QPointF& ResultingPoint);
-
- static QPointF midPoint(const QPointF& p0, const QPointF& p1);
-
- void createPointsSelfAssociation();
- void updatePointsSelfAssociation();
- void createPointsException();
- void updatePointsException();
-
- /**
- * The WidgetRole struct gathers all information pertaining to the role.
- * The AssociationWidget class contains two WidgetRole objects, one for each
- * side of the association (A and B).
- */
- struct WidgetRole {
-
- FloatingTextWidget* multiplicityWidget; ///< information regarding multiplicity
- FloatingTextWidget* changeabilityWidget; ///< information regarding changeability
- FloatingTextWidget* roleWidget; ///< role's label of this association
-
- UMLWidget* umlWidget; ///< UMLWidget at this role's side of this association
-
- Uml::Region::Enum m_WidgetRegion; ///< region of this role's widget
-
- int m_nIndex; ///< the index of where the line is on the region for this role
- int m_nTotalCount; ///< total amount of associations on the region this role's line is on
-
- // The following items are only used if m_pObject is not set.
- Uml::Visibility::Enum visibility;
- Uml::Changeability::Enum changeability;
- QString roleDocumentation;
-
- };
-
- void updateRegionLineCount(int index, int totalCount,
- Uml::Region::Enum region, Uml::RoleType::Enum role);
-
- void updateAssociations(int totalCount, Uml::Region::Enum region, Uml::RoleType::Enum role);
-
- int getRegionCount(Uml::Region::Enum region, Uml::RoleType::Enum role);
-
- void doUpdates(const QPointF &otherP, Uml::RoleType::Enum role);
-
- void setChangeWidget(const QString &strChangeWidget, Uml::RoleType::Enum role);
-
- bool checkAddPoint(const QPointF &scenePos);
- bool checkRemovePoint(const QPointF &scenePos);
-
- bool linePathStartsAt(const UMLWidget* widget);
-
- void insertIntoLists(qreal position, const AssociationWidget* assoc);
-
- qreal m_positions[100]; ///< auxiliary variable for updateAssociations()
- int m_positions_len; ///< auxiliary variable for updateAssociations()
- AssociationWidgetList m_ordered; ///< auxiliary variable for updateAssociations()
-
- bool m_activated; ///< flag which is true if the activate method has been called for this class instance
-
- /**
- * When the association has a Role Floating Text this text should move
- * when the AssociationLine moves but only if the closest segment to the
- * role text moves.
- * This segment is:
- * m_associationLine[m_unNameLineSegment] -- m_associationLine[m_unNameLineSegment+1]
- */
- int m_unNameLineSegment;
-
- QPointF m_oldNamePoint; ///< Position of name floatingtext saved by saveIdealTextPositions()
- QPointF m_oldMultiAPoint; ///< Position of role A multiplicity floatingtext saved by saveIdealTextPositions()
- QPointF m_oldMultiBPoint; ///< Position of role B multiplicity floatingtext saved by saveIdealTextPositions()
- QPointF m_oldChangeAPoint; ///< Position of role A changeability floatingtext saved by saveIdealTextPositions()
- QPointF m_oldChangeBPoint; ///< Position of role B changeability floatingtext saved by saveIdealTextPositions()
- QPointF m_oldRoleAPoint; ///< Position of role A name floatingtext saved by saveIdealTextPositions()
- QPointF m_oldRoleBPoint; ///< Position of role B name floatingtext saved by saveIdealTextPositions()
-
- int m_nLinePathSegmentIndex; ///< anchor for m_pAssocClassLine
- QGraphicsLineItem *m_pAssocClassLine; ///< used for connecting assoc. class
- QGraphicsRectItem *m_pAssocClassLineSel0; ///< selection decoration for the start point of the assoc. class line
- QGraphicsRectItem *m_pAssocClassLineSel1; ///< selection decoration for the end point of the assoc. class line
-
- AssociationLine *m_associationLine; ///< the definition points for the association line
- ClassifierWidget *m_associationClass; ///< used if we have an assoc. class
- Uml::AssociationType::Enum m_associationType; ///< is only used if m_pObject is not set
- WidgetRole m_role[2];
- FloatingTextWidget* m_nameWidget; ///< displays the name of this association
- QPointF m_eventScenePos; ///< holds scene pos of contextMenuEvent()
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/boxwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/boxwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/boxwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/boxwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,79 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "boxwidget.h"
-
-// app includes
-#include "uml.h"
-#include "umldoc.h"
-
-// qt includes
-#include <QColorDialog>
-
-/**
- * Constructs a BoxWidget.
- *
- * @param scene The parent to this widget.
- * @param id The ID to assign (-1 will prompt a new ID.)
- * @param type The WidgetType (wt_Box.)
- */
-BoxWidget::BoxWidget(UMLScene * scene, Uml::ID::Type id, WidgetType type)
- : UMLWidget(scene, type, id)
-{
- setSize(100, 80);
- m_usesDiagramLineColor = false; // boxes be black
- m_lineColor = QColor("black");
- setZValue(-10);
-}
-
-/**
- * Destructor.
- */
-BoxWidget::~BoxWidget()
-{
-}
-
-/**
- * Draws a rectangle.
- */
-void BoxWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
- setPenFromSettings(painter);
- painter->drawRect(0, 0, width(), height());
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Saves the widget to the "boxwidget" XMI element.
- * Note: For loading from XMI, the inherited parent method is used.
- */
-void BoxWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement boxElement = qDoc.createElement(QLatin1String("boxwidget"));
- UMLWidget::saveToXMI(qDoc, boxElement);
- qElement.appendChild(boxElement);
-}
-
-/**
- * Show a properties dialog for a BoxWidget.
- */
-void BoxWidget::showPropertiesDialog()
-{
- QColor newColor = QColorDialog::getColor(lineColor()); // krazy:exclude=qclasses
- if (newColor != lineColor()) {
- setLineColor(newColor);
- setUsesDiagramLineColor(false);
- umlDoc()->setModified(true);
- }
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/boxwidget.h umbrello-kf6-15.08.1/umbrello/widgets/boxwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/boxwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/boxwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,39 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef BOXWIDGET_H
-#define BOXWIDGET_H
-
-//app includes
-#include "umlwidget.h"
-
-/**
- * Displays a rectangular box.
- * These widgets are diagram specific. They will still need a unique id
- * from the @ref UMLDoc class for deletion and other purpose-kf6s.
- *
- * @short Displays a box.
- * @author Jonathan Riddell
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class BoxWidget : public UMLWidget
-{
-public:
- explicit BoxWidget(UMLScene * scene, Uml::ID::Type id = Uml::ID::None, WidgetType type = WidgetBase::wt_Box);
- virtual ~BoxWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
- virtual void showPropertiesDialog();
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/categorywidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/categorywidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/categorywidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/categorywidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,148 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header file
-#include "categorywidget.h"
-
-// local includes
-#include "category.h"
-#include "debug_utils.h"
-#include "umlview.h"
-#include "listpopupmenu.h"
-
-// qt includes
-#include <QPainter>
-
-/**
- * Creates a Category widget.
- *
- * @param scene The parent of the widget.
- * @param o The UMLCategory to represent.
- */
-CategoryWidget::CategoryWidget(UMLScene * scene, UMLCategory *o)
- : UMLWidget(scene, WidgetBase::wt_Category, o)
-{
- m_fixedAspectRatio = true;
-}
-
-/**
- * Destructor.
- */
-CategoryWidget::~CategoryWidget()
-{
-}
-
-/**
- * Overrides the standard paint event.
- */
-void CategoryWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- UMLWidget::setPenFromSettings(painter);
- if (UMLWidget::useFillColor())
- painter->setBrush(UMLWidget::fillColor());
- QFont font = UMLWidget::font();
- font.setUnderline(false);
- font.setBold(false);
- font.setItalic(m_umlObject->isAbstract());
- painter->setFont(font);
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- // the height is our radius
- const int h = height();
- const int w = width();
- const int r = h > w ? h : w;
-
- //int middleX = w / 2;
- const int textStartY = (r / 2) - (fontHeight / 2);
-
- // draw a circle
- painter->drawEllipse(0, 0, r, r);
- painter->setPen(textColor());
-
- QString letterType(QLatin1Char('D'));
- switch(static_cast<UMLCategory*>(m_umlObject)->getType()) {
- case UMLCategory::ct_Disjoint_Specialisation:
- letterType = QLatin1Char('D');
- break;
- case UMLCategory::ct_Overlapping_Specialisation:
- letterType = QLatin1Char('O');
- break;
- case UMLCategory::ct_Union:
- letterType = QLatin1Char('U');
- break;
- default:
- break;
- }
-
- painter->drawText(UC_MARGIN, textStartY, r - UC_MARGIN * 2, fontHeight, Qt::AlignCenter, letterType);
- UMLWidget::setPenFromSettings(painter);
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF CategoryWidget::minimumSize() const
-{
- const UMLWidget::FontType ft = (m_umlObject->isAbstract() ? FT_BOLD_ITALIC : FT_BOLD);
- const QFontMetrics &fm = UMLWidget::getFontMetrics(ft);
- const int fontHeight = fm.lineSpacing();
- int radius = UC_RADIUS + fontHeight + UC_MARGIN;
-
- return QSizeF(radius, radius);
-}
-
-/**
- * Saves this Category to file.
- */
-void CategoryWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement categoryElement = qDoc.createElement(QLatin1String("categorywidget"));
- UMLWidget::saveToXMI(qDoc, categoryElement);
- qElement.appendChild(categoryElement);
-}
-
-/**
- * Will be called when a menu selection has been made from the
- * popup menu.
- *
- * @param action The action that has been selected.
- */
-void CategoryWidget::slotMenuSelection(QAction* action)
-{
- UMLCategory* catObj = static_cast<UMLCategory*>(umlObject());
- if (!catObj) {
- uWarning() << "No UMLCategory for this widget.";
- return;
- }
-
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_DisjointSpecialisation:
- catObj->setType(UMLCategory::ct_Disjoint_Specialisation);
- break;
-
- case ListPopupMenu::mt_OverlappingSpecialisation:
- catObj->setType(UMLCategory::ct_Overlapping_Specialisation);
- break;
-
- case ListPopupMenu::mt_Union:
- catObj->setType(UMLCategory::ct_Union);
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- }
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/categorywidget.h umbrello-kf6-15.08.1/umbrello/widgets/categorywidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/categorywidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/categorywidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,56 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef CATEGORYWIDGET_H
-#define CATEGORYWIDGET_H
-
-#include "umlwidget.h"
-
-#define UC_MARGIN 5
-#define UC_RADIUS 30
-
-class UMLCategory;
-
-/**
- * This class is the graphical version of a UMLCategory. A CategoryWidget is created
- * by a @ref UMLView. An CategoryWidget belongs to only one @ref UMLView instance.
- * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
- *
- * If the Category class that this CategoryWidget is displaying is deleted, the @ref UMLView will
- * make sure that this instance is also deleted.
- *
- * The CategoryWidget class inherits from the @ref UMLWidget class which adds most of the functionality
- * to this class.
- *
- * @short A graphical version of a UMLCategory.
- * @author Sharan Rao
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class CategoryWidget : public UMLWidget
-{
- Q_OBJECT
-public:
- CategoryWidget(UMLScene * scene, UMLCategory *o);
- virtual ~CategoryWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
- // For loading we can use the loadFromXMI() inherited from UMLWidget.
-
-protected:
- QSizeF minimumSize() const;
-
-public slots:
- void slotMenuSelection(QAction* action);
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/classifierwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/classifierwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/classifierwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/classifierwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,1420 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// 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 "listpopupmenu.h"
-#include "object_factory.h"
-#include "operation.h"
-#include "template.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlview.h"
-
-#define PACKAGE_MARGIN 5
-
-// qt includes
-#include <QPainter>
-
-DEBUG_REGISTER_DISABLED(ClassifierWidget)
-
-const int ClassifierWidget::MARGIN = 5;
-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()) {
- m_baseType = WidgetBase::wt_Interface;
- m_visualProperties = ShowOperations | ShowVisibility | ShowStereotype;
- setShowStereotype(true);
- updateSignatureTypes();
- }
-}
-
-/**
- * Constructs a ClassifierWidget.
- *
- * @param scene The parent of this ClassifierWidget.
- * @param c The UMLClassifier 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 dynamic_cast<UMLClassifier*>(m_umlObject);
-}
-
-/**
- * @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 += MARGIN;
- }
-
- // consider name
- height += fontHeight;
- // ... width
- QString displayedName;
- if (visualProperty(ShowPackage))
- displayedName = m_umlObject->fullyQualifiedName();
- else
- displayedName = m_umlObject->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*MARGIN, 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(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)).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);
- 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() - MARGIN;
- }
- }
-
- // allow for height margin
- if (showNameOnly) {
- height += MARGIN;
- }
-
- // allow for width margin
- width += MARGIN * 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() + (MARGIN*2);
-
- foreach (UMLTemplate *t, list) {
- int textWidth = fm.size(0, t->toString()).width();
- if (textWidth > width)
- width = textWidth;
- }
-
- width += (MARGIN*2);
- return QSize(width, height);
-}
-
-/**
- * Return the number of displayed attributes.
- */
-int ClassifierWidget::displayedAttributes() const
-{
- if (!visualProperty(ShowAttributes))
- return 0;
- 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 = NULL;
- 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.
- */
-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() - MARGIN;
- int w = width();
- if (templatesBoxSize.width() > 0)
- w -= templatesBoxSize.width() / 2;
- int h = height();
- if (templatesBoxSize.height() > 0)
- h -= templatesBoxSize.height() - MARGIN;
- 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() + MARGIN;
- int y = MARGIN;
- foreach (UMLTemplate *t, tlist) {
- QString text = t->toString();
- painter->drawText(x, y, fm.size(0, text).width(), fontHeight, Qt::AlignVCenter, text);
- y += fontHeight;
- }
- }
-
- const int textX = MARGIN;
- const int textWidth = w - MARGIN * 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;
- if (visualProperty(ShowPackage)) {
- name = m_umlObject->fullyQualifiedName();
- } else {
- name = this->name();
- }
- font.setItalic(m_umlObject->isAbstract());
- painter->setFont(font);
- painter->drawText(textX, bodyOffsetY, textWidth, nameHeight, Qt::AlignCenter, name);
- 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*MARGIN, h-bodyOffsetY), Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, documentation());
- if (brect.width() > width() + 2*MARGIN)
- brect.setWidth(width()-2*MARGIN);
- 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) {
- 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(rect());
- return path;
- }
-#ifdef ENABLE_WIDGET_SHOW_DOC
- QSizeF mainSize = rect().size();
-#else
- QSizeF mainSize = calculateSize(false);
-#endif
- QSize templatesBoxSize = calculateTemplatesBoxSize();
- qreal mainY = 0.0;
- if (templatesBoxSize.height() > 0) {
- mainY += templatesBoxSize.height() - MARGIN;
- 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)
-{
- const int w = width();
-
- if (m_Assocs.size() > 1) {
- painter->drawEllipse(w/2 - CIRCLE_SIZE/2, SOCKET_INCREMENT / 2, CIRCLE_SIZE, CIRCLE_SIZE);
- // 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, m_Assocs) {
- 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;
-
- 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);
-
- UMLWidget::paint(painter, option);
-}
-
-/**
- * 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 (m_Assocs.size() > 1)
- 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 + PACKAGE_MARGIN,
- w, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true));
- lines = 2;
- }
-
- painter->drawText(0, (fontHeight*lines) + PACKAGE_MARGIN,
- 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 += PACKAGE_MARGIN * 2;
- if (width < 70)
- width = 70; // minumin width of 70
-
- int height = (lines*fontHeight) + fontHeight + (PACKAGE_MARGIN * 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);
- 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 NULL;
- * m_pInterfaceName if m_pName is non NULL and
- * m_pInterfaceName->onWidget(p) returns non NULL; else NULL.
- */
-UMLWidget* ClassifierWidget::onWidget(const QPointF &p)
-{
- if (UMLWidget::onWidget(p) != NULL)
- return this;
- if (getDrawAsCircle() && m_pInterfaceName) {
- uDebug() << "floatingtext: " << m_pInterfaceName->text();
- return m_pInterfaceName->onWidget(p);
- }
- return NULL;
-}
-
-/**
- * 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 NULL;
-}
-
-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;
- }
- 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()
-{
- m_baseType = 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()
-{
- m_baseType = 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()
-{
- m_baseType = 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::loadFromXMI(QDomElement & qElement)
-{
- if (!UMLWidget::loadFromXMI(qElement)) {
- return false;
- }
-
- 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"));
-#ifdef ENABLE_WIDGET_SHOW_DOC
- QString showDocumentation = qElement.attribute(QLatin1String("showdocumentation"), QLatin1String("0"));
-#endif
-
- 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());
-#ifdef ENABLE_WIDGET_SHOW_DOC
- setVisualPropertyCmd(ShowDocumentation, (bool)showDocumentation.toInt());
-#endif
-
- m_attributeSignature = Uml::SignatureType::fromInt(showattsigs.toInt());
- m_operationSignature = Uml::SignatureType::fromInt(showopsigs.toInt());
-
- 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 == NULL) {
- m_pInterfaceName = new FloatingTextWidget(m_scene,
- Uml::TextRole::Floating,
- name(), Uml::ID::Reserved);
- m_pInterfaceName->setParentItem(this);
- }
- if (!m_pInterfaceName->loadFromXMI(element)) {
- // Most likely cause: The FloatingTextWidget is empty.
- delete m_pInterfaceName;
- m_pInterfaceName = NULL;
- } else {
- m_pInterfaceName->activate();
- m_pInterfaceName->update();
- }
- } else {
- uError() << "unknown tag " << tag;
- }
- }
-
- return true;
-}
-
-/**
- * Creates the "classwidget" or "interfacewidget" XML element.
- */
-void ClassifierWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement conceptElement;
- UMLClassifier *umlc = classifier();
- if (umlc && umlc->isInterface())
- conceptElement = qDoc.createElement(QLatin1String("interfacewidget"));
- else
- conceptElement = qDoc.createElement(QLatin1String("classwidget"));
- UMLWidget::saveToXMI(qDoc, conceptElement);
- 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);
-#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->saveToXMI(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:
- {
- 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_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);
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/classifierwidget.h umbrello-kf6-15.08.1/umbrello/widgets/classifierwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/classifierwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/classifierwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,146 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef CLASSIFIERWIDGET_H
-#define CLASSIFIERWIDGET_H
-
-#include "basictypes.h"
-#include "umlobject.h"
-#include "umlwidget.h"
-
-class AssociationWidget;
-class FloatingTextWidget;
-class QPainter;
-class UMLClassifier;
-
-/**
- * @short Common implementation for class widget and interface widget
- *
- * @author Oliver Kellogg
- * @author Gopala Krishna
- *
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class ClassifierWidget : public UMLWidget
-{
- Q_OBJECT
- Q_ENUMS(VisualProperty)
-public:
- /**
- * This enumeration lists the visual properties that can be easily
- * set, reset and toggled and all these operate on an integer
- * which stores all the flag status.
- */
- enum VisualProperty {
- ShowStereotype = 0x1,
- ShowOperations = 0x2,
- ShowPublicOnly = 0x4,
- ShowVisibility = 0x8,
- ShowPackage = 0x10,
- ShowAttributes = 0x20,
- DrawAsCircle = 0x40,
- ShowOperationSignature = 0x60, ///< only in setter
- ShowAttributeSignature = 0x80, ///< only in setter
- DrawAsPackage = 0x100,
- ShowDocumentation = 0x200,
- };
-
- Q_DECLARE_FLAGS(VisualProperties, VisualProperty)
-
- ClassifierWidget(UMLScene * scene, UMLClassifier * o);
- ClassifierWidget(UMLScene * scene, UMLPackage * o);
- virtual ~ClassifierWidget();
-
- UMLClassifier *classifier() const;
-
- VisualProperties visualProperties() const;
- void setVisualProperties(VisualProperties properties);
-
- bool visualProperty(VisualProperty property) const;
- void setVisualProperty(VisualProperty property, bool enable = true);
- void setVisualPropertyCmd(VisualProperty property, bool enable = true);
- void toggleVisualProperty(VisualProperty property);
-
- int displayedAttributes() const;
- int displayedOperations() const;
-
- Uml::SignatureType::Enum attributeSignature() const;
- void setAttributeSignature(Uml::SignatureType::Enum sig);
-
- Uml::SignatureType::Enum operationSignature() const;
- void setOperationSignature(Uml::SignatureType::Enum sig);
-
- void setShowAttSigs(bool _show);
- void toggleShowAttSigs();
-
- bool getDrawAsCircle() const;
- void setDrawAsCircle(bool drawAsCircle);
- void toggleDrawAsCircle();
-
- void changeToClass();
- void changeToInterface();
- void changeToPackage();
-
- AssociationWidget *classAssociationWidget() const;
- void setClassAssociationWidget(AssociationWidget *assocwidget);
-// virtual void adjustAssociations(int x, int y);
-
- UMLWidget* onWidget(const QPointF& p);
- UMLWidget* widgetWithID(Uml::ID::Type id);
-
- virtual void setDocumentation(const QString& doc);
-
- QSizeF calculateSize(bool withExtensions = true) const;
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
- virtual QPainterPath shape() const;
-
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
- virtual bool loadFromXMI(QDomElement & qElement);
-
-public Q_SLOTS:
- virtual void slotMenuSelection(QAction* action);
-
-private Q_SLOTS:
- void slotShowAttributes(bool state);
- void slotShowOperations(bool state);
-
-private:
- void updateSignatureTypes();
- QSize calculateTemplatesBoxSize() const;
-
- QSizeF minimumSize() const;
-
- void drawAsCircle(QPainter *p, const QStyleOptionGraphicsItem *option);
- QSize calculateAsCircleSize() const;
-
- void drawAsPackage(QPainter *painter, const QStyleOptionGraphicsItem *option);
- QSize calculateAsPackageSize() const;
-
- int displayedMembers(UMLObject::ObjectType ot) const;
- void drawMembers(QPainter *painter, UMLObject::ObjectType ot, Uml::SignatureType::Enum sigType,
- int x, int y, int fontHeight);
-
- static const int MARGIN; ///< text width margin
- static const int CIRCLE_SIZE; ///< size of circle when interface is rendered as such
- static const int SOCKET_INCREMENT; ///< augmentation of circle for socket (required interface)
-
- VisualProperties m_visualProperties;
- Uml::SignatureType::Enum m_attributeSignature; ///< Loaded/saved item.
- Uml::SignatureType::Enum m_operationSignature; ///< Loaded/saved item.
- AssociationWidget *m_pAssocWidget; ///< related AssociationWidget in case this classifier acts as an association class
- FloatingTextWidget *m_pInterfaceName; ///< Separate widget for name in case of interface drawn as circle
-
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(ClassifierWidget::VisualProperties)
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/combinedfragmentwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/combinedfragmentwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/combinedfragmentwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/combinedfragmentwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,477 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "combinedfragmentwidget.h"
-
-// app includes
-#include "debug_utils.h"
-#include "dialog_utils.h"
-#include "listpopupmenu.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-// kde includes
-#include <KLocalizedString>
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-#include <QPainter>
-#include <QString>
-
-/**
- * Creates a Combined Fragment widget.
- *
- * @param scene The parent of the widget.
- * @param combinedfragmentType The type of combined fragment.
- * @param id The ID to assign (-1 will prompt a new ID.)
- */
-CombinedFragmentWidget::CombinedFragmentWidget(UMLScene * scene, CombinedFragmentType combinedfragmentType, Uml::ID::Type id)
- : UMLWidget(scene, WidgetBase::wt_CombinedFragment, id)
-{
- setCombinedFragmentType(combinedfragmentType);
-}
-
-/**
- * Destructor.
- */
-CombinedFragmentWidget::~CombinedFragmentWidget()
-{
- for (QList<FloatingDashLineWidget*>::iterator it=m_dashLines.begin() ; it!=m_dashLines.end() ; ++it) {
- delete(*it);
- }
-}
-
-/**
- * Overrides the standard paint event.
- */
-void CombinedFragmentWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- int w = width();
- int h = height();
- int line_width = 45;
- int old_Y;
-
- setPenFromSettings(painter);
-
- if (m_CombinedFragment == Ref) {
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- }
- }
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- const QString combined_fragment_value = name();
- int textStartY = (h / 2) - (fontHeight / 2);
- painter->drawRect(0, 0, w, h);
-
- painter->setPen(textColor());
- painter->setFont(UMLWidget::font());
- QString temp = QLatin1String("loop");
-
- switch (m_CombinedFragment)
- {
- case Ref :
- painter->drawText(COMBINED_FRAGMENT_MARGIN, textStartY, w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignCenter, combined_fragment_value);
- painter->drawText(COMBINED_FRAGMENT_MARGIN, 0, w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("ref"));
- break;
-
- case Opt :
- painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
- w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("opt"));
- break;
-
- case Break :
- painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
- w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("break"));
- break;
-
- case Loop :
- if (combined_fragment_value != QLatin1String("-"))
- {
- temp += QLatin1String(" [") + combined_fragment_value + QLatin1Char(']');
- line_width += (combined_fragment_value.size() + 2) * 8;
- }
- painter->drawText(COMBINED_FRAGMENT_MARGIN, 0, w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, temp);
-
- break;
-
- case Neg :
- painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
- w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("neg"));
- break;
-
- case Crit :
- painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
- w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("critical"));
- break;
-
- case Ass :
- painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
- w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("assert"));
- break;
-
- case Alt :
- if (combined_fragment_value != QLatin1String("-"))
- {
- temp = QLatin1Char('[') + combined_fragment_value + QLatin1Char(']');
- painter->drawText(COMBINED_FRAGMENT_MARGIN, 20, w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, temp);
- if (m_dashLines.size() == 1 && m_dashLines.first()->y() < y() + 20 + fontHeight)
- m_dashLines.first()->setY(y() + h/2);
- }
- painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
- w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("alt"));
- // dash lines
- //m_dashLines.first()->paint(painter);
- // TODO: move to UMLWidget::calculateSize api
- for (QList<FloatingDashLineWidget*>::iterator it=m_dashLines.begin() ; it!=m_dashLines.end() ; ++it) {
- (*it)->setX(x());
- old_Y = (*it)->getYMin();
- (*it)->setYMin(y());
- (*it)->setYMax(y() + height());
- (*it)->setY(y() + (*it)->y() - old_Y);
- (*it)->setSize(w, (*it)->height());
- (*it)->setLineColor(lineColor());
- (*it)->setLineWidth(lineWidth());
- }
-
- break;
-
- case Par :
- painter->drawText(COMBINED_FRAGMENT_MARGIN, 0,
- w - COMBINED_FRAGMENT_MARGIN * 2, fontHeight, Qt::AlignLeft, QLatin1String("parallel"));
- // dash lines
- if (m_dashLines.size() != 0) {
- //m_dashLines.first()->paint(painter);
- // TODO: move to UMLWidget::calculateSize api
- for (QList<FloatingDashLineWidget*>::iterator it=m_dashLines.begin() ; it!=m_dashLines.end() ; ++it) {
- (*it)->setX(x());
- old_Y = (*it)->getYMin();
- (*it)->setYMin(y());
- (*it)->setYMax(y() + height());
- (*it)->setY(y() + (*it)->y() - old_Y);
- (*it)->setSize(w, (*it)->height());
- (*it)->setLineColor(lineColor());
- (*it)->setLineWidth(lineWidth());
- }
- }
- break;
-
- default : break;
- }
-
- setPenFromSettings(painter);
- painter->drawLine(0, 20, line_width, 20);
- painter->drawLine(line_width, 20, line_width + 10, 10);
- painter->drawLine(line_width + 10, 10, line_width + 10, 0);
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF CombinedFragmentWidget::minimumSize() const
-{
- int width = 10, height = 10;
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- const int textWidth = fm.width(name());
- height = fontHeight;
- width = textWidth + 60 > COMBINED_FRAGMENT_WIDTH ? textWidth + 60: COMBINED_FRAGMENT_WIDTH;
- if (m_CombinedFragment == Loop)
- width += int((float)textWidth * 0.4f);
- if (m_CombinedFragment == Alt)
- height += fontHeight + 40;
- height = height > COMBINED_FRAGMENT_HEIGHT ? height : COMBINED_FRAGMENT_HEIGHT;
- width += COMBINED_FRAGMENT_MARGIN * 2;
- height += COMBINED_FRAGMENT_MARGIN * 2;
-
- return QSizeF(width, height);
-}
-
-/**
- * Returns the type of combined fragment.
- */
-CombinedFragmentWidget::CombinedFragmentType CombinedFragmentWidget::combinedFragmentType() const
-{
- return m_CombinedFragment;
-}
-
-/**
- * Sets the type of combined fragment.
- */
-void CombinedFragmentWidget::setCombinedFragmentType(CombinedFragmentType combinedfragmentType)
-{
- m_CombinedFragment = combinedfragmentType;
- UMLWidget::m_resizable = true ; //(m_CombinedFragment == Normal);
- // creates a dash line if the combined fragment type is alternative or parallel
- if (m_CombinedFragment == Alt && m_dashLines.isEmpty())
- {
- m_dashLines.push_back(new FloatingDashLineWidget(m_scene, Uml::ID::None, this));
- if (m_CombinedFragment == Alt)
- {
- m_dashLines.back()->setText(QLatin1String("else"));
- }
- // TODO: move to UMLWidget::calculateSize api
- m_dashLines.back()->setX(x());
- m_dashLines.back()->setYMin(y());
- m_dashLines.back()->setYMax(y() + height());
- m_dashLines.back()->setY(y() + height()/2);
- m_dashLines.back()->setSize(width(), m_dashLines.back()->height());
- m_scene->widgetList().append(m_dashLines.back());
- }
-}
-
-/**
- * Returns the type of combined fragment.
- */
-CombinedFragmentWidget::CombinedFragmentType CombinedFragmentWidget::combinedFragmentType(const QString& type) const
-{
- if (type == QLatin1String("Reference"))
- return (CombinedFragmentWidget::Ref);
- if (type == QLatin1String("Option"))
- return (CombinedFragmentWidget::Opt);
- if (type == QLatin1String("Break"))
- return (CombinedFragmentWidget::Break);
- if (type == QLatin1String("Loop"))
- return (CombinedFragmentWidget::Loop);
- if (type == QLatin1String("Negative"))
- return (CombinedFragmentWidget::Neg);
- if (type == QLatin1String("Critical"))
- return (CombinedFragmentWidget::Crit);
- if (type == QLatin1String("Assertion"))
- return (CombinedFragmentWidget::Ass);
- if (type == QLatin1String("Alternative"))
- return (CombinedFragmentWidget::Alt);
- if (type == QLatin1String("Parallel"))
- return (CombinedFragmentWidget::Par);
- // Shouldn't happen
- Q_ASSERT(0);
- return (CombinedFragmentWidget::Ref);
-}
-
-/**
- * Sets the type of combined fragment.
- */
-void CombinedFragmentWidget::setCombinedFragmentType(const QString& combinedfragmentType)
-{
- setCombinedFragmentType(combinedFragmentType(combinedfragmentType));
-}
-
-/**
- * ...
- */
-void CombinedFragmentWidget::askNameForWidgetType(UMLWidget* &targetWidget, const QString& dialogTitle,
- const QString& dialogPrompt, const QString& defaultName)
-{
- Q_UNUSED(defaultName);
- bool pressedOK = false;
- const QStringList list = QStringList()
- << QLatin1String("Reference")
- << QLatin1String("Option")
- << QLatin1String("Break")
- << QLatin1String("Loop")
- << QLatin1String("Negative")
- << QLatin1String("Critical")
- << QLatin1String("Assertion")
- << QLatin1String("Alternative")
- << QLatin1String("Parallel") ;
-#if QT_VERSION >= 0x050000
- QPointer<QInputDialog> inputDlg = new QInputDialog();
- inputDlg->setComboBoxItems(list);
- inputDlg->setOptions(QInputDialog::UseListViewForComboBoxItems);
- inputDlg->setWindowTitle(dialogTitle);
- inputDlg->setLabelText(dialogPrompt);
- pressedOK = inputDlg->exec();
- QStringList result;
- result.append(inputDlg->textValue());
- delete inputDlg;
-#else
- const QStringList select = list;
- QStringList result = KInputDialog::getItemList (dialogTitle, dialogPrompt, list, select, false, &pressedOK, UMLApp::app());
-#endif
- if (pressedOK) {
- QString type = result.join(QString());
- dynamic_cast<CombinedFragmentWidget*>(targetWidget)->setCombinedFragmentType(type);
- if (type == QLatin1String("Reference"))
- Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the name of the diagram referenced"), i18n("Enter the name of the diagram referenced"), i18n("Diagram name"));
- else if (type == QLatin1String(QLatin1String("Loop")))
- Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the guard of the loop"), i18n("Enter the guard of the loop"), i18n("-"));
- else if (type == QLatin1String("Alternative"))
- Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the first alternative name"), i18n("Enter the first alternative name"), i18n("-"));
- } else {
- targetWidget->cleanup();
- delete targetWidget;
- targetWidget = NULL;
- }
-}
-
-/**
- * Saves the widget to the "combinedFragmentwidget" XMI element.
- */
-void CombinedFragmentWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement combinedFragmentElement = qDoc.createElement(QLatin1String("combinedFragmentwidget"));
- UMLWidget::saveToXMI(qDoc, combinedFragmentElement);
- combinedFragmentElement.setAttribute(QLatin1String("combinedFragmentname"), m_Text);
- combinedFragmentElement.setAttribute(QLatin1String("documentation"), m_Doc);
- combinedFragmentElement.setAttribute(QLatin1String("CombinedFragmenttype"), m_CombinedFragment);
-
- // save the corresponding floating dash lines
- for (QList<FloatingDashLineWidget*>::iterator it = m_dashLines.begin() ; it != m_dashLines.end() ; ++it) {
- (*it)-> saveToXMI(qDoc, combinedFragmentElement);
- }
-
- qElement.appendChild(combinedFragmentElement);
-}
-
-/**
- * Loads the widget from the "CombinedFragmentwidget" XMI element.
- */
-bool CombinedFragmentWidget::loadFromXMI(QDomElement & qElement)
-{
- if (!UMLWidget::loadFromXMI(qElement))
- return false;
- m_Text = qElement.attribute(QLatin1String("combinedFragmentname"));
- m_Doc = qElement.attribute(QLatin1String("documentation"));
- QString type = qElement.attribute(QLatin1String("CombinedFragmenttype"));
-
- //now load child elements
- QDomNode node = qElement.firstChild();
- QDomElement element = node.toElement();
- while (!element.isNull()) {
- QString tag = element.tagName();
- if (tag == QLatin1String("floatingdashlinewidget")) {
- FloatingDashLineWidget * fdlwidget = new FloatingDashLineWidget(m_scene, Uml::ID::None, this);
- m_dashLines.push_back(fdlwidget);
- if (!fdlwidget->loadFromXMI(element)) {
- // Most likely cause: The FloatingTextWidget is empty.
- delete m_dashLines.back();
- return false;
- }
- else {
- m_scene->widgetList().append(fdlwidget);
- fdlwidget->clipSize();
- }
- } else {
- uError() << "unknown tag " << tag;
- }
- node = node.nextSibling();
- element = node.toElement();
- }
- // m_dashLines = listline;
- setCombinedFragmentType((CombinedFragmentType)type.toInt());
-
- return true;
-}
-
-void CombinedFragmentWidget::removeDashLine(FloatingDashLineWidget *line)
-{
- if (m_dashLines.contains(line))
- m_dashLines.removeOne(line);
-}
-
-/**
- * Overrides the function from UMLWidget. Deletes all FloatingDashLineWidgets
- * that are associated with this instance.
- */
-void CombinedFragmentWidget::cleanup()
-{
- foreach (FloatingDashLineWidget* w, m_dashLines)
- {
- if (!w->isSelected()) {
- // no need to make this undoable, since the dashlines will be
- // reconstructed when deleting the combined fragment is undone.
- umlScene()->removeWidgetCmd(w);
- }
- }
-}
-
-/**
- * Overrides the function from UMLWidget.
- *
- * @param action The command to be executed.
- */
-void CombinedFragmentWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch (sel) {
- // for alternative or parallel combined fragments
- case ListPopupMenu::mt_AddInteractionOperand:
- m_dashLines.push_back(new FloatingDashLineWidget(m_scene, Uml::ID::None, this));
- if (m_CombinedFragment == Alt)
- {
- m_dashLines.back()->setText(QLatin1String("else"));
- }
- // TODO: move to UMLWidget::calculateSize api
- m_dashLines.back()->setX(x());
- m_dashLines.back()->setYMin(y());
- m_dashLines.back()->setYMax(y() + height());
- m_dashLines.back()->setY(y() + height() / 2);
- m_dashLines.back()->setSize(width(), m_dashLines.back()->height());
- m_scene->setupNewWidget(m_dashLines.back());
- break;
-
- case ListPopupMenu::mt_Rename:
- {
- bool ok = false;
- QString name = m_Text;
-
-#if QT_VERSION >= 0x050000
- if (m_CombinedFragment == Alt) {
- name = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter first alternative"), i18n("Enter first alternative :"),
- QLineEdit::Normal,
- m_Text, &ok);
- }
- else if (m_CombinedFragment == Ref) {
- name = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter referenced diagram name"), i18n("Enter referenced diagram name :"),
- QLineEdit::Normal,
- m_Text, &ok);
- }
- else if (m_CombinedFragment == Loop) {
- name = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter the guard of the loop"), i18n("Enter the guard of the loop:"),
- QLineEdit::Normal,
- m_Text, &ok);
- }
-#else
- if (m_CombinedFragment == Alt) {
- name = KInputDialog::getText(i18n("Enter first alternative"), i18n("Enter first alternative :"), m_Text, &ok);
- }
- else if (m_CombinedFragment == Ref) {
- name = KInputDialog::getText(i18n("Enter referenced diagram name"), i18n("Enter referenced diagram name :"), m_Text, &ok);
- }
- else if (m_CombinedFragment == Loop) {
- name = KInputDialog::getText(i18n("Enter the guard of the loop"), i18n("Enter the guard of the loop:"), m_Text, &ok);
- }
-#endif
- if (ok && name.length() > 0)
- m_Text = name;
- }
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- }
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/combinedfragmentwidget.h umbrello-kf6-15.08.1/umbrello/widgets/combinedfragmentwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/combinedfragmentwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/combinedfragmentwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,91 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef COMBINEDFRAGMENTWIDGET_H
-#define COMBINEDFRAGMENTWIDGET_H
-
-#include "umlwidget.h"
-#include "worktoolbar.h"
-#include "floatingdashlinewidget.h"
-
-#include <QList>
-
-#define COMBINED_FRAGMENT_MARGIN 5
-#define COMBINED_FRAGMENT_WIDTH 100
-#define COMBINED_FRAGMENT_HEIGHT 50
-
-/**
- * This class is the graphical version of a UML combined fragment. A combinedfragmentWidget is created
- * by a @ref UMLView. An combinedfragmentWidget belongs to only one @ref UMLView instance.
- * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
- *
- * The combinedfragmentWidget class inherits from the @ref UMLWidget class which adds most of the functionality
- * to this class.
- *
- * @short A graphical version of a UML combined fragment.
- * @author Hassan KOUCH <hkouch@hotmail.com>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class CombinedFragmentWidget : public UMLWidget
-{
- Q_OBJECT
-
-public:
- enum CombinedFragmentType
- {
- Ref = 0,
- Opt,
- Break,
- Loop,
- Neg,
- Crit,
- Ass,
- Alt,
- Par
- };
-
- explicit CombinedFragmentWidget(UMLScene * scene,
- CombinedFragmentType combinedfragmentType = Ref,
- Uml::ID::Type id = Uml::ID::None);
- virtual ~CombinedFragmentWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- CombinedFragmentType combinedFragmentType() const;
- CombinedFragmentType combinedFragmentType(const QString& combinedfragmentType) const;
- void setCombinedFragmentType(CombinedFragmentType combinedfragmentType);
- void setCombinedFragmentType(const QString& combinedfragmentType);
-
- void askNameForWidgetType(UMLWidget* &targetWidget, const QString& dialogTitle,
- const QString& dialogPrompt, const QString& defaultName);
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
- bool loadFromXMI(QDomElement & qElement);
- void removeDashLine(FloatingDashLineWidget *line);
-
- virtual void cleanup();
-
-public slots:
- void slotMenuSelection(QAction* action);
-
-
-protected:
- QSizeF minimumSize() const;
-
- /// Type of CombinedFragment.
- CombinedFragmentType m_CombinedFragment;
-
-private:
- /// Dash lines of an alternative or parallel combined fragment
- QList<FloatingDashLineWidget*> m_dashLines ;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/componentwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/componentwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/componentwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/componentwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,207 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "componentwidget.h"
-
-// app includes
-#include "component.h"
-#include "debug_utils.h"
-#include "umlscene.h"
-#include "umlview.h"
-#include "optionstate.h"
-#include "umldoc.h"
-#include "package.h"
-#include "portwidget.h"
-
-/**
- * Constructs a ComponentWidget.
- *
- * @param scene The parent of this ComponentWidget.
- * @param c The UMLComponent this will be representing.
- */
-ComponentWidget::ComponentWidget(UMLScene * scene, UMLComponent *c)
- : UMLWidget(scene, WidgetBase::wt_Component, c)
-{
- setSize(100, 30);
- //set defaults from m_scene
- if (m_scene) {
- //check to see if correct
- const Settings::OptionState& ops = m_scene->optionState();
- m_showStereotype = ops.classState.showStereoType;
- }
-}
-
-/**
- * Destructor.
- */
-ComponentWidget::~ComponentWidget()
-{
-}
-
-/**
- * Reimplemented from UMLWidget::paint to paint component
- * widget.
- */
-void ComponentWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- UMLComponent *umlcomp = static_cast<UMLComponent*>(m_umlObject);
- if (umlcomp == NULL)
- return;
- setPenFromSettings(painter);
- QPen origPen = painter->pen();
- QPen pen = origPen;
- if (umlcomp->getExecutable()) {
- pen.setWidth(origPen.width() + 2);
- painter->setPen(pen);
- }
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- } else {
- painter->setBrush(m_scene->backgroundColor());
- }
-
- const int w = width();
- const int h = height();
- const int halfHeight = h / 2;
- int textXOffset = 0;
- QFont font = UMLWidget::font();
- font.setBold(true);
- const QFontMetrics &fm = getFontMetrics(FT_BOLD);
- const int fontHeight = fm.lineSpacing();
- QString nameStr = name();
- const QString stereotype = m_umlObject->stereotype();
-
- if (Settings::optionState().generalState.uml2) {
- painter->drawRect(0, 0, w, h);
- // draw small component symbol in upper right corner
- painter->setPen(origPen);
- painter->drawRect(w - 17, 5, 11, 13);
- painter->drawRect(w - 19, 7, 2, 2);
- painter->drawRect(w - 19, 11, 2, 2);
- painter->setPen(pen);
- } else {
- painter->drawRect(2*COMPONENT_MARGIN, 0, w - 2*COMPONENT_MARGIN, h);
- painter->drawRect(0, halfHeight - fontHeight/2 - fontHeight, COMPONENT_MARGIN*4, fontHeight);
- painter->drawRect(0, halfHeight + fontHeight/2, COMPONENT_MARGIN*4, fontHeight);
- textXOffset = COMPONENT_MARGIN * 4;
- }
-
- painter->setPen(textColor());
- painter->setFont(font);
-
- int lines = 1;
-
- if (!stereotype.isEmpty()) {
- painter->drawText(textXOffset, halfHeight - fontHeight,
- w - textXOffset, fontHeight, Qt::AlignCenter,
- m_umlObject->stereotype(true));
- lines = 2;
- }
-
- if (UMLWidget::isInstance()) {
- font.setUnderline(true);
- painter->setFont(font);
- nameStr = UMLWidget::instanceName() + QLatin1String(" : ") + nameStr;
- }
-
- if (lines == 1) {
- painter->drawText(textXOffset, halfHeight - (fontHeight/2),
- w - textXOffset, fontHeight, Qt::AlignCenter, nameStr);
- } else {
- painter->drawText(textXOffset, halfHeight,
- w - textXOffset, fontHeight, Qt::AlignCenter, nameStr);
- }
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overridden from UMLWidget due to emission of signal sigCompMoved()
- */
-void ComponentWidget::moveWidgetBy(qreal diffX, qreal diffY)
-{
- UMLWidget::moveWidgetBy(diffX, diffY);
- emit sigCompMoved(diffX, diffY);
-}
-
-/**
- * Override method from UMLWidget for adjustment of attached PortWidgets.
- */
-void ComponentWidget::adjustAssocs(qreal dx, qreal dy)
-{
- if (m_doc->loading()) {
- // don't recalculate the assocs during load of XMI
- // -> return immediately without action
- return;
- }
- UMLWidget::adjustAssocs(dx, dy);
- UMLPackage *comp = static_cast<UMLPackage*>(m_umlObject);
- foreach (UMLObject *o, comp->containedObjects()) {
- uIgnoreZeroPointer(o);
- if (o->baseType() != UMLObject::ot_Port)
- continue;
- UMLWidget *portW = m_scene->widgetOnDiagram(o->id());
- if (portW)
- portW->adjustAssocs(dx, dy);
- }
-}
-
-/**
- * Saves to the "componentwidget" XMI element.
- */
-void ComponentWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement conceptElement = qDoc.createElement(QLatin1String("componentwidget"));
- UMLWidget::saveToXMI(qDoc, conceptElement);
- qElement.appendChild(conceptElement);
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF ComponentWidget::minimumSize() const
-{
- if (!m_umlObject) {
- return QSizeF(70, 70);
- }
- const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
- const int fontHeight = fm.lineSpacing();
-
- QString name = m_umlObject->name();
- if (UMLWidget::isInstance()) {
- name = UMLWidget::instanceName() + QLatin1String(" : ") + name;
- }
-
- int width = fm.width(name);
-
- int stereoWidth = 0;
- if (!m_umlObject->stereotype().isEmpty()) {
- stereoWidth = fm.width(m_umlObject->stereotype(true));
- }
- if (stereoWidth > width)
- width = stereoWidth;
- width += COMPONENT_MARGIN * 6;
- width = 70>width ? 70 : width; //minumin width of 70
-
- int height = (2*fontHeight) + (COMPONENT_MARGIN * 3);
-
- UMLComponent *umlcomp = static_cast<UMLComponent*>(m_umlObject);
- if (umlcomp && umlcomp->getExecutable()) {
- width += 2;
- height += 2;
- }
-
- return QSizeF(width, height);
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/componentwidget.h umbrello-kf6-15.08.1/umbrello/widgets/componentwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/componentwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/componentwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,58 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef COMPONENTWIDGET_H
-#define COMPONENTWIDGET_H
-
-#include "umlwidget.h"
-
-class UMLComponent;
-
-#define COMPONENT_MARGIN 10
-
-/**
- * Defines a graphical version of the Component. Most of the functionality
- * will come from the @ref UMLComponent class.
- *
- * @short A graphical version of a Component.
- * @author Jonathan Riddell
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class ComponentWidget : public UMLWidget
-{
- Q_OBJECT
-public:
- ComponentWidget(UMLScene * scene, UMLComponent *c);
- virtual ~ComponentWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
- virtual void moveWidgetBy(qreal diffX, qreal diffY);
- virtual void adjustAssocs(qreal dx, qreal dy);
-
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
-signals:
- /**
- * Emitted when the component widget is moved.
- * Provides the delta X and delta Y amount by which the widget was moved
- * relative to the previous position.
- * Slots into PortWidget::slotCompMoved()
- * @param diffX The difference between previous and new X value.
- * @param diffY The difference between previous and new Y value.
- */
- void sigCompMoved(qreal diffX, qreal diffY);
-
-protected:
- QSizeF minimumSize() const;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/datatypewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/datatypewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/datatypewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/datatypewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,129 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "datatypewidget.h"
-
-// app includes
-#include "classifier.h"
-#include "classifierlistitem.h"
-#include "debug_utils.h"
-#include "operation.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-// qt includes
-#include <QPainter>
-
-/**
- * Constructs an DatatypeWidget.
- *
- * @param scene The parent of this DatatypeWidget.
- * @param d The UMLClassifier this will be representing.
- */
-DatatypeWidget::DatatypeWidget(UMLScene *scene, UMLClassifier *d)
- : UMLWidget(scene, WidgetBase::wt_Datatype, d)
-{
- setSize(100, 30);
-}
-
-/**
- * Standard deconstructor.
- */
-DatatypeWidget::~DatatypeWidget()
-{
-}
-
-/**
- * Overrides standard method.
- */
-void DatatypeWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- setPenFromSettings(painter);
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- } else {
- painter->setBrush(m_scene->backgroundColor());
- }
-
- int w = width();
- int h = height();
-
- QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- int fontHeight = fm.lineSpacing();
-
- painter->drawRect(0, 0, w, h);
- painter->setPen(textColor());
-
- QFont font = UMLWidget::font();
- font.setBold(true);
- painter->setFont(font);
- painter->drawText(DATATYPE_MARGIN, 0,
- w - DATATYPE_MARGIN* 2, fontHeight,
- Qt::AlignCenter, m_umlObject->stereotype(true));
-
- font.setItalic(m_umlObject->isAbstract());
- painter->setFont(font);
- painter->drawText(DATATYPE_MARGIN, fontHeight,
- w - DATATYPE_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Loads from a "datatypewidget" XMI element.
- */
-bool DatatypeWidget::loadFromXMI(QDomElement & qElement)
-{
- return UMLWidget::loadFromXMI(qElement);
-}
-
-/**
- * Saves to the "datatypewidget" XMI element.
- */
-void DatatypeWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement conceptElement = qDoc.createElement(QLatin1String("datatypewidget"));
- UMLWidget::saveToXMI(qDoc, conceptElement);
- qElement.appendChild(conceptElement);
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF DatatypeWidget::minimumSize() const
-{
- if (!m_umlObject) {
- return UMLWidget::minimumSize();
- }
- int width, height;
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
-
- int lines = 1;//always have one line - for name
- lines++; //for the stereotype
-
- height = width = 0;
- height += lines * fontHeight;
-
- //now set the width of the concept
- //set width to name to start with
- //set width to name to start with
- width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(m_umlObject->fullyQualifiedName()).width();
- int w = getFontMetrics(FT_BOLD).boundingRect(m_umlObject->stereotype(true)).width();
-
- width = w > width?w:width;
-
- //allow for width margin
- width += DATATYPE_MARGIN * 2;
-
- return QSizeF(width, height);
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/datatypewidget.h umbrello-kf6-15.08.1/umbrello/widgets/datatypewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/datatypewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/datatypewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,48 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef DATATYPEWIDGET_H
-#define DATATYPEWIDGET_H
-
-#include "umlwidget.h"
-
-class UMLClassifier;
-
-#define DATATYPE_MARGIN 5
-
-/**
- * Defines a graphical version of the datatype. Most of the functionality
- * will come from the @ref UMLWidget class from which class inherits from.
- *
- * @short A graphical version of an datatype.
- * @author Jonathan Riddell
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class DatatypeWidget : public UMLWidget
-{
- Q_OBJECT
-public:
- DatatypeWidget(UMLScene *scene, UMLClassifier *d);
- virtual ~DatatypeWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- bool loadFromXMI(QDomElement& qElement);
- void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
-public Q_SLOTS:
-
-protected:
- QSizeF minimumSize() const;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/entitywidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/entitywidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/entitywidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/entitywidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,246 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "entitywidget.h"
-
-// app includes
-#include "classifier.h"
-#include "classifierlistitem.h"
-#include "debug_utils.h"
-#include "entity.h"
-#include "entityattribute.h"
-#include "foreignkeyconstraint.h"
-#include "listpopupmenu.h"
-#include "object_factory.h"
-#include "uml.h"
-#include "umlclassifierlistitemlist.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-#include "uniqueconstraint.h"
-
-/**
- * Constructs an EntityWidget.
- *
- * @param scene The parent of this EntityWidget.
- * @param o The UMLObject this will be representing.
- */
-EntityWidget::EntityWidget(UMLScene *scene, UMLObject* o)
- : UMLWidget(scene, WidgetBase::wt_Entity, o)
-{
- setSize(100, 30);
-}
-
-/**
- * Destructor.
- */
-EntityWidget::~EntityWidget()
-{
-}
-
-/**
- * Draws the entity as a rectangle with a box underneith with a list of literals
- */
-void EntityWidget::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());
-
- const int w = width();
- const int h = height();
-
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- int fontHeight = fm.lineSpacing();
- const QString name = this->name();
-
- painter->drawRect(0, 0, w, h);
- painter->setPen(textColor());
-
- QFont font = UMLWidget::font();
- font.setBold(true);
- painter->setFont(font);
- int y = 0;
- if (!m_umlObject->stereotype().isEmpty()) {
- painter->drawText(ENTITY_MARGIN, 0,
- w - ENTITY_MARGIN * 2, fontHeight,
- Qt::AlignCenter, m_umlObject->stereotype(true));
- font.setItalic(m_umlObject->isAbstract());
- painter->setFont(font);
- painter->drawText(ENTITY_MARGIN, fontHeight,
- w - ENTITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
- font.setBold(false);
- font.setItalic(false);
- painter->setFont(font);
- y = fontHeight * 2;
- } else {
- font.setItalic(m_umlObject->isAbstract());
- painter->setFont(font);
- painter->drawText(ENTITY_MARGIN, 0,
- w - ENTITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
- font.setBold(false);
- font.setItalic(false);
- painter->setFont(font);
-
- y = fontHeight;
- }
-
- setPenFromSettings(painter);
-
- painter->drawLine(0, y, w, y);
-
- QFontMetrics fontMetrics(font);
- UMLClassifier *classifier = (UMLClassifier*)m_umlObject;
- UMLClassifierListItem* entityattribute = 0;
- UMLClassifierListItemList list = classifier->getFilteredList(UMLObject::ot_EntityAttribute);
- foreach (entityattribute, list) {
- QString text = entityattribute->name();
- painter->setPen(textColor());
- UMLEntityAttribute* casted = dynamic_cast<UMLEntityAttribute*>(entityattribute);
- if(casted && casted->indexType() == UMLEntityAttribute::Primary)
- {
- font.setUnderline(true);
- painter->setFont(font);
- font.setUnderline(false);
- }
- painter->drawText(ENTITY_MARGIN, y,
- fontMetrics.width(text), fontHeight, Qt::AlignVCenter, text);
- painter->setFont(font);
- y+=fontHeight;
- }
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Saves to the "entitywidget" XMI element.
- */
-void EntityWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement conceptElement = qDoc.createElement(QLatin1String("entitywidget"));
- UMLWidget::saveToXMI(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 EntityWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_EntityAttribute:
- if (Object_Factory::createChildObject(static_cast<UMLClassifier*>(m_umlObject),
- UMLObject::ot_EntityAttribute)) {
- UMLApp::app()->document()->setModified();
- }
- break;
-
- case ListPopupMenu::mt_PrimaryKeyConstraint:
- case ListPopupMenu::mt_UniqueConstraint:
- if (UMLObject* obj = Object_Factory::createChildObject(static_cast<UMLEntity*>(m_umlObject),
- UMLObject::ot_UniqueConstraint)) {
- UMLApp::app()->document()->setModified();
-
- if (sel == ListPopupMenu::mt_PrimaryKeyConstraint) {
- UMLUniqueConstraint* uc = static_cast<UMLUniqueConstraint*>(obj);
- static_cast<UMLEntity*>(m_umlObject)->setAsPrimaryKey(uc);
- }
- }
- break;
-
- case ListPopupMenu::mt_ForeignKeyConstraint:
- if (Object_Factory::createChildObject(static_cast<UMLEntity*>(m_umlObject),
- UMLObject::ot_ForeignKeyConstraint)) {
- UMLApp::app()->document()->setModified();
-
- }
- break;
-
- case ListPopupMenu::mt_CheckConstraint:
- if (Object_Factory::createChildObject(static_cast<UMLEntity*>(m_umlObject),
- UMLObject::ot_CheckConstraint)) {
- UMLApp::app()->document()->setModified();
-
- }
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- }
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF EntityWidget::minimumSize() const
-{
- if (!m_umlObject) {
- return UMLWidget::minimumSize();
- }
-
- int width, height;
- QFont font = UMLWidget::font();
- font.setItalic(false);
- font.setUnderline(false);
- font.setBold(false);
- const QFontMetrics fm(font);
-
- const int fontHeight = fm.lineSpacing();
-
- int lines = 1;//always have one line - for name
- if (!m_umlObject->stereotype().isEmpty()) {
- lines++;
- }
-
- const int numberOfEntityAttributes = ((UMLEntity*)m_umlObject)->entityAttributes();
-
- height = width = 0;
- //set the height of the entity
-
- lines += numberOfEntityAttributes;
- if (numberOfEntityAttributes == 0) {
- height += fontHeight / 2; //no entity literals, so just add a bit of space
- }
-
- height += lines * fontHeight;
-
- //now set the width of the concept
- //set width to name to start with
- // FIXME spaces to get round beastie with font width,
- // investigate UMLWidget::getFontMetrics()
- width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(QLatin1Char(' ') + name() +
- QLatin1Char(' ')).width();
- const int w = getFontMetrics(FT_BOLD).boundingRect(m_umlObject->stereotype(true)).width();
-
- width = w > width ? w : width;
-
- UMLClassifier* classifier = (UMLClassifier*)m_umlObject;
- UMLClassifierListItemList list = classifier->getFilteredList(UMLObject::ot_EntityAttribute);
- UMLClassifierListItem* listItem = 0;
- foreach (listItem, list) {
- int w = fm.width(listItem->name());
- width = w > width?w:width;
- }
-
- //allow for width margin
- width += ENTITY_MARGIN * 2;
-
- return QSizeF(width, height);
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/entitywidget.h umbrello-kf6-15.08.1/umbrello/widgets/entitywidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/entitywidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/entitywidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,49 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ENTITYWIDGET_H
-#define ENTITYWIDGET_H
-
-#include "umlwidget.h"
-
-class UMLScene;
-
-#define ENTITY_MARGIN 5
-
-/**
- * Defines a graphical version of the entity. Most of the functionality
- * will come from the @ref UMLWidget class from which class inherits from.
- *
- * @short A graphical version of an entity.
- * @author Jonathan Riddell
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class EntityWidget : public UMLWidget
-{
- Q_OBJECT
-public:
- explicit EntityWidget(UMLScene *scene, UMLObject* o);
- virtual ~EntityWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- // UMLWidget::loadFromXMI is used to load this widget.
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
-public Q_SLOTS:
- virtual void slotMenuSelection(QAction* action);
-
-protected:
- QSizeF minimumSize() const;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/enumwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/enumwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/enumwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/enumwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,262 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "enumwidget.h"
-
-// app includes
-#include "classifier.h"
-#include "classifierlistitem.h"
-#include "debug_utils.h"
-#include "enum.h"
-#include "enumliteral.h"
-#include "listpopupmenu.h"
-#include "object_factory.h"
-#include "uml.h"
-#include "umlclassifierlistitemlist.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-/**
- * Constructs an instance of EnumWidget.
- *
- * @param scene The parent of this EnumWidget.
- * @param o The UMLObject this will be representing.
- */
-EnumWidget::EnumWidget(UMLScene *scene, UMLObject* o)
- : UMLWidget(scene, WidgetBase::wt_Enum, o),
- m_showPackage(false)
-{
- setSize(100, 30);
- //set defaults from m_scene
- if (m_scene) {
- //check to see if correct
- const Settings::OptionState& ops = m_scene->optionState();
- m_showPackage = ops.classState.showPackage;
- } else {
- // For completeness only. Not supposed to happen.
- m_showPackage = false;
- }
-}
-
-/**
- * Destructor.
- */
-EnumWidget::~EnumWidget()
-{
-}
-
-/**
- * Returns the status of whether to show Package.
- *
- * @return True if package is shown.
- */
-bool EnumWidget::showPackage() const
-{
- return m_showPackage;
-}
-
-/**
- * Set the status of whether to show Package.
- *
- * @param _status True if package shall be shown.
- */
-void EnumWidget::setShowPackage(bool _status)
-{
- m_showPackage = _status;
- updateGeometry();
- update();
-}
-
-/**
- * Toggles the status of whether to show package.
- */
-void EnumWidget::toggleShowPackage()
-{
- m_showPackage = !m_showPackage;
- updateGeometry();
- update();
-}
-
-/**
- * Draws the enum as a rectangle with a box underneith with a list of literals
- * Reimplemented from UMLWidget::paint
- */
-void EnumWidget::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());
-
- const int w = width();
- const int h = height();
-
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- QString name;
- if (m_showPackage) {
- name = m_umlObject->fullyQualifiedName();
- } else {
- name = this->name();
- }
-
- painter->drawRect(0, 0, w, h);
- painter->setPen(textColor());
-
- QFont font = UMLWidget::font();
- font.setBold(true);
- painter->setFont(font);
- painter->drawText(ENUM_MARGIN, 0,
- w - ENUM_MARGIN * 2, fontHeight,
- Qt::AlignCenter, m_umlObject->stereotype(true));
-
- font.setItalic(m_umlObject->isAbstract());
- painter->setFont(font);
- painter->drawText(ENUM_MARGIN, fontHeight,
- w - ENUM_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
- font.setBold(false);
- font.setItalic(false);
- painter->setFont(font);
-
- int y = fontHeight * 2;
-
- setPenFromSettings(painter);
-
- painter->drawLine(0, y, w, y);
-
- QFontMetrics fontMetrics(font);
- UMLClassifier *classifier = (UMLClassifier*)m_umlObject;
- UMLClassifierListItem* enumLiteral = 0;
- UMLClassifierListItemList list = classifier->getFilteredList(UMLObject::ot_EnumLiteral);
- foreach (enumLiteral, list) {
- QString text = enumLiteral->name();
- painter->setPen(textColor());
- painter->drawText(ENUM_MARGIN, y,
- fontMetrics.width(text), fontHeight, Qt::AlignVCenter, text);
- y+=fontHeight;
- }
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Loads from an "enumwidget" XMI element.
- */
-bool EnumWidget::loadFromXMI(QDomElement & qElement)
-{
- if (!UMLWidget::loadFromXMI(qElement)) {
- return false;
- }
- QString showpackage = qElement.attribute(QLatin1String("showpackage"), QLatin1String("0"));
-
- m_showPackage = (bool)showpackage.toInt();
-
- return true;
-}
-
-/**
- * Saves to the "enumwidget" XMI element.
- */
-void EnumWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement conceptElement = qDoc.createElement(QLatin1String("enumwidget"));
- UMLWidget::saveToXMI(qDoc, conceptElement);
-
- conceptElement.setAttribute(QLatin1String("showpackage"), m_showPackage);
- 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 EnumWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- if (sel == ListPopupMenu::mt_EnumLiteral) {
- if (Object_Factory::createChildObject(static_cast<UMLClassifier*>(m_umlObject),
- UMLObject::ot_EnumLiteral)) {
- /* I don't know why it works without these calls:
- updateComponentSize();
- update();
- */
- UMLApp::app()->document()->setModified();
- }
- return;
- }
- UMLWidget::slotMenuSelection(action);
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF EnumWidget::minimumSize() const
-{
- if (!m_umlObject) {
- return UMLWidget::minimumSize();
- }
-
- int width, height;
- QFont font = UMLWidget::font();
- font.setItalic(false);
- font.setUnderline(false);
- font.setBold(false);
- const QFontMetrics fm(font);
-
- const int fontHeight = fm.lineSpacing();
-
- int lines = 1;//always have one line - for name
- lines++; //for the stereotype
-
- const int numberOfEnumLiterals = ((UMLEnum*)m_umlObject)->enumLiterals();
-
- height = width = 0;
- //set the height of the enum
-
- lines += numberOfEnumLiterals;
- if (numberOfEnumLiterals == 0) {
- height += fontHeight / 2; //no enum literals, so just add a bit of space
- }
-
- height += lines * fontHeight;
-
- //now set the width of the concept
- //set width to name to start with
- if (m_showPackage) {
- width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(m_umlObject->fullyQualifiedName()).width();
- } else {
- width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(name()).width();
- }
- int w = getFontMetrics(FT_BOLD).boundingRect(m_umlObject->stereotype(true)).width();
-
-
- width = w > width?w:width;
-
- UMLClassifier *classifier = (UMLClassifier*)m_umlObject;
- UMLClassifierListItemList list = classifier->getFilteredList(UMLObject::ot_EnumLiteral);
- UMLClassifierListItem* listItem = 0;
- foreach (listItem, list) {
- int w = fm.width(listItem->name());
- width = w > width?w:width;
- }
-
- //allow for width margin
- width += ENUM_MARGIN * 2;
-
- return QSizeF(width, height);
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/enumwidget.h umbrello-kf6-15.08.1/umbrello/widgets/enumwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/enumwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/enumwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,52 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef ENUMWIDGET_H
-#define ENUMWIDGET_H
-
-#include "umlwidget.h"
-
-#define ENUM_MARGIN 5
-
-/**
- * Defines a graphical version of the enum. Most of the functionality
- * will come from the @ref UMLWidget class from which class inherits from.
- *
- * @short A graphical version of an enum.
- * @author Jonathan Riddell
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class EnumWidget : public UMLWidget
-{
- Q_OBJECT
-public:
- explicit EnumWidget(UMLScene *scene, UMLObject* o);
- virtual ~EnumWidget();
-
- bool showPackage() const;
- void setShowPackage(bool _status);
- void toggleShowPackage();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- virtual bool loadFromXMI(QDomElement& qElement);
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
-public Q_SLOTS:
- virtual void slotMenuSelection(QAction* action);
-
-protected:
- QSizeF minimumSize() const;
-
- bool m_showPackage;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/floatingdashlinewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/floatingdashlinewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/floatingdashlinewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/floatingdashlinewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,199 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-// own header
-#include "floatingdashlinewidget.h"
-#include "combinedfragmentwidget.h"
-
-//kde includes
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-#include <KLocalizedString>
-
-//app includes
-#include "debug_utils.h"
-#include "umlview.h"
-#include "widget_utils.h"
-#include "listpopupmenu.h"
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-#include <QPainter>
-
-DEBUG_REGISTER_DISABLED(FloatingDashLineWidget)
-
-/**
- * Creates a floating dash line.
- * @param scene The parent of the widget
- * @param id The ID to assign (-1 will prompt a new ID)
- * @param parent The CombinedFragmentWidget which acts as the parent
- */
-FloatingDashLineWidget::FloatingDashLineWidget(UMLScene * scene, Uml::ID::Type id, CombinedFragmentWidget *parent)
- : UMLWidget(scene, WidgetBase::wt_FloatingDashLine, id),
- m_yMin(0),
- m_yMax(0),
- m_parent(parent)
-{
- m_resizable = false;
- m_Text = QString();
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- setSize(10, fontHeight);
-}
-
-/**
- * Destructor.
- */
-FloatingDashLineWidget::~FloatingDashLineWidget()
-{
- if (m_parent)
- m_parent->removeDashLine(this);
-}
-
-/**
- * Overrides the standard paint event.
- */
-void FloatingDashLineWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- painter->setPen(textColor());
- painter->setFont(UMLWidget::font());
- painter->drawText(FLOATING_DASH_LINE_TEXT_MARGIN, 0,
- width() - FLOATING_DASH_LINE_TEXT_MARGIN * 2, fontHeight,
- Qt::AlignLeft, QLatin1Char('[') + m_Text + QLatin1Char(']'));
- painter->setPen(QPen(UMLWidget::lineColor(), 0, Qt::DashLine));
- painter->drawLine(0, 0, width(), 0);
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Sets m_text.
- */
-void FloatingDashLineWidget::setText(const QString& text)
-{
- m_Text = text;
-}
-
-/**
- * Returns true if the given point is near the floatingdashline.
- */
-bool FloatingDashLineWidget::onLine(const QPointF& point)
-{
- // check if the given point is the start or end point of the line
- if (((abs((long)(y() + height() - point.y()))) <= POINT_DELTA) || (abs((long)(y() - point.y())) <= POINT_DELTA)) {
- return true;
- }
- // check if the given point is the start or end point of the line
- return false;
-}
-
-void FloatingDashLineWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_Rename:
- {
- bool ok = false;
- QString name = m_Text;
-#if QT_VERSION >= 0x050000
- name = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter alternative Name"), i18n("Enter the alternative:"),
- QLineEdit::Normal,
- m_Text, &ok);
-#else
- name = KInputDialog::getText(i18n("Enter alternative Name"), i18n("Enter the alternative:"), m_Text, &ok);
-#endif
- if (ok && name.length() > 0)
- m_Text = name;
- }
- break;
- default:
- UMLWidget::slotMenuSelection(action);
- }
-}
-
-/**
- * Overrides the setY method.
- */
-void FloatingDashLineWidget::setY(qreal y)
-{
- if(y >= m_yMin + FLOATING_DASH_LINE_MARGIN && y <= m_yMax - FLOATING_DASH_LINE_MARGIN)
- UMLWidget::setY(y);
-}
-
-/**
- * Sets m_yMin.
- */
-void FloatingDashLineWidget::setYMin(qreal yMin)
-{
- m_yMin = yMin;
-}
-
-/**
- * Sets m_yMax.
- */
-void FloatingDashLineWidget::setYMax(qreal yMax)
-{
- m_yMax = yMax;
-}
-
-/**
- * Returns m_yMin.
- */
-qreal FloatingDashLineWidget::getYMin() const
-{
- return m_yMin;
-}
-
-/**
- * Returns the difference between the y-coordinate of the dash line and m_yMin.
- */
-qreal FloatingDashLineWidget::getDiffY() const
-{
- return (y() - getYMin());
-}
-
-/**
- * Creates the "floatingdashline" XMI element.
- */
-void FloatingDashLineWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement textElement = qDoc.createElement(QLatin1String("floatingdashlinewidget"));
- UMLWidget::saveToXMI(qDoc, textElement);
- textElement.setAttribute(QLatin1String("text"), m_Text);
- textElement.setAttribute(QLatin1String("y"), y());
- textElement.setAttribute(QLatin1String("minY"), m_yMin);
- textElement.setAttribute(QLatin1String("maxY"), m_yMax);
-
- qElement.appendChild(textElement);
-}
-
-/**
- * Loads the "floatingdashline" XMI element.
- */
-bool FloatingDashLineWidget::loadFromXMI(QDomElement & qElement)
-{
- if(!UMLWidget::loadFromXMI(qElement)) {
- return false;
- }
- DEBUG(DBG_SRC) << "load.......";
- m_yMax = qElement.attribute(QLatin1String("maxY")).toFloat();
- m_yMin = qElement.attribute(QLatin1String("minY")).toFloat();
- m_Text = qElement.attribute(QLatin1String("text"));
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/floatingdashlinewidget.h umbrello-kf6-15.08.1/umbrello/widgets/floatingdashlinewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/floatingdashlinewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/floatingdashlinewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,77 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef FLOATINGDASHLINEWIDGET_H
-#define FLOATINGDASHLINEWIDGET_H
-
-#include "umlwidget.h"
-class CombinedFragmentWidget;
-
-#define FLOATING_DASH_LINE_MARGIN 25
-#define FLOATING_DASH_LINE_TEXT_MARGIN 5
-
-/* how many pixels a user could click around a point */
-#define POINT_DELTA 5
-
-/**
- * This class is used to draw dash lines for UML combined fragments. A FloatingDashLineWidget
- * belongs to one @ref CombinedFragmentWidget instance.
- *
- * The FloatingDashLineWidget class inherits from the @ref UMLWidget class.
- *
- * @short A dash line for UML combined fragments.
- * @author Thomas GALLINARI <tg8187@yahoo.fr>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class FloatingDashLineWidget : public UMLWidget
-{
- Q_OBJECT
-public:
- explicit FloatingDashLineWidget(UMLScene * scene, Uml::ID::Type id = Uml::ID::None, CombinedFragmentWidget *parent = 0);
- ~FloatingDashLineWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option = 0, QWidget *widget = 0);
-
- void slotMenuSelection(QAction* action);
-
- bool onLine(const QPointF& point);
-
- void setText(const QString& text);
-
- void setY(qreal y);
- void setYMin(qreal yMin);
- void setYMax(qreal yMax);
- qreal getYMin() const;
- qreal getDiffY() const;
-
- void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
- bool loadFromXMI(QDomElement & qElement);
-
-private:
- /**
- * Text associated to the dash line
- */
- QString m_text;
-
- /**
- * Minimum value of the Y-coordinate of the dash line
- * (= y-coordinate of the combined fragment)
- */
- int m_yMin;
-
- /**
- * Maximum value of the Y-coordinate of the dash line
- * (= y-coordinate of the combined fragment + height of the combined fragment)
- */
- int m_yMax;
- CombinedFragmentWidget *m_parent;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/floatingtextwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/floatingtextwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/floatingtextwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/floatingtextwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,854 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "floatingtextwidget.h"
-
-// local includes
-#include "association.h"
-#include "associationwidget.h"
-#include "associationpropertiesdialog.h"
-#include "classifier.h"
-#include "cmds.h"
-#include "debug_utils.h"
-#include "linkwidget.h"
-#include "classifierwidget.h"
-#include "listpopupmenu.h"
-#include "messagewidget.h"
-#include "model_utils.h"
-#include "object_factory.h"
-#include "operation.h"
-#include "selectoperationdialog.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlview.h"
-
-// kde includes
-#if QT_VERSION < 0x050000
-#include <kfontdialog.h>
-#include <kinputdialog.h>
-#endif
-#include <KLocalizedString>
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QFontDialog>
-#include <QInputDialog>
-#endif
-#include <QPointer>
-#include <QRegExp>
-#include <QPainter>
-#include <QValidator>
-
-DEBUG_REGISTER_DISABLED(FloatingTextWidget)
-
-/**
- * Constructs a FloatingTextWidget instance.
- *
- * @param scene The parent of this FloatingTextWidget.
- * @param role The role this FloatingTextWidget will take up.
- * @param text The main text to display.
- * @param id The ID to assign (-1 will prompt a new ID.)
- */
-FloatingTextWidget::FloatingTextWidget(UMLScene * scene, Uml::TextRole::Enum role, const QString& text, Uml::ID::Type id)
- : UMLWidget(scene, WidgetBase::wt_Text, id),
- m_linkWidget(0),
- m_preText(QString()),
- m_postText(QString()),
- m_textRole(role),
- m_unconstrainedPositionX(0),
- m_unconstrainedPositionY(0),
- m_movementDirectionX(0),
- m_movementDirectionY(0)
-{
- m_Text = text;
- m_resizable = false;
- setZValue(10); //make sure always on top.
-}
-
-/**
- * Destructor.
- */
-FloatingTextWidget::~FloatingTextWidget()
-{
-}
-
-/**
- * Use to get the _main body_ of text (e.g. prepended and appended
- * text is omitted) as currently displayed by the widget.
- *
- * @return The main text currently being displayed by the widget.
- */
-QString FloatingTextWidget::text() const
-{
- // test to make sure not just the ":" between the seq number and
- // the actual message widget
-
- // hmm. this section looks like it could have been avoided by
- // using pre-, post- text instead of storing in the main body of
- // the text -b.t.
- if (m_textRole == Uml::TextRole::Seq_Message || m_textRole == Uml::TextRole::Seq_Message_Self ||
- m_textRole == Uml::TextRole::Coll_Message || m_textRole == Uml::TextRole::Coll_Message_Self) {
- if (m_Text.length() <= 1 || m_Text == QLatin1String(": "))
- return QString();
- }
- return m_Text;
-}
-
-/**
- * Set the main body of text to display.
- *
- * @param t The text to display.
- */
-void FloatingTextWidget::setText(const QString &t)
-{
- if (m_textRole == Uml::TextRole::Seq_Message || m_textRole == Uml::TextRole::Seq_Message_Self) {
- QString op;
- if (m_linkWidget)
- op = m_linkWidget->lwOperationText();
- if (op.length() > 0) {
- if (!m_scene->showOpSig())
- op.replace(QRegExp(QLatin1String("\\(.*\\)")), QLatin1String("()"));
- m_Text = op;
- }
- else
- m_Text = t;
- }
- else {
- m_Text = t;
- }
-
- QSizeF s = minimumSize();
- setSize(s.width(), s.height());
-
- updateGeometry();
- update();
-}
-
-/**
- * Set some text to be prepended to the main body of text.
- * @param t The text to prepend to main body which is displayed.
- */
-void FloatingTextWidget::setPreText(const QString &t)
-{
- m_preText = t;
- updateGeometry();
- update();
-}
-
-/**
- * Set some text to be appended to the main body of text.
- * @param t The text to append to main body which is displayed.
- */
-void FloatingTextWidget::setPostText(const QString &t)
-{
- m_postText = t;
- updateGeometry();
- update();
-}
-
-/**
- * Use to get the total text (prepended + main body + appended)
- * currently displayed by the widget.
- *
- * @return The text currently being displayed by the widget.
- */
-QString FloatingTextWidget::displayText() const
-{
- QString displayText;
- if (!m_SequenceNumber.isEmpty())
- displayText = m_SequenceNumber + QLatin1String(": ") + m_Text;
- else
- displayText = m_Text;
- displayText.prepend(m_preText);
- displayText.append(m_postText);
- return displayText;
-}
-
-/**
- * Return state if no pre, post and main text is empty
- * @return true if widget contains no text
- */
-bool FloatingTextWidget::isEmpty()
-{
- return m_Text.isEmpty() && m_preText.isEmpty() && m_postText.isEmpty();
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF FloatingTextWidget::minimumSize() const
-{
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- int h = fm.lineSpacing();
- int w = fm.width(displayText());
- return QSizeF(w + 8, h + 4); // give a small margin
-}
-
-/**
- * Method used by setText: its called by cmdsetTxt, Don't use it!
- *
- * @param t The text to display.
- */
-void FloatingTextWidget::setTextcmd(const QString &t)
-{
- UMLApp::app()->executeCommand(new Uml::CmdSetTxt(this, t));
-}
-
-/**
- * Displays a dialog box to change the text.
- */
-void FloatingTextWidget::showChangeTextDialog()
-{
- bool ok = false;
-#if QT_VERSION >= 0x050000
- QString newText = QInputDialog::getText(m_scene->activeView(),
- i18n("Change Text"), i18n("Enter new text:"),
- QLineEdit::Normal,
- text(), &ok);
-#else
- QString newText = KInputDialog::getText(i18n("Change Text"), i18n("Enter new text:"), text(), &ok, m_scene->activeView());
-#endif
- if (ok && newText != text() && isTextValid(newText)) {
- setText(newText);
- setVisible(!text().isEmpty());
- updateGeometry();
- update();
- }
- if (!isTextValid(newText))
- hide();
-}
-
-/**
- * Shows an operation dialog box.
- *
- * @param enableAutoIncrement Enable auto increment checkbox
- */
-void FloatingTextWidget::showOperationDialog(bool enableAutoIncrement)
-{
- if (!m_linkWidget) {
- uError() << "m_linkWidget is NULL";
- return;
- }
- QString seqNum = m_linkWidget->sequenceNumber();
- UMLClassifier* c = m_linkWidget->lwClassifier();
- QString opText = m_linkWidget->lwOperationText();
- if (!c) {
- uError() << "m_linkWidget->lwClassifier() returns a NULL classifier";
- return;
- }
-
- QPointer<SelectOperationDialog> selectDialog = new SelectOperationDialog(m_scene->activeView(), c, enableAutoIncrement);
- if (enableAutoIncrement && m_scene->autoIncrementSequence()) {
- seqNum = m_scene->autoIncrementSequenceValue();
- selectDialog->setAutoIncrementSequence(true);
- }
- selectDialog->setSeqNumber(seqNum);
- if (m_linkWidget->operation() == 0) {
- selectDialog->setCustomOp(opText);
- } else {
- selectDialog->setClassOp(opText);
- }
- if (selectDialog->exec()) {
- seqNum = selectDialog->getSeqNumber();
- opText = selectDialog->getOpText();
- if (selectDialog->isClassOp()) {
- Model_Utils::OpDescriptor od;
- Model_Utils::Parse_Status st = Model_Utils::parseOperation(opText, od, c);
- if (st == Model_Utils::PS_OK) {
- UMLClassifierList selfAndAncestors = c->findSuperClassConcepts();
- selfAndAncestors.prepend(c);
- UMLOperation *op = 0;
- foreach (UMLClassifier *cl, selfAndAncestors) {
- op = cl->findOperation(od.m_name, od.m_args);
- if (op) {
- break;
- }
- }
- if (!op) {
- // The op does not yet exist. Create a new one.
- UMLObject *o = c->createOperation(od.m_name, 0, &od.m_args);
- op = static_cast<UMLOperation*>(o);
- }
- if (od.m_pReturnType) {
- op->setType(od.m_pReturnType);
- }
-
- m_linkWidget->setOperation(op);
- opText.clear();
- } else {
- m_linkWidget->setOperation(0);
- }
- } else {
- m_linkWidget->setOperation(0);
- }
- m_linkWidget->setSequenceNumber(seqNum);
- m_linkWidget->setOperationText(opText);
- if (enableAutoIncrement) {
- m_scene->setAutoIncrementSequence(selectDialog->autoIncrementSequence());
- }
- setMessageText();
- }
- delete selectDialog;
-}
-
-/**
- * Show the properties for a FloatingTextWidget.
- * Depending on the role of the floating text wiget, the options dialog
- * for the floating text widget, the rename dialog for floating text or
- * the options dialog for the link widget are shown.
- */
-void FloatingTextWidget::showPropertiesDialog()
-{
- if (m_textRole == Uml::TextRole::Coll_Message || m_textRole == Uml::TextRole::Coll_Message_Self ||
- m_textRole == Uml::TextRole::Seq_Message || m_textRole == Uml::TextRole::Seq_Message_Self) {
- showOperationDialog(false);
- } else if (m_textRole == Uml::TextRole::Floating) {
- // double clicking on a text line opens the dialog to change the text
- handleRename();
- } else if (m_linkWidget) {
- m_linkWidget->showPropertiesDialog();
- }
-}
-
-/**
- * Use to get the pre-text which is prepended to the main body of
- * text to be displayed.
- *
- * @return The pre-text currently displayed by the widget.
- */
-QString FloatingTextWidget::preText() const
-{
- return m_preText;
-}
-
-/**
- * Use to get the post-text which is appended to the main body of
- * text to be displayed.
- *
- * @return The post-text currently displayed by the widget.
- */
-QString FloatingTextWidget::postText() const
-{
- return m_postText;
-}
-
-/**
- * Activate the FloatingTextWidget after the saved data has been loaded
- *
- * @param ChangeLog Pointer to the IDChangeLog.
- * @return true for success
- */
-bool FloatingTextWidget::activate(IDChangeLog* ChangeLog /*= 0 */)
-{
- if (! UMLWidget::activate(ChangeLog))
- return false;
- update();
- return true;
-}
-
-/**
- * Set the LinkWidget that this FloatingTextWidget is related to.
- *
- * @param l The related LinkWidget.
- */
-void FloatingTextWidget::setLink(LinkWidget * l)
-{
- m_linkWidget = l;
-}
-
-/**
- * Returns the LinkWidget this floating text is related to.
- *
- * @return The LinkWidget this floating text is related to.
- */
-LinkWidget * FloatingTextWidget::link() const
-{
- return m_linkWidget;
-}
-
-/**
- * Sets the role type of this FloatingTextWidget.
- *
- * @param role The TextRole::Enum of this FloatingTextWidget.
- */
-void FloatingTextWidget::setTextRole(Uml::TextRole::Enum role)
-{
- m_textRole = role;
-}
-
-/**
- * Return the role of the text widget
- * @return The TextRole::Enum of this FloatingTextWidget.
- */
-Uml::TextRole::Enum FloatingTextWidget::textRole() const
-{
- return m_textRole;
-}
-
-/**
- * Handle the ListPopupMenu::mt_Rename case of the slotMenuSelection.
- * Given an own method because it requires rather lengthy code.
- */
-void FloatingTextWidget::handleRename()
-{
- QRegExpValidator v(QRegExp(QLatin1String(".*")), 0);
- QString t;
- if (m_textRole == Uml::TextRole::RoleAName || m_textRole == Uml::TextRole::RoleBName) {
- t = i18n("Enter role name:");
- } else if (m_textRole == Uml::TextRole::MultiA || m_textRole == Uml::TextRole::MultiB) {
- t = i18n("Enter multiplicity:");
- /*
- // NO! shouldn't be allowed
- } else if (m_textRole == Uml::TextRole::ChangeA || m_textRole == Uml::TextRole::ChangeB) {
- t = i18n("Enter changeability");
- */
- } else if (m_textRole == Uml::TextRole::Name) {
- t = i18n("Enter association name:");
- } else if (m_textRole == Uml::TextRole::Floating) {
- t = i18n("Enter new text:");
- } else {
- t = i18n("ERROR");
- }
- bool ok = false;
-#if QT_VERSION >= 0x050000
- QString newText = QInputDialog::getText(m_scene->activeView(),
- i18n("Rename"), t,
- QLineEdit::Normal,
- text(), &ok);
-#else
- QString newText = KInputDialog::getText(i18n("Rename"), t, text(), &ok, m_scene->activeView(), &v);
-#endif
- if (!ok || newText == text()) {
- return;
- }
-
- UMLApp::app()->executeCommand(new Uml::CmdHandleRename(this, newText));
-}
-
-/**
- * Changes the text of linked widget.
- * @param newText the new text
- */
-void FloatingTextWidget::changeName(const QString& newText)
-{
- if (m_linkWidget && !isTextValid(newText)) {
- AssociationWidget *assoc = dynamic_cast<AssociationWidget*>(m_linkWidget);
- if (assoc) {
- switch (m_textRole) {
- case Uml::TextRole::MultiA:
- assoc->setMultiplicity(QString(), Uml::RoleType::A);
- break;
- case Uml::TextRole::MultiB:
- assoc->setMultiplicity(QString(), Uml::RoleType::B);
- break;
- case Uml::TextRole::RoleAName:
- assoc->setRoleName(QString(), Uml::RoleType::A);
- break;
- case Uml::TextRole::RoleBName:
- assoc->setRoleName(QString(), Uml::RoleType::B);
- break;
- case Uml::TextRole::ChangeA:
- assoc->setChangeability(Uml::Changeability::Changeable, Uml::RoleType::A);
- break;
- case Uml::TextRole::ChangeB:
- assoc->setChangeability(Uml::Changeability::Changeable, Uml::RoleType::B);
- break;
- default:
- assoc->setName(QString());
- break;
- }
- }
- else {
- MessageWidget *msg = dynamic_cast<MessageWidget*>(m_linkWidget);
- if (msg) {
- msg->setName(QString());
- m_scene->removeWidget(this);
- }
- }
- return;
- }
-
- if (m_linkWidget && m_textRole != Uml::TextRole::Seq_Message
- && m_textRole != Uml::TextRole::Seq_Message_Self) {
- m_linkWidget->setText(this, newText);
- }
- else {
- setText(newText);
- UMLApp::app()->document()->setModified(true);
- }
-
- setVisible(true);
- updateGeometry();
- update();
-}
-
-/**
- * Write property of QString m_SequenceNumber.
- */
-void FloatingTextWidget::setSequenceNumber(const QString &sequenceNumber)
-{
- m_SequenceNumber = sequenceNumber;
-}
-
-/**
- * Read property of QString m_SequenceNumber.
- */
-QString FloatingTextWidget::sequenceNumber() const
-{
- return m_SequenceNumber;
-}
-
-/**
- * For a text to be valid it must be non-empty, i.e. have a length
- * larger than zero, and have at least one non whitespace character.
- *
- * @param text The string to analyze.
- * @return True if the given text is valid.
- */
-bool FloatingTextWidget::isTextValid(const QString &text)
-{
- int length = text.length();
- if(length < 1)
- return false;
- for(int i=0;i<length;i++) {
- if(!text.at(i).isSpace()) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Returns a constrained position for the widget after applying the position
- * difference.
- * If no link widget exists, the position returned is the current widget
- * position with the difference applied. If there's a link, the position
- * to be returned is constrained using constrainTextPos method from the
- * LinkWidget, if any.
- *
- * @param diffX The difference between current X position and new X position.
- * @param diffY The difference between current Y position and new Y position.
- * @return A QPointF with the constrained new position.
- */
-QPointF FloatingTextWidget::constrainPosition(qreal diffX, qreal diffY)
-{
- qreal newX = x() + diffX;
- qreal newY = y() + diffY;
-
- if (link()) {
- link()->constrainTextPos(newX, newY, width(), height(), textRole());
- }
-
- return QPointF(newX, newY);
-}
-
-/**
- * Overridden from UMLWidget.
- * Moves the widget to a new position using the difference between the
- * current position and the new position.
- * If the floating text widget is part of a sequence message, and the
- * message widget is selected, it does nothing: the message widget will
- * update the text position when it's moved.
- * In any other case, the floating text widget constrains its move using
- * constrainPosition. When the position of the floating text is constrained,
- * it's kept at that position until it can be moved to another valid
- * position (m_unconstrainedPositionX/Y and m_movementDirectionX/Y are
- * used for that).
- * Moreover, if is part of a sequence message (and the message widget
- * isn't selected), it updates the position of the message widget.
- * @see constrainPosition
- *
- * @param diffX The difference between current X position and new X position.
- * @param diffY The difference between current Y position and new Y position.
- */
-void FloatingTextWidget::moveWidgetBy(qreal diffX, qreal diffY)
-{
- if (textRole() == Uml::TextRole::Seq_Message_Self)
- return;
-
- if (textRole() == Uml::TextRole::Seq_Message
- && ((MessageWidget*)link())->isSelected()) {
- return;
- }
-
- m_unconstrainedPositionX += diffX;
- m_unconstrainedPositionY += diffY;
- QPointF constrainedPosition = constrainPosition(diffX, diffY);
-
- qreal newX = constrainedPosition.x();
- qreal newY = constrainedPosition.y();
-
- if (!m_movementDirectionX) {
- if (m_unconstrainedPositionX != constrainedPosition.x()) {
- m_movementDirectionX = (diffX > 0)? 1: -1;
- }
- } else if ((m_movementDirectionX < 0 && m_unconstrainedPositionX > x()) ||
- (m_movementDirectionX > 0 && m_unconstrainedPositionX < x()) ) {
- newX = m_unconstrainedPositionX;
- m_movementDirectionX = 0;
- }
-
- if (!m_movementDirectionY) {
- if (m_unconstrainedPositionY != constrainedPosition.y()) {
- m_movementDirectionY = (diffY > 0)? 1: -1;
- }
- } else if ((m_movementDirectionY < 0 && m_unconstrainedPositionY > y()) ||
- (m_movementDirectionY > 0 && m_unconstrainedPositionY < y()) ) {
- newY = m_unconstrainedPositionY;
- m_movementDirectionY = 0;
- }
-
- setX(newX);
- setY(newY);
-
- if (link()) {
- link()->calculateNameTextSegment();
- if (textRole() == Uml::TextRole::Seq_Message) {
- MessageWidget* messageWidget = (MessageWidget*)link();
- messageWidget->setY(newY + height());
- }
- }
-}
-
-/**
- * Overridden from UMLWidget.
- * Modifies the value of the diffX and diffY variables used to move the
- * widgets.
- * The values are constrained using constrainPosition.
- * @see constrainPosition
- *
- * @param diffX The difference between current X position and new X position.
- * @param diffY The difference between current Y position and new Y position.
- */
-void FloatingTextWidget::constrainMovementForAllWidgets(qreal &diffX, qreal &diffY)
-{
- QPointF constrainedPosition = constrainPosition(diffX, diffY);
-
- diffX = constrainedPosition.x() - x();
- diffY = constrainedPosition.y() - y();
-}
-
-/**
- * Override method from UMLWidget in order to additionally check widget parentage.
- *
- * @param p Point to be checked.
- *
- * @return 'this' if UMLWidget::onWidget(p) returns non NULL;
- * else NULL.
- */
-UMLWidget* FloatingTextWidget::onWidget(const QPointF &p)
-{
- WidgetBase *pw = dynamic_cast<WidgetBase*>(parentItem());
- if (pw == NULL) {
- return WidgetBase::onWidget(p);
- }
- const WidgetBase::WidgetType t = pw->baseType();
- bool isWidgetChild = false;
- if (t == WidgetBase::wt_Interface) {
- ClassifierWidget *cw = static_cast<ClassifierWidget*>(pw);
- isWidgetChild = cw->getDrawAsCircle();
- } else if (t == wt_Association ||
- t == WidgetBase::wt_Port || t == WidgetBase::wt_Pin) {
- isWidgetChild = true;
- }
- if (!isWidgetChild) {
- return WidgetBase::onWidget(p);
- }
- const qreal w = width();
- const qreal h = height();
- const qreal left = pw->x() + x();
- const qreal right = left + w;
- const qreal top = pw->y() + y();
- const qreal bottom = top + h;
- // uDebug() << "child_of_pw; p=(" << p.x() << "," << p.y() << "), "
- // << "x=" << left << ", y=" << top << ", w=" << w << ", h=" << h
- // << "; right=" << right << ", bottom=" << bottom;
- if (p.x() >= left && p.x() <= right &&
- p.y() >= top && p.y() <= bottom) { // Qt coord.sys. origin in top left corner
- // uDebug() << "floatingtext: " << m_Text;
- return this;
- }
- return NULL;
-}
-
-/**
- * Overrides default method
- */
-void FloatingTextWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- int w = width();
- int h = height();
- painter->setFont(UMLWidget::font());
- painter->setPen(textColor());
- painter->drawText(0, 0, w, h, Qt::AlignCenter, displayText());
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Loads the "floatingtext" XMI element.
- */
-bool FloatingTextWidget::loadFromXMI(QDomElement & qElement)
-{
- if(!UMLWidget::loadFromXMI(qElement))
- return false;
-
- m_unconstrainedPositionX = x();
- m_unconstrainedPositionY = y();
- QString role = qElement.attribute(QLatin1String("role"));
- if(!role.isEmpty())
- m_textRole = Uml::TextRole::fromInt(role.toInt());
-
- m_preText = qElement.attribute(QLatin1String("pretext"));
- m_postText = qElement.attribute(QLatin1String("posttext"));
- setText(qElement.attribute(QLatin1String("text"))); // use setText for geometry update
- // If all texts are empty then this is a useless widget.
- // In that case we return false.
- // CAVEAT: The caller should not interpret the false return value
- // as an indication of failure since previous umbrello-kf6 versions
- // saved lots of these empty FloatingTexts.
- bool usefulWidget = !isEmpty();
- return usefulWidget;
-}
-
-/**
- * Reimplemented from UMLWidget::saveToXMI to save the widget
- * data into XMI 'floatingtext' element.
- */
-void FloatingTextWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- if (isEmpty())
- return;
-
- QDomElement textElement = qDoc.createElement(QLatin1String("floatingtext"));
- UMLWidget::saveToXMI(qDoc, textElement);
- textElement.setAttribute(QLatin1String("text"), m_Text);
- textElement.setAttribute(QLatin1String("pretext"), m_preText);
- textElement.setAttribute(QLatin1String("posttext"), m_postText);
-
- /* No need to save these - the messagewidget already did it.
- m_Operation = qElement.attribute("operation");
- m_SeqNum = qElement.attribute("seqnum");
- */
-
- textElement.setAttribute(QLatin1String("role"), m_textRole);
- qElement.appendChild(textElement);
-}
-
-/**
- * Called when a menu selection has been made.
- *
- * @param action The action that has been selected.
- */
-void FloatingTextWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_Properties:
- showPropertiesDialog();
- break;
-
- case ListPopupMenu::mt_Delete:
- hide(); // This is only a workaround; if set then m_linkWidget should
- // really delete this FloatingTextWidget.
- update();
- m_scene->removeWidget(this);
- break;
-
- case ListPopupMenu::mt_New_Operation: // needed by AssociationWidget
- case ListPopupMenu::mt_Operation:
- {
- if (m_linkWidget == 0) {
- DEBUG(DBG_SRC) << "mt_Operation: m_linkWidget is NULL";
- return;
- }
- UMLClassifier* c = m_linkWidget->operationOwner();
- if (c == 0) {
- bool ok = false;
-#if QT_VERSION >= 0x050000
- QString opText = QInputDialog::getText(m_scene->activeView(),
- i18nc("operation name", "Name"),
- i18n("Enter operation name:"),
- QLineEdit::Normal,
- text(), &ok);
-#else
- QString opText = KInputDialog::getText(i18nc("operation name", "Name"),
- i18n("Enter operation name:"),
- text(), &ok, m_scene->activeView());
-#endif
- if (ok)
- m_linkWidget->setCustomOpText(opText);
- return;
- }
- UMLClassifierListItem* umlObj = Object_Factory::createChildObject(c, UMLObject::ot_Operation);
- if (umlObj) {
- UMLOperation* newOperation = static_cast<UMLOperation*>(umlObj);
- m_linkWidget->setOperation(newOperation);
- }
- }
- break;
-
- case ListPopupMenu::mt_Select_Operation:
- showOperationDialog(false);
- break;
-
- case ListPopupMenu::mt_Rename:
- handleRename();
- break;
-
- case ListPopupMenu::mt_Change_Font:
- {
-#if QT_VERSION >= 0x050000
- bool ok = false;
- QFont fnt = QFontDialog::getFont(&ok, font(), m_scene->activeView());
- if (ok) {
-#else
- QFont fnt = font();
- if(KFontDialog::getFont(fnt, KFontChooser::NoDisplayFlags, m_scene->activeView())) {
-#endif
- if(m_textRole == Uml::TextRole::Floating || m_textRole == Uml::TextRole::Seq_Message) {
- setFont(fnt);
- } else if (m_linkWidget) {
- m_linkWidget->lwSetFont(fnt);
- }
- }
- }
- break;
-
- case ListPopupMenu::mt_Reset_Label_Positions:
- if (m_linkWidget)
- m_linkWidget->resetTextPositions();
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- break;
- }//end switch
-}
-
-/**
- * Sets the text for this label if it is acting as a sequence diagram
- * message or a collaboration diagram message.
- */
-void FloatingTextWidget::setMessageText()
-{
- if (m_linkWidget) {
- m_linkWidget->setMessageText(this);
- QSizeF s = minimumSize();
- setSize(s.width(), s.height());
-
- }
- setVisible(!text().isEmpty());
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/floatingtextwidget.h umbrello-kf6-15.08.1/umbrello/widgets/floatingtextwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/floatingtextwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/floatingtextwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,131 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef FLOATINGTEXTWIDGET_H
-#define FLOATINGTEXTWIDGET_H
-
-#include "basictypes.h"
-#include "umlwidget.h"
-
-class LinkWidget;
-class UMLScene;
-
-/**
- * @short Displays a line of text or an operation.
- *
- * This is a multipurpose-kf6 class. In its simplest form it will display a
- * line of text.
- * It can also be setup to be the text for an operation with regard to the
- * @ref MessageWidget on the sequence diagram.
- * It is also used for the text required for an association.
- *
- * The differences between all these different uses will be the popup menu
- * that is associated with it.
- *
- * @author Paul Hensgen <phensgen@techie.com>
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class FloatingTextWidget : public UMLWidget
-{
- Q_OBJECT
-public:
- explicit FloatingTextWidget(UMLScene * scene, Uml::TextRole::Enum role = Uml::TextRole::Floating,
- const QString& text = QString(), Uml::ID::Type id = Uml::ID::None);
- virtual ~FloatingTextWidget();
-
- QString text() const;
- void setText(const QString &t);
-
- void setTextcmd(const QString &t);
-
- QString preText() const;
- void setPreText(const QString &t);
-
- QString postText() const;
- void setPostText(const QString &t);
-
- QString displayText() const;
-
- bool isEmpty();
-
- void showChangeTextDialog();
- void showOperationDialog(bool enableAutoIncrement = true);
- virtual void showPropertiesDialog();
-
- LinkWidget* link() const;
- void setLink(LinkWidget * l);
-
- bool activate(IDChangeLog* ChangeLog = 0);
-
- Uml::TextRole::Enum textRole() const;
- void setTextRole(Uml::TextRole::Enum role);
-
- void handleRename();
- void changeName(const QString& newText);
-
- void setSequenceNumber(const QString &sequenceNumber);
- QString sequenceNumber() const;
-
- static bool isTextValid(const QString &text);
-
- UMLWidget* onWidget(const QPointF& p);
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
- virtual bool loadFromXMI(QDomElement& qElement);
-
-public Q_SLOTS:
- virtual void slotMenuSelection(QAction* action);
- void setMessageText();
-
-protected:
- QSizeF minimumSize() const;
-
- virtual void moveWidgetBy(qreal diffX, qreal diffY);
- virtual void constrainMovementForAllWidgets(qreal &diffX, qreal &diffY);
-
-private:
- QPointF constrainPosition(qreal diffX, qreal diffY);
-
- /// The association or message widget we may be linked to.
- LinkWidget * m_linkWidget;
-
- //////////////////// Data loaded/saved:
-
- /// Prepended text (such as for scope of association Role or method)
- QString m_preText;
- /// Ending text (such as bracket on changability notation for association Role)
- QString m_postText;
- /// The role the text widget will enact.
- Uml::TextRole::Enum m_textRole;
-
- ////////
-
- /// The horizontal position the widget would have if its move wasn't constrained.
- qreal m_unconstrainedPositionX;
-
- /// The vertical position the widget would have if its move wasn't constrained.
- qreal m_unconstrainedPositionY;
-
- /// The X direction the widget was moved when the constrain was applied.
- /// -1 means left, 1 means right.
- int m_movementDirectionX;
-
- /// The Y direction the widget was moved when the constrain was applied.
- /// -1 means up, 1 means down.
- int m_movementDirectionY;
-
- /// Contains sequence number for sequence or collaboration diagram message.
- QString m_SequenceNumber;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/forkjoinwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/forkjoinwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/forkjoinwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/forkjoinwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,205 +0,0 @@
-/***************************************************************************
- * 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) 2005-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "forkjoinwidget.h"
-
-//app includes
-#include "debug_utils.h"
-#include "umlview.h"
-#include "umldoc.h"
-#include "listpopupmenu.h"
-
-// qt includes
-#include <QColorDialog>
-
-/**
- * Constructs a ForkJoinWidget.
- *
- * @param scene The parent to this widget.
- * @param ori Whether to draw the plate horizontally or vertically.
- * @param id The ID to assign (-1 will prompt a new ID.)
- */
-ForkJoinWidget::ForkJoinWidget(UMLScene * scene, Qt::Orientation ori, Uml::ID::Type id)
- : BoxWidget(scene, id, WidgetBase::wt_ForkJoin),
- m_orientation(ori)
-{
- setSize(10, 40);
- m_usesDiagramFillColor = false;
- setFillColorCmd(QColor("black"));
-}
-
-/**
- * Destructor.
- */
-ForkJoinWidget::~ForkJoinWidget()
-{
-}
-
-/**
- * Get whether to draw the plate vertically or horizontally.
- */
-Qt::Orientation ForkJoinWidget::orientation() const
-{
- return m_orientation;
-}
-
-/**
- * Set whether to draw the plate vertically or horizontally.
- */
-void ForkJoinWidget::setOrientation(Qt::Orientation ori)
-{
- m_orientation = ori;
- updateGeometry();
- UMLWidget::adjustAssocs(x(), y());
-}
-
-/**
- * Reimplemented from UMLWidget::paint to draw the plate of
- * fork join.
- */
-void ForkJoinWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- painter->fillRect(0, 0, width(), height(), fillColor());
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Reimplemented from UMLWidget::loadFromXMI to load widget
- * info from XMI element - 'forkjoin'.
- */
-bool ForkJoinWidget::loadFromXMI(QDomElement& qElement)
-{
- if (!UMLWidget::loadFromXMI(qElement)) {
- return false;
- }
-
- QString drawVerticalStr = qElement.attribute(QLatin1String("drawvertical"), QLatin1String("0"));
- bool drawVertical = (bool)drawVerticalStr.toInt();
- if (drawVertical) {
- setOrientation(Qt::Vertical);
- }
- else {
- setOrientation(Qt::Horizontal);
- }
-
- return true;
-}
-
-/**
- * Reimplemented from UMLWidget::saveToXMI to save widget info
- * into XMI element - 'forkjoin'.
- */
-void ForkJoinWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement fjElement = qDoc.createElement(QLatin1String("forkjoin"));
- UMLWidget::saveToXMI(qDoc, fjElement);
- bool drawVertical = true;
- if (m_orientation == Qt::Horizontal) {
- drawVertical = false;
- }
- fjElement.setAttribute(QLatin1String("drawvertical"), drawVertical);
- qElement.appendChild(fjElement);
-}
-
-/**
- * Show a properties dialog for a Fork/Join Widget.
- */
-void ForkJoinWidget::showPropertiesDialog()
-{
- QColor newColor = QColorDialog::getColor(fillColor()); // krazy:exclude=qclasses
- if (newColor != fillColor()) {
- setFillColor(newColor);
- setUsesDiagramFillColor(false);
- umlDoc()->setModified(true);
- }
-}
-
-/**
- * Reimplemented form UMLWidget::slotMenuSelection to handle
- * Flip action.
- */
-void ForkJoinWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch (sel) {
- case ListPopupMenu::mt_Fill_Color:
- showPropertiesDialog();
- break;
-
- case ListPopupMenu::mt_Flip:
- switch (m_orientation) {
- case Qt::Vertical:
- setOrientation(Qt::Horizontal);
- break;
- case Qt::Horizontal:
- default:
- setOrientation(Qt::Vertical);
- break;
- }
- break;
- default:
- break;
- }
-}
-
-/**
- * Overrides the function from UMLWidget.
- */
-QSizeF ForkJoinWidget::minimumSize() const
-{
- if (m_orientation == Qt::Vertical) {
- return QSizeF(4, 40);
- } else {
- return QSizeF(40, 4);
- }
-}
-
-/**
- * Reimplement method from UMLWidget to suppress the resize corner.
- * Although the ForkJoinWidget supports resizing, we suppress the
- * resize corner because it is too large for this very slim widget.
- */
-void ForkJoinWidget::paintSelected(QPainter * p, int offsetX, int offsetY)
-{
- Q_UNUSED(p);
- Q_UNUSED(offsetX);
- Q_UNUSED(offsetY);
-}
-
-/**
- * Reimplement method from UMLWidget.
- */
-void ForkJoinWidget::constrain(qreal& width, qreal& height)
-{
- if (m_orientation == Qt::Vertical) {
- if (width < 4)
- width = 4;
- else if (width > 10)
- width = 10;
- if (height < 40)
- height = 40;
- else if (height > 100)
- height = 100;
- } else {
- if (height < 4)
- height = 4;
- else if (height > 10)
- height = 10;
- if (width < 40)
- width = 40;
- else if (width > 100)
- width = 100;
- }
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/forkjoinwidget.h umbrello-kf6-15.08.1/umbrello/widgets/forkjoinwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/forkjoinwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/forkjoinwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,57 +0,0 @@
-/***************************************************************************
- * 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) 2005-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef FORKJOINWIDGET_H
-#define FORKJOINWIDGET_H
-
-//app includes
-#include "boxwidget.h"
-
-/**
- * @short Displays a fork/join plate in a state diagram.
- *
- * @author Oliver Kellogg <okellogg@users.sourceforge.net>
- *
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class ForkJoinWidget : public BoxWidget
-{
- Q_OBJECT
- Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
-public:
- explicit ForkJoinWidget(UMLScene * scene, Qt::Orientation ori = Qt::Horizontal, Uml::ID::Type id = Uml::ID::None);
- virtual ~ForkJoinWidget();
-
- Qt::Orientation orientation() const;
- void setOrientation(Qt::Orientation ori);
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- virtual bool loadFromXMI(QDomElement & qElement);
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
- void showPropertiesDialog();
-
-public Q_SLOTS:
- virtual void slotMenuSelection(QAction* action);
-
-protected:
- QSizeF minimumSize() const;
-
- virtual void paintSelected(QPainter * p, int offsetX = 0, int offsetY = 0);
-
- void constrain(qreal& width, qreal& height);
-
-private:
- Qt::Orientation m_orientation; ///< whether to draw the plate horizontally or vertically
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/layoutgrid.cpp umbrello-kf6-15.08.1/umbrello/widgets/layoutgrid.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/layoutgrid.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/layoutgrid.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,113 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Andi Fischer <andi.fischer@hispeed.ch> *
- * Copyright (C) 2012 by Ralf Habacker <ralf.habacker@freenet.de> *
- * *
- * This 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, or (at your option) *
- * any later version. *
- * *
- * This software is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR purpose-kf6. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this package; see the file COPYING. If not, write to *
- * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, *
- * Boston, MA 02110-1301, USA. *
- ***************************************************************************/
-
-#include "layoutgrid.h"
-
-#include "debug_utils.h"
-#include "umlscene.h"
-
-#include <QPainter>
-#include <QVarLengthArray>
-
-#define DBG_LOG() DEBUG(QLatin1String("LayoutGrid"))
-DEBUG_REGISTER_DISABLED(LayoutGrid)
-
-/**
- * Constructor.
- */
-LayoutGrid::LayoutGrid(UMLScene *scene)
- : m_scene(scene),
- m_gridSpacingX(25),
- m_gridSpacingY(25),
- m_gridDotColor(Qt::gray),
- m_isVisible(false)
-{
-}
-
-/**
- * Destructor.
- */
-LayoutGrid::~LayoutGrid()
-{
-}
-
-void LayoutGrid::paint(QPainter *painter, const QRectF &rect)
-{
- if (!isVisible())
- return;
-
- int gridSizeX = gridSpacingX();
- int gridSizeY = gridSpacingY();
-
- qreal left = int(rect.left()) - (int(rect.left()) % gridSizeX);
- qreal top = int(rect.top()) - (int(rect.top()) % gridSizeY);
-
- QVarLengthArray<QLineF, 200> lines;
-
- for (qreal x = left; x < rect.right(); x += gridSizeX)
- lines.append(QLineF(x, rect.top(), x, rect.bottom()));
- for (qreal y = top; y < rect.bottom(); y += gridSizeY)
- lines.append(QLineF(rect.left(), y, rect.right(), y));
-
- painter->setPen(m_gridDotColor);
- painter->drawLines(lines.data(), lines.size());
-}
-
-int LayoutGrid::gridSpacingX() const
-{
- return m_gridSpacingX;
-}
-
-int LayoutGrid::gridSpacingY() const
-{
- return m_gridSpacingY;
-}
-
-void LayoutGrid::setGridSpacing(int sizeX, int sizeY)
-{
- DBG_LOG() << "x = " << sizeX << " / y = " << sizeY;
- m_gridSpacingX= sizeX;
- m_gridSpacingY= sizeY;
-}
-
-const QColor& LayoutGrid::gridDotColor() const
-{
- return m_gridDotColor;
-}
-
-void LayoutGrid::setGridDotColor(const QColor& color)
-{
- DBG_LOG() << "color = " << color;
- m_gridDotColor = color;
-}
-
-bool LayoutGrid::isVisible() const
-{
- return m_isVisible;
-}
-
-void LayoutGrid::setVisible(bool visible)
-{
- if (m_isVisible != visible) {
- DBG_LOG() << "visible = " << visible;
- m_isVisible = visible;
- m_scene->update();
- }
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/layoutgrid.h umbrello-kf6-15.08.1/umbrello/widgets/layoutgrid.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/layoutgrid.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/layoutgrid.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,76 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Andi Fischer <andi.fischer@hispeed.ch> *
- * Copyright (C) 2012 by Ralf Habacker <ralf.habacker@freenet.de> *
- * *
- * This 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, or (at your option) *
- * any later version. *
- * *
- * This software is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR purpose-kf6. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this package; see the file COPYING. If not, write to *
- * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, *
- * Boston, MA 02110-1301, USA. *
- ***************************************************************************/
-
-#ifndef LAYOUTGRID_H
-#define LAYOUTGRID_H
-
-#include <QColor>
-#include <QFont>
-
-class UMLScene;
-class QRectF;
-
-/**
- * @author Andi Fischer
- * This class handles the layout grid, which is drawn in the background
- * of the scene. It is used only in UMLScene.
- */
-class LayoutGrid
-{
-public:
- explicit LayoutGrid(UMLScene *scene);
- ~LayoutGrid();
-
- void paint(QPainter *painter, const QRectF &rect);
-
- QRect gridRect() const;
- void setGridRect(const QRect& rect);
-
- int gridSpacingX() const;
- int gridSpacingY() const;
- void setGridSpacing(int sizeX, int sizeY);
-
- const QColor& gridDotColor() const;
- void setGridDotColor(const QColor& color);
-
- const QColor& gridCrossColor() const;
- void setGridCrossColor(const QColor& color);
-
- const QColor& textColor() const;
- void setTextColor(const QColor& color);
-
- QFont textFont() const;
- void setTextFont(const QFont& font);
-
- bool isVisible() const;
- void setVisible(bool visible);
-
- bool isTextVisible() const;
- void setTextVisible(bool visible);
-
-private:
- UMLScene *m_scene;
- int m_gridSpacingX;
- int m_gridSpacingY;
- QColor m_gridDotColor;
- bool m_isVisible;
-};
-
-#endif // LAYOUTGRID_H
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/linkwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/linkwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/linkwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/linkwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,121 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "linkwidget.h"
-
-// app includes
-#include "classifier.h"
-#include "operation.h"
-#include "uml.h"
-#include "umlobject.h"
-#include "umlview.h"
-
-LinkWidget::LinkWidget()
-{
-}
-
-LinkWidget::~LinkWidget()
-{
-}
-
-/**
- * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
- */
-UMLClassifier *LinkWidget::operationOwner()
-{
- UMLOperation *op = operation();
- if (op == NULL)
- return NULL;
- return static_cast<UMLClassifier*>(op->parent());
-}
-
-/**
- * Return the operation text.
- * When no scene parameter is given, the scene of the current view
- * is taken instead.
- * @param scene the given scene
- * @return the operation text
- */
-QString LinkWidget::operationText(UMLScene *scene)
-{
- UMLOperation *op = operation();
- if (op == NULL)
- return customOpText();
- if (scene == NULL)
- scene = UMLApp::app()->currentView()->umlScene();
- Uml::SignatureType::Enum sigType;
- if (scene && scene->showOpSig())
- sigType = Uml::SignatureType::SigNoVis;
- else
- sigType = Uml::SignatureType::NoSigNoVis;
- QString opText = op->toString(sigType);
- return opText;
-}
-
-/**
- * Motivated by FloatingTextWidget::slotMenuSelection(mt_Reset_Label_Positions)
- * Only applies to AssociationWidget.
- */
-void LinkWidget::resetTextPositions()
-{
-}
-
-/**
- * Motivated by FloatingTextWidget::mouseDoubleClickEvent()
- * Only applies to AssociationWidget.
- */
-void LinkWidget::showPropertiesDialog()
-{
-}
-
-/**
- * Motivated by FloatingTextWidget::setLink().
- * Only applies to AssociationWidget.
- */
-void LinkWidget::calculateNameTextSegment()
-{
-}
-
-
-/**
- * Write property of QString m_SequenceNumber.
- */
-void LinkWidget::setSequenceNumber(const QString &sequenceNumber)
-{
- m_SequenceNumber = sequenceNumber;
-}
-
-/**
- * Read property of QString m_SequenceNumber.
- */
-QString LinkWidget::sequenceNumber() const
-{
- return m_SequenceNumber;
-}
-
-/**
- * Load data from XMI.
- */
-bool LinkWidget::loadFromXMI(QDomElement &qElement)
-{
- m_SequenceNumber = qElement.attribute(QLatin1String("seqnum"));
- return true;
-}
-
-/**
- * Save data to XMI.
- */
-void LinkWidget::saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
-{
- Q_UNUSED(qDoc);
-
- qElement.setAttribute(QLatin1String("seqnum"), m_SequenceNumber);
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/linkwidget.h umbrello-kf6-15.08.1/umbrello/widgets/linkwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/linkwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/linkwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,123 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef LINKWIDGET_H
-#define LINKWIDGET_H
-
-#include "basictypes.h"
-#include "umlscene.h"
-
-#include <QFont>
-
-// forward declarations
-class UMLClassifier;
-class UMLOperation;
-class FloatingTextWidget;
-
-/**
- * This is an interface realized by AssociationWidget and MessageWidget.
- * The design of this interface was driven by the requirements of
- * class FloatingTextWidget. As the architecture of umbrello-kf6 evolves (for
- * example, if the class FloatingTextWidget is redesigned), it can be
- * cleaned up.
- *
- * @short Interface to FloatingTextWidget for AssociationWidget and MessageWidget.
- * @author Oliver Kellogg <okellogg@users.sourceforge.net>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class LinkWidget
-{
-public:
- LinkWidget();
- virtual ~LinkWidget();
-
- /**
- * Sets the font the widget is to use.
- * Abstract operation implemented by inheriting classes.
- * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
- *
- * @param font Font to be set.
- */
- virtual void lwSetFont(QFont font) = 0;
-
- virtual UMLClassifier *operationOwner();
-
- /**
- * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
- */
- virtual UMLOperation *operation() = 0;
-
- /**
- * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
- */
- virtual void setOperation(UMLOperation *op) = 0;
-
- /**
- * Motivated by getOperationText()
- */
- virtual QString customOpText() = 0;
-
- /**
- * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
- */
- virtual void setCustomOpText(const QString &opText) = 0;
-
- QString operationText(UMLScene *scene = 0);
-
- virtual void resetTextPositions();
-
- /**
- * Motivated by FloatingTextWidget::setMessageText()
- */
- virtual void setMessageText(FloatingTextWidget *ft) = 0;
-
- /**
- * Motivated by FloatingTextWidget::handleRename()
- */
- virtual void setText(FloatingTextWidget *ft, const QString &newText) = 0;
-
- virtual void showPropertiesDialog();
-
- /**
- * Motivated by FloatingTextWidget::showOpDialog()
- */
- virtual QString lwOperationText() = 0;
-
- /**
- * Motivated by FloatingTextWidget::showOpDialog()
- */
- virtual UMLClassifier *lwClassifier() = 0;
-
- /**
- * Motivated by FloatingTextWidget::showOpDialog()
- */
- virtual void setOperationText(const QString &op) = 0;
-
- /**
- * Abstract operation implemented by inheriting classes.
- * Motivated by FloatingTextWidget::mouseMoveEvent()
- */
- virtual void constrainTextPos(qreal &textX, qreal &textY,
- qreal textWidth, qreal textHeight,
- Uml::TextRole::Enum tr) = 0;
-
- virtual void calculateNameTextSegment();
-
- void setSequenceNumber(const QString &sequenceNumber);
- QString sequenceNumber() const;
-
- virtual bool loadFromXMI(QDomElement &qElement);
- virtual void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
-
-protected:
- QString m_SequenceNumber;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/messagewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/messagewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/messagewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/messagewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,1385 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// onw header
-#include "messagewidget.h"
-
-//app includes
-#include "classifier.h"
-#include "debug_utils.h"
-#include "floatingtextwidget.h"
-#include "listpopupmenu.h"
-#include "objectwidget.h"
-#include "operation.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlview.h"
-#include "uniqueid.h"
-#include "idchangelog.h"
-
-//qt includes
-#include <QMoveEvent>
-#include <QPainter>
-#include <QPolygon>
-#include <QResizeEvent>
-
-//kde includes
-#include <KLocalizedString>
-
-DEBUG_REGISTER_DISABLED(MessageWidget)
-
-static const int circleWidth = 10;
-
-/**
- * Constructs a MessageWidget.
- *
- * This method is used for creation, synchronous and synchronous message types.
- *
- * @param scene The parent to this class.
- * @param a The role A widget for this message.
- * @param b The role B widget for this message.
- * @param y The vertical position to display this message.
- * @param sequenceMessageType Whether synchronous or asynchronous
- * @param id A unique id used for deleting this object cleanly.
- * The default (-1) will prompt generation of a new ID.
- */
-MessageWidget::MessageWidget(UMLScene * scene, ObjectWidget* a, ObjectWidget* b,
- int y, Uml::SequenceMessage::Enum sequenceMessageType,
- Uml::ID::Type id /* = Uml::id_None */)
- : UMLWidget(scene, WidgetBase::wt_Message, id)
-{
- init();
- m_pOw[Uml::RoleType::A] = a;
- m_pOw[Uml::RoleType::B] = b;
- m_sequenceMessageType = sequenceMessageType;
- if (m_sequenceMessageType == Uml::SequenceMessage::Creation) {
- y -= m_pOw[Uml::RoleType::B]->height() / 2;
- m_pOw[Uml::RoleType::B]->setY(y);
- }
- updateResizability();
- calculateWidget();
- y = y < getMinY() ? getMinY() : y;
- y = y > getMaxY() ? getMaxY() : y;
- setY(y);
-
- this->activate();
-}
-
-/**
- * Constructs a MessageWidget.
- *
- * @param scene The parent to this class.
- * @param seqMsgType The Uml::SequenceMessage::Enum of this message widget
- * @param id The ID to assign (-1 will prompt a new ID.)
- */
-MessageWidget::MessageWidget(UMLScene * scene, Uml::SequenceMessage::Enum seqMsgType,
- Uml::ID::Type id)
- : UMLWidget(scene, WidgetBase::wt_Message, id)
-{
- init();
- m_sequenceMessageType = seqMsgType;
-}
-
-/**
- * Constructs a Lost or Found MessageWidget.
- *
- * @param scene The parent to this class.
- * @param a The role A widget for this message.
- * @param xclick The horizontal position clicked by the user
- * @param yclick The vertical position clicked by the user
- * @param sequenceMessageType Whether lost or found
- * @param id The ID to assign (-1 will prompt a new ID.)
- */
-MessageWidget::MessageWidget(UMLScene * scene, ObjectWidget* a, int xclick, int yclick,
- Uml::SequenceMessage::Enum sequenceMessageType,
- Uml::ID::Type id /*= Uml::id_None*/)
- : UMLWidget(scene, WidgetBase::wt_Message, id)
-{
- init();
- m_pOw[Uml::RoleType::A] = a;
- m_pOw[Uml::RoleType::B] = a;
-
- m_sequenceMessageType = sequenceMessageType;
-
- m_xclicked = xclick;
- m_yclicked = yclick;
-
- updateResizability();
- calculateWidget();
- yclick = yclick < getMinY() ? getMinY() : yclick;
- yclick = yclick > getMaxY() ? getMaxY() : yclick;
- setY(yclick);
- m_yclicked = yclick;
-
- this->activate();
-}
-
-/**
- * Initializes key variables of the class.
- */
-void MessageWidget::init()
-{
- m_xclicked = -1;
- m_yclicked = -1;
- m_ignoreSnapToGrid = true;
- m_ignoreSnapComponentSizeToGrid = true;
- m_pOw[Uml::RoleType::A] = m_pOw[Uml::RoleType::B] = NULL;
- m_pFText = NULL;
-}
-
-/**
- * Standard destructor.
- */
-MessageWidget::~MessageWidget()
-{
-}
-
-/**
- * Sets the y-coordinate.
- * Reimplemented from UMLWidget.
- *
- * @param y The y-coordinate to be set.
- */
-void MessageWidget::setY(qreal y)
-{
- if (y < getMinY()) {
- DEBUG(DBG_SRC) << "got out of bounds y position, check the reason" << this->y() << getMinY();
- return;
- }
-
- UMLWidget::setY(y);
- if (m_sequenceMessageType == Uml::SequenceMessage::Creation) {
- const qreal objWidgetHalfHeight = m_pOw[Uml::RoleType::B]->height() / 2;
- m_pOw[Uml::RoleType::B]->setY(y - objWidgetHalfHeight);
- }
-
- if (m_pFText && !UMLApp::app()->document()->loading()) {
- setTextPosition();
- emit sigMessageMoved();
- }
-}
-
-/**
- * Update the UMLWidget::m_resizable flag according to the
- * charactersitics of this message.
- */
-void MessageWidget::updateResizability()
-{
- if (m_sequenceMessageType == Uml::SequenceMessage::Synchronous)
- UMLWidget::m_resizable = true;
- else
- UMLWidget::m_resizable = false;
-}
-
-/**
- * Overridden from UMLWidget.
- * Returns the cursor to be shown when resizing the widget.
- * The cursor shown is KCursor::sizeVerCursor().
- *
- * @return The cursor to be shown when resizing the widget.
- */
-QCursor MessageWidget::resizeCursor() const
-{
- return Qt::SizeVerCursor;
-}
-
-/**
- * Overridden from UMLWidget.
- * Resizes the height of the message widget and emits the message moved signal.
- * Message widgets can only be resized vertically, so width isn't modified.
- *
- * @param newW The new width for the widget (isn't used).
- * @param newH The new height for the widget.
- */
-void MessageWidget::resizeWidget(qreal newW, qreal newH)
-{
- if (sequenceMessageType() == Uml::SequenceMessage::Creation)
- setSize(width(), newH);
- else {
- qreal x1 = m_pOw[Uml::RoleType::A]->x();
- qreal x2 = getxclicked();
- qreal diffX = 0;
- if (x1 < x2) {
- diffX = x2 + (newW - width());
- }
- else {
- diffX = x2 - (newW - width());
- }
- if (diffX <= 0 )
- diffX = 10;
- setxclicked (diffX);
- setSize(newW, newH);
- calculateWidget();
-
- }
- emit sigMessageMoved();
-}
-
-/**
- * Constrains the vertical position of the message widget so it doesn't go
- * upper than the bottom side of the lower object.
- * The height of the floating text widget in the message is taken in account
- * if there is any and isn't empty.
- *
- * @param diffY The difference between current Y position and new Y position.
- * @return The new Y position, constrained.
- */
-qreal MessageWidget::constrainPositionY(qreal diffY)
-{
- qreal newY = y() + diffY;
-
- qreal minY = getMinY();
- if (m_pFText && !m_pFText->displayText().isEmpty()) {
- minY += m_pFText->height();
- }
-
- if (newY < minY) {
- newY = minY;
- }
-
- return newY;
-}
-
-/**
- * Overridden from UMLWidget.
- * Moves the widget to a new position using the difference between the
- * current position and the new position. X position is ignored, and widget
- * is only moved along Y axis. If message goes upper than the object, it's
- * kept at this position until it should be lowered again (the unconstrained
- * Y position is saved to know when it's the time to lower it again).
- * If the message is a creation message, the object created is also moved to
- * the new vertical position.
- * @see constrainPositionY
- *
- * @param diffX The difference between current X position and new X position
- * (isn't used).
- * @param diffY The difference between current Y position and new Y position.
- */
-void MessageWidget::moveWidgetBy(qreal diffX, qreal diffY)
-{
- Q_UNUSED(diffX);
- qreal newY = constrainPositionY(diffY);
- setY(newY);
-}
-
-/**
- * Overridden from UMLWidget.
- * Modifies the value of the diffX and diffY variables used to move the widgets.
- * All the widgets are constrained to be moved only in Y axis (diffX is set to 0).
- * @see constrainPositionY
- *
- * @param diffX The difference between current X position and new X position.
- * @param diffY The difference between current Y position and new Y position.
- */
-void MessageWidget::constrainMovementForAllWidgets(qreal &diffX, qreal &diffY)
-{
- diffX = 0;
- diffY = constrainPositionY(diffY) - y();
-}
-
-/**
- * Reimplemented from UMLWidget and calls other paint...() methods
- * depending on the message type.
- */
-void MessageWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- if(!m_pOw[Uml::RoleType::A] || !m_pOw[Uml::RoleType::B]) {
- return;
- }
- setPenFromSettings(painter);
- if (m_sequenceMessageType == Uml::SequenceMessage::Synchronous) {
- paintSynchronous(painter, option);
- } else if (m_sequenceMessageType == Uml::SequenceMessage::Asynchronous) {
- paintAsynchronous(painter, option);
- } else if (m_sequenceMessageType == Uml::SequenceMessage::Creation) {
- paintCreation(painter, option);
- } else if (m_sequenceMessageType == Uml::SequenceMessage::Lost) {
- paintLost(painter, option);
- } else if (m_sequenceMessageType == Uml::SequenceMessage::Found) {
- paintFound(painter, option);
- } else {
- uWarning() << "Unknown message type";
- }
-}
-
-/**
- * Draw a solid-kf6 (triangular) arrowhead pointing in the given direction.
- * The direction can be either Qt::LeftArrow or Qt::RightArrow.
- */
-void MessageWidget::paintsolid-kf6Arrowhead(QPainter *p, int x, int y, Qt::ArrowType direction)
-{
- int arrowheadExtentX = 4;
- if (direction == Qt::RightArrow) {
- arrowheadExtentX = -arrowheadExtentX;
- }
- QPolygon points;
- points.putPoints(0, 3, x, y, x + arrowheadExtentX, y - 3, x + arrowheadExtentX, y + 3);
- p->setBrush(QBrush(p->pen().color()));
- p->drawPolygon(points);
-}
-
-/**
- * Draw an arrow pointing in the given direction.
- * The arrow head is not solid-kf6, i.e. it is made up of two lines
- * like so: --->
- * The direction can be either Qt::LeftArrow or Qt::RightArrow.
- */
-void MessageWidget::paintArrow(QPainter *p, int x, int y, int w,
- Qt::ArrowType direction, bool useDottedLine /* = false */)
-{
- if (w > 3) {
- int arrowheadStartX = x;
- int arrowheadExtentX = 4;
- if (direction == Qt::RightArrow) {
- arrowheadStartX += w;
- arrowheadExtentX = -arrowheadExtentX;
- }
- // draw upper half of arrowhead
- p->drawLine(arrowheadStartX, y, arrowheadStartX + arrowheadExtentX, y - 3);
- // draw lower half of arrowhead
- p->drawLine(arrowheadStartX, y, arrowheadStartX + arrowheadExtentX, y + 3);
- }
- // draw arrow line
- if (useDottedLine) {
- QPen pen = p->pen();
- pen.setStyle(Qt::DotLine);
- p->setPen(pen);
- }
- p->drawLine(x, y, x + w, y);
-}
-
-/**
- * Draws the calling arrow with filled in arrowhead, the
- * timeline box and the returning arrow with a dashed line and
- * stick arrowhead.
- */
-void MessageWidget::paintSynchronous(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- int x1 = m_pOw[Uml::RoleType::A]->x();
- int x2 = m_pOw[Uml::RoleType::B]->x();
- int w = width() - 1;
- int h = height();
- int offsetX = 0;
- int offsetY = 0;
-
- bool messageOverlaps = m_pOw[Uml::RoleType::A]->messageOverlap(y(), this);
- const int boxWidth = 17;
- const int wr = w < boxWidth ? w : boxWidth;
- const int arrowWidth = 4;
-
- if(isSelf()) {
- painter->fillRect(offsetX, offsetY, wr, h, QBrush(Qt::white)); //box
- painter->drawRect(offsetX, offsetY, wr, h); //box
- offsetX += wr;
- w -= wr;
- offsetY += 3;
- const int lowerLineY = offsetY + h - 6;
- // draw upper line segment (leaving the life line)
- painter->drawLine(offsetX, offsetY, offsetX + w, offsetY);
- // draw line segment parallel to (and at the right of) the life line
- painter->drawLine(offsetX + w, offsetY, offsetX + w, lowerLineY);
- // draw lower line segment (back to the life line)
- paintArrow(painter, offsetX, lowerLineY, w, Qt::LeftArrow);
- offsetX -= wr;
- offsetY -= 3;
- } else if(x1 < x2) {
- if (messageOverlaps) {
- offsetX += 8;
- w -= 8;
- }
- QPen pen = painter->pen();
- int startX = offsetX + w - wr + 1;
- painter->fillRect(startX, offsetY, wr, h, QBrush(Qt::white)); //box
- painter->drawRect(startX, offsetY, wr, h); //box
- painter->drawLine(offsetX, offsetY + arrowWidth, startX, offsetY + arrowWidth); //arrow line
- if (w > boxWidth + arrowWidth)
- paintsolid-kf6Arrowhead(painter, startX - 1, offsetY + arrowWidth, Qt::RightArrow);
- paintArrow(painter, offsetX, offsetY + h - arrowWidth + 1, w - wr + 1, Qt::LeftArrow, true); // return arrow
- if (messageOverlaps) {
- offsetX -= 8; //reset for drawSelected()
- }
- } else {
- if (messageOverlaps) {
- w -=8;
- }
- QPen pen = painter->pen();
- painter->fillRect(offsetX, offsetY, wr, h, QBrush(Qt::white)); //box
- painter->drawRect(offsetX, offsetY, wr, h); //box
- painter->drawLine(offsetX + wr + 1, offsetY + arrowWidth, offsetX + w, offsetY + arrowWidth); //arrow line
- if (w > boxWidth + arrowWidth)
- paintsolid-kf6Arrowhead(painter, offsetX + wr, offsetY + arrowWidth, Qt::LeftArrow);
- paintArrow(painter, offsetX + wr + 1, offsetY + h - arrowWidth + 1, w - wr - 1, Qt::RightArrow, true); // return arrow
- }
-
- UMLWidget::paint(painter, option);
-}
-
-/**
- * Draws a solid-kf6 arrow line and a stick arrow head.
- */
-void MessageWidget::paintAsynchronous(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- int x1 = m_pOw[Uml::RoleType::A]->x();
- int x2 = m_pOw[Uml::RoleType::B]->x();
- int w = width() - 1;
- int h = height() - 1;
- int offsetX = 0;
- int offsetY = 0;
- bool messageOverlapsA = m_pOw[Uml::RoleType::A]->messageOverlap(y(), this);
- //bool messageOverlapsB = m_pOw[Uml::RoleType::B]->messageOverlap(y(), this);
-
- if(isSelf()) {
- if (messageOverlapsA) {
- offsetX += 7;
- w -= 7;
- }
- const int lowerLineY = offsetY + h - 3;
- // draw upper line segment (leaving the life line)
- painter->drawLine(offsetX, offsetY, offsetX + w, offsetY);
- // draw line segment parallel to (and at the right of) the life line
- painter->drawLine(offsetX + w, offsetY, offsetX + w, lowerLineY);
- // draw lower line segment (back to the life line)
- paintArrow(painter, offsetX, lowerLineY, w, Qt::LeftArrow);
- if (messageOverlapsA) {
- offsetX -= 7; //reset for drawSelected()
- }
- } else if(x1 < x2) {
- if (messageOverlapsA) {
- offsetX += 7;
- w -= 7;
- }
- paintArrow(painter, offsetX, offsetY + 4, w, Qt::RightArrow);
- if (messageOverlapsA) {
- offsetX -= 7;
- }
- } else {
- if (messageOverlapsA) {
- w -= 7;
- }
- paintArrow(painter, offsetX, offsetY + 4, w, Qt::LeftArrow);
- }
-
- UMLWidget::paint(painter, option);
-}
-
-/**
- * Draws a solid-kf6 arrow line and a stick arrow head to the
- * edge of the target object widget instead of to the
- * sequence line.
- */
-void MessageWidget::paintCreation(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- int x1 = m_pOw[Uml::RoleType::A]->x();
- int x2 = m_pOw[Uml::RoleType::B]->x();
- int w = width();
- //int h = height() - 1;
- int offsetX = 0;
- int offsetY = 0;
- bool messageOverlapsA = m_pOw[Uml::RoleType::A]->messageOverlap(y(), this);
- //bool messageOverlapsB = m_pOw[Uml::RoleType::B]->messageOverlap(y(), this);
-
- const int lineY = offsetY + 4;
- if (x1 < x2) {
- if (messageOverlapsA) {
- offsetX += 7;
- w -= 7;
- }
- paintArrow(painter, offsetX, lineY, w, Qt::RightArrow);
- if (messageOverlapsA) {
- offsetX -= 7;
- }
- } else {
- if (messageOverlapsA) {
- w -= 7;
- }
- paintArrow(painter, offsetX, lineY, w, Qt::LeftArrow);
- }
-
- UMLWidget::paint(painter, option);
-}
-
-
-/**
- * Draws a solid-kf6 arrow line and a stick arrow head
- * and a circle
- */
-void MessageWidget::paintLost(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- int x1 = m_pOw[Uml::RoleType::A]->centerX();
- int x2 = m_xclicked;
- int w = width();
- int h = height();
- int offsetX = 0;
- int offsetY = 0;
- bool messageOverlapsA = m_pOw[Uml::RoleType::A]->messageOverlap(y(), this);
- //bool messageOverlapsB = m_pOw[Uml::RoleType::B]->messageOverlap(y(), this);
-
- if(x1 < x2) {
- if (messageOverlapsA) {
- offsetX += 7;
- w -= 7;
- }
-
- setPenFromSettings(painter);
- painter->setBrush(WidgetBase::lineColor());
- painter->drawEllipse(offsetX + w - h, offsetY, h, h);
- paintArrow(painter, offsetX, offsetY + h/2, w - h, Qt::RightArrow);
-
- if (messageOverlapsA) {
- offsetX -= 7;
- }
- } else {
- setPenFromSettings(painter);
- painter->setBrush(WidgetBase::lineColor());
- painter->drawEllipse(offsetX, offsetY, h, h);
- paintArrow(painter, offsetX + h, offsetY + h/2, w - h, Qt::LeftArrow);
- }
-
- UMLWidget::paint(painter, option);
-}
-
-/**
- * Draws a circle and a solid-kf6 arrow line and a stick arrow head.
- */
-void MessageWidget::paintFound(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- int x1 = m_pOw[Uml::RoleType::A]->centerX();
- int x2 = m_xclicked;
- int w = width();
- int h = height();
- int offsetX = 0;
- int offsetY = 0;
- bool messageOverlapsA = m_pOw[Uml::RoleType::A]->messageOverlap(y(), this);
- //bool messageOverlapsB = m_pOw[Uml::RoleType::B]->messageOverlap(y(), this);
-
- if(x1 < x2) {
- if (messageOverlapsA) {
- offsetX += 7;
- w -= 7;
- }
- setPenFromSettings(painter);
- painter->setBrush(WidgetBase::lineColor());
- painter->drawEllipse(offsetX + w - h, offsetY, h, h);
- paintArrow(painter, offsetX, offsetY + h/2, w, Qt::LeftArrow);
- if (messageOverlapsA) {
- offsetX -= 7;
- }
- } else {
- if (messageOverlapsA) {
- w -= 7;
- }
- setPenFromSettings(painter);
- painter->setBrush(WidgetBase::lineColor());
- painter->drawEllipse(offsetX, offsetY, h, h);
- paintArrow(painter, offsetX, offsetY + h/2, w, Qt::RightArrow);
- }
-
- UMLWidget::paint(painter, option);
-}
-
-/**
- * Overrides operation from UMLWidget.
- *
- * @param p Point to be checked.
- *
- * @return 'this' if the point is on a part of the MessageWidget.
- * NB In case of a synchronous message, the empty space
- * between call line and return line does not count, i.e. if
- * the point is located in that space the function returns NULL.
- */
-UMLWidget* MessageWidget::onWidget(const QPointF& p)
-{
- if (m_sequenceMessageType != Uml::SequenceMessage::Synchronous) {
- return UMLWidget::onWidget(p);
- }
- // Synchronous message:
- // Consists of top arrow (call) and bottom arrow (return.)
- if (p.x() < x() || p.x() > x() + width())
- return NULL;
- const int tolerance = 5; // pixels
- const int pY = p.y();
- const int topArrowY = y() + 3;
- const int bottomArrowY = y() + height() - 3;
- if (pY < topArrowY - tolerance || pY > bottomArrowY + tolerance)
- return NULL;
- if (height() <= 2 * tolerance)
- return this;
- if (pY > topArrowY + tolerance && pY < bottomArrowY - tolerance)
- return NULL;
- return this;
-}
-
-/**
- * Sets the text position relative to the sequence message.
- */
-void MessageWidget::setTextPosition()
-{
- if (m_pFText == NULL) {
- DEBUG(DBG_SRC) << "m_pFText is NULL";
- return;
- }
- if (m_pFText->displayText().isEmpty()) {
- return;
- }
- m_pFText->updateGeometry();
- int ftX = constrainX(m_pFText->x(), m_pFText->width(), m_pFText->textRole());
- int ftY = y() - m_pFText->height();
- m_pFText->setX(ftX);
- m_pFText->setY(ftY);
-}
-
-/**
- * Returns the textX arg with constraints applied.
- * Auxiliary to setTextPosition() and constrainTextPos().
- */
-int MessageWidget::constrainX(int textX, int textWidth, Uml::TextRole::Enum tr)
-{
- int result = textX;
- const int minTextX = x() + 5;
- if (textX < minTextX || tr == Uml::TextRole::Seq_Message_Self) {
- result = minTextX;
- } else {
- ObjectWidget *objectAtRight = NULL;
- if (m_pOw[Uml::RoleType::B]->x() > m_pOw[Uml::RoleType::A]->x())
- objectAtRight = m_pOw[Uml::RoleType::B];
- else
- objectAtRight = m_pOw[Uml::RoleType::A];
- const int objRight_seqLineX = objectAtRight->centerX();
- const int maxTextX = objRight_seqLineX - textWidth - 5;
- if (maxTextX <= minTextX)
- result = minTextX;
- else if (textX > maxTextX)
- result = maxTextX;
- }
- return result;
-}
-
-/**
- * Constrains the FloatingTextWidget X and Y values supplied.
- * Overrides operation from LinkWidget.
- *
- * @param textX candidate X value (may be modified by the constraint)
- * @param textY candidate Y value (may be modified by the constraint)
- * @param textWidth width of the text
- * @param textHeight height of the text
- * @param tr Uml::TextRole::Enum of the text
- */
-void MessageWidget::constrainTextPos(qreal &textX, qreal &textY, qreal textWidth, qreal textHeight,
- Uml::TextRole::Enum tr)
-{
- textX = constrainX(textX, textWidth, tr);
- // Constrain Y.
- const qreal minTextY = getMinY();
- const qreal maxTextY = getMaxY() - textHeight - 5;
- if (textY < minTextY)
- textY = minTextY;
- else if (textY > maxTextY)
- textY = maxTextY;
-// setY(textY + textHeight); // NB: side effect
-}
-
-/**
- * Shortcut for calling m_pFText->setLink() followed by
- * this->setTextPosition().
- */
-void MessageWidget::setLinkAndTextPos()
-{
- if (m_pFText) {
- m_pFText->setLink(this);
- setTextPosition();
- }
-}
-
-void MessageWidget::resizeEvent(QResizeEvent* /*re*/)
-{
-}
-
-/**
- * Calculate the geometry of the widget.
- */
-void MessageWidget::calculateWidget()
-{
- setMessageText(m_pFText);
- calculateDimensions();
- setVisible(true);
-}
-
-void MessageWidget::slotWidgetMoved(Uml::ID::Type id)
-{
- const Uml::ID::Type idA = m_pOw[Uml::RoleType::A]->localID();
- const Uml::ID::Type idB = m_pOw[Uml::RoleType::B]->localID();
- if (idA != id && idB != id) {
- DEBUG(DBG_SRC) << "id=" << Uml::ID::toString(id) << ": ignoring for idA=" << Uml::ID::toString(idA)
- << ", idB=" << Uml::ID::toString(idB);
- return;
- }
- qreal y = this->y();
- if (y < getMinY())
- y = getMinY();
- if (y > getMaxY())
- y = getMaxY();
- setPos(x(), y);
- calculateWidget();
- if(!m_pFText)
- return;
- if (m_scene->selectedCount(true) > 1)
- return;
- setTextPosition();
-}
-
-/**
- * Check to see if the given ObjectWidget is involved in the message.
- *
- * @param w The ObjectWidget to check for.
- * @return true - if is contained, false - not contained.
- */
-bool MessageWidget::hasObjectWidget(ObjectWidget * w)
-{
- if(m_pOw[Uml::RoleType::A] == w || m_pOw[Uml::RoleType::B] == w)
- return true;
- else
- return false;
-}
-
-/**
- * This method determines whether the message is for "Self" for
- * an ObjectWidget.
- *
- * @retval True If both ObjectWidgets for this widget exists and
- * are same.
- */
-bool MessageWidget::isSelf() const
-{
- return (m_pOw[Uml::RoleType::A] && m_pOw[Uml::RoleType::B] &&
- m_pOw[Uml::RoleType::A] == m_pOw[Uml::RoleType::B]);
-}
-
-void MessageWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- if (sel == ListPopupMenu::mt_Delete) {
- // This will clean up this widget and the text widget:
- m_scene->removeWidget(this);
- } else {
-
- UMLWidget::slotMenuSelection(action);
- }
-}
-
-/**
- * Activates a MessageWidget. Connects its m_pOw[] pointers
- * to UMLObjects and also send signals about its FloatingTextWidget.
- */
-bool MessageWidget::activate(IDChangeLog * /*Log = 0*/)
-{
- m_scene->resetPastep-kf6oint();
- // UMLWidget::activate(Log); CHECK: I don't think we need this ?
- if (m_pOw[Uml::RoleType::A] == NULL) {
- UMLWidget *pWA = m_scene->findWidget(m_widgetAId);
- if (pWA == NULL) {
- DEBUG(DBG_SRC) << "role A object " << Uml::ID::toString(m_widgetAId) << " not found";
- return false;
- }
- m_pOw[Uml::RoleType::A] = dynamic_cast<ObjectWidget*>(pWA);
- if (m_pOw[Uml::RoleType::A] == NULL) {
- DEBUG(DBG_SRC) << "role A widget " << Uml::ID::toString(m_widgetAId)
- << " is not an ObjectWidget";
- return false;
- }
- }
- if (m_pOw[Uml::RoleType::B] == NULL) {
- UMLWidget *pWB = m_scene->findWidget(m_widgetBId);
- if (pWB == NULL) {
- DEBUG(DBG_SRC) << "role B object " << Uml::ID::toString(m_widgetBId) << " not found";
- return false;
- }
- m_pOw[Uml::RoleType::B] = dynamic_cast<ObjectWidget*>(pWB);
- if (m_pOw[Uml::RoleType::B] == NULL) {
- DEBUG(DBG_SRC) << "role B widget " << Uml::ID::toString(m_widgetBId)
- << " is not an ObjectWidget";
- return false;
- }
- }
- updateResizability();
-
- UMLClassifier *c = dynamic_cast<UMLClassifier*>(m_pOw[Uml::RoleType::B]->umlObject());
- UMLOperation *op = NULL;
- if (c && !m_CustomOp.isEmpty()) {
- Uml::ID::Type opId = Uml::ID::fromString(m_CustomOp);
- op = dynamic_cast<UMLOperation*>(c->findChildObjectById(opId, true));
- if (op) {
- // If the UMLOperation is set, m_CustomOp isn't used anyway.
- // Just setting it empty for the sake of sanity.
- m_CustomOp.clear();
- }
- }
-
- if(!m_pFText) {
- Uml::TextRole::Enum tr = Uml::TextRole::Seq_Message;
- if (isSelf())
- tr = Uml::TextRole::Seq_Message_Self;
- m_pFText = new FloatingTextWidget(m_scene, tr, operationText(m_scene));
- m_scene->addFloatingTextWidget(m_pFText);
- m_pFText->setFontCmd(UMLWidget::font());
- }
- if (op)
- setOperation(op); // This requires a valid m_pFText.
- setLinkAndTextPos();
- m_pFText->setText(QString());
- m_pFText->setActivated();
- QString messageText = m_pFText->text();
- m_pFText->setVisible(messageText.length() > 1);
-
- connect(m_pOw[Uml::RoleType::A], SIGNAL(sigWidgetMoved(Uml::ID::Type)), this, SLOT(slotWidgetMoved(Uml::ID::Type)));
- connect(m_pOw[Uml::RoleType::B], SIGNAL(sigWidgetMoved(Uml::ID::Type)), this, SLOT(slotWidgetMoved(Uml::ID::Type)));
-
- connect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::RoleType::A], SLOT(slotMessageMoved()));
- connect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::RoleType::B], SLOT(slotMessageMoved()));
- m_pOw[Uml::RoleType::A]->messageAdded(this);
- if (!isSelf())
- m_pOw[Uml::RoleType::B]->messageAdded(this);
-
- // Calculate the size and position of the message widget
- calculateDimensions();
-
- // Position the floating text accordingly
- setTextPosition();
-
- emit sigMessageMoved();
- return true;
-}
-
-/**
- * Resolve references of this message so they reference the correct
- * new object widgets after paste.
- */
-void MessageWidget::resolveObjectWidget(IDChangeLog* log) {
- m_widgetAId = log->findNewID(m_widgetAId);
- m_widgetBId = log->findNewID(m_widgetBId);
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- *
- * @param ft The text widget which to update.
- */
-void MessageWidget::setMessageText(FloatingTextWidget *ft)
-{
- if (ft == NULL)
- return;
- ft->setSequenceNumber(m_SequenceNumber);
- ft->setText(operationText(m_scene));
- setTextPosition();
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- *
- * @param ft The text widget which to update.
- * @param newText The new text to set.
- */
-void MessageWidget::setText(FloatingTextWidget *ft, const QString &newText)
-{
- ft->setText(newText);
- UMLApp::app()->document()->setModified(true);
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- *
- * @param op The new operation string to set.
- */
-void MessageWidget::setOperationText(const QString &op)
-{
- m_CustomOp = op; ///FIXME m_pOperation
-}
-
-/**
- * Implements operation from LinkWidget.
- * Required by FloatingTextWidget.
- */
-void MessageWidget::lwSetFont (QFont font)
-{
- UMLWidget::setFont(font);
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- * @todo Move to LinkWidget.
- */
-UMLClassifier *MessageWidget::operationOwner()
-{
- UMLObject *pObject = m_pOw[Uml::RoleType::B]->umlObject();
- if (pObject == NULL)
- return NULL;
- UMLClassifier *c = dynamic_cast<UMLClassifier*>(pObject);
- return c;
-}
-
-/**
- * Implements operation from LinkWidget.
- * Motivated by FloatingTextWidget.
- */
-UMLOperation *MessageWidget::operation()
-{
- return static_cast<UMLOperation*>(m_umlObject);
-}
-
-/**
- * Implements operation from LinkWidget.
- * Motivated by FloatingTextWidget.
- */
-void MessageWidget::setOperation(UMLOperation *op)
-{
- if (m_umlObject && m_pFText)
- disconnect(m_umlObject, SIGNAL(modified()), m_pFText, SLOT(setMessageText()));
- m_umlObject = op;
- if (m_umlObject && m_pFText) {
- connect(m_umlObject, SIGNAL(modified()), m_pFText, SLOT(setMessageText()));
- m_pFText->setMessageText();
- }
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- */
-QString MessageWidget::customOpText()
-{
- return m_CustomOp;
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- */
-void MessageWidget::setCustomOpText(const QString &opText)
-{
- m_CustomOp = opText;
- m_pFText->setMessageText();
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- */
-QString MessageWidget::lwOperationText()
-{
- UMLOperation *pOperation = operation();
- if (pOperation != NULL) {
- return pOperation->toString(Uml::SignatureType::SigNoVis);
- } else {
- return customOpText();
- }
-}
-
-/**
- * Overrides operation from LinkWidget.
- * Required by FloatingTextWidget.
- */
-UMLClassifier *MessageWidget::lwClassifier()
-{
- UMLObject *o = m_pOw[Uml::RoleType::B]->umlObject();
- UMLClassifier *c = dynamic_cast<UMLClassifier*>(o);
- return c;
-}
-
-/**
- * Calculates the size of the widget by calling
- * calculateDimensionsSynchronous(),
- * calculateDimensionsAsynchronous(), or
- * calculateDimensionsCreation()
- */
-void MessageWidget::calculateDimensions()
-{
- if (m_sequenceMessageType == Uml::SequenceMessage::Synchronous) {
- calculateDimensionsSynchronous();
- } else if (m_sequenceMessageType == Uml::SequenceMessage::Asynchronous) {
- calculateDimensionsAsynchronous();
- } else if (m_sequenceMessageType == Uml::SequenceMessage::Creation) {
- calculateDimensionsCreation();
- } else if (m_sequenceMessageType == Uml::SequenceMessage::Lost) {
- calculateDimensionsLost();
- } else if (m_sequenceMessageType == Uml::SequenceMessage::Found) {
- calculateDimensionsFound();
- } else {
- uWarning() << "Unknown message type";
- }
- if (! UMLApp::app()->document()->loading()) {
- adjustAssocs(x(), y()); // adjust assoc lines
- }
-}
-
-/**
- * Calculates and sets the size of the widget for a synchronous message.
- */
-void MessageWidget::calculateDimensionsSynchronous()
-{
- int x = 0;
-
- int x1 = m_pOw[Uml::RoleType::A]->centerX();
- int x2 = m_pOw[Uml::RoleType::B]->centerX();
-
- int widgetWidth = 0;
- int widgetHeight = 0;
- if(isSelf()) {
- widgetWidth = 50;
- x = x1 - 2;
- } else if(x1 < x2) {
- x = x1;
- widgetWidth = x2 - x1 + 8;
- } else {
- x = x2 - 8;
- widgetWidth = x1 - x2 + 8;
- }
-
- if (height() < 20) {
- widgetHeight = 20;
- } else {
- widgetHeight = height();
- }
-
- setX(x);
- setSize(widgetWidth, widgetHeight);
-}
-
-/**
- * Calculates and sets the size of the widget for an asynchronous message.
- */
-void MessageWidget::calculateDimensionsAsynchronous()
-{
- int x = 0;
-
- int x1 = m_pOw[Uml::RoleType::A]->centerX();
- int x2 = m_pOw[Uml::RoleType::B]->centerX();
-
- int widgetWidth = 0;
- int widgetHeight = 8;
- if(isSelf()) {
- widgetWidth = 50;
- x = x1;
- if(height() < 20) {
- widgetHeight = 20;
- } else {
- widgetHeight = height();
- }
- } else if(x1 < x2) {
- x = x1;
- widgetWidth = x2 - x1;
- } else {
- x = x2;
- widgetWidth = x1 - x2;
- }
- x += 1;
- widgetWidth -= 2;
- setX(x);
- setSize(widgetWidth, widgetHeight);
-}
-
-/**
- * Calculates and sets the size of the widget for a creation message.
- */
-void MessageWidget::calculateDimensionsCreation()
-{
- int x = 0;
-
- int x1 = m_pOw[Uml::RoleType::A]->centerX();
- int x2 = m_pOw[Uml::RoleType::B]->x();
- int w2 = m_pOw[Uml::RoleType::B]->width();
-
- if (x1 > x2)
- x2 += w2;
-
- int widgetWidth = 0;
- int widgetHeight = 8;
- if (x1 < x2) {
- x = x1;
- widgetWidth = x2 - x1;
- } else {
- x = x2;
- widgetWidth = x1 - x2;
- }
- x += 1;
- widgetWidth -= 2;
- setPos(x, m_pOw[Uml::RoleType::B]->y() + m_pOw[Uml::RoleType::B]->height() / 2);
- setSize(widgetWidth, widgetHeight);
-}
-
-/**
- * Calculates and sets the size of the widget for a lost message.
- */
-void MessageWidget::calculateDimensionsLost()
-{
- int x = 0;
-
- int x1 = m_pOw[Uml::RoleType::A]->centerX();
- int x2 = m_xclicked;
-
- int widgetWidth = 0;
- int widgetHeight = 10;
- if(x1 < x2) {
- x = x1;
- widgetWidth = x2 - x1 + circleWidth/2;
- } else {
- x = x2 - circleWidth/2;
- widgetWidth = x1 - x2 + circleWidth/2;
- }
- setX(x);
- setSize(widgetWidth, widgetHeight);
-}
-
-/**
- * Calculates and sets the size of the widget for a found message.
- */
-void MessageWidget::calculateDimensionsFound()
-{
- int x = 0;
-
- int x1 = m_pOw[Uml::RoleType::A]->centerX();
- int x2 = m_xclicked;
-
- int widgetWidth = 0;
- int widgetHeight = 10;
- if(x1 < x2) {
- x = x1;
- widgetWidth = x2 - x1 + circleWidth/2;
- } else {
- x = x2 - circleWidth/2;
- widgetWidth = x1 - x2 + circleWidth/2;
- }
-
- setX(x);
- setSize(widgetWidth, widgetHeight);
-}
-
-/**
- * Used to cleanup any other widget it may need to delete.
- */
-void MessageWidget::cleanup()
-{
- if (m_pOw[Uml::RoleType::A]) {
- disconnect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::RoleType::A], SLOT(slotMessageMoved()));
- m_pOw[Uml::RoleType::A]->messageRemoved(this);
- }
- if (m_pOw[Uml::RoleType::B]) {
- disconnect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::RoleType::B], SLOT(slotMessageMoved()));
- m_pOw[Uml::RoleType::B]->messageRemoved(this);
- }
-
- UMLWidget::cleanup();
- if (m_pFText) {
- m_scene->removeWidgetCmd(m_pFText);
- m_pFText = NULL;
- }
-}
-
-/**
- * Sets the state of whether the widget is selected.
- *
- * @param _select True if the widget is selected.
- */
-void MessageWidget::setSelected(bool _select)
-{
- UMLWidget::setSelected(_select);
- if(!m_pFText || m_pFText->displayText().isEmpty())
- return;
- if(isSelected() && m_pFText->isSelected())
- return;
- if(!isSelected() && !m_pFText->isSelected())
- return;
-
- m_pFText->setSelected(isSelected());
-}
-
-/**
- * Returns the minimum height this widget should be set at on
- * a sequence diagrams. Takes into account the widget positions
- * it is related to.
- */
-int MessageWidget::getMinY()
-{
- if (!m_pOw[Uml::RoleType::A] || !m_pOw[Uml::RoleType::B]) {
- return 0;
- }
- if (m_sequenceMessageType == Uml::SequenceMessage::Creation) {
- return m_pOw[Uml::RoleType::A]->y() + m_pOw[Uml::RoleType::A]->height();
- }
- int heightA = m_pOw[Uml::RoleType::A]->y() + m_pOw[Uml::RoleType::A]->height();
- int heightB = m_pOw[Uml::RoleType::B]->y() + m_pOw[Uml::RoleType::B]->height();
- int height = heightA;
- if(heightA < heightB) {
- height = heightB;
- }
- return height;
-}
-
-/**
- * Returns the maximum height this widget should be set at on
- * a sequence diagrams. Takes into account the widget positions
- * it is related to.
- */
-int MessageWidget::getMaxY()
-{
- if(!m_pOw[Uml::RoleType::A] || !m_pOw[Uml::RoleType::B]) {
- return 0;
- }
- int heightA = (int)((ObjectWidget*)m_pOw[Uml::RoleType::A])->getEndLineY();
- int heightB = (int)((ObjectWidget*)m_pOw[Uml::RoleType::B])->getEndLineY();
- int height = heightA;
- if(heightA > heightB) {
- height = heightB;
- }
- return (height - this->height());
-}
-
-/**
- * Sets the related widget on the given side.
- *
- * @param ow The ObjectWidget we are related to.
- * @param role The Uml::RoleType::Enum to be set for the ObjectWidget
- */
-void MessageWidget::setObjectWidget(ObjectWidget * ow, Uml::RoleType::Enum role)
-{
- m_pOw[role] = ow;
- updateResizability();
-}
-
-/**
- * Returns the related widget on the given side.
- *
- * @return The ObjectWidget we are related to.
- */
-ObjectWidget* MessageWidget::objectWidget(Uml::RoleType::Enum role)
-{
- return m_pOw[role];
-}
-
-/**
- * Set the xclicked
- */
-void MessageWidget::setxclicked(int xclick)
-{
- m_xclicked = xclick;
-}
-
-/**
- * Set the yclicked
- */
-void MessageWidget::setyclicked(int yclick)
-{
- m_yclicked = yclick;
-}
-
-/**
- * Event handler for mouse double click events.
- * @param event QGraphicsSceneMouseEvent which triggered the double click event
- */
-void MessageWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
-{
- Q_UNUSED(event)
- DEBUG(DBG_SRC) << "NOT IMPLEMENTED YET!";
- if (m_pFText != NULL) {
- DEBUG(DBG_SRC) << "NOT IMPLEMENTED YET - on floating text widget!";
-// QAction* action = m_pMenu->getAction(ListPopupMenu::mt_Select_Operation);
-// m_pFText->slotMenuSelection(action);
- }
-}
-
-/**
- * Saves to the "messagewidget" XMI element.
- */
-void MessageWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement messageElement = qDoc.createElement(QLatin1String("messagewidget"));
- UMLWidget::saveToXMI(qDoc, messageElement);
- LinkWidget::saveToXMI(qDoc, messageElement);
- if (m_pOw[Uml::RoleType::A])
- messageElement.setAttribute(QLatin1String("widgetaid"), Uml::ID::toString(m_pOw[Uml::RoleType::A]->localID()));
- if (m_pOw[Uml::RoleType::B])
- messageElement.setAttribute(QLatin1String("widgetbid"), Uml::ID::toString(m_pOw[Uml::RoleType::B]->localID()));
- UMLOperation *pOperation = operation();
- if (pOperation)
- messageElement.setAttribute(QLatin1String("operation"), Uml::ID::toString(pOperation->id()));
- else
- messageElement.setAttribute(QLatin1String("operation"), m_CustomOp);
- messageElement.setAttribute(QLatin1String("sequencemessagetype"), m_sequenceMessageType);
- if (m_sequenceMessageType == Uml::SequenceMessage::Lost || m_sequenceMessageType == Uml::SequenceMessage::Found) {
- messageElement.setAttribute(QLatin1String("xclicked"), m_xclicked);
- messageElement.setAttribute(QLatin1String("yclicked"), m_yclicked);
- }
-
- // save the corresponding message text
- if (m_pFText && !m_pFText->text().isEmpty()) {
- messageElement.setAttribute(QLatin1String("textid"), Uml::ID::toString(m_pFText->id()));
- m_pFText->saveToXMI(qDoc, messageElement);
- }
-
- qElement.appendChild(messageElement);
-}
-
-/**
- * Loads from the "messagewidget" XMI element.
- */
-bool MessageWidget::loadFromXMI(QDomElement& qElement)
-{
- if (!UMLWidget::loadFromXMI(qElement)) {
- return false;
- }
- if (!LinkWidget::loadFromXMI(qElement)) {
- return false;
- }
- QString textid = qElement.attribute(QLatin1String("textid"), QLatin1String("-1"));
- QString widgetaid = qElement.attribute(QLatin1String("widgetaid"), QLatin1String("-1"));
- QString widgetbid = qElement.attribute(QLatin1String("widgetbid"), QLatin1String("-1"));
- m_CustomOp = qElement.attribute(QLatin1String("operation"));
- QString sequenceMessageType = qElement.attribute(QLatin1String("sequencemessagetype"), QLatin1String("1001"));
- m_sequenceMessageType = Uml::SequenceMessage::fromInt(sequenceMessageType.toInt());
- if (m_sequenceMessageType == Uml::SequenceMessage::Lost || m_sequenceMessageType == Uml::SequenceMessage::Found) {
- m_xclicked = qElement.attribute(QLatin1String("xclicked"), QLatin1String("-1")).toFloat();
- m_yclicked = qElement.attribute(QLatin1String("yclicked"), QLatin1String("-1")).toFloat();
- }
-
- m_widgetAId = Uml::ID::fromString(widgetaid);
- m_widgetBId = Uml::ID::fromString(widgetbid);
- m_textId = Uml::ID::fromString(textid);
-
- Uml::TextRole::Enum tr = Uml::TextRole::Seq_Message;
- if (m_widgetAId == m_widgetBId)
- tr = Uml::TextRole::Seq_Message_Self;
-
- //now load child elements
- QDomNode node = qElement.firstChild();
- QDomElement element = node.toElement();
- if (!element.isNull()) {
- QString tag = element.tagName();
- if (tag == QLatin1String("floatingtext") || tag == QLatin1String("UML::FloatingTextWidget")) {
- m_pFText = new FloatingTextWidget(m_scene, tr, operationText(m_scene), m_textId);
- m_scene->addFloatingTextWidget(m_pFText);
- if(! m_pFText->loadFromXMI(element)) {
- // Most likely cause: The FloatingTextWidget is empty.
- delete m_pFText;
- m_pFText = NULL;
- }
- else
- m_pFText->setSequenceNumber(m_SequenceNumber);
- } else {
- uError() << "unknown tag " << tag;
- }
- }
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/messagewidget.h umbrello-kf6-15.08.1/umbrello/widgets/messagewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/messagewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/messagewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,212 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef MESSAGEWIDGET_H
-#define MESSAGEWIDGET_H
-
-#include "umlwidget.h"
-#include "linkwidget.h"
-
-// forward declarations
-class FloatingTextWidget;
-class ObjectWidget;
-class QResizeEvent;
-class UMLOperation;
-
-/**
- * Used to display a message on a sequence diagram. The message
- * could be between two objects or a message that calls itself on
- * an object. This class will only display the line that is
- * required and the text will be setup by the @ref FloatingTextWidget
- * widget that is passed in the constructor. A message can be
- * synchronous (calls a method and gains control back on return,
- * as happens in most programming languages) or asynchronous
- * (calls a method and gains back control immediately).
- *
- * @short Displays a message.
- * @author Paul Hensgen
- * @see UMLWidget
- * @see ObjectWidget
- * @see FloatingTextWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class MessageWidget : public UMLWidget, public LinkWidget
-{
- Q_OBJECT
-public:
- MessageWidget(UMLScene * scene, ObjectWidget* a, ObjectWidget* b,
- int y, Uml::SequenceMessage::Enum sequenceMessageType,
- Uml::ID::Type id = Uml::ID::None);
- MessageWidget(UMLScene * scene, Uml::SequenceMessage::Enum sequenceMessageType,
- Uml::ID::Type id = Uml::ID::None);
- MessageWidget(UMLScene * scene, ObjectWidget* a, int xclick, int yclick,
- Uml::SequenceMessage::Enum sequenceMessageType,
- Uml::ID::Type id = Uml::ID::None);
- virtual ~MessageWidget();
-
- virtual void setY(qreal y);
-
- //---------- LinkWidget Interface methods implemementation from now on.
-
- virtual void lwSetFont (QFont font);
- virtual UMLClassifier *operationOwner();
-
- virtual UMLOperation *operation();
- virtual void setOperation(UMLOperation *op);
-
- virtual QString customOpText();
- virtual void setCustomOpText(const QString &opText);
-
- virtual void setMessageText(FloatingTextWidget *ft);
- virtual void setText(FloatingTextWidget *ft, const QString &newText);
-
- virtual QString lwOperationText();
- virtual UMLClassifier *lwClassifier();
- virtual void setOperationText(const QString &op);
-
- virtual void constrainTextPos(qreal &textX, qreal &textY, qreal textWidth, qreal textHeight,
- Uml::TextRole::Enum tr);
-
- //---------- End LinkWidget Interface methods implemementation.
-
- /// @return Whether the message is synchronous or asynchronous
- Uml::SequenceMessage::Enum sequenceMessageType() const {
- return m_sequenceMessageType;
- }
-
- bool hasObjectWidget(ObjectWidget * w);
-
- ObjectWidget* objectWidget(Uml::RoleType::Enum role);
- void setObjectWidget(ObjectWidget * ow, Uml::RoleType::Enum role) ;
-
- bool isSelf() const;
-
- /**
- * Returns the text widget it is related to.
- *
- * @return The text widget we are related to.
- */
- FloatingTextWidget * floatingTextWidget() {
- return m_pFText;
- }
-
- /**
- * Sets the text widget it is related to.
- *
- * @param f The text widget we are related to.
- */
- void setFloatingTextWidget(FloatingTextWidget * f) {
- m_pFText = f;
- }
-
- void calculateWidget();
-
- virtual bool activate(IDChangeLog * Log = 0);
- void resolveObjectWidget(IDChangeLog* log);
-
- void calculateDimensions();
- void calculateDimensionsSynchronous();
- void calculateDimensionsAsynchronous();
- void calculateDimensionsCreation();
- void calculateDimensionsLost();
- void calculateDimensionsFound();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- void setTextPosition();
-
- void cleanup();
-
- void setSelected(bool _select);
-
- int getMinY();
- int getMaxY();
-
- UMLWidget* onWidget(const QPointF& p);
-
- virtual void resizeWidget(qreal newW, qreal newH);
-
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
- virtual bool loadFromXMI(QDomElement & qElement);
-
- void setxclicked(int xclick);
- void setyclicked(int yclick);
-
- /**
- * Return the xclicked
- */
- int getxclicked() const {
- return m_xclicked;
- }
-
-protected:
- virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
-
- virtual void moveWidgetBy(qreal diffX, qreal diffY);
- virtual void constrainMovementForAllWidgets(qreal &diffX, qreal &diffY);
-
- virtual QCursor resizeCursor() const;
-
- void setLinkAndTextPos();
-
- int constrainX(int textX, int textWidth, Uml::TextRole::Enum tr);
-
- static void paintArrow(QPainter *p, int x, int y, int w,
- Qt::ArrowType direction, bool useDottedLine = false);
- static void paintsolid-kf6Arrowhead(QPainter *p, int x, int y, Qt::ArrowType direction);
-
- void updateResizability();
-
- void paintSynchronous(QPainter *painter, const QStyleOptionGraphicsItem *option);
- void paintAsynchronous(QPainter *painter, const QStyleOptionGraphicsItem *option);
- void paintCreation(QPainter *painter, const QStyleOptionGraphicsItem *option);
- void paintLost(QPainter *painter, const QStyleOptionGraphicsItem *option);
- void paintFound(QPainter *painter, const QStyleOptionGraphicsItem *option);
-
- // Data loaded/saved
- QString m_CustomOp;
- /**
- * Whether the message is synchronous or asynchronous
- */
- Uml::SequenceMessage::Enum m_sequenceMessageType;
-
-private:
- void resizeEvent(QResizeEvent *re);
-
- qreal constrainPositionY(qreal diffY);
-
- void init();
-
- ObjectWidget * m_pOw[2];
- FloatingTextWidget * m_pFText;
-
- int m_xclicked;
- int m_yclicked;
-
- /**
- * The following variables are used by loadFromXMI() as an intermediate
- * store. activate() resolves the IDs, i.e. after activate() the variables
- * m_pOw[] and m_pFText can be used.
- */
- Uml::ID::Type m_widgetAId, m_widgetBId, m_textId;
-
-public slots:
- void slotWidgetMoved(Uml::ID::Type id);
- void slotMenuSelection(QAction* action);
-
-signals:
- /**
- * emitted when the message widget is moved up or down
- * slots into ObjectWidget::slotMessageMoved()
- */
- void sigMessageMoved();
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/nodewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/nodewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/nodewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/nodewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,156 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "nodewidget.h"
-
-// app includes
-#include "debug_utils.h"
-#include "node.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-// qt includes
-#include <QPainter>
-#include <QPolygon>
-
-DEBUG_REGISTER_DISABLED(NodeWidget)
-
-/**
- * Constructs a NodeWidget.
- *
- * @param scene The parent of this NodeWidget.
- * @param n The UMLNode this will be representing.
- */
-NodeWidget::NodeWidget(UMLScene * scene, UMLNode *n)
- : UMLWidget(scene, WidgetBase::wt_Node, n)
-{
- setSize(100, 30);
- setZValue(1); // above box but below UMLWidget because may embed widgets
-}
-
-/**
- * Destructor.
- */
-NodeWidget::~NodeWidget()
-{
-}
-
-/**
- * Overrides standard method.
- */
-void NodeWidget::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());
- }
- const int w = width();
- const int h = height();
- const int wDepth = (w/3 > DEPTH ? DEPTH : w/3);
- const int hDepth = (h/3 > DEPTH ? DEPTH : h/3);
- const int bodyOffsetY = hDepth;
- const int bodyWidth = w - wDepth;
- const int bodyHeight = h - hDepth;
- QFont font = UMLWidget::font();
- font.setBold(true);
- const QFontMetrics &fm = getFontMetrics(FT_BOLD);
- const int fontHeight = fm.lineSpacing();
- QString nameStr = name();
-
- QPolygon pointArray(5);
- pointArray.setPoint(0, 0, bodyOffsetY);
- pointArray.setPoint(1, wDepth, 0);
- pointArray.setPoint(2, w, 0);
- pointArray.setPoint(3, w, bodyHeight);
- pointArray.setPoint(4, bodyWidth, h);
- painter->drawPolygon(pointArray);
- painter->drawRect(0, bodyOffsetY, bodyWidth, bodyHeight);
- painter->drawLine(w, 0, bodyWidth, bodyOffsetY);
-
- painter->setPen(textColor());
- painter->setFont(font);
-
- int lines = 1;
- if (m_umlObject) {
- QString stereotype = m_umlObject->stereotype();
- if (!stereotype.isEmpty()) {
- painter->drawText(0, bodyOffsetY + (bodyHeight/2) - fontHeight,
- bodyWidth, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true));
- lines = 2;
- }
- }
-
- if (UMLWidget::isInstance()) {
- font.setUnderline(true);
- painter->setFont(font);
- nameStr = UMLWidget::instanceName() + QLatin1String(" : ") + nameStr;
- }
-
- if (lines == 1) {
- painter->drawText(0, bodyOffsetY + (bodyHeight/2) - (fontHeight/2),
- bodyWidth, fontHeight, Qt::AlignCenter, nameStr);
- } else {
- painter->drawText(0, bodyOffsetY + (bodyHeight/2),
- bodyWidth, fontHeight, Qt::AlignCenter, nameStr);
- }
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF NodeWidget::minimumSize() const
-{
- if (m_umlObject == NULL) {
- DEBUG(DBG_SRC) << "m_umlObject is NULL";
- return UMLWidget::minimumSize();
- }
-
- const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
- const int fontHeight = fm.lineSpacing();
-
- QString name = m_umlObject->name();
- if (UMLWidget::isInstance()) {
- name = UMLWidget::instanceName() + QLatin1String(" : ") + name;
- }
-
- int width = fm.width(name) + 2 * defaultMargin;
-
- int tempWidth = 0;
- if (!m_umlObject->stereotype().isEmpty()) {
- tempWidth = fm.width(m_umlObject->stereotype(true));
- }
- if (tempWidth > width)
- width = tempWidth;
- width += DEPTH;
-
- int height = (2*fontHeight) + DEPTH;
-
- return QSizeF(width, height);
-}
-
-/**
- * Saves to the "nodewidget" XMI element.
- * Note: For loading we use the method inherited from UMLWidget.
- */
-void NodeWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement conceptElement = qDoc.createElement(QLatin1String("nodewidget"));
- UMLWidget::saveToXMI(qDoc, conceptElement);
- qElement.appendChild(conceptElement);
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/nodewidget.h umbrello-kf6-15.08.1/umbrello/widgets/nodewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/nodewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/nodewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,44 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef NODEWIDGET_H
-#define NODEWIDGET_H
-
-#include "umlwidget.h"
-
-class UMLNode;
-
-/**
- * Defines a graphical version of the Node. Most of the functionality
- * will come from the @ref UMLNode class.
- *
- * @short A graphical version of a Node.
- * @author Jonathan Riddell
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class NodeWidget : public UMLWidget
-{
-public:
-
- NodeWidget(UMLScene * scene, UMLNode *n);
- virtual ~NodeWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
-protected:
- QSizeF minimumSize() const;
-
- static const int DEPTH = 30; ///< pixels on Z axis
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/notewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/notewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/notewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/notewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,517 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "notewidget.h"
-
-// app includes
-#include "debug_utils.h"
-#include "docwindow.h"
-#include "listpopupmenu.h"
-#include "notedialog.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-// kde includes
-#include <KLocalizedString>
-#if QT_VERSION < 0x050000
-#include <kcolordialog.h>
-#include <kinputdialog.h>
-#endif
-
-// qt includes
-#include <QPainter>
-#if QT_VERSION >= 0x050000
-#include <QColorDialog>
-#include <QInputDialog>
-#endif
-
-NoteWidget * NoteWidget::s_pCurrentNote;
-
-/**
- * Constructs a NoteWidget.
- *
- * @param scene The parent to this widget.
- * @param noteType The NoteWidget::NoteType of this NoteWidget
- * @param id The unique id of the widget.
- * The default (-1) will prompt a new ID.
- */
-NoteWidget::NoteWidget(UMLScene * scene, NoteType noteType , Uml::ID::Type id)
- : UMLWidget(scene, WidgetBase::wt_Note, id),
- m_diagramLink(Uml::ID::None),
- m_noteType(noteType)
-{
- setZValue(20); //make sure always on top.
-}
-
-/**
- * Destructor.
- */
-NoteWidget::~NoteWidget()
-{
-}
-
-/**
- * Override default method.
- */
-void NoteWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- const int margin = 10;
- int w = width();
- int h = height();
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- QPolygon poly(6);
- poly.setPoint(0, 0, 0);
- poly.setPoint(1, 0, h);
- poly.setPoint(2, w, h);
- poly.setPoint(3, w, margin);
- poly.setPoint(4, w - margin, 0);
- poly.setPoint(5, 0, 0);
-
- setPenFromSettings(painter);
- if (UMLWidget::useFillColor()) {
- QBrush brush(UMLWidget::fillColor());
- painter->setBrush(brush);
- painter->drawPolygon(poly);
- } else
- painter->drawPolyline(poly);
- painter->drawLine(w - margin, 0, w - margin, margin);
- painter->drawLine(w - margin, margin, w, margin);
- painter->setPen(textColor());
- switch(m_noteType) {
- case NoteWidget::PreCondition :
- painter->drawText(0, margin, w, fontHeight, Qt::AlignCenter, QLatin1String("<< precondition >>"));
- break;
- case NoteWidget::PostCondition :
- painter->drawText(0, margin, w, fontHeight, Qt::AlignCenter, QLatin1String("<< postcondition >>"));
- break;
- case NoteWidget::Transformation :
- painter->drawText(0, margin, w, fontHeight, Qt::AlignCenter, QLatin1String("<< transformation >>"));
- break;
- case NoteWidget::Normal :
- default :
- break;
- }
-
- UMLWidget::paint(painter, option, widget);
-
-// paintText(&p, 0, 0);
- paintTextWordWrap(painter);
-}
-
-/**
- * Returns the type of note.
- */
-NoteWidget::NoteType NoteWidget::noteType() const
-{
- return m_noteType;
-}
-
-/**
- * Converts a string to NoteWidget::NoteType.
- */
-NoteWidget::NoteType NoteWidget::stringToNoteType(const QString& noteType)
-{
- if (noteType == QLatin1String("Precondition"))
- return NoteWidget::PreCondition;
- else if (noteType == QLatin1String("Postcondition"))
- return NoteWidget::PostCondition;
- else if (noteType == QLatin1String("Transformation"))
- return NoteWidget::Transformation;
- else
- return NoteWidget::Normal;
-}
-
-/**
- * Sets the type of note.
- */
-void NoteWidget::setNoteType(NoteType noteType)
-{
- m_noteType = noteType;
-}
-
-/**
- * Sets the type of note.
- */
-void NoteWidget::setNoteType(const QString& noteType)
-{
- setNoteType(stringToNoteType(noteType));
-}
-
-/**
- * Return the ID of the diagram hyperlinked to this note.
- *
- * @return ID of an UMLView, or Uml::ID::None if no
- * hyperlink is set.
- */
-Uml::ID::Type NoteWidget::diagramLink() const
-{
- return m_diagramLink;
-}
-
-/**
- * Set the ID of the diagram hyperlinked to this note.
- * To switch off the hyperlink, set this to Uml::id_None.
- *
- * @param viewID ID of an UMLScene.
- */
-void NoteWidget::setDiagramLink(Uml::ID::Type viewID)
-{
- UMLDoc *umldoc = UMLApp::app()->document();
- UMLView *view = umldoc->findView(viewID);
- if (view == NULL) {
- uError() << "no view found for viewID " << Uml::ID::toString(viewID);
- return;
- }
- QString linkText(QLatin1String("Diagram: ") + view->umlScene()->name());
- setDocumentation(linkText);
- m_diagramLink = viewID;
- update();
-}
-
-/**
- * Display a dialog box to allow the user to choose the note's type.
- */
-void NoteWidget::askForNoteType(UMLWidget* &targetWidget)
-{
- static const QStringList list = QStringList() << i18n("Precondition")
- << i18n("Postcondition")
- << i18n("Transformation");
- bool pressedOK = false;
-
-#if QT_VERSION >= 0x050000
- QString type = QInputDialog::getItem (UMLApp::app(),
- i18n("Note Type"), i18n("Select the Note Type"), list,
- 0, false, &pressedOK);
-#else
- QString type = KInputDialog::getItem (i18n("Note Type"), i18n("Select the Note Type"), list,
- 0, false, &pressedOK, UMLApp::app());
-#endif
-
- if (pressedOK) {
- dynamic_cast<NoteWidget*>(targetWidget)->setNoteType(type);
- } else {
- targetWidget->cleanup();
- delete targetWidget;
- targetWidget = 0;
- }
-}
-
-/**
- * Loads a "notewidget" XMI element.
- */
-bool NoteWidget::loadFromXMI(QDomElement & qElement)
-{
- if (!UMLWidget::loadFromXMI(qElement))
- return false;
- setZValue(20); //make sure always on top.
- setDocumentation(qElement.attribute(QLatin1String("text")));
- QString diagramlink = qElement.attribute(QLatin1String("diagramlink"));
- if (!diagramlink.isEmpty())
- m_diagramLink = Uml::ID::fromString(diagramlink);
- QString type = qElement.attribute(QLatin1String("noteType"));
- setNoteType((NoteType)type.toInt());
- return true;
-}
-
-/**
- * Saves to the "notewidget" XMI element.
- */
-void NoteWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement noteElement = qDoc.createElement(QLatin1String("notewidget"));
- UMLWidget::saveToXMI(qDoc, noteElement);
- noteElement.setAttribute(QLatin1String("text"), documentation());
- if (m_diagramLink != Uml::ID::None)
- noteElement.setAttribute(QLatin1String("diagramlink"), Uml::ID::toString(m_diagramLink));
- noteElement.setAttribute(QLatin1String("noteType"), m_noteType);
- qElement.appendChild(noteElement);
-}
-
-/**
- * Show a properties dialog for a NoteWidget.
- */
-void NoteWidget::showPropertiesDialog()
-{
- NoteDialog * dlg = 0;
- UMLApp::app()->docWindow()->updateDocumentation(false);
- dlg = new NoteDialog(umlScene()->activeView(), this);
- if (dlg->exec()) {
- UMLApp::app()->docWindow()->showDocumentation(this, true);
- UMLApp::app()->document()->setModified(true);
- update();
- }
- delete dlg;
-}
-
-/**
- * Will be called when a menu selection has been made from the popup
- * menu.
- *
- * @param action The action that has been selected.
- */
-void NoteWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_Rename:
- showPropertiesDialog();
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- break;
- }
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF NoteWidget::minimumSize() const
-{
- int width = 60;
- int height = 30;
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int textWidth = fm.width(documentation());
- if (m_noteType == PreCondition) {
- const int widthtemp = fm.width(QLatin1String("<< precondition >>"));
- width = textWidth > widthtemp ? textWidth : widthtemp;
- width += 10;
- }
- else if (m_noteType == PostCondition) {
- const int widthtemp = fm.width(QLatin1String("<< postcondition >>"));
- width = textWidth > widthtemp ? textWidth : widthtemp;
- width += 10;
- }
- else if (m_noteType == Transformation) {
- const int widthtemp = fm.width(QLatin1String("<< transformation >>"));
- width = textWidth > widthtemp ? textWidth : widthtemp;
- width += 10;
- }
- return QSizeF(width, height);
-}
-
-/**
- * Calculate content related size of widget.
- * Overrides method from UMLWidget.
- */
-QSizeF NoteWidget::calculateSize(bool withExtensions /* = true */) const
-{
- Q_UNUSED(withExtensions)
- int width = this->width();
- int height = this->height();
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int margin = fm.width(QLatin1String("W"));
- QSize size = fm.size (0, documentation());
- const int textWidth = size.width();
- if (m_noteType == PreCondition) {
- const int widthtemp = fm.width(QLatin1String("<< precondition >>"));
- width = textWidth > widthtemp ? textWidth : widthtemp;
- width += 2 * margin;
- }
- else if (m_noteType == PostCondition) {
- const int widthtemp = fm.width(QLatin1String("<< postcondition >>"));
- width = textWidth > widthtemp ? textWidth : widthtemp;
- width += 2 * margin;
- }
- else if (m_noteType == Transformation) {
- const int widthtemp = fm.width(QLatin1String("<< transformation >>"));
- width = textWidth > widthtemp ? textWidth : widthtemp;
- width += 2 * margin;
- }
- return QSizeF(width, height);
-}
-
-/**
- * Paints the text. Auxiliary to paint().
- * Implemented without word wrap.
- */
-void NoteWidget::paintText(QPainter *painter)
-{
- if (painter == 0) {
- return;
- }
-
- QString text = documentation();
- if (text.length() == 0) {
- return;
- }
-
- painter->setPen(Qt::black);
- QFont font = UMLWidget::font();
- painter->setFont(font);
-
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- const int margin = fm.width(QLatin1String("W"));
- const QSize textSize = fm.size(Qt::TextExpandTabs, text);
-
- const int width = this->width() - margin * 2;
- const int height = this->height() - fontHeight;
- int textY = fontHeight / 2;
- int textX = margin;
-
- if ((textSize.width() < width) && (textSize.height() < height)) {
- // the entire text is small enough - draw it
- painter->drawText(textX, textY,
- textSize.width(), textSize.height(),
- Qt::AlignLeft, text);
- }
- else {
- // not all text can be drawn
- QStringList lines = text.split(QLatin1Char('\n'));
- foreach(const QString& line, lines) {
- int lineWidth = fm.width(line);
- if (lineWidth < width) {
- // line is small enough - draw it
- painter->drawText(textX, textY,
- textSize.width(), fontHeight,
- Qt::AlignLeft, line);
- }
- else {
- // draw a smaller line
- for(int len = line.length(); len > 0; --len) {
- QString smallerLine = line.left(len);
- int smallerLineWidth = fm.width(smallerLine);
- if (smallerLineWidth < width) {
- // line is small enough - draw it
- painter->drawText(textX, textY,
- width, fontHeight,
- Qt::AlignLeft, smallerLine);
- }
- }
- }
- textY += fontHeight;
- if (textY > height) {
- // skip the next lines - size is not enough
- break;
- }
- }
- }
-}
-
-/**
- * Paints the text. Auxiliary to paint().
- * Implemented with word wrap.
- */
-void NoteWidget::paintTextWordWrap(QPainter *painter)
-{
- if (painter == 0) {
- return;
- }
- QString text = documentation();
- if (text.length() == 0) {
- return;
- }
- // Implement word wrap for text as follows:
- // wrap at width on whole words.
- // if word is wider than width then clip word
- // if reach height exit and don't print anymore
- // start new line on \n character
- painter->setPen(Qt::black);
- QFont font = UMLWidget::font();
- painter->setFont(font);
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- QString word;
- QString fullLine;
- QString testCombineLine;
- const int margin = fm.width(QLatin1String("W"));
- int textY = fontHeight / 2;
- int textX = margin;
- const int width = this -> width() - margin * 2;
- const int height = this -> height() - fontHeight;
- QChar returnChar = QChar::fromLatin1('\n');
- QChar c;
-
- for (int i = 0; i <= text.length(); ++i) {
- if (i < text.length()) {
- c = text[i];
- } else {
- // all chars of text have been handled already ->
- // perform this last run to spool current content of "word"
- c = returnChar;
- }
- if (c == returnChar || c.isSpace()) {
- // new word delimiter found -> it is time to decide on word wrap
- testCombineLine = fullLine + QLatin1Char(' ') + word;
- int textWidth = fm.width(testCombineLine);
- if (textX + textWidth > width) {
- // combination of "fullLine" and "word" doesn't fit into one line ->
- // print "fullLine" in current line, update write position to next line
- // and decide then on following actions
- painter->drawText(textX, textY,
- textWidth, fontHeight, Qt::AlignLeft, fullLine);
- fullLine = word;
- word = QString();
- // update write position
- textX = margin;
- textY += fontHeight;
- if (textY > height)
- return;
- // in case of c==newline ->
- // print "word" and set write position one additional line lower
- if (c == returnChar) {
- // print "word" - which is now "fullLine" and set to next line
- painter->drawText(textX, textY,
- textWidth, fontHeight, Qt::AlignLeft, fullLine);
- fullLine = QString();
- textX = margin;
- textY += fontHeight;
- if(textY > height) return;
- }
- }
- else if (c == returnChar) {
- // newline found and combination of "fullLine" and "word" fits
- // in one line
- painter->drawText(textX, textY,
- textWidth, fontHeight, Qt::AlignLeft, testCombineLine);
- fullLine = word = QString();
- textX = margin;
- textY += fontHeight;
- if (textY > height)
- return;
- } else {
- // word delimiter found, and combination of "fullLine", space and "word" fits into one line
- fullLine = testCombineLine;
- word = QString();
- }
- } else {
- // no word delimiter found --> add current char to "word"
- if (c != QLatin1Char('\0'))
- word += c;
- }
- }//end for
-}
-
-/**
- * Event handler for moude double click events.
- *
- * @param event The QGraphicsSceneMouseEvent event.
- */
-void NoteWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
-{
- if (event->button() == Qt::LeftButton) {
- if (m_diagramLink == Uml::ID::None) {
- showPropertiesDialog();
- } else {
- UMLDoc *umldoc = UMLApp::app()->document();
- umldoc->changeCurrentView(m_diagramLink);
- }
- event->accept();
- }
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/notewidget.h umbrello-kf6-15.08.1/umbrello/widgets/notewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/notewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/notewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,83 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef NOTEWIDGET_H
-#define NOTEWIDGET_H
-
-//app includes
-#include "umlwidget.h"
-
-// Qt forward declarations
-class QPainter;
-
-/**
- * Displays a note box to allow multiple lines of text to be displayed.
- * These widgets are diagram specific. They will still need a unique id
- * from the @ref UMLDoc class for deletion and other purpose-kf6s.
- *
- * @short Displays a note box.
- * @author Paul Hensgen <phensgen@techie.com>
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class NoteWidget : public UMLWidget
-{
- Q_OBJECT
-public:
-
- /// This enum type is used to specify the type of note.
- enum NoteType
- {
- Normal,
- PreCondition,
- PostCondition,
- Transformation
- };
-
- explicit NoteWidget(UMLScene * scene, NoteWidget::NoteType noteType = Normal,
- Uml::ID::Type id = Uml::ID::None);
- virtual ~NoteWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- static NoteType stringToNoteType(const QString& noteType);
-
- NoteType noteType() const;
- void setNoteType(NoteType noteType);
- void setNoteType(const QString& noteType);
-
- Uml::ID::Type diagramLink() const;
- void setDiagramLink(Uml::ID::Type viewID);
-
- void askForNoteType(UMLWidget* &targetWidget);
-
- virtual void showPropertiesDialog();
-
- virtual bool loadFromXMI(QDomElement & qElement);
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
- static NoteWidget *s_pCurrentNote;
-
-public Q_SLOTS:
- void slotMenuSelection(QAction* action);
-
-protected:
- virtual QSizeF minimumSize() const;
- virtual QSizeF calculateSize(bool withExtensions = true) const;
- void paintText(QPainter *painter);
- void paintTextWordWrap(QPainter *painter);
- virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
-
-private:
- Uml::ID::Type m_diagramLink; ///< The diagram/scene this note links to.
- NoteType m_noteType; ///< The type of note. @see NoteWidget::NoteType
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/objectnodewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/objectnodewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/objectnodewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/objectnodewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,377 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "objectnodewidget.h"
-
-// app includes
-#include "debug_utils.h"
-#include "docwindow.h"
-#include "dialog_utils.h"
-#include "listpopupmenu.h"
-#include "objectnodedialog.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-// kde includes
-#include <KLocalizedString>
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-#include <QPainter>
-#include <QPointer>
-
-#define OBJECTNODE_MARGIN 5
-#define OBJECTNODE_WIDTH 30
-#define OBJECTNODE_HEIGHT 10
-
-/**
- * Creates a Object Node widget.
- *
- * @param scene The parent of the widget.
- * @param objectNodeType The type of object node
- * @param id The ID to assign (-1 will prompt a new ID.)
- */
-ObjectNodeWidget::ObjectNodeWidget(UMLScene * scene, ObjectNodeType objectNodeType, Uml::ID::Type id)
- : UMLWidget(scene, WidgetBase::wt_ObjectNode, id)
-{
- setObjectNodeType(objectNodeType);
- setState(QString());
-}
-
-/**
- * Destructor.
- */
-ObjectNodeWidget::~ObjectNodeWidget()
-{
-}
-
-/**
- * Overrides the standard paint event.
- */
-void ObjectNodeWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- int w = width();
- int h = height();
-
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- int textStartY = (h / 2) - (fontHeight / 2);
-
- setPenFromSettings(painter);
-
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- }
-
- painter->drawRect(0, 0, w, h);
- painter->setFont(UMLWidget::font());
-
- switch (m_objectNodeType)
- {
- case Normal : break;
- case Buffer :
- {
- painter->setPen(textColor());
- painter->drawText(OBJECTNODE_MARGIN, (textStartY/2), w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, QLatin1String("<< centralBuffer >>"));
- painter->drawText(OBJECTNODE_MARGIN, (textStartY/2) + fontHeight + 5, w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, name());
- }
- break;
- case Data :
- {
- painter->setPen(textColor());
- painter->drawText(OBJECTNODE_MARGIN, (textStartY/2), w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, QLatin1String("<< datastore >>"));
- painter->drawText(OBJECTNODE_MARGIN, (textStartY/2) + fontHeight + 5, w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, name());
- }
- break;
- case Flow :
- {
- QString objectflow_value;
- if (state() == QLatin1String("-") || state().isEmpty())
- {
- objectflow_value = QLatin1Char(' ');
- }
- else
- {
- objectflow_value = QLatin1Char('[') + state() + QLatin1Char(']');
- }
-
- painter->drawLine(10, h/2, w-10, h/2);
- painter->setPen(textColor());
- painter->setFont(UMLWidget::font());
- painter->drawText(OBJECTNODE_MARGIN, textStartY/2 - OBJECTNODE_MARGIN, w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, name());
- painter->drawText(OBJECTNODE_MARGIN, textStartY/2 + textStartY + OBJECTNODE_MARGIN, w - OBJECTNODE_MARGIN * 2, fontHeight, Qt::AlignHCenter, objectflow_value);
- }
- break;
- }
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF ObjectNodeWidget::minimumSize() const
-{
- int widthtmp = 10, height = 10, width=10;
- if (m_objectNodeType == Buffer) {
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- const int textWidth = fm.width(QLatin1String("<< centralBuffer >>"));
- const int namewidth = fm.width(name());
- height = fontHeight * 2;
- widthtmp = textWidth > OBJECTNODE_WIDTH ? textWidth : OBJECTNODE_WIDTH;
- width = namewidth > widthtmp ? namewidth : widthtmp;
- height = height > OBJECTNODE_HEIGHT ? height : OBJECTNODE_HEIGHT;
- width += OBJECTNODE_MARGIN * 2;
- height += OBJECTNODE_MARGIN * 2 + 5;
- } else if (m_objectNodeType == Data) {
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- const int textWidth = fm.width(QLatin1String("<< datastore >>"));
- const int namewidth = fm.width(name());
- height = fontHeight * 2;
- widthtmp = textWidth > OBJECTNODE_WIDTH ? textWidth : OBJECTNODE_WIDTH;
- width = namewidth > widthtmp ? namewidth : widthtmp;
- height = height > OBJECTNODE_HEIGHT ? height : OBJECTNODE_HEIGHT;
- width += OBJECTNODE_MARGIN * 2;
- height += OBJECTNODE_MARGIN * 2 + 5;
- } else if (m_objectNodeType == Flow) {
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- const int textWidth = fm.width(QLatin1Char('[') + state() + QLatin1Char(']'));
- const int namewidth = fm.width(name());
- height = fontHeight * 2;
- widthtmp = textWidth > OBJECTNODE_WIDTH ? textWidth : OBJECTNODE_WIDTH;
- width = namewidth > widthtmp ? namewidth : widthtmp;
- height = height > OBJECTNODE_HEIGHT ? height : OBJECTNODE_HEIGHT;
- width += OBJECTNODE_MARGIN * 2;
- height += OBJECTNODE_MARGIN * 4;
- }
-
- return QSizeF(width, height);
-}
-
-/**
- * Returns the type of object node.
- */
-ObjectNodeWidget::ObjectNodeType ObjectNodeWidget::objectNodeType() const
-{
- return m_objectNodeType;
-}
-
-/**
- * Returns the type of object node.
- */
-ObjectNodeWidget::ObjectNodeType ObjectNodeWidget::toObjectNodeType(const QString& type)
-{
- if (type == QLatin1String("Central buffer"))
- return ObjectNodeWidget::Buffer;
- if (type == QLatin1String("Data store"))
- return ObjectNodeWidget::Data;
- if (type == QLatin1String("Object Flow"))
- return ObjectNodeWidget::Flow;
- // Shouldn't happen
- Q_ASSERT(0);
- return ObjectNodeWidget::Flow;
-}
-
-/**
- * Sets the type of object node.
- */
-void ObjectNodeWidget::setObjectNodeType(ObjectNodeType objectNodeType)
-{
- m_objectNodeType = objectNodeType;
- UMLWidget::m_resizable = true;
-}
-
-/**
- * Sets the type of object node.
- */
-void ObjectNodeWidget::setObjectNodeType(const QString& type)
-{
- setObjectNodeType(ObjectNodeWidget::toObjectNodeType(type));
-}
-
-/**
- * Sets the state of an object node when it's an objectflow.
- */
-void ObjectNodeWidget::setState(const QString& state)
-{
- m_state = state;
- updateGeometry();
-}
-
-/**
- * Returns the state of object node.
- */
-QString ObjectNodeWidget::state() const
-{
- return m_state;
-}
-
-/**
- * Captures any popup menu signals for menus it created.
- */
-void ObjectNodeWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_Rename:
- {
- bool ok = false;
- QString text = name();
-#if QT_VERSION >= 0x050000
- text = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter Object Node Name"),
- i18n("Enter the name of the object node :"),
- QLineEdit::Normal,
- name(), &ok);
-#else
- text = KInputDialog::getText(i18n("Enter Object Node Name"),
- i18n("Enter the name of the object node :"),
- name(), &ok);
-#endif
- if (ok && !text.isEmpty()) {
- setName(text);
- }
- }
- break;
-
- case ListPopupMenu::mt_Properties:
- showPropertiesDialog();
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- }
-}
-
-/**
- * Show a properties dialog for an ObjectNodeWidget.
- */
-void ObjectNodeWidget::showPropertiesDialog()
-{
- UMLApp::app()->docWindow()->updateDocumentation(false);
-
- QPointer<ObjectNodeDialog> dialog = new ObjectNodeDialog(UMLApp::app()->currentView(), this);
- if (dialog->exec() && dialog->getChangesMade()) {
- UMLApp::app()->docWindow()->showDocumentation(this, true);
- UMLApp::app()->document()->setModified(true);
- }
- delete dialog;
-}
-
-/**
- * Saves the widget to the "objectnodewidget" XMI element.
- */
-void ObjectNodeWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement objectNodeElement = qDoc.createElement(QLatin1String("objectnodewidget"));
- UMLWidget::saveToXMI(qDoc, objectNodeElement);
- objectNodeElement.setAttribute(QLatin1String("objectnodename"), m_Text);
- objectNodeElement.setAttribute(QLatin1String("documentation"), m_Doc);
- objectNodeElement.setAttribute(QLatin1String("objectnodetype"), m_objectNodeType);
- objectNodeElement.setAttribute(QLatin1String("objectnodestate"), m_state);
- qElement.appendChild(objectNodeElement);
-}
-
-/**
- * Loads the widget from the "objectnodewidget" XMI element.
- */
-bool ObjectNodeWidget::loadFromXMI(QDomElement& qElement)
-{
- if(!UMLWidget::loadFromXMI(qElement) )
- return false;
- m_Text = qElement.attribute(QLatin1String("objectnodename"));
- m_Doc = qElement.attribute(QLatin1String("documentation"));
- QString type = qElement.attribute(QLatin1String("objectnodetype"), QLatin1String("1"));
- m_state = qElement.attribute(QLatin1String("objectnodestate"));
- setObjectNodeType((ObjectNodeType)type.toInt());
- return true;
-}
-
-/**
- * Open a dialog box to select the objectNode type (Data, Buffer or Flow).
- */
-void ObjectNodeWidget::askForObjectNodeType(UMLWidget* &targetWidget)
-{
- bool pressedOK = false;
- int current = 0;
- const QStringList list = QStringList()
- << QLatin1String("Central buffer")
- << QLatin1String("Data store")
- << QLatin1String("Object Flow");
-
-#if QT_VERSION >= 0x050000
- QString type = QInputDialog::getItem (UMLApp::app(),
- i18n("Select Object node type"), i18n("Select the object node type"),
- list, current, false, &pressedOK);
-
-#else
- QString type = KInputDialog::getItem (i18n("Select Object node type"), i18n("Select the object node type"), list, current, false, &pressedOK, UMLApp::app());
-#endif
-
- if (pressedOK) {
- dynamic_cast<ObjectNodeWidget*>(targetWidget)->setObjectNodeType(type);
- if (type == QLatin1String("Data store"))
- Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the name of the data store node"), i18n("Enter the name of the data store node"), i18n("data store name"));
- if (type == QLatin1String("Central buffer"))
- Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the name of the buffer node"), i18n("Enter the name of the buffer"), i18n("centralBuffer"));
- if (type == QLatin1String("Object Flow")) {
- Dialog_Utils::askNameForWidget(targetWidget, i18n("Enter the name of the object flow"), i18n("Enter the name of the object flow"), i18n("object flow"));
- askStateForWidget();
- }
- } else {
- targetWidget->cleanup();
- delete targetWidget;
- targetWidget = NULL;
- }
-}
-
-/**
- * Open a dialog box to input the state of the widget.
- * This box is shown only if m_objectNodeType = Flow.
- */
-void ObjectNodeWidget::askStateForWidget()
-{
- bool pressedOK = false;
-#if QT_VERSION >= 0x050000
- QString state = QInputDialog::getText(UMLApp::app(),
- i18n("Enter Object Flow State"), i18n("Enter State (keep '-' if there is no state for the object) "),
- QLineEdit::Normal,
- i18n("-"), &pressedOK);
-#else
- QString state = KInputDialog::getText(i18n("Enter Object Flow State"), i18n("Enter State (keep '-' if there is no state for the object) "), i18n("-"), &pressedOK, UMLApp::app());
-#endif
-
- if (pressedOK) {
- setState(state);
- } else {
- cleanup();
- }
-}
-
-void ObjectNodeWidget::slotOk()
-{
- // kdialog-kf6::accept();
-}
-
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/objectnodewidget.h umbrello-kf6-15.08.1/umbrello/widgets/objectnodewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/objectnodewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/objectnodewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,76 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef OBJECTNODEWIDGET_H
-#define OBJECTNODEWIDGET_H
-
-#include "umlwidget.h"
-
-/**
- * This class is the graphical version of a UML Object Node. A ObjectNodeWidget is created
- * by a @ref UMLView. An ObjectNodeWidget belongs to only one @ref UMLView instance.
- * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
- *
- * The ObjectNodeWidget class inherits from the @ref UMLWidget class which adds most of the functionality
- * to this class.
- *
- * @short A graphical version of a UML Activity.
- * @author Florence Mattler <florence.mattler@libertysurf.fr>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class ObjectNodeWidget : public UMLWidget
-{
- Q_OBJECT
-
-public:
- enum ObjectNodeType
- {
- Normal,
- Data,
- Buffer,
- Flow
- };
-
- explicit ObjectNodeWidget(UMLScene * scene, ObjectNodeType objectNodeType = Normal, Uml::ID::Type id = Uml::ID::None);
- virtual ~ObjectNodeWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- ObjectNodeType objectNodeType() const;
- static ObjectNodeType toObjectNodeType(const QString& type);
-
- void setObjectNodeType(ObjectNodeType objectNodeType);
- void setObjectNodeType(const QString& type) ;
-
- void setState(const QString& state);
- QString state() const;
-
- virtual void showPropertiesDialog();
-
- void askStateForWidget();
- void askForObjectNodeType(UMLWidget* &targetWidget);
-
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
- virtual bool loadFromXMI(QDomElement& qElement);
-
-protected:
- QSizeF minimumSize() const;
-
-public slots:
- void slotMenuSelection(QAction* action);
- void slotOk();
-
-private:
- ObjectNodeType m_objectNodeType; ///< type of object node
- QString m_state; ///< state of object node when it's an objectFlow
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/objectwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/objectwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/objectwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/objectwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,710 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header file
-#include "objectwidget.h"
-
-// local includes
-#include "classpropertiesdialog.h"
-#include "debug_utils.h"
-#include "docwindow.h"
-#include "listpopupmenu.h"
-#include "messagewidget.h"
-#include "seqlinewidget.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlobject.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-// kde includes
-#include <KLocalizedString>
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-#include <QPointer>
-#include <QPainter>
-#include <QValidator>
-
-#define O_MARGIN 5
-#define O_WIDTH 40
-#define A_WIDTH 20
-#define A_HEIGHT 40
-#define A_MARGIN 5
-
-DEBUG_REGISTER_DISABLED(ObjectWidget)
-
-/**
- * The number of pixels margin between the lowest message
- * and the bottom of the vertical line
- */
-static const int sequenceLineMargin = 20;
-
-/**
- * Creates an ObjectWidget.
- *
- * @param scene The parent to this object.
- * @param o The object it will be representing.
- */
-ObjectWidget::ObjectWidget(UMLScene * scene, UMLObject *o)
- : UMLWidget(scene, WidgetBase::wt_Object, o),
- m_multipleInstance(false),
- m_drawAsActor(false),
- m_showDestruction(false),
- m_isOnDestructionBox(false)
-{
- if (m_scene && (m_scene->type() == Uml::DiagramType::Sequence)) {
- m_pLine = new SeqLineWidget( m_scene, this );
- m_pLine->setStartPoint(x() + width() / 2, y() + height());
- } else {
- m_pLine = 0;
- }
-}
-
-/**
- * Destructor.
- */
-ObjectWidget::~ObjectWidget()
-{
- cleanup();
-}
-
-/**
- * Sets whether representing a multi-instance object.
- *
- * @param multiple Object state. true- multi, false - single.
- */
-void ObjectWidget::setMultipleInstance(bool multiple)
-{
- //make sure only calling this in relation to an object on a collab. diagram
- if (m_scene && (m_scene->type() == Uml::DiagramType::Collaboration)) {
- m_multipleInstance = multiple;
- updateGeometry();
- update();
- }
-}
-
-/**
- * Returns whether object is representing a multi-object.
- *
- * @return True if object is representing a multi-object.
- */
-bool ObjectWidget::multipleInstance() const
-{
- return m_multipleInstance;
-}
-
-/**
- * Overridden from UMLWidget.
- * Moves the widget to a new position using the difference between the
- * current position and the new position.
- * Y position is ignored, and widget is only moved along X axis.
- *
- * @param diffX The difference between current X position and new X position.
- * @param diffY The difference between current Y position and new Y position
- * (isn't used).
- */
-void ObjectWidget::moveWidgetBy(qreal diffX, qreal diffY)
-{
- setX(x() + diffX);
- if (m_scene && (m_scene->type() != Uml::DiagramType::Sequence)) {
- setY(y() + diffY);
- }
-}
-
-/**
- * Overridden from UMLWidget.
- * Modifies the value of the diffX and diffY variables used to move the widgets.
- * All the widgets are constrained to be moved only in X axis (diffY is set to 0).
- *
- * @param diffX The difference between current X position and new X position.
- * @param diffY The difference between current Y position and new Y position.
- */
-void ObjectWidget::constrainMovementForAllWidgets(qreal &diffX, qreal &diffY)
-{
- Q_UNUSED(diffX);
- if (m_scene && (m_scene->type() == Uml::DiagramType::Sequence)) {
- diffY = 0;
- }
-}
-
-/**
- * Override default method.
- */
-void ObjectWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- if (m_drawAsActor)
- paintActor(painter);
- else
- paintObject(painter);
-
- setPenFromSettings(painter);
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Handles a popup menu selection.
- */
-void ObjectWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_Rename_Object:
- {
- bool ok;
- QRegExpValidator* validator = new QRegExpValidator(QRegExp(QLatin1String(".*")), 0);
-#if QT_VERSION >= 0x050000
- QString name = QInputDialog::getText(m_scene->activeView(),
- i18n("Rename Object"),
- i18n("Enter object name:"),
- QLineEdit::Normal,
- m_instanceName,
- &ok);
-#else
- QString name = KInputDialog::getText
- (i18n("Rename Object"),
- i18n("Enter object name:"),
- m_instanceName,
- &ok,
- m_scene->activeView(),
- validator);
-#endif
- if (ok) {
- m_instanceName = name;
- updateGeometry();
- moveEvent(0);
- update();
- UMLApp::app()->document()->setModified(true);
- }
- delete validator;
- break;
- }
- case ListPopupMenu::mt_Properties:
- showPropertiesDialog();
- updateGeometry();
- moveEvent(0);
- update();
- break;
-
- case ListPopupMenu::mt_Up:
- tabUp();
- break;
-
- case ListPopupMenu::mt_Down:
- tabDown();
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- break;
- }
-}
-
-/**
- * Overrides method from UMLWidget
- */
-QSizeF ObjectWidget::minimumSize() const
-{
- int width, height;
- const QFontMetrics &fm = getFontMetrics(FT_UNDERLINE);
- const int fontHeight = fm.lineSpacing();
- const QString t = m_instanceName + QLatin1String(" : ") + name();
- const int textWidth = fm.width(t);
- if (m_drawAsActor) {
- width = textWidth > A_WIDTH?textWidth:A_WIDTH;
- height = A_HEIGHT + fontHeight + A_MARGIN;
- width += A_MARGIN * 2;
- } else {
- width = textWidth > O_WIDTH?textWidth:O_WIDTH;
- height = fontHeight + O_MARGIN * 2;
- width += O_MARGIN * 2;
- if (m_multipleInstance) {
- width += 10;
- height += 10;
- }
- }//end else drawasactor
-
- return QSizeF(width, height);
-}
-
-/**
- * Sets whether to draw as an Actor.
- *
- * @param drawAsActor True if widget shall be drawn as an actor.
- */
-void ObjectWidget::setDrawAsActor(bool drawAsActor)
-{
- m_drawAsActor = drawAsActor;
- updateGeometry();
-}
-
-/**
- * Returns whether to draw as an Actor or not.
- *
- * @return True if widget is drawn as an actor.
- */
-bool ObjectWidget::drawAsActor() const
-{
- return m_drawAsActor;
-}
-
-/**
- * Activate the object after serializing it from a QDataStream
- */
-bool ObjectWidget::activate(IDChangeLog* ChangeLog /*= 0*/)
-{
- if (! UMLWidget::activate(ChangeLog))
- return false;
- if (m_showDestruction && m_pLine)
- m_pLine->setupDestructionBox();
- moveEvent(0);
- return true;
-}
-
-/**
- * Sets the x-coordinate.
- * Reimplements the method from UMLWidget.
- *
- * @param x The x-coordinate to be set.
- */
-void ObjectWidget::setX(qreal x)
-{
- UMLWidget::setX(x);
- moveEvent(0);
-}
-
-/**
- * Sets the y-coordinate.
- * Reimplements the method from UMLWidget.
- *
- * @param y The y-coordinate to be set.
- */
-void ObjectWidget::setY(qreal y)
-{
- UMLWidget::setY(y);
- if (!UMLApp::app()->document()->loading())
- moveEvent(0);
-}
-
-/**
- * Return the x coordinate of the widgets center.
- * @return The x-coordinate of the widget center.
- */
-qreal ObjectWidget::centerX()
-{
- return x() + width()/2;
-}
-
-/**
- * Overrides the standard operation.
- */
-void ObjectWidget::moveEvent(QGraphicsSceneMouseEvent *event)
-{
- Q_UNUSED(event)
- emit sigWidgetMoved(m_nLocalID);
- if (m_pLine) {
- m_pLine->setStartPoint(x() + width() / 2, y() + height());
- }
-}
-
-/**
- * Overrides the standard operation.
- */
-void ObjectWidget::mousePressEvent(QGraphicsSceneMouseEvent *me)
-{
- UMLWidget::mousePressEvent(me);
- m_isOnDestructionBox = false;
- if (m_pLine && m_pLine->onDestructionBox(me->scenePos())) {
- m_isOnDestructionBox = true;
- qreal oldX = x() + width() / 2;
- qreal oldY = getEndLineY() - 10;
- m_oldPos = QPointF(oldX, oldY);
- }
-}
-
-/**
- * Overrides the standard operation.
- */
-void ObjectWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* me)
-{
- if (m_inResizeArea) {
- DEBUG(DBG_SRC) << "resizing...";
- resize(me);
- moveEvent(0);
- return;
- }
-
- if (m_isOnDestructionBox) {
- qreal diffY = me->scenePos().y() - m_oldPos.y();
- moveDestructionBy(diffY);
- }
- else {
- UMLWidget::mouseMoveEvent(me);
- }
-}
-
-/**
- * Moves the destruction Box to a new position using the difference between the
- * current position and the new position.
- * The destruction box is only moved along Y axis.
- *
- * @param diffY The difference between current Y position and new Y position
- */
-void ObjectWidget::moveDestructionBy(qreal diffY)
-{
- // endLine = length of the life line + diffY - 10 to center on the destruction box
- qreal endLine = getEndLineY() + diffY - 10;
- SeqLineWidget *pLine = sequentialLine();
- pLine->setEndOfLine(endLine);
- m_oldPos.setY(endLine);
-}
-
-/**
- * Handles a color change signal.
- */
-void ObjectWidget::slotFillColorChanged(Uml::ID::Type /*viewID*/)
-{
- UMLWidget::setFillColor(m_scene->fillColor());
- UMLWidget::setLineColor(m_scene->lineColor());
-
- if(m_pLine)
- m_pLine->setPen(QPen(UMLWidget::lineColor(), UMLWidget::lineWidth(), Qt::DashLine));
-}
-
-/**
- * Used to cleanup any other widget it may need to delete.
- */
-void ObjectWidget::cleanup()
-{
- UMLWidget::cleanup();
- if(m_pLine) {
- m_pLine->cleanup();
- delete m_pLine;
- m_pLine = 0;
- }
-}
-
-/**
- * Show a properties dialog for an ObjectWidget.
- */
-void ObjectWidget::showPropertiesDialog()
-{
- UMLApp::app()->docWindow()->updateDocumentation(false);
- QPointer<ClassPropertiesDialog> dlg = new ClassPropertiesDialog((QWidget*)UMLApp::app(), this);
- if (dlg->exec()) {
- UMLApp::app()->docWindow()->showDocumentation(this, true);
- UMLApp::app()->document()->setModified(true);
- }
- dlg->close();
- delete dlg;
-}
-
-/**
- * Draw the object as an object (default).
- */
-void ObjectWidget::paintObject(QPainter *painter)
-{
- QFont oldFont = painter->font();
- QFont font = UMLWidget::font();
- font.setUnderline(true);
- painter->setFont(font);
-
- setPenFromSettings(painter);
- if(UMLWidget::useFillColor())
- painter->setBrush(UMLWidget::fillColor());
- else
- painter->setBrush(m_scene->backgroundColor());
- const int w = width();
- const int h = height();
-
- const QString t = m_instanceName + QLatin1String(" : ") + name();
- int multiInstOfst = 0;
- if (m_multipleInstance) {
- painter->drawRect(10, 10, w - 10, h - 10);
- painter->drawRect(5, 5, w - 10, h - 10);
- multiInstOfst = 10;
- }
- painter->drawRect(0, 0, w - multiInstOfst, h - multiInstOfst);
- painter->setPen(textColor());
- painter->drawText(O_MARGIN, O_MARGIN,
- w - O_MARGIN * 2 - multiInstOfst, h - O_MARGIN * 2 - multiInstOfst,
- Qt::AlignCenter, t);
-
- painter->setFont(oldFont);
-}
-
-/**
- * Draw the object as an actor.
- */
-void ObjectWidget::paintActor(QPainter *painter)
-{
- const QFontMetrics &fm = getFontMetrics(FT_UNDERLINE);
-
- setPenFromSettings(painter);
- if (UMLWidget::useFillColor())
- painter->setBrush(UMLWidget::fillColor());
- const int w = width();
- const int textStartY = A_HEIGHT + A_MARGIN;
- const int fontHeight = fm.lineSpacing();
-
- const int middleX = w / 2;
- const int thirdH = A_HEIGHT / 3;
-
- //draw actor
- painter->drawEllipse(middleX - A_WIDTH / 2, 0, A_WIDTH, thirdH);//head
- painter->drawLine(middleX, thirdH, middleX, thirdH * 2);//body
- painter->drawLine(middleX, 2 * thirdH,
- middleX - A_WIDTH / 2, A_HEIGHT);//left leg
- painter->drawLine(middleX, 2 * thirdH,
- middleX + A_WIDTH / 2, A_HEIGHT);//right leg
- painter->drawLine(middleX - A_WIDTH / 2, thirdH + thirdH / 2,
- middleX + A_WIDTH / 2, thirdH + thirdH / 2);//arms
- //draw text
- painter->setPen(textColor());
- QString t = m_instanceName + QLatin1String(" : ") + name();
- painter->drawText(A_MARGIN, textStartY,
- w - A_MARGIN * 2, fontHeight, Qt::AlignCenter, t);
-}
-
-/**
- * Move the object up on a sequence diagram.
- */
-void ObjectWidget::tabUp()
-{
- int newY = y() - height();
- if (newY < topMargin())
- newY = topMargin();
- setY(newY);
- adjustAssocs(x(), newY);
-}
-
-/**
- * Move the object down on a sequence diagram.
- */
-void ObjectWidget::tabDown()
-{
- int newY = y() + height();
- setY(newY);
- adjustAssocs(x(), newY);
-}
-
-/**
- * Returns the top margin constant (Y axis value)
- *
- * @return Y coordinate of the space between the diagram top
- * and the upper edge of the ObjectWidget.
- */
-int ObjectWidget::topMargin()
-{
- return 80 - height();
-}
-
-/**
- * Returns whether or not the widget can be moved vertically up.
- *
- * @return True if widget can be moved upwards vertically.
- */
-bool ObjectWidget::canTabUp()
-{
- return (y() > topMargin());
-}
-
-/**
- * Sets whether to show deconstruction on sequence line.
- *
- * @param bShow True if destruction on line shall be shown.
- */
-void ObjectWidget::setShowDestruction(bool bShow)
-{
- m_showDestruction = bShow;
- if(m_pLine)
- m_pLine->setupDestructionBox();
-}
-
-/**
- * Returns whether to show deconstruction on sequence line.
- *
- * @return True if destruction on sequence line is shown.
- */
-bool ObjectWidget::showDestruction() const
-{
- return m_showDestruction;
-}
-
-/**
- * Sets the y position of the bottom of the vertical line.
- *
- * @param yPosition The y coordinate for the bottom of the line.
- */
-void ObjectWidget::setEndLine(int yPosition)
-{
- if (m_pLine) {
- m_pLine->setEndOfLine(yPosition);
- }
-}
-
-/**
- * Returns the end Y co-ord of the sequence line.
- *
- * @return Y coordinate of the endpoint of the sequence line.
- */
-int ObjectWidget::getEndLineY()
-{
- int y = this->y() + height();
- if(m_pLine)
- y += m_pLine->getLineLength();
- if (m_showDestruction)
- y += 10;
- return y;
-}
-
-/**
- * Add a message widget to the list.
- *
- * @param message Pointer to the MessageWidget to add.
- */
-void ObjectWidget::messageAdded(MessageWidget* message)
-{
- if (m_messages.count(message)) {
- uError() << message->name() << ": duplicate entry !";
- return ;
- }
- m_messages.append(message);
-}
-
-/**
- * Remove a message widget from the list.
- *
- * @param message Pointer to the MessageWidget to remove.
- */
-void ObjectWidget::messageRemoved(MessageWidget* message)
-{
- if (m_messages.removeAll(message) == false) {
- uError() << message->name() << ": missing entry !";
- return ;
- }
-}
-
-/**
- * Called when a message widget with an end on this object has
- * moved up or down.
- * Sets the bottom of the line to a nice position.
- */
-void ObjectWidget::slotMessageMoved()
-{
- if (m_pLine) {
- int lowestMessage = 0;
- foreach (MessageWidget* message, m_messages) {
- int messageHeight = message->y() + message->height();
- if (lowestMessage < messageHeight) {
- lowestMessage = messageHeight;
- }
- }
- m_pLine->setEndOfLine(lowestMessage + sequenceLineMargin);
- }
-}
-
-/**
- * Returns whether a message is overlapping with another message.
- * Used by MessageWidget::paint() methods.
- *
- * @param y top of your message
- * @param messageWidget pointer to your message so it doesn't check against itself
- */
-bool ObjectWidget::messageOverlap(qreal y, MessageWidget* messageWidget)
-{
- foreach (MessageWidget* message, m_messages) {
- if (message == messageWidget) {
- continue;
- }
- const qreal msgY = message->y();
- const qreal msgHeight = msgY + message->height();
- if (y >= msgY && y <= msgHeight) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Return the SeqLineWidget.
- * Returns a non NULL pointer if this ObjectWidget is part of a
- * sequence diagram.
- */
-SeqLineWidget *ObjectWidget::sequentialLine() const
-{
- return m_pLine;
-}
-
-/**
- * Overridden from UMLWidget.
- * Returns the cursor to be shown when resizing the widget.
- * The cursor shown is KCursor::sizeHorCursor().
- *
- * @return The cursor to be shown when resizing the widget.
- */
-QCursor ObjectWidget::resizeCursor() const
-{
- return Qt::SizeHorCursor;
-}
-
-/**
- * Overridden from UMLWidget.
- * Resizes the width of the object widget.
- * Object widgets can only be resized horizontally, so height isn't modified.
- *
- * @param newW The new width for the widget.
- * @param newH The new height for the widget (isn't used).
- */
-void ObjectWidget::resizeWidget(qreal newW, qreal newH)
-{
- Q_UNUSED(newH);
- setSize(newW, height());
-}
-
-/**
- * Saves to the "objectwidget" XMI element.
- */
-void ObjectWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement objectElement = qDoc.createElement(QLatin1String("objectwidget"));
- UMLWidget::saveToXMI(qDoc, objectElement);
- objectElement.setAttribute(QLatin1String("drawasactor"), m_drawAsActor);
- objectElement.setAttribute(QLatin1String("multipleinstance"), m_multipleInstance);
- objectElement.setAttribute(QLatin1String("decon"), m_showDestruction);
- qElement.appendChild(objectElement);
-}
-
-/**
- * Loads from a "objectwidget" XMI element.
- */
-bool ObjectWidget::loadFromXMI(QDomElement& qElement)
-{
- if(!UMLWidget::loadFromXMI(qElement))
- return false;
- QString draw = qElement.attribute(QLatin1String("drawasactor"), QLatin1String("0"));
- QString multi = qElement.attribute(QLatin1String("multipleinstance"), QLatin1String("0"));
- QString decon = qElement.attribute(QLatin1String("decon"), QLatin1String("0"));
-
- m_drawAsActor = (bool)draw.toInt();
- m_multipleInstance = (bool)multi.toInt();
- m_showDestruction = (bool)decon.toInt();
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/objectwidget.h umbrello-kf6-15.08.1/umbrello/widgets/objectwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/objectwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/objectwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,115 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef OBJECTWIDGET_H
-#define OBJECTWIDGET_H
-
-#include "messagewidgetlist.h"
-#include "umlwidget.h"
-
-class MessageWidget;
-class SeqLineWidget;
-class UMLScene;
-
-/**
- * Displays an instance UMLObject of a concept.
- *
- * The local ID is needed as a it can represent a class
- * that has many objects representing it.
- *
- * @short Displays an instance of a Concept.
- * @author Paul Hensgen <phensgen@techie.com>
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class ObjectWidget : public UMLWidget
-{
- Q_OBJECT
-public:
- ObjectWidget(UMLScene *scene, UMLObject *o);
- virtual ~ObjectWidget();
-
- virtual void setX(qreal x);
- virtual void setY(qreal y);
-
- qreal centerX();
-
- void setMultipleInstance(bool multiple);
- bool multipleInstance() const;
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- bool activate(IDChangeLog* ChangeLog = 0);
-
- void cleanup();
-
- void showPropertiesDialog();
-
- void setDrawAsActor(bool drawAsActor);
- bool drawAsActor() const;
-
- void setShowDestruction(bool bShow);
- bool showDestruction() const;
-
- int topMargin();
-
- void setEndLine(int yPosition);
- int getEndLineY();
-
- void messageAdded(MessageWidget* message);
- void messageRemoved(MessageWidget* message);
-
- bool canTabUp();
-
- bool messageOverlap(qreal y, MessageWidget* messageWidget);
-
- SeqLineWidget *sequentialLine() const;
-
- virtual void resizeWidget(qreal newW, qreal newH);
-
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
- virtual bool loadFromXMI(QDomElement& qElement);
-
-public slots:
- void slotMenuSelection(QAction* action);
- virtual void slotFillColorChanged(Uml::ID::Type viewID);
- void slotMessageMoved();
-
-protected:
- virtual void mousePressEvent(QGraphicsSceneMouseEvent *me);
- virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *me);
-
- QSizeF minimumSize() const;
-
- virtual void moveEvent(QGraphicsSceneMouseEvent *event);
- virtual void moveWidgetBy(qreal diffX, qreal diffY);
- virtual void constrainMovementForAllWidgets(qreal &diffX, qreal &diffY);
-
- virtual QCursor resizeCursor() const;
-
- void paintActor(QPainter *p);
- void paintObject(QPainter *p);
-
-private:
- void tabUp();
- void tabDown();
-
- void moveDestructionBy(qreal diffY);
-
- SeqLineWidget* m_pLine;
- bool m_multipleInstance; ///< draw an object as a multiple object
- bool m_drawAsActor; ///< object should be drawn as an Actor or an Object
- bool m_showDestruction; ///< show object destruction on sequence diagram line
- bool m_isOnDestructionBox; ///< true when a click occurred on the destruction box
- MessageWidgetList m_messages; ///< message widgets with an end on this widget
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/packagewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/packagewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/packagewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/packagewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,149 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "packagewidget.h"
-
-// app includes
-#include "debug_utils.h"
-#include "package.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlobject.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-// qt includes
-#include <QPainter>
-
-/**
- * Constructs a PackageWidget.
- *
- * @param scene The parent of this PackageWidget.
- * @param o The UMLObject this will be representing.
- */
-PackageWidget::PackageWidget(UMLScene * scene, UMLPackage *o)
- : UMLWidget(scene, WidgetBase::wt_Package, o),
- m_pMenu(0)
-{
- setSize(100, 30);
- setZValue(1); // above box but below UMLWidget because may embed widgets
- //set defaults from m_scene
- if (m_scene) {
- //check to see if correct
- const Settings::OptionState& ops = m_scene->optionState();
- m_showStereotype = ops.classState.showStereoType;
- }
-}
-
-/**
- * Destructor.
- */
-PackageWidget::~PackageWidget()
-{
-}
-
-/**
- * Overrides standard method.
- */
-void PackageWidget::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());
-
- 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 != NULL
- && 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;
- if (m_umlObject != NULL) {
- QString stereotype = m_umlObject->stereotype();
- if (!stereotype.isEmpty()) {
- painter->drawText(0, fontHeight + PACKAGE_MARGIN,
- w, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true));
- lines = 2;
- }
- }
-
- painter->drawText(0, (fontHeight*lines) + PACKAGE_MARGIN,
- w, fontHeight, Qt::AlignCenter, name());
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overrides method from UMLWidget
- */
-QSizeF PackageWidget::minimumSize() const
-{
- if (!m_umlObject) {
- return UMLWidget::minimumSize();
- }
-
- 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 += PACKAGE_MARGIN * 2;
- if (width < 70)
- width = 70; // minumin width of 70
-
- int height = (lines*fontHeight) + fontHeight + (PACKAGE_MARGIN * 2);
-
- return QSizeF(width, height);
-}
-
-/**
- * Saves to the "packagewidget" XMI element.
- */
-void PackageWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement conceptElement = qDoc.createElement(QLatin1String("packagewidget"));
- UMLWidget::saveToXMI(qDoc, conceptElement);
- qElement.appendChild(conceptElement);
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/packagewidget.h umbrello-kf6-15.08.1/umbrello/widgets/packagewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/packagewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/packagewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,47 +0,0 @@
-/***************************************************************************
- * 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) 2003-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef PACKAGEWIDGET_H
-#define PACKAGEWIDGET_H
-
-#include "umlwidget.h"
-
-class UMLPackage;
-class ListPopupMenu;
-
-#define PACKAGE_MARGIN 5
-
-/**
- * Defines a graphical version of the Package. Most of the
- * functionality will come from the @ref UMLPackage class.
- *
- * @short A graphical version of a Package.
- * @author Jonathan Riddell
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class PackageWidget : public UMLWidget
-{
-public:
- explicit PackageWidget(UMLScene * scene, UMLPackage * o);
- virtual ~PackageWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
-
-protected:
- QSizeF minimumSize() const;
-
-private:
- ListPopupMenu* m_pMenu; ///< the right mouse button menu
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/pinportbase.cpp umbrello-kf6-15.08.1/umbrello/widgets/pinportbase.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/pinportbase.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/pinportbase.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,378 +0,0 @@
-/***************************************************************************
- * 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) 2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "pinportbase.h"
-
-// app includes
-#include "port.h"
-#include "package.h"
-#include "debug_utils.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-#include "floatingtextwidget.h"
-
-// qt includes
-#include <QPainter>
-#include <QToolTip>
-
-// sys includes
-#include <cmath>
-
-PinPortBase::PinPortBase(UMLScene *scene, WidgetType type, UMLObject *o)
- : UMLWidget(scene, type, o)
-{
- init();
-}
-
-PinPortBase::PinPortBase(UMLScene *scene, WidgetType type, UMLWidget *a, Uml::ID::Type id)
- : UMLWidget(scene, type, id)
-{
- init(a);
-}
-
-/**
- * Standard destructor.
- */
-PinPortBase::~PinPortBase()
-{
-}
-
-/**
- * Performs initializations which are common to PinWidget and PortWidget.
- */
-void PinPortBase::init(UMLWidget *owner)
-{
- m_ignoreSnapToGrid = true;
- m_ignoreSnapComponentSizeToGrid = true;
- m_resizable = false;
- m_pOw = owner;
- m_pName = NULL;
- m_motionConnected = false;
- const int edgeLength = 15; // old: (m_baseType == wt_Pin ? 10 : 15);
- const QSizeF FixedSize(edgeLength, edgeLength);
- setMinimumSize(FixedSize);
- setMaximumSize(FixedSize);
- setSize(FixedSize);
-}
-
-UMLWidget* PinPortBase::ownerWidget()
-{
- return m_pOw;
-}
-
-/**
- * Overrides method from UMLWidget in order to set a tooltip.
- * The tooltip is set to the name().
- * The reason for using a tooltip for the name is that the size of this
- * widget is not large enough to accommodate the average name.
- */
-void PinPortBase::updateWidget()
-{
- QString strName = name();
- uDebug() << " port name is " << strName;
- if (m_pName) {
- m_pName->setText(strName);
- } else {
- setToolTip(strName);
- }
-}
-
-/**
- * Overrides method from UMLWidget to set the name.
- */
-void PinPortBase::setName(const QString &strName)
-{
- UMLWidget::setName(strName);
- updateGeometry();
- if (m_pName) {
- m_pName->setText(strName);
- }
-}
-
-/**
- * Overridden from UMLWidget.
- * Moves the widget to a new position using the difference between the
- * current position and the new position.
- * Movement is constrained such that the port is always attached to its
- * owner widget.
- *
- * @param diffX The difference between current X position and new X position.
- * @param diffY The difference between current Y position and new Y position.
- */
-void PinPortBase::moveWidgetBy(qreal diffX, qreal diffY)
-{
- UMLWidget* owner = ownerWidget();
- qreal newX = x() + diffX;
- qreal newY = y() + diffY;
- uDebug() << "PinPortBase::moveWidgetBy " << diffX << "," << diffY;
- if (owner == NULL) {
- uError() << "PinPortBase::moveWidgetBy: ownerWidget() returns NULL";
- setX(newX);
- setY(newY);
- return;
- }
- const qreal deltaTop = fabs(y() + height() - owner->y());
- const qreal deltaBottom = fabs(owner->y() + owner->height() - y());
- const qreal deltaLeft = fabs(x() + width() - owner->x());
- const qreal deltaRight = fabs(owner->x() + owner->width() - x());
- bool didAnyMovement = false;
- if (deltaTop < 1.0 || deltaBottom < 1.0) {
- if (newX < owner->x() - width())
- newX = owner->x() - width();
- else if (newX > owner->x() + owner->width())
- newX = owner->x() + owner->width();
- setX(newX);
- didAnyMovement = true;
- }
- if (deltaLeft < 1.0 || deltaRight < 1.0) {
- if (newY < owner->y() - height())
- newY = owner->y() - height();
- else if (newY > owner->y() + owner->height())
- newY = owner->y() + owner->height();
- setY(newY);
- didAnyMovement = true;
- }
- if (!didAnyMovement) {
- uDebug() << "constraint failed for (" << diffX << ", " << diffY << ")";
- setX(newX);
- setY(newY);
- }
-}
-
-/**
- * Align this widget's position such that it is attached at one of the
- * sides of its owner's widget.
- */
-void PinPortBase::attachToOwner() {
- UMLWidget *owner = ownerWidget();
- const QPointF scenePos = m_scene->pos();
- if (owner == NULL) {
- uError() << "PinPortBase::attachToOwner: ownerWidget() returns NULL";
- setX(scenePos.x());
- setY(scenePos.y());
- return;
- }
- bool xIsWithinOwner = false;
- if (scenePos.x() < owner->x() - width()) {
- setX(owner->x() - width());
- } else if (scenePos.x() <= owner->x() + owner->width()) {
- setX(scenePos.x());
- xIsWithinOwner = true;
- } else {
- setX(owner->x() + owner->width());
- }
- if (scenePos.y() < owner->y() - height()) {
- setY(owner->y() - height());
- } else if (scenePos.y() <= owner->y() + owner->height()) {
- if (xIsWithinOwner) {
- if (scenePos.y() <= owner->y() + owner->height() / 2.0)
- setY(owner->y() - height());
- else
- setY(owner->y() + owner->height());
- } else {
- setY(scenePos.y());
- }
- } else {
- setY(owner->y() + owner->height());
- }
-
- if (m_motionConnected) {
- uDebug() << "connectOwnerMotion was already done";
- } else {
- connectOwnerMotion();
- m_motionConnected = true;
- }
-}
-
-/**
- * Overrides standard method.
- */
-void PinPortBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- setPenFromSettings(painter);
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- } else {
- painter->setBrush(m_scene->backgroundColor());
- }
-
- int w = width();
- int h = height();
-
- painter->drawRect(0, 0, w, h);
-
- UMLWidget::paint(painter, option, widget);
-}
-
-void PinPortBase::slotOwnerMoved(qreal diffX, qreal diffY)
-{
- setX(x() + diffX);
- setY(y() + diffY);
-}
-
-/**
- * Captures any popup menu signals for menus it created.
- */
-void PinPortBase::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_NameAsTooltip:
- if (m_pName) {
- action->setChecked(true);
- delete m_pName;
- m_pName = NULL;
- setToolTip(name());
- } else {
- action->setChecked(false);
- m_pName = new FloatingTextWidget(m_scene, Uml::TextRole::Floating, name());
- m_pName->setParentItem(this);
- m_pName->setText(name()); // to get geometry update
- m_pName->activate();
- UMLWidget* owner = ownerWidget();
- if (owner == NULL) {
- uError() << "PinPortBase::slotMenuSelection: ownerWidget() returns NULL";
- setX(x());
- setY(y());
- } else {
- const qreal w = width();
- const qreal h = height();
- if (x() < owner->x())
- m_pName->setX(-m_pName->width());
- else if (x() >= owner->x() + owner->width())
- m_pName->setX(w);
- else
- m_pName->setX(-m_pName->width() / 2.0 + w / 2.0);
- if (y() < owner->y())
- m_pName->setY(-m_pName->height() - 2);
- else if (y() >= owner->y() + owner->height())
- m_pName->setY(h);
- else
- m_pName->setY(-m_pName->height() / 2.0 + h / 2.0);
- }
- m_pName->update();
- setToolTip(QString());
- QToolTip::hideText();
- }
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- }
-}
-
-FloatingTextWidget *PinPortBase::floatingTextWidget() {
- return m_pName;
-}
-
-void PinPortBase::setFloatingTextWidget(FloatingTextWidget *ft) {
- m_pName = ft;
- if (m_pName)
- m_pName->setParentItem(this);
-}
-
-/**
- * Override method from UMLWidget in order to additionally check m_pName.
- *
- * @param p Point to be checked.
- *
- * @return 'this' if UMLWidget::onWidget(p) returns non NULL;
- * m_pName if m_pName is non NULL and m_pName->onWidget(p) returns non NULL;
- * else NULL.
- */
-UMLWidget* PinPortBase::onWidget(const QPointF &p)
-{
- if (UMLWidget::onWidget(p) != NULL)
- return this;
- if (m_pName) {
- uDebug() << "floatingtext: " << m_pName->text();
- return m_pName->onWidget(p);
- }
- return NULL;
-}
-
-/**
- * Reimplement function from UMLWidget
- */
-UMLWidget* PinPortBase::widgetWithID(Uml::ID::Type id)
-{
- if (UMLWidget::widgetWithID(id))
- return this;
- if (m_pName && m_pName->widgetWithID(id))
- return m_pName;
- return NULL;
-}
-
-
-/**
- * Saves the widget to the "pinwidget" or "portwidget" XMI element.
- */
-void PinPortBase::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement element = qDoc.createElement(m_baseType == wt_Pin ? QLatin1String("pinwidget")
- : QLatin1String("portwidget"));
- element.setAttribute(QLatin1String("widgetaid"), Uml::ID::toString(ownerWidget()->id()));
- UMLWidget::saveToXMI(qDoc, element);
- if (m_pName && !m_pName->text().isEmpty()) {
- m_pName->saveToXMI(qDoc, element);
- }
- qElement.appendChild(element);
-}
-
-/**
- * Loads from a "pinwidget" or from a "portwidget" XMI element.
- */
-bool PinPortBase::loadFromXMI(QDomElement & qElement)
-{
- if (!UMLWidget::loadFromXMI(qElement))
- return false;
-
- QString widgetaid = qElement.attribute(QLatin1String("widgetaid"), QLatin1String("-1"));
- Uml::ID::Type aId = Uml::ID::fromString(widgetaid);
- UMLWidget *owner = m_scene->findWidget(aId);
- if (owner == NULL) {
- DEBUG(DBG_SRC) << "owner object " << Uml::ID::toString(aId) << " not found";
- return false;
- }
- m_pOw = owner;
-
- // Optional child element: floatingtext
- QDomNode node = qElement.firstChild();
- QDomElement element = node.toElement();
- if (!element.isNull()) {
- QString tag = element.tagName();
- if (tag == QLatin1String("floatingtext")) {
- m_pName = new FloatingTextWidget(m_scene, Uml::TextRole::Floating,
- name(), Uml::ID::Reserved);
- if (!m_pName->loadFromXMI(element)) {
- // Most likely cause: The FloatingTextWidget is empty.
- delete m_pName;
- m_pName = NULL;
- } else {
- m_pName->setParentItem(this);
- m_pName->activate();
- m_pName->update();
- }
- } else {
- uError() << "unknown tag " << tag;
- }
- }
-
- if (m_motionConnected) {
- uDebug() << "connectOwnerMotion was already done";
- } else {
- connectOwnerMotion();
- m_motionConnected = true;
- }
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/pinportbase.h umbrello-kf6-15.08.1/umbrello/widgets/pinportbase.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/pinportbase.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/pinportbase.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,63 +0,0 @@
-/***************************************************************************
- * 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) 2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef PINPORTBASE_H
-#define PINPORTBASE_H
-
-#include "umlwidget.h"
-
-class FloatingTextWidget;
-
-/**
- * @short Abstract base class for PinWidget and PortWidget
- * @author Oliver Kellogg
- * @see UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class PinPortBase : public UMLWidget
-{
- Q_OBJECT
-public:
- PinPortBase(UMLScene *scene, WidgetType type, UMLObject *o);
- PinPortBase(UMLScene *scene, WidgetType type, UMLWidget *a, Uml::ID::Type id = Uml::ID::None);
- virtual ~PinPortBase();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- virtual UMLWidget* ownerWidget();
- virtual void connectOwnerMotion() = 0;
-
- void setName(const QString &strName);
- void updateWidget();
- void moveWidgetBy(qreal diffX, qreal diffY);
- void attachToOwner();
-
- UMLWidget* onWidget(const QPointF& p);
- UMLWidget* widgetWithID(Uml::ID::Type id);
-
- FloatingTextWidget *floatingTextWidget();
- void setFloatingTextWidget(FloatingTextWidget *ft);
-
- void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
- bool loadFromXMI(QDomElement& qElement);
-
-public slots:
- void slotOwnerMoved(qreal diffX, qreal diffY);
- virtual void slotMenuSelection(QAction* action);
-
-protected:
- void init(UMLWidget *owner = 0);
-
- UMLWidget* m_pOw;
- FloatingTextWidget *m_pName;
- bool m_motionConnected;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/pinwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/pinwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/pinwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/pinwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,103 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "pinwidget.h"
-
-// app includes
-#include "debug_utils.h"
-#include "floatingtextwidget.h"
-#include "listpopupmenu.h"
-#include "umlscene.h"
-#include "activitywidget.h"
-
-// kde includes
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-#include <KLocalizedString>
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-#include <QPainter>
-
-DEBUG_REGISTER_DISABLED(PinWidget)
-
-/**
- * Creates a Pin widget.
- *
- * @param scene The parent of the widget.
- * @param a The widget to which this pin is attached.
- * @param id The ID to assign (-1 will prompt a new ID).
- */
-PinWidget::PinWidget(UMLScene* scene, UMLWidget* a, Uml::ID::Type id)
- : PinPortBase(scene, WidgetBase::wt_Pin, a, id)
-{
- // setParent(a);
- // m_nY = y() < getMinY() ? getMinY() : y();
-
- m_pName = new FloatingTextWidget(m_scene, Uml::TextRole::Floating, name());
- m_pName->setParentItem(this);
- m_pName->setText(name()); // to get geometry update
- m_pName->activate();
- setVisible(true);
-}
-
-/**
- * Destructor.
- */
-PinWidget::~PinWidget()
-{
-}
-
-/**
- * Implement abstract function from PinPortWidget.
- */
-void PinWidget::connectOwnerMotion()
-{
- ActivityWidget *owner = static_cast<ActivityWidget*>(ownerWidget());
- connect(owner, SIGNAL(sigActMoved(qreal,qreal)), this, SLOT(slotOwnerMoved(qreal,qreal)));
-}
-
-/**
- * Captures any popup menu signals for menus it created.
- */
-void PinWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_Rename:
- {
- bool ok = false;
- QString name = m_Text;
-#if QT_VERSION >= 0x050000
- name = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter Pin Name"),
- i18n("Enter the pin name :"),
- QLineEdit::Normal,
- m_Text, &ok);
-#else
- name = KInputDialog::getText(i18n("Enter Pin Name"),
- i18n("Enter the pin name :"),
- m_Text, &ok);
-#endif
- if (ok) {
- setName(name);
- }
- }
- break;
-
- default:
- PinPortBase::slotMenuSelection(action);
- }
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/pinwidget.h umbrello-kf6-15.08.1/umbrello/widgets/pinwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/pinwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/pinwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,46 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef PINWIDGET_H
-#define PINWIDGET_H
-
-#include "pinportbase.h"
-
-/**
- * This class is the graphical version of a UML Pin. A pinWidget is created
- * by a @ref UMLView. An pinWidget belongs to only one @ref UMLView instance.
- * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
- *
- * The pinWidget class inherits from the @ref UMLWidget class which adds most of the functionality
- * to this class.
- *
- * @short A graphical version of a UML pin.
- * @author Hassan KOUCH <hkouch@hotmail.com>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class PinWidget : public PinPortBase
-{
- Q_OBJECT
-public:
-
- PinWidget(UMLScene* scene, UMLWidget* a, Uml::ID::Type id = Uml::ID::None);
- virtual ~PinWidget();
-
- void connectOwnerMotion();
- // int getMinY();
-
-public slots:
- void slotMenuSelection(QAction* action);
-
-// private:
- // int m_nY;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/portwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/portwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/portwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/portwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,106 +0,0 @@
-/***************************************************************************
- * 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) 2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "portwidget.h"
-
-// app includes
-#include "port.h"
-#include "package.h"
-#include "debug_utils.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "componentwidget.h"
-#include "floatingtextwidget.h"
-
-// kde includes
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-#include <KLocalizedString>
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-#include <QPainter>
-#include <QToolTip>
-
-/**
- * Constructs a PortWidget.
- *
- * @param scene The parent of this PortWidget.
- * @param d The UMLPort this will be representing.
- */
-PortWidget::PortWidget(UMLScene *scene, UMLPort *d)
- : PinPortBase(scene, WidgetBase::wt_Port, d)
-{
- setToolTip(d->name());
-}
-
-/**
- * Standard deconstructor.
- */
-PortWidget::~PortWidget()
-{
-}
-
-/**
- * Override function from PinPortWidget.
- */
-UMLWidget* PortWidget::ownerWidget()
-{
- if (m_pOw == NULL) {
- const Uml::ID::Type compWidgetId = m_umlObject->umlPackage()->id();
- m_pOw = m_scene->widgetOnDiagram(compWidgetId);
- }
- return m_pOw;
-}
-
-/**
- * Implement abstract function from PinPortWidget.
- */
-void PortWidget::connectOwnerMotion()
-{
- ComponentWidget *owner = static_cast<ComponentWidget*>(ownerWidget());
- connect(owner, SIGNAL(sigCompMoved(qreal,qreal)), this, SLOT(slotOwnerMoved(qreal,qreal)));
-}
-
-/**
- * Captures any popup menu signals for menus it created.
- */
-void PortWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_Rename:
- {
- bool ok = false;
- QString newName;
-#if QT_VERSION >= 0x050000
- newName = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter Port Name"), i18n("Enter the port name :"),
- QLineEdit::Normal,
- name(), &ok);
-#else
- newName = KInputDialog::getText(i18n("Enter Port Name"), i18n("Enter the port name :"),
- name(), &ok);
-#endif
- if (ok) {
- setName(newName);
- }
- }
- break;
-
- default:
- PinPortBase::slotMenuSelection(action);
- }
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/portwidget.h umbrello-kf6-15.08.1/umbrello/widgets/portwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/portwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/portwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,42 +0,0 @@
-/***************************************************************************
- * 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) 2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef PORTWIDGET_H
-#define PORTWIDGET_H
-
-#include "pinportbase.h"
-
-class UMLPort;
-
-/**
- * Defines a graphical version of the UML2 port. Most of the functionality
- * comes from the @ref PinPortBase class from which this class inherits.
- *
- * @short A graphical version of a port on a component.
- * @author Oliver Kellogg
- * @see PinPortBase, UMLWidget
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class PortWidget : public PinPortBase
-{
- Q_OBJECT
-public:
- PortWidget(UMLScene *scene, UMLPort *d);
- virtual ~PortWidget();
-
- UMLWidget* ownerWidget();
- void connectOwnerMotion();
-
-public slots:
- void slotMenuSelection(QAction* action);
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/preconditionwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/preconditionwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/preconditionwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/preconditionwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,335 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "preconditionwidget.h"
-
-// app includes
-#include "debug_utils.h"
-#include "listpopupmenu.h"
-#include "objectwidget.h"
-#include "uml.h"
-#include "umlscene.h"
-#include "uniqueid.h"
-#include "idchangelog.h"
-
-// kde includes
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-#include <KLocalizedString>
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-#include <QPainter>
-
-DEBUG_REGISTER_DISABLED(PreconditionWidget)
-
-#define PRECONDITION_MARGIN 5
-#define PRECONDITION_WIDTH 30
-#define PRECONDITION_HEIGHT 10
-
-/**
- * Creates a Precondition widget.
- *
- * @param scene The parent of the widget.
- * @param a The role A widget for this precondition.
- * @param id The ID to assign (-1 will prompt a new ID).
- */
-PreconditionWidget::PreconditionWidget(UMLScene* scene, ObjectWidget* a, Uml::ID::Type id)
- : UMLWidget(scene, WidgetBase::wt_Precondition, id),
- m_objectWidget(a)
-{
- m_ignoreSnapToGrid = true;
- m_ignoreSnapComponentSizeToGrid = true;
- m_resizable = true ;
- setVisible(true);
- //updateResizability();
- // calculateWidget();
- if (y() < minY())
- m_nY = minY();
- else if (y() > maxY())
- m_nY = maxY();
- else
- m_nY = y();
-
- activate();
-}
-
-/**
- * Destructor.
- */
-PreconditionWidget::~PreconditionWidget()
-{
-}
-
-/**
- * Overrides the standard paint event.
- */
-void PreconditionWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- int w = width();
- int h = height();
-
- int x = m_objectWidget->x() + m_objectWidget->width() / 2;
- x -= w/2;
- setX(x);
- int y = this->y();
-
- //test if y isn't above the object
- if (y <= m_objectWidget->y() + m_objectWidget->height()) {
- y = m_objectWidget->y() + m_objectWidget->height() + 15;
- }
- if (y + h >= m_objectWidget->getEndLineY()) {
- y = m_objectWidget->getEndLineY() - h;
- }
- setY(y);
- setPenFromSettings(painter);
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- }
- {
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- const QString precondition_value = QLatin1String("{ ") + name() + QLatin1String(" }");
- //int middleX = w / 2;
- int textStartY = (h / 2) - (fontHeight / 2);
- painter->drawRoundRect(0, 0, w, h, (h * 60) / w, 60);
- painter->setPen(textColor());
- painter->setFont(UMLWidget::font());
- painter->drawText(PRECONDITION_MARGIN, textStartY,
- w - PRECONDITION_MARGIN * 2, fontHeight, Qt::AlignCenter, precondition_value);
- }
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overrides method from UMLWidget.
- */
-QSizeF PreconditionWidget::minimumSize() const
-{
- int width = 10, height = 10;
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- const int textWidth = fm.width(name()) + 25;
- height = fontHeight;
- width = textWidth > PRECONDITION_WIDTH ? textWidth : PRECONDITION_WIDTH;
- height = height > PRECONDITION_HEIGHT ? height : PRECONDITION_HEIGHT;
- width += PRECONDITION_MARGIN * 2;
- height += PRECONDITION_MARGIN * 2;
-
- return QSizeF(width, height);
-}
-
-/**
- * Calculate the geometry of the widget.
- */
-void PreconditionWidget::calculateWidget()
-{
- calculateDimensions();
-
- setVisible(true);
-
- setX(m_nPosX);
- setY(m_nY);
-}
-
-/**
- * Activates a PreconditionWidget. Connects the WidgetMoved signal from
- * its m_objectWidget pointer so that PreconditionWidget can adjust to the move of
- * the object widget.
- */
-bool PreconditionWidget::activate(IDChangeLog * Log /*= 0*/)
-{
- m_scene->resetPastep-kf6oint();
- UMLWidget::activate(Log);
-
- loadObjectWidget();
-
- if (!m_objectWidget) {
- DEBUG(DBG_SRC) << "role A widget " << Uml::ID::toString(m_widgetAId)
- << " could not be found";
- return false;
- }
-
- connect(m_objectWidget, SIGNAL(sigWidgetMoved(Uml::ID::Type)), this, SLOT(slotWidgetMoved(Uml::ID::Type)));
-
- calculateDimensions();
- return true;
-}
-
-/**
- * Resolve references of this precondition so it references the correct
- * new object widget after paste.
- */
-void PreconditionWidget::resolveObjectWidget(IDChangeLog* log) {
- m_widgetAId = log->findNewID(m_widgetAId);
-}
-
-/**
- * Calculates the size of the widget.
- */
-void PreconditionWidget::calculateDimensions()
-{
- int x = 0;
- int w = 0;
- int h = 0;
- int x1 = m_objectWidget->x();
- int w1 = m_objectWidget->width() / 2;
-
- x1 += w1;
-
- QSizeF q = minimumSize();
- w = q.width() > width() ? q.width() : width();
- h = q.height() > height() ? q.height() : height();
-
- x = x1 - w/2;
-
- m_nPosX = x;
-
- setSize(w, h);
-}
-
-/**
- * Slot when widget is moved.
- */
-void PreconditionWidget::slotWidgetMoved(Uml::ID::Type id)
-{
- const Uml::ID::Type idA = m_objectWidget->localID();
- if (idA != id) {
- DEBUG(DBG_SRC) << "id=" << Uml::ID::toString(id) << ": ignoring for idA=" << Uml::ID::toString(idA);
- return;
- }
- m_nY = y();
- if (m_nY < minY())
- m_nY = minY();
- if (m_nY > maxY())
- m_nY = maxY();
-
- calculateDimensions();
- if (m_scene->selectedCount(true) > 1)
- return;
-}
-
-/**
- * Returns the minimum height this widget should be set at on
- * a sequence diagrams. Takes into account the widget positions
- * it is related to.
- */
-int PreconditionWidget::minY() const
-{
- if (m_objectWidget) {
- return m_objectWidget->y() + m_objectWidget->height();
- }
- return 0;
-}
-
-/**
- * Returns the maximum height this widget should be set at on
- * a sequence diagrams. Takes into account the widget positions
- * it is related to.
- */
-int PreconditionWidget::maxY() const
-{
- if (m_objectWidget) {
- return ((int)m_objectWidget->getEndLineY() - height());
- }
- return 0;
-}
-
-/**
- * Captures any popup menu signals for menus it created.
- */
-void PreconditionWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_Rename:
- {
- bool ok = false;
- QString text = name();
-#if QT_VERSION >= 0x050000
- text = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter Precondition Name"),
- i18n("Enter the precondition :"),
- QLineEdit::Normal,
- text, &ok);
-#else
- text = KInputDialog::getText(i18n("Enter Precondition Name"),
- i18n("Enter the precondition :"),
- text, &ok);
-#endif
- if (ok && !text.isEmpty()) {
- setName(text);
- }
- calculateWidget();
- }
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- }
-}
-
-/**
- * Saves the widget to the "preconditionwidget" XMI element.
- */
-void PreconditionWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement preconditionElement = qDoc.createElement(QLatin1String("preconditionwidget"));
- UMLWidget::saveToXMI(qDoc, preconditionElement);
-
- preconditionElement.setAttribute(QLatin1String("widgetaid"), Uml::ID::toString(m_objectWidget->localID()));
- preconditionElement.setAttribute(QLatin1String("preconditionname"), name());
- preconditionElement.setAttribute(QLatin1String("documentation"), documentation());
- qElement.appendChild(preconditionElement);
-}
-
-/**
- * Loads the widget from the "preconditionwidget" XMI element.
- */
-bool PreconditionWidget::loadFromXMI(QDomElement& qElement)
-{
- if(!UMLWidget::loadFromXMI(qElement))
- return false;
- QString widgetaid = qElement.attribute(QLatin1String("widgetaid"), QLatin1String("-1"));
- setName(qElement.attribute(QLatin1String("preconditionname")));
- setDocumentation(qElement.attribute(QLatin1String("documentation")));
-
- m_widgetAId = Uml::ID::fromString(widgetaid);
-
- // Lookup the ObjectWidget, if it can't be found, assume it will be
- // resolved later
- loadObjectWidget();
-
- return true;
-}
-
-/**
- * Load the object widget from m_widgetAId
- *
- * This method is called in loadFromXMI() when loading an XMI file, and called
- * from activate() when activating a widget after pasting.
- */
-void PreconditionWidget::loadObjectWidget()
-{
- if (m_objectWidget == 0) {
- m_objectWidget = dynamic_cast<ObjectWidget*>(
- umlScene()->findWidget(m_widgetAId)
- );
- }
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/preconditionwidget.h umbrello-kf6-15.08.1/umbrello/widgets/preconditionwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/preconditionwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/preconditionwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,70 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef PRECONDITIONWIDGET_H
-#define PRECONDITIONWIDGET_H
-
-#include "umlwidget.h"
-
-class ObjectWidget;
-
-/**
- * @short A graphical version of a UML Precondition (new in UML 2.0).
- *
- * This class is the graphical version of a UML Precondition. A PreconditionWidget is created
- * by a @ref UMLView. An PreconditionWidget belongs to only one @ref UMLView instance.
- * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
- *
- * The PreconditionWidget class inherits from the @ref UMLWidget class which adds most of the functionality
- * to this class.
- *
- * @author Florence Mattler <florence.mattler@libertysurf.fr>
- *
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class PreconditionWidget : public UMLWidget
-{
- Q_OBJECT
-public:
- PreconditionWidget(UMLScene* scene, ObjectWidget* a, Uml::ID::Type id = Uml::ID::None);
- virtual ~PreconditionWidget();
-
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- int minY() const;
- int maxY() const;
-
- bool activate(IDChangeLog* Log = 0);
- void resolveObjectWidget(IDChangeLog* log);
-
- virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
- virtual bool loadFromXMI(QDomElement& qElement);
-
- void setObjectWidget(ObjectWidget* widget);
-
-public slots:
- void slotMenuSelection(QAction* action);
- void slotWidgetMoved(Uml::ID::Type id);
-
-protected:
- QSizeF minimumSize() const;
-
-private:
- void calculateWidget();
- void calculateDimensions();
-
- ObjectWidget* m_objectWidget;
- int m_nY;
-
- Uml::ID::Type m_widgetAId;
- void loadObjectWidget();
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/regionwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/regionwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/regionwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/regionwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,108 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "regionwidget.h"
-
-// app includes
-#include "basictypes.h"
-#include "debug_utils.h"
-
-// kde includes
-#include <KLocalizedString>
-
-#define REGION_MARGIN 5
-#define REGION_WIDTH 90
-#define REGION_HEIGHT 45
-
-/**
- * Creates a Region widget.
- *
- * @param scene The parent of the widget.
- * @param id The ID to assign (-1 will prompt a new ID.)
- */
-RegionWidget::RegionWidget(UMLScene* scene, Uml::ID::Type id)
- : UMLWidget(scene, WidgetBase::wt_Region, id)
-{
-}
-
-/**
- * Destructor.
- */
-RegionWidget::~RegionWidget()
-{
-}
-
-/**
- * Overrides the standard paint event.
- */
-void RegionWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- const int w = width();
- const int h = height();
-
- setPenFromSettings(painter);
- QPen pen = painter->pen();
- pen.setColor(Qt::red);
- pen.setStyle(Qt::DashLine);
- painter->setPen(pen);
- painter->drawRoundRect(0, 0, w, h, (h * 60) / w, 60);
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overrides method from UMLWidget
- */
-QSizeF RegionWidget::minimumSize() const
-{
- int width = 10, height = 10;
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- int textWidth = fm.width(name());
-
- height = fontHeight;
- width = textWidth > REGION_WIDTH?textWidth:REGION_WIDTH;
- height = height > REGION_HEIGHT ? height : REGION_HEIGHT;
- width += REGION_MARGIN * 2;
- height += REGION_MARGIN * 2;
-
- return QSizeF(width, height);
-}
-
-/**
- * Saves region widget to XMI element.
- */
-void RegionWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
-{
- QDomElement regionElement = qDoc.createElement(QLatin1String("regionwidget"));
- UMLWidget::saveToXMI(qDoc, regionElement);
- regionElement.setAttribute(QLatin1String("regionname"), name());
- regionElement.setAttribute(QLatin1String("documentation"), documentation());
-
- qElement.appendChild(regionElement);
-}
-
-/**
- * Loads region widget from XMI element.
- */
-bool RegionWidget::loadFromXMI(QDomElement& qElement)
-{
- if (!UMLWidget::loadFromXMI(qElement)) {
- return false;
- }
- setName(qElement.attribute(QLatin1String("regionname")));
- setDocumentation(qElement.attribute(QLatin1String("documentation")));
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/regionwidget.h umbrello-kf6-15.08.1/umbrello/widgets/regionwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/regionwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/regionwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,36 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
-***************************************************************************/
-
-#ifndef REGIONWIDGET_H
-#define REGIONWIDGET_H
-
-#include "umlwidget.h"
-
-/**
- * Represents a rectangular region on Activity diagram.
- */
-class RegionWidget: public UMLWidget
-{
- Q_OBJECT
-public:
- explicit RegionWidget(UMLScene* scene, Uml::ID::Type id = Uml::ID::None);
- virtual ~RegionWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
- bool loadFromXMI(QDomElement& qElement);
-
-protected:
- QSizeF minimumSize() const;
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/seqlinewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/seqlinewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/seqlinewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/seqlinewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,197 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "seqlinewidget.h"
-
-//app includes
-#include "messagewidget.h"
-#include "objectwidget.h"
-#include "umlscene.h"
-#include "umlview.h"
-
-//qt includes
-#include <QPainter>
-
-// class members
-int const SeqLineWidget::m_nMouseDownEpsilonX = 20;
-
-/**
- * Constructor.
- */
-SeqLineWidget::SeqLineWidget(UMLScene *scene, ObjectWidget * pObject)
- : QGraphicsLineItem(),
- m_scene(scene)
-{
- scene->addItem(this);
- m_pObject = pObject;
- setPen(QPen(m_pObject->lineColor(), 0, Qt::DashLine));
- setZValue(0);
- setVisible(true);
- m_DestructionBox.line1 = 0;
- m_nLengthY = 250;
- setupDestructionBox();
-}
-
-/**
- * Destructor.
- */
-SeqLineWidget::~SeqLineWidget()
-{
-}
-
-/**
- * Return whether point is on sequence line.
- * Takes into account destruction box if shown.
- *
- * @param p The point to investigate.
- * @return True if point is on this sequence line.
- */
-bool SeqLineWidget::onWidget(const QPointF & p)
-{
- bool isOnWidget = false;
- QPointF sp = line().p1();
- QPointF ep = line().p2();
- //see if on widget (for message creation)
- if (sp.x() - m_nMouseDownEpsilonX < p.x()
- && ep.x() + m_nMouseDownEpsilonX > p.x()
- && sp.y() < p.y() && ep.y() + 3 > p.y())
- {
- isOnWidget = true;
- }
- return isOnWidget;
-}
-
-/**
- * Return whether point is on the destruction box.
- *
- * @param p The point to investigate.
- * @return True if point is on the destruction box of this sequence line.
- */
-bool SeqLineWidget::onDestructionBox(const QPointF & p)
-{
- bool isOnDestructionBox = false;
- int x = m_pObject->x() + m_pObject->width() / 2;
- int y = m_pObject->y() + m_pObject->height() + m_nLengthY;
-
- //see if on destruction box
- if (!m_pObject->showDestruction()) {
- return false;
- }
- if (x - 10 < p.x() && x + 10 > p.x()
- && y - 10 < p.y() && y + 10 > p.y())
- {
- isOnDestructionBox = true;
- }
- return isOnDestructionBox;
-}
-
-/**
- * Clean up anything before deletion.
- */
-void SeqLineWidget::cleanup()
-{
- cleanupDestructionBox();
-}
-
-/**
- * Set the start point of the line.
- *
- * @param startX X coordinate of the start point.
- * @param startY Y coordinate of the start point.
- */
-void SeqLineWidget::setStartPoint(int startX, int startY)
-{
- int endX = startX;
- int endY = startY + m_nLengthY;
- QGraphicsLineItem::setLine(startX, startY, endX, endY);
- moveDestructionBox();
-}
-
-/**
- * Clean up destruction box.
- */
-void SeqLineWidget::cleanupDestructionBox()
-{
- if (m_DestructionBox.line1) {
- delete m_DestructionBox.line1;
- m_DestructionBox.line1 = 0;
- delete m_DestructionBox.line2;
- m_DestructionBox.line2 = 0;
- }
-}
-
-/**
- * Set up destruction box.
- */
-void SeqLineWidget::setupDestructionBox()
-{
- cleanupDestructionBox();
- if(!m_pObject->showDestruction()) {
- return;
- }
- QRect rect;
- rect.setX(m_pObject->x() + m_pObject->width() / 2 - 10);
- rect.setY(m_pObject->y() + m_pObject->height() + m_nLengthY);
- rect.setWidth(14);
- rect.setHeight(14);
-
- m_DestructionBox.line1 = new QGraphicsLineItem;
- m_scene->addItem(m_DestructionBox.line1);
- m_DestructionBox.setLine1Points(rect);
- m_DestructionBox.line1->setVisible(true);
- m_DestructionBox.line1->setPen(QPen(m_pObject->lineColor(), 2));
- m_DestructionBox.line1->setZValue(3);
-
- m_DestructionBox.line2 = new QGraphicsLineItem;
- m_scene->addItem(m_DestructionBox.line2);
- m_DestructionBox.setLine2Points(rect);
- m_DestructionBox.line2->setVisible(true);
- m_DestructionBox.line2->setPen(QPen(m_pObject->lineColor(), 2));
- m_DestructionBox.line2->setZValue(3);
-}
-
-/**
- * Move destruction box.
- */
-void SeqLineWidget::moveDestructionBox()
-{
- if(!m_DestructionBox.line1) {
- return;
- }
- QRect rect;
- rect.setX(m_pObject->x() + m_pObject->width() / 2 - 7);
- rect.setY(m_pObject->y() + m_pObject->height() + m_nLengthY - 7);
- rect.setWidth(14);
- rect.setHeight(14);
- m_DestructionBox.setLine1Points(rect);
- m_DestructionBox.setLine2Points(rect);
-}
-
-/**
- * Sets the y position of the bottom of the vertical line.
- *
- * @param yPosition The y coordinate for the bottom of the line.
- */
-void SeqLineWidget::setEndOfLine(int yPosition)
-{
- QPointF sp = line().p1();
- int newY = yPosition;
- m_nLengthY = yPosition - m_pObject->y() - m_pObject->height();
- // normally the managing Objectwidget is responsible for the call of this function
- // but to be sure - make a double check _against current position_
- if (m_nLengthY < 0) {
- m_nLengthY = 0;
- newY = m_pObject->y() + m_pObject->height();
- }
- setLine(sp.x(), sp.y(), sp.x(), newY);
- moveDestructionBox();
- m_scene->resizeSceneToItems();
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/seqlinewidget.h umbrello-kf6-15.08.1/umbrello/widgets/seqlinewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/seqlinewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/seqlinewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,86 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef SEQLINEWIDGET_H
-#define SEQLINEWIDGET_H
-
-#include <QGraphicsLineItem>
-
-class ObjectWidget;
-class UMLScene;
-
-/**
- * @short Widget class for graphical representation of sequence lines
- * @author Paul Hensgen
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class SeqLineWidget : public QGraphicsLineItem
-{
-public:
- SeqLineWidget(UMLScene *scene, ObjectWidget * pObject);
- virtual ~SeqLineWidget();
-
- bool onWidget(const QPointF& p);
-
- bool onDestructionBox(const QPointF& p);
-
- void cleanup();
-
- void setupDestructionBox();
-
- void setStartPoint(int startX, int startY);
-
- /**
- * Gets the length of the line.
- *
- * @return Length of the line.
- */
- int getLineLength() {
- return m_nLengthY;
- }
-
- /**
- * Returns the @ref ObjectWidget associated with this sequence line.
- *
- * @return Pointer to the associated ObjectWidget.
- */
- ObjectWidget * getObjectWidget() {
- return m_pObject;
- }
-
- void setEndOfLine(int yPosition);
-
-protected:
- void cleanupDestructionBox();
-
- void moveDestructionBox();
-
- ObjectWidget* m_pObject; ///< ObjectWidget associated with this sequence line
- UMLScene* m_scene; ///< scene displayed on
-
- struct DestructionBox {
- QGraphicsLineItem * line1;
- QGraphicsLineItem * line2;
- void setLine1Points(QRect rect) {
- line1->setLine(rect.x(), rect.y(),
- rect.x() + rect.width(), rect.y() + rect.height());
- }
- void setLine2Points(QRect rect) {
- line2->setLine(rect.x(), rect.y() + rect.height(),
- rect.x() + rect.width(), rect.y());
- }
- } m_DestructionBox; ///< the destruction box
-
- int m_nLengthY; ///< the length of the line
-
- static int const m_nMouseDownEpsilonX; ///< margin used for mouse clicks
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/signalwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/signalwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/signalwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/signalwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,386 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "signalwidget.h"
-
-// app includes
-#include "basictypes.h"
-#include "debug_utils.h"
-#include "floatingtextwidget.h"
-#include "linkwidget.h"
-#include "listpopupmenu.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "uniqueid.h"
-#include "umlview.h"
-#include "umlwidget.h"
-
-// kde includes
-#include <KLocalizedString>
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-
-// qt includes
-#include <QEvent>
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-#include <QPolygon>
-
-/**
- * Creates a Signal widget.
- *
- * @param scene The parent of the widget.
- * @param signalType The type of Signal.
- * @param id The ID to assign (-1 will prompt a new ID.)
- */
-SignalWidget::SignalWidget(UMLScene *scene, SignalType signalType, Uml::ID::Type id)
- : UMLWidget(scene, WidgetBase::wt_Signal, id),
- m_oldX(0),
- m_oldY(0)
-{
- m_signalType = signalType;
- m_pName = NULL;
- if (signalType == SignalWidget::Time) {
- m_pName = new FloatingTextWidget(scene, Uml::TextRole::Floating, QString());
- scene->setupNewWidget(m_pName);
- m_pName->setX(0);
- m_pName->setY(0);
- connect(m_pName, SIGNAL(destroyed()), this, SLOT(slotTextDestroyed()));
- }
-}
-
-/**
- * Destructor.
- */
-SignalWidget::~SignalWidget()
-{
-}
-
-/**
- * Overrides the standard paint event.
- */
-void SignalWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- setPenFromSettings(painter);
- const int w = width();
- const int h = height();
- QPolygon a;
- switch (m_signalType)
- {
- case Send :
- if(UMLWidget::useFillColor())
- painter->setBrush(UMLWidget::fillColor());
- {
- a.setPoints(5, 0, 0,
- (w*2)/3, 0,
- w, h/2,
- (w*2)/3, h,
- 0, h);
- painter->drawPolygon(a);
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- int textStartY = (h / 2) - (fontHeight / 2);
-
- painter->setPen(textColor());
- QFont font = UMLWidget::font();
- font.setBold(false);
- painter->setFont(font);
- painter->drawText(SIGNAL_MARGIN, textStartY,
- w - SIGNAL_MARGIN * 2, fontHeight,
- Qt::AlignCenter, name());
- setPenFromSettings(painter);
- }
- break;
- case Accept :
- if(UMLWidget::useFillColor())
- painter->setBrush(UMLWidget::fillColor());
- {
- a.setPoints(5, 0, 0,
- w/3, h/2,
- 0, h,
- w, h,
- w, 0);
-
- painter->drawPolygon(a);
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- int textStartY = (h / 2) - (fontHeight / 2);
-
- painter->setPen(textColor());
- QFont font = UMLWidget::font();
- font.setBold(false);
- painter->setFont(font);
- painter->drawText(SIGNAL_MARGIN, textStartY,
- w - SIGNAL_MARGIN * 2 + (w/3), fontHeight,
- Qt::AlignCenter, name());
- setPenFromSettings(painter);
- }
- break;
- case Time :
- if(UMLWidget::useFillColor())
- painter->setBrush(UMLWidget::fillColor());
- {
- a.setPoints(4, 0, 0,
- w, h,
- 0, h,
- w, 0);
-
- painter->drawPolygon(a);
- //const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- //const int fontHeight = fm.lineSpacing();
- //int textStartY = (h / 2) - (fontHeight / 2);
- painter->setPen(textColor());
- QFont font = UMLWidget::font();
- font.setBold(false);
- painter->setFont(font);
-
- setPenFromSettings(painter);
- }
- if (m_pName) {
- if (m_pName->x() == 0 && m_pName->y() == 0) {
- //the floating text has not been linked with the signal
- m_pName->setX(w/2 - m_pName->width()/2);
- m_pName->setY(h);
- }
- m_pName->setVisible((m_pName->text().length() > 0));
- m_pName->updateGeometry();
- }
-
- break;
- default:
- uWarning() << "Unknown signal type:" << m_signalType;
- break;
- }
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overrides the UMLWidget method.
- */
-void SignalWidget::setX(qreal newX)
-{
- m_oldX = x();
- UMLWidget::setX(newX);
-}
-
-/**
- * Overrides the UMLWidget method.
- */
-void SignalWidget::setY(qreal newY)
-{
- m_oldY = y();
- UMLWidget::setY(newY);
-}
-
-/**
- * Sets the name of the signal.
- */
-void SignalWidget::setName(const QString &strName)
-{
- UMLWidget::setName(strName);
- updateGeometry();
- if (signalType() == SignalWidget::Time) {
- if (!m_pName) {
- m_pName = new FloatingTextWidget(umlScene(), Uml::TextRole::Floating, m_Text);
- umlScene()->setupNewWidget(m_pName);
- m_pName->setX(0);
- m_pName->setY(0);
- connect(m_pName, SIGNAL(destroyed()), this, SLOT(slotTextDestroyed()));
- }
- else
- m_pName->setText(m_Text);
- }
-}
-
-/**
- * Returns the type of Signal.
- */
-SignalWidget::SignalType SignalWidget::signalType() const
-{
- return m_signalType;
-}
-
-/**
- * Returns the type string of Signal.
- */
-QString SignalWidget::signalTypeStr() const
-{
- return QLatin1String(ENUM_NAME(SignalWidget, SignalType, m_signalType));
-}
-
-/**
- * Sets the type of Signal.
- */
-void SignalWidget::setSignalType(SignalType signalType)
-{
- m_signalType = signalType;
-}
-
-/**
- * Show a properties dialog for a UMLWidget.
- */
-void SignalWidget::showPropertiesDialog()
-{
-}
-
-/**
- * Overrides mouseMoveEvent.
- */
-void SignalWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* me)
-{
- UMLWidget::mouseMoveEvent(me);
- int diffX = m_oldX - x();
- int diffY = m_oldY - y();
- if (m_pName!=NULL) {
- m_pName->setX(m_pName->x() - diffX);
- m_pName->setY(m_pName->y() - diffY);
- }
-}
-
-/**
- * Loads a "signalwidget" XMI element.
- */
-bool SignalWidget::loadFromXMI(QDomElement & qElement)
-{
- if(!UMLWidget::loadFromXMI(qElement))
- return false;
- m_Text = qElement.attribute(QLatin1String("signalname"));
- m_Doc = qElement.attribute(QLatin1String("documentation"));
- QString type = qElement.attribute(QLatin1String("signaltype"));
- QString textid = qElement.attribute(QLatin1String("textid"), QLatin1String("-1"));
- Uml::ID::Type textId = Uml::ID::fromString(textid);
-
- setSignalType((SignalType)type.toInt());
- if (signalType() == Time) {
-
- if (textId != Uml::ID::None) {
- UMLWidget *flotext = m_scene -> findWidget(textId);
- if (flotext != NULL) {
- // This only happens when loading files produced by
- // umbrello-kf6-1.3-beta2.
- m_pName = static_cast<FloatingTextWidget*>(flotext);
- return true;
- }
- } else {
- // no textid stored -> get unique new one
- textId = UniqueID::gen();
- }
- }
- //now load child elements
- QDomNode node = qElement.firstChild();
- QDomElement element = node.toElement();
- if (!element.isNull()) {
- QString tag = element.tagName();
- if (tag == QLatin1String("floatingtext") || tag == QLatin1String("UML::FloatingTextWidget")) {
- m_pName = new FloatingTextWidget(m_scene, Uml::TextRole::Floating, m_Text, textId);
- if(! m_pName->loadFromXMI(element)) {
- // Most likely cause: The FloatingTextWidget is empty.
- delete m_pName;
- m_pName = NULL;
- }
- else
- connect(m_pName, SIGNAL(destroyed()), this, SLOT(slotTextDestroyed()));
- } else {
- uError() << "unknown tag " << tag;
- }
- }
- return true;
-}
-
-/**
- * Creates the "signalwidget" XMI element.
- */
-void SignalWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement signalElement = qDoc.createElement(QLatin1String("signalwidget"));
- UMLWidget::saveToXMI(qDoc, signalElement);
- signalElement.setAttribute(QLatin1String("signalname"), m_Text);
- signalElement.setAttribute(QLatin1String("documentation"), m_Doc);
- signalElement.setAttribute(QLatin1String("signaltype"), m_signalType);
- if (m_pName && !m_pName->text().isEmpty()) {
- signalElement.setAttribute(QLatin1String("textid"), Uml::ID::toString(m_pName->id()));
- m_pName -> saveToXMI(qDoc, signalElement);
- }
- qElement.appendChild(signalElement);
-}
-
-/**
- * Show a properties dialog for a SignalWidget.
- *
- */
-void SignalWidget::slotMenuSelection(QAction* action)
-{
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_Rename:
- {
- bool ok = false;
- QString name = m_Text;
-#if QT_VERSION >= 0x050000
- name = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter signal name"),
- i18n("Enter the signal name :"),
- QLineEdit::Normal,
- m_Text, &ok);
-#else
- name = KInputDialog::getText(i18n("Enter signal name"),
- i18n("Enter the signal name :"),
- m_Text, &ok);
-#endif
- if (ok && name.length() > 0) {
- setName(name);
- }
- }
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- }
-}
-
-/**
- * Overrides method from UMLWidget
- */
-QSizeF SignalWidget::minimumSize() const
-{
- int width = SIGNAL_WIDTH, height = SIGNAL_HEIGHT;
- const QFontMetrics &fm = getFontMetrics(FT_BOLD);
- const int fontHeight = fm.lineSpacing();
- int textWidth = fm.width(name());
-
- if (m_signalType == Accept)
- textWidth = int((float)textWidth * 1.3f);
- height = fontHeight;
- if (m_signalType != Time)
- {
- width = textWidth > SIGNAL_WIDTH?textWidth:SIGNAL_WIDTH;
- height = height > SIGNAL_HEIGHT?height:SIGNAL_HEIGHT;
- }
- width += SIGNAL_MARGIN * 2;
- height += SIGNAL_MARGIN * 2;
-
- return QSizeF(width, height);
-}
-
-/**
- * Called if user deletes text widget
- */
-void SignalWidget::slotTextDestroyed()
-{
- m_pName = 0;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/signalwidget.h umbrello-kf6-15.08.1/umbrello/widgets/signalwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/signalwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/signalwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,86 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
-***************************************************************************/
-
-#ifndef SIGNALWIDGET_H
-#define SIGNALWIDGET_H
-
-#include "floatingtextwidget.h"
-#include "linkwidget.h"
-#include "umlwidget.h"
-#include "worktoolbar.h"
-
-#define SIGNAL_MARGIN 5
-#define SIGNAL_WIDTH 45
-#define SIGNAL_HEIGHT 15
-
-/**
- * Represents a Send signal, Accept signal or Time event on an
- * Activity diagram.
- */
-class SignalWidget : public UMLWidget
-{
- Q_OBJECT
- Q_ENUMS(SignalType)
-public:
- /// Enumeration that codes the different types of signal.
- enum SignalType
- {
- Send = 0,
- Accept,
- Time
- };
-
- explicit SignalWidget(UMLScene * scene, SignalType signalType = Send, Uml::ID::Type id = Uml::ID::None);
- virtual ~SignalWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- void setX(qreal newX);
- void setY(qreal newY);
-
- virtual void setName(const QString &strName);
-
- SignalType signalType() const;
- QString signalTypeStr() const;
- void setSignalType(SignalType signalType);
-
- virtual void showPropertiesDialog();
-
- void mouseMoveEvent(QGraphicsSceneMouseEvent *me);
-
- virtual bool loadFromXMI(QDomElement & qElement);
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
-public Q_SLOTS:
- virtual void slotMenuSelection(QAction* action);
-
-protected:
- QSizeF minimumSize() const;
-
- /**
- * Save the value of the widget to know how to move the floatingtext
- */
- int m_oldX;
- int m_oldY;
-
- // Only for the time event
- /**
- * This is a pointer to the Floating Text widget which displays the
- * name of the signal widget.
- */
- FloatingTextWidget* m_pName;
-
- SignalType m_signalType; ///< Type of signal
-
-protected Q_SLOTS:
- void slotTextDestroyed();
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/statewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/statewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/statewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/statewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,534 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "statewidget.h"
-
-// app includes
-#include "debug_utils.h"
-#include "docwindow.h"
-#include "listpopupmenu.h"
-#include "statedialog.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-#include "umlwidget.h"
-
-// kde includes
-#include <KLocalizedString>
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-#include <QPointer>
-
-/**
- * Creates a State widget.
- *
- * @param scene The parent of the widget.
- * @param stateType The type of state.
- * @param id The ID to assign (-1 will prompt a new ID.)
- */
-StateWidget::StateWidget(UMLScene * scene, StateType stateType, Uml::ID::Type id)
- : UMLWidget(scene, WidgetBase::wt_State, id)
-{
- m_stateType = stateType;
- m_drawVertical = true;
- setAspectRatioMode();
- m_Text = QLatin1String("State");
- QSizeF size = minimumSize();
- setSize(size.width(), size.height());
-}
-
-/**
- * Destructor.
- */
-StateWidget::~StateWidget()
-{
-}
-
-/**
- * Overrides the standard paint event.
- */
-void StateWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- const qreal w = width();
- const qreal h = height();
- if (w == 0 || h == 0)
- return;
-
- setPenFromSettings(painter);
- switch (m_stateType) {
- case StateWidget::Normal:
- {
- if (UMLWidget::useFillColor()) {
- painter->setBrush(UMLWidget::fillColor());
- }
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- int textStartY = (h / 2) - (fontHeight / 2);
- const int count = m_Activities.count();
- if (count == 0) {
- painter->drawRoundRect(0, 0, w, h, (h*40)/w, (w*40)/h);
- painter->setPen(textColor());
- QFont font = UMLWidget::font();
- font.setBold(false);
- painter->setFont(font);
- painter->drawText(STATE_MARGIN, textStartY,
- w - STATE_MARGIN * 2, fontHeight,
- Qt::AlignCenter, name());
- setPenFromSettings(painter);
- } else {
- painter->drawRoundRect(0, 0, w, h, (h*40)/w, (w*40)/h);
- textStartY = STATE_MARGIN;
- painter->setPen(textColor());
- QFont font = UMLWidget::font();
- font.setBold(true);
- painter->setFont(font);
- painter->drawText(STATE_MARGIN, textStartY, w - STATE_MARGIN * 2,
- fontHeight, Qt::AlignCenter, name());
- font.setBold(false);
- painter->setFont(font);
- setPenFromSettings(painter);
- int linePosY = textStartY + fontHeight;
-
- QStringList::Iterator end(m_Activities.end());
- for(QStringList::Iterator it(m_Activities.begin()); it != end; ++it) {
- textStartY += fontHeight;
- painter->drawLine(0, linePosY, w, linePosY);
- painter->setPen(textColor());
- painter->drawText(STATE_MARGIN, textStartY, w - STATE_MARGIN * 2,
- fontHeight, Qt::AlignCenter, *it);
- setPenFromSettings(painter);
- linePosY += fontHeight;
- }//end for
- }//end else
- }
- break;
- case StateWidget::Initial :
- painter->setBrush(WidgetBase::lineColor());
- painter->drawEllipse(0, 0, w, h);
- break;
- case StateWidget::End :
- painter->setBrush(WidgetBase::lineColor());
- painter->drawEllipse(0, 0, w, h);
- painter->setBrush(Qt::white);
- painter->drawEllipse(1, 1, w - 2, h - 2);
- painter->setBrush(WidgetBase::lineColor());
- painter->drawEllipse(3, 3, w - 6, h - 6);
- break;
- case StateWidget::Fork:
- case StateWidget::Join:
- {
- painter->setPen(Qt::black);
- painter->setBrush(Qt::black);
- painter->drawRect(rect());
- }
- break;
- case StateWidget::Junction:
- {
- painter->setPen(Qt::black);
- painter->setBrush(Qt::black);
- painter->drawEllipse(rect());
- }
- break;
- case StateWidget::DeepHistory:
- {
- painter->setBrush(Qt::white);
- painter->drawEllipse(rect());
- painter->setPen(Qt::black);
- painter->setFont(UMLWidget::font());
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing() / 2;
- const int xStar = fm.boundingRect(QLatin1String("H")).width();
- const int yStar = fontHeight / 4;
- painter->drawText((w / 6),
- (h / 4) + fontHeight, QLatin1String("H"));
- painter->drawText((w / 6) + xStar,
- (h / 4) + fontHeight - yStar, QLatin1String("*"));
- }
- break;
- case StateWidget::ShallowHistory:
- {
- painter->setBrush(Qt::white);
- painter->drawEllipse(rect());
- painter->setPen(Qt::black);
- painter->setFont(UMLWidget::font());
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing() / 2;
- painter->drawText((w / 6),
- (h / 4) + fontHeight, QLatin1String("H"));
- }
- break;
- case StateWidget::Choice:
- {
- const qreal x = w / 2;
- const qreal y = h / 2;
- QPolygonF polygon;
- polygon << QPointF(x, 0) << QPointF(w, y)
- << QPointF(x, h) << QPointF(0, y);
- painter->setBrush(UMLWidget::fillColor());
- painter->drawPolygon(polygon);
- }
- break;
- default:
- uWarning() << "Unknown state type: " << stateTypeStr();
- break;
- }
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Overrides method from UMLWidget
- */
-QSizeF StateWidget::minimumSize() const
-{
- int width = 10, height = 10;
- switch (m_stateType) {
- case StateWidget::Normal:
- {
- const QFontMetrics &fm = getFontMetrics(FT_BOLD);
- const int fontHeight = fm.lineSpacing();
- int textWidth = fm.width(name());
- const int count = m_Activities.count();
- height = fontHeight;
- if(count > 0) {
- height = fontHeight * (count + 1);
-
- QStringList::ConstIterator end(m_Activities.end());
- for(QStringList::ConstIterator it(m_Activities.begin()); it != end; ++it) {
- int w = fm.width(*it);
- if(w > textWidth)
- textWidth = w;
- }//end for
- }//end if
- width = textWidth > STATE_WIDTH?textWidth:STATE_WIDTH;
- height = height > STATE_HEIGHT?height:STATE_HEIGHT;
- width += STATE_MARGIN * 2;
- height += STATE_MARGIN * 2;
- break;
- }
- case StateWidget::Fork:
- case StateWidget::Join:
- if (m_drawVertical) {
- width = 8;
- height = 60;
- } else {
- width = 60;
- height = 8;
- }
- break;
- case StateWidget::Junction:
- width = 18;
- height = 18;
- break;
- case StateWidget::DeepHistory:
- case StateWidget::ShallowHistory:
- {
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- width = height = fm.lineSpacing();
- }
- break;
- case StateWidget::Choice:
- width = 25;
- height = 25;
- break;
- default:
- break;
- }
-
- return QSizeF(width, height);
-}
-
-/**
- * Overrides method from UMLWidget
- */
-QSizeF StateWidget::maximumSize()
-{
- switch (m_stateType) {
- case StateWidget::Initial:
- case StateWidget::End:
- case StateWidget::Junction:
- case StateWidget::Choice:
- return QSizeF(35, 35);
- break;
- case StateWidget::DeepHistory:
- case StateWidget::ShallowHistory:
- {
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- return QSizeF(fontHeight + 10, fontHeight + 10);
- }
- break;
- default:
- break;
- }
- return UMLWidget::maximumSize();
-}
-
-/**
- * Set the aspect ratio mode.
- * Some state types have a fixed aspect ratio
- */
-void StateWidget::setAspectRatioMode()
-{
- switch (m_stateType) {
- case StateWidget::Initial:
- case StateWidget::End:
- case StateWidget::Choice:
- case StateWidget::DeepHistory:
- case StateWidget::ShallowHistory:
- case StateWidget::Fork:
- case StateWidget::Join:
- case StateWidget::Junction:
- setFixedAspectRatio(true);
- break;
- default:
- setFixedAspectRatio(false);
- break;
- }
-}
-
-/**
- * Returns the type of state.
- * @return StateType
- */
-StateWidget::StateType StateWidget::stateType() const
-{
- return m_stateType;
-}
-
-/**
- * Returns the type string of state.
- */
-QString StateWidget::stateTypeStr() const
-{
- return QLatin1String(ENUM_NAME(StateWidget, StateType, m_stateType));
-}
-
-/**
- * Sets the type of state.
- */
-void StateWidget::setStateType(StateType stateType)
-{
- m_stateType = stateType;
- setAspectRatioMode();
-}
-
-/**
- * Adds an activity to this widget.
- * @return true on success
- */
-bool StateWidget::addActivity(const QString &activity)
-{
- m_Activities.append(activity);
- updateGeometry();
- return true;
-}
-
-/**
- * Removes the given activity from the state.
- */
-bool StateWidget::removeActivity(const QString &activity)
-{
- if(m_Activities.removeAll(activity) == 0)
- return false;
- updateGeometry();
- return true;
-}
-
-/**
- * Renames the given activity.
- */
-bool StateWidget::renameActivity(const QString &activity, const QString &newName)
-{
- int index = - 1;
- if((index = m_Activities.indexOf(activity)) == -1)
- return false;
- m_Activities[ index ] = newName;
- return true;
-}
-
-/**
- * Sets the states activities to the ones given.
- */
-void StateWidget::setActivities(const QStringList &list)
-{
- m_Activities = list;
- updateGeometry();
-}
-
-/**
- * Returns the list of activities.
- */
-QStringList StateWidget::activities() const
-{
- return m_Activities;
-}
-
-/**
- * Get whether to draw a fork or join vertically.
- */
-bool StateWidget::drawVertical() const
-{
- return m_drawVertical;
-}
-
-/**
- * Set whether to draw a fork or join vertically.
- */
-void StateWidget::setDrawVertical(bool to)
-{
- m_drawVertical = to;
- setSize(height(), width());
- updateGeometry();
- UMLWidget::adjustAssocs(x(), y());
-}
-
-/**
- * Show a properties dialog for a StateWidget.
- */
-void StateWidget::showPropertiesDialog()
-{
- UMLApp::app()->docWindow()->updateDocumentation(false);
-
- QPointer<StateDialog> dialog = new StateDialog(m_scene->activeView(), this);
- if (dialog->exec() && dialog->getChangesMade()) {
- UMLApp::app()->docWindow()->showDocumentation(this, true);
- UMLApp::app()->document()->setModified(true);
- }
- delete dialog;
-}
-
-/**
- * Creates the "statewidget" XMI element.
- */
-void StateWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement stateElement = qDoc.createElement(QLatin1String("statewidget"));
- UMLWidget::saveToXMI(qDoc, stateElement);
- stateElement.setAttribute(QLatin1String("statename"), m_Text);
- stateElement.setAttribute(QLatin1String("documentation"), m_Doc);
- stateElement.setAttribute(QLatin1String("statetype"), m_stateType);
- if (m_stateType == Fork || m_stateType == Join)
- stateElement.setAttribute(QLatin1String("drawvertical"), m_drawVertical);
- //save states activities
- QDomElement activitiesElement = qDoc.createElement(QLatin1String("Activities"));
-
- QStringList::Iterator end(m_Activities.end());
- for(QStringList::Iterator it(m_Activities.begin()); it != end; ++it) {
- QDomElement tempElement = qDoc.createElement(QLatin1String("Activity"));
- tempElement.setAttribute(QLatin1String("name"), *it);
- activitiesElement.appendChild(tempElement);
- }//end for
- stateElement.appendChild(activitiesElement);
- qElement.appendChild(stateElement);
-}
-
-/**
- * Loads a "statewidget" XMI element.
- */
-bool StateWidget::loadFromXMI(QDomElement & qElement)
-{
- if(!UMLWidget::loadFromXMI(qElement))
- return false;
- m_Text = qElement.attribute(QLatin1String("statename"));
- m_Doc = qElement.attribute(QLatin1String("documentation"));
- QString type = qElement.attribute(QLatin1String("statetype"), QLatin1String("1"));
- m_stateType = (StateType)type.toInt();
- setAspectRatioMode();
- QString drawVertical = qElement.attribute(QLatin1String("drawvertical"), QLatin1String("1"));
- m_drawVertical = (bool)drawVertical.toInt();
- //load states activities
- QDomNode node = qElement.firstChild();
- QDomElement tempElement = node.toElement();
- if(!tempElement.isNull() && tempElement.tagName() == QLatin1String("Activities")) {
- QDomNode node = tempElement.firstChild();
- QDomElement activityElement = node.toElement();
- while(!activityElement.isNull()) {
- if(activityElement.tagName() == QLatin1String("Activity")) {
- QString name = activityElement.attribute(QLatin1String("name"));
- if(!name.isEmpty())
- m_Activities.append(name);
- }//end if
- node = node.nextSibling();
- activityElement = node.toElement();
- }//end while
- }//end if
- return true;
-}
-
-/**
- * Captures any popup menu signals for menus it created.
- */
-void StateWidget::slotMenuSelection(QAction* action)
-{
- bool ok = false;
- QString nameNew = name();
-
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action);
- switch(sel) {
- case ListPopupMenu::mt_Rename:
-#if QT_VERSION >= 0x050000
- nameNew = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter State Name"),
- i18n("Enter the name of the new state:"),
- QLineEdit::Normal,
- name(), &ok);
-#else
- nameNew = KInputDialog::getText(i18n("Enter State Name"),
- i18n("Enter the name of the new state:"),
- name(), &ok);
-#endif
- if (ok && nameNew.length() > 0) {
- setName(nameNew);
- }
- break;
-
- case ListPopupMenu::mt_Properties:
- showPropertiesDialog();
- break;
-
- case ListPopupMenu::mt_New_Activity:
-#if QT_VERSION >= 0x050000
- nameNew = QInputDialog::getText(Q_NULLPTR,
- i18n("Enter Activity"),
- i18n("Enter the name of the new activity:"),
- QLineEdit::Normal,
- i18n("new activity"), &ok);
-#else
- nameNew = KInputDialog::getText(i18n("Enter Activity"),
- i18n("Enter the name of the new activity:"),
- i18n("new activity"), &ok);
-#endif
- if (ok && nameNew.length() > 0) {
- addActivity(nameNew);
- }
- break;
-
- case ListPopupMenu::mt_Flip:
- setDrawVertical(!m_drawVertical);
- break;
-
- default:
- UMLWidget::slotMenuSelection(action);
- break;
- }
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/statewidget.h umbrello-kf6-15.08.1/umbrello/widgets/statewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/statewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/statewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,99 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
-***************************************************************************/
-
-#ifndef STATEWIDGET_H
-#define STATEWIDGET_H
-
-#include "umlwidget.h"
-
-#include <QPainter>
-#include <QStringList>
-
-#define STATE_MARGIN 5
-#define STATE_WIDTH 30
-#define STATE_HEIGHT 10
-
-/**
- * This class is the graphical version of a UML State.
- *
- * A StateWidget is created by a @ref UMLView. A StateWidget belongs to
- * only one @ref UMLView instance.
- * When the @ref UMLView instance that this class belongs to is destroyed,
- * it will be automatically deleted.
- *
- * The StateWidget class inherits from the @ref UMLWidget class
- * which adds most of the functionality to this class.
- *
- * @short A graphical version of a UML State.
- * @author Paul Hensgen <phensgen@techie.com>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class StateWidget : public UMLWidget
-{
- Q_OBJECT
- Q_ENUMS(StateType)
-public:
- /// Enumeration that codes the different types of state.
- enum StateType
- {
- Initial = 0, // Pseudostate
- Normal,
- End,
- Fork, // Pseudostate
- Join, // Pseudostate
- Junction, // Pseudostate
- DeepHistory, // Pseudostate
- ShallowHistory, // Pseudostate
- Choice // Pseudostate
- //Terminate // Pseudostate
- //EntryPoint // Pseudostate
- //ExitPoint // Pseudostate
- };
-
- explicit StateWidget(UMLScene * scene, StateType stateType = Normal, Uml::ID::Type id = Uml::ID::None);
- virtual ~StateWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- StateType stateType() const;
- QString stateTypeStr() const;
- void setStateType(StateType stateType);
-
- bool addActivity(const QString &activity);
- bool removeActivity(const QString &activity);
- bool renameActivity(const QString &activity, const QString &newName);
-
- QStringList activities() const;
- void setActivities(const QStringList &list);
-
- bool drawVertical() const;
- void setDrawVertical(bool to = true);
-
- virtual void showPropertiesDialog();
-
- virtual bool loadFromXMI(QDomElement & qElement);
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
-protected:
- QSizeF minimumSize() const;
- QSizeF maximumSize();
- void setAspectRatioMode();
-
-public Q_SLOTS:
- virtual void slotMenuSelection(QAction* action);
-
-private:
- StateType m_stateType; ///< Type of state.
- bool m_drawVertical; ///< whether to draw the fork/join horizontally or vertically
- QStringList m_Activities; ///< List of activities for the state.
-
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/statusbartoolbutton.cpp umbrello-kf6-15.08.1/umbrello/widgets/statusbartoolbutton.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/statusbartoolbutton.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/statusbartoolbutton.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,122 +0,0 @@
-// vim: set tabstop=4 shiftwidth=4 noexpandtab:
-/*
-Widget taken from gwenview-kf6
-Copyright 2007 Aurélien Gâteau <agateau@kde.org>
-
-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.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR purpose-kf6. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-*/
-// Self
-#include "statusbartoolbutton.h"
-
-// Qt
-#include <QAction>
-#include <QStyleOptionToolButton>
-#include <QStylePainter>
-#include <QToolButton>
-
-// KDE
-#include <KLocalizedString>
-
-StatusBarToolButton::StatusBarToolButton(QWidget* parent)
- : QToolButton(parent),
- mGroupPosition(NotGrouped)
-{
- setToolButtonStyle(Qt::ToolButtonTextOnly);
- setFocusPolicy(Qt::NoFocus);
- setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
-}
-
-
-QSize StatusBarToolButton::minimumSizeHint() const
-{
- return sizeHint();
-}
-
-
-QSize StatusBarToolButton::sizeHint() const
-{
- QSize sh = QToolButton::sizeHint();
- sh.setHeight(fontMetrics().height());
- return sh;
-}
-
-
-void StatusBarToolButton::setGroupPosition(StatusBarToolButton::GroupPosition groupPosition)
-{
- mGroupPosition = groupPosition;
-}
-
-
-void StatusBarToolButton::paintEvent(QPaintEvent* event)
-{
- if (mGroupPosition == NotGrouped) {
- QToolButton::paintEvent(event);
- return;
- }
- QStylePainter painter(this);
- QStyleOptionToolButton opt;
- initStyleOption(&opt);
- QStyleOptionToolButton panelOpt = opt;
-
- // Panel
- QRect& panelRect = panelOpt.rect;
- switch (mGroupPosition) {
- case GroupLeft:
- panelRect.setWidth(panelRect.width() * 2);
- break;
- case GroupCenter:
- panelRect.setLeft(panelRect.left() - panelRect.width());
- panelRect.setWidth(panelRect.width() * 3);
- break;
- case GroupRight:
- panelRect.setLeft(panelRect.left() - panelRect.width());
- break;
- case NotGrouped:
- Q_ASSERT(0);
- }
- painter.drawPrimitive(QStyle::PE_PanelButtonTool, panelOpt);
-
- // Separator
- const int y1 = opt.rect.top() + 6;
- const int y2 = opt.rect.bottom() - 6;
- if (mGroupPosition & GroupRight) {
- const int x = opt.rect.left();
- painter.setPen(opt.palette.color(QPalette::Light));
- painter.drawLine(x, y1, x, y2);
- }
- if (mGroupPosition & GroupLeft) {
- const int x = opt.rect.right();
- painter.setPen(opt.palette.color(QPalette::Mid));
- painter.drawLine(x, y1, x, y2);
- }
-
- // Text
- painter.drawControl(QStyle::CE_ToolButtonLabel, opt);
-
- // Filtering message on tooltip text for CJK to remove accelerators.
- // Quoting ktoolbar.cpp:
- // """
- // CJK languages use more verbose accelerator marker: they add a Latin
- // letter in parenthesis, and put accelerator on that. Hence, the default
- // removal of ampersand only may not be enough there, instead the whole
- // parenthesis construct should be removed. Provide these filtering i18n
- // messages so that translators can use Transcript for custom removal.
- // """
- if (!actions().isEmpty()) {
- QAction* action = actions().first();
- setToolTip(i18nc("@info:tooltip of custom toolbar button", "%1", action->toolTip()));
- }
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/statusbartoolbutton.h umbrello-kf6-15.08.1/umbrello/widgets/statusbartoolbutton.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/statusbartoolbutton.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/statusbartoolbutton.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,58 +0,0 @@
-// vim: set tabstop=4 shiftwidth=4 noexpandtab:
-/*
-gwenview-kf6: an image viewer
-Copyright 2007 Aurélien Gâteau <agateau@kde.org>
-
-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.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR purpose-kf6. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-*/
-#ifndef STATUSBARTOOLBUTTON_H
-#define STATUSBARTOOLBUTTON_H
-
-// Qt
-#include <QToolButton>
-
-/**
- * A thin tool button which can be grouped with another and look like one solid-kf6
- * bar:
- *
- * (button1 | button2)
- */
-class StatusBarToolButton : public QToolButton
-{
- Q_OBJECT
-public:
- enum GroupPosition {
- NotGrouped = 0,
- GroupLeft = 1,
- GroupRight = 2,
- GroupCenter = 3
- };
-
- explicit StatusBarToolButton(QWidget* parent = 0);
-
- virtual QSize minimumSizeHint() const;
- virtual QSize sizeHint() const;
-
- void setGroupPosition(StatusBarToolButton::GroupPosition groupPosition);
-
-protected:
- virtual void paintEvent(QPaintEvent* event);
-
-private:
- GroupPosition mGroupPosition;
-};
-
-#endif /* STATUSBARTOOLBUTTON_H */
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/toolbarstateonewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/toolbarstateonewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/toolbarstateonewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/toolbarstateonewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,249 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "toolbarstateonewidget.h"
-
-// app includes
-#include "activitywidget.h"
-#include "dialog_utils.h"
-#include "floatingtextwidget.h"
-#include "messagewidget.h"
-#include "objectwidget.h"
-#include "pinwidget.h"
-#include "portwidget.h"
-#include "preconditionwidget.h"
-#include "regionwidget.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlwidget.h"
-#include "object_factory.h"
-#include "package.h"
-#include "widget_factory.h"
-
-// kde includes
-#include <KLocalizedString>
-#include <KMessageBox>
-#if QT_VERSION < 0x050000
-#include <kinputdialog.h>
-#endif
-
-// qt includes
-#if QT_VERSION >= 0x050000
-#include <QInputDialog>
-#endif
-
-// using namespace Uml;
-
-/**
- * Creates a new ToolBarStateOneWidget.
- *
- * @param umlScene The UMLScene to use.
- */
-ToolBarStateOneWidget::ToolBarStateOneWidget(UMLScene *umlScene)
- : ToolBarStatePool(umlScene),
- m_firstObject(0),
- m_isObjectWidgetLine(false)
-{
-}
-
-/**
- * Destroys this ToolBarStateOneWidget.
- */
-ToolBarStateOneWidget::~ToolBarStateOneWidget()
-{
-}
-
-/**
- * Called when the current tool is changed to use another tool.
- * Executes base method and cleans the message.
- */
-void ToolBarStateOneWidget::cleanBeforeChange()
-{
- ToolBarStatePool::cleanBeforeChange();
-}
-
-/**
- * Called when a mouse event happened.
- * It executes the base method and then updates the position of the
- * message line, if any.
- */
-void ToolBarStateOneWidget::mouseMove(QGraphicsSceneMouseEvent* ome)
-{
- ToolBarStatePool::mouseMove(ome);
-}
-
-/**
- * A widget was removed from the UMLView.
- * If the widget removed was the current widget, the current widget is set
- * to 0.
- * Also, if it was the first object, the message is cleaned.
- */
-void ToolBarStateOneWidget::slotWidgetRemoved(UMLWidget* widget)
-{
- ToolBarState::slotWidgetRemoved(widget);
-}
-
-/**
- * Selects only widgets, but no associations.
- * Overrides base class method.
- * If the press event happened on the line of an object, the object is set
- * as current widget. If the press event happened on a widget, the widget is
- * set as current widget.
- */
-void ToolBarStateOneWidget::setCurrentElement()
-{
- m_isObjectWidgetLine = false;
- ObjectWidget* objectWidgetLine = m_pUMLScene->onWidgetLine(m_pMouseEvent->scenePos());
- if (objectWidgetLine) {
- setCurrentWidget(objectWidgetLine);
- m_isObjectWidgetLine = true;
- return;
- }
-
- UMLWidget *widget = m_pUMLScene->widgetAt(m_pMouseEvent->scenePos());
- if (widget) {
- setCurrentWidget(widget);
- return;
- }
-}
-
-/**
- * Called when the release event happened on a widget.
- * If the button pressed isn't left button or the widget isn't an object
- * widget, the message is cleaned.
- * If the release event didn't happen on the line of an object and the first
- * object wasn't selected, nothing is done. If the first object was already
- * selected, a creation message is made.
- * If the event happened on the line of an object, the first object or the
- * second are set, depending on whether the first object was already set or
- * not.
- */
-void ToolBarStateOneWidget::mouseReleaseWidget()
-{
- WidgetBase::WidgetType type = widgetType();
-
- if (type == WidgetBase::wt_Precondition) {
- m_firstObject = 0;
- }
- if (type == WidgetBase::wt_Pin) {
- m_firstObject = 0;
- }
-
- if (m_pMouseEvent->button() != Qt::LeftButton ||
- (currentWidget()->baseType() != WidgetBase::wt_Object &&
- currentWidget()->baseType() != WidgetBase::wt_Activity &&
- currentWidget()->baseType() != WidgetBase::wt_Component &&
- currentWidget()->baseType() != WidgetBase::wt_Region)) {
- return;
- }
-
- if (!m_firstObject && type == WidgetBase::wt_Pin) {
- setWidget(currentWidget());
- return ;
- }
-
- if (!m_isObjectWidgetLine && !m_firstObject) {
- return;
- }
-
- if (!m_firstObject) {
- setWidget(currentWidget());
- }
-
-}
-
-/**
- * Called when the release event happened on an empty space.
- * Cleans the message.
- * Empty spaces are not only actual empty spaces, but also associations.
- */
-void ToolBarStateOneWidget::mouseReleaseEmpty()
-{
-}
-
-/**
- * Sets the first object of the message using the specified object.
- * The temporal visual message is created and mouse tracking enabled, so
- * mouse events will be delivered.
- *
- * @param firstObject The first object of the message.
- */
-void ToolBarStateOneWidget::setWidget(UMLWidget* firstObject)
-{
- m_firstObject = firstObject;
-
- UMLWidget * umlwidget = 0;
- //m_pUMLScene->viewport()->setMouseTracking(true);
- if (widgetType() == WidgetBase::wt_Precondition) {
- umlwidget = new PreconditionWidget(m_pUMLScene, static_cast<ObjectWidget*>(m_firstObject));
-
- Dialog_Utils::askNameForWidget(umlwidget, i18n("Enter Precondition Name"), i18n("Enter the precondition"), i18n("new precondition"));
- // Create the widget. Some setup functions can remove the widget.
- }
-
- if (widgetType() == WidgetBase::wt_Pin) {
- if (m_firstObject->baseType() == WidgetBase::wt_Activity) {
- umlwidget = new PinWidget(m_pUMLScene, m_firstObject);
- // Create the widget. Some setup functions can remove the widget.
- } else if (m_firstObject->baseType() == WidgetBase::wt_Component) {
- bool pressedOK = false;
-#if QT_VERSION >= 0x050000
- QString name = QInputDialog::getText(UMLApp::app(),
- i18n("Enter Port Name"), i18n("Enter the port"),
- QLineEdit::Normal,
- i18n("new port"),
- &pressedOK);
-#else
- QString name = KInputDialog::getText(i18n("Enter Port Name"), i18n("Enter the port"), i18n("new port"),
- &pressedOK, UMLApp::app());
-#endif
- if (pressedOK) {
- UMLPackage* component = static_cast<UMLPackage*>(m_firstObject->umlObject());
- UMLObject *port = Object_Factory::createUMLObject(UMLObject::ot_Port, name, component);
- umlwidget = Widget_Factory::createWidget(m_pUMLScene, port);
- }
- }
- }
-
- if (umlwidget) {
- m_pUMLScene->setupNewWidget(umlwidget);
- }
-
-}
-
-/**
- * Returns the widget type of this tool.
- *
- * @return The widget type of this tool.
- */
-WidgetBase::WidgetType ToolBarStateOneWidget::widgetType()
-{
- if (getButton() == WorkToolBar::tbb_Seq_Precondition) {
- return WidgetBase::wt_Precondition;
- }
-
- if (getButton() == WorkToolBar::tbb_Pin) {
- return WidgetBase::wt_Pin;
- }
- // Shouldn't happen
- Q_ASSERT(0);
- return WidgetBase::wt_Pin;
-}
-
-/**
- * Goes back to the initial state.
- */
-void ToolBarStateOneWidget::init()
-{
- ToolBarStatePool::init();
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/toolbarstateonewidget.h umbrello-kf6-15.08.1/umbrello/widgets/toolbarstateonewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/toolbarstateonewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/toolbarstateonewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,59 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef TOOLBARSTATEONEWIDGET_H
-#define TOOLBARSTATEONEWIDGET_H
-
-#include "toolbarstatepool.h"
-#include "widgetbase.h"
-
-/**
- * Sequence tool to create components linked with one object in sequence diagram
- * like precondition.
- * With sequence tool, one objects is selected clicking with left button on
- * it
- */
-class ToolBarStateOneWidget : public ToolBarStatePool
-{
- Q_OBJECT
-public:
- explicit ToolBarStateOneWidget(UMLScene *umlScene);
- virtual ~ToolBarStateOneWidget();
-
- virtual void cleanBeforeChange();
-
- // FIXME: obsolete
- virtual void mouseMove(QGraphicsSceneMouseEvent* ome);
-
-public Q_SLOTS:
- virtual void slotWidgetRemoved(UMLWidget* widget);
-
-protected:
- virtual void setCurrentElement();
-
- virtual void mouseReleaseWidget();
- virtual void mouseReleaseEmpty();
-
- void setWidget(UMLWidget* firstObject);
- WidgetBase::WidgetType widgetType();
-
- UMLWidget* m_firstObject; ///< The first object in the message.
-
- /**
- * If there is a current widget, it is true if the press event happened on
- * the line of an object, or false if it happened on a normal UMLWidget.
- */
- bool m_isObjectWidgetLine;
-
-private:
- virtual void init();
-};
-
-#endif //TOOLBARSTATEONEWIDGET_H
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/umlwidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/umlwidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/umlwidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/umlwidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,1859 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "umlwidget.h"
-
-// local includes
-#include "associationwidget.h"
-#include "classifier.h"
-#include "classpropertiesdialog.h"
-#include "cmds.h"
-#include "debug_utils.h"
-#include "docwindow.h"
-#include "floatingtextwidget.h"
-#include "idchangelog.h"
-#include "listpopupmenu.h"
-#include "settingsdialog.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umllistview.h"
-#include "umlobject.h"
-#include "umlscene.h"
-#include "umlview.h"
-#include "uniqueid.h"
-
-// kde includes
-#include <KLocalizedString>
-#include <KMessageBox>
-
-// qt includes
-#include <QApplication>
-#include <QColor>
-#include <QPainter>
-#include <QPointer>
-
-using namespace Uml;
-
-DEBUG_REGISTER_DISABLED(UMLWidget)
-
-const QSizeF UMLWidget::DefaultMinimumSize(50, 20);
-const QSizeF UMLWidget::DefaultMaximumSize(1000, 5000);
-const qreal UMLWidget::defaultMargin = 5;
-
-/**
- * Creates a UMLWidget object.
- *
- * @param scene The view to be displayed on.
- * @param type The WidgetType to construct.
- * This must be set to the appropriate value by the constructors of inheriting classes.
- * @param o The UMLObject to represent.
- */
-UMLWidget::UMLWidget(UMLScene * scene, WidgetType type, UMLObject * o)
- : WidgetBase(scene, type)
-{
- init();
- m_umlObject = o;
- if (m_umlObject) {
- connect(m_umlObject, SIGNAL(modified()), this, SLOT(updateWidget()));
- m_nId = m_umlObject->id();
- }
-}
-
-/**
- * Creates a UMLWidget object.
- *
- * @param scene The view to be displayed on.
- * @param type The WidgetType to construct.
- * This must be set to the appropriate value by the constructors of inheriting classes.
- * @param id The id of the widget.
- * The default value (id_None) will prompt generation of a new ID.
- */
-UMLWidget::UMLWidget(UMLScene *scene, WidgetType type, Uml::ID::Type id)
- : WidgetBase(scene, type)
-{
- init();
- if (id == Uml::ID::None)
- m_nId = UniqueID::gen();
- else
- m_nId = id;
-}
-
-/**
- * Destructor.
- */
-UMLWidget::~UMLWidget()
-{
- cleanup();
-}
-
-/**
- * Assignment operator
- */
-UMLWidget& UMLWidget::operator=(const UMLWidget & other)
-{
- if (this == &other)
- return *this;
-
- WidgetBase::operator=(other);
-
- // assign members loaded/saved
- m_useFillColor = other.m_useFillColor;
- m_usesDiagramFillColor = other.m_usesDiagramFillColor;
- m_usesDiagramUseFillColor = other.m_usesDiagramUseFillColor;
- m_fillColor = other.m_fillColor;
- m_Assocs = other.m_Assocs;
- m_isInstance = other.m_isInstance;
- m_instanceName = other.m_instanceName;
- m_instanceName = other.m_instanceName;
- m_showStereotype = other.m_showStereotype;
- setX(other.x());
- setY(other.y());
- setRect(rect().x(), rect().y(), other.width(), other.height());
-
- // assign volatile (non-saved) members
- m_startMove = other.m_startMove;
- m_nPosX = other.m_nPosX;
- m_doc = other.m_doc; //new
- m_resizable = other.m_resizable;
- for (unsigned i = 0; i < FT_INVALID; ++i)
- m_pFontMetrics[i] = other.m_pFontMetrics[i];
- m_activated = other.m_activated;
- m_ignoreSnapToGrid = other.m_ignoreSnapToGrid;
- m_ignoreSnapComponentSizeToGrid = other.m_ignoreSnapComponentSizeToGrid;
- return *this;
-}
-
-/**
- * Overload '==' operator
- */
-bool UMLWidget::operator==(const UMLWidget& other) const
-{
- if (this == &other)
- return true;
-
- if (m_baseType != other.m_baseType) {
- return false;
- }
-
- if (id() != other.id())
- return false;
-
- /* Testing the associations is already an exaggeration, no?
- The type and ID should uniquely identify an UMLWidget.
- */
- if (m_Assocs.count() != other.m_Assocs.count()) {
- return false;
- }
-
- // if(getBaseType() != wt_Text) // DON'T do this for floatingtext widgets, an infinite loop will result
- // {
- AssociationWidgetListIt assoc_it(m_Assocs);
- AssociationWidgetListIt assoc_it2(other.m_Assocs);
- AssociationWidget * assoc = 0, *assoc2 = 0;
- while (assoc_it.hasNext() && assoc_it2.hasNext()) {
- assoc = assoc_it.next();
- assoc2 = assoc_it2.next();
-
- if (!(*assoc == *assoc2)) {
- return false;
- }
- }
- // }
- return true;
- // NOTE: In the comparison tests we are going to do, we don't need these values.
- // They will actually stop things functioning correctly so if you change these, be aware of that.
- /*
- if(m_useFillColor != other.m_useFillColor)
- return false;
- if(m_nId != other.m_nId)
- return false;
- if(m_nX != other.m_nX)
- return false;
- if(m_nY != other.m_nY)
- return false;
- */
-}
-
-/**
- * Sets the local id of the object.
- *
- * @param id The local id of the object.
- */
-void UMLWidget::setLocalID(Uml::ID::Type id)
-{
- m_nLocalID = id;
-}
-
-/**
- * Returns the local ID for this object. This ID is used so that
- * many objects of the same @ref UMLObject instance can be on the
- * same diagram.
- *
- * @return The local ID.
- */
-Uml::ID::Type UMLWidget::localID() const
-{
- return m_nLocalID;
-}
-
-/**
- * Returns the widget with the given ID.
- * The default implementation tests the following IDs:
- * - m_nLocalID
- * - if m_umlObject is non NULL: m_umlObject->id()
- * - m_nID
- * Composite widgets override this function to test further owned widgets.
- *
- * @param id The ID to test this widget against.
- * @return 'this' if id is either of m_nLocalID, m_umlObject->id(), or m_nId;
- * else NULL.
- */
-UMLWidget* UMLWidget::widgetWithID(Uml::ID::Type id)
-{
- if (id == m_nLocalID ||
- (m_umlObject != NULL && id == m_umlObject->id()) ||
- id == m_nId)
- return this;
- return NULL;
-}
-
-/**
- * Compute the minimum possible width and height.
- *
- * @return QSizeF(mininum_width, minimum_height)
- */
-QSizeF UMLWidget::minimumSize() const
-{
- return m_minimumSize;
-}
-
-/**
- * This method is used to set the minimum size variable for this
- * widget.
- *
- * @param newSize The size being set as minimum.
- */
-void UMLWidget::setMinimumSize(const QSizeF& newSize)
-{
- m_minimumSize = newSize;
-}
-
-/**
- * Compute the maximum possible width and height.
- *
- * @return maximum size
- */
-QSizeF UMLWidget::maximumSize()
-{
- return m_maximumSize;
-}
-
-/**
- * This method is used to set the maximum size variable for this
- * widget.
- *
- * @param newSize The size being set as maximum.
- */
-void UMLWidget::setMaximumSize(const QSizeF& newSize)
-{
- m_maximumSize = newSize;
-}
-
-/**
- * Event handler for context menu events.
- */
-void UMLWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
-{
- WidgetBase::contextMenuEvent(event);
-}
-
-/**
- * Moves the widget to a new position using the difference between the
- * current position and the new position.
- * This method doesn't adjust associations. It only moves the widget.
- *
- * It can be overridden to constrain movement only in one axis even when
- * the user isn't constraining the movement with shift or control buttons, for example.
- * The movement policy set here is applied whenever the widget is moved, being it
- * moving it explicitly, or as a part of a selection but not receiving directly the
- * mouse events.
- *
- * Default behaviour is move the widget to the new position using the diffs.
- * @see constrainMovementForAllWidgets
- *
- * @param diffX The difference between current X position and new X position.
- * @param diffY The difference between current Y position and new Y position.
- */
-void UMLWidget::moveWidgetBy(qreal diffX, qreal diffY)
-{
- setX(x() + diffX);
- setY(y() + diffY);
-}
-
-/**
- * Modifies the value of the diffX and diffY variables used to move the widgets.
- *
- * It can be overridden to constrain movement of all the selected widgets only in one
- * axis even when the user isn't constraining the movement with shift or control
- * buttons, for example.
- * The difference with moveWidgetBy is that the diff positions used here are
- * applied to all the selected widgets instead of only to m_widget, and that
- * moveWidgetBy, in fact, moves the widget, and here simply the diff positions
- * are modified.
- *
- * Default behaviour is do nothing.
- * @see moveWidgetBy
- *
- * @param diffX The difference between current X position and new X position.
- * @param diffY The difference between current Y position and new Y position.
- */
-void UMLWidget::constrainMovementForAllWidgets(qreal &diffX, qreal &diffY)
-{
- Q_UNUSED(diffX) Q_UNUSED(diffY)
-}
-
-/**
- * Bring the widget at the pressed position to the foreground.
- */
-void UMLWidget::toForeground()
-{
- QRectF rect = QRectF(scenePos(), QSizeF(width(), height()));
- QList<QGraphicsItem*> items = scene()->items(rect, Qt::IntersectsItemShape, Qt::DescendingOrder);
- DEBUG(DBG_SRC) << "items at " << rect << " = " << items.count();
- if (items.count() > 1) {
- foreach(QGraphicsItem* i, items) {
- UMLWidget* w = dynamic_cast<UMLWidget*>(i);
- if (w) {
- DEBUG(DBG_SRC) << "item=" << w->name() << " with zValue=" << w->zValue();
- if (w->name() != name()) {
- if (w->zValue() >= zValue()) {
- setZValue(w->zValue() + 1.0);
- DEBUG(DBG_SRC) << "bring to foreground with zValue: " << zValue();
- }
- }
- }
- }
- }
- else {
- setZValue(0.0);
- }
- DEBUG(DBG_SRC) << "zValue is " << zValue();
-}
-
-/**
- * Handles a mouse press event.
- * It'll select the widget (or mark it to be deselected) and prepare it to
- * be moved or resized. Go on reading for more info about this.
- *
- * Widget values and message bar status are saved.
- *
- * If shift or control buttons are pressed, we're in move area no matter
- * where the button was pressed in the widget. Moreover, if the widget
- * wasn't already selected, it's added to the selection. If already selected,
- * it's marked to be deselected when releasing the button (provided it isn't
- * moved).
- * Also, if the widget is already selected with other widgets but shift nor
- * control buttons are pressed, we're in move area. If finally we don't move
- * the widget, it's selected and the other widgets deselected when releasing
- * the left button.
- *
- * If shift nor control buttons are pressed, we're facing a single selection.
- * Depending on the position of the cursor, we're in move or in resize area.
- * If the widget wasn't selected (both when there are no widgets selected, or
- * when there're other widgets selected but not the one receiving the press
- * event) it's selected and the others deselected, if any. If already selected,
- * it's marked to be deselected when releasing the button (provided it wasn't
- * moved or resized).
- *
- * @param event The QGraphicsSceneMouseEvent event.
- */
-void UMLWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
- if (event->button() != Qt::LeftButton) {
- event->ignore();
- return;
- }
- event->accept();
- DEBUG(DBG_SRC) << "widget = " << name() << " / type = " << baseTypeStr();
-
- toForeground();
-
- m_startMovePostion = pos();
- m_startResizeSize = QSizeF(width(), height());
-
- // saving the values of the widget
- m_pressOffset = event->scenePos() - pos();
- DEBUG(DBG_SRC) << "press offset=" << m_pressOffset;
-
- m_oldStatusBarMsg = UMLApp::app()->statusBarMsg();
-
- if (event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) {
- m_shiftPressed = true;
-
- if (event->button() == Qt::LeftButton) {
- m_inMoveArea = true;
- }
-
- if (!isSelected()) {
- selectMultiple(event);
- }
- return;
- }
-
- m_shiftPressed = false;
-
- int count = m_scene->selectedCount(true);
- if (event->button() == Qt::LeftButton) {
- if (isSelected() && count > 1) {
- // single selection is made in release event if the widget wasn't moved
- m_inMoveArea = true;
- m_oldPos = pos();
- return;
- }
-
- if (isInResizeArea(event)) {
- m_inResizeArea = true;
- m_oldW = width();
- m_oldH = height();
- } else {
- m_inMoveArea = true;
- }
- }
-
- // if widget wasn't selected, or it was selected but with other widgets also selected
- if (!isSelected() || count > 1) {
- selectSingle(event);
- }
-}
-
-/**
- * Handles a mouse move event.
- * It resizes or moves the widget, depending on where the cursor is pressed
- * on the widget. Go on reading for more info about this.
- *
- * If resizing, the widget is resized using UMLWidget::resizeWidget (where specific
- * widget resize constraint can be applied), and then the associations are
- * adjusted.
- * The resizing can be constrained also to a specific axis using control
- * and shift buttons. If on or another is pressed, it's constrained to X axis.
- * If both are pressed, it's constrained to Y axis.
- *
- * If not resizing, the widget is being moved. If the move is being started,
- * the selection bounds are set (which includes updating the list of selected
- * widgets).
- * The difference between the previous position of the selection and the new
- * one is got (taking in account the selection bounds so widgets don't go
- * beyond the scene limits). Then, it's constrained to X or Y axis depending
- * on shift and control buttons.
- * A further constraint is made using constrainMovementForAllWidgets (for example,
- * if the widget that receives the event can only be moved in Y axis, with this
- * method the movement of all the widgets in the selection can be constrained to
- * be moved only in Y axis).
- * Then, all the selected widgets are moved using moveWidgetBy (where specific
- * widget movement constraint can be applied) and, if a certain amount of time
- * passed from the last move event, the associations are also updated (they're
- * not updated always to be easy on the CPU). Finally, the scene is resized,
- * and selection bounds updated.
- *
- * @param event The QGraphicsSceneMouseEvent event.
- */
-void UMLWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
-{
- if (m_inResizeArea) {
- resize(event);
- return;
- }
-
- if (!m_moved) {
- UMLApp::app()->document()->writeToStatusBar(i18n("Hold shift or ctrl to move in X axis. Hold shift and control to move in Y axis. Right button click to cancel move."));
-
- m_moved = true;
- //Maybe needed by AssociationWidget
- m_startMove = true;
-
- setSelectionBounds();
- }
-
- QPointF position = event->scenePos() - m_pressOffset;
- qreal diffX = position.x() - x();
- qreal diffY = position.y() - y();
-
- if ((event->modifiers() & Qt::ShiftModifier) && (event->modifiers() & Qt::ControlModifier)) {
- // move only in Y axis
- diffX = 0;
- } else if ((event->modifiers() & Qt::ShiftModifier) || (event->modifiers() & Qt::ControlModifier)) {
- // move only in X axis
- diffY = 0;
- }
-
- constrainMovementForAllWidgets(diffX, diffY);
-
- // nothing to move
- if (diffX == 0 && diffY == 0) {
- return;
- }
-
- QPointF delta = event->scenePos() - event->lastScenePos();
- adjustUnselectedAssocs(delta.x(), delta.y());
-
- DEBUG(DBG_SRC) << "diffX=" << diffX << " / diffY=" << diffY;
- foreach(UMLWidget* widget, umlScene()->selectedWidgets()) {
- widget->moveWidgetBy(diffX, diffY);
- widget->slotSnapToGrid();
- }
-
- // Move any selected associations.
- foreach(AssociationWidget* aw, m_scene->selectedAssocs()) {
- if (aw->isSelected()) {
- aw->moveEntireAssoc(diffX, diffY);
- }
- }
-
- umlScene()->resizeSceneToItems();
-}
-
-/**
- * Handles a mouse release event.
- * It selects or deselects the widget and cancels or confirms the move or
- * resize. Go on reading for more info about this.
- * No matter which tool is selected, Z position of widget is updated.
- *
- * Middle button release resets the selection.
- * Left button release, if it wasn't moved nor resized, selects the widget
- * and deselect the others if it wasn't selected and there were other widgets
- * selected. If the widget was marked to be deselected, deselects it.
- * If it was moved or resized, the document is set to modified if position
- * or size changed. Also, if moved, all the associations are adjusted because
- * the timer could have prevented the adjustment in the last move event before
- * the release.
- * If mouse was pressed in resize area, cursor is set again to normal cursor
- * Right button release if right button was pressed shows the pop up menu for
- * the widget.
- * If left button was pressed, it cancels the move or resize with a mouse move
- * event at the same position than the cursor was when pressed. Another left
- * button release is also sent.
- *
- * @param event The QGraphicsSceneMouseEvent event.
- */
-void UMLWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
-{
- if (!m_moved && !m_resized) {
- if (!m_shiftPressed && (m_scene->selectedCount(true) > 1)) {
- selectSingle(event);
- } else if (!isSelected()) {
- deselect(event);
- }
- } else {
- // Commands
- if (m_moved) {
- int selectionCount = umlScene()->selectedWidgets().count();
- if (selectionCount > 1) {
- UMLApp::app()->beginMacro(i18n("Move widgets"));
- }
- foreach(UMLWidget* widget, umlScene()->selectedWidgets()) {
- UMLApp::app()->executeCommand(new Uml::CmdMoveWidget(widget));
- }
- if (selectionCount > 1) {
- UMLApp::app()->endMacro();
- }
- m_moved = false;
- } else {
- UMLApp::app()->executeCommand(new Uml::CmdResizeWidget(this));
- m_resized = false;
- }
-
- if ((m_inMoveArea && wasPositionChanged()) ||
- (m_inResizeArea && wasSizeChanged())) {
- umlDoc()->setModified(true);
- }
-
- UMLApp::app()->document()->writeToStatusBar(m_oldStatusBarMsg);
- }
-
- if (m_inResizeArea) {
- m_inResizeArea = false;
- m_scene->activeView()->setCursor(Qt::ArrowCursor);
- } else {
- m_inMoveArea = false;
- }
-}
-
-/**
- * Event handler for mouse double click events.
- * @param event the QGraphicsSceneMouseEvent event.
- */
-void UMLWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
-{
- if (event->button() == Qt::LeftButton) {
- DEBUG(DBG_SRC) << "widget = " << name() << " / type = " << baseTypeStr();
- switch(baseType()) {
- case WidgetBase::wt_Message: // will be handled in its class
- QGraphicsItem::mouseDoubleClickEvent(event);
- break;
- default:
- showPropertiesDialog();
- event->accept();
- break;
- }
- }
-}
-
-/**
- * Return the start position of the move action.
- * @return point where the move began
- */
-QPointF UMLWidget::startMovePosition() const
-{
- return m_startMovePostion;
-}
-
-/**
- * Set the start position of the move action.
- * @param position point where the move began
- */
-void UMLWidget::setStartMovePosition(const QPointF &position)
-{
- m_startMovePostion = position;
-}
-
-/**
- * Return the start size of the resize action.
- * @return size where the resize began
- */
-QSizeF UMLWidget::startResizeSize() const
-{
- return m_startResizeSize;
-}
-
-/**
- * Resizes the widget.
- * It's called from resize, after the values are constrained and before
- * the associations are adjusted.
- *
- * Default behaviour is resize the widget using the new size values.
- * @see resize
- *
- * @param newW The new width for the widget.
- * @param newH The new height for the widget.
- */
-void UMLWidget::resizeWidget(qreal newW, qreal newH)
-{
- setSize(newW, newH);
-}
-
-/**
- * When a widget changes this slot captures that signal.
- */
-void UMLWidget::updateWidget()
-{
- updateGeometry();
- switch (m_baseType) {
- case WidgetBase::wt_Class:
- m_scene->createAutoAttributeAssociations(this);
- break;
- case WidgetBase::wt_Entity:
- m_scene->createAutoConstraintAssociations(this);
- break;
- default:
- break;
- }
-
- if (isVisible())
- update();
-}
-
-/**
- * Apply possible constraints to the given candidate width and height.
- * The default implementation limits input values to the bounds returned
- * by minimumSize()/maximumSize().
- *
- * @param width input value, may be modified by the constraint
- * @param height input value, may be modified by the constraint
- */
-void UMLWidget::constrain(qreal& width, qreal& height)
-{
- QSizeF minSize = minimumSize();
- if (width < minSize.width())
- width = minSize.width();
- if (height < minSize.height())
- height = minSize.height();
- QSizeF maxSize = maximumSize();
- if (width > maxSize.width())
- width = maxSize.width();
- if (height > maxSize.height())
- height = maxSize.height();
-
- if (fixedAspectRatio()) {
- QSizeF size = rect().size();
- float aspectRatio = size.width() > 0 ? (float)size.height()/size.width() : 1;
- height = width * aspectRatio;
- }
-}
-
-/**
- * Initializes key attributes of the class.
- */
-void UMLWidget::init()
-{
- m_nId = Uml::ID::None;
- m_nLocalID = UniqueID::gen();
- m_isInstance = false;
- setMinimumSize(DefaultMinimumSize);
- setMaximumSize(DefaultMaximumSize);
-
- m_font = QApplication::font();
- for (int i = (int)FT_INVALID - 1; i >= 0; --i) {
- FontType fontType = (FontType)i;
- setupFontType(m_font, fontType);
- m_pFontMetrics[fontType] = new QFontMetrics(m_font);
- }
-
- if (m_scene) {
- m_useFillColor = true;
- m_usesDiagramFillColor = true;
- m_usesDiagramUseFillColor = true;
- const Settings::OptionState& optionState = m_scene->optionState();
- m_fillColor = optionState.uiState.fillColor;
- m_showStereotype = optionState.classState.showStereoType;
- } else {
- uError() << "SERIOUS PROBLEM - m_scene is NULL";
- m_useFillColor = false;
- m_usesDiagramFillColor = false;
- m_usesDiagramUseFillColor = false;
- m_showStereotype = false;
- }
-
- m_resizable = true;
- m_fixedAspectRatio = false;
-
- m_startMove = false;
- m_activated = false;
- m_ignoreSnapToGrid = false;
- m_ignoreSnapComponentSizeToGrid = false;
- m_doc = UMLApp::app()->document();
- m_nPosX = 0;
- connect(m_scene, SIGNAL(sigFillColorChanged(Uml::ID::Type)), this, SLOT(slotFillColorChanged(Uml::ID::Type)));
- connect(m_scene, SIGNAL(sigLineColorChanged(Uml::ID::Type)), this, SLOT(slotLineColorChanged(Uml::ID::Type)));
- connect(m_scene, SIGNAL(sigTextColorChanged(Uml::ID::Type)), this, SLOT(slotTextColorChanged(Uml::ID::Type)));
- connect(m_scene, SIGNAL(sigLineWidthChanged(Uml::ID::Type)), this, SLOT(slotLineWidthChanged(Uml::ID::Type)));
-
- m_umlObject = 0;
-
- m_oldPos = QPointF();
- m_pressOffset = QPointF();
- m_oldW = 0;
- m_oldH = 0;
-
- m_shiftPressed = false;
- m_inMoveArea = false;
- m_inResizeArea = false;
- m_moved = false;
- m_resized = false;
-
- setZValue(2.0); // default for most widgets
-}
-
-/**
- * This is usually called synchronously after menu.exec() and \a
- * trigger's parent is always the ListPopupMenu which can be used to
- * get the type of action of \a trigger.
- *
- * @note Subclasses can reimplement to handle specific actions and
- * leave the rest to WidgetBase::slotMenuSelection.
- */
-void UMLWidget::slotMenuSelection(QAction *trigger)
-{
- if (!trigger) {
- return;
- }
-
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(trigger);
- switch (sel) {
- case ListPopupMenu::mt_Resize:
- umlScene()->resizeSelection();
- break;
-
- default:
- WidgetBase::slotMenuSelection(trigger);
- break;
- }
-}
-
-/**
- * Captures when another widget moves if this widget is linked to it.
- * @see sigWidgetMoved
- *
- * @param id The id of object behind the widget.
- */
-void UMLWidget::slotWidgetMoved(Uml::ID::Type /*id*/)
-{
-}
-
-/**
- * Captures a color change signal.
- *
- * @param viewID The id of the UMLScene behind the widget.
- */
-void UMLWidget::slotFillColorChanged(Uml::ID::Type viewID)
-{
- //only change if on the diagram concerned
- if (m_scene->ID() != viewID) {
- return;
- }
- if (m_usesDiagramFillColor) {
- WidgetBase::setFillColor(m_scene->fillColor());
- }
- if (m_usesDiagramUseFillColor) {
- WidgetBase::setUseFillColor(m_scene->useFillColor());
- }
- update();
-}
-
-/**
- * Captures a text color change signal.
- *
- * @param viewID The id of the UMLScene behind the widget.
- */
-void UMLWidget::slotTextColorChanged(Uml::ID::Type viewID)
-{
- //only change if on the diagram concerned
- if (m_scene->ID() != viewID)
- return;
- WidgetBase::setTextColor(m_scene->textColor());
- update();
-}
-
-
-/**
- * Captures a line color change signal.
- *
- * @param viewID The id of the UMLScene behind the widget.
- */
-void UMLWidget::slotLineColorChanged(Uml::ID::Type viewID)
-{
- //only change if on the diagram concerned
- if (m_scene->ID() != viewID)
- return;
-
- if (m_usesDiagramLineColor) {
- WidgetBase::setLineColor(m_scene->lineColor());
- }
- update();
-}
-
-/**
- * Captures a linewidth change signal.
- *
- * @param viewID The id of the UMLScene behind the widget.
- */
-void UMLWidget::slotLineWidthChanged(Uml::ID::Type viewID)
-{
- //only change if on the diagram concerned
- if (m_scene->ID() != viewID) {
- return;
- }
- if (m_usesDiagramLineWidth) {
- WidgetBase::setLineWidth(m_scene->lineWidth());
- }
- update();
-}
-
-/**
- * Set the status of using fill color (undo action)
- *
- * @param fc the status of using fill color.
- */
-void UMLWidget::setUseFillColor(bool fc)
-{
- if (useFillColor() != fc) {
- UMLApp::app()->executeCommand(new CmdChangeUseFillColor(this, fc));
- }
-}
-
-/**
- * Set the status of using fill color.
- *
- * @param fc the status of using fill color.
- */
-void UMLWidget::setUseFillColorCmd(bool fc)
-{
- WidgetBase::setUseFillColor(fc);
- update();
-}
-
-/**
- * Overrides the method from WidgetBase.
- */
-void UMLWidget::setTextColorCmd(const QColor &color)
-{
- WidgetBase::setTextColor(color);
- update();
-}
-
-/**
- * Overrides the method from WidgetBase.
- */
-void UMLWidget::setTextColor(const QColor &color)
-{
- if (textColor() != color) {
- UMLApp::app()->executeCommand(new CmdChangeTextColor(this, color));
- update();
- }
-}
-
-/**
- * Overrides the method from WidgetBase.
- */
-void UMLWidget::setLineColorCmd(const QColor &color)
-{
- WidgetBase::setLineColor(color);
- update();
-}
-
-/**
- * Overrides the method from WidgetBase.
- */
-void UMLWidget::setLineColor(const QColor &color)
-{
- if (lineColor() != color) {
- UMLApp::app()->executeCommand(new CmdChangeLineColor(this, color));
- }
-}
-
-/**
- * Overrides the method from WidgetBase, execute CmdChangeLineWidth
- */
-void UMLWidget::setLineWidth(uint width)
-{
- if (lineWidth() != width) {
- UMLApp::app()->executeCommand(new CmdChangeLineWidth(this, width));
- }
-}
-
-/**
- * Overrides the method from WidgetBase.
- */
-void UMLWidget::setLineWidthCmd(uint width)
-{
- WidgetBase::setLineWidth(width);
- update();
-}
-
-/**
- * Sets the background fill color
- *
- * @param color the new fill color
- */
-void UMLWidget::setFillColor(const QColor &color)
-{
- if (fillColor() != color) {
- UMLApp::app()->executeCommand(new CmdChangeFillColor(this, color));
- }
-}
-
-/**
- * Sets the background fill color
- *
- * @param color the new fill color
- */
-void UMLWidget::setFillColorCmd(const QColor &color)
-{
- WidgetBase::setFillColor(color);
- update();
-}
-
-/**
- * Activate the object after serializing it from a QDataStream
- *
- * @param ChangeLog
- * @return true for success
- */
-bool UMLWidget::activate(IDChangeLog* /*ChangeLog = 0 */)
-{
- if (widgetHasUMLObject(m_baseType) && m_umlObject == NULL) {
- m_umlObject = m_doc->findObjectById(m_nId);
- if (m_umlObject == NULL) {
- uError() << "cannot find UMLObject with id=" << Uml::ID::toString(m_nId);
- return false;
- }
- }
- setFontCmd(m_font);
- setSize(width(), height());
- m_activated = true;
- updateGeometry();
- if (m_scene->getPaste()) {
- FloatingTextWidget * ft = 0;
- QPointF point = m_scene->getPastep-kf6oint();
- int x = point.x() + this->x();
- int y = point.y() + this->y();
- if (m_scene->type() == Uml::DiagramType::Sequence) {
- switch (baseType()) {
- case WidgetBase::wt_Object:
- case WidgetBase::wt_Precondition :
- setY(this->y());
- setX(x);
- break;
-
- case WidgetBase::wt_Message:
- setY(this->y());
- setX(x);
- break;
-
- case WidgetBase::wt_Text:
- ft = static_cast<FloatingTextWidget *>(this);
- if (ft->textRole() == Uml::TextRole::Seq_Message) {
- setX(x);
- setY(this->y());
- } else {
- setX(this->x());
- setY(this->y());
- }
- break;
-
- default:
- setY(y);
- break;
- }//end switch base type
- }//end if sequence
- else {
- setX(x);
- setY(y);
- }
- }//end if pastep-kf6oint
- else {
- setX(this->x());
- setY(this->y());
- }
- if (m_scene->getPaste())
- m_scene->createAutoAssociations(this);
- updateGeometry();
- return true;
-}
-
-/**
- * Returns true if the Activate method has been called for this instance
- *
- * @return The activate status.
- */
-bool UMLWidget::isActivated() const
-{
- return m_activated;
-}
-
-/**
- * Set the m_activated flag of a widget but does not perform the Activate method
- *
- * @param active Status of activation is to be set.
- */
-void UMLWidget::setActivated(bool active /*=true*/)
-{
- m_activated = active;
-}
-
-/**
- * Adds an already created association to the list of
- * associations that include this UMLWidget
- */
-void UMLWidget::addAssoc(AssociationWidget* pAssoc)
-{
- if (pAssoc && !m_Assocs.contains(pAssoc)) {
- m_Assocs.append(pAssoc);
- }
-}
-
-/**
- * Removes an already created association from the list of
- * associations that include this UMLWidget
- */
-void UMLWidget::removeAssoc(AssociationWidget* pAssoc)
-{
- if (pAssoc) {
- m_Assocs.removeAll(pAssoc);
- }
-}
-
-/**
- * Adjusts associations with the given co-ordinates
- *
- * @param dx The amount by which the widget moved in X direction.
- * @param dy The amount by which the widget moved in Y direction.
- */
-void UMLWidget::adjustAssocs(qreal dx, qreal dy)
-{
- // don't adjust Assocs on file load, as
- // the original positions, which are stored in XMI
- // should be reproduced exactly
- // (don't try to reposition assocs as long
- // as file is only partly loaded -> reposition
- // could be misguided)
- /// @todo avoid trigger of this event during load
- if (m_doc->loading()) {
- // don't recalculate the assocs during load of XMI
- // -> return immediately without action
- return;
- }
-
- foreach(AssociationWidget* assocwidget, m_Assocs) {
- assocwidget->saveIdealTextPositions();
- }
-
- foreach(AssociationWidget* assocwidget, m_Assocs) {
- assocwidget->widgetMoved(this, dx, dy);
- }
-}
-
-/**
- * Adjusts all unselected associations with the given co-ordinates
- *
- * @param dx The amount by which the widget moved in X direction.
- * @param dy The amount by which the widget moved in Y direction.
- */
-void UMLWidget::adjustUnselectedAssocs(qreal dx, qreal dy)
-{
- foreach(AssociationWidget* assocwidget, m_Assocs) {
- if (!assocwidget->isSelected())
- assocwidget->saveIdealTextPositions();
- }
-
- foreach(AssociationWidget* assocwidget, m_Assocs) {
- if (!assocwidget->isSelected()) {
- assocwidget->widgetMoved(this, dx, dy);
- }
- }
-}
-
-/**
- * Show a properties dialog for a UMLWidget.
- */
-void UMLWidget::showPropertiesDialog()
-{
- // will already be selected so make sure docWindow updates the doc
- // back it the widget
- UMLApp::app()->docWindow()->updateDocumentation(false);
- QPointer<ClassPropertiesDialog> dlg = new ClassPropertiesDialog((QWidget*)UMLApp::app(), this);
-
- if (dlg->exec()) {
- UMLApp::app()->docWindow()->showDocumentation(umlObject(), true);
- m_doc->setModified(true);
- }
- dlg->close(); //wipe from memory
- delete dlg;
-}
-
-/**
- * Move the widget by an X and Y offset relative to
- * the current position.
- */
-void UMLWidget::moveByLocal(qreal dx, qreal dy)
-{
- qreal newX = x() + dx;
- qreal newY = y() + dy;
- setX(newX);
- setY(newY);
- adjustAssocs(dx, dy);
-}
-
-/**
- * Set the pen.
- */
-void UMLWidget::setPenFromSettings(QPainter & p)
-{
- p.setPen(QPen(m_lineColor, m_lineWidth));
-}
-
-/**
- * Set the pen.
- */
-void UMLWidget::setPenFromSettings(QPainter *p)
-{
- p->setPen(QPen(m_lineColor, m_lineWidth));
-}
-
-/**
- * Returns the cursor to be shown when resizing the widget.
- * Default cursor is KCursor::sizeFDiagCursor().
- *
- * @return The cursor to be shown when resizing the widget.
- */
-QCursor UMLWidget::resizeCursor() const
-{
- return Qt::SizeFDiagCursor;
-}
-
-/**
- * Checks if the mouse is in resize area (right bottom corner), and sets
- * the cursor depending on that.
- * The cursor used when resizing is gotten from resizeCursor().
- *
- * @param me The QMouseEVent to check.
- * @return true if the mouse is in resize area, false otherwise.
- */
-bool UMLWidget::isInResizeArea(QGraphicsSceneMouseEvent *me)
-{
- qreal m = 10.0;
- const qreal w = width();
- const qreal h = height();
-
- // If the widget itself is very small then make the resize area small, too.
- // Reason: Else it becomes impossible to do a move instead of resize.
- if (w - m < m || h - m < m) {
- m = 2.0;
- }
-
- if (m_resizable &&
- me->scenePos().x() >= (x() + w - m) &&
- me->scenePos().y() >= (y() + h - m)) {
- m_scene->activeView()->setCursor(resizeCursor());
- return true;
- } else {
- m_scene->activeView()->setCursor(Qt::ArrowCursor);
- return false;
- }
-}
-
-/**
- * calculate content related size of widget.
- *
- * @return calculated widget size
- */
-QSizeF UMLWidget::calculateSize(bool withExtensions /* = true */) const
-{
- Q_UNUSED(withExtensions)
- return QSizeF(width(), height());
-}
-
-/**
- * Resize widget to minimum size.
- */
-void UMLWidget::resize()
-{
- qreal oldW = width();
- qreal oldH = height();
- // @TODO minimumSize() do not work in all cases, we need a dedicated autoResize() method
- QSizeF size = minimumSize();
- setSize(size.width(), size.height());
- DEBUG(DBG_SRC) << "size=" << size;
- adjustAssocs(size.width()-oldW, size.height()-oldH);
-}
-
-/**
- * Resizes the widget and adjusts the associations.
- * It's called when a mouse move event happens and the cursor was
- * in resize area when pressed.
- * Resizing can be constrained to an specific axis using control and shift buttons.
- *
- * @param me The QGraphicsSceneMouseEvent to get the values from.
- */
-void UMLWidget::resize(QGraphicsSceneMouseEvent *me)
-{
- // TODO the status message lies for at least MessageWidget which could only be resized vertical
- UMLApp::app()->document()->writeToStatusBar(i18n("Hold shift or ctrl to move in X axis. Hold shift and control to move in Y axis. Right button click to cancel resize."));
-
- m_resized = true;
-
- qreal newW = m_oldW + me->scenePos().x() - x() - m_pressOffset.x();
- qreal newH = m_oldH + me->scenePos().y() - y() - m_pressOffset.y();
-
- if ((me->modifiers() & Qt::ShiftModifier) && (me->modifiers() & Qt::ControlModifier)) {
- //Move in Y axis
- newW = m_oldW;
- } else if ((me->modifiers() & Qt::ShiftModifier) || (me->modifiers() & Qt::ControlModifier)) {
- //Move in X axis
- newH = m_oldH;
- }
-
- constrain(newW, newH);
- resizeWidget(newW, newH);
- DEBUG(DBG_SRC) << "event=" << me->scenePos() << "/ pos=" << pos() << " / newW=" << newW << " / newH=" << newH;
- QPointF delta = me->scenePos() - me->lastScenePos();
- adjustAssocs(delta.x(), delta.y());
-
- m_scene->resizeSceneToItems();
-}
-
-/**
- * Checks if the size of the widget changed respect to the size that
- * it had when press event was fired.
- *
- * @return true if was resized, false otherwise.
- */
-bool UMLWidget::wasSizeChanged()
-{
- return m_oldW != width() || m_oldH != height();
-}
-
-/**
- * Checks if the position of the widget changed respect to the position that
- * it had when press event was fired.
- *
- * @return true if was moved, false otherwise.
- */
-bool UMLWidget::wasPositionChanged()
-{
- return m_oldPos != pos();
-}
-
-/**
- * Fills m_selectedWidgetsList and sets the selection bounds ((m_min/m_max)X/Y attributes).
- */
-void UMLWidget::setSelectionBounds()
-{
-}
-
-void UMLWidget::setSelectedFlag(bool _select)
-{
- WidgetBase::setSelected(_select);
-}
-
-/**
- * Sets the state of whether the widget is selected.
- *
- * @param _select The state of whether the widget is selected.
- */
-void UMLWidget::setSelected(bool _select)
-{
- WidgetBase::setSelected(_select);
- const WidgetBase::WidgetType wt = m_baseType;
- if (_select) {
- if (m_scene->selectedCount() == 0) {
- if (widgetHasUMLObject(wt)) {
- UMLApp::app()->docWindow()->showDocumentation(m_umlObject, false);
- } else {
- UMLApp::app()->docWindow()->showDocumentation(this, false);
- }
- }//end if
- /* if (wt != wt_Text && wt != wt_Box) {
- setZ(9);//keep text on top and boxes behind so don't touch Z value
- } */
- } else {
- /* if (wt != wt_Text && wt != wt_Box) {
- setZ(m_origZ);
- } */
- if (isSelected())
- UMLApp::app()->docWindow()->updateDocumentation(true);
- }
-
- // TODO: isn't this handled by toForeground() ?
- const QPoint pos(x(), y());
- UMLWidget *bkgnd = m_scene->widgetAt(pos);
- if (bkgnd && bkgnd != this && _select) {
- DEBUG(DBG_SRC) << "setting Z to " << bkgnd->zValue() + 1.0 << ", SelectState: " << _select;
- setZValue(bkgnd->zValue() + 1.0);
- }
-
- update();
-
- // selection changed, we have to make sure the copy and paste items
- // are correctly enabled/disabled
- UMLApp::app()->slotCopyChanged();
-
- // select in tree view as done for diagrams
- if (_select) {
- UMLListViewItem * item = UMLApp::app()->listView()->findItem(id());
- if (item)
- UMLApp::app()->listView()->setCurrentItem(item);
- else
- UMLApp::app()->listView()->clearSelection();
- }
-}
-
-/**
- * Selects the widget and clears the other selected widgets, if any.
- *
- * @param me The QGraphicsSceneMouseEvent which made the selection.
- */
-void UMLWidget::selectSingle(QGraphicsSceneMouseEvent *me)
-{
- m_scene->clearSelected();
-
- // Adds the widget to the selected widgets list, but as it has been cleared
- // only the current widget is selected.
- selectMultiple(me);
-}
-
-/**
- * Selects the widget and adds it to the list of selected widgets.
- *
- * @param me The QGraphicsSceneMouseEvent which made the selection.
- */
-void UMLWidget::selectMultiple(QGraphicsSceneMouseEvent *me)
-{
- Q_UNUSED(me);
-
- setSelected(true);
-}
-
-/**
- * Deselects the widget and removes it from the list of selected widgets.
- *
- * @param me The QGraphicsSceneMouseEvent which made the selection.
- */
-void UMLWidget::deselect(QGraphicsSceneMouseEvent *me)
-{
- Q_UNUSED(me);
-
- setSelected(false);
-}
-
-/**
- * Clears the selection, resets the toolbar and deselects the widget.
- */
-//void UMLWidget::resetSelection()
-//{
-// m_scene->clearSelected();
-// m_scene->resetToolbar();
-// setSelected(false);
-//}
-
-/**
- * Sets the view the widget is on.
- *
- * @param scene The UMLScene the widget is on.
- */
-void UMLWidget::setScene(UMLScene *scene)
-{
- //remove signals from old view - was probably 0 anyway
- disconnect(m_scene, SIGNAL(sigFillColorChanged(Uml::ID::Type)), this, SLOT(slotFillColorChanged(Uml::ID::Type)));
- disconnect(m_scene, SIGNAL(sigTextColorChanged(Uml::ID::Type)), this, SLOT(slotTextColorChanged(Uml::ID::Type)));
- disconnect(m_scene, SIGNAL(sigLineWidthChanged(Uml::ID::Type)), this, SLOT(slotLineWidthChanged(Uml::ID::Type)));
- m_scene = scene;
- connect(m_scene, SIGNAL(sigFillColorChanged(Uml::ID::Type)), this, SLOT(slotFillColorChanged(Uml::ID::Type)));
- connect(m_scene, SIGNAL(sigTextColorChanged(Uml::ID::Type)), this, SLOT(slotTextColorChanged(Uml::ID::Type)));
- connect(m_scene, SIGNAL(sigLineWidthChanged(Uml::ID::Type)), this, SLOT(slotLineWidthChanged(Uml::ID::Type)));
-}
-
-/**
- * Sets the x-coordinate.
- * Currently, the only class that reimplements this method is
- * ObjectWidget.
- *
- * @param x The x-coordinate to be set.
- */
-void UMLWidget::setX(qreal x)
-{
- QGraphicsObject::setX(x);
-}
-
-/**
- * Sets the y-coordinate.
- * Currently, the only class that reimplements this method is
- * ObjectWidget.
- *
- * @param y The y-coordinate to be set.
- */
-void UMLWidget::setY(qreal y)
-{
- QGraphicsObject::setY(y);
-}
-
-/**
- * Used to cleanup any other widget it may need to delete.
- * Used by child classes. This should be called before deleting a widget of a diagram.
- */
-void UMLWidget::cleanup()
-{
-}
-
-/**
- * Tells the widget to snap to grid.
- * Will use the grid settings of the @ref UMLView it belongs to.
- */
-void UMLWidget::slotSnapToGrid()
-{
- if (!m_ignoreSnapToGrid) {
- qreal newX = m_scene->snappedX(x());
- setX(newX);
- qreal newY = m_scene->snappedY(y());
- setY(newY);
- }
-}
-
-/**
- * Returns whether the widget type has an associated UMLObject
- */
-bool UMLWidget::widgetHasUMLObject(WidgetBase::WidgetType type)
-{
- if (type == WidgetBase::wt_Actor ||
- type == WidgetBase::wt_UseCase ||
- type == WidgetBase::wt_Class ||
- type == WidgetBase::wt_Interface ||
- type == WidgetBase::wt_Enum ||
- type == WidgetBase::wt_Datatype ||
- type == WidgetBase::wt_Package ||
- type == WidgetBase::wt_Component ||
- type == WidgetBase::wt_Port ||
- type == WidgetBase::wt_Node ||
- type == WidgetBase::wt_Artifact ||
- type == WidgetBase::wt_Object) {
- return true;
- } else {
- return false;
- }
-}
-
-/**
- * Set m_ignoreSnapToGrid.
- */
-void UMLWidget::setIgnoreSnapToGrid(bool to)
-{
- m_ignoreSnapToGrid = to;
-}
-
-/**
- * Return the value of m_ignoreSnapToGrid.
- */
-bool UMLWidget::getIgnoreSnapToGrid() const
-{
- return m_ignoreSnapToGrid;
-}
-
-/**
- * Sets the size.
- * If m_scene->snapComponentSizeToGrid() is true, then
- * set the next larger size that snaps to the grid.
- */
-void UMLWidget::setSize(qreal width, qreal height)
-{
- // snap to the next larger size that is a multiple of the grid
- if (!m_ignoreSnapComponentSizeToGrid
- && m_scene->snapComponentSizeToGrid()) {
- // integer divisions
- int numX = width / m_scene->snapX();
- int numY = height / m_scene->snapY();
- // snap to the next larger valid value
- if (width > numX * m_scene->snapX())
- width = (numX + 1) * m_scene->snapX();
- if (height > numY * m_scene->snapY())
- height = (numY + 1) * m_scene->snapY();
- }
-
- setRect(rect().x(), rect().y(), width, height);
-}
-
-/**
- * Sets the size with another size.
- */
-void UMLWidget::setSize(const QSizeF& size)
-{
- setSize(size.width(), size.height());
-}
-
-/**
- * Update the size of this widget.
- */
-void UMLWidget::updateGeometry()
-{
- if (m_doc->loading()) {
- return;
- }
- qreal oldW = width();
- qreal oldH = height();
- QSizeF size = calculateSize();
- qreal clipWidth = size.width();
- qreal clipHeight = size.height();
- constrain(clipWidth, clipHeight);
- setSize(clipWidth, clipHeight);
- slotSnapToGrid();
- adjustAssocs(size.width()-oldW, size.height()-oldH);
-}
-
-/**
- * clip the size of this widget against the
- * minimal and maximal limits.
- */
-void UMLWidget::clipSize()
-{
- qreal clipWidth = width();
- qreal clipHeight = height();
- constrain(clipWidth, clipHeight);
- setSize(clipWidth, clipHeight);
-}
-
-/**
- * Template Method, override this to set the default font metric.
- */
-void UMLWidget::setDefaultFontMetrics(QFont &font, UMLWidget::FontType fontType)
-{
- setupFontType(font, fontType);
- setFontMetrics(fontType, QFontMetrics(font));
-}
-
-void UMLWidget::setupFontType(QFont &font, UMLWidget::FontType fontType)
-{
- switch (fontType) {
- case FT_NORMAL:
- font.setBold(false);
- font.setItalic(false);
- font.setUnderline(false);
- break;
- case FT_BOLD:
- font.setBold(true);
- font.setItalic(false);
- font.setUnderline(false);
- break;
- case FT_ITALIC:
- font.setBold(false);
- font.setItalic(true);
- font.setUnderline(false);
- break;
- case FT_UNDERLINE:
- font.setBold(false);
- font.setItalic(false);
- font.setUnderline(true);
- break;
- case FT_BOLD_ITALIC:
- font.setBold(true);
- font.setItalic(true);
- font.setUnderline(false);
- break;
- case FT_BOLD_UNDERLINE:
- font.setBold(true);
- font.setItalic(false);
- font.setUnderline(true);
- break;
- case FT_ITALIC_UNDERLINE:
- font.setBold(false);
- font.setItalic(true);
- font.setUnderline(true);
- break;
- case FT_BOLD_ITALIC_UNDERLINE:
- font.setBold(true);
- font.setItalic(true);
- font.setUnderline(true);
- break;
- default: return;
- }
-}
-
-void UMLWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- if (option->state & QStyle::State_Selected) {
- const qreal w = width();
- const qreal h = height();
- const qreal s = 4;
- QBrush brush(Qt::blue);
- painter->fillRect(0, 0, s, s, brush);
- painter->fillRect(0, 0 + h - s, s, s, brush);
- painter->fillRect(0 + w - s, 0, s, s, brush);
-
- // Draw the resize anchor in the lower right corner.
- // Don't draw it if the widget is so small that the
- // resize anchor would cover up most of the widget.
- if (m_resizable && w >= s+8 && h >= s+8) {
- brush.setColor(Qt::red);
- const int right = 0 + w;
- const int bottom = 0 + h;
- painter->drawLine(right - s, 0 + h - 1, 0 + w - 1, 0 + h - s);
- painter->drawLine(right - (s*2), bottom - 1, right - 1, bottom - (s*2));
- painter->drawLine(right - (s*3), bottom - 1, right - 1, bottom - (s*3));
- } else {
- painter->fillRect(0 + w - s, 0 + h - s, s, s, brush);
- }
- // debug info
- if (Tracer::instance()->isEnabled(QLatin1String(metaObject()->className()))) {
- painter->setPen(Qt::green);
- painter->setBrush(Qt::NoBrush);
- painter->drawPath(shape());
- painter->setPen(Qt::red);
- painter->drawRect(boundingRect());
- // origin
- painter->drawLine(-10, 0, 10, 0);
- painter->drawLine(0, -10, 0, 10);
- }
- }
-
- if (umlScene()->isShowDocumentationIndicator() && hasDocumentation()) {
- const qreal h = height();
- const qreal d = 8;
- QPolygonF p;
- p << QPointF(0, h - d) << QPointF(d, h) << QPointF(0, h);
- painter->setPen(Qt::blue);
- painter->setBrush(Qt::red);
- painter->drawPolygon(p);
- }
-}
-
-/**
- * Template Method, override this to set the default font metric.
- */
-void UMLWidget::setDefaultFontMetrics(QFont &font, UMLWidget::FontType fontType, QPainter &painter)
-{
- setupFontType(font, fontType);
- painter.setFont(font);
- setFontMetrics(fontType, painter.fontMetrics());
-}
-
-/**
- * Returns the font metric used by this object for Text
- * which uses bold/italic fonts.
- */
-QFontMetrics &UMLWidget::getFontMetrics(UMLWidget::FontType fontType) const
-{
- return *m_pFontMetrics[fontType];
-}
-
-/**
- * Set the font metric to use.
- */
-void UMLWidget::setFontMetrics(UMLWidget::FontType fontType, QFontMetrics fm)
-{
- delete m_pFontMetrics[fontType];
- m_pFontMetrics[fontType] = new QFontMetrics(fm);
-}
-
-/**
- * Sets the font the widget is to use.
- *
- * @param font Font to be set.
- */
-void UMLWidget::setFont(const QFont &font)
-{
- QFont newFont = font;
- forceUpdateFontMetrics(newFont, 0);
-
- if (m_font != newFont) {
- UMLApp::app()->executeCommand(new CmdChangeFont(this, font));
- }
-}
-
-/**
- * Sets the font the widget is to use.
- *
- * @param font Font to be set.
- */
-void UMLWidget::setFontCmd(const QFont &font)
-{
- WidgetBase::setFont(font);
- forceUpdateFontMetrics(0);
- if (m_doc->loading())
- return;
- update();
-}
-
-/**
- * Updates font metrics for widgets current m_font
- */
-void UMLWidget::forceUpdateFontMetrics(QPainter *painter)
-{
- forceUpdateFontMetrics(m_font, painter);
-}
-
-/**
- * @note For performance Reasons, only FontMetrics for already used
- * font types are updated. Not yet used font types will not get a font metric
- * and will get the same font metric as if painter was zero.
- * This behaviour is acceptable, because diagrams will always be shown on Display
- * first before a special painter like a printer device is used.
- */
-void UMLWidget::forceUpdateFontMetrics(QFont& font, QPainter *painter)
-{
- if (painter == 0) {
- for (int i = (int)FT_INVALID - 1; i >= 0; --i) {
- if (m_pFontMetrics[(UMLWidget::FontType)i] != 0)
- setDefaultFontMetrics(font, (UMLWidget::FontType)i);
- }
- } else {
- for (int i2 = (int)FT_INVALID - 1; i2 >= 0; --i2) {
- if (m_pFontMetrics[(UMLWidget::FontType)i2] != 0)
- setDefaultFontMetrics(font, (UMLWidget::FontType)i2, *painter);
- }
- }
- if (m_doc->loading())
- return;
- // calculate the size, based on the new font metric
- updateGeometry();
-}
-
-/**
- * Set the status of whether to show Stereotype.
- *
- * @param flag True if stereotype shall be shown.
- */
-void UMLWidget::setShowStereotype(bool flag)
-{
- m_showStereotype = flag;
- updateGeometry();
- update();
-}
-
-/**
- * Returns the status of whether to show Stereotype.
- *
- * @return True if stereotype is shown.
- */
-bool UMLWidget::showStereotype() const
-{
- return m_showStereotype;
-}
-
-/**
- * Overrides the standard operation.
- *
- * @param me The move event.
- */
-void UMLWidget::moveEvent(QGraphicsSceneMouseEvent* me)
-{
- Q_UNUSED(me)
-}
-
-void UMLWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- /*
- Call after required actions in child class.
- Type must be set in the child class.
- */
- WidgetBase::saveToXMI(qDoc, qElement);
- qElement.setAttribute(QLatin1String("xmi.id"), Uml::ID::toString(id()));
- qElement.setAttribute(QLatin1String("x"), x());
- qElement.setAttribute(QLatin1String("y"), y());
- qElement.setAttribute(QLatin1String("width"), width());
- qElement.setAttribute(QLatin1String("height"), height());
- qElement.setAttribute(QLatin1String("isinstance"), m_isInstance);
- if (!m_instanceName.isEmpty())
- qElement.setAttribute(QLatin1String("instancename"), m_instanceName);
- if (m_showStereotype)
- qElement.setAttribute(QLatin1String("showstereotype"), m_showStereotype);
-
- // Unique identifier for widget (todo: id() should be unique, new attribute
- // should indicate the UMLObject's ID it belongs to)
- qElement.setAttribute(QLatin1String("localid"), Uml::ID::toString(m_nLocalID));
-}
-
-bool UMLWidget::loadFromXMI(QDomElement & qElement)
-{
- QString id = qElement.attribute(QLatin1String("xmi.id"), QLatin1String("-1"));
- m_nId = Uml::ID::fromString(id);
-
- WidgetBase::loadFromXMI(qElement);
- QString x = qElement.attribute(QLatin1String("x"), QLatin1String("0"));
- QString y = qElement.attribute(QLatin1String("y"), QLatin1String("0"));
- QString h = qElement.attribute(QLatin1String("height"), QLatin1String("0"));
- QString w = qElement.attribute(QLatin1String("width"), QLatin1String("0"));
-
- setSize(w.toFloat(), h.toFloat());
- setX(x.toFloat());
- setY(y.toFloat());
- QString isinstance = qElement.attribute(QLatin1String("isinstance"), QLatin1String("0"));
- m_isInstance = (bool)isinstance.toInt();
- m_instanceName = qElement.attribute(QLatin1String("instancename"));
- QString showstereo = qElement.attribute(QLatin1String("showstereotype"), QLatin1String("0"));
- m_showStereotype = (bool)showstereo.toInt();
-
- QString localid = qElement.attribute(QLatin1String("localid"), QLatin1String("0"));
- if (localid != QLatin1String("0")) {
- m_nLocalID = Uml::ID::fromString(localid);
- }
-
- return true;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/umlwidget.h umbrello-kf6-15.08.1/umbrello/widgets/umlwidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/umlwidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/umlwidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,347 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef UMLWIDGET_H
-#define UMLWIDGET_H
-
-#include "associationwidgetlist.h"
-#include "basictypes.h"
-#include "optionstate.h"
-#include "umlwidgetlist.h"
-#include "widgetbase.h"
-
-#include <QCursor>
-#include <QFont>
-
-class IDChangeLog;
-class UMLDoc;
-class UMLObject;
-class UMLScene;
-
-class QPainter;
-class QFontMetrics;
-
-/**
- * This is the base class for nearly all graphical widgets.
- *
- * @short The base class for graphical UML objects.
- * @author Paul Hensgen <phensgen@techie.com>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UMLWidget : public WidgetBase
-{
- Q_OBJECT
-public:
-
- friend class ToolBarStateArrow; // for calling the mouse*Event handlers
-
- static const QSizeF DefaultMinimumSize;
- static const QSizeF DefaultMaximumSize;
- static const qreal defaultMargin;
-
- explicit UMLWidget(UMLScene *scene, WidgetType type = wt_UMLWidget, UMLObject *o = 0);
- explicit UMLWidget(UMLScene *scene, WidgetType type = wt_UMLWidget, Uml::ID::Type id = Uml::ID::None);
- virtual ~UMLWidget();
-
- // Copy constructor - not implemented.
- // UMLWidget(const UMLWidget& other);
-
- UMLWidget& operator=(const UMLWidget& other);
-
- bool operator==(const UMLWidget& other) const;
-
- void setLocalID(Uml::ID::Type id);
- Uml::ID::Type localID() const;
-
- virtual UMLWidget* widgetWithID(Uml::ID::Type id);
-
- virtual QSizeF minimumSize() const;
- void setMinimumSize(const QSizeF &size);
-
- virtual QSizeF maximumSize();
- void setMaximumSize(const QSizeF &size);
-
- virtual void setUseFillColor(bool fc);
- void setUseFillColorCmd(bool fc);
-
- virtual void setTextColor(const QColor &color);
- void setTextColorCmd(const QColor &color);
-
- virtual void setLineColor(const QColor &color);
- void setLineColorCmd(const QColor &color);
-
- virtual void setLineWidth(uint width);
- void setLineWidthCmd(uint width);
-
- virtual void setFillColor(const QColor &color);
- void setFillColorCmd(const QColor &color);
-
- void setSelectedFlag(bool _select);
- virtual void setSelected(bool _select);
-
- void setScene(UMLScene *scene);
-
- virtual bool activate(IDChangeLog* ChangeLog = 0);
-
- void setPenFromSettings(QPainter &p);
- void setPenFromSettings(QPainter *p);
-
- virtual void setFont(const QFont &font);
- void setFontCmd(const QFont &font);
-
- /**
- * Returns whether we triggered the update of position movement.
- * If so, you probably don't want to move it.
- *
- * @return The moving state.
- */
- bool getStartMove() const {
- return m_startMove;
- }
-
- virtual void setX(qreal x);
- virtual void setY(qreal y);
-
- /**
- * Returns the height of widget.
- */
- qreal height() const {
- return rect().height();
- }
-
- /**
- * Returns the width of the widget.
- */
- qreal width() const {
- return rect().width();
- }
-
- void setSize(qreal width, qreal height);
- void setSize(const QSizeF& size);
-
- virtual void resizeWidget(qreal newW, qreal newH);
-
- bool getIgnoreSnapToGrid() const;
- void setIgnoreSnapToGrid(bool to);
-
- void moveByLocal(qreal dx, qreal dy);
-
- void removeAssoc(AssociationWidget* pAssoc);
- void addAssoc(AssociationWidget* pAssoc);
-
- /**
- * Returns the list of associations connected to this widget.
- */
- AssociationWidgetList & associationWidgetList() {
- return m_Assocs;
- }
-
- /**
- * Read property of bool m_isInstance
- */
- bool isInstance() const {
- return m_isInstance;
- }
-
- /**
- * Write property of bool m_isInstance
- */
- void setIsInstance(bool isInstance) {
- m_isInstance = isInstance;
- }
-
- /**
- * Write property of m_instanceName
- */
- void setInstanceName(const QString &instanceName) {
- m_instanceName = instanceName;
- }
-
- /**
- * Read property of m_instanceName
- */
- QString instanceName() const {
- return m_instanceName;
- }
-
- bool showStereotype() const;
- virtual void setShowStereotype(bool flag);
-
- virtual void showPropertiesDialog();
-
- virtual void adjustAssocs(qreal dx, qreal dy);
- void adjustUnselectedAssocs(qreal dx, qreal dy);
-
- bool isActivated() const;
- void setActivated(bool active = true);
-
- virtual void cleanup();
-
- static bool widgetHasUMLObject(WidgetBase::WidgetType type);
-
- void updateGeometry();
-
- void clipSize();
-
- void forceUpdateFontMetrics(QPainter *painter);
- void forceUpdateFontMetrics(QFont &font, QPainter *painter);
-
- virtual bool loadFromXMI(QDomElement &qElement);
- virtual void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
-
- QPointF startMovePosition() const;
- void setStartMovePosition(const QPointF &position);
-
- QSizeF startResizeSize() const;
-
- virtual QSizeF calculateSize(bool withExtensions = true) const;
- void resize();
-
- bool fixedAspectRatio() const {
- return m_fixedAspectRatio;
- }
-
- void setFixedAspectRatio(bool state) {
- m_fixedAspectRatio = state;
- }
-
- typedef enum {
- FT_NORMAL = 0,
- FT_BOLD = 1,
- FT_ITALIC = 2,
- FT_UNDERLINE = 3,
- FT_BOLD_ITALIC = 4,
- FT_BOLD_UNDERLINE = 5,
- FT_ITALIC_UNDERLINE = 6,
- FT_BOLD_ITALIC_UNDERLINE = 7,
- FT_INVALID = 8
- } FontType;
-
- virtual void setDefaultFontMetrics(QFont &font, UMLWidget::FontType fontType);
- virtual void setDefaultFontMetrics(QFont &font, UMLWidget::FontType fontType, QPainter &painter);
-
- QFontMetrics &getFontMetrics(UMLWidget::FontType fontType) const;
- void setFontMetrics(UMLWidget::FontType fontType, QFontMetrics fm);
- void setupFontType(QFont &font, UMLWidget::FontType fontType);
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
-public Q_SLOTS:
- virtual void updateWidget();
- virtual void slotMenuSelection(QAction* action);
- virtual void slotWidgetMoved(Uml::ID::Type id);
- virtual void slotFillColorChanged(Uml::ID::Type viewID);
- virtual void slotLineColorChanged(Uml::ID::Type viewID);
- virtual void slotTextColorChanged(Uml::ID::Type viewID);
- virtual void slotLineWidthChanged(Uml::ID::Type viewID);
-
- void slotSnapToGrid();
-
-signals:
- /**
- * Emit when the widget moves its' position.
- * @param id The id of the object behind the widget.
- */
- void sigWidgetMoved(Uml::ID::Type id);
-
-protected:
- virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent* event);
- virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
- virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
- virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
- virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
-
- virtual void moveEvent(QGraphicsSceneMouseEvent *event);
- virtual void moveWidgetBy(qreal diffX, qreal diffY);
- virtual void constrainMovementForAllWidgets(qreal &diffX, qreal &diffY);
- virtual void constrain(qreal& width, qreal& height);
-
- virtual bool isInResizeArea(QGraphicsSceneMouseEvent *me);
- virtual QCursor resizeCursor() const;
-
- void selectSingle(QGraphicsSceneMouseEvent *me);
- void selectMultiple(QGraphicsSceneMouseEvent *me);
- void deselect(QGraphicsSceneMouseEvent *me);
- // void resetSelection();
-
- void setSelectionBounds();
-
- void resize(QGraphicsSceneMouseEvent *me);
-
- bool wasSizeChanged();
- bool wasPositionChanged();
-
- ///////////////// Data Loaded/Saved /////////////////////////////////
-
- /// A list of AssociationWidgets between the UMLWidget and other UMLWidgets in the diagram
- AssociationWidgetList m_Assocs;
-
- QString m_instanceName; ///< instance name (used if on a deployment diagram)
- bool m_isInstance; ///< holds whether this widget is a component instance (i.e. on a deployment diagram)
- bool m_showStereotype; ///< should the stereotype be displayed
-
- ///////////////// End of Data Loaded/Saved //////////////////////////
-
- Uml::ID::Type m_nLocalID;
- bool m_startMove;
- QPointF m_startMovePostion;
- QSizeF m_startResizeSize;
- int m_nPosX;
- UMLDoc *m_doc; ///< shortcut for UMLApp::app()->getDocument()
- bool m_resizable;
- QFontMetrics *m_pFontMetrics[FT_INVALID];
- QSizeF m_minimumSize;
- QSizeF m_maximumSize;
-
- /// true if the activate function has been called for this class instance
- bool m_activated;
-
- /**
- * Change Widget Behaviour
- */
- bool m_ignoreSnapToGrid;
- bool m_ignoreSnapComponentSizeToGrid;
- bool m_fixedAspectRatio;
-
- /// The text in the status bar when the cursor was pressed.
- QString m_oldStatusBarMsg;
-
- /// The X/Y offset from the position of the cursor when it was pressed to the
- /// upper left corner of the widget.
- QPointF m_pressOffset;
-
- /// The X/Y position the widget had when the movement started.
- QPointF m_oldPos;
-
- /// The width/height the widget had when the resize started.
- qreal m_oldW, m_oldH;
-
- /// If shift or control button were pressed in mouse press event.
- bool m_shiftPressed;
-
- /**
- * If cursor was in move/resize area when left button was pressed (and no
- * other widgets were selected).
- */
- bool m_inMoveArea, m_inResizeArea;
-
- /**
- * If the widget was selected/moved/resized in the press and release cycle.
- * Moved/resized is true if the widget was moved/resized even if the final
- * position/size is the same as the starting one.
- */
- bool m_moved, m_resized;
-
-private:
- void init();
- void toForeground();
-
-};
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/usecasewidget.cpp umbrello-kf6-15.08.1/umbrello/widgets/usecasewidget.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/usecasewidget.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/usecasewidget.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,96 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header file
-#include "usecasewidget.h"
-
-// app includes
-#include "usecase.h"
-#include "umlview.h"
-
-/**
- * Creates a UseCase widget.
- * @param scene The parent of the widget.
- * @param o The UMLUseCase to represent.
- */
-UseCaseWidget::UseCaseWidget(UMLScene * scene, UMLUseCase *o)
- : UMLWidget(scene, WidgetBase::wt_UseCase, o)
-{
-}
-
-/**
- * Destructor.
- */
-UseCaseWidget::~UseCaseWidget()
-{
-}
-
-/**
- * Overrides the standard paint event.
- */
-void UseCaseWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- setPenFromSettings(painter);
- if (UMLWidget::useFillColor())
- painter->setBrush(UMLWidget::fillColor());
- QFont font = UMLWidget::font();
- font.setUnderline(false);
- font.setBold(false);
- font.setItalic(m_umlObject->isAbstract());
- painter->setFont(font);
- const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
- const int fontHeight = fm.lineSpacing();
- const int w = width();
- const int h = height();
- //int middleX = w / 2;
- bool drawStereotype = umlObject() && !umlObject()->stereotype().isEmpty();
- const int textStartY = (h / 2) - (drawStereotype ? fontHeight / 4 : fontHeight / 2);
-
- painter->drawEllipse(0, 0, w, h);
- painter->setPen(textColor());
- if (drawStereotype)
- painter->drawText(UC_MARGIN, textStartY-fontHeight, w - UC_MARGIN * 2, fontHeight, Qt::AlignCenter, umlObject()->stereotype(true));
-
- painter->drawText(UC_MARGIN, textStartY, w - UC_MARGIN * 2, fontHeight, Qt::AlignCenter, name());
- setPenFromSettings(painter);
-
- UMLWidget::paint(painter, option, widget);
-}
-
-/**
- * Saves this UseCase to file.
- */
-void UseCaseWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
-{
- QDomElement usecaseElement = qDoc.createElement(QLatin1String("usecasewidget"));
- UMLWidget::saveToXMI(qDoc, usecaseElement);
- qElement.appendChild(usecaseElement);
-}
-
-/**
- * Overrides method from UMLWidget
- */
-QSizeF UseCaseWidget::minimumSize() const
-{
- const UMLWidget::FontType ft = (m_umlObject->isAbstract() ? FT_BOLD_ITALIC : FT_BOLD);
- const QFontMetrics &fm = UMLWidget::getFontMetrics(ft);
- const int fontHeight = fm.lineSpacing();
- const int textWidth = fm.width(name());
- bool drawStereotype = umlObject() && !umlObject()->stereotype().isEmpty();
- int width = textWidth > UC_WIDTH?textWidth:UC_WIDTH;
- int height = UC_HEIGHT + (drawStereotype ? 2 * fontHeight : fontHeight) + UC_MARGIN;
-
- width += UC_MARGIN * 2;
-
- return QSizeF(width, height);
-}
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/usecasewidget.h umbrello-kf6-15.08.1/umbrello/widgets/usecasewidget.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/usecasewidget.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/usecasewidget.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,58 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef USECASEWIDGET_H
-#define USECASEWIDGET_H
-
-#include "umlwidget.h"
-
-class UMLUseCase;
-
-#define UC_MARGIN 5
-#define UC_WIDTH 60
-#define UC_HEIGHT 30
-
-
-/**
- * This class is the graphical version of a UMLUseCase. The
- * UseCaseWidget class inherits from the @ref UMLWidget class
- * which adds most of the functionality to this class.
-
- * A UseCaseWidget is created by a @ref UMLView. An UseCaseWidget belongs to only one
- * @ref UMLView instance. When the @ref UMLView instance that this class belongs to,
- * it will be automatically deleted.
- *
- * If the @ref UMLUseCase class that this UseCaseWidget is displaying is deleted, the @ref UMLView will
- * make sure that this instance is also deleted.
- *
- * The UseCaseWidget class inherits from the @ref UMLWidget class which adds most of the functionality
- * to this class.
- *
- * @short A graphical version of a UMLUseCase.
- * @author Paul Hensgen <phensgen@techie.com>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class UseCaseWidget : public UMLWidget
-{
-public:
- UseCaseWidget(UMLScene * scene, UMLUseCase *o);
- virtual ~UseCaseWidget();
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
- // For loading we can use the loadFromXMI() inherited from
- // UMLWidget.
- virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
-
-protected:
- QSizeF minimumSize() const;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/widgetbase.cpp umbrello-kf6-15.08.1/umbrello/widgets/widgetbase.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/widgetbase.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/widgetbase.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,1119 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#include "widgetbase.h"
-
-#include "classifier.h"
-#include "debug_utils.h"
-#include "floatingtextwidget.h"
-#include "optionstate.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlobject.h"
-#include "umlscene.h"
-
-#if QT_VERSION < 0x050000
-#include <kcolordialog.h>
-#include <kfontdialog.h>
-#endif
-#include <KLocalizedString>
-
-#include <QAction>
-#if QT_VERSION >= 0x050000
-#include <QColorDialog>
-#include <QFontDialog>
-#endif
-#include <QPointer>
-
-/**
- * Creates a WidgetBase object.
- *
- * @param scene The view to be displayed on.
- * @param type The WidgetType to construct. This must be set to the appropriate
- * value by the constructors of inheriting classes.
- */
-WidgetBase::WidgetBase(UMLScene *scene, WidgetType type)
- : QGraphicsObject(),
- m_baseType(type),
- m_scene(scene),
- m_umlObject(0),
- m_textColor(QColor("black")),
- m_lineColor(QColor("black")),
- m_fillColor(QColor("yellow")),
- m_brush(m_fillColor),
- m_lineWidth(0), // initialize with 0 to have valid start condition
- m_useFillColor(true),
- m_usesDiagramTextColor(true),
- m_usesDiagramLineColor(true),
- m_usesDiagramLineWidth(true)
-{
- setSelected(false);
- scene->addItem(this);
-
- // TODO 310283
- setFlags(ItemIsSelectable);
- //setFlags(ItemIsSelectable | ItemIsMovable |ItemSendsGeometryChanges);
- if (m_scene) {
- m_usesDiagramLineColor = true;
- m_usesDiagramLineWidth = true;
- m_usesDiagramTextColor = true;
- const Settings::OptionState& optionState = m_scene->optionState();
- m_textColor = optionState.uiState.textColor;
- m_lineColor = optionState.uiState.lineColor;
- m_lineWidth = optionState.uiState.lineWidth;
- m_font = optionState.uiState.font;
- } else {
- uError() << "WidgetBase constructor: SERIOUS PROBLEM - m_scene is NULL";
- }
-}
-
-/**
- * Destructor.
- */
-WidgetBase::~WidgetBase()
-{
-}
-
-/**
- * Read property of m_baseType.
- */
-WidgetBase::WidgetType WidgetBase::baseType() const
-{
- return m_baseType;
-}
-
-/**
- * @return The type used for rtti as string.
- */
-QLatin1String WidgetBase::baseTypeStr() const
-{
- return QLatin1String(ENUM_NAME(WidgetBase, WidgetType, m_baseType));
-}
-
-/*
- * Sets the state of whether the widget is selected.
- *
- * @param select The state of whether the widget is selected.
- */
-void WidgetBase::setSelected(bool select)
-{
- QGraphicsObject::setSelected(select);
-}
-
-/**
- * Deliver a pointer to the connected UMLView
- * (needed esp. by event handling of AssociationLine).
- */
-UMLScene* WidgetBase::umlScene() const
-{
- return m_scene;
-}
-
-/**
- * This is shortcut method for UMLApp::app()->document().
- *
- * @return Pointer to the UMLDoc object.
- */
-UMLDoc* WidgetBase::umlDoc() const
-{
- return UMLApp::app()->document();
-}
-
-/**
- * Returns the @ref UMLObject set to represent.
- *
- * @return the UMLObject to represent.
- */
-UMLObject* WidgetBase::umlObject() const
-{
- return m_umlObject;
-}
-
-/**
- * Sets the @ref UMLObject to represent.
- *
- * @param obj The object to represent.
- */
-void WidgetBase::setUMLObject(UMLObject *obj)
-{
- m_umlObject = obj;
-}
-
-/**
- * Write property of m_nId.
- */
-void WidgetBase::setID(Uml::ID::Type id)
-{
- if (m_umlObject) {
- if (m_umlObject->id() != Uml::ID::None)
- uWarning() << "changing old UMLObject " << Uml::ID::toString(m_umlObject->id())
- << " to " << Uml::ID::toString(id);
- m_umlObject->setID(id);
- }
- m_nId = id;
-}
-
-/**
- * Read property of m_nId.
- */
-Uml::ID::Type WidgetBase::id() const
-{
- if (m_umlObject)
- return m_umlObject->id();
- return m_nId;
-}
-
-/**
- * Used by some child classes to get documentation.
- *
- * @return The documentation from the UMLObject (if m_umlObject is set.)
- */
-QString WidgetBase::documentation() const
-{
- if (m_umlObject)
- return m_umlObject->doc();
- return m_Doc;
-}
-
-/**
- * Returns state of documentation for the widget.
- *
- * @return false if documentation is empty
- */
-bool WidgetBase::hasDocumentation()
-{
- if (m_umlObject)
- return m_umlObject->hasDoc();
- return !m_Doc.isEmpty();
-}
-
-/**
- * Used by some child classes to set documentation.
- *
- * @param doc The documentation to be set in the UMLObject
- * (if m_umlObject is set.)
- */
-void WidgetBase::setDocumentation(const QString& doc)
-{
- if (m_umlObject)
- m_umlObject->setDoc(doc);
- else
- m_Doc = doc;
-}
-
-/**
- * Gets the name from the corresponding UMLObject if this widget has an
- * underlying UMLObject; if it does not, then it returns the local
- * m_Text (notably the case for FloatingTextWidget.)
- *
- * @return the currently set name
- */
-QString WidgetBase::name() const
-{
- if (m_umlObject)
- return m_umlObject->name();
- return m_Text;
-}
-
-/**
- * Sets the name in the corresponding UMLObject.
- * Sets the local m_Text if m_umlObject is NULL.
- *
- * @param strName The name to be set.
- */
-void WidgetBase::setName(const QString &strName)
-{
- if (m_umlObject)
- m_umlObject->setName(strName);
- else
- m_Text = strName;
-}
-
-/**
- * Returns text color
- *
- * @return currently used text color
- */
-QColor WidgetBase::textColor() const
-{
- return m_textColor;
-}
-
-/**
- * Sets the text color
- *
- * @param color the new text color
- */
-void WidgetBase::setTextColor(const QColor &color)
-{
- m_textColor = color;
- m_usesDiagramTextColor = false;
-}
-
-/**
- * Returns line color
- *
- * @return currently used line color
- */
-QColor WidgetBase::lineColor() const
-{
- return m_lineColor;
-}
-
-/**
- * Sets the line color
- *
- * @param color The new line color
- */
-void WidgetBase::setLineColor(const QColor &color)
-{
- m_lineColor = color;
- m_usesDiagramLineColor = false;
-}
-
-/**
- * Returns fill color
- *
- * @return currently used fill color
- */
-QColor WidgetBase::fillColor() const
-{
- return m_fillColor;
-}
-
-/**
- * Sets the fill color
- *
- * @param color The new fill color
- */
-void WidgetBase::setFillColor(const QColor &color)
-{
- m_fillColor = color;
- m_usesDiagramFillColor = false;
-}
-
-/**
- * Returns line width
- *
- * @return currently used line with
- */
-uint WidgetBase::lineWidth() const
-{
- return m_lineWidth;
-}
-
-/**
- * Sets the line width
- *
- * @param width The new line width
- */
-void WidgetBase::setLineWidth(uint width)
-{
- m_lineWidth = width;
- m_usesDiagramLineWidth = false;
-}
-
-/**
- * Return state of fill color usage
- *
- * @return True if fill color is used
- */
-bool WidgetBase::useFillColor()
-{
- return m_useFillColor;
-}
-
-/**
- * Set state if fill color is used
- *
- * @param state The state to set
- */
-void WidgetBase::setUseFillColor(bool state)
-{
- m_useFillColor = state;
- m_usesDiagramUseFillColor = false;
-}
-
-/**
- * Returns state if diagram text color is used
- *
- * @return True means diagram text color is used
- */
-bool WidgetBase::usesDiagramTextColor() const
-{
- return m_usesDiagramTextColor;
-}
-
-/**
- * Set state if diagram text color is used
- *
- * @param state The state to set
- */
-void WidgetBase::setUsesDiagramTextColor(bool state)
-{
- if (m_usesDiagramTextColor == state) {
- return;
- }
- m_usesDiagramTextColor = state;
- setTextColor(m_textColor);
-}
-
-/**
- * Returns state of diagram line color is used
- *
- * @return True means diagrams line color is used
-*/
-bool WidgetBase::usesDiagramLineColor() const
-{
- return m_usesDiagramLineColor;
-}
-
-/**
- * Set state of diagram line color is used
- *
- * @param state The state to set
- */
-void WidgetBase::setUsesDiagramLineColor(bool state)
-{
- m_usesDiagramLineColor = state;
-}
-
-/**
- * Returns state of diagram fill color is used
- *
- * @return True means diagrams fill color is used
-*/
-bool WidgetBase::usesDiagramFillColor() const
-{
- return m_usesDiagramFillColor;
-}
-
-/**
- * Set state if diagram fill color is used
- *
- * @param state The state to set
- */
-void WidgetBase::setUsesDiagramFillColor(bool state)
-{
- m_usesDiagramFillColor = state;
-}
-
-/**
- * Returns state of diagram use fill color is used
- *
- * @return True means diagrams fill color is used
-*/
-bool WidgetBase::usesDiagramUseFillColor() const
-{
- return m_usesDiagramUseFillColor;
-}
-
-/**
- * Set state of diagram use fill color is used
- *
- * @param state The state to set
- */
-void WidgetBase::setUsesDiagramUseFillColor(bool state)
-{
- m_usesDiagramUseFillColor = state;
-}
-
-/**
- * Returns state of diagram line width is used
- *
- * @return True means diagrams line width is used
- */
-bool WidgetBase::usesDiagramLineWidth() const
-{
- return m_usesDiagramLineWidth;
-}
-
-/**
- * Set state of diagram line width is used
- *
- * @param state The state to set
- */
-void WidgetBase::setUsesDiagramLineWidth(bool state)
-{
- m_usesDiagramLineWidth = state;
-}
-
-/**
- * Returns the font used for diaplaying any text.
- * @return the font
- */
-QFont WidgetBase::font() const
-{
- return m_font;
-}
-
-/**
- * Set the font used to display text inside this widget.
- */
-void WidgetBase::setFont(const QFont& font)
-{
- m_font = font;
-}
-
-/**
- * A virtual method for the widget to display a property dialog box.
- * Subclasses should reimplment this appropriately.
- */
-void WidgetBase::showPropertiesDialog()
-{
-}
-
-/**
- * A virtual method to save the properties of this widget into a
- * QDomElement i.e xml.
- *
- * Subclasses should first create a new dedicated element as the child
- * of \a qElement parameter passed. Then this base method should be
- * called to save basic widget properties.
- *
- * @param qDoc A QDomDocument object representing the xml document.
- * @param qElement A QDomElement representing xml element data.
- */
-void WidgetBase::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
- {
- Q_UNUSED(qDoc)
-
- qElement.setAttribute(QLatin1String("textcolor"), m_usesDiagramTextColor ? QLatin1String("none")
- : m_textColor.name());
- if (m_usesDiagramLineColor) {
- qElement.setAttribute(QLatin1String("linecolor"), QLatin1String("none"));
- } else {
- qElement.setAttribute(QLatin1String("linecolor"), m_lineColor.name());
- }
- if (m_usesDiagramLineWidth) {
- qElement.setAttribute(QLatin1String("linewidth"), QLatin1String("none"));
- } else {
- qElement.setAttribute(QLatin1String("linewidth"), m_lineWidth);
- }
- qElement.setAttribute(QLatin1String("usefillcolor"), m_useFillColor);
- // for consistency the following attributes now use american spelling for "color"
- qElement.setAttribute(QLatin1String("usesdiagramfillcolor"), m_usesDiagramFillColor);
- qElement.setAttribute(QLatin1String("usesdiagramusefillcolor"), m_usesDiagramUseFillColor);
- if (m_usesDiagramFillColor) {
- qElement.setAttribute(QLatin1String("fillcolor"), QLatin1String("none"));
- } else {
- qElement.setAttribute(QLatin1String("fillcolor"), m_fillColor.name());
- }
- qElement.setAttribute(QLatin1String("font"), m_font.toString());
-}
-
-/**
- * A virtual method to load the properties of this widget from a
- * QDomElement into this widget.
- *
- * Subclasses should reimplement this to load addtional properties
- * required, calling this base method to load the basic properties of
- * the widget.
- *
- * @param qElement A QDomElement which contains xml info for this widget.
- *
- * @todo Add support to load older version.
- */
-bool WidgetBase::loadFromXMI(QDomElement& qElement)
-{
- // first load from "linecolour" and then overwrite with the "linecolor"
- // attribute if that one is present. The "linecolour" name was a "typo" in
- // earlier versions of umbrello-kf6
- QString lineColor = qElement.attribute(QLatin1String("linecolour"), QLatin1String("none"));
- lineColor = qElement.attribute(QLatin1String("linecolor"), lineColor);
- if (lineColor != QLatin1String("none")) {
- m_lineColor = QColor(lineColor);
- m_usesDiagramLineColor = false;
- } else if (m_baseType != WidgetBase::wt_Box && m_scene != NULL) {
- m_lineColor = m_scene->lineColor();
- m_usesDiagramLineColor = true;
- }
- QString lineWidth = qElement.attribute(QLatin1String("linewidth"), QLatin1String("none"));
- if (lineWidth != QLatin1String("none")) {
- m_lineWidth = lineWidth.toInt();
- m_usesDiagramLineWidth = false;
- } else if (m_scene) {
- m_lineWidth = m_scene->lineWidth();
- m_usesDiagramLineWidth = true;
- }
- QString textColor = qElement.attribute(QLatin1String("textcolor"), QLatin1String("none"));
- if (textColor != QLatin1String("none")) {
- m_textColor = QColor(textColor);
- m_usesDiagramTextColor = false;
- } else if (m_scene) {
- m_textColor = m_scene->textColor();
- m_usesDiagramTextColor = true;
- }
- QString usefillcolor = qElement.attribute(QLatin1String("usefillcolor"), QLatin1String("1"));
- m_useFillColor = (bool)usefillcolor.toInt();
- /*
- For the next three *color attributes, there was a mixup of american and english spelling for "color".
- So first we need to keep backward compatibility and try to retrieve the *colour attribute.
- Next we overwrite this value if we find a *color, otherwise the former *colour is kept.
- */
- QString fillColor = qElement.attribute(QLatin1String("fillcolour"), QLatin1String("none"));
- fillColor = qElement.attribute(QLatin1String("fillcolor"), fillColor);
- if (fillColor != QLatin1String("none")) {
- m_fillColor = QColor(fillColor);
- }
-
- QString usesDiagramFillColor = qElement.attribute(QLatin1String("usesdiagramfillcolour"), QLatin1String("1"));
- usesDiagramFillColor = qElement.attribute(QLatin1String("usesdiagramfillcolor"), usesDiagramFillColor);
- m_usesDiagramFillColor = (bool)usesDiagramFillColor.toInt();
-
- QString usesDiagramUseFillColor = qElement.attribute(QLatin1String("usesdiagramusefillcolour"), QLatin1String("1"));
- usesDiagramUseFillColor = qElement.attribute(QLatin1String("usesdiagramusefillcolor"), usesDiagramUseFillColor);
- m_usesDiagramUseFillColor = (bool)usesDiagramUseFillColor.toInt();
-
- QString font = qElement.attribute(QLatin1String("font"));
- if (!font.isEmpty()) {
- QFont newFont;
- newFont.fromString(font);
- m_font = newFont;
- } else {
- uWarning() << "Using default font " << m_font.toString()
- << " for widget with xmi.id " << Uml::ID::toString(m_nId);
- }
-
- return true;
-}
-
-/**
- * Assignment operator
- */
-WidgetBase& WidgetBase::operator=(const WidgetBase& other)
-{
- m_baseType = other.m_baseType;
- m_scene = other.m_scene;
- m_umlObject = other.m_umlObject;
- m_Doc = other.m_Doc;
- m_Text = other.m_Text;
- m_nId = other.m_nId;
- m_textColor = other.m_textColor;
- m_lineColor = other.m_lineColor;
- m_fillColor = other.m_fillColor;
- m_brush = other.m_brush;
- m_font = other.m_font;
- m_lineWidth = other.m_lineWidth;
- m_useFillColor = other.m_useFillColor;
- m_usesDiagramTextColor = other.m_usesDiagramTextColor;
- m_usesDiagramLineColor = other.m_usesDiagramLineColor;
- m_usesDiagramFillColor = other.m_usesDiagramFillColor;
- m_usesDiagramLineWidth = other.m_usesDiagramLineWidth;
- setSelected(other.isSelected());
-
- return *this;
-}
-
-/**
- * return drawing rectangle of widget in local coordinates
- */
-QRectF WidgetBase::rect() const
-{
- return m_rect;
-}
-
-/**
- * set widget rectangle in item coordinates
- */
-void WidgetBase::setRect(const QRectF& rect)
-{
- if (m_rect == rect)
- return;
- prepareGeometryChange();
- m_rect = rect;
- update();
-}
-
-/**
- * set widget rectangle in item coordinates
- */
-void WidgetBase::setRect(qreal x, qreal y, qreal width, qreal height)
-{
- setRect(QRectF(x, y, width, height));
-}
-
-/**
- * @return The bounding rectangle for this widget.
- * @see setRect
- */
-QRectF WidgetBase::boundingRect() const
-{
- int halfWidth = lineWidth()/2;
- return m_rect.adjusted(-halfWidth, -halfWidth, halfWidth, halfWidth);
-}
-
-/**
- * Test if point is inside the bounding rectangle of the widget.
- * Inheriting classes may reimplement this to test possible child widgets.
- *
- * @param p Point to be checked.
- *
- * @return 'this' if the given point is in the boundaries of the widget;
- * else NULL.
- */
-UMLWidget* WidgetBase::onWidget(const QPointF &p)
-{
- UMLWidget *uw = dynamic_cast<UMLWidget*>(this);
- if (uw == NULL)
- return NULL;
- const qreal w = m_rect.width();
- const qreal h = m_rect.height();
- const qreal left = x(); // don't use m_rect.x() for this, it is always 0
- const qreal right = left + w;
- const qreal top = y(); // don't use m_rect.y() for this, it is always 0
- const qreal bottom = top + h;
- // uDebug() << "p=(" << p.x() << "," << p.y()
- // << "), x=" << left << ", y=" << top << ", w=" << w << ", h=" << h
- // << "; right=" << right << ", bottom=" << bottom;
- if (p.x() < left || p.x() > right ||
- p.y() < top || p.y() > bottom) { // Qt coord.sys. origin in top left corner
- // uDebug() << "returning NULL";
- return NULL;
- }
- // uDebug() << "returning this";
- return uw;
-}
-
-/**
- * Draws the UMLWidget on the given paint device
- *
- * @param painter The painter for the drawing device
- * @param option Painting related options
- * @param widget Background widget on which to paint (optional)
- *
- */
-void WidgetBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(painter); Q_UNUSED(option); Q_UNUSED(widget);
-}
-
-/**
- * Reimplemented to show appropriate context menu.
- */
-void WidgetBase::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
-{
- event->accept();
- uDebug() << "widget = " << name() << " / type = " << baseTypeStr();
-
- UMLScene *scene = umlScene();
-
- // If right-click was done on a widget that was not selected, clear the
- // current selection and select the new widget. The context menu is shown
- // with actions for that single widget.
- // If a keyboard modifier was used, add the widget to the current selection
- // and show the menu with actions for the whole selection.
- if (!isSelected()) {
- Qt::KeyboardModifiers forSelection = (Qt::ControlModifier | Qt::ShiftModifier);
- if ((event->modifiers() & forSelection) == 0) {
- scene->clearSelected();
- }
-
- if (umlObject() != 0) {
- scene->selectWidget(dynamic_cast<UMLWidget*>(this));
- } else {
- setSelected(true);
- }
- }
-
- int count = scene->selectedCount(true);
-
- // Determine multi state
- bool multi = (isSelected() && count > 1);
-
- ListPopupMenu popup(0, this, multi, scene->getUniqueSelectionType());
-
- // Disable the "view code" menu for simple code generators
- if (UMLApp::app()->isSimpleCodeGeneratorActive()) {
- popup.setActionEnabled(ListPopupMenu::mt_ViewCode, false);
- }
-
- QAction *triggered = popup.exec(event->screenPos());
- ListPopupMenu *parentMenu = ListPopupMenu::menuFromAction(triggered);
-
- if (!parentMenu) {
- uDebug() << "Action's data field does not contain ListPopupMenu pointer";
- return;
- }
-
- WidgetBase *ownerWidget = parentMenu->ownerWidget();
- // assert because logic is based on only WidgetBase being the owner of
- // ListPopupMenu actions executed in this context menu.
- Q_ASSERT_X(ownerWidget != 0, "WidgetBase::contextMenuEvent",
- "ownerWidget is null which means action belonging to UMLView, UMLScene"
- " or UMLObject is the one triggered in ListPopupMenu");
-
- ownerWidget->slotMenuSelection(triggered);
-}
-
-/**
- * This is usually called synchronously after menu.exec() and \a
- * trigger's parent is always the ListPopupMenu which can be used to
- * get the type of action of \a trigger.
- *
- * @note Subclasses can reimplement to handle specific actions and
- * leave the rest to WidgetBase::slotMenuSelection.
- */
-void WidgetBase::slotMenuSelection(QAction *trigger)
-{
- if (!trigger) {
- return;
- }
- QColor newColor;
-
- const WidgetType wt = m_baseType; // short hand name
-
- ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(trigger);
- switch (sel) {
- case ListPopupMenu::mt_Rename:
- umlDoc()->renameUMLObject(umlObject());
- break;
-
- case ListPopupMenu::mt_Properties:
- if (wt == WidgetBase::wt_Actor || wt == WidgetBase::wt_UseCase ||
- wt == WidgetBase::wt_Package || wt == WidgetBase::wt_Interface ||
- wt == WidgetBase::wt_Datatype || wt == WidgetBase::wt_Node ||
- wt == WidgetBase::wt_Component || wt == WidgetBase::wt_Artifact ||
- wt == WidgetBase::wt_Enum || wt == WidgetBase::wt_Entity ||
- wt == WidgetBase::wt_Port ||
- (wt == WidgetBase::wt_Class && umlScene()->type() == Uml::DiagramType::Class)) {
-
- showPropertiesDialog();
-
- } else if (wt == WidgetBase::wt_Object) {
- m_umlObject->showPropertiesDialog();
- } else {
- uWarning() << "making properties dialog for unknown widget type";
- }
- break;
-
- case ListPopupMenu::mt_Line_Color:
- case ListPopupMenu::mt_Line_Color_Selection:
-#if QT_VERSION >= 0x050000
- newColor = QColorDialog::getColor(lineColor());
- if (newColor != lineColor()) {
-#else
- newColor = lineColor();
- if (KColorDialog::getColor(newColor)) {
-#endif
- if (sel == ListPopupMenu::mt_Line_Color_Selection) {
- umlScene()->selectionSetLineColor(newColor);
- } else {
- setLineColor(newColor);
- }
- setUsesDiagramLineColor(false);
- umlDoc()->setModified(true);
- }
- break;
-
- case ListPopupMenu::mt_Fill_Color:
- case ListPopupMenu::mt_Fill_Color_Selection:
-#if QT_VERSION >= 0x050000
- newColor = QColorDialog::getColor(fillColor());
- if (newColor != fillColor()) {
-#else
- newColor = fillColor();
- if (KColorDialog::getColor(newColor)) {
-#endif
- if (sel == ListPopupMenu::mt_Fill_Color_Selection) {
- umlScene()->selectionSetFillColor(newColor);
- } else {
- setFillColor(newColor);
- }
- umlDoc()->setModified(true);
- }
- break;
-
- case ListPopupMenu::mt_Use_Fill_Color:
- setUseFillColor(!m_useFillColor);
- break;
-
- case ListPopupMenu::mt_Set_Use_Fill_Color_Selection:
- umlScene()->selectionUseFillColor(true);
- break;
-
- case ListPopupMenu::mt_Unset_Use_Fill_Color_Selection:
- umlScene()->selectionUseFillColor(false);
- break;
-
- case ListPopupMenu::mt_Show_Attributes_Selection:
- case ListPopupMenu::mt_Hide_Attributes_Selection:
- umlScene()->selectionSetVisualProperty(
- ClassifierWidget::ShowAttributes, sel != ListPopupMenu::mt_Hide_Attributes_Selection
- );
- break;
-
- case ListPopupMenu::mt_Show_Operations_Selection:
- case ListPopupMenu::mt_Hide_Operations_Selection:
- umlScene()->selectionSetVisualProperty(
- ClassifierWidget::ShowOperations, sel != ListPopupMenu::mt_Hide_Operations_Selection
- );
- break;
-
- case ListPopupMenu::mt_Show_Visibility_Selection:
- case ListPopupMenu::mt_Hide_Visibility_Selection:
- umlScene()->selectionSetVisualProperty(
- ClassifierWidget::ShowVisibility, sel != ListPopupMenu::mt_Hide_Visibility_Selection
- );
- break;
-
- case ListPopupMenu::mt_Show_Operation_Signature_Selection:
- case ListPopupMenu::mt_Hide_Operation_Signature_Selection:
- umlScene()->selectionSetVisualProperty(
- ClassifierWidget::ShowOperationSignature, sel != ListPopupMenu::mt_Hide_Operation_Signature_Selection
- );
- break;
-
- case ListPopupMenu::mt_Show_Attribute_Signature_Selection:
- case ListPopupMenu::mt_Hide_Attribute_Signature_Selection:
- umlScene()->selectionSetVisualProperty(
- ClassifierWidget::ShowAttributeSignature, sel != ListPopupMenu::mt_Hide_Attribute_Signature_Selection
- );
- break;
-
- case ListPopupMenu::mt_Show_Packages_Selection:
- case ListPopupMenu::mt_Hide_Packages_Selection:
- umlScene()->selectionSetVisualProperty(
- ClassifierWidget::ShowPackage, sel != ListPopupMenu::mt_Hide_Packages_Selection
- );
- break;
-
- case ListPopupMenu::mt_Show_Stereotypes_Selection:
- case ListPopupMenu::mt_Hide_Stereotypes_Selection:
- umlScene()->selectionSetVisualProperty(
- ClassifierWidget::ShowStereotype, sel != ListPopupMenu::mt_Hide_Stereotypes_Selection
- );
- break;
-
- case ListPopupMenu::mt_Hide_NonPublic_Selection:
- case ListPopupMenu::mt_Show_NonPublic_Selection:
- umlScene()->selectionSetVisualProperty(
- ClassifierWidget::ShowPublicOnly, sel != ListPopupMenu::mt_Show_NonPublic_Selection
- );
- break;
-
-
- case ListPopupMenu::mt_ViewCode: {
- UMLClassifier *c = dynamic_cast<UMLClassifier*>(umlObject());
- if (c) {
- UMLApp::app()->viewCodeDocument(c);
- }
- break;
- }
-
- case ListPopupMenu::mt_Delete:
- umlScene()->deleteSelection();
- break;
-
- case ListPopupMenu::mt_Change_Font:
- case ListPopupMenu::mt_Change_Font_Selection: {
-#if QT_VERSION >= 0x050000
- bool ok = false;
- QFont newFont = QFontDialog::getFont(&ok, font());
- if (ok) {
-#else
- QFont newFont = font();
- if (KFontDialog::getFont(newFont, KFontChooser::NoDisplayFlags, 0) == KFontDialog::Accepted) {
-#endif
- if (sel == ListPopupMenu::mt_Change_Font_Selection) {
- m_scene->selectionSetFont(newFont);
- } else {
- setFont(newFont);
- }
- }
- }
- break;
-
- case ListPopupMenu::mt_Cut:
- umlScene()->setStartedCut();
- UMLApp::app()->slotEditCut();
- break;
-
- case ListPopupMenu::mt_Copy:
- UMLApp::app()->slotEditCopy();
- break;
-
- case ListPopupMenu::mt_Paste:
- UMLApp::app()->slotEditPaste();
- break;
-
- case ListPopupMenu::mt_Refactoring:
- //check if we are operating on a classifier, or some other kind of UMLObject
- if (dynamic_cast<UMLClassifier*>(umlObject())) {
- UMLApp::app()->refactor(static_cast<UMLClassifier*>(umlObject()));
- }
- break;
-
- case ListPopupMenu::mt_Clone:
- {
- foreach (UMLWidget* widget, umlScene()->selectedWidgets()) {
- if (Model_Utils::isCloneable(widget->baseType())) {
- UMLObject *clone = widget->umlObject()->clone();
- umlScene()->addObject(clone);
- }
- }
- }
- break;
-
- case ListPopupMenu::mt_Rename_MultiA:
- case ListPopupMenu::mt_Rename_MultiB:
- case ListPopupMenu::mt_Rename_Name:
- case ListPopupMenu::mt_Rename_RoleAName:
- case ListPopupMenu::mt_Rename_RoleBName: {
- FloatingTextWidget *ft = static_cast<FloatingTextWidget*>(this);
- ft->handleRename();
- break;
- }
- case ListPopupMenu::mt_Align_Right:
- umlScene()->alignRight();
- break;
- case ListPopupMenu::mt_Align_Left:
- umlScene()->alignLeft();
- break;
- case ListPopupMenu::mt_Align_Top:
- umlScene()->alignTop();
- break;
- case ListPopupMenu::mt_Align_Bottom:
- umlScene()->alignBottom();
- break;
- case ListPopupMenu::mt_Align_VerticalMiddle:
- umlScene()->alignVerticalMiddle();
- break;
- case ListPopupMenu::mt_Align_HorizontalMiddle:
- umlScene()->alignHorizontalMiddle();
- break;
- case ListPopupMenu::mt_Align_VerticalDistribute:
- umlScene()->alignVerticalDistribute();
- break;
- case ListPopupMenu::mt_Align_HorizontalDistribute:
- umlScene()->alignHorizontalDistribute();
- break;
- default:
- uDebug() << "MenuType " << ListPopupMenu::toString(sel) << " not implemented";
- break;
- }
-}
-
-/**
- * Helper function for debug output.
- * Returns the given enum value as string.
- * @param wt WidgetType of which a string representation is wanted
- * @return the WidgetType as string
- */
-QString WidgetBase::toString(WidgetType wt)
-{
- return QLatin1String(ENUM_NAME(WidgetBase, WidgetType, wt));
-}
-
-/**
- * Returns the given enum value as localized string.
- * @param wt WidgetType of which a string representation is wanted
- * @return the WidgetType as localized string
- */
-QString WidgetBase::toI18nString(WidgetType wt)
-{
- QString name;
-
- switch (wt) {
- case wt_Activity:
- name = i18n("Activity");
- break;
- case wt_Actor:
- name = i18n("Actor");
- break;
- case wt_Artifact:
- name = i18n("Artifact");
- break;
- case wt_Association:
- name = i18n("Association");
- break;
- case wt_Box:
- name = i18n("Box");
- break;
- case wt_Category:
- name = i18n("Category");
- break;
- case wt_CombinedFragment:
- name = i18n("CombinedFragment");
- break;
- case wt_Component:
- name = i18n("Component");
- break;
- case wt_Class:
- name = i18n("Class");
- break;
- case wt_Datatype:
- name = i18n("Datatype");
- break;
- case wt_Entity:
- name = i18n("Entity");
- break;
- case wt_Enum:
- name = i18n("Enum");
- break;
- case wt_FloatingDashLine:
- name = i18n("FloatingDashLine");
- break;
- case wt_ForkJoin:
- name = i18n("ForkJoin");
- break;
- case wt_Interface:
- name = i18n("Interface");
- break;
- case wt_Message:
- name = i18n("Message");
- break;
- case wt_Node:
- name = i18n("Node");
- break;
- case wt_Note:
- name = i18n("Note");
- break;
- case wt_Object:
- name = i18n("Object");
- break;
- case wt_ObjectNode:
- name = i18n("ObjectNode");
- break;
- case wt_Package:
- name = i18n("Package");
- break;
- case wt_Pin:
- name = i18n("Pin");
- break;
- case wt_Port:
- name = i18n("Port");
- break;
- case wt_Precondition:
- name = i18n("Precondition");
- break;
- case wt_Region:
- name = i18n("Region");
- break;
- case wt_Signal:
- name = i18n("Signal");
- break;
- case wt_State:
- name = i18n("State");
- break;
- case wt_Text:
- name = i18n("Text");
- break;
- case wt_UseCase:
- name = i18n("UseCase");
- break;
- default:
- name = QLatin1String("<unknown> &name:");
- uWarning() << "unknown widget type";
- break;
- }
- return name;
-}
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/widgetbase.h umbrello-kf6-15.08.1/umbrello/widgets/widgetbase.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/widgetbase.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/widgetbase.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,192 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef WIDGETBASE_H
-#define WIDGETBASE_H
-
-#include "basictypes.h"
-
-#include <QColor>
-#include <QDomDocument>
-#include <QFont>
-#include <QGraphicsObject>
-#include <QObject>
-#include <QPainter>
-
-// forward declarations
-class QAction;
-class UMLDoc;
-class UMLObject;
-class UMLScene;
-class UMLWidget; // required by function onWidget()
-
-/**
- * @short Common base class for UMLWidget and AssociationWidget
- * @author Oliver Kellogg <okellogg@users.sourceforge.net>
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-class WidgetBase : public QGraphicsObject
-{
- Q_OBJECT
- Q_ENUMS(WidgetType)
-
-public:
- enum WidgetType
- {
- wt_UMLWidget = 300, // does not have UMLObject representation
- wt_Actor, // has UMLObject representation
- wt_UseCase, // has UMLObject representation
- wt_Class, // has UMLObject representation
- wt_Interface, // has UMLObject representation
- wt_Datatype, // has UMLObject representation
- wt_Enum, // has UMLObject representation
- wt_Entity, // has UMLObject representation
- wt_Package, // has UMLObject representation
- wt_Object, // has UMLObject representation
- wt_Note, // does not have UMLObject representation
- wt_Box, // does not have UMLObject representation
- wt_Message, // does not have UMLObject representation
- wt_Text, // does not have UMLObject representation
- wt_State, // does not have UMLObject representation
- wt_Activity, // does not have UMLObject representation
- wt_Component, // has UMLObject representation
- wt_Artifact, // has UMLObject representation
- wt_Node, // has UMLObject representation
- wt_Association, // has UMLObject representation
- wt_ForkJoin, // does not have UMLObject representation
- wt_Precondition, // does not have UMLObject representation
- wt_CombinedFragment, // does not have UMLObject representation
- wt_FloatingDashLine, // does not have UMLObject representation
- wt_Signal, // does not have UMLObject representation
- wt_Pin,
- wt_ObjectNode,
- wt_Region,
- wt_Category, // has UMLObject representation
- wt_Port // has UMLObject representation
- };
-
- static QString toString(WidgetType wt);
- static QString toI18nString(WidgetType wt);
-
- explicit WidgetBase(UMLScene * scene, WidgetType type= wt_UMLWidget);
- virtual ~WidgetBase();
-
- UMLObject* umlObject() const;
- virtual void setUMLObject(UMLObject *obj);
-
- Uml::ID::Type id() const;
- void setID(Uml::ID::Type id);
-
- WidgetType baseType() const;
- QLatin1String baseTypeStr() const;
-
- virtual void setSelected(bool select);
-
- UMLScene* umlScene() const;
- UMLDoc* umlDoc() const;
-
- QString documentation() const;
- bool hasDocumentation();
- virtual void setDocumentation(const QString& doc);
-
- QString name() const;
- virtual void setName(const QString &strName);
-
- QColor lineColor() const;
- virtual void setLineColor(const QColor& color);
-
- uint lineWidth() const;
- virtual void setLineWidth(uint width);
-
- QColor textColor() const;
- virtual void setTextColor(const QColor& color);
-
- QColor fillColor() const;
- virtual void setFillColor(const QColor& color);
-
- bool usesDiagramLineColor() const;
- void setUsesDiagramLineColor(bool state);
-
- bool usesDiagramLineWidth() const;
- void setUsesDiagramLineWidth(bool state);
-
- bool useFillColor();
- virtual void setUseFillColor(bool state);
-
- bool usesDiagramTextColor() const;
- void setUsesDiagramTextColor(bool state);
-
- bool usesDiagramFillColor() const;
- void setUsesDiagramFillColor(bool state);
-
- bool usesDiagramUseFillColor() const;
- void setUsesDiagramUseFillColor(bool state);
-
- virtual QFont font() const;
- virtual void setFont(const QFont& font);
-
- virtual void showPropertiesDialog();
-
- virtual bool loadFromXMI(QDomElement &qElement);
- virtual void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
-
- WidgetBase& operator=(const WidgetBase& other);
-
- QRectF rect() const;
- void setRect(const QRectF& rect);
- void setRect(qreal x, qreal y, qreal width, qreal height);
-
- virtual QRectF boundingRect() const;
-
- virtual UMLWidget* onWidget(const QPointF &p);
-
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
-public Q_SLOTS:
- virtual void slotMenuSelection(QAction *trigger);
-
-protected:
- virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
-
- WidgetType m_baseType; ///< Type of widget.
- UMLScene *m_scene;
- UMLObject *m_umlObject;
- QString m_Doc; ///< Only used if m_umlObject is not set.
- QString m_Text;
- QRectF m_rect; ///< widget size
-
- /**
- * This ID is only used when the widget does not have a
- * corresponding UMLObject (i.e. the m_umlObject pointer is NULL.)
- * For UMLObjects, the ID from the UMLObject is used.
- */
- Uml::ID::Type m_nId;
-
- QColor m_textColor; ///< Color of the text of the widget. Is saved to XMI.
- QColor m_lineColor; ///< Color of the lines of the widget. Is saved to XMI.
- QColor m_fillColor; ///< color of the background of the widget
- QBrush m_brush;
- QFont m_font;
- uint m_lineWidth; ///< Width of the lines of the widget. Is saved to XMI.
- bool m_useFillColor; ///< flag indicates if the UMLWidget uses the Diagram FillColour
-
- /**
- * true by default, false if the colors have
- * been explicitly set for this widget.
- * These are saved to XMI.
- */
- bool m_usesDiagramTextColor;
- bool m_usesDiagramLineColor;
- bool m_usesDiagramFillColor;
- bool m_usesDiagramUseFillColor;
- bool m_usesDiagramLineWidth;
-};
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/widget_factory.cpp umbrello-kf6-15.08.1/umbrello/widgets/widget_factory.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/widget_factory.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/widget_factory.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,296 +0,0 @@
-/***************************************************************************
- * 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) 2006-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "widget_factory.h"
-
-// app includes
-#include "activitywidget.h"
-#include "actor.h"
-#include "actorwidget.h"
-#include "artifact.h"
-#include "artifactwidget.h"
-#include "associationwidget.h"
-#include "boxwidget.h"
-#include "category.h"
-#include "categorywidget.h"
-#include "classifier.h"
-#include "classifierwidget.h"
-#include "cmds.h"
-#include "combinedfragmentwidget.h"
-#include "component.h"
-#include "componentwidget.h"
-#include "datatypewidget.h"
-#include "debug_utils.h"
-#include "entity.h"
-#include "entitywidget.h"
-#include "enum.h"
-#include "enumwidget.h"
-#include "floatingdashlinewidget.h"
-#include "floatingtextwidget.h"
-#include "folder.h"
-#include "forkjoinwidget.h"
-#include "messagewidget.h"
-#include "node.h"
-#include "nodewidget.h"
-#include "notewidget.h"
-#include "object_factory.h"
-#include "objectnodewidget.h"
-#include "objectwidget.h"
-#include "package.h"
-#include "packagewidget.h"
-#include "pinwidget.h"
-#include "port.h"
-#include "portwidget.h"
-#include "preconditionwidget.h"
-#include "regionwidget.h"
-#include "signalwidget.h"
-#include "statewidget.h"
-#include "uml.h"
-#include "umldoc.h"
-#include "umlscene.h"
-#include "umlview.h"
-#include "usecase.h"
-#include "usecasewidget.h"
-
-namespace Widget_Factory {
-
-/**
- * Create a UMLWidget in the given view and representing the given document object.
- */
-UMLWidget *createWidget(UMLScene *scene, UMLObject *o)
-{
- QPointF pos = scene->pos();
- int y = pos.y();
- Uml::DiagramType::Enum diagramType = scene->type();
- UMLObject::ObjectType type = o->baseType();
- UMLWidget *newWidget = NULL;
- switch (type) {
- case UMLObject::ot_Actor:
- if (diagramType == Uml::DiagramType::Sequence) {
- ObjectWidget *ow = new ObjectWidget(scene, o);
- ow->setDrawAsActor(true);
- y = ow->topMargin();
- newWidget = ow;
- } else
- newWidget = new ActorWidget(scene, static_cast<UMLActor*>(o));
- break;
- case UMLObject::ot_UseCase:
- newWidget = new UseCaseWidget(scene, static_cast<UMLUseCase*>(o));
- break;
- case UMLObject::ot_Folder:
- case UMLObject::ot_Package:
- newWidget = new ClassifierWidget(scene, static_cast<UMLPackage*>(o));
- break;
- case UMLObject::ot_Component:
- newWidget = new ComponentWidget(scene, static_cast<UMLComponent*>(o));
- if (diagramType == Uml::DiagramType::Deployment) {
- newWidget->setIsInstance(true);
- }
- break;
- case UMLObject::ot_Port:
- {
- PinPortBase *pw = new PortWidget(scene, static_cast<UMLPort*>(o));
- pw->attachToOwner();
- newWidget = pw;
- }
- break;
- case UMLObject::ot_Node:
- newWidget = new NodeWidget(scene, static_cast<UMLNode*>(o));
- break;
- case UMLObject::ot_Artifact:
- newWidget = new ArtifactWidget(scene, static_cast<UMLArtifact*>(o));
- break;
- case UMLObject::ot_Datatype:
- newWidget = new DatatypeWidget(scene, static_cast<UMLClassifier*>(o));
- break;
- case UMLObject::ot_Enum:
- newWidget = new EnumWidget(scene, static_cast<UMLEnum*>(o));
- break;
- case UMLObject::ot_Entity:
- newWidget = new EntityWidget(scene, static_cast<UMLEntity*>(o));
- break;
- case UMLObject::ot_Interface:
- if (diagramType == Uml::DiagramType::Sequence || diagramType == Uml::DiagramType::Collaboration) {
- ObjectWidget *ow = new ObjectWidget(scene, o);
- if (diagramType == Uml::DiagramType::Sequence) {
- y = ow->topMargin();
- }
- newWidget = ow;
- } else {
- UMLClassifier *c = static_cast<UMLClassifier*>(o);
- ClassifierWidget* interfaceWidget = new ClassifierWidget(scene, c);
- if (diagramType == Uml::DiagramType::Component || diagramType == Uml::DiagramType::Deployment) {
- interfaceWidget->setDrawAsCircle(true);
- }
- newWidget = interfaceWidget;
- }
- break;
- case UMLObject::ot_Class:
- //see if we really want an object widget or class widget
- if (diagramType == Uml::DiagramType::Class || diagramType == Uml::DiagramType::Component) {
- UMLClassifier *c = static_cast<UMLClassifier*>(o);
- ClassifierWidget *cw = new ClassifierWidget(scene, c);
- if (diagramType == Uml::DiagramType::Component)
- cw->setDrawAsCircle(true);
- newWidget = cw;
- } else {
- ObjectWidget *ow = new ObjectWidget(scene, o);
- if (diagramType == Uml::DiagramType::Sequence) {
- y = ow->topMargin();
- }
- newWidget = ow;
- }
- break;
- case UMLObject::ot_Category:
- newWidget = new CategoryWidget(scene, static_cast<UMLCategory*>(o));
- break;
- default:
- uWarning() << "trying to create an invalid widget (" << UMLObject::toString(type) << ")";
- }
-
- if (newWidget) {
- newWidget->setX(pos.x());
- newWidget->setY(y);
- }
-
- return newWidget;
-}
-
-bool validateObjType(UMLObject::ObjectType expected, UMLObject* &o, Uml::ID::Type id)
-{
- if (o == NULL) {
- uDebug() << "Widget_Factory::validateObjType: creating new object of type "
- << expected;
- QString artificialName = QLatin1String("LOST_") + Uml::ID::toString(id);
- o = Object_Factory::createUMLObject(expected, artificialName, NULL, false);
- if (o == NULL)
- return false;
- o->setID(id);
- UMLPackage *parentPkg = o->umlPackage();
- parentPkg->addObject(o);
- return true;
- }
- UMLObject::ObjectType actual = o->baseType();
- if (actual == expected)
- return true;
- uError() << "validateObjType(" << o->name()
- << "): expected type " << UMLObject::toString(expected) << ", actual type "
- << UMLObject::toString(actual);
- return false;
-}
-
-/**
- * Create a UMLWidget according to the given XMI tag.
- */
-UMLWidget* makeWidgetFromXMI(const QString& tag,
- const QString& idStr, UMLScene *scene)
-{
- UMLWidget *widget = NULL;
-
- // Loading of widgets which do NOT represent any UMLObject,
- // just graphic stuff with no real model information
- //FIXME while boxes and texts are just diagram objects, activities and
- // states should be UMLObjects
- if (tag == QLatin1String("statewidget") || tag == QLatin1String("UML:StateWidget")) {
- widget = new StateWidget(scene, StateWidget::Normal, Uml::ID::Reserved);
- } else if (tag == QLatin1String("notewidget") || tag == QLatin1String("UML:NoteWidget")) {
- widget = new NoteWidget(scene, NoteWidget::Normal, Uml::ID::Reserved);
- } else if (tag == QLatin1String("boxwidget")) {
- widget = new BoxWidget(scene, Uml::ID::Reserved);
- } else if (tag == QLatin1String("floatingtext") || tag == QLatin1String("UML:FloatingTextWidget")) {
- widget = new FloatingTextWidget(scene, Uml::TextRole::Floating, QString(), Uml::ID::Reserved);
- } else if (tag == QLatin1String("activitywidget") || tag == QLatin1String("UML:ActivityWidget")) {
- widget = new ActivityWidget(scene, ActivityWidget::Initial, Uml::ID::Reserved);
- } else if (tag == QLatin1String("messagewidget")) {
- widget = new MessageWidget(scene, Uml::SequenceMessage::Asynchronous, Uml::ID::Reserved);
- } else if (tag == QLatin1String("forkjoin")) {
- widget = new ForkJoinWidget(scene, Qt::Vertical, Uml::ID::Reserved);
- } else if (tag == QLatin1String("preconditionwidget")) {
- widget = new PreconditionWidget(scene, NULL, Uml::ID::Reserved);
- } else if (tag == QLatin1String("combinedFragmentwidget")) {
- widget = new CombinedFragmentWidget(scene, CombinedFragmentWidget::Ref, Uml::ID::Reserved);
- } else if (tag == QLatin1String("signalwidget")) {
- widget = new SignalWidget(scene, SignalWidget::Send, Uml::ID::Reserved);
- } else if (tag == QLatin1String("floatingdashlinewidget")) {
- widget = new FloatingDashLineWidget(scene, Uml::ID::Reserved);
- } else if (tag == QLatin1String("objectnodewidget")) {
- widget = new ObjectNodeWidget(scene, ObjectNodeWidget::Normal, Uml::ID::Reserved);
- } else if (tag == QLatin1String("regionwidget")) {
- widget = new RegionWidget(scene, Uml::ID::Reserved);
- } else if (tag == QLatin1String("pinwidget")) {
- PinPortBase *pw = new PinWidget(scene, NULL, Uml::ID::Reserved);
- pw->attachToOwner();
- widget = pw;
- }
- else
- {
- // Loading of widgets which represent an UMLObject
-
- // Find the UMLObject and create the Widget to represent it
- Uml::ID::Type id = Uml::ID::fromString(idStr);
- UMLDoc *umldoc = UMLApp::app()->document();
- UMLObject *o = umldoc->findObjectById(id);
- if (o == NULL) {
- uDebug() << "makeWidgetFromXMI: cannot find object with id "
- << Uml::ID::toString(id);
- }
-
- if (tag == QLatin1String("actorwidget") || tag == QLatin1String("UML:ActorWidget")) {
- if (validateObjType(UMLObject::ot_Actor, o, id))
- widget = new ActorWidget(scene, static_cast<UMLActor*>(o));
- } else if (tag == QLatin1String("usecasewidget") || tag == QLatin1String("UML:UseCaseWidget")) {
- if (validateObjType(UMLObject::ot_UseCase, o, id))
- widget = new UseCaseWidget(scene, static_cast<UMLUseCase*>(o));
- } else if (tag == QLatin1String("classwidget") ||
- tag == QLatin1String("UML:ClassWidget") || tag == QLatin1String("UML:ConceptWidget")) {
- if (validateObjType(UMLObject::ot_Class, o, id))
- widget = new ClassifierWidget(scene, static_cast<UMLClassifier*>(o));
- } else if (tag == QLatin1String("packagewidget")) {
- if (validateObjType(UMLObject::ot_Package, o, id))
- widget = new ClassifierWidget(scene, static_cast<UMLPackage*>(o));
- } else if (tag == QLatin1String("componentwidget")) {
- if (validateObjType(UMLObject::ot_Component, o, id))
- widget = new ComponentWidget(scene, static_cast<UMLComponent*>(o));
- } else if (tag == QLatin1String("portwidget")) {
- if (validateObjType(UMLObject::ot_Port, o, id))
- widget = new PortWidget(scene, static_cast<UMLPort*>(o));
- } else if (tag == QLatin1String("nodewidget")) {
- if (validateObjType(UMLObject::ot_Node, o, id))
- widget = new NodeWidget(scene, static_cast<UMLNode*>(o));
- } else if (tag == QLatin1String("artifactwidget")) {
- if (validateObjType(UMLObject::ot_Artifact, o, id))
- widget = new ArtifactWidget(scene, static_cast<UMLArtifact*>(o));
- } else if (tag == QLatin1String("interfacewidget")) {
- if (validateObjType(UMLObject::ot_Interface, o, id))
- widget = new ClassifierWidget(scene, static_cast<UMLClassifier*>(o));
- } else if (tag == QLatin1String("datatypewidget")) {
- if (validateObjType(UMLObject::ot_Datatype, o, id))
- widget = new DatatypeWidget(scene, static_cast<UMLClassifier*>(o));
- } else if (tag == QLatin1String("enumwidget")) {
- if (validateObjType(UMLObject::ot_Enum, o, id))
- widget = new EnumWidget(scene, static_cast<UMLEnum*>(o));
- } else if (tag == QLatin1String("entitywidget")) {
- if (validateObjType(UMLObject::ot_Entity, o, id))
- widget = new EntityWidget(scene, static_cast<UMLEntity*>(o));
- } else if (tag == QLatin1String("categorywidget")) {
- if (validateObjType(UMLObject::ot_Category, o, id))
- widget = new CategoryWidget(scene, static_cast<UMLCategory*>(o));
- } else if (tag == QLatin1String("objectwidget") || tag == QLatin1String("UML:ObjectWidget")) {
- widget = new ObjectWidget(scene, o);
- } else {
- uWarning() << "Trying to create an unknown widget:" << tag;
- }
- }
- return widget;
-}
-
-} // end namespace Widget_Factory
-
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/widget_factory.h umbrello-kf6-15.08.1/umbrello/widgets/widget_factory.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/widget_factory.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/widget_factory.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,34 +0,0 @@
-/***************************************************************************
- * 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) 2006-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef WIDGET_FACTORY_H
-#define WIDGET_FACTORY_H
-
-#include <QString>
-
-// forward declarations
-class UMLObject;
-class UMLScene;
-class UMLWidget;
-
-/**
- * Widget factory methods.
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-namespace Widget_Factory {
-
- UMLWidget *createWidget(UMLScene *scene, UMLObject *docObj);
-
- UMLWidget* makeWidgetFromXMI(const QString& tag,
- const QString& idStr, UMLScene *scene);
-
-} // end namespace Widget_Factory
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/widgetlist_utils.cpp umbrello-kf6-15.08.1/umbrello/widgets/widgetlist_utils.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/widgetlist_utils.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/widgetlist_utils.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,157 +0,0 @@
-/***************************************************************************
- * 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) 2009-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "widgetlist_utils.h"
-
-// app includes
-#include "debug_utils.h"
-#include "umlwidget.h"
-
-// qt/kde includes
-#include <QVector>
-
-namespace WidgetList_Utils
-{
-
-/**
- * Looks for the smallest x-value of the given UMLWidgets.
- * @param widgetList A list with UMLWidgets.
- * @return The smallest X position.
- */
-qreal getSmallestX(const UMLWidgetList &widgetList)
-{
- qreal smallestX = 0;
-
- int i = 1;
- foreach(UMLWidget *widget, widgetList) {
- if (i == 1) {
- smallestX = widget->x();
- } else {
- if (smallestX > widget->x())
- smallestX = widget->x();
- }
- i++;
- }
-
- return smallestX;
-}
-
-/**
- * Looks for the smallest y-value of the given UMLWidgets.
- * @param widgetList A list with UMLWidgets.
- * @return The smallest Y position.
- */
-qreal getSmallestY(const UMLWidgetList &widgetList)
-{
- if (widgetList.isEmpty())
- return -1;
-
- qreal smallestY = 0;
-
- int i = 1;
- foreach(UMLWidget *widget, widgetList) {
- if (i == 1) {
- smallestY = widget->y();
- } else {
- if (smallestY > widget->y())
- smallestY = widget->y();
- }
- i++;
- }
-
- return smallestY;
-}
-
-/**
- * Looks for the biggest x-value of the given UMLWidgets.
- * @param widgetList A list with UMLWidgets.
- * @return The biggest X position.
- */
-qreal getBiggestX(const UMLWidgetList &widgetList)
-{
- if (widgetList.isEmpty())
- return -1;
-
- qreal biggestX = 0;
-
- int i = 1;
- foreach(UMLWidget *widget, widgetList) {
- if (i == 1) {
- biggestX = widget->x();
- biggestX += widget->width();
- } else {
- if (biggestX < widget->x() + widget->width())
- biggestX = widget->x() + widget->width();
- }
- i++;
- }
-
- return biggestX;
-}
-
-/**
- * Looks for the biggest y-value of the given UMLWidgets.
- * @param widgetList A list with UMLWidgets.
- * @return The biggest Y position.
- */
-qreal getBiggestY(const UMLWidgetList &widgetList)
-{
- if (widgetList.isEmpty())
- return -1;
-
- qreal biggestY = 0;
-
- int i = 1;
- foreach(UMLWidget *widget, widgetList) {
- if (i == 1) {
- biggestY = widget->y();
- biggestY += widget->height();
- } else {
- if (biggestY < widget->y() + widget->height())
- biggestY = widget->y() + widget->height();
- }
- i++;
- }
-
- return biggestY;
-}
-
-/**
- * Returns the sum of the heights of the given UMLWidgets
- * @param widgetList A list with UMLWidgets.
- */
-qreal getHeightsSum(const UMLWidgetList &widgetList)
-{
- qreal heightsSum = 0;
-
- foreach(UMLWidget *widget, widgetList) {
- heightsSum += widget->height();
- }
-
- return heightsSum;
-}
-
-/**
- * Returns the sum of the widths of the given UMLWidgets.
- * @param widgetList A list with UMLWidgets.
- */
-qreal getWidthsSum(const UMLWidgetList &widgetList)
-{
- qreal widthsSum = 0;
-
- foreach(UMLWidget *widget, widgetList) {
- widthsSum += widget->width();
- }
-
- return widthsSum;
-}
-
-} // namespace WidgetList_Utils
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/widgetlist_utils.h umbrello-kf6-15.08.1/umbrello/widgets/widgetlist_utils.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/widgetlist_utils.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/widgetlist_utils.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,30 +0,0 @@
-/***************************************************************************
- * 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) 2009-2014 *
- * umbrello-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef WIDGETLIST_UTILS_H
-#define WIDGETLIST_UTILS_H
-
-#include "umlwidgetlist.h"
-
-/**
- * General purpose-kf6 widget list utilities.
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-namespace WidgetList_Utils
-{
- qreal getSmallestX(const UMLWidgetList &widgetList);
- qreal getSmallestY(const UMLWidgetList &widgetList);
- qreal getBiggestX(const UMLWidgetList &widgetList);
- qreal getBiggestY(const UMLWidgetList &widgetList);
- qreal getHeightsSum(const UMLWidgetList &widgetList);
- qreal getWidthsSum(const UMLWidgetList &widgetList);
-} // namespace WidgetList_Utils
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/widget_utils.cpp umbrello-kf6-15.08.1/umbrello/widgets/widget_utils.cpp
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/widget_utils.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/widget_utils.cpp 1970-01-01 02:00:00.000000000 +0200
@@ -1,827 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-// own header
-#include "widget_utils.h"
-
-// app includes
-#include "debug_utils.h"
-#include "objectwidget.h"
-#include "messagewidget.h"
-#include "umlwidget.h"
-
-// qt includes
-#include <QBuffer>
-#include <QImageReader>
-#include <QGraphicsItem>
-#include <QGraphicsRectItem>
-#include <QPolygonF>
-
-// c++ include
-#include <cmath>
-
-namespace Widget_Utils
-{
-
- /**
- * Find the widget identified by the given ID in the given widget
- * or message list.
- *
- * @param id The unique ID to find.
- * @param widgets The UMLWidgetList to search in.
- * @param messages Optional pointer to a MessageWidgetList to search in.
- */
- UMLWidget* findWidget(Uml::ID::Type id,
- const UMLWidgetList& widgets,
- const MessageWidgetList* messages /* = 0 */)
- {
- foreach (UMLWidget* obj, widgets) {
- if (obj->baseType() == WidgetBase::wt_Object) {
- if (static_cast<ObjectWidget *>(obj)->localID() == id)
- return obj;
- } else if (obj->id() == id) {
- return obj;
- }
- }
-
- if (messages) {
- foreach (UMLWidget* obj, *messages) {
- if (obj->id() == id)
- return obj;
- }
- }
- return NULL;
- }
-
- /**
- * Creates the decoration point.
- * @param p base point to decorate
- * @param parent parent item
- * @return decoration point
- */
- QGraphicsRectItem* decoratePoint(const QPointF &p, QGraphicsItem* parent)
- {
- const qreal SIZE = 4.0;
- const qreal SIZE_HALF = SIZE / 2.0;
- QGraphicsRectItem *rect = new QGraphicsRectItem(p.x() - SIZE_HALF,
- p.y() - SIZE_HALF,
- SIZE, SIZE,
- parent);
- rect->setBrush(QBrush(Qt::blue));
- rect->setPen(QPen(Qt::blue));
- return rect;
- }
-
- /**
- * Calculates and draws a cross inside an ellipse
- * @param p Pointer to a QPainter object.
- * @param r The rectangle describing the ellipse.
- */
- void drawCrossInEllipse(QPainter *p, const QRectF& r)
- {
- QRectF ellipse = r;
- ellipse.moveCenter(QPointF(0, 0));
- qreal a = ellipse.width() * 0.5;
- qreal b = ellipse.height() * .5;
- qreal xc = ellipse.center().x();
- qreal yc = ellipse.center().y();
-
- // The first point's x value is chosen to be center.x() + 70% of x radius.
- qreal x1 = ellipse.center().x() + .7 * .5 * ellipse.width();
- // Calculate y1 corresponding to x1 using formula.
- qreal y1_sqr = b*b*(1 - (x1 * x1) / (a*a));
- qreal y1 = std::sqrt(y1_sqr);
-
- // Mirror x1, y1 along both the axes to get 4 points for the cross.
- QPointF p1(xc + x1, yc + y1);
- QPointF p2(xc - x1, yc + y1);
- QPointF p3(xc + x1, yc - y1);
- QPointF p4(xc - x1, yc - y1);
-
- // Translate as we calculate for ellipse with (0, 0) as center.
- p->translate(r.center().x(), r.center().y());
-
- // Draw the cross now
- p->drawLine(QLineF(p1, p4));
- p->drawLine(QLineF(p2, p3));
-
- // Restore the translate on painter.
- p->translate(-r.center().x(), -r.center().y());
- }
-
- /**
- * Draws a polygon which is almost rectangular except for the top
- * right corner. A triangle is drawn in top right corner of the
- * rectangle.
- *
- * @param painter The painter with which this shape is to be drawn.
- * @param rect The rectangle dimensions.
- * @param triSize The size of the triangle in the top-right corner.
- */
- void drawTriangledRect(QPainter *painter,
- const QRectF &rect, const QSizeF &triSize)
- {
- // Draw outer boundary defined by polygon "poly".
- QPolygonF poly(5);
- poly[0] = rect.topLeft();
- poly[1] = rect.topRight() - QPointF(triSize.width(), 0);
- poly[2] = rect.topRight() + QPointF(0, triSize.height());
- poly[3] = rect.bottomRight();
- poly[4] = rect.bottomLeft();
- painter->drawPolygon(poly);
-
- // Now draw the triangle base and height edges.
- QLineF heightEdge(poly[1], poly[1] + QPointF(0, triSize.height()));
- painter->drawLine(heightEdge);
- QLineF baseEdge(heightEdge.p2(), poly[2]);
- painter->drawLine(baseEdge);
- }
-
-// /**
-// * Draws an arrow head with the given painter, with the arrow
-// * sharp point at \a headPos.
-// *
-// * param painter The painter with which this arrow should be drawn.
-// * param headPos The position where the head of the arrow should lie.
-// * param arrowSize This indicates the size of the arrow head.
-// * param arrowType This indicates direction of arrow as in LeftArrow, RightArrow..
-// * param solid-kf6 If true, a solid-kf6 head is drawn. Otherwise 2 lines are drawn.
-// */
-// void drawArrowHead(QPainter *painter, const QPointF &arrowPos,
-// const QSizeF& arrowSize, Qt::ArrowType arrowType,
-// bool solid-kf6)
-// {
-// QPolygonF poly;
-// if (arrowType == Qt::LeftArrow) {
-// poly << QPointF(arrowPos.x() + arrowSize.width(), arrowPos.y() - .5 * arrowSize.height())
-// << arrowPos
-// << QPointF(arrowPos.x() + arrowSize.width(), arrowPos.y() + .5 * arrowSize.height());
-// }
-// else if (arrowType == Qt::RightArrow) {
-// poly << QPointF(arrowPos.x() - arrowSize.width(), arrowPos.y() - .5 * arrowSize.height())
-// << arrowPos
-// << QPointF(arrowPos.x() - arrowSize.width(), arrowPos.y() + .5 * arrowSize.height());
-// }
-
-// if (solid-kf6) {
-// painter->drawPolygon(poly);
-// }
-// else {
-// painter->drawPolyline(poly);
-// }
-// }
-
-// /**
-// * Draws a rounded rect rounded at specified corners.
-// *
-// * param painter The painter with which this round rect should be drawn.
-// * param rect The rectangle to be drawn.
-// * param xRadius The x radius of rounded corner.
-// * param yRadius The y radius of rounded corner.
-// * param corners The corners to be rounded.
-// */
-// void drawRoundedRect(QPainter *painter, const QRectF& rect, qreal xRadius,
-// qreal yRadius, Uml::Corners corners)
-// {
-// if (xRadius < 0 || yRadius < 0) {
-// painter->drawRect(rect);
-// return;
-// }
-// QRectF arcRect(0, 0, 2 * xRadius, 2 * yRadius);
-
-// QPainterPath path;
-// path.moveTo(rect.left(), rect.top() + yRadius);
-// if (corners.testFlag(Uml::Corner::TopLeft)) {
-// arcRect.moveTopLeft(rect.topLeft());
-// path.arcTo(arcRect, 180, -90);
-// } else {
-// path.lineTo(rect.topLeft());
-// }
-
-// path.lineTo(rect.right() - xRadius, rect.top());
-
-// if (corners.testFlag(Uml::Corner::TopRight)) {
-// arcRect.moveTopRight(rect.topRight());
-// path.arcTo(arcRect, 90, -90);
-// } else {
-// path.lineTo(rect.topRight());
-// }
-
-// path.lineTo(rect.right(), rect.bottom() - yRadius);
-
-// if (corners.testFlag(Uml::Corner::BottomRight)) {
-// arcRect.moveBottomRight(rect.bottomRight());
-// path.arcTo(arcRect, 0, -90);
-// } else {
-// path.lineTo(rect.bottomRight());
-// }
-
-// path.lineTo(rect.left() + xRadius, rect.bottom());
-
-// if (corners.testFlag(Uml::Corner::BottomLeft)) {
-// arcRect.moveBottomLeft(rect.bottomLeft());
-// path.arcTo(arcRect, 270, 90);
-// } else {
-// path.lineTo(rect.bottomLeft());
-// }
-
-// path.closeSubpath();
-// painter->drawPath(path);
-// }
-
- /**
- * Converts a point to a comma separated string i.e "x,y"
- * @param point The QPointF to convert.
- */
- QString pointToString(const QPointF& point)
- {
- return QString::fromLatin1("%1,%2").arg(point.x()).arg(point.y());
- }
-
- /**
- * Converts a comma separated string to point.
- */
- QPointF stringToPoint(const QString& str)
- {
- QPointF retVal;
- QStringList list = str.split(QLatin1Char(','));
-
- if(list.size() == 2) {
- retVal.setX(list.first().toDouble());
- retVal.setY(list.last().toDouble());
- }
- return retVal;
- }
-
- /**
- * Loads pixmap from xmi.
- *
- * @param pixEle The dom element from which pixmap should be loaded.
- *
- * @param pixmap The pixmap into which the image should be loaded.
- *
- * @return True or false based on success or failure of this method.
- */
- bool loadPixmapFromXMI(QDomElement &pixEle, QPixmap &pixmap)
- {
- if (pixEle.isNull()) {
- return false;
- }
- QDomElement xpmElement = pixEle.firstChildElement(QLatin1String("xpm"));
-
- QByteArray xpmData = xpmElement.text().toLatin1();
- QBuffer buffer(&xpmData);
- buffer.open(QIODevice::ReadOnly);
-
- QImageReader reader(&buffer, "xpm");
- QImage image;
- if (!reader.read(&image)) {
- return false;
- }
-
- pixmap = QPixmap::fromImage(image);
- return true;
- }
-
- /**
- * Saves pixmap information into DOM element \a qElement.
- *
- * @param qDoc The DOM document object.
- *
- * @param qElement The DOM element into which the pixmap should be
- * saved.
- *
- * @param pixmap The pixmap to be saved.
- */
- void savePixmapToXMI(QDomDocument &qDoc, QDomElement &qElement, const QPixmap& pixmap)
- {
- QDomElement pixmapElement = qDoc.createElement(QLatin1String("pixmap"));
-
- QDomElement xpmElement = qDoc.createElement(QLatin1String("xpm"));
- pixmapElement.appendChild(xpmElement);
-
- QBuffer buffer;
- buffer.open(QIODevice::WriteOnly);
- pixmap.save(&buffer, "xpm");
- buffer.close();
-
- xpmElement.appendChild(qDoc.createTextNode(QString::fromLatin1(buffer.data())));
-
- qElement.appendChild(pixmapElement);
- }
-
- /**
- * Loads gradient from xmi. The gradient pointer should be null
- * and the new gradient object will be created inside this method.
- * The gradient should later be deleted externally.
- *
- * @param gradientElement The DOM element from which gradient should be
- * loaded.
- *
- * @param gradient The pointer to gradient into which the gradient
- * should be loaded. (Allocated inside this
- * method)
- *
- * @return True or false based on success or failure of this method.
- */
- bool loadGradientFromXMI(QDomElement &gradientElement, QGradient *&gradient)
- {
- if(gradientElement.isNull()) {
- return false;
- }
-
- int type_as_int;
- QGradient::Type type;
- QGradientStops stops;
- QGradient::CoordinateMode cmode = QGradient::LogicalMode;
- QGradient::Spread spread = QGradient::PadSpread;
-
- type_as_int = gradientElement.attribute(QLatin1String("type")).toInt();
- type = QGradient::Type(type_as_int);
- type_as_int = gradientElement.attribute(QLatin1String("spread")).toInt();
- spread = QGradient::Spread(type_as_int);
- type_as_int = gradientElement.attribute(QLatin1String("coordinatemode")).toInt();
- cmode = QGradient::CoordinateMode(type_as_int);
-
- QDomElement stopElement = gradientElement.firstChildElement(QLatin1String("stops"));
- if(stopElement.isNull()) {
- return false;
- }
- for(QDomNode node = stopElement.firstChild(); !node.isNull(); node = node.nextSibling()) {
- QDomElement ele = node.toElement();
- if(ele.tagName() != QLatin1String("stop")) {
- continue;
- }
-
- qreal posn = ele.attribute(QLatin1String("position")).toDouble();
- QColor color = QColor(ele.attribute(QLatin1String("color")));
- stops << QGradientStop(posn, color);
- }
-
- if (type == QGradient::LinearGradient) {
- QPointF p1 = stringToPoint(gradientElement.attribute(QLatin1String("start")));
- QPointF p2 = stringToPoint(gradientElement.attribute(QLatin1String("finalstop")));
- gradient = new QLinearGradient(p1, p2);
- }
- else if (type == QGradient::RadialGradient) {
- QPointF center = stringToPoint(gradientElement.attribute(QLatin1String("center")));
- QPointF focal = stringToPoint(gradientElement.attribute(QLatin1String("focalpoint")));
- double radius = gradientElement.attribute(QLatin1String("radius")).toDouble();
- gradient = new QRadialGradient(center, radius, focal);
- }
- else { // type == QGradient::ConicalGradient
- QPointF center = stringToPoint(gradientElement.attribute(QLatin1String("center")));
- double angle = gradientElement.attribute(QLatin1String("angle")).toDouble();
- gradient = new QConicalGradient(center, angle);
- }
-
- if(gradient) {
- gradient->setStops(stops);
- gradient->setSpread(spread);
- gradient->setCoordinateMode(cmode);
- return true;
- }
-
- return false;
- }
-
- /**
- * Saves gradient information into DOM element \a qElement.
- *
- * @param qDoc The DOM document object.
- *
- * @param qElement The DOM element into which the gradient should be
- * saved.
- *
- * @param gradient The gradient to be saved.
- */
- void saveGradientToXMI(QDomDocument &qDoc, QDomElement &qElement, const QGradient *gradient)
- {
- QDomElement gradientElement = qDoc.createElement(QLatin1String("gradient"));
-
- gradientElement.setAttribute(QLatin1String("type"), int(gradient->type()));
- gradientElement.setAttribute(QLatin1String("spread"), int(gradient->spread()));
- gradientElement.setAttribute(QLatin1String("coordinatemode"), int(gradient->coordinateMode()));
-
- QDomElement stopsElement = qDoc.createElement(QLatin1String("stops"));
- gradientElement.appendChild(stopsElement);
-
- foreach(const QGradientStop& stop, gradient->stops()) {
- QDomElement ele = qDoc.createElement(QLatin1String("stop"));
- ele.setAttribute(QLatin1String("position"), stop.first);
- ele.setAttribute(QLatin1String("color"), stop.second.name());
- stopsElement.appendChild(ele);
- }
-
- QGradient::Type type = gradient->type();
-
- if(type == QGradient::LinearGradient) {
- const QLinearGradient *lg = static_cast<const QLinearGradient*>(gradient);
- gradientElement.setAttribute(QLatin1String("start"), pointToString(lg->start()));
- gradientElement.setAttribute(QLatin1String("finalstop"), pointToString(lg->finalStop()));
- }
- else if(type == QGradient::RadialGradient) {
- const QRadialGradient *rg = static_cast<const QRadialGradient*>(gradient);
- gradientElement.setAttribute(QLatin1String("center"), pointToString(rg->center()));
- gradientElement.setAttribute(QLatin1String("focalpoint"), pointToString(rg->focalPoint()));
- gradientElement.setAttribute(QLatin1String("radius"), rg->radius());
- }
- else { //type == QGradient::ConicalGradient
- const QConicalGradient *cg = static_cast<const QConicalGradient*>(gradient);
- gradientElement.setAttribute(QLatin1String("center"), pointToString(cg->center()));
- gradientElement.setAttribute(QLatin1String("angle"), cg->angle());
- }
-
- qElement.appendChild(gradientElement);
- }
-
- /**
- * Extracts the QBrush properties into brush from the XMI xml
- * element qElement.
- *
- * @param qElement The DOM element from which the xmi info should
- * be extracted.
- *
- * @param brush The QBrush object into which brush details should
- * be read into.
- */
- bool loadBrushFromXMI(QDomElement &qElement, QBrush &brush)
- {
- if(qElement.isNull()) {
- return false;
- }
-
- quint8 style = qElement.attribute(QLatin1String("style")).toShort();
- const QString colorString = qElement.attribute(QLatin1String("color"));
- QColor color;
- color.setNamedColor(colorString);
-
- if(style == Qt::TexturePattern) {
- QPixmap pixmap;
- QDomElement pixElement = qElement.firstChildElement(QLatin1String("pixmap"));
- if(!loadPixmapFromXMI(pixElement, pixmap)) {
- return false;
- }
- brush = QBrush(color, pixmap);
- }
-
- else if(style == Qt::LinearGradientPattern
- || style == Qt::RadialGradientPattern
- || style == Qt::ConicalGradientPattern) {
- QGradient *gradient = 0;
- QDomElement gradElement = qElement.firstChildElement(QLatin1String("gradient"));
-
- if(!loadGradientFromXMI(gradElement, gradient) || !gradient) {
- delete gradient;
- return false;
- }
-
- brush = QBrush(*gradient);
- delete gradient;
- }
-
- else {
- brush = QBrush(color, (Qt::BrushStyle)style);
- }
-
- //TODO: Checks if transform needs to be loaded.
-
- return true;
- }
-
- /**
- * Saves the brush info as xmi into the DOM element \a qElement.
- *
- * @param qDoc The QDomDocument object pointing to the xmi document.
- *
- * @param qElement The element into which the pen, brush and font
- * info should be saved.
- *
- * @param brush The QBrush whose details should be saved.
- */
- void saveBrushToXMI(QDomDocument &qDoc, QDomElement &qElement,
- const QBrush& brush)
- {
- QDomElement brushElement = qDoc.createElement(QLatin1String("brush"));
-
- brushElement.setAttribute(QLatin1String("style"), (quint8)brush.style());
- brushElement.setAttribute(QLatin1String("color"), brush.color().name());
-
- if(brush.style() == Qt::TexturePattern) {
- savePixmapToXMI(qDoc, brushElement, brush.texture());
- }
- else if(brush.style() == Qt::LinearGradientPattern
- || brush.style() == Qt::RadialGradientPattern
- || brush.style() == Qt::ConicalGradientPattern) {
- saveGradientToXMI(qDoc, brushElement, brush.gradient());
- }
-
- //TODO: Check if transform of this brush needs to be saved.
- qElement.appendChild(brushElement);
- }
-
- /**
- * Returns true if the first widget's X is smaller than second's.
- * Used for sorting the UMLWidgetList.
- * @param widget1 The widget to compare.
- * @param widget2 The widget to compare with.
- */
- bool hasSmallerX(const UMLWidget* widget1, const UMLWidget* widget2)
- {
- return widget1->x() < widget2->x();
- }
-
- /**
- * Returns true if the first widget's Y is smaller than second's.
- * Used for sorting the UMLWidgetList.
- * @param widget1 The widget to compare.
- * @param widget2 The widget to compare with.
- */
- bool hasSmallerY(const UMLWidget* widget1, const UMLWidget* widget2)
- {
- return widget1->y() < widget2->y();
- }
-
- /**
- * Find the region in which the rectangle \a other lies with respect to
- * the rectangle \a self.
- * Beware that the Qt coordinate system has its origin point (0,0) in
- * the upper left corner with Y values growing downwards, thus the Y
- * related comparisons might look inverted if your are used to the
- * natural coordinate system with (0,0) in the lower left corner.
- */
- Uml::Region::Enum findRegion(const QRectF& self, const QRectF &other)
- {
- const qreal ownX = self.x();
- const qreal ownY = self.y();
- const qreal ownWidth = self.width();
- const qreal ownHeight = self.height();
- const qreal otherX = other.x();
- const qreal otherY = other.y();
- const qreal otherWidth = other.width();
- const qreal otherHeight = other.height();
- Uml::Region::Enum region = Uml::Region::Center;
- if (otherX + otherWidth < ownX) {
- if (otherY + otherHeight < ownY)
- region = Uml::Region::NorthWest;
- else if (otherY > ownY + ownHeight)
- region = Uml::Region::SouthWest;
- else
- region = Uml::Region::West;
- } else if (otherX > ownX + ownWidth) {
- if (otherY + otherHeight < ownY)
- region = Uml::Region::NorthEast;
- else if (otherY > ownY + ownHeight)
- region = Uml::Region::SouthEast;
- else
- region = Uml::Region::East;
- } else {
- if (otherY + otherHeight < ownY)
- region = Uml::Region::North;
- else if (otherY > ownY + ownHeight)
- region = Uml::Region::South;
- else
- region = Uml::Region::Center;
- }
- return region;
- }
-
- /**
- * Return the point in \a poly which precedes the point at index \a index.
- * If \a index is 0 then return the last (or, if \a poly.isClosed() is
- * true, the second to last) point.
- */
- QPointF prevPoint(int index, const QPolygonF& poly) {
- if (poly.size() < 3 || index >= poly.size())
- return QPoint();
- if (index == 0)
- return poly.at(poly.size() - 1 - (int)poly.isClosed());
- return poly.at(index - 1);
- }
-
- /**
- * Return the point in \a poly which follows the point at index \a index.
- * If \a index is the last index then return the first (or, if
- * \a poly.isClosed() is true, the second) point.
- */
- QPointF nextPoint(int index, const QPolygonF& poly) {
- if (poly.size() < 3 || index >= poly.size())
- return QPoint();
- if (index == poly.size() - 1)
- return poly.at((int)poly.isClosed());
- return poly.at(index + 1);
- }
-
- /**
- * Return the middle value between \a a and \a b.
- */
- qreal middle(qreal a, qreal b)
- {
- return (a + b) / 2.0;
- }
-
- /**
- * Auxiliary type for function findLine()
- */
- enum Axis_Type { X , Y };
-
- /**
- * Auxiliary type for function findLine()
- */
- enum Comparison_Type { Smallest, Largest };
-
- /**
- * Find the line of \a poly with the smallest or largest value (controlled by \a seek)
- * along the axis controlled by \a axis.
- * In case \a axis is X, do not consider lines whose Y values lie outside the Y values
- * defined by \a boundingRect.
- * In case \a axis is Y, do not consider lines whose X values lie outside the X values
- * defined by \a boundingRect.
- */
- QLineF findLine(const QPolygonF& poly, Axis_Type axis, Comparison_Type seek, const QRectF& boundingRect)
- {
- const int lastIndex = poly.size() - 1 - (int)poly.isClosed();
- QPointF prev = poly.at(lastIndex), curr;
- QPointF p1(seek == Smallest ? QPointF(1.0e6, 1.0e6) : QPointF(-1.0e6, -1.0e6));
- QPointF p2;
- for (int i = 0; i <= lastIndex; i++) {
- curr = poly.at(i);
- // uDebug() << " poly[" << i << "] = " << curr;
- if (axis == X) {
- if (fmin(prev.y(), curr.y()) > boundingRect.y() + boundingRect.height() ||
- fmax(prev.y(), curr.y()) < boundingRect.y()) {
- // line is outside Y-axis range defined by boundingRect
- } else if ((seek == Smallest && curr.x() <= p1.x()) ||
- (seek == Largest && curr.x() >= p1.x())) {
- p1 = curr;
- p2 = prev;
- }
- } else {
- if (fmin(prev.x(), curr.x()) > boundingRect.x() + boundingRect.width() ||
- fmax(prev.x(), curr.x()) < boundingRect.x()) {
- // line is outside X-axis range defined by boundingRect
- } else if ((seek == Smallest && curr.y() <= p1.y()) ||
- (seek == Largest && curr.y() >= p1.y())) {
- p1 = curr;
- p2 = prev;
- }
- }
- prev = curr;
- }
- return QLineF(p1, p2);
- }
-
- /**
- * Determine the approximate closest points of two polygons.
- * @param self First QPolygonF.
- * @param other Second QPolygonF.
- * @return QLineF::p1() returns point of \a self;
- * QLineF::p2() returns point of \a other.
- */
- QLineF closestPoints(const QPolygonF& self, const QPolygonF& other)
- {
- const QRectF& selfRect = self.boundingRect();
- const QRectF& otherRect = other.boundingRect();
- Uml::Region::Enum region = findRegion(selfRect, otherRect);
- if (region == Uml::Region::Center)
- return QLineF();
- if (self.size() < 3 || other.size() < 3)
- return QLineF();
- QLineF result;
- const int selfLastIndex = self.size() - 1 - (int)self.isClosed();
- const int otherLastIndex = other.size() - 1 - (int)other.isClosed();
- QPointF selfPoint(self.at(selfLastIndex));
- QPointF otherPoint(other.at(otherLastIndex));
- QLineF selfLine, otherLine;
- int i;
-
- switch (region) {
-
- case Uml::Region::North:
- // Find other's line with largest Y values
- otherLine = findLine(other, Y, Largest, selfRect);
- // Find own line with smallest Y values
- selfLine = findLine(self, Y, Smallest, otherRect);
- // Use the middle value of the X values
- result.setLine(middle(selfLine.p2().x(), selfLine.p1().x()), selfLine.p1().y(),
- middle(otherLine.p2().x(), otherLine.p1().x()), otherLine.p1().y());
- break;
-
- case Uml::Region::South:
- // Find other's line with smallest Y values
- otherLine = findLine(other, Y, Smallest, selfRect);
- // Find own line with largest Y values
- selfLine = findLine(self, Y, Largest, otherRect);
- // Use the middle value of the X values
- result.setLine(middle(selfLine.p2().x(), selfLine.p1().x()), selfLine.p1().y(),
- middle(otherLine.p2().x(), otherLine.p1().x()), otherLine.p1().y());
- break;
-
- case Uml::Region::West:
- // Find other's line with largest X values
- otherLine = findLine(other, X, Largest, selfRect);
- // Find own line with smallest X values
- selfLine = findLine(self, X, Smallest, otherRect);
- // Use the middle value of the Y values
- result.setLine(selfLine.p1().x(), middle(selfLine.p2().y(), selfLine.p1().y()),
- otherLine.p1().x(), middle(otherLine.p2().y(), otherLine.p1().y()));
- break;
-
- case Uml::Region::East:
- // Find other's line with smallest X values
- otherLine = findLine(other, X, Smallest, selfRect);
- // Find own line with largest X values
- selfLine = findLine(self, X, Largest, otherRect);
- // Use the middle value of the Y values
- result.setLine(selfLine.p1().x(), middle(selfLine.p2().y(), selfLine.p1().y()),
- otherLine.p1().x(), middle(otherLine.p2().y(), otherLine.p1().y()));
- break;
-
- case Uml::Region::NorthWest:
- // Find other's point with largest X and largest Y value
- for (i = 0; i < otherLastIndex; ++i) {
- QPointF current(other.at(i));
- if (current.x() + current.y() >= otherPoint.x() + otherPoint.y()) {
- otherPoint = current;
- }
- }
- // Find own point with smallest X and smallest Y value
- for (i = 0; i < selfLastIndex; ++i) {
- QPointF current(self.at(i));
- if (current.x() + current.y() <= selfPoint.x() + selfPoint.y()) {
- selfPoint = current;
- }
- }
- result.setPoints(selfPoint, otherPoint);
- break;
-
- case Uml::Region::SouthWest:
- // Find other's point with largest X and smallest Y value
- for (i = 0; i < otherLastIndex; ++i) {
- QPointF current(other.at(i));
- if (current.x() >= otherPoint.x() && current.y() <= otherPoint.y()) {
- otherPoint = current;
- }
- }
- // Find own point with smallest X and largest Y value
- for (i = 0; i < selfLastIndex; ++i) {
- QPointF current(self.at(i));
- if (current.x() <= selfPoint.x() && current.y() >= selfPoint.y()) {
- selfPoint = current;
- }
- }
- result.setPoints(selfPoint, otherPoint);
- break;
-
- case Uml::Region::NorthEast:
- // Find other's point with smallest X and largest Y value
- for (i = 0; i < otherLastIndex; ++i) {
- QPointF current(other.at(i));
- if (current.x() <= otherPoint.x() && current.y() >= otherPoint.y()) {
- otherPoint = current;
- }
- }
- // Find own point with largest X and smallest Y value
- for (i = 0; i < selfLastIndex; ++i) {
- QPointF current(self.at(i));
- if (current.x() >= selfPoint.x() && current.y() <= selfPoint.y()) {
- selfPoint = current;
- }
- }
- result.setPoints(selfPoint, otherPoint);
- break;
-
- case Uml::Region::SouthEast:
- // Find other's point with smallest X and smallest Y value
- for (i = 0; i < otherLastIndex; ++i) {
- QPointF current(other.at(i));
- if (current.x() + current.y() <= otherPoint.x() + otherPoint.y()) {
- otherPoint = current;
- }
- }
- // Find own point with largest X and largest Y value
- for (i = 0; i < selfLastIndex; ++i) {
- QPointF current(self.at(i));
- if (current.x() + current.y() >= selfPoint.x() + selfPoint.y()) {
- selfPoint = current;
- }
- }
- result.setPoints(selfPoint, otherPoint);
- break;
-
- default:
- // Error
- break;
- }
-
- return result;
- }
-
-} // namespace Widget_Utils
diff -Nuar umbrello-kf6-15.08.1.orig/umbrello/widgets/widget_utils.h umbrello-kf6-15.08.1/umbrello/widgets/widget_utils.h
--- umbrello-kf6-15.08.1.orig/umbrello/widgets/widget_utils.h 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/umbrello/widgets/widget_utils.h 1970-01-01 02:00:00.000000000 +0200
@@ -1,66 +0,0 @@
-/***************************************************************************
- * 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-kf6 UML Modeller Authors <umbrello-kf6-devel@kde.org> *
- ***************************************************************************/
-
-#ifndef WIDGET_UTILS_H
-#define WIDGET_UTILS_H
-
-#include "basictypes.h"
-#include "messagewidgetlist.h"
-#include "umlwidgetlist.h"
-
-#include <QBrush>
-#include <QDomDocument>
-#include <QPointF>
-#include <QLineF>
-#include <QPolygonF>
-
-class QGraphicsItem;
-class QGraphicsRectItem;
-
-/**
- * General purpose-kf6 widget utilities.
- * Bugs and comments to umbrello-kf6-devel@kde.org or http://bugs.kde.org
- */
-namespace Widget_Utils
-{
- UMLWidget* findWidget(Uml::ID::Type id,
- const UMLWidgetList& widgets,
- const MessageWidgetList* messages = 0);
-
- QGraphicsRectItem* decoratePoint(const QPointF& p, QGraphicsItem* parent = 0);
-
- void drawCrossInEllipse(QPainter *p, const QRectF& ellipse);
- void drawTriangledRect(QPainter *painter, const QRectF& rect, const QSizeF& triSize);
-// void drawArrowHead(QPainter *painter, const QPointF& arrowPos,
-// const QSizeF& arrowSize, Qt::ArrowType arrowType,
-// bool solid-kf6 = false);
-// void drawRoundedRect(QPainter *painter, const QRectF& rect, qreal xRadius,
-// qreal yRadius, Uml::Corners corners);
-
- QString pointToString(const QPointF& point);
- QPointF stringToPoint(const QString& str);
-
- bool loadPixmapFromXMI(QDomElement &qElement, QPixmap &pixmap);
- void savePixmapToXMI(QDomDocument &qDoc, QDomElement &qElement, const QPixmap& pixmap);
-
- bool loadGradientFromXMI(QDomElement &qElement, QGradient *&gradient);
- void saveGradientToXMI(QDomDocument &qDoc, QDomElement &qElement, const QGradient *gradient);
-
- bool loadBrushFromXMI(QDomElement &qElement, QBrush &brush);
- void saveBrushToXMI(QDomDocument &qDoc, QDomElement &qElement,
- const QBrush& brush);
-
- bool hasSmallerX(const UMLWidget* widget1, const UMLWidget* widget2);
- bool hasSmallerY(const UMLWidget* widget1, const UMLWidget* widget2);
-
- QLineF closestPoints(const QPolygonF& self, const QPolygonF& other);
-}
-
-#endif
diff -Nuar umbrello-kf6-15.08.1.orig/unittests/CMakeLists.txt umbrello-kf6-15.08.1/unittests/CMakeLists.txt
--- umbrello-kf6-15.08.1.orig/unittests/CMakeLists.txt 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/unittests/CMakeLists.txt 2015-10-08 11:48:59.553089025 +0300
@@ -37,7 +37,8 @@
${SRC_PATH}/dialogs
${SRC_PATH}/docgenerators
${SRC_PATH}/refactoring
- ${SRC_PATH}/widgets
+ ${SRC_PATH}/umlmodel/
+ ${SRC_PATH}/umlwidgets/
${CMAKE_CURRENT_BINARY_DIR}
)
diff -Nuar umbrello-kf6-15.08.1.orig/unittests/testbase.cpp umbrello-kf6-15.08.1/unittests/testbase.cpp
--- umbrello-kf6-15.08.1.orig/unittests/testbase.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/unittests/testbase.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -39,8 +39,6 @@
#include <QTemporaryDir>
#endif
-static UMLApp *umlApp = 0;
-
TestBase::TestBase(QObject *parent)
: QObject(parent)
{
@@ -49,12 +47,12 @@
void TestBase::initTestCase()
{
QWidget *w = new QWidget;
- umlApp = new UMLApp(w);
+ new UMLApp(w);
}
void TestBase::cleanupTestCase()
{
- delete umlApp;
+ delete UMLApp::app();
}
void TestCodeGeneratorBase::initTestCase()
diff -Nuar umbrello-kf6-15.08.1.orig/unittests/TEST_cppwriter.cpp umbrello-kf6-15.08.1/unittests/TEST_cppwriter.cpp
--- umbrello-kf6-15.08.1.orig/unittests/TEST_cppwriter.cpp 2015-09-10 01:54:59.000000000 +0300
+++ umbrello-kf6-15.08.1/unittests/TEST_cppwriter.cpp 2015-10-08 11:48:59.553089025 +0300
@@ -51,9 +51,11 @@
UMLAttribute* attr;
attr = c->createAttribute("name_");
attr = c->createAttribute("address_");
+ c->addAttribute(attr);
UMLOperation* op;
op = c->createOperation("getName");
op = c->createOperation("getAddress");
+ c->addOperation(op);
cpp->writeClass(c);
// does the just created file exist?