You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
724 lines
23 KiB
724 lines
23 KiB
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General 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 UML Modeller Authors <uml-devel@uml.sf.net> *
|
|
***************************************************************************/
|
|
|
|
/* This code generated by:
|
|
* Author : thomas
|
|
* Date : Thu Jun 19 2003
|
|
*/
|
|
|
|
// own header
|
|
#include "codegenerator.h"
|
|
|
|
// system includes
|
|
#include <cstdlib> //to get the user name
|
|
|
|
// qt includes
|
|
#include <tqdatetime.h>
|
|
#include <tqregexp.h>
|
|
#include <tqdir.h>
|
|
#include <tqtextstream.h>
|
|
|
|
// kde includes
|
|
#include <kdebug.h>
|
|
#include <klocale.h>
|
|
#include <kmessagebox.h>
|
|
#include <kdialogbase.h>
|
|
#include <kapplication.h>
|
|
|
|
// app includes
|
|
#include "dialogs/overwritedialogue.h"
|
|
#include "dialogs/codeviewerdialog.h"
|
|
#include "codegenerators/simplecodegenerator.h"
|
|
#include "attribute.h"
|
|
#include "association.h"
|
|
#include "classifier.h"
|
|
#include "classifiercodedocument.h"
|
|
#include "codedocument.h"
|
|
#include "codegenerationpolicy.h"
|
|
#include "operation.h"
|
|
#include "uml.h"
|
|
#include "umldoc.h"
|
|
#include "umlobject.h"
|
|
#include "umlattributelist.h"
|
|
#include "umloperationlist.h"
|
|
#include "model_utils.h"
|
|
|
|
// Constructors/Destructors
|
|
//
|
|
|
|
CodeGenerator::CodeGenerator ()
|
|
: TQObject (UMLApp::app()->getDocument())
|
|
{
|
|
initFields();
|
|
}
|
|
|
|
// FIX
|
|
// hmm. this should be pure virtual so that implemented in sub-class
|
|
CodeGenerator::CodeGenerator (TQDomElement & element )
|
|
: TQObject (UMLApp::app()->getDocument()) {
|
|
initFields();
|
|
loadFromXMI(element); // hmm. cant call this here.. its 'pure' virtual
|
|
}
|
|
|
|
CodeGenerator::~CodeGenerator ( ) {
|
|
// destroy all owned codedocuments
|
|
CodeDocument *doc;
|
|
for (CodeDocumentListIt it(m_codedocumentVector);
|
|
(doc = it.current()) != NULL; ++it)
|
|
delete doc;
|
|
m_codedocumentVector.clear();
|
|
}
|
|
|
|
//
|
|
// Methods
|
|
//
|
|
|
|
|
|
// Accessor methods
|
|
//
|
|
|
|
TQString CodeGenerator::getUniqueID(CodeDocument * codeDoc)
|
|
{
|
|
|
|
TQString id = codeDoc->getID();
|
|
|
|
// does this document already exist? then just return its present id
|
|
if (!id.isEmpty() && findCodeDocumentByID(id))
|
|
return id;
|
|
|
|
// approach now differs by whether or not its a classifier code document
|
|
ClassifierCodeDocument * classDoc = dynamic_cast<ClassifierCodeDocument*>(codeDoc);
|
|
if(classDoc) {
|
|
UMLClassifier *c = classDoc->getParentClassifier();
|
|
id = ID2STR(c->getID()); // this is supposed to be unique already..
|
|
} else {
|
|
|
|
TQString prefix = "doc";
|
|
TQString id = prefix + "_0";
|
|
int number = lastIDIndex;
|
|
for ( ; findCodeDocumentByID(id); number++) {
|
|
id = prefix + '_' + TQString::number(number);
|
|
}
|
|
lastIDIndex = number;
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
CodeDocument * CodeGenerator::findCodeDocumentByID( const TQString &tag ) {
|
|
//if we already know to which file this class was written/should be written, just return it.
|
|
CodeDocument * doc = (CodeDocument*)NULL;
|
|
if((doc = m_codeDocumentDictionary.tqfind(tag)))
|
|
return doc;
|
|
|
|
return doc;
|
|
}
|
|
|
|
bool CodeGenerator::addCodeDocument ( CodeDocument * doc )
|
|
{
|
|
TQString tag = doc->getID();
|
|
|
|
// assign a tag if one doesn't already exist
|
|
if(tag.isEmpty())
|
|
{
|
|
tag = getUniqueID(doc);
|
|
doc->setID(tag);
|
|
}
|
|
|
|
if(m_codeDocumentDictionary.tqfind(tag))
|
|
return false; // return false, we already have some object with this tag in the list
|
|
else
|
|
m_codeDocumentDictionary.insert(tag, doc);
|
|
|
|
m_codedocumentVector.append(doc);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Remove a CodeDocument object from m_codedocumentVector List
|
|
*/
|
|
bool CodeGenerator::removeCodeDocument ( CodeDocument * remove_object ) {
|
|
TQString tag = remove_object->getID();
|
|
if(!(tag.isEmpty()))
|
|
m_codeDocumentDictionary.remove(tag);
|
|
else
|
|
return false;
|
|
|
|
m_codedocumentVector.remove(remove_object);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get the list of CodeDocument objects held by m_codedocumentVector
|
|
* @return TQPtrList<CodeDocument *> list of CodeDocument objects held by
|
|
* m_codedocumentVector
|
|
*/
|
|
CodeDocumentList * CodeGenerator::getCodeDocumentList ( ) {
|
|
return &m_codedocumentVector;
|
|
}
|
|
|
|
// the vanilla version
|
|
CodeViewerDialog * CodeGenerator::getCodeViewerDialog ( TQWidget* tqparent, CodeDocument *doc,
|
|
Settings::CodeViewerState state)
|
|
{
|
|
return new CodeViewerDialog(tqparent, doc, state);
|
|
}
|
|
|
|
// Other methods
|
|
//
|
|
|
|
void CodeGenerator::loadFromXMI (TQDomElement & qElement ) {
|
|
|
|
// don't do anything for simple (compatability) code generators
|
|
if(dynamic_cast<SimpleCodeGenerator*>(this))
|
|
return;
|
|
|
|
//now look for our particular child element
|
|
TQDomNode node = qElement.firstChild();
|
|
TQDomElement element = node.toElement();
|
|
TQString langType = Model_Utils::progLangToString( getLanguage() );
|
|
|
|
if (qElement.tagName() != "codegenerator"
|
|
|| qElement.attribute("language", "UNKNOWN") != langType)
|
|
return;
|
|
// got our code generator element, now load
|
|
// codedocuments
|
|
TQDomNode codeDocNode = qElement.firstChild();
|
|
TQDomElement codeDocElement = codeDocNode.toElement();
|
|
while( !codeDocElement.isNull() ) {
|
|
|
|
TQString docTag = codeDocElement.tagName();
|
|
if( docTag == "codedocument" ||
|
|
docTag == "classifiercodedocument"
|
|
) {
|
|
TQString id = codeDocElement.attribute( "id", "-1" );
|
|
CodeDocument * codeDoc = findCodeDocumentByID(id);
|
|
if(codeDoc)
|
|
codeDoc->loadFromXMI(codeDocElement);
|
|
else {
|
|
kWarning()<<" loadFromXMI: missing code document w/ id:"<<id<<", plowing ahead with pre-generated one."<<endl;
|
|
}
|
|
} else
|
|
kWarning()<<" loadFromXMI : got strange codegenerator child node:"<<docTag<<", ignoring."<<endl;
|
|
|
|
codeDocNode = codeDocElement.nextSibling();
|
|
codeDocElement = codeDocNode.toElement();
|
|
}
|
|
}
|
|
|
|
void CodeGenerator::saveToXMI ( TQDomDocument & doc, TQDomElement & root ) {
|
|
TQString langType = Model_Utils::progLangToString( getLanguage() );
|
|
TQDomElement docElement = doc.createElement( "codegenerator" );
|
|
docElement.setAttribute("language",langType);
|
|
|
|
CodeDocumentList * docList = getCodeDocumentList();
|
|
for (CodeDocument * codeDoc = docList->first(); codeDoc; codeDoc= docList->next())
|
|
codeDoc->saveToXMI(doc, docElement);
|
|
|
|
root.appendChild( docElement );
|
|
}
|
|
|
|
/**
|
|
* Initialize this code generator from its tqparent UMLDoc. When this is called, it will
|
|
* (re-)generate the list of code documents for this project (generator) by checking
|
|
* for new objects/attributes which have been added or changed in the documnet. One or more
|
|
* CodeDocuments will be created/overwritten/amended as is appropriate for the given language.
|
|
*
|
|
* In this 'generic' version a ClassifierCodeDocument will exist for each and
|
|
* every classifier that exists in our UMLDoc. IF when this is called, a code document
|
|
* doesn't exist for the given classifier, then we will created and add a new code
|
|
* document to our generator.
|
|
*
|
|
* IF you want to add non-classifier related code documents at this step,
|
|
* you will need to overload this method in the appropriate
|
|
* code generatator (see JavaCodeGenerator for an example of this).
|
|
*/
|
|
void CodeGenerator::initFromParentDocument( ) {
|
|
|
|
// Walk through the document converting classifiers into
|
|
// classifier code documents as needed (e.g only if doesn't exist)
|
|
UMLClassifierList concepts = UMLApp::app()->getDocument()->getClassesAndInterfaces();
|
|
for (UMLClassifier *c = concepts.first(); c; c = concepts.next())
|
|
{
|
|
|
|
// Doesn't exist? Then build one.
|
|
CodeDocument * codeDoc = findCodeDocumentByClassifier(c);
|
|
if (!codeDoc)
|
|
{
|
|
codeDoc = newClassifierCodeDocument(c);
|
|
addCodeDocument(codeDoc); // this will also add a unique tag to the code document
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Force a synchronize of this code generator, and its present contents, to that of the tqparent UMLDocument.
|
|
* "UserGenerated" code will be preserved, but Autogenerated contents will be updated/replaced
|
|
* or removed as is apppropriate.
|
|
*/
|
|
void CodeGenerator::syncCodeToDocument ( ) {
|
|
for (CodeDocument * doc = m_codedocumentVector.first(); doc; doc=m_codedocumentVector.next())
|
|
doc->synchronize();
|
|
}
|
|
|
|
// in this 'vanilla' version, we only worry about adding classifier
|
|
// documents
|
|
void CodeGenerator::checkAddUMLObject (UMLObject * obj) {
|
|
if (!obj)
|
|
return;
|
|
|
|
UMLClassifier * c = dynamic_cast<UMLClassifier*>(obj);
|
|
if(c) {
|
|
CodeDocument * cDoc = newClassifierCodeDocument(c);
|
|
addCodeDocument(cDoc);
|
|
}
|
|
}
|
|
|
|
void CodeGenerator::checkRemoveUMLObject (UMLObject * obj)
|
|
{
|
|
|
|
if (!obj)
|
|
return;
|
|
|
|
UMLClassifier * c = dynamic_cast<UMLClassifier*>(obj);
|
|
if(c) {
|
|
ClassifierCodeDocument * cDoc = (ClassifierCodeDocument*) findCodeDocumentByClassifier(c);
|
|
if (cDoc)
|
|
removeCodeDocument(cDoc);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @return CodeDocument
|
|
* @param classifier
|
|
*/
|
|
CodeDocument * CodeGenerator::findCodeDocumentByClassifier ( UMLClassifier * classifier ) {
|
|
return findCodeDocumentByID(ID2STR(classifier->getID()));
|
|
}
|
|
|
|
|
|
/**
|
|
* Write out all code documents to file as appropriate.
|
|
*/
|
|
void CodeGenerator::writeCodeToFile ( )
|
|
{
|
|
writeListedCodeDocsToFile(&m_codedocumentVector);
|
|
}
|
|
|
|
void CodeGenerator::writeCodeToFile ( UMLClassifierList & concepts) {
|
|
CodeDocumentList docs;
|
|
docs.setAutoDelete(false);
|
|
|
|
for (UMLClassifier *concept= concepts.first(); concept; concept= concepts.next())
|
|
{
|
|
CodeDocument * doc = findCodeDocumentByClassifier(concept);
|
|
if(doc)
|
|
docs.append(doc);
|
|
}
|
|
|
|
writeListedCodeDocsToFile(&docs);
|
|
}
|
|
|
|
// Main method. Will write out passed code documents to file as appropriate.
|
|
void CodeGenerator::writeListedCodeDocsToFile ( CodeDocumentList * docs ) {
|
|
|
|
// iterate thru all code documents
|
|
for (CodeDocument *doc = docs->first(); doc; doc = docs->next())
|
|
{
|
|
|
|
// we need this so we know when to emit a 'codeGenerated' signal
|
|
ClassifierCodeDocument * cdoc = dynamic_cast<ClassifierCodeDocument *>(doc);
|
|
bool codeGenSuccess = false;
|
|
|
|
// we only write the document, if so requested
|
|
if(doc->getWriteOutCode())
|
|
{
|
|
TQString filename = findFileName(doc);
|
|
// check that we may open that file for writing
|
|
TQFile file;
|
|
if ( openFile(file,filename) ) {
|
|
TQTextStream stream(&file);
|
|
stream<<doc->toString()<<endl;
|
|
file.close();
|
|
codeGenSuccess = true; // we wrote the code OK
|
|
} else {
|
|
kWarning() << "Cannot open file :"<<filename<<" for writing " << endl;
|
|
}
|
|
}
|
|
|
|
if(cdoc)
|
|
emit codeGenerated(cdoc->getParentClassifier(), codeGenSuccess);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Create a new Code document belonging to this package.
|
|
* @return CodeDocument
|
|
*/
|
|
CodeDocument * CodeGenerator::newCodeDocument ( ) {
|
|
CodeDocument * newCodeDoc = new CodeDocument ();
|
|
return newCodeDoc;
|
|
}
|
|
|
|
/**
|
|
* @return TQString
|
|
* @param file
|
|
*/
|
|
|
|
TQString CodeGenerator::getHeadingFile( const TQString &file ) {
|
|
return UMLApp::app()->getCommonPolicy()->getHeadingFile(file);
|
|
}
|
|
|
|
/**
|
|
* @return TQString
|
|
* @param codeDoc
|
|
* @param name
|
|
*/
|
|
TQString CodeGenerator::overwritableName(const TQString& name, const TQString &extension ) {
|
|
|
|
CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy();
|
|
TQDir outputDirectory = pol->getOutputDirectory();
|
|
TQString filename = name + extension;
|
|
|
|
if (!outputDirectory.exists(filename)) {
|
|
return filename;
|
|
}
|
|
|
|
int suffix;
|
|
OverwriteDialogue overwriteDialog( name, outputDirectory.absPath(),
|
|
m_applyToAllRemaining, kapp -> mainWidget() );
|
|
switch (pol->getOverwritePolicy()) { //if it exists, check the OverwritePolicy we should use
|
|
case CodeGenerationPolicy::Ok: //ok to overwrite file
|
|
filename = name + extension;
|
|
break;
|
|
case CodeGenerationPolicy::Ask: //ask if we can overwrite
|
|
switch(overwriteDialog.exec()) {
|
|
case KDialogBase::Yes: //overwrite file
|
|
if ( overwriteDialog.applyToAllRemaining() ) {
|
|
pol->setOverwritePolicy(CodeGenerationPolicy::Ok);
|
|
filename = name + extension;
|
|
} else {
|
|
m_applyToAllRemaining = false;
|
|
}
|
|
break;
|
|
case KDialogBase::No: //generate similar name
|
|
suffix = 1;
|
|
while (1) {
|
|
filename = name + "__" + TQString::number(suffix) + extension;
|
|
if (!outputDirectory.exists(filename))
|
|
break;
|
|
suffix++;
|
|
}
|
|
if ( overwriteDialog.applyToAllRemaining() ) {
|
|
pol->setOverwritePolicy(CodeGenerationPolicy::Never);
|
|
} else {
|
|
m_applyToAllRemaining = false;
|
|
}
|
|
break;
|
|
case KDialogBase::Cancel: //don't output anything
|
|
if ( overwriteDialog.applyToAllRemaining() ) {
|
|
pol->setOverwritePolicy(CodeGenerationPolicy::Cancel);
|
|
} else {
|
|
m_applyToAllRemaining = false;
|
|
}
|
|
return TQString();
|
|
break;
|
|
}
|
|
|
|
break;
|
|
case CodeGenerationPolicy::Never: //generate similar name
|
|
suffix = 1;
|
|
while (1) {
|
|
filename = name + "__" + TQString::number(suffix) + extension;
|
|
if (!outputDirectory.exists(filename))
|
|
break;
|
|
suffix++;
|
|
}
|
|
break;
|
|
case CodeGenerationPolicy::Cancel: //don't output anything
|
|
return TQString();
|
|
break;
|
|
}
|
|
|
|
return filename;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return bool
|
|
* @param file
|
|
* @param name
|
|
*/
|
|
bool CodeGenerator::openFile (TQFile & file, const TQString &fileName ) {
|
|
//open files for writing.
|
|
if(fileName.isEmpty()) {
|
|
kWarning() << "cannot find a file name" << endl;
|
|
return false;
|
|
} else {
|
|
TQDir outputDirectory = UMLApp::app()->getCommonPolicy()->getOutputDirectory();
|
|
file.setName(outputDirectory.absFilePath(fileName));
|
|
if(!file.open(IO_WriteOnly)) {
|
|
KMessageBox::sorry(0,i18n("Cannot open file %1 for writing. Please make sure the folder exists and you have permissions to write to it.").tqarg(file.name()),i18n("Cannot Open File"));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @return TQString
|
|
* @param name
|
|
*/
|
|
TQString CodeGenerator::cleanName ( const TQString &name ) {
|
|
TQString retval = name;
|
|
retval.tqreplace(TQRegExp("\\W"), "_");
|
|
return retval;
|
|
}
|
|
|
|
TQString CodeGenerator::findFileName ( CodeDocument * codeDocument ) {
|
|
|
|
//else, determine the "natural" file name
|
|
TQString name;
|
|
|
|
// Get the path name
|
|
TQString path = codeDocument->getPath();
|
|
|
|
// if path is given add this as a directory to the file name
|
|
if (!path.isEmpty()) {
|
|
path.tqreplace(TQRegExp("::"), "/"); // Simple hack!
|
|
name = path + '/' + codeDocument->getFileName();
|
|
path = '/' + path;
|
|
} else {
|
|
name = codeDocument->getFileName();
|
|
}
|
|
|
|
// Convert all "::" to "/" : Platform-specific path separator
|
|
name.tqreplace(TQRegExp("::"), "/"); // Simple hack!
|
|
|
|
// if a path name exists check the existence of the path directory
|
|
if (!path.isEmpty()) {
|
|
TQDir outputDirectory = UMLApp::app()->getCommonPolicy()->getOutputDirectory();
|
|
TQDir pathDir(outputDirectory.absPath() + path);
|
|
|
|
// does our complete output directory exist yet? if not, try to create it
|
|
if (!pathDir.exists())
|
|
{
|
|
// ugh. dir separator here is UNIX specific..
|
|
TQStringList dirs = TQStringList::split("/",pathDir.absPath());
|
|
TQString currentDir = "";
|
|
|
|
TQStringList::iterator end(dirs.end());
|
|
for (TQStringList::iterator dir(dirs.begin()); dir != end; ++dir)
|
|
{
|
|
currentDir += '/' + *dir;
|
|
if (! (pathDir.exists(currentDir)
|
|
|| pathDir.mkdir(currentDir) ) )
|
|
{
|
|
KMessageBox::error(0, i18n("Cannot create the folder:\n") +
|
|
pathDir.absPath() + i18n("\nPlease check the access rights"),
|
|
i18n("Cannot Create Folder"));
|
|
return NULL;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
name.simplifyWhiteSpace();
|
|
name.tqreplace(TQRegExp(" "),"_");
|
|
|
|
return overwritableName( name, codeDocument->getFileExtension() );
|
|
}
|
|
|
|
void CodeGenerator::findObjectsRelated(UMLClassifier *c, UMLPackageList &cList) {
|
|
UMLPackage *temp;
|
|
UMLAssociationList associations = c->getAssociations();
|
|
|
|
for (UMLAssociation *a = associations.first(); a; a = associations.next()) {
|
|
temp = 0;
|
|
switch (a->getAssocType()) {
|
|
case Uml::at_Generalization:
|
|
case Uml::at_Realization:
|
|
// only the "b" end is seen by the "a" end, not other way around
|
|
{
|
|
UMLObject *objB = a->getObject(Uml::B);
|
|
if (objB != c)
|
|
temp = (UMLPackage*)objB;
|
|
}
|
|
break;
|
|
case Uml::at_Dependency:
|
|
case Uml::at_UniAssociation:
|
|
{
|
|
UMLObject *objA = a->getObject(Uml::A);
|
|
UMLObject *objB = a->getObject(Uml::B);
|
|
if (objA == c)
|
|
temp = static_cast<UMLPackage*>(objB);
|
|
}
|
|
break;
|
|
case Uml::at_Aggregation:
|
|
case Uml::at_Composition:
|
|
case Uml::at_Association:
|
|
{
|
|
UMLObject *objA = a->getObject(Uml::A);
|
|
UMLObject *objB = a->getObject(Uml::B);
|
|
if (objA == c && objB->getBaseType() != Uml::ot_Datatype)
|
|
temp = static_cast<UMLPackage*>(objB);
|
|
}
|
|
break;
|
|
default: /* all others.. like for state diagrams..we currently don't use */
|
|
break;
|
|
}
|
|
|
|
// now add in list ONLY if its not already there
|
|
if(temp && !cList.tqcontainsRef(temp))
|
|
cList.append(temp);
|
|
}
|
|
|
|
//operations
|
|
UMLOperationList opl(c->getOpList());
|
|
for(UMLOperation *op = opl.first(); op ; op = opl.next()) {
|
|
temp =0;
|
|
//check return value
|
|
temp =(UMLClassifier*) op->getType();
|
|
if (temp && temp->getBaseType() != Uml::ot_Datatype && !cList.tqcontainsRef(temp))
|
|
cList.append(temp);
|
|
//check parameters
|
|
UMLAttributeList atl = op->getParmList();
|
|
for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
|
|
temp = (UMLClassifier*)at->getType();
|
|
if (temp && temp->getBaseType() != Uml::ot_Datatype && !cList.tqcontainsRef(temp))
|
|
cList.append(temp);
|
|
}
|
|
|
|
}
|
|
|
|
//attributes
|
|
if (!c->isInterface()) {
|
|
UMLAttributeList atl = c->getAttributeList();
|
|
for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
|
|
temp=0;
|
|
temp = (UMLClassifier*) at->getType();
|
|
if (temp && temp->getBaseType() != Uml::ot_Datatype && !cList.tqcontainsRef(temp))
|
|
cList.append(temp);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* Format an output document.
|
|
* @return TQString
|
|
* @param text
|
|
* @param lineprefix
|
|
* @param linewidth
|
|
*/
|
|
TQString CodeGenerator::formatDoc(const TQString &text, const TQString &linePrefix, int lineWidth) {
|
|
TQString output;
|
|
|
|
const TQString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
|
|
TQStringList lines = TQStringList::split(endLine, text);
|
|
for (TQStringList::ConstIterator lit = lines.begin(); lit != lines.end(); ++lit) {
|
|
TQString input = *lit;
|
|
input.remove( TQRegExp("\\s+$") );
|
|
if (input.length() < (uint)lineWidth) {
|
|
output += linePrefix + input + endLine;
|
|
continue;
|
|
}
|
|
int index;
|
|
while ((index = input.tqfindRev(" ", lineWidth)) >= 0) {
|
|
output += linePrefix + input.left(index) + endLine; // add line
|
|
input.remove(0, index + 1); //and remove processed string, including
|
|
// white space
|
|
}
|
|
if (!input.isEmpty())
|
|
output += linePrefix + input + endLine;
|
|
}
|
|
return output;
|
|
}
|
|
|
|
void CodeGenerator::initFields() {
|
|
|
|
m_document = UMLApp::app()->getDocument();
|
|
m_codeDocumentDictionary.setAutoDelete(false);
|
|
m_codedocumentVector.setAutoDelete(false);
|
|
m_applyToAllRemaining = true;
|
|
lastIDIndex = 0;
|
|
|
|
// initial population of our project generator
|
|
// CANT Be done here because we would call pure virtual method
|
|
// of newClassifierDocument (bad!).
|
|
// We should only call from the child
|
|
// initFromParentDocument();
|
|
|
|
}
|
|
|
|
void CodeGenerator::connect_newcodegen_slots() {
|
|
UMLDoc *doc = UMLApp::app()->getDocument();
|
|
connect(doc, TQT_SIGNAL(sigObjectCreated(UMLObject*)),
|
|
this, TQT_SLOT(checkAddUMLObject(UMLObject*)));
|
|
connect(doc, TQT_SIGNAL(sigObjectRemoved(UMLObject*)),
|
|
this, TQT_SLOT(checkRemoveUMLObject(UMLObject*)));
|
|
CodeGenerationPolicy *commonPolicy = UMLApp::app()->getCommonPolicy();
|
|
connect(commonPolicy, TQT_SIGNAL(modifiedCodeContent()),
|
|
this, TQT_SLOT(syncCodeToDocument()));
|
|
}
|
|
|
|
// these are utility methods for accessing the default
|
|
// code gen policy object and should go away when we
|
|
// finally implement the CodeGenDialog class -b.t.
|
|
void CodeGenerator::setForceDoc(bool f) {
|
|
UMLApp::app()->getCommonPolicy()->setCodeVerboseDocumentComments(f);
|
|
}
|
|
|
|
bool CodeGenerator::forceDoc() const {
|
|
return UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments();
|
|
}
|
|
|
|
void CodeGenerator::setForceSections(bool f) {
|
|
UMLApp::app()->getCommonPolicy()->setCodeVerboseSectionComments(f);
|
|
}
|
|
|
|
bool CodeGenerator::forceSections() const {
|
|
return UMLApp::app()->getCommonPolicy()->getCodeVerboseSectionComments();
|
|
}
|
|
|
|
TQStringList CodeGenerator::defaultDatatypes() {
|
|
return TQStringList();
|
|
//empty by default, override in your code generator
|
|
}
|
|
|
|
bool CodeGenerator::isReservedKeyword(const TQString & keyword) {
|
|
|
|
const TQStringList keywords = reservedKeywords();
|
|
|
|
return keywords.tqcontains(keyword);
|
|
}
|
|
|
|
const TQStringList CodeGenerator::reservedKeywords() const {
|
|
static TQStringList emptyList;
|
|
|
|
return emptyList;
|
|
}
|
|
|
|
void CodeGenerator::createDefaultStereotypes() {
|
|
//empty by default, override in your code generator
|
|
//e.g. m_document->createDefaultStereotypes("constructor");
|
|
}
|
|
|
|
#include "codegenerator.moc"
|