umbrello API Documentation

folder.cpp

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) 2006                                                    *
00009  *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
00010  ***************************************************************************/
00011 
00012 // own header
00013 #include "folder.h"
00014 // qt/kde includes
00015 #include <qfile.h>
00016 #include <kdebug.h>
00017 #include <klocale.h>
00018 #include <kmessagebox.h>
00019 // app includes
00020 #include "uml.h"
00021 #include "umldoc.h"
00022 #include "umlview.h"
00023 #include "umllistview.h"
00024 #include "optionstate.h"
00025 #include "object_factory.h"
00026 #include "model_utils.h"
00027 
00028 UMLFolder::UMLFolder(const QString & name, Uml::IDType id)
00029         : UMLPackage(name, id) {
00030     init();
00031 }
00032 
00033 UMLFolder::~UMLFolder() {
00034 }
00035 
00036 void UMLFolder::init() {
00037     m_BaseType = Uml::ot_Folder;
00038     m_diagrams.setAutoDelete(true);
00039     UMLObject::setStereotype("folder");
00040 }
00041 
00042 UMLObject* UMLFolder::clone() const {
00043     UMLFolder *clone = new UMLFolder();
00044     UMLObject::copyInto(clone);
00045     return clone;
00046 }
00047 
00048 void UMLFolder::setLocalName(const QString& localName) {
00049     m_localName = localName;
00050 }
00051 
00052 QString UMLFolder::getLocalName() {
00053     return m_localName;
00054 }
00055 
00056 void UMLFolder::addView(UMLView *view) {
00057     m_diagrams.append(view);
00058 }
00059 
00060 void UMLFolder::removeView(UMLView *view) {
00061     // m_diagrams is set to autodelete!
00062     m_diagrams.remove(view);
00063 }
00064 
00065 void UMLFolder::appendViews(UMLViewList& viewList, bool includeNested) {
00066     if (includeNested) {
00067         UMLObject *o;
00068         for (UMLObjectListIt oit(m_objects); (o = oit.current()) != NULL; ++oit) {
00069             if (o->getBaseType() == Uml::ot_Folder) {
00070                 UMLFolder *f = static_cast<UMLFolder*>(o);
00071                 f->appendViews(viewList);
00072             }
00073         }
00074     }
00075     UMLView *v;
00076     for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit)
00077         viewList.append(v);
00078 }
00079 
00080 void UMLFolder::activateViews() {
00081     UMLObject *o;
00082     for (UMLObjectListIt oit(m_objects); (o = oit.current()) != NULL; ++oit) {
00083         if (o->getBaseType() == Uml::ot_Folder) {
00084             UMLFolder *f = static_cast<UMLFolder*>(o);
00085             f->activateViews();
00086         }
00087     }
00088     UMLView *v;
00089     for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit)
00090         v->activateAfterLoad();
00091     // Make sure we have a treeview item for each diagram.
00092     // It may happen that we are missing them after switching off tabbed widgets.
00093     Settings::OptionState optionState = Settings::getOptionState();
00094     if (optionState.generalState.tabdiagrams)
00095         return;
00096     UMLListView *lv = UMLApp::app()->getListView();
00097     for (UMLViewListIt it(m_diagrams); (v = it.current()) != NULL; ++it) {
00098         if (lv->findItem(v->getID()) != NULL)
00099             continue;
00100         lv->createDiagramItem(v);
00101     }
00102 }
00103 
00104 UMLView *UMLFolder::findView(Uml::IDType id) {
00105     UMLView *v = NULL;
00106     for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit) {
00107         if (v->getID() == id)
00108             return v;
00109     }
00110     UMLObject *o;
00111     for (UMLObjectListIt oit(m_objects); (o = oit.current()) != NULL; ++oit) {
00112         if (o->getBaseType() != Uml::ot_Folder)
00113             continue;
00114         UMLFolder *f = static_cast<UMLFolder*>(o);
00115         v = f->findView(id);
00116         if (v)
00117             break;
00118     }
00119     return v;
00120 }
00121 
00122 UMLView *UMLFolder::findView(Uml::Diagram_Type type, const QString &name, bool searchAllScopes) {
00123     UMLView *v = NULL;
00124     for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit) {
00125         if (v->getType() == type && v->getName() == name)
00126             return v;
00127     }
00128     if (searchAllScopes) {
00129         UMLObject *o;
00130         for (UMLObjectListIt oit(m_objects); (o = oit.current()) != NULL; ++oit) {
00131             if (o->getBaseType() != Uml::ot_Folder)
00132                 continue;
00133             UMLFolder *f = static_cast<UMLFolder*>(o);
00134             v = f->findView(type, name, searchAllScopes);
00135             if (v)
00136                 break;
00137         }
00138     }
00139     return v;
00140 }
00141 
00142 void UMLFolder::setViewOptions(const Settings::OptionState& optionState) {
00143     // for each view update settings
00144     UMLView *v;
00145     for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit)
00146         v->setOptionState(optionState);
00147 }
00148 
00149 void UMLFolder::removeAllViews() {
00150     UMLObject *o;
00151     for (UMLObjectListIt oit(m_objects); (o = oit.current()) != NULL; ++oit) {
00152         if (o->getBaseType() != Uml::ot_Folder)
00153             continue;
00154         UMLFolder *f = static_cast<UMLFolder*>(o);
00155         f->removeAllViews();
00156     }
00157     UMLView *v = NULL;
00158     for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit) {
00159         // TODO ------------------ check this code - bad: calling back to UMLDoc::removeView()
00160         v->removeAllAssociations(); // note : It may not be apparent, but when we remove all associations
00161         // from a view, it also causes any UMLAssociations that lack parent
00162         // association widgets (but once had them) to remove themselves from
00163         // this document.
00164         UMLApp::app()->getDocument()->removeView(v, false);
00165     }
00166     m_diagrams.clear();
00167 }
00168 
00169 void UMLFolder::setFolderFile(const QString& fileName) {
00170     m_folderFile = fileName;
00171 }
00172 
00173 QString UMLFolder::getFolderFile() {
00174     return m_folderFile;
00175 }
00176 
00177 void UMLFolder::saveContents(QDomDocument& qDoc, QDomElement& qElement) {
00178     QDomElement ownedElement = qDoc.createElement("UML:Namespace.ownedElement");
00179     UMLObject *obj;
00180     // Save contained objects if any.
00181     for (UMLObjectListIt oit(m_objects); (obj = oit.current()) != NULL; ++oit)
00182         obj->saveToXMI (qDoc, ownedElement);
00183     // Save asscociations if any.
00184     for (UMLObjectListIt ait(m_List); (obj = ait.current()) != NULL; ++ait)
00185         obj->saveToXMI (qDoc, ownedElement);
00186     qElement.appendChild(ownedElement);
00187     // Save diagrams to `extension'.
00188     if (m_diagrams.count()) {
00189         QDomElement diagramsElement = qDoc.createElement("diagrams");
00190         UMLView *pView;
00191         for (UMLViewListIt vit(m_diagrams); (pView = vit.current()) != NULL; ++vit) {
00192             pView->saveToXMI(qDoc, diagramsElement);
00193         }
00194         QDomElement extension = qDoc.createElement("XMI.extension");
00195         extension.setAttribute("xmi.extender", "umbrello");
00196         extension.appendChild( diagramsElement );
00197         qElement.appendChild(extension);
00198     }
00199 }
00200 
00201 void UMLFolder::save(QDomDocument& qDoc, QDomElement& qElement) {
00202     UMLDoc *umldoc = UMLApp::app()->getDocument();
00203     QString elementName("UML:Package");
00204     const Uml::Model_Type mt = umldoc->rootFolderType(this);
00205     if (mt != Uml::N_MODELTYPES)
00206         elementName = "UML:Model";
00207     QDomElement folderElement = UMLObject::save(elementName, qDoc);
00208     saveContents(qDoc, folderElement);
00209     qElement.appendChild(folderElement);
00210 }
00211 
00212 void UMLFolder::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
00213     if (m_folderFile.isEmpty()) {
00214         save(qDoc, qElement);
00215         return;
00216     }
00217     // See if we can create the external file.
00218     // If not then internalize the folder.
00219     UMLDoc *umldoc = UMLApp::app()->getDocument();
00220     QString fileName = umldoc->URL().directory() + '/' + m_folderFile;
00221     QFile file(fileName);
00222     if (!file.open(IO_WriteOnly)) {
00223         kError() << "UMLFolder::saveToXMI(" << m_folderFile << "): "
00224             << "cannot create file, contents will be saved in main model file"
00225             << endl;
00226         m_folderFile = QString::null;
00227         save(qDoc, qElement);
00228         return;
00229     }
00230     // Okay, external file is writable.  Wrap up main file.
00231     QDomElement folderElement = UMLObject::save("UML:Package", qDoc);
00232     QDomElement extension = qDoc.createElement("XMI.extension");
00233     extension.setAttribute("xmi.extender", "umbrello");
00234     QDomElement fileElement = qDoc.createElement("external_file");
00235     fileElement.setAttribute("name", m_folderFile);
00236     extension.appendChild(fileElement);
00237     folderElement.appendChild(extension);
00238     qElement.appendChild(folderElement);
00239 
00240     // Save folder to external file.
00241     QDomDocument folderDoc;
00242     QDomElement folderRoot;
00243     QDomProcessingInstruction xmlHeading =
00244         folderDoc.createProcessingInstruction("xml",
00245                                               "version=\"1.0\" encoding=\"UTF-8\"");
00246     folderDoc.appendChild(xmlHeading);
00247     folderRoot = folderDoc.createElement("external_file");
00248     folderRoot.setAttribute("name", m_Name);
00249     folderRoot.setAttribute("filename", m_folderFile);
00250     folderRoot.setAttribute("mainModel", umldoc->URL().fileName());
00251     folderRoot.setAttribute("parentId", ID2STR(m_pUMLPackage->getID()));
00252     folderRoot.setAttribute("parent", m_pUMLPackage->getFullyQualifiedName("::", true));
00253     saveContents(folderDoc, folderRoot);
00254     folderDoc.appendChild(folderRoot);
00255     QTextStream stream(&file);
00256     stream.setEncoding(QTextStream::UnicodeUTF8);
00257     stream << folderDoc.toString();
00258     file.close();
00259 }
00260 
00261 bool UMLFolder::loadDiagramsFromXMI(QDomNode& diagrams) {
00262     const Settings::OptionState optionState = Settings::getOptionState();
00263     UMLDoc *umldoc = UMLApp::app()->getDocument();
00264     bool totalSuccess = true;
00265     for (QDomElement diagram = diagrams.toElement(); !diagram.isNull();
00266          diagrams = diagrams.nextSibling(), diagram = diagrams.toElement()) {
00267         QString tag = diagram.tagName();
00268         if (tag != "diagram") {
00269             kDebug() << "UMLFolder::loadDiagramsFromXMI: ignoring "
00270                 << tag << " in <diagrams>" << endl;
00271             continue;
00272         }
00273         UMLView * pView = new UMLView(this);
00274         pView->setOptionState(optionState);
00275         if (pView->loadFromXMI(diagram)) {
00276             pView->hide();
00277             umldoc->addView(pView);
00278         } else {
00279             delete pView;
00280             totalSuccess = false;
00281         }
00282     }
00283     return totalSuccess;
00284 }
00285 
00286 bool UMLFolder::loadFolderFile(const QString& path) {
00287     QFile file(path);
00288     if (!file.exists()) {
00289         KMessageBox::error(0, i18n("The folderfile %1 does not exist.").arg(path), i18n("Load Error"));
00290         return false;
00291     }
00292     if (!file.open(IO_ReadOnly)) {
00293         KMessageBox::error(0, i18n("The folderfile %1 cannot be opened.").arg(path), i18n("Load Error"));
00294         return false;
00295     }
00296     QTextStream stream(&file);
00297     QString data = stream.read();
00298     file.close();
00299     QDomDocument doc;
00300     QString error;
00301     int line;
00302     if (!doc.setContent( data, false, &error, &line)) {
00303         kError() << "UMLFolder::loadFolderFile: Can't set content:"
00304             << error << " line:" << line << endl;
00305         return false;
00306     }
00307     QDomNode rootNode = doc.firstChild();
00308     while (rootNode.isComment() || rootNode.isProcessingInstruction()) {
00309         rootNode = rootNode.nextSibling();
00310     }
00311     if (rootNode.isNull()) {
00312         kError() << "UMLFolder::loadFolderFile: Root node is Null" << endl;
00313         return false;
00314     }
00315     QDomElement element = rootNode.toElement();
00316     QString type = element.tagName();
00317     if (type != "external_file") {
00318         kError() << "UMLFolder::loadFolderFile: Root node has unknown type "
00319             << type << endl;
00320         return false;
00321     }
00322     return load(element);
00323 }
00324 
00325 bool UMLFolder::load(QDomElement& element) {
00326     UMLDoc *umldoc = UMLApp::app()->getDocument();
00327     bool totalSuccess = true;
00328     for (QDomNode node = element.firstChild(); !node.isNull();
00329             node = node.nextSibling()) {
00330         if (node.isComment())
00331             continue;
00332         QDomElement tempElement = node.toElement();
00333         QString type = tempElement.tagName();
00334         if (Model_Utils::isCommonXMIAttribute(type))
00335             continue;
00336         if (Uml::tagEq(type, "Namespace.ownedElement") ||
00337                 Uml::tagEq(type, "Namespace.contents")) {
00338             //CHECK: Umbrello currently assumes that nested elements
00339             // are ownedElements anyway.
00340             // Therefore these tags are not further interpreted.
00341             if (! load(tempElement)) {
00342                 kDebug() << "An error happened while loading the " << type
00343                     << " of the " << m_Name << endl;
00344                 totalSuccess = false;
00345             }
00346             continue;
00347         } else if (type == "XMI.extension") {
00348             for (QDomNode xtnode = node.firstChild(); !xtnode.isNull();
00349                                               xtnode = xtnode.nextSibling()) {
00350                 QDomElement el = xtnode.toElement();
00351                 const QString xtag = el.tagName();
00352                 if (xtag == "diagrams") {
00353                     QDomNode diagramNode = xtnode.firstChild();
00354                     if (!loadDiagramsFromXMI(diagramNode))
00355                         totalSuccess = false;
00356                 } else if (xtag == "external_file") {
00357                     const QString rootDir(umldoc->URL().directory());
00358                     QString fileName = el.attribute("name", "");
00359                     const QString path(rootDir + '/' + fileName);
00360                     if (loadFolderFile(path))
00361                         m_folderFile = fileName;
00362                 } else {
00363                     kDebug() << "UMLFolder::load(" << m_Name
00364                         << "): ignoring XMI.extension " << xtag << endl;
00365                     continue;
00366                 }
00367             }
00368             continue;
00369         }
00370         // Do not re-create the predefined Datatypes folder in the Logical View,
00371         // it already exists.
00372         UMLFolder *logicalView = umldoc->getRootFolder(Uml::mt_Logical);
00373         if (this == logicalView && Uml::tagEq(type, "Package")) {
00374             QString thisName = tempElement.attribute("name", "");
00375             if (thisName == "Datatypes") {
00376                 UMLFolder *datatypeFolder = umldoc->getDatatypeFolder();
00377                 if (!datatypeFolder->loadFromXMI(tempElement))
00378                     totalSuccess = false;
00379                 continue;
00380             }
00381         }
00382         UMLObject *pObject = NULL;
00383         // Avoid duplicate creation of forward declared object
00384         QString idStr = tempElement.attribute("xmi.id", "");
00385         if (!idStr.isEmpty()) {
00386             Uml::IDType id = STR2ID(idStr);
00387             pObject = umldoc->findObjectById(id);
00388             if (pObject) {
00389                 kDebug() << "UMLFolder::load: object " << idStr
00390                   << "already exists" << endl;
00391             }
00392         }
00393         if (pObject == NULL) {
00394             QString stereoID = tempElement.attribute("stereotype", "");
00395             pObject = Object_Factory::makeObjectFromXMI(type, stereoID);
00396             if (!pObject) {
00397                 kWarning() << "UMLFolder::load: "
00398                     << "Unknown type of umlobject to create: " << type << endl;
00399                 continue;
00400             }
00401         }
00402         pObject->setUMLPackage(this);
00403         if (!pObject->loadFromXMI(tempElement)) {
00404             removeObject(pObject);
00405             delete pObject;
00406             totalSuccess = false;
00407         }
00408     }
00409     return totalSuccess;
00410 }
00411 
00412 #include "folder.moc"
KDE Logo
This file is part of the documentation for umbrello Version 3.1.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Jun 26 08:07:57 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003