00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "folder.h"
00014
00015 #include <qfile.h>
00016 #include <kdebug.h>
00017 #include <klocale.h>
00018 #include <kmessagebox.h>
00019
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
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
00092
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
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
00160 v->removeAllAssociations();
00161
00162
00163
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
00181 for (UMLObjectListIt oit(m_objects); (obj = oit.current()) != NULL; ++oit)
00182 obj->saveToXMI (qDoc, ownedElement);
00183
00184 for (UMLObjectListIt ait(m_List); (obj = ait.current()) != NULL; ++ait)
00185 obj->saveToXMI (qDoc, ownedElement);
00186 qElement.appendChild(ownedElement);
00187
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
00218
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
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
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
00339
00340
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
00371
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
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"