Commit 9817ffc9 authored by Oliver Kellogg's avatar Oliver Kellogg

https://bugs.kde.org/show_bug.cgi?id=427532#c1

Remove default datatypes of previous Active Language:

umbrello/uml1model/datatype.{h,cpp}
- Add member variable m_isActive initialized to true by constructor.
- Add accessor functions setActive(bool active = true), isActive().
- Peripheral cleanup: Override function load1 in lieu of loadFromXMI1.

umbrello/uml1model/datatype.cpp
- In function load1, set m_isActive true if XMI attribute "isActive"
  does not exist or if its value is not "false".
- In function saveToXMI1, setAttribute "isActive" to "false" on the
  classifierElement if m_isActive is false.

umbrello/uml1model/package.{h,cpp}
- At function containedObjects add optional argument includeInactive
  of type bool defaulting to false.  If includeInactive is true then
  include datatypes with isActive() false in the returned list.

umbrello/uml1model/package.cpp
- In function removeObject do not delete a datatype from its package
  but just set its isActive flag false.

umbrello/uml1model/folder.cpp
- In function load1 avoid duplicate creation of datatype when its name
  already exists in m_objects.

umbrello/umldoc.{h,cpp}
- At function datatypes() add optional argument includeInactive of type
  bool defaulting to false.  If includeInactive is true then include
  datatypes which have isActive() == false in the returned list.
- New function removeDatatype(const QString &name) removes a datatype
  from m_datatypeRoot->containedObjects() by name.

umbrello/umldoc.cpp
- In function createDatatype,
  - at call to m_datatypeRoot->containedObjects() provide argument
    includeInactive = true;
  - if Model_Utils::findUMLObject() returns non null and the retuned
    object is a UMLDatatype then set its isActive flag to true and emit
    sigObjectCreated; do not call Object_Factory::createUMLObject().

umbrello/uml.cpp
- In function setGenerator, if m_codegen is non null on entry then query
  m_codegen->defaultDatatypes() and call m_doc->removeDatatype() for
  each name returned.

umbrello/umllistview.cpp
- In function slotObjectCreated, if object->baseType() is ot_Datatype
  then check that the isActive flag is true; else refuse to create the
  UMLListViewItem.

umbrello/main.cpp
- At function initDocument :
  - Add argument progLang of type Uml::ProgrammingLanguage::Enum.
  - If UMLApp::app()->newDocument() is called then follow it by
    UMLApp::app()->setActiveLanguage(progLang).
  - If a file shall be opened, the programming language set by the
    <XMI.extensions> <codegeneration> element in the file shall take
    precedence over the language set via command line parameter,
    therefore do not call UMLApp::app()->setActiveLanguage.
- Adjust main program to change of function initDocument.

umbrello/version.h
- Increase XMI_FILE_VERSION to "1.6.19" due to the <UML:DataType> new
  attribute "isActive".

CCBUG: 427532
parent 4eaf28cf
......@@ -65,7 +65,7 @@ bool showGUI(KCmdLineArgs *args)
*
* @param args The command line arguments given.
*/
void initDocument(KCmdLineArgs *args)
void initDocument(KCmdLineArgs *args, Uml::ProgrammingLanguage::Enum progLang)
{
if (args->count()) {
UMLApp::app()->openDocumentFile(args->url(0));
......@@ -76,6 +76,8 @@ void initDocument(KCmdLineArgs *args)
UMLApp::app()->openDocumentFile(KUrl(file));
} else {
UMLApp::app()->newDocument();
if (progLang != Uml::ProgrammingLanguage::Reserved)
UMLApp::app()->setActiveLanguage(progLang);
}
}
}
......@@ -226,9 +228,7 @@ int main(int argc, char *argv[])
uml->importFiles(listFile, dir);
}
else {
initDocument(args);
if (lang != Uml::ProgrammingLanguage::Reserved)
uml->setActiveLanguage(lang);
initDocument(args, lang);
}
// export option
......
......@@ -2322,6 +2322,11 @@ CodeGenerator *UMLApp::setGenerator(Uml::ProgrammingLanguage::Enum pl)
// if (m_codegen->language() == pl) return m_codegen;
// Some languages depend on a new generator instance being created
// for each run.
QStringList entries = m_codegen->defaultDatatypes();
QStringList::Iterator end(entries.end());
for (QStringList::Iterator it = entries.begin(); it != end; ++it) {
m_doc->removeDatatype(*it);
}
delete m_codegen; // ATTENTION! remove all refs to it or its policy first
m_codegen = 0;
}
......
......@@ -18,7 +18,7 @@
*/
UMLDatatype::UMLDatatype(const QString & name, Uml::ID::Type id)
: UMLClassifier(name, id),
m_isRef(false)
m_isRef(false), m_isActive(true)
{
m_BaseType = UMLObject::ot_Datatype;
}
......@@ -67,25 +67,44 @@ bool UMLDatatype::isReference() const
}
/**
* Loads object from QDomElement.
* Set the m_isActive flag (is already set true by constructor).
* @param active the flag to set
*/
void UMLDatatype::setActive(bool active)
{
m_isActive = active;
}
/**
* Get the m_isActive flag.
* @return true if is active, otherwise false
*/
bool UMLDatatype::isActive() const
{
return m_isActive;
}
/**
* Loads Datatype specific attributes from QDomElement.
* Is invoked by UMLObject::loadFromXMI() which does most of the work.
*
* @param element A QDomElement which contains xml info for this object.
*/
bool UMLDatatype::loadFromXMI1(QDomElement & element)
bool UMLDatatype::load1(QDomElement & element)
{
if (!UMLObject::loadFromXMI1(element))
return false;
m_SecondaryId = element.attribute(QLatin1String("elementReference"));
if (!m_SecondaryId.isEmpty()) {
// @todo We do not currently support composition.
m_isRef = true;
}
QString active = element.attribute(QLatin1String("isActive"));
m_isActive = (active != QLatin1String("false"));
return true;
}
/**
* Creates the UML:Datatype element.
* Creates the UML:Datatype XMI element.
* Invokes UMLObject::save1() which does most of the work.
*
* @param qDoc the xml document
* @param qElement the xml element
......@@ -97,5 +116,8 @@ void UMLDatatype::saveToXMI1(QDomDocument & qDoc, QDomElement & qElement)
if (m_pSecondary != 0)
classifierElement.setAttribute(QLatin1String("elementReference"),
Uml::ID::toString(m_pSecondary->id()));
if (!m_isActive)
classifierElement.setAttribute(QLatin1String("isActive"), QLatin1String("false"));
qElement.appendChild(classifierElement);
}
......@@ -35,11 +35,15 @@ public:
void setIsReference(bool isRef = true);
bool isReference() const;
virtual bool loadFromXMI1(QDomElement & element);
void setActive(bool active = true);
bool isActive() const;
virtual bool load1(QDomElement & element);
virtual void saveToXMI1(QDomDocument & qDoc, QDomElement & qElement);
protected:
bool m_isRef;
bool m_isActive;
};
#endif
......@@ -21,6 +21,7 @@
#include "umldoc.h"
#include "umlscene.h"
#include "umlview.h"
#include "datatype.h"
// kde includes
#include <KLocalizedString>
......@@ -541,6 +542,22 @@ bool UMLFolder::load1(QDomElement& element)
uDebug() << "object " << idStr << "already exists";
}
}
// Avoid duplicate creation of datatype
if (pObject == 0 && this == umldoc->datatypeFolder()) {
QString name = tempElement.attribute(QLatin1String("name"));
foreach (UMLObject *o, m_objects) {
uIgnoreZeroPointer(o);
if (o->name() == name) {
UMLDatatype *dt = o->asUMLDatatype();
if (dt) {
QString isActive = tempElement.attribute(QLatin1String("isActive"));
dt->setActive(isActive != QLatin1String("false"));
pObject = dt;
break;
}
}
}
}
if (pObject == 0) {
QString stereoID = tempElement.attribute(QLatin1String("stereotype"));
pObject = Object_Factory::makeObjectFromXMI(type, stereoID);
......
......@@ -18,7 +18,9 @@
#include "umldoc.h"
#include "classifier.h"
#include "association.h"
#include "datatype.h"
#include "entity.h"
#include "folder.h"
#include "object_factory.h"
#include "model_utils.h"
......@@ -215,11 +217,29 @@ void UMLPackage::removeObject(UMLObject *pObject)
else
uError() << "invalid cast found";
}
if (m_objects.indexOf(pObject) == -1)
if (m_objects.indexOf(pObject) == -1) {
uDebug() << name() << " removeObject: object with id="
<< Uml::ID::toString(pObject->id()) << "not found.";
else
return;
}
// Do not delete a datatype from its root folder but just mark it as inactive.
// We need this special handling because of the possibility of switching
// the active programming language. Without it,
// - switching the active language could create dangling references on all
// objects referencing the previous language's datatypes;
// - the display of the datatypes in the list view or in dialogs get
// populated with the types from previously active languages.
if (this == UMLApp::app()->document()->datatypeFolder()) {
UMLDatatype *dt = pObject->asUMLDatatype();
if (dt) {
dt->setActive(false);
} else {
uWarning() << "UMLPackage::removeObject(" << pObject->name()
<< ") : Expected Datatype, found " << pObject->baseTypeStr();
}
} else {
m_objects.removeAll(pObject);
}
}
/**
......@@ -243,9 +263,24 @@ void UMLPackage::removeAllObjects()
/**
* Returns the list of objects contained in this package.
*/
UMLObjectList UMLPackage::containedObjects()
UMLObjectList UMLPackage::containedObjects(bool includeInactive /* = false */)
{
return m_objects;
UMLObjectList result;
foreach (UMLObject *obj, m_objects) {
uIgnoreZeroPointer(obj);
if (includeInactive) {
result.append(obj);
}
else if (obj->isUMLDatatype()) {
UMLDatatype *dt = obj->asUMLDatatype();
if (dt->isActive())
result.append(obj);
}
else {
result.append(obj);
}
}
return result;
}
/**
......
......@@ -45,7 +45,7 @@ public:
virtual void removeAllObjects();
UMLObjectList containedObjects();
UMLObjectList containedObjects(bool includeInactive = false);
void addAssocToConcepts(UMLAssociation* assoc);
void removeAssocFromConcepts(UMLAssociation *assoc);
......
......@@ -28,6 +28,7 @@
#include "template.h"
#include "enumliteral.h"
#include "stereotype.h"
#include "datatype.h"
#include "classifierlistitem.h"
#include "object_factory.h"
#include "import_argo.h"
......@@ -3033,11 +3034,13 @@ UMLEntityList UMLDoc::entities(bool includeNested /* =true */)
/**
* Returns a list of the datatypes in this UMLDoc.
*
* @param includeInactive Include inactive datatypes which may have accrued by
* changing the active programming language.
* @return List of datatypes.
*/
UMLClassifierList UMLDoc::datatypes()
UMLClassifierList UMLDoc::datatypes(bool includeInactive /* = false */)
{
UMLObjectList objects = m_datatypeRoot->containedObjects();
UMLObjectList objects = m_datatypeRoot->containedObjects(includeInactive);
UMLClassifierList datatypeList;
foreach (UMLObject *obj, objects) {
uIgnoreZeroPointer(obj);
......@@ -3480,18 +3483,41 @@ void UMLDoc::addDefaultDatatypes()
/**
* Add a datatype if it doesn't already exist.
* Used by code generators and attribute dialog.
* Used by addDefaultDatatypes().
*/
void UMLDoc::createDatatype(const QString &name)
{
UMLObjectList datatypes = m_datatypeRoot->containedObjects();
UMLObjectList datatypes = m_datatypeRoot->containedObjects(true);
UMLObject* umlobject = Model_Utils::findUMLObject(datatypes, name,
UMLObject::ot_Datatype, m_datatypeRoot);
if (!umlobject) {
if (umlobject) {
UMLDatatype *dt = umlobject->asUMLDatatype();
dt->setActive(true);
signalUMLObjectCreated(umlobject);
qApp->processEvents();
} else {
Object_Factory::createUMLObject(UMLObject::ot_Datatype, name, m_datatypeRoot);
}
}
/**
* Remove a datatype by name.
* Used when changing the active programming language.
*/
void UMLDoc::removeDatatype(const QString &name)
{
UMLObjectList datatypes = m_datatypeRoot->containedObjects();
// We don't use Model_Utils::findUMLObject because that function considers
// case sensitivity of the active language, which we don't want here.
foreach (UMLObject *obj, datatypes) {
uIgnoreZeroPointer(obj);
if (obj->name() == name) {
removeUMLObject(obj);
break;
}
}
}
/**
* Make a popup menu for the tabs
* signalled from tabWidget's contextMenu().
......
......@@ -194,7 +194,7 @@ public:
UMLClassifierList classesAndInterfaces(bool includeNested = true);
UMLEntityList entities(bool includeNested = true);
UMLFolder * datatypeFolder() const;
UMLClassifierList datatypes();
UMLClassifierList datatypes(bool includeInactive = false);
UMLAssociationList associations();
UMLPackageList packages(bool includeNested = true, Uml::ModelType::Enum model = Uml::ModelType::Logical);
......@@ -238,6 +238,7 @@ public:
void addDefaultDatatypes();
void createDatatype(const QString &name);
void removeDatatype(const QString &name);
UMLStereotype *createStereotype(const QString &name);
UMLStereotype *findStereotype(const QString &name);
......
......@@ -26,6 +26,7 @@
#include "enumliteral.h"
#include "entity.h"
#include "category.h"
#include "datatype.h"
#include "docwindow.h"
#include "layoutgenerator.h"
#include "umllistviewpopupmenu.h"
......@@ -990,6 +991,13 @@ void UMLListView::slotObjectCreated(UMLObject* object)
if (parentItem == 0)
return;
UMLObject::ObjectType type = object->baseType();
if (type == UMLObject::ot_Datatype) {
UMLDatatype *dt = object->asUMLDatatype();
if (!dt->isActive()) {
DEBUG(DBG_SRC) << object->name() << " is not active. Refusing to create UMLListViewItem";
return;
}
}
connectNewObjectsSlots(object);
const UMLListViewItem::ListViewType lvt = Model_Utils::convert_OT_LVT(object);
......@@ -1623,7 +1631,7 @@ void UMLListView::addAtContainer(UMLListViewItem *item, UMLListViewItem *parent)
}
/**
* Moves an object given is unique ID and listview type to an
* Moves an object given its unique ID and listview type to an
* other listview parent item.
* Also takes care of the corresponding move in the model.
*/
......
......@@ -32,6 +32,6 @@ inline QByteArray umbrelloVersion()
}
// Update this version and dtd's in doc/xml when changing the XMI file format
#define XMI_FILE_VERSION "1.6.18"
#define XMI_FILE_VERSION "1.6.19"
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment