diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | bd9e6617827818fd043452c08c606f07b78014a0 (patch) | |
tree | 425bb4c3168f9c02f10150f235d2cb998dcc6108 /umbrello/umbrello/operation.cpp | |
download | tdesdk-bd9e6617827818fd043452c08c606f07b78014a0.tar.gz tdesdk-bd9e6617827818fd043452c08c606f07b78014a0.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdesdk@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'umbrello/umbrello/operation.cpp')
-rw-r--r-- | umbrello/umbrello/operation.cpp | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/umbrello/umbrello/operation.cpp b/umbrello/umbrello/operation.cpp new file mode 100644 index 00000000..1052c469 --- /dev/null +++ b/umbrello/umbrello/operation.cpp @@ -0,0 +1,431 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * copyright (C) 2002-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header +#include "operation.h" + +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> +#include <klocale.h> + +// app includes +#include "attribute.h" +#include "classifier.h" +#include "uml.h" +#include "umldoc.h" +#include "uniqueid.h" +#include "dialogs/umloperationdialog.h" + +UMLOperation::UMLOperation(const UMLClassifier *parent, const QString& name, + Uml::IDType id, Uml::Visibility s, UMLObject *rt) + : UMLClassifierListItem(parent, name, id) +{ + if (rt) + m_returnId = UniqueID::gen(); + else + m_returnId = Uml::id_None; + m_pSecondary = rt; + m_Vis = s; + m_BaseType = Uml::ot_Operation; + m_bConst = false; +} + +UMLOperation::UMLOperation(const UMLClassifier * parent) + : UMLClassifierListItem (parent) +{ + m_BaseType = Uml::ot_Operation; + m_bConst = false; +} + +UMLOperation::~UMLOperation() { +} + +void UMLOperation::setType(UMLObject *type) { + UMLClassifierListItem::setType(type); + if (m_returnId == Uml::id_None) + m_returnId = UniqueID::gen(); +} + +void UMLOperation::moveParmLeft(UMLAttribute * a) { + if (a == NULL) { + kDebug() << "UMLOperation::moveParmLeft called on NULL attribute" + << endl; + return; + } + kDebug() << "UMLOperation::moveParmLeft(" << a->getName() << ") called" + << endl; + disconnect(a,SIGNAL(modified()),this,SIGNAL(modified())); + int idx; + if ( (idx=m_List.find( a )) == -1 ) { + kDebug() << "Error move parm left " << a->getName() << endl; + return; + } + if ( idx == 0 ) + return; + m_List.remove( a ); + m_List.insert( idx-1, a ); +} + +void UMLOperation::moveParmRight(UMLAttribute * a) { + if (a == NULL) { + kDebug() << "UMLOperation::moveParmRight called on NULL attribute" + << endl; + return; + } + kDebug() << "UMLOperation::moveParmRight(" << a->getName() << ") called" + << endl; + disconnect(a,SIGNAL(modified()),this,SIGNAL(modified())); + int idx; + if ( (idx=m_List.find( a )) == -1 ) { + kDebug() << "Error move parm right " << a->getName() << endl; + return; + } + int count = m_List.count(); + if ( idx == count-1 ) + return; + m_List.remove( a ); + m_List.insert( idx+1, a ); +} + +void UMLOperation::removeParm(UMLAttribute * a, bool emitModifiedSignal /* =true */) { + if (a == NULL) { + kDebug() << "UMLOperation::removeParm called on NULL attribute" + << endl; + return; + } + kDebug() << "UMLOperation::removeParm(" << a->getName() << ") called" + << endl; + disconnect(a,SIGNAL(modified()),this,SIGNAL(modified())); + if(!m_List.remove(a)) + kDebug() << "Error removing parm " << a->getName() << endl; + + if (emitModifiedSignal) + emit modified(); +} + +UMLAttribute* UMLOperation::findParm(const QString &name) { + UMLAttribute * obj=0; + for (obj = m_List.first(); obj; obj = m_List.next()) { + if (obj->getName() == name) + return obj; + } + return 0; +} + +QString UMLOperation::toString(Uml::Signature_Type sig) { + QString s = ""; + + if(sig == Uml::st_ShowSig || sig == Uml::st_NoSig) + s = m_Vis.toString(true) + ' '; + + s += getName(); + Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage(); + bool parameterlessOpNeedsParentheses = (pl != Uml::pl_Pascal && pl != Uml::pl_Ada); + + if (sig == Uml::st_NoSig || sig == Uml::st_NoSigNoVis) { + if (parameterlessOpNeedsParentheses) + s.append("()"); + return s; + } + int last = m_List.count(); + if (last) { + s.append("("); + int i = 0; + for (UMLAttribute *param = m_List.first(); param; param = m_List.next()) { + i++; + s.append(param->toString(Uml::st_SigNoVis)); + if (i < last) + s.append(", "); + } + s.append(")"); + } else if (parameterlessOpNeedsParentheses) { + s.append("()"); + } + UMLClassifier *ownParent = static_cast<UMLClassifier*>(parent()); + QString returnType; + UMLClassifier *retType = UMLClassifierListItem::getType(); + if (retType) { + UMLPackage *retVisibility = retType->getUMLPackage(); + if (retVisibility != ownParent && retVisibility != ownParent->getUMLPackage()) + returnType = retType->getFullyQualifiedName(); + else + returnType = retType->getName(); + } + if (returnType.length() > 0 && returnType != "void") { + s.append(" : "); + + if (returnType.startsWith("virtual ")) { + s += returnType.mid(8); + } else { + s += returnType; + } + } + return s; +} + +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())); +} + +QString UMLOperation::getUniqueParameterName() { + QString currentName = i18n("new_parameter"); + QString name = currentName; + for (int number = 1; findParm(name); number++) { + name = currentName + '_' + QString::number(number); + } + return name; +} + +bool UMLOperation::operator==( UMLOperation & rhs ) { + 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; +} + +void UMLOperation::copyInto(UMLOperation *rhs) const +{ + UMLClassifierListItem::copyInto(rhs); + + m_List.copyInto(&(rhs->m_List)); +} + +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; +} + +bool UMLOperation::resolveRef() { + bool overallSuccess = UMLObject::resolveRef(); + // See remark on iteration style in UMLClassifier::resolveRef() + for (UMLAttributeListIt ait(m_List); ait.current(); ++ait) { + UMLAttribute *pAtt = ait.current(); + if (! pAtt->resolveRef()) + overallSuccess = false; + } + return overallSuccess; +} + +bool UMLOperation::isConstructorOperation() { + // if an operation has the stereotype constructor + // return true + QString strConstructor ("constructor"); + if (getStereotype() == strConstructor) + return true; + + UMLClassifier * c = static_cast<UMLClassifier*>(this->parent()); + QString cName = c->getName(); + QString opName = getName(); + // It's a constructor operation if the operation name + // matches that of the parent classifier. + return (cName == opName); +} + +bool UMLOperation::isDestructorOperation() { + if (getStereotype() == "destructor") + return true; + UMLClassifier * c = static_cast<UMLClassifier*>(this->parent()); + + QString cName = c->getName(); + QString opName = getName(); + // 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("~")) + return false; + opName.remove( QRegExp("^~\\s*") ); + return (cName == opName); +} + +bool UMLOperation::isLifeOperation() { + return (isConstructorOperation() || isDestructorOperation()); +} + +void UMLOperation::setConst(bool b) { + m_bConst = b; +} + +bool UMLOperation::getConst() const { + return m_bConst; +} + +bool UMLOperation::showPropertiesDialog(QWidget* parent) { + UMLOperationDialog dialog(parent, this); + return dialog.exec(); +} + +void UMLOperation::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) { + QDomElement operationElement = UMLObject::save("UML:Operation", qDoc); + operationElement.setAttribute( "isQuery", m_bConst ? "true" : "false" ); + QDomElement featureElement = qDoc.createElement( "UML:BehavioralFeature.parameter" ); + if (m_pSecondary) { + QDomElement retElement = qDoc.createElement("UML:Parameter"); + if (m_returnId == Uml::id_None) { + kDebug() << "UMLOperation::saveToXMI(" << m_Name + << "): m_returnId is not set, setting it now." << endl; + m_returnId = UniqueID::gen(); + } + retElement.setAttribute( "xmi.id", ID2STR(m_returnId) ); + retElement.setAttribute( "type", ID2STR(m_pSecondary->getID()) ); + retElement.setAttribute( "kind", "return" ); + featureElement.appendChild( retElement ); + } else { + kDebug() << "UMLOperation::saveToXMI: m_SecondaryId is " + << m_SecondaryId << endl; + } + //save each attribute here, type different + UMLAttribute* pAtt = 0; + for( pAtt = m_List.first(); pAtt != 0; pAtt = m_List.next() ) { + QDomElement attElement = pAtt->UMLObject::save("UML:Parameter", qDoc); + UMLClassifier *attrType = pAtt->getType(); + if (attrType) { + attElement.setAttribute( "type", ID2STR(attrType->getID()) ); + } else { + attElement.setAttribute( "type", pAtt -> getTypeName() ); + } + attElement.setAttribute( "value", pAtt -> getInitialValue() ); + + Uml::Parameter_Direction kind = pAtt->getParmKind(); + if (kind == Uml::pd_Out) + attElement.setAttribute("kind", "out"); + else if (kind == Uml::pd_InOut) + attElement.setAttribute("kind", "inout"); + // The default for the parameter kind is "in". + + featureElement.appendChild( attElement ); + } + if (featureElement.hasChildNodes()) + operationElement.appendChild( featureElement ); + qElement.appendChild( operationElement ); +} + +bool UMLOperation::load( QDomElement & element ) { + m_SecondaryId = element.attribute( "type", "" ); + QString isQuery = element.attribute( "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 == "true"); + } + QDomNode node = element.firstChild(); + if (node.isComment()) + node = node.nextSibling(); + QDomElement attElement = node.toElement(); + while( !attElement.isNull() ) { + QString tag = attElement.tagName(); + if (Uml::tagEq(tag, "BehavioralFeature.parameter")) { + if (! load(attElement)) + return false; + } else if (Uml::tagEq(tag, "Parameter")) { + QString kind = attElement.attribute("kind", ""); + 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 (!Uml::tagEq(tag, "kind")) + continue; + kind = tempElement.attribute( "xmi.value", "" ); + break; + } + if (kind.isEmpty()) { + // kDebug() << "UMLOperation::load(" << m_Name << "): " + // << "cannot find kind, using default \"in\"." << endl; + kind = "in"; + } + } + if (kind == "return") { + QString returnId = attElement.attribute("xmi.id", ""); + if (!returnId.isEmpty()) + m_returnId = STR2ID(returnId); + m_SecondaryId = attElement.attribute( "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 (!Uml::tagEq(tag, "type")) { + node = node.nextSibling(); + continue; + } + m_SecondaryId = tempElement.attribute( "xmi.id", "" ); + if (m_SecondaryId.isEmpty()) + m_SecondaryId = tempElement.attribute( "xmi.idref", "" ); + if (m_SecondaryId.isEmpty()) { + QDomNode inner = node.firstChild(); + QDomElement tmpElem = inner.toElement(); + m_SecondaryId = tmpElem.attribute( "xmi.id", "" ); + if (m_SecondaryId.isEmpty()) + m_SecondaryId = tmpElem.attribute( "xmi.idref", "" ); + } + break; + } + if (m_SecondaryId.isEmpty()) { + kError() << "UMLOperation::load(" << m_Name << "): " + << "cannot find return type." << endl; + } + } + // Use deferred xmi.id resolution. + m_pSecondary = NULL; + } else { + UMLAttribute * pAtt = new UMLAttribute( this ); + if( !pAtt->loadFromXMI(attElement) ) { + delete pAtt; + return false; + } + if (kind == "out") + pAtt->setParmKind(Uml::pd_Out); + else if (kind == "inout") + pAtt->setParmKind(Uml::pd_InOut); + else + pAtt->setParmKind(Uml::pd_In); + m_List.append( pAtt ); + } + } + node = node.nextSibling(); + if (node.isComment()) + node = node.nextSibling(); + attElement = node.toElement(); + }//end while + return true; +} + + +#include "operation.moc" |