umbrello/umbrello
umlcanvasobject.cpp
Go to the documentation of this file.00001 /*************************************************************************** 00002 * * 00003 * This program is free software; you can redistribute it and/or modify * 00004 * it under the terms of the GNU General Public License as published by * 00005 * the Free Software Foundation; either version 2 of the License, or * 00006 * (at your option) any later version. * 00007 * * 00008 * copyright (C) 2003-2007 * 00009 * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * 00010 ***************************************************************************/ 00011 00012 // own header 00013 #include "umlcanvasobject.h" 00014 00015 // qt/kde includes 00016 #include <kdebug.h> 00017 #include <klocale.h> 00018 00019 // local includes 00020 #include "uml.h" 00021 #include "umldoc.h" 00022 #include "classifier.h" 00023 #include "association.h" 00024 #include "attribute.h" 00025 #include "operation.h" 00026 #include "template.h" 00027 #include "stereotype.h" 00028 #include "clipboard/idchangelog.h" 00029 00030 UMLCanvasObject::UMLCanvasObject(const QString & name, Uml::IDType id) 00031 : UMLObject(name, id) 00032 { 00033 init(); 00034 } 00035 00036 UMLCanvasObject::~UMLCanvasObject() { 00037 //removeAllAssociations(); 00038 /* No! This is way too late to do that. 00039 It should have been called explicitly before destructing the 00040 UMLCanvasObject. 00041 Here is an example crash that happens if we rely on 00042 removeAllAssociations() at this point: 00043 #4 0x415aac7f in __dynamic_cast () from /usr/lib/libstdc++.so.5 00044 #5 0x081acdbd in UMLCanvasObject::removeAllAssociations() (this=0x89e5b08) 00045 at umlcanvasobject.cpp:83 00046 #6 0x081ac9fa in ~UMLCanvasObject (this=0x89e5b08) at umlcanvasobject.cpp:29 00047 #7 0x08193ffc in ~UMLPackage (this=0x89e5b08) at package.cpp:35 00048 #8 0x0813cbf6 in ~UMLClassifier (this=0x89e5b08) at classifier.cpp:40 00049 #9 0x081af3a6 in UMLDoc::closeDocument() (this=0x8468b10) at umldoc.cpp:284 00050 */ 00051 if (associations()) 00052 uDebug() << "UMLCanvasObject destructor: FIXME: there are still associations()"; 00053 } 00054 00055 UMLAssociationList UMLCanvasObject::getSpecificAssocs(Uml::Association_Type assocType) { 00056 UMLAssociationList list; 00057 UMLObject *o = NULL; 00058 for (UMLObjectListIt oit(m_List); oit.hasNext(); ) { 00059 o = oit.next(); 00060 if (o->getBaseType() != Uml::ot_Association) 00061 continue; 00062 UMLAssociation *a = static_cast<UMLAssociation*>(o); 00063 if (a->getAssocType() == assocType) 00064 list.append(a); 00065 } 00066 return list; 00067 } 00068 00069 bool UMLCanvasObject::addAssociationEnd(UMLAssociation* assoc) { 00070 // add association only if not already present in list 00071 if(!hasAssociation(assoc)) 00072 { 00073 m_List.append( assoc ); 00074 00075 // Don't emit signals during load from XMI 00076 UMLObject::emitModified(); 00077 emit sigAssociationEndAdded(assoc); 00078 return true; 00079 } 00080 return false; 00081 } 00082 00083 bool UMLCanvasObject::hasAssociation(UMLAssociation* assoc) { 00084 if(m_List.count(assoc) > 0) 00085 return true; 00086 return false; 00087 } 00088 00089 int UMLCanvasObject::removeAssociationEnd(UMLAssociation * assoc) { 00090 if(!hasAssociation(assoc) || !m_List.removeAll(assoc)) { 00091 uWarning() << "can't find given assoc in list" << endl; 00092 return -1; 00093 } 00094 UMLObject::emitModified(); 00095 emit sigAssociationEndRemoved(assoc); 00096 return m_List.count(); 00097 } 00098 00099 void UMLCanvasObject::removeAllAssociationEnds() { 00100 for (int i = 0; i < m_List.count(); ) { 00101 UMLObject *o = m_List.at(i); 00102 if (o->getBaseType() != Uml::ot_Association) { 00103 ++i; 00104 continue; 00105 } 00106 UMLAssociation *assoc = static_cast<UMLAssociation*>(o); 00107 //umldoc->slotRemoveUMLObject(assoc); 00108 UMLObject* objA = assoc->getObject(Uml::A); 00109 UMLObject* objB = assoc->getObject(Uml::B); 00110 UMLCanvasObject *roleAObj = dynamic_cast<UMLCanvasObject*>(objA); 00111 if (roleAObj) { 00112 roleAObj->removeAssociationEnd(assoc); 00113 } else if (objA) 00114 uDebug() << m_Name << ": objA " << objA->getName() << " is not a UMLCanvasObject" 00115 << endl; 00116 else 00117 uDebug() << m_Name << "): objA is NULL" << endl; 00118 UMLCanvasObject *roleBObj = dynamic_cast<UMLCanvasObject*>(objB); 00119 if (roleBObj) { 00120 roleBObj->removeAssociationEnd(assoc); 00121 } else if (objB) 00122 uDebug() << m_Name << "): objB " << objB->getName() << " is not a UMLCanvasObject" 00123 << endl; 00124 else 00125 uDebug() << m_Name << "): objB is NULL" << endl; 00126 m_List.removeAt(i); 00127 } 00128 } 00129 00130 void UMLCanvasObject::removeAllChildObjects() { 00131 removeAllAssociationEnds(); 00132 while ( !m_List.isEmpty() ) { 00133 delete m_List.takeFirst(); 00134 } 00135 } 00136 00137 QString UMLCanvasObject::uniqChildName( const Uml::Object_Type type, 00138 const QString &prefix /* = QString() */ ) { 00139 QString currentName = prefix; 00140 if (currentName.isEmpty()) { 00141 switch (type) { 00142 case Uml::ot_Association: 00143 currentName = i18n("new_association"); 00144 break; 00145 case Uml::ot_Attribute: 00146 currentName = i18n("new_attribute"); 00147 break; 00148 case Uml::ot_Template: 00149 currentName = i18n("new_template"); 00150 break; 00151 case Uml::ot_Operation: 00152 currentName = i18n("new_operation"); 00153 break; 00154 case Uml::ot_EnumLiteral: 00155 currentName = i18n("new_literal"); 00156 break; 00157 case Uml::ot_EntityAttribute: 00158 currentName = i18n("new_field"); 00159 break; 00160 case Uml::ot_UniqueConstraint: 00161 currentName = i18n( "new_unique_constraint" ); 00162 break; 00163 case Uml::ot_ForeignKeyConstraint: 00164 currentName = i18n( "new_fkey_constraint" ); 00165 break; 00166 case Uml::ot_CheckConstraint: 00167 currentName = i18n( "new_check_constraint" ); 00168 break; 00169 default: 00170 uWarning() << "uniqChildName() called for unknown child type " << type; 00171 return "ERROR_in_UMLCanvasObject_uniqChildName"; 00172 } 00173 } 00174 00175 QString name = currentName; 00176 for (int number = 1; findChildObject(name); ++number) { 00177 name = currentName + '_' + QString::number(number); 00178 } 00179 return name; 00180 } 00181 00182 UMLObject * UMLCanvasObject::findChildObject(const QString &n, Uml::Object_Type t) { 00183 const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive(); 00184 UMLObject *obj = NULL; 00185 for (UMLObjectListIt oit(m_List); oit.hasNext(); ) { 00186 obj = oit.next(); 00187 if (t != Uml::ot_UMLObject && obj->getBaseType() != t) 00188 continue; 00189 if (caseSensitive) { 00190 if (obj->getName() == n) 00191 return obj; 00192 } else if (obj->getName().toLower() == n.toLower()) { 00193 return obj; 00194 } 00195 } 00196 return NULL; 00197 } 00198 00199 UMLObject* UMLCanvasObject::findChildObjectById(Uml::IDType id, bool /* considerAncestors */) { 00200 UMLObject *o = NULL; 00201 for (UMLObjectListIt oit(m_List); oit.hasNext(); ) { 00202 o = oit.next(); 00203 if (o->getID() == id) 00204 return o; 00205 } 00206 return 0; 00207 } 00208 00209 void UMLCanvasObject::init() { 00210 00211 } 00212 00213 bool UMLCanvasObject::operator==(const UMLCanvasObject& rhs) { 00214 if (this == &rhs) { 00215 return true; 00216 } 00217 if ( !UMLObject::operator==(rhs) ) { 00218 return false; 00219 } 00220 if ( m_List.count() != rhs.m_List.count() ) { 00221 return false; 00222 } 00223 if ( &m_List != &(rhs.m_List) ) { 00224 return false; 00225 } 00226 return true; 00227 } 00228 00229 void UMLCanvasObject::copyInto(UMLObject *lhs) const 00230 { 00231 UMLObject::copyInto(lhs); 00232 00233 // TODO Associations are not copied at the moment. This because 00234 // the duplicate function (on umlwidgets) do not copy the associations. 00235 // 00236 //target->m_List = m_List; 00237 } 00238 00239 int UMLCanvasObject::associations() { 00240 int count = 0; 00241 UMLObject *obj = NULL; 00242 for (UMLObjectListIt oit(m_List); oit.hasNext(); ) { 00243 obj = oit.next(); 00244 if (obj->getBaseType() == Uml::ot_Association) 00245 count++; 00246 } 00247 return count; 00248 } 00249 00250 UMLAssociationList UMLCanvasObject::getAssociations() { 00251 UMLAssociationList assocs; 00252 UMLObject *o = NULL; 00253 for (UMLObjectListIt oit(m_List); oit.hasNext() ; ) { 00254 o = oit.next(); 00255 if (o->getBaseType() != Uml::ot_Association) 00256 continue; 00257 UMLAssociation *assoc = static_cast<UMLAssociation*>(o); 00258 assocs.append(assoc); 00259 } 00260 return assocs; 00261 } 00262 00263 UMLClassifierList UMLCanvasObject::getSuperClasses() { 00264 UMLClassifierList list; 00265 UMLAssociationList assocs = getAssociations(); 00266 foreach (UMLAssociation* a , assocs ) { 00267 if ((a->getAssocType() != Uml::at_Generalization && 00268 a->getAssocType() != Uml::at_Realization) || 00269 a->getObjectId(Uml::A) != getID() ) 00270 continue; 00271 UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::B)); 00272 if (c) 00273 list.append(c); 00274 else 00275 uDebug() << m_Name << ": generalization's other end is not a " 00276 << "UMLClassifier (id= " << ID2STR(a->getObjectId(Uml::B)) << ")" 00277 << endl; 00278 } 00279 return list; 00280 } 00281 00282 UMLClassifierList UMLCanvasObject::getSubClasses() { 00283 UMLClassifierList list; 00284 UMLAssociationList assocs = getAssociations(); 00285 foreach (UMLAssociation* a , assocs ) { 00286 if ((a->getAssocType() != Uml::at_Generalization && 00287 a->getAssocType() != Uml::at_Realization) || 00288 a->getObjectId(Uml::B) != getID() ) 00289 continue; 00290 UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A)); 00291 if (c) 00292 list.append(c); 00293 else 00294 uDebug() << "specialization's other end is not a UMLClassifier" 00295 << " (id=" << ID2STR(a->getObjectId(Uml::A)) << ")" << endl; 00296 } 00297 return list; 00298 } 00299 00300 UMLAssociationList UMLCanvasObject::getRealizations() { 00301 return getSpecificAssocs(Uml::at_Realization); 00302 } 00303 00304 UMLAssociationList UMLCanvasObject::getAggregations() { 00305 return getSpecificAssocs(Uml::at_Aggregation); 00306 } 00307 00308 UMLAssociationList UMLCanvasObject::getCompositions() { 00309 return getSpecificAssocs(Uml::at_Composition); 00310 } 00311 00312 UMLAssociationList UMLCanvasObject::getRelationships() { 00313 return getSpecificAssocs(Uml::at_Relationship); 00314 } 00315 00316 bool UMLCanvasObject::resolveRef() { 00317 bool overallSuccess = UMLObject::resolveRef(); 00318 for (UMLObjectListIt ait(m_List); ait.hasNext(); ) { 00319 UMLObject *obj = ait.next(); 00320 if (! obj->resolveRef()) { 00321 m_List.removeAll(obj); 00322 overallSuccess = false; 00323 } 00324 } 00325 return overallSuccess; 00326 } 00327 00328 #include "umlcanvasobject.moc" 00329
KDE 4.0 API Reference