77853 lines
2.5 MiB
Plaintext
Executable File
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&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?
|