00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "umldoc.h"
00014
00015
00016 #include <qpainter.h>
00017 #include <qtimer.h>
00018 #include <qdatetime.h>
00019 #include <qbuffer.h>
00020 #include <qdir.h>
00021 #include <qregexp.h>
00022 #include <qlabel.h>
00023
00024
00025 #include <kapplication.h>
00026 #include <kdeversion.h>
00027 #include <kdebug.h>
00028 #include <kio/job.h>
00029 #include <kio/netaccess.h>
00030 #include <klocale.h>
00031 #include <kmessagebox.h>
00032 #include <kmimetype.h>
00033 #include <kprinter.h>
00034 #include <ktar.h>
00035 #include <ktempdir.h>
00036 #include <ktempfile.h>
00037 #include <kiconloader.h>
00038 #include <kinputdialog.h>
00039 #include <ktabwidget.h>
00040
00041
00042 #include "uniqueid.h"
00043 #include "associationwidget.h"
00044 #include "association.h"
00045 #include "package.h"
00046 #include "folder.h"
00047 #include "codegenerator.h"
00048 #include "classifier.h"
00049 #include "enum.h"
00050 #include "entity.h"
00051 #include "docwindow.h"
00052 #include "operation.h"
00053 #include "attribute.h"
00054 #include "template.h"
00055 #include "enumliteral.h"
00056 #include "entityattribute.h"
00057 #include "stereotype.h"
00058 #include "classifierlistitem.h"
00059 #include "object_factory.h"
00060 #include "import_rose.h"
00061 #include "model_utils.h"
00062 #include "widget_utils.h"
00063 #include "uml.h"
00064 #include "umllistview.h"
00065 #include "umllistviewitem.h"
00066 #include "umlview.h"
00067 #include "clipboard/idchangelog.h"
00068 #include "dialogs/classpropdlg.h"
00069 #include "codegenerators/codegenfactory.h"
00070 #include "listpopupmenu.h"
00071 #include "version.h"
00072
00073 #define XMI_FILE_VERSION UMBRELLO_VERSION
00074
00075
00076
00077 using namespace Uml;
00078
00079 static const uint undoMax = 30;
00080
00081 UMLDoc::UMLDoc() {
00082 m_Name = i18n("UML Model");
00083 m_modelID = "m1";
00084 m_count = 0;
00085 m_pChangeLog = 0;
00086 m_Doc = "";
00087 m_modified = false;
00088 m_bLoading = false;
00089 m_bTypesAreResolved = false;
00090 m_pAutoSaveTimer = 0;
00091 m_nViewID = Uml::id_None;
00092 m_pTabPopupMenu = 0;
00093 m_pCurrentRoot = NULL;
00094 }
00095
00096 void UMLDoc::init() {
00097
00098 const QString nativeRootName[Uml::N_MODELTYPES] = {
00099 "Logical View",
00100 "Use Case View",
00101 "Component View",
00102 "Deployment View",
00103 "Entity Relationship Model"
00104 };
00105 const QString localizedRootName[Uml::N_MODELTYPES] = {
00106 i18n("Logical View"),
00107 i18n("Use Case View"),
00108 i18n("Component View"),
00109 i18n("Deployment View"),
00110 i18n("Entity Relationship Model")
00111 };
00112 for (int i = 0; i < Uml::N_MODELTYPES; i++) {
00113 m_root[i] = new UMLFolder(nativeRootName[i], STR2ID(nativeRootName[i]));
00114 m_root[i]->setLocalName(localizedRootName[i]);
00115 }
00116 m_datatypeRoot = new UMLFolder("Datatypes", "Datatypes");
00117 m_datatypeRoot->setLocalName(i18n("Datatypes"));
00118 m_datatypeRoot->setUMLPackage(m_root[Uml::mt_Logical]);
00119 m_root[Uml::mt_Logical]->addObject(m_datatypeRoot);
00120
00121
00122 UMLApp * pApp = UMLApp::app();
00123 connect(this, SIGNAL(sigDiagramCreated(Uml::IDType)), pApp, SLOT(slotUpdateViews()));
00124 connect(this, SIGNAL(sigDiagramRemoved(Uml::IDType)), pApp, SLOT(slotUpdateViews()));
00125 connect(this, SIGNAL(sigDiagramRenamed(Uml::IDType)), pApp, SLOT(slotUpdateViews()));
00126 connect(this, SIGNAL( sigCurrentViewChanged() ), pApp, SLOT( slotCurrentViewChanged() ) );
00127 }
00128
00129 UMLDoc::~UMLDoc() {
00130 delete m_pChangeLog;
00131 m_pChangeLog = 0;
00132 }
00133
00134 void UMLDoc::addView(UMLView *view) {
00135 if (view == NULL) {
00136 kError() << "UMLDoc::addView: argument is NULL" << endl;
00137 return;
00138 }
00139 UMLFolder *f = view->getFolder();
00140 if (f == NULL) {
00141 kError() << "UMLDoc::addView: view folder is not set" << endl;
00142 return;
00143 }
00144 f->addView(view);
00145
00146 UMLApp * pApp = UMLApp::app();
00147 if ( pApp->getListView() )
00148 connect(this, SIGNAL(sigObjectRemoved(UMLObject *)), view, SLOT(slotObjectRemoved(UMLObject *)));
00149
00150 pApp->setCurrentView(view);
00151 if ( ! m_bLoading ) {
00152 view -> show();
00153 emit sigDiagramChanged(view ->getType());
00154 }
00155
00156 Settings::OptionState optionState = Settings::getOptionState();
00157 KTabWidget* tabWidget = NULL;
00158 if (optionState.generalState.tabdiagrams) {
00159 tabWidget = UMLApp::app()->tabWidget();
00160 tabWidget->addTab(view, view->getName());
00161 tabWidget->setTabIconSet(view, Widget_Utils::iconSet(view->getType()));
00162 }
00163 pApp->setDiagramMenuItemsState(true);
00164 pApp->slotUpdateViews();
00165 pApp->setCurrentView(view);
00166 if (tabWidget) {
00167 tabWidget->showPage(view);
00168 tabWidget->setCurrentPage(tabWidget->currentPageIndex());
00169 }
00170 }
00171
00172 void UMLDoc::removeView(UMLView *view , bool enforceCurrentView ) {
00173 if(!view)
00174 {
00175 kError()<<"UMLDoc::removeView(UMLView *view) called with view = 0"<<endl;
00176 return;
00177 }
00178 if ( UMLApp::app()->getListView() ) {
00179 disconnect(this,SIGNAL(sigObjectRemoved(UMLObject *)), view,SLOT(slotObjectRemoved(UMLObject *)));
00180 }
00181 view->hide();
00182
00183 view->removeAllWidgets();
00184 UMLFolder *f = view->getFolder();
00185 if (f == NULL) {
00186 kError() << "UMLDoc::removeView(" << view->getName()
00187 << "): view->getFolder() returns NULL" << endl;
00188 return;
00189 }
00190 f->removeView(view);
00191 UMLView *currentView = UMLApp::app()->getCurrentView();
00192 if (currentView == view)
00193 {
00194 UMLApp::app()->setCurrentView(NULL);
00195 UMLViewList viewList;
00196 m_root[mt_Logical]->appendViews(viewList);
00197 UMLView* firstView = viewList.first();
00198 if (!firstView && enforceCurrentView)
00199 {
00200 createDiagram(m_root[mt_Logical], dt_Class, false);
00201 kapp->processEvents();
00202 m_root[mt_Logical]->appendViews(viewList);
00203 firstView = viewList.first();
00204 }
00205
00206 if ( firstView )
00207 {
00208 changeCurrentView( firstView->getID() );
00209 UMLApp::app()->setDiagramMenuItemsState(true);
00210 }
00211 }
00212 }
00213
00214 void UMLDoc::setURL(const KURL &url) {
00215 m_doc_url = url;
00216 return;
00217 }
00218
00219 const KURL& UMLDoc::URL() const {
00220 return m_doc_url;
00221 }
00222
00223 bool UMLDoc::saveModified() {
00224 bool completed(true);
00225 if (!m_modified)
00226 return completed;
00227
00228 UMLApp *win = UMLApp::app();
00229 int want_save = KMessageBox::warningYesNoCancel(win, i18n("The current file has been modified.\nDo you want to save it?"), i18n("Warning"),KStdGuiItem::save(),KStdGuiItem::discard());
00230 switch(want_save) {
00231 case KMessageBox::Yes:
00232 if (m_doc_url.fileName() == i18n("Untitled")) {
00233 if (win->slotFileSaveAs()) {
00234 closeDocument();
00235 completed=true;
00236 } else {
00237 completed=false;
00238 }
00239 } else {
00240 saveDocument(URL());
00241 closeDocument();
00242 completed=true;
00243 }
00244 break;
00245
00246 case KMessageBox::No:
00247 setModified(false);
00248 closeDocument();
00249 completed=true;
00250 break;
00251
00252 case KMessageBox::Cancel:
00253 completed=false;
00254 break;
00255
00256 default:
00257 completed=false;
00258 break;
00259 }
00260 return completed;
00261 }
00262
00263 void UMLDoc::closeDocument() {
00264 UMLApp::app()->setGenerator(Uml::pl_Reserved);
00265 m_Doc = "";
00266 DocWindow* dw = UMLApp::app()->getDocWindow();
00267 if (dw) {
00268 dw->newDocumentation();
00269 }
00270
00271 UMLListView *listView = UMLApp::app()->getListView();
00272 if (listView) {
00273 listView->init();
00274
00275 bool m_bLoading_old = m_bLoading;
00276 m_bLoading = true;
00277
00278
00279
00280
00281
00282
00283
00284 removeAllViews();
00285 m_bLoading = m_bLoading_old;
00286
00287
00288 UMLObject *obj;
00289 for (int i = 0; i < Uml::N_MODELTYPES; i++)
00290 m_root[i]->removeAllObjects();
00291
00292 m_datatypeRoot = new UMLFolder("Datatypes", "Datatypes");
00293 m_datatypeRoot->setLocalName(i18n("Datatypes"));
00294 m_datatypeRoot->setUMLPackage(m_root[Uml::mt_Logical]);
00295 m_root[Uml::mt_Logical]->addObject(m_datatypeRoot);
00296 listView->theDatatypeFolder()->setUMLObject(m_datatypeRoot);
00297
00298
00299
00300
00301
00302
00303
00304
00305 }
00306 m_bTypesAreResolved = false;
00307 }
00308
00309 bool UMLDoc::newDocument() {
00310 closeDocument();
00311 UMLApp::app()->setCurrentView(NULL);
00312 m_doc_url.setFileName(i18n("Untitled"));
00313
00314 Settings::OptionState optionState = Settings::getOptionState();
00315 Uml::Diagram_Type dt = optionState.generalState.diagram;
00316 Uml::Model_Type mt = Model_Utils::convert_DT_MT(dt);
00317 if (mt == Uml::N_MODELTYPES) {
00318 dt = Uml::dt_Class;
00319 mt = Uml::mt_Logical;
00320 }
00321 createDiagram(m_root[mt], dt, false);
00322
00323 UMLApp::app()->initGenerator();
00324 addDefaultDatatypes();
00325 addDefaultStereotypes();
00326
00327 setModified(false);
00328 initSaveTimer();
00329
00330 UMLApp::app()->enableUndo(false);
00331 clearUndoStack();
00332 addToUndoStack();
00333
00334 return true;
00335 }
00336
00337 bool UMLDoc::openDocument(const KURL& url, const char* ) {
00338 if(url.fileName().length() == 0) {
00339 newDocument();
00340 return false;
00341 }
00342
00343 m_doc_url = url;
00344 QDir d = url.path(1);
00345 closeDocument();
00346
00347
00348
00349
00350 m_bLoading = true;
00351 QString tmpfile;
00352 KIO::NetAccess::download( url, tmpfile, UMLApp::app() );
00353 QFile file( tmpfile );
00354 if ( !file.exists() ) {
00355 KMessageBox::error(0, i18n("The file %1 does not exist.").arg(d.path()), i18n("Load Error"));
00356 m_doc_url.setFileName(i18n("Untitled"));
00357 m_bLoading = false;
00358 newDocument();
00359 return false;
00360 }
00361
00362
00363 bool status = false;
00364
00365
00366 QString filetype = m_doc_url.fileName(true);
00367 QString mimetype = "";
00368 if (filetype.find(QRegExp("\\.tgz$")) != -1)
00369 {
00370 mimetype = "application/x-gzip";
00371 } else if (filetype.find(QRegExp("\\.tar.bz2$")) != -1) {
00372 mimetype = "application/x-bzip2";
00373 }
00374
00375 if (mimetype.isEmpty() == false)
00376 {
00377 KTar archive(tmpfile, mimetype);
00378 if (archive.open(IO_ReadOnly) == false)
00379 {
00380 KMessageBox::error(0, i18n("The file %1 seems to be corrupted.").arg(d.path()), i18n("Load Error"));
00381 m_doc_url.setFileName(i18n("Untitled"));
00382 m_bLoading = false;
00383 newDocument();
00384 return false;
00385 }
00386
00387
00388 const KArchiveDirectory * rootDir = archive.directory();
00389 QStringList entries = rootDir->entries();
00390 QString entryMimeType;
00391 bool foundXMI = false;
00392 QStringList::Iterator it;
00393 QStringList::Iterator end(entries.end());
00394
00395
00396 for (it = entries.begin(); it != end; ++it)
00397 {
00398
00399 if (rootDir->entry(*it)->isFile() == true)
00400 {
00401
00402 entryMimeType = KMimeType::findByPath(*it, 0, true)->name();
00403 if (entryMimeType == "application/x-uml")
00404 {
00405 foundXMI = true;
00406 break;
00407 }
00408 }
00409 }
00410
00411
00412 if (foundXMI == true)
00413 {
00414 KTempDir tmp_dir;
00415 KArchiveEntry * entry;
00416 KArchiveFile * fileEntry;
00417
00418
00419 entry = const_cast<KArchiveEntry*>(rootDir->entry(*it));
00420 if (entry == 0)
00421 {
00422 KMessageBox::error(0, i18n("There was no XMI file found in the compressed file %1.").arg(d.path()), i18n("Load Error"));
00423 m_doc_url.setFileName(i18n("Untitled"));
00424 m_bLoading = false;
00425 newDocument();
00426 return false;
00427 }
00428
00429
00430
00431 fileEntry = dynamic_cast<KArchiveFile*>(entry);
00432 if (fileEntry == 0)
00433 {
00434 KMessageBox::error(0, i18n("There was no XMI file found in the compressed file %1.").arg(d.path()), i18n("Load Error"));
00435 m_doc_url.setFileName(i18n("Untitled"));
00436 m_bLoading = false;
00437 newDocument();
00438 return false;
00439 }
00440
00441
00442 fileEntry->copyTo(tmp_dir.name());
00443
00444
00445 QFile xmi_file(tmp_dir.name() + *it);
00446 if( !xmi_file.open( IO_ReadOnly ) )
00447 {
00448 KMessageBox::error(0, i18n("There was a problem loading the extracted file: %1").arg(d.path()), i18n("Load Error"));
00449 m_doc_url.setFileName(i18n("Untitled"));
00450 m_bLoading = false;
00451 newDocument();
00452 return false;
00453 }
00454 status = loadFromXMI( xmi_file, ENC_UNKNOWN );
00455
00456
00457 xmi_file.close();
00458 tmp_dir.unlink();
00459
00460 } else {
00461 KMessageBox::error(0, i18n("There was no XMI file found in the compressed file %1.").arg(d.path()), i18n("Load Error"));
00462 m_doc_url.setFileName(i18n("Untitled"));
00463 m_bLoading = false;
00464 newDocument();
00465 return false;
00466 }
00467
00468 archive.close();
00469 } else {
00470
00471 if( !file.open( IO_ReadOnly ) ) {
00472 KMessageBox::error(0, i18n("There was a problem loading file: %1").arg(d.path()), i18n("Load Error"));
00473 m_doc_url.setFileName(i18n("Untitled"));
00474 m_bLoading = false;
00475 newDocument();
00476 return false;
00477 }
00478 if (filetype.endsWith(".mdl"))
00479 status = Import_Rose::loadFromMDL(file);
00480 else
00481 status = loadFromXMI( file, ENC_UNKNOWN );
00482 }
00483
00484 file.close();
00485 KIO::NetAccess::removeTempFile( tmpfile );
00486 if( !status )
00487 {
00488 KMessageBox::error(0, i18n("There was a problem loading file: %1").arg(d.path()), i18n("Load Error"));
00489 m_bLoading = false;
00490 newDocument();
00491 return false;
00492 }
00493 setModified(false);
00494 m_bLoading = false;
00495 initSaveTimer();
00496
00497 UMLApp::app()->enableUndo(false);
00498 clearUndoStack();
00499 addToUndoStack();
00500
00501 addDefaultStereotypes();
00502
00503 return true;
00504 }
00505
00506 bool UMLDoc::saveDocument(const KURL& url, const char * ) {
00507 m_doc_url = url;
00508 QDir d = m_doc_url.path(1);
00509 QFile file;
00510 bool uploaded = true;
00511
00512
00513 QString strFileName = url.path(-1);
00514 QFileInfo fileInfo(strFileName);
00515 QString fileExt = fileInfo.extension();
00516 QString fileFormat = "xmi";
00517 if (fileExt == "xmi" || fileExt == "bak.xmi")
00518 {
00519 fileFormat = "xmi";
00520 } else if (fileExt == "xmi.tgz" || fileExt == "bak.xmi.tgz") {
00521 fileFormat = "tgz";
00522 } else if (fileExt == "xmi.tar.bz2" || fileExt == "bak.xmi.tar.bz2") {
00523 fileFormat = "bz2";
00524 } else {
00525 fileFormat = "xmi";
00526 }
00527
00528 initSaveTimer();
00529
00530 if (fileFormat == "tgz" || fileFormat == "bz2")
00531 {
00532 KTar * archive;
00533 KTempFile tmp_tgz_file;
00534
00535
00536 if (url.isLocalFile())
00537 {
00538 if (fileFormat == "tgz")
00539 {
00540 archive = new KTar(d.path(), "application/x-gzip");
00541 } else {
00542 archive = new KTar(d.path(), "application/x-bzip2");
00543 }
00544 } else {
00545 if (fileFormat == "tgz")
00546 {
00547 archive = new KTar(tmp_tgz_file.name(), "application/x-gzip");
00548 } else {
00549 archive = new KTar(tmp_tgz_file.name(), "application/x-bzip2");
00550 }
00551 }
00552
00553
00554 if (archive->open(IO_WriteOnly) == false)
00555 {
00556 KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(d.path()), i18n("Save Error"));
00557 return false;
00558 }
00559
00560
00561
00562 KTempFile tmp_xmi_file;
00563 file.setName(tmp_xmi_file.name());
00564 if( !file.open( IO_WriteOnly ) ) {
00565 KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(d.path()), i18n("Save Error"));
00566 return false;
00567 }
00568 saveToXMI(file);
00569 file.close();
00570
00571
00572 QString tmpQString = url.fileName();
00573 if (fileFormat == "tgz")
00574 {
00575 tmpQString.replace(QRegExp("\\.tgz$"), "");
00576 } else {
00577 tmpQString.replace(QRegExp("\\.tar\\.bz2$"), "");
00578 }
00579 archive->addLocalFile(tmp_xmi_file.name(), tmpQString);
00580 archive->close();
00581
00582 #if KDE_IS_VERSION(3,4,89)
00583 if (!archive->closeSucceeded())
00584 {
00585 KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(d.path()), i18n("Save Error"));
00586 return false;
00587 }
00588 #endif
00589
00590 tmp_xmi_file.close();
00591 tmp_xmi_file.unlink();
00592
00593
00594 if ( !url.isLocalFile() ) {
00595 uploaded = KIO::NetAccess::upload( tmp_tgz_file.name(), m_doc_url,
00596 UMLApp::app() );
00597 }
00598
00599
00600
00601 tmp_tgz_file.close();
00602 tmp_tgz_file.unlink();
00603 delete archive;
00604
00605 } else {
00606
00607
00608 KTempFile tmpfile;
00609
00610
00611
00612
00613
00614
00616 file.setName( tmpfile.name() );
00617
00618
00619 if( !file.open( IO_WriteOnly ) ) {
00620 KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(d.path()), i18n("Save Error"));
00621 return false;
00622 }
00623 saveToXMI(file);
00624 file.close();
00625 tmpfile.close();
00626
00627
00628 if ( !url.isLocalFile() ) {
00629 uploaded = KIO::NetAccess::upload( tmpfile.name(), m_doc_url, UMLApp::app() );
00630 } else {
00631
00632 if ( KIO::NetAccess::file_move( tmpfile.name(), d.path(), -1, true ) == false ) {
00633 KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(d.path()), i18n("Save Error"));
00634 m_doc_url.setFileName(i18n("Untitled"));
00635 return false;
00636 }
00637 }
00638 }
00639 if( !uploaded )
00640 {
00641 KMessageBox::error(0, i18n("There was a problem uploading file: %1").arg(d.path()), i18n("Save Error"));
00642 m_doc_url.setFileName(i18n("Untitled"));
00643 }
00644 setModified(false);
00645 return uploaded;
00646 }
00647
00648 void UMLDoc::setupSignals() {
00649 WorkToolBar *tb = UMLApp::app() -> getWorkToolBar();
00650
00651
00652 connect(this, SIGNAL(sigDiagramChanged(Uml::Diagram_Type)), tb, SLOT(slotCheckToolBar(Uml::Diagram_Type)));
00653
00654
00655 return;
00656 }
00657
00658 UMLView * UMLDoc::findView(Uml::IDType id) {
00659 UMLView *v = NULL;
00660 for (int i = 0; i < Uml::N_MODELTYPES; i++) {
00661 v = m_root[i]->findView(id);
00662 if (v)
00663 break;
00664 }
00665 return v;
00666 }
00667
00668 UMLView * UMLDoc::findView(Diagram_Type type, const QString &name,
00669 bool searchAllScopes ) {
00670 Uml::Model_Type mt = Model_Utils::convert_DT_MT(type);
00671 return m_root[mt]->findView(type, name, searchAllScopes);
00672 }
00673
00674 UMLObject* UMLDoc::findObjectById(Uml::IDType id) {
00675 UMLObject *o = NULL;
00676 for (int i = 0; i < Uml::N_MODELTYPES; i++) {
00677 if (id == m_root[i]->getID())
00678 return m_root[i];
00679 o = m_root[i]->findObjectById(id);
00680 if (o)
00681 return o;
00682 }
00683 o = findStereotypeById(id);
00684 return o;
00685 }
00686
00687 UMLStereotype * UMLDoc::findStereotypeById(Uml::IDType id) {
00688 for (UMLStereotype *s = m_stereoList.first(); s; s = m_stereoList.next() ) {
00689 if (s->getID() == id)
00690 return s;
00691 }
00692 return NULL;
00693 }
00694
00695 UMLObject* UMLDoc::findUMLObject(const QString &name,
00696 Object_Type type ,
00697 UMLObject *currentObj ) {
00698 UMLObject *o = m_datatypeRoot->findObject(name);
00699 if (o)
00700 return o;
00701 for (int i = 0; i < Uml::N_MODELTYPES; i++) {
00702 UMLObjectList list = m_root[i]->containedObjects();
00703 o = Model_Utils::findUMLObject(list, name, type, currentObj);
00704 if (o)
00705 return o;
00706 if ((type == ot_UMLObject || type == ot_Folder) &&
00707 name == m_root[i]->getName())
00708 return m_root[i];
00709 }
00710 return NULL;
00711 }
00712
00713 UMLClassifier* UMLDoc::findUMLClassifier(const QString &name) {
00714
00715 UMLObject * obj = findUMLObject(name);
00716 return dynamic_cast<UMLClassifier*>(obj);
00717 }
00718
00724 bool UMLDoc::addUMLObject(UMLObject* object) {
00725 Object_Type ot = object->getBaseType();
00726 if (ot == ot_Attribute || ot == ot_Operation || ot == ot_EnumLiteral
00727 || ot == ot_EntityAttribute || ot == ot_Template || ot == ot_Stereotype) {
00728 kDebug() << "UMLDoc::addUMLObject(" << object->getName()
00729 << "): not adding type " << ot << endl;
00730 return false;
00731 }
00732 UMLPackage *pkg = object->getUMLPackage();
00733 if (pkg == NULL) {
00734 pkg = currentRoot();
00735 kDebug() << "UMLDoc::addUMLObject(" << object->getName()
00736 << "): no parent package set, assuming " << pkg->getName() << endl;
00737 object->setUMLPackage( pkg );
00738 }
00739 return pkg->addObject(object);
00740 }
00741
00742 void UMLDoc::addStereotype(const UMLStereotype *s) {
00743 if (! m_stereoList.contains(s))
00744 m_stereoList.append(s);
00745 }
00746
00747 void UMLDoc::removeStereotype(const UMLStereotype *s) {
00748 if (m_stereoList.contains(s))
00749 m_stereoList.remove(s);
00750 }
00751
00752 void UMLDoc::writeToStatusBar(const QString &text) {
00753 emit sigWriteToStatusBar(text);
00754 }
00755
00756
00757 void UMLDoc::slotRemoveUMLObject(UMLObject* object) {
00758
00759 UMLPackage *pkg = object->getUMLPackage();
00760 if (pkg == NULL) {
00761 kError() << "UMLDoc::slotRemoveUMLObject(" << object->getName()
00762 << "): parent package is not set !" << endl;
00763 return;
00764 }
00765 pkg->removeObject(object);
00766 }
00767
00768 bool UMLDoc::isUnique(const QString &name)
00769 {
00770 UMLListView *listView = UMLApp::app()->getListView();
00771 UMLListViewItem *currentItem = (UMLListViewItem*)listView->currentItem();
00772 UMLListViewItem *parentItem = 0;
00773
00774
00775
00776
00777 if(currentItem)
00778 {
00779
00780
00781 if (Model_Utils::typeIsContainer(currentItem->getType()))
00782 return isUnique (name, (UMLPackage*) currentItem->getUMLObject());
00783 parentItem = (UMLListViewItem*)currentItem->parent();
00784 }
00785
00786
00787 if (parentItem != NULL && Model_Utils::typeIsContainer(parentItem->getType())) {
00788 UMLPackage *parentPkg = static_cast<UMLPackage*>(parentItem->getUMLObject());
00789 return isUnique(name, parentPkg);
00790 }
00791
00792 kError() << "UMLDoc::isUnique(" << name << "): Not currently in a package"
00793 << endl;
00794
00795
00796
00797
00798
00799
00800
00801 return true;
00802 }
00803
00804 bool UMLDoc::isUnique(const QString &name, UMLPackage *package)
00805 {
00806
00807 if (package)
00808 return (package->findObject(name) == NULL);
00809
00810
00811 kError() << "UMLDoc::isUnique(2)(" << name << "): Not currently in a package"
00812 << endl;
00813
00814
00815
00816
00817
00818
00819
00820 return true;
00821 }
00822
00823 UMLStereotype* UMLDoc::findStereotype(const QString &name) {
00824 UMLStereotype *s;
00825 for (UMLStereotypeListIt it(m_stereoList); (s = it.current()) != NULL; ++it) {
00826 if (s->getName() == name)
00827 return s;
00828 }
00829 return NULL;
00830 }
00831
00832 UMLStereotype* UMLDoc::findOrCreateStereotype(const QString &name) {
00833 UMLStereotype *s = findStereotype(name);
00834 if (s != NULL) {
00835 return s;
00836 }
00837 s = new UMLStereotype(name, STR2ID(name));
00838 addStereotype(s);
00839
00840 return s;
00841 }
00842
00843 void UMLDoc::removeAssociation (UMLAssociation * assoc, bool doSetModified ) {
00844 if(!assoc)
00845 return;
00846
00847
00848 UMLPackage *pkg = assoc->getUMLPackage();
00849 if (pkg == NULL) {
00850 kError() << "UMLDoc::removeAssociation(" << assoc->getName()
00851 << "): parent package is not set !" << endl;
00852 return;
00853 }
00854 pkg->removeObject(assoc);
00855
00856 if (doSetModified)
00857 setModified(true, false);
00858 }
00859
00860 UMLAssociation * UMLDoc::findAssociation(Uml::Association_Type assocType,
00861 const UMLObject *roleAObj,
00862 const UMLObject *roleBObj,
00863 bool *swap)
00864 {
00865 UMLAssociationList assocs = getAssociations();
00866 UMLAssociation *a, *ret = NULL;
00867 for (a = assocs.first(); a; a = assocs.next()) {
00868 if (a->getAssocType() != assocType)
00869 continue;
00870 if (a->getObject(Uml::A) == roleAObj && a->getObject(Uml::B) == roleBObj)
00871 return a;
00872 if (a->getObject(Uml::A) == roleBObj && a->getObject(Uml::B) == roleAObj) {
00873 ret = a;
00874 }
00875 }
00876 if (swap)
00877 *swap = (ret != NULL);
00878 return ret;
00879 }
00880
00881
00882 UMLAssociation* UMLDoc::createUMLAssociation(UMLObject *a, UMLObject *b, Uml::Association_Type type)
00883 {
00884 bool swap;
00885 UMLAssociation *assoc = findAssociation(type, a, b, &swap);
00886 if (assoc == NULL) {
00887 assoc = new UMLAssociation(type, a, b );
00888 addAssociation(assoc);
00889 }
00890 return assoc;
00891 }
00892
00893 void UMLDoc::addAssociation(UMLAssociation *Assoc)
00894 {
00895 if (Assoc == NULL)
00896 return;
00897
00898
00899
00900
00901 UMLAssociationList assocs = getAssociations();
00902 for (UMLAssociationListIt ait(assocs); ait.current(); ++ait) {
00903 UMLAssociation *a = ait.current();
00904
00905
00906 if (a == Assoc)
00907 {
00908 kDebug() << "UMLDoc::addAssociation: duplicate addition attempted"
00909 << endl;
00910 return;
00911 }
00912 }
00913
00914
00915
00916
00917 UMLPackage *pkg = Assoc->getUMLPackage();
00918 if (pkg == NULL) {
00919 kError() << "UMLDoc::addAssociation(" << Assoc->getName()
00920 << "): parent package is not set !" << endl;
00921 return;
00922 }
00923 pkg->addObject(Assoc);
00924
00925
00926
00927
00928 setModified(true);
00929 }
00930
00931 QString UMLDoc::uniqViewName(const Diagram_Type type) {
00932 QString dname;
00933 if(type == dt_UseCase)
00934 dname = i18n("use case diagram");
00935 else if(type == dt_Class)
00936 dname = i18n("class diagram");
00937 else if(type == dt_Sequence)
00938 dname = i18n("sequence diagram");
00939 else if(type == dt_Collaboration)
00940 dname = i18n("collaboration diagram");
00941 else if( type == dt_State )
00942 dname = i18n( "state diagram" );
00943 else if( type == dt_Activity )
00944 dname = i18n( "activity diagram" );
00945 else if( type == dt_Component )
00946 dname = i18n( "component diagram" );
00947 else if( type == dt_Deployment )
00948 dname = i18n( "deployment diagram" );
00949 else if( type == dt_EntityRelationship )
00950 dname = i18n( "entity relationship diagram" );
00951 else {
00952 kWarning() << "uniqViewName() called with unknown diagram type" << endl;
00953 }
00954 QString name = dname;
00955 for (int number = 0; findView(type, name, true); ++number,
00956 name = dname + '_' + QString::number(number))
00957 ;
00958 return name;
00959 }
00960
00961 bool UMLDoc::loading() const {
00962 return m_bLoading;
00963 }
00964
00965 void UMLDoc::setLoading(bool state ) {
00966 m_bLoading = state;
00967 }
00968
00969 void UMLDoc::createDiagram(UMLFolder *folder, Diagram_Type type, bool askForName ) {
00970 bool ok = true;
00971 QString name,
00972 dname = uniqViewName(type);
00973
00974 while(true) {
00975 if (askForName) {
00976 name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), dname, &ok, (QWidget*)UMLApp::app());
00977 } else {
00978 name = dname;
00979 }
00980 if (!ok) {
00981 break;
00982 }
00983 if (name.length() == 0) {
00984 KMessageBox::error(0, i18n("That is an invalid name for a diagram."), i18n("Invalid Name"));
00985 } else if(!findView(type, name)) {
00986 UMLView* temp = new UMLView(folder);
00987 temp -> setOptionState( Settings::getOptionState() );
00988 temp->setName( name );
00989 temp->setType( type );
00990 temp->setID( UniqueID::gen() );
00991 addView(temp);
00992 emit sigDiagramCreated( temp->getID() );
00993 setModified(true, false);
00994 UMLApp::app()->enablePrint(true);
00995 changeCurrentView( temp->getID() );
00996 break;
00997 } else {
00998 KMessageBox::error(0, i18n("A diagram is already using that name."), i18n("Not a Unique Name"));
00999 }
01000 }
01001 }
01002
01003 void UMLDoc::renameDiagram(Uml::IDType id) {
01004 bool ok = false;
01005
01006 UMLView *temp = findView(id);
01007 Diagram_Type type = temp->getType();
01008
01009 QString oldName= temp->getName();
01010 while(true) {
01011 QString name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), oldName, &ok, (QWidget*)UMLApp::app());
01012
01013 if(!ok)
01014 break;
01015 if(name.length() == 0)
01016 KMessageBox::error(0, i18n("That is an invalid name for a diagram."), i18n("Invalid Name"));
01017 else if(!findView(type, name)) {
01018 temp->setName(name);
01019
01020 emit sigDiagramRenamed(id);
01021 setModified(true);
01022 break;
01023 } else
01024 KMessageBox::error(0, i18n("A diagram is already using that name."), i18n("Not a Unique Name"));
01025 }
01026 }
01027
01028 void UMLDoc::renameUMLObject(UMLObject *o) {
01029 bool ok = false;
01030 QString oldName= o->getName();
01031 while(true) {
01032 QString name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), oldName, &ok, (QWidget*)UMLApp::app());
01033 if(!ok)
01034 break;
01035 if(name.length() == 0)
01036 KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
01037 else if (isUnique(name)) {
01038 o->setName(name);
01039 setModified(true);
01040 break;
01041 } else {
01042 KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
01043 }
01044 }
01045 return;
01046 }
01047
01048 void UMLDoc::renameChildUMLObject(UMLObject *o) {
01049 bool ok = false;
01050 UMLClassifier* p = dynamic_cast<UMLClassifier *>(o->parent());
01051 if(!p) {
01052 kDebug() << "Can't create object, no parent found" << endl;
01053 return;
01054 }
01055
01056 QString oldName= o->getName();
01057 while(true) {
01058 QString name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), oldName, &ok, (QWidget*)UMLApp::app());
01059 if(!ok)
01060 break;
01061 if(name.length() == 0)
01062 KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
01063 else {
01064 if (p->findChildObject(name) == NULL
01065 || ((o->getBaseType() == Uml::ot_Operation) && KMessageBox::warningYesNo( kapp -> mainWidget() ,
01066 i18n( "The name you entered was not unique.\nIs this what you wanted?" ),
01067 i18n( "Name Not Unique"),i18n("Use Name"),i18n("Enter New Name")) == KMessageBox::Yes) ) {
01068 o->setName(name);
01069 setModified(true);
01070 break;
01071 } else {
01072 KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
01073 }
01074 }
01075 }
01076 }
01077
01078 void UMLDoc::changeCurrentView(Uml::IDType id) {
01079 UMLApp* pApp = UMLApp::app();
01080 UMLView* w = findView(id);
01081 if (w) {
01082 pApp->setCurrentView(w);
01083 emit sigDiagramChanged(w->getType());
01084 pApp->setDiagramMenuItemsState( true );
01085 setModified(true);
01086 }
01087 emit sigCurrentViewChanged();
01088 }
01089
01090 void UMLDoc::removeDiagram(Uml::IDType id) {
01091 UMLApp::app()->getDocWindow()->updateDocumentation(true);
01092 UMLView* umlview = findView(id);
01093 if(!umlview)
01094 {
01095 kError()<<"Request to remove diagram " << ID2STR(id) << ": Diagram not found!"<<endl;
01096 return;
01097 }
01098 if (KMessageBox::warningContinueCancel(0, i18n("Are you sure you want to delete diagram %1?").arg(umlview->getName()), i18n("Delete Diagram"),KGuiItem( i18n("&Delete"), "editdelete")) == KMessageBox::Continue) {
01099 removeView(umlview);
01100 emit sigDiagramRemoved(id);
01101 setModified(true);
01102
01103
01104
01105
01106
01107
01108 }
01109 }
01110
01111 UMLFolder *UMLDoc::currentRoot() {
01112 UMLView *currentView = UMLApp::app()->getCurrentView();
01113 if (currentView == NULL) {
01114 if (m_pCurrentRoot)
01115 return m_pCurrentRoot;
01116 kDebug() << "UMLDoc::currentRoot: currentView is NULL, assuming Logical View"
01117 << endl;
01118 return m_root[Uml::mt_Logical];
01119 }
01120 UMLFolder *f = currentView->getFolder();
01121 while (f->getUMLPackage()) {
01122 f = static_cast<UMLFolder*>(f->getUMLPackage());
01123 }
01124 return f;
01125 }
01126
01127 void UMLDoc::setCurrentRoot(Uml::Model_Type rootType) {
01128 m_pCurrentRoot = m_root[rootType];
01129 }
01130
01131 void UMLDoc::removeUMLObject(UMLObject* umlobject) {
01132 UMLApp::app()->getDocWindow()->updateDocumentation(true);
01133 Object_Type type = umlobject->getBaseType();
01134
01135 umlobject->setUMLStereotype(NULL);
01136 if (dynamic_cast<UMLClassifierListItem*>(umlobject)) {
01137 UMLClassifier* parent = dynamic_cast<UMLClassifier*>(umlobject->parent());
01138 if (parent == NULL) {
01139 kError() << "UMLDoc::removeUMLObject: parent of umlobject is NULL"
01140 << endl;
01141 return;
01142 }
01143 if (type == ot_Operation) {
01144 parent->removeOperation(static_cast<UMLOperation*>(umlobject));
01145 } else if (type == ot_EnumLiteral) {
01146 UMLEnum *e = static_cast<UMLEnum*>(parent);
01147 e->removeEnumLiteral(static_cast<UMLEnumLiteral*>(umlobject));
01148 } else if (type == ot_EntityAttribute) {
01149 UMLEntity *ent = static_cast<UMLEntity*>(parent);
01150 ent->removeEntityAttribute(static_cast<UMLClassifierListItem*>(umlobject));
01151 } else {
01152 UMLClassifier* pClass = dynamic_cast<UMLClassifier*>(parent);
01153 if (pClass == NULL) {
01154 kError() << "UMLDoc::removeUMLObject: parent of umlobject has "
01155 << "unexpected type " << parent->getBaseType() << endl;
01156 return;
01157 }
01158 if (type == ot_Attribute) {
01159 pClass->removeAttribute(static_cast<UMLAttribute*>(umlobject));
01160 } else if (type == ot_Template) {
01161 pClass->removeTemplate(static_cast<UMLTemplate*>(umlobject));
01162 } else {
01163 kError() << "UMLDoc::removeUMLObject: umlobject has "
01164 << "unexpected type " << type << endl;
01165 }
01166 }
01167 } else {
01168 if (type == ot_Association) {
01169 UMLAssociation *a = (UMLAssociation *)umlobject;
01170 removeAssociation(a, false);
01171 } else {
01172 UMLPackage* pkg = umlobject->getUMLPackage();
01173 if (pkg) {
01174 pkg->removeObject(umlobject);
01175 } else {
01176 kError() << "UMLDoc::removeUMLObject(" << umlobject->getName()
01177 << "): parent package is not set !" << endl;
01178 }
01179 }
01180 emit sigObjectRemoved(umlobject);
01181 }
01182 setModified(true);
01183 }
01184
01185 void UMLDoc::signalUMLObjectCreated(UMLObject * o) {
01186 emit sigObjectCreated(o);
01187
01188
01189
01190
01191
01192
01193 }
01194
01195 void UMLDoc::setName(const QString& name) {
01196 m_Name = name;
01197 }
01198
01199 QString UMLDoc::getName() const {
01200 return m_Name;
01201 }
01202
01203 Uml::IDType UMLDoc::getModelID() const {
01204 return m_modelID;
01205 }
01206
01207 void UMLDoc::saveToXMI(QIODevice& file) {
01208 QDomDocument doc;
01209
01210 QDomProcessingInstruction xmlHeading =
01211 doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
01212 doc.appendChild(xmlHeading);
01213
01214 QDomElement root = doc.createElement( "XMI" );
01215 root.setAttribute( "xmi.version", "1.2" );
01216 QDateTime now = QDateTime::currentDateTime();
01217 root.setAttribute( "timestamp", now.toString(Qt::ISODate));
01218 root.setAttribute( "verified", "false");
01219 root.setAttribute( "xmlns:UML", "http://schema.omg.org/spec/UML/1.3");
01220 doc.appendChild( root );
01221
01222 QDomElement header = doc.createElement( "XMI.header" );
01223 QDomElement meta = doc.createElement( "XMI.metamodel" );
01224 meta.setAttribute( "xmi.name", "UML" );
01225 meta.setAttribute( "xmi.version", "1.3" );
01226 meta.setAttribute( "href", "UML.xml" );
01227 header.appendChild( meta );
01228
01244 QDomElement documentation = doc.createElement( "XMI.documentation" );
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 QDomElement exporter = doc.createElement( "XMI.exporter" );
01256 exporter.appendChild( doc.createTextNode( "umbrello uml modeller http://uml.sf.net" ) );
01257 documentation.appendChild( exporter );
01258
01259 QDomElement exporterVersion = doc.createElement( "XMI.exporterVersion" );
01260 exporterVersion.appendChild( doc.createTextNode( XMI_FILE_VERSION ) );
01261 documentation.appendChild( exporterVersion );
01262
01263
01264
01265 QDomElement exporterEncoding = doc.createElement( "XMI.exporterEncoding" );
01266 exporterEncoding.appendChild( doc.createTextNode( "UnicodeUTF8" ) );
01267 documentation.appendChild( exporterEncoding );
01268
01269 header.appendChild( documentation );
01270
01275 header.appendChild( meta );
01276 root.appendChild( header );
01277
01278 QDomElement content = doc.createElement( "XMI.content" );
01279
01280 QDomElement contentNS = doc.createElement( "UML:Namespace.contents" );
01281
01282 QDomElement objectsElement = doc.createElement( "UML:Model" );
01283 objectsElement.setAttribute( "xmi.id", ID2STR(m_modelID) );
01284 objectsElement.setAttribute( "name", m_Name );
01285 objectsElement.setAttribute( "isSpecification", "false" );
01286 objectsElement.setAttribute( "isAbstract", "false" );
01287 objectsElement.setAttribute( "isRoot", "false" );
01288 objectsElement.setAttribute( "isLeaf", "false" );
01289
01290 QDomElement ownedNS = doc.createElement( "UML:Namespace.ownedElement" );
01291
01292
01293
01294
01295
01296 QStringList stereoNames;
01297 QValueList<Uml::IDType> stereoIDs;
01298 for (UMLStereotype *s = m_stereoList.first(); s; s = m_stereoList.next() ) {
01299 QString stName = s->getName();
01300 Uml::IDType stID = s->getID();
01301 if (!stereoNames.contains(stName) && !stereoIDs.contains(stID)) {
01302 s->saveToXMI(doc, ownedNS);
01303 stereoNames.append(stName);
01304 stereoIDs.append(stID);
01305 } else {
01306 kDebug() << "UMLDoc::saveToXMI: encountered duplicated stereotype "
01307 << stName << " (id " << ID2STR(stID) << "), see bug 144924" << endl;
01308 }
01309 }
01310 for (int i = 0; i < Uml::N_MODELTYPES; i++) {
01311 m_root[i]->saveToXMI(doc, ownedNS);
01312 }
01313
01314 objectsElement.appendChild( ownedNS );
01315
01316 content.appendChild( objectsElement );
01317
01318 root.appendChild( content );
01319
01320
01321 QDomElement extensions = doc.createElement( "XMI.extensions" );
01322 extensions.setAttribute( "xmi.extender", "umbrello" );
01323
01324 QDomElement docElement = doc.createElement( "docsettings" );
01325 Uml::IDType viewID = Uml::id_None;
01326 UMLView *currentView = UMLApp::app()->getCurrentView();
01327 if (currentView)
01328 viewID = currentView->getID();
01329 docElement.setAttribute( "viewid", ID2STR(viewID) );
01330 docElement.setAttribute( "documentation", m_Doc );
01331 docElement.setAttribute( "uniqueid", ID2STR(UniqueID::get()) );
01332 extensions.appendChild( docElement );
01333
01334
01335 UMLApp::app()->getListView()->saveToXMI(doc, extensions);
01336
01337
01338 CodeGenerator *codegen = UMLApp::app()->getGenerator();
01339 if (codegen) {
01340 QDomElement codeGenElement = doc.createElement( "codegeneration" );
01341 codegen->saveToXMI( doc, codeGenElement );
01342 extensions.appendChild( codeGenElement );
01343 }
01344
01345 root.appendChild( extensions );
01346
01347 QTextStream stream( &file );
01348 stream.setEncoding(QTextStream::UnicodeUTF8);
01349 stream << doc.toString();
01350 }
01351
01352 short UMLDoc::getEncoding(QIODevice & file)
01353 {
01354 QTextStream stream( &file );
01355 stream.setEncoding(QTextStream::UnicodeUTF8);
01356 QString data = stream.read();
01357 QString error;
01358 int line;
01359 QDomDocument doc;
01360 if( !doc.setContent( data, false, &error, &line ) )
01361 {
01362 kWarning()<<"Can't set content: "<<error<<" Line: "<<line<<endl;
01363 return ENC_UNKNOWN;
01364 }
01365
01366
01367
01368 QDomNode node = doc.firstChild();
01369 while (node.isComment() || node.isProcessingInstruction())
01370 {
01371 node = node.nextSibling();
01372 }
01373 QDomElement root = node.toElement();
01374 if( root.isNull() )
01375 {
01376 return ENC_UNKNOWN;
01377 }
01378
01379 if( root.tagName() != "XMI" )
01380 {
01381 return ENC_UNKNOWN;
01382 }
01383 node = node.firstChild();
01384
01385 if ( node.isNull() )
01386 return ENC_UNKNOWN;
01387
01388 QDomElement element = node.toElement();
01389
01390 if( element.isNull() || element.tagName() != "XMI.header" )
01391 return ENC_UNKNOWN;
01392
01393 QDomNode headerNode = node.firstChild();
01394 while ( !headerNode.isNull() )
01395 {
01396 QDomElement headerElement = headerNode.toElement();
01397
01398
01399 if (headerElement.isNull() ||
01400 headerElement.tagName() != "XMI.documentation") {
01401 headerNode = headerNode.nextSibling();
01402 continue;
01403 }
01404 QDomNode docuNode = headerNode.firstChild();
01405 while ( !docuNode.isNull() )
01406 {
01407 QDomElement docuElement = docuNode.toElement();
01408
01409
01410 if (! docuElement.isNull() &&
01411 docuElement.tagName() == "XMI.exporterEncoding")
01412 {
01413
01414
01415 if (docuElement.text() == QString("UnicodeUTF8"))
01416 {
01417 return ENC_UNICODE;
01418 }
01419 }
01420 docuNode = docuNode.nextSibling();
01421 }
01422 break;
01423 }
01424 return ENC_OLD_ENC;
01425 }
01426
01427 bool UMLDoc::loadFromXMI( QIODevice & file, short encode )
01428 {
01429
01430
01431
01432
01433 if (encode == ENC_UNKNOWN)
01434 {
01435 if ((encode = getEncoding(file)) == ENC_UNKNOWN)
01436 return false;
01437 file.reset();
01438 }
01439 QTextStream stream( &file );
01440 if (encode == ENC_UNICODE)
01441 {
01442 stream.setEncoding(QTextStream::UnicodeUTF8);
01443 }
01444
01445 QString data = stream.read();
01446 kapp->processEvents();
01447 QString error;
01448 int line;
01449 QDomDocument doc;
01450 if( !doc.setContent( data, false, &error, &line ) ) {
01451 kWarning()<<"Can't set content:"<<error<<" Line:"<<line<<endl;
01452 return false;
01453 }
01454 kapp->processEvents();
01455 QDomNode node = doc.firstChild();
01456
01457
01458 while (node.isComment() || node.isProcessingInstruction()) {
01459 node = node.nextSibling();
01460 }
01461
01462 QDomElement root = node.toElement();
01463 if( root.isNull() ) {
01464 return false;
01465 }
01466
01467 if( root.tagName() != "XMI" ) {
01468 return false;
01469 }
01470
01471 m_nViewID = Uml::id_None;
01472 for (node = node.firstChild(); !node.isNull(); node = node.nextSibling()) {
01473 if (node.isComment())
01474 continue;
01475 QDomElement element = node.toElement();
01476 if (element.isNull()) {
01477 kDebug() << "loadFromXMI: skip empty elem" << endl;
01478 continue;
01479 }
01480 bool recognized = false;
01481 QString outerTag = element.tagName();
01482
01483 if (outerTag == "XMI.header") {
01484 QDomNode headerNode = node.firstChild();
01485 if ( !validateXMIHeader(headerNode) ) {
01486 return false;
01487 }
01488 recognized = true;
01489 } else if (outerTag == "XMI.extensions") {
01490 QDomNode extensionsNode = node.firstChild();
01491 while (! extensionsNode.isNull()) {
01492 loadExtensionsFromXMI(extensionsNode);
01493 extensionsNode = extensionsNode.nextSibling();
01494 }
01495 recognized = true;
01496 }
01497 if (outerTag != "XMI.content" ) {
01498 if (!recognized)
01499 kDebug() << "UMLDoc::loadFromXMI: skipping <"
01500 << outerTag << ">" << endl;
01501 continue;
01502 }
01503 bool seen_UMLObjects = false;
01504
01505 for (QDomNode child = node.firstChild(); !child.isNull();
01506 child = child.nextSibling()) {
01507 if (child.isComment())
01508 continue;
01509 element = child.toElement();
01510 QString tag = element.tagName();
01511 if (tag == "umlobjects"
01512 || tagEq(tag, "Subsystem")
01513 || tagEq(tag, "Model") ) {
01514 if( !loadUMLObjectsFromXMI( element ) ) {
01515 kWarning() << "failed load on objects" << endl;
01516 return false;
01517 }
01518 m_Name = element.attribute( "name", i18n("UML Model") );
01519 UMLListView *lv = UMLApp::app()->getListView();
01520 lv->setColumnText(0, m_Name);
01521 seen_UMLObjects = true;
01522 } else if (tagEq(tag, "Package") ||
01523 tagEq(tag, "Class") ||
01524 tagEq(tag, "Interface")) {
01525
01526
01527 QDomElement parentElem = node.toElement();
01528 if( !loadUMLObjectsFromXMI( parentElem ) ) {
01529 kWarning() << "failed load on model objects" << endl;
01530 return false;
01531 }
01532 seen_UMLObjects = true;
01533 } else if (tagEq(tag, "TaggedValue")) {
01534
01535
01536 if (! seen_UMLObjects) {
01537 kDebug() << "skipping TaggedValue because not seen_UMLObjects"
01538 << endl;
01539 continue;
01540 }
01541 tag = element.attribute("tag", "");
01542 if (tag != "documentation") {
01543 continue;
01544 }
01545 QString modelElement = element.attribute("modelElement", "");
01546 if (modelElement.isEmpty()) {
01547 kDebug() << "skipping TaggedValue(documentation) because "
01548 << "modelElement.isEmpty()" << endl;
01549 continue;
01550 }
01551 UMLObject *o = findObjectById(STR2ID(modelElement));
01552 if (o == NULL) {
01553 kDebug() << "TaggedValue(documentation): cannot find object"
01554 << " for modelElement " << modelElement << endl;
01555 continue;
01556 }
01557 QString value = element.attribute("value", "");
01558 if (! value.isEmpty())
01559 o->setDoc(value);
01560 } else {
01561
01562 loadExtensionsFromXMI(child);
01563 }
01564 }
01565 }
01566 #ifdef VERBOSE_DEBUGGING
01567 kDebug() << "UMLDoc::m_objectList.count() is " << m_objectList.count() << endl;
01568 #endif
01569 resolveTypes();
01570
01571 if (UMLApp::app()->getGenerator() == NULL)
01572 UMLApp::app()->setGenerator(UMLApp::app()->getDefaultLanguage());
01573 emit sigWriteToStatusBar( i18n("Setting up the document...") );
01574 kapp->processEvents();
01575 activateAllViews();
01576
01577 UMLView *viewToBeSet = NULL;
01578 if (m_nViewID != Uml::id_None)
01579 viewToBeSet = findView( m_nViewID );
01580 if (viewToBeSet) {
01581 changeCurrentView( m_nViewID );
01582 Settings::OptionState optionState = Settings::getOptionState();
01583 if (optionState.generalState.tabdiagrams) {
01584 UMLApp::app()->tabWidget()->showPage(viewToBeSet);
01585 }
01586 } else {
01587 createDiagram(m_root[mt_Logical], Uml::dt_Class, false);
01588 m_pCurrentRoot = m_root[mt_Logical];
01589 }
01590 emit sigResetStatusbarProgress();
01591 return true;
01592 }
01593
01594 void UMLDoc::resolveTypes() {
01595
01596
01597 if (m_bTypesAreResolved)
01598 return;
01599 m_bTypesAreResolved = true;
01600 writeToStatusBar( i18n("Resolving object references...") );
01601 for (int i = 0; i < Uml::N_MODELTYPES; i++) {
01602 UMLFolder *obj = m_root[i];
01603 #ifdef VERBOSE_DEBUGGING
01604 kDebug() << "UMLDoc: invoking resolveRef() for " << obj->getName()
01605 << " (id=" << ID2STR(obj->getID()) << ")" << endl;
01606 #endif
01607 obj->resolveRef();
01608 }
01609 kapp->processEvents();
01610 }
01611
01612 bool UMLDoc::validateXMIHeader(QDomNode& headerNode) {
01613 QDomElement headerElement = headerNode.toElement();
01614 while ( !headerNode.isNull() ) {
01615
01616
01617
01618
01619
01620
01621
01622
01623 headerNode = headerNode.nextSibling();
01624 headerElement = headerNode.toElement();
01625 }
01626 return true;
01627 }
01628
01629 bool UMLDoc::loadUMLObjectsFromXMI(QDomElement& element) {
01630
01631
01632
01633
01634
01635
01636
01637
01638 emit sigWriteToStatusBar( i18n("Loading UML elements...") );
01639
01640 for (QDomNode node = element.firstChild(); !node.isNull();
01641 node = node.nextSibling()) {
01642 if (node.isComment())
01643 continue;
01644 QDomElement tempElement = node.toElement();
01645 QString type = tempElement.tagName();
01646 if (tagEq(type, "Model")) {
01647 bool foundUmbrelloRootFolder = false;
01648 QString name = tempElement.attribute("name");
01649 for (int i = 0; i < Uml::N_MODELTYPES; i++) {
01650 if (name == m_root[i]->getName()) {
01651 m_pCurrentRoot = m_root[i];
01652 m_root[i]->loadFromXMI(tempElement);
01653 foundUmbrelloRootFolder = true;
01654 break;
01655 }
01656 }
01657 if (foundUmbrelloRootFolder)
01658 continue;
01659 }
01660
01661 if (tagEq(type, "Namespace.ownedElement") ||
01662 tagEq(type, "Namespace.contents") ||
01663 tagEq(type, "Model") || tagEq(type, "ModelElement.stereotype")) {
01664
01665
01666
01667
01668 if( !loadUMLObjectsFromXMI( tempElement ) ) {
01669 if (! tagEq(type, "ModelElement.stereotype")) {
01670 kWarning() << "failed load on " << type << endl;
01671 return false;
01672 }
01673 }
01674 continue;
01675 }
01676 if (Model_Utils::isCommonXMIAttribute(type))
01677 continue;
01678 if (! tempElement.hasAttribute("xmi.id")) {
01679 QString idref = tempElement.attribute("xmi.idref", "");
01680 if (! idref.isEmpty()) {
01681 kDebug() << "resolution of xmi.idref " << idref
01682 << " is not yet implemented" << endl;
01683 } else {
01684 kError() << "Cannot load " << type
01685 << " because xmi.id is missing" << endl;
01686 }
01687 continue;
01688 }
01689 QString stID = tempElement.attribute("stereotype", "");
01690 UMLObject *pObject = Object_Factory::makeObjectFromXMI(type, stID);
01691 if( !pObject ) {
01692 kWarning() << "Unknown type of umlobject to create: " << type << endl;
01693
01694
01695 continue;
01696 }
01697 Uml::Object_Type ot = pObject->getBaseType();
01698
01699 UMLPackage *pkg = NULL;
01700 if (ot == Uml::ot_Datatype) {
01701 pkg = m_datatypeRoot;
01702 } else {
01703 Uml::Model_Type guess = Model_Utils::guessContainer(pObject);
01704 if (guess != Uml::N_MODELTYPES)
01705 pkg = m_root[guess];
01706 }
01707 pObject->setUMLPackage(pkg);
01708
01709 bool status = pObject -> loadFromXMI( tempElement );
01710 if ( !status ) {
01711
01712
01713
01714 kError() << "loadFromXMI failed for " << pObject->getName() << " xmi.id="
01715 << ID2STR(pObject->getID()) << endl;
01716 continue;
01717 }
01718 pkg = pObject->getUMLPackage();
01719 if (ot == ot_Stereotype) {
01720 UMLStereotype *s = static_cast<UMLStereotype*>(pObject);
01721 UMLStereotype *exist = findStereotype(pObject->getName());
01722 if (exist) {
01723 if (exist->getID() == pObject->getID()) {
01724 delete pObject;
01725 } else {
01726 kDebug() << "Stereotype " << pObject->getName()
01727 << "(id=" << ID2STR(pObject->getID())
01728 << ") already exists with id="
01729 << ID2STR(exist->getID()) << endl;
01730 addStereotype(s);
01731 }
01732 } else {
01733 addStereotype(s);
01734 }
01735 continue;
01736 }
01737 if (pkg == NULL)
01738 kError() << "UMLDoc::loadUMLObjectsFromXMI: pkg is NULL for "
01739 << pObject->getName() << " xmi.id="
01740 << ID2STR(pObject->getID()) << endl;
01741 else
01742 pkg->addObject(pObject);
01743
01744
01745
01746
01747 }
01748 return true;
01749 }
01750
01751 void UMLDoc::setMainViewID(Uml::IDType viewID) {
01752 m_nViewID = viewID;
01753 }
01754
01755 void UMLDoc::loadExtensionsFromXMI(QDomNode& node) {
01756 QDomElement element = node.toElement();
01757 QString tag = element.tagName();
01758
01759 if (tag == "docsettings") {
01760 QString viewID = element.attribute( "viewid", "-1" );
01761 m_Doc = element.attribute( "documentation", "" );
01762 QString uniqueid = element.attribute( "uniqueid", "0" );
01763
01764 m_nViewID = STR2ID(viewID);
01765 UniqueID::set(STR2ID(uniqueid));
01766 UMLApp::app()->getDocWindow() -> newDocumentation();
01767
01768 } else if (tag == "diagrams" || tag == "UISModelElement") {
01769
01770
01771 QDomNode diagramNode = node.firstChild();
01772 if (tag == "UISModelElement") {
01773 element = diagramNode.toElement();
01774 tag = element.tagName();
01775 if (tag != "uisOwnedDiagram") {
01776 kError() << "unknown child node " << tag << endl;
01777 return;
01778 }
01779 diagramNode = diagramNode.firstChild();
01780 }
01781 if( !loadDiagramsFromXMI( diagramNode ) ) {
01782 kWarning() << "failed load on diagrams" << endl;
01783 }
01784
01785 } else if (tag == "listview") {
01786
01787
01788 resolveTypes();
01789 if( !UMLApp::app()->getListView() -> loadFromXMI( element ) ) {
01790 kWarning() << "failed load on listview" << endl;
01791 }
01792
01793 } else if (tag == "codegeneration") {
01794 QDomNode cgnode = node.firstChild();
01795 QDomElement cgelement = cgnode.toElement();
01796 while( !cgelement.isNull() ) {
01797 QString nodeName = cgelement.tagName();
01798 QString lang = cgelement.attribute("language","UNKNOWN");
01799 Uml::Programming_Language pl = Model_Utils::stringToProgLang(lang);
01800 CodeGenerator *g = UMLApp::app()->setGenerator(pl);
01801 g->loadFromXMI(cgelement);
01802 cgnode = cgnode.nextSibling();
01803 cgelement = cgnode.toElement();
01804 }
01805 if (UMLApp::app()->getGenerator() == NULL)
01806 UMLApp::app()->setGenerator(UMLApp::app()->getDefaultLanguage());
01807 }
01808 }
01809
01810
01811
01812 bool UMLDoc::loadDiagramsFromXMI( QDomNode & node ) {
01813 emit sigWriteToStatusBar( i18n("Loading diagrams...") );
01814 emit sigResetStatusbarProgress();
01815 emit sigSetStatusbarProgress( 0 );
01816 emit sigSetStatusbarProgressSteps( 10 );
01817 QDomElement element = node.toElement();
01818 if( element.isNull() )
01819 return true;
01820 const Settings::OptionState state = Settings::getOptionState();
01821 UMLView * pView = 0;
01822 int count = 0;
01823 while( !element.isNull() ) {
01824 QString tag = element.tagName();
01825 if (tag == "diagram" || tag == "UISDiagram") {
01826 pView = new UMLView(NULL);
01827
01828
01829
01830
01831 pView -> setOptionState( state );
01832 bool success = false;
01833 if (tag == "UISDiagram") {
01834 success = pView->loadUISDiagram(element);
01835 } else {
01836 success = pView->loadFromXMI(element);
01837 }
01838 if (!success) {
01839 kWarning() << "failed load on viewdata loadfromXMI" << endl;
01840 delete pView;
01841 return false;
01842 }
01843
01844
01845 Uml::Model_Type mt = Model_Utils::convert_DT_MT(pView->getType());
01846 pView->setFolder(m_root[mt]);
01847 pView -> hide();
01848 addView( pView );
01849 emit sigSetStatusbarProgress( ++count );
01850 kapp->processEvents();
01851 }
01852 node = node.nextSibling();
01853 element = node.toElement();
01854 }
01855 return true;
01856 }
01857
01858 void UMLDoc::removeAllViews() {
01859 for (int i = 0; i < Uml::N_MODELTYPES; i++)
01860 m_root[i]->removeAllViews();
01861 UMLApp::app()->setCurrentView(NULL);
01862 emit sigDiagramChanged(dt_Undefined);
01863 UMLApp::app()->setDiagramMenuItemsState(false);
01864 }
01865
01866 UMLClassifierList UMLDoc::getConcepts(bool includeNested ) {
01867 UMLClassifierList conceptList;
01868 m_root[mt_Logical]->appendClassifiers(conceptList, includeNested);
01869 return conceptList;
01870 }
01871
01872 UMLClassifierList UMLDoc::getClasses(bool includeNested ) {
01873 UMLClassifierList conceptList;
01874 m_root[mt_Logical]->appendClasses(conceptList, includeNested);
01875 return conceptList;
01876 }
01877
01878 UMLClassifierList UMLDoc::getClassesAndInterfaces(bool includeNested ) {
01879 UMLClassifierList conceptList;
01880 m_root[mt_Logical]->appendClassesAndInterfaces(conceptList, includeNested);
01881 return conceptList;
01882 }
01883
01884 UMLClassifierList UMLDoc::getInterfaces(bool includeNested ) {
01885 UMLClassifierList interfaceList;
01886 m_root[mt_Logical]->appendInterfaces(interfaceList, includeNested);
01887 return interfaceList;
01888 }
01889
01890 UMLClassifierList UMLDoc::getDatatypes() {
01891 UMLObjectList objects = m_datatypeRoot->containedObjects();
01892 UMLClassifierList datatypeList;
01893 UMLObject *obj;
01894 for (UMLObjectListIt oit(objects); (obj = oit.current()) != NULL; ++oit) {
01895 if (obj->getBaseType() == ot_Datatype) {
01896 datatypeList.append(static_cast<UMLClassifier*>(obj));
01897 }
01898 }
01899 return datatypeList;
01900 }
01901
01902 UMLAssociationList UMLDoc::getAssociations() {
01903 UMLAssociationList associationList;
01904 for (int i = 0; i < Uml::N_MODELTYPES; i++) {
01905 UMLAssociationList assocs = m_root[i]->getAssociations();
01906 UMLAssociation *a;
01907 for (UMLAssociationListIt ait(assocs); (a = ait.current()) != NULL; ++ait)
01908 associationList.append(a);
01909 }
01910 return associationList;
01911 }
01912
01913 void UMLDoc::print(KPrinter * pPrinter) {
01914 UMLView * printView = 0;
01915 int count = QString(pPrinter -> option("kde-uml-count")).toInt();
01916 QPainter painter(pPrinter);
01917 for(int i = 0;i < count;i++) {
01918 if(i>0)
01919 pPrinter -> newPage();
01920 QString diagram = i18n("kde-uml-Diagram") + QString("%1").arg(i);
01921 QString sID = pPrinter -> option(diagram);
01922 Uml::IDType id = STR2ID(sID);
01923 printView = findView(id);
01924
01925 if(printView)
01926 printView ->print(pPrinter, painter);
01927 printView = 0;
01928 }
01929 painter.end();
01930 }
01931
01932 UMLViewList UMLDoc::getViewIterator() {
01933 UMLViewList accumulator;
01934 for (int i = 0; i < Uml::N_MODELTYPES; i++)
01935 m_root[i]->appendViews(accumulator, true);
01936 return accumulator;
01937 }
01938
01939 void UMLDoc::setModified(bool modified , bool addToUndo ) {
01940 if(!m_bLoading) {
01941 m_modified = modified;
01942 UMLApp::app()->setModified(modified);
01943
01944 if (modified && addToUndo) {
01945 addToUndoStack();
01946 clearRedoStack();
01947 }
01948 }
01949 }
01950
01951 bool UMLDoc::assignNewIDs(UMLObject* Obj) {
01952 if(!Obj || !m_pChangeLog) {
01953 kDebug() << "no Obj || Changelog" << endl;
01954 return false;
01955 }
01956 Uml::IDType result = assignNewID(Obj->getID());
01957 Obj->setID(result);
01958
01959
01960 if(Obj->getBaseType() == ot_Class ) {
01961 UMLClassifier *c = static_cast<UMLClassifier*>(Obj);
01962 UMLClassifierListItemList attributes = c->getFilteredList(ot_Attribute);
01963 for(UMLObject* listItem = attributes.first(); listItem; listItem = attributes.next()) {
01964 result = assignNewID(listItem->getID());
01965 listItem->setID(result);
01966 }
01967
01968 UMLClassifierListItemList templates = c->getFilteredList(ot_Template);
01969 for(UMLObject* listItem = templates.first(); listItem; listItem = templates.next()) {
01970 result = assignNewID(listItem->getID());
01971 listItem->setID(result);
01972 }
01973 }
01974
01975 if(Obj->getBaseType() == ot_Interface || Obj->getBaseType() == ot_Class ) {
01976 UMLOperationList operations(((UMLClassifier*)Obj)->getOpList());
01977 for(UMLObject* listItem = operations.first(); listItem; listItem = operations.next()) {
01978 result = assignNewID(listItem->getID());
01979 listItem->setID(result);
01980 }
01981 }
01982
01983 setModified(true);
01984
01985 return true;
01986 }
01987
01988 UMLFolder *UMLDoc::getRootFolder(Uml::Model_Type mt) {
01989 if (mt < Uml::mt_Logical || mt >= Uml::N_MODELTYPES) {
01990 kError() << "UMLDoc::getRootFolder: illegal input value " << mt << endl;
01991 return NULL;
01992 }
01993 return m_root[mt];
01994 }
01995
01996 Uml::Model_Type UMLDoc::rootFolderType(UMLObject *obj) {
01997 for (int i = 0; i < Uml::N_MODELTYPES; i++) {
01998 const Uml::Model_Type m = (Uml::Model_Type)i;
01999 if (obj == m_root[m])
02000 return m;
02001 }
02002 return Uml::N_MODELTYPES;
02003 }
02004
02006 IDChangeLog* UMLDoc::getChangeLog() {
02007 return m_pChangeLog;
02008 }
02009
02013 void UMLDoc::beginPaste() {
02014 if(m_pChangeLog) {
02015 delete m_pChangeLog;
02016 m_pChangeLog = 0;
02017 }
02018 m_pChangeLog = new IDChangeLog;
02019 }
02020
02023 void UMLDoc::endPaste() {
02024 if(m_pChangeLog) {
02025 delete m_pChangeLog;
02026 m_pChangeLog = 0;
02027 }
02028 }
02029
02032 Uml::IDType UMLDoc::assignNewID(Uml::IDType OldID) {
02033 Uml::IDType result = UniqueID::gen();
02034 if (m_pChangeLog) {
02035 m_pChangeLog->addIDChange(OldID, result);
02036 }
02037 return result;
02038 }
02039
02044 bool UMLDoc::addUMLView(UMLView * pView ) {
02045 if(!pView || !m_pChangeLog)
02046 return false;
02047
02048 int i = 0;
02049 QString viewName = (QString)pView->getName();
02050 QString name = viewName;
02051 while( findView(pView->getType(), name) != NULL) {
02052 name = viewName + '_' + QString::number(++i);
02053 }
02054 if(i)
02055 pView->setName(name);
02056 Uml::IDType result = assignNewID(pView->getID());
02057 pView->setID(result);
02058
02059 pView->activateAfterLoad( true );
02060 pView->endPartialWidgetPaste();
02061 pView->setOptionState( Settings::getOptionState() );
02062 addView(pView);
02063 setModified(true);
02064 return true;
02065 }
02066
02067 void UMLDoc::activateAllViews() {
02068
02069 bool m_bLoading_old = m_bLoading;
02070 m_bLoading = true;
02071
02072 for (int i = 0; i < Uml::N_MODELTYPES; i++)
02073 m_root[i]->activateViews();
02074 m_bLoading = m_bLoading_old;
02075 }
02076
02077 void UMLDoc::settingsChanged(Settings::OptionState optionState) {
02078 for (int i = 0; i < Uml::N_MODELTYPES; i++)
02079 m_root[i]->setViewOptions(optionState);
02080 initSaveTimer();
02081 }
02082
02083 void UMLDoc::initSaveTimer() {
02084 if( m_pAutoSaveTimer ) {
02085 m_pAutoSaveTimer -> stop();
02086 disconnect( m_pAutoSaveTimer, SIGNAL( timeout() ), this, SLOT( slotAutoSave() ) );
02087 delete m_pAutoSaveTimer;
02088 m_pAutoSaveTimer = 0;
02089 }
02090 Settings::OptionState optionState = Settings::getOptionState();
02091 if( optionState.generalState.autosave ) {
02092 m_pAutoSaveTimer = new QTimer(this, "_AUTOSAVETIMER_" );
02093 connect( m_pAutoSaveTimer, SIGNAL( timeout() ), this, SLOT( slotAutoSave() ) );
02094 m_pAutoSaveTimer->start( optionState.generalState.autosavetime * 60000, false );
02095 }
02096 return;
02097 }
02098
02099 void UMLDoc::slotAutoSave() {
02100
02101 if( !m_modified ) {
02102 return;
02103 }
02104 KURL tempURL = m_doc_url;
02105 if( tempURL.fileName() == i18n("Untitled") ) {
02106 tempURL.setPath( QDir::homeDirPath() + i18n("/autosave%1").arg(".xmi") );
02107 saveDocument( tempURL );
02108 m_doc_url.setFileName( i18n("Untitled") );
02109 m_modified = true;
02110 UMLApp::app()->setModified( m_modified );
02111 } else {
02112
02113 KURL orgDocUrl = m_doc_url;
02114 QString orgFileName = m_doc_url.fileName();
02115
02116 QString fileName = tempURL.fileName();
02117 Settings::OptionState optionState = Settings::getOptionState();
02118 fileName.replace( ".xmi", optionState.generalState.autosavesuffix );
02119 tempURL.setFileName( fileName );
02120
02121
02122 saveDocument( tempURL );
02123
02124
02125
02126 if ( ".xmi" != optionState.generalState.autosavesuffix ) {
02127 m_modified = true;
02128 UMLApp::app()->setModified( m_modified );
02129 }
02130
02131
02132 setURL( orgDocUrl );
02133 UMLApp * pApp = UMLApp::app();
02134 pApp->setCaption(orgFileName, isModified() );
02135
02136 }
02137 }
02138
02139 void UMLDoc::signalDiagramRenamed(UMLView* pView ) {
02140 Settings::OptionState optionState = Settings::getOptionState();
02141 if (optionState.generalState.tabdiagrams)
02142 UMLApp::app()->tabWidget()->setTabLabel( pView, pView->getName() );
02143 emit sigDiagramRenamed( pView -> getID() );
02144 }
02145
02146 void UMLDoc::addToUndoStack() {
02147 Settings::OptionState optionState = Settings::getOptionState();
02148 if (!m_bLoading && optionState.generalState.undo) {
02149 QBuffer* buffer = new QBuffer();
02150 buffer->open(IO_WriteOnly);
02151 QDataStream* undoData = new QDataStream();
02152 undoData->setDevice(buffer);
02153 saveToXMI(*buffer);
02154 buffer->close();
02155 undoStack.prepend(undoData);
02156
02157 if (undoStack.count() > 1) {
02158 UMLApp::app()->enableUndo(true);
02159 }
02160 }
02161 }
02162
02163 void UMLDoc::clearUndoStack() {
02164 undoStack.setAutoDelete(true);
02165 undoStack.clear();
02166 UMLApp::app()->enableRedo(false);
02167 undoStack.setAutoDelete(false);
02168 clearRedoStack();
02169 }
02170
02171 void UMLDoc::clearRedoStack() {
02172 redoStack.setAutoDelete(true);
02173 redoStack.clear();
02174 UMLApp::app()->enableRedo(false);
02175 redoStack.setAutoDelete(false);
02176 }
02177
02178 void UMLDoc::loadUndoData() {
02179 if (undoStack.count() < 1) {
02180 kWarning() << "no data in undostack" << endl;
02181 return;
02182 }
02183 UMLView *currentView = UMLApp::app()->getCurrentView();
02184 if (currentView == NULL) {
02185 kWarning() << "UMLDoc::loadUndoData: currentView is NULL" << endl;
02186 undoStack.setAutoDelete(true);
02187 undoStack.clear();
02188 undoStack.setAutoDelete(false);
02189 UMLApp::app()->enableUndo(false);
02190 return;
02191 }
02192 Uml::IDType currentViewID = currentView->getID();
02193
02194 bool m_bLoading_old = m_bLoading;
02195 m_bLoading = true;
02196 closeDocument();
02197 redoStack.prepend( undoStack.take(0) );
02198 QDataStream* undoData = undoStack.getFirst();
02199 QBuffer* buffer = static_cast<QBuffer*>( undoData->device() );
02200 buffer->open(IO_ReadOnly);
02201 loadFromXMI(*buffer);
02202 buffer->close();
02203
02204 setModified(true, false);
02205 m_bLoading = m_bLoading_old;
02206
02207 undoStack.setAutoDelete(true);
02208 if (undoStack.count() <= 1) {
02209 UMLApp::app()->enableUndo(false);
02210 }
02211 if (redoStack.count() >= 1) {
02212 UMLApp::app()->enableRedo(true);
02213 }
02214 while (undoStack.count() > undoMax) {
02215 undoStack.removeLast();
02216 }
02217 undoStack.setAutoDelete(false);
02218
02219 currentView = UMLApp::app()->getCurrentView();
02220 if (currentView) {
02221 if (currentView->getID() != currentViewID)
02222 changeCurrentView( currentView->getID() );
02223 currentView->resizeCanvasToItems();
02224 }
02225 }
02226
02227 void UMLDoc::loadRedoData() {
02228 if (redoStack.count() >= 1) {
02229 UMLView *currentView = UMLApp::app()->getCurrentView();
02230 Uml::IDType currentViewID = currentView->getID();
02231
02232 bool m_bLoading_old = m_bLoading;
02233 m_bLoading = true;
02234 closeDocument();
02235 undoStack.prepend( redoStack.getFirst() );
02236 QDataStream* redoData = redoStack.getFirst();
02237 redoStack.removeFirst();
02238 QBuffer* buffer = static_cast<QBuffer*>( redoData->device() );
02239 buffer->open(IO_ReadOnly);
02240 loadFromXMI(*buffer);
02241 buffer->close();
02242
02243 setModified(true, false);
02244 currentView = UMLApp::app()->getCurrentView();
02245 currentView->resizeCanvasToItems();
02246 m_bLoading = m_bLoading_old;
02247
02248 redoStack.setAutoDelete(true);
02249 if (redoStack.count() < 1) {
02250 UMLApp::app()->enableRedo(false);
02251 }
02252 if (undoStack.count() > 1) {
02253 UMLApp::app()->enableUndo(true);
02254 }
02255 if (currentView->getID() != currentViewID) {
02256 changeCurrentView(currentViewID);
02257 }
02258 redoStack.setAutoDelete(false);
02259 } else {
02260 kWarning() << "no data in redostack" << endl;
02261 }
02262 }
02263
02264 void UMLDoc::addDefaultDatatypes() {
02265 CodeGenerator *cg = UMLApp::app()->getGenerator();
02266 if (cg == NULL) {
02267 kDebug() << "UMLDoc::addDefaultDatatypes: CodeGenerator is still NULL"
02268 << endl;
02269 return;
02270 }
02271 QStringList entries = cg->defaultDatatypes();
02272 QStringList::Iterator end(entries.end());
02273 for (QStringList::Iterator it = entries.begin(); it != end; ++it)
02274 createDatatype(*it);
02275 }
02276
02277 void UMLDoc::createDatatype(const QString &name) {
02278 UMLObjectList datatypes = m_datatypeRoot->containedObjects();
02279 UMLObject* umlobject = Model_Utils::findUMLObject(datatypes, name,
02280 ot_Datatype, m_datatypeRoot);
02281 if (!umlobject) {
02282 Object_Factory::createUMLObject(ot_Datatype, name, m_datatypeRoot);
02283 }
02284 UMLApp::app()->getListView()->closeDatatypesFolder();
02285 }
02286
02287 void UMLDoc::slotDiagramPopupMenu(QWidget* umlview, const QPoint& point) {
02288 UMLView* view = (UMLView*) umlview;
02289 if(m_pTabPopupMenu != 0) {
02290 m_pTabPopupMenu->hide();
02291 delete m_pTabPopupMenu;
02292 m_pTabPopupMenu = 0;
02293 }
02294 Settings::OptionState optionState = Settings::getOptionState();
02295 if (! optionState.generalState.tabdiagrams)
02296 return;
02297
02298 Uml::ListView_Type type = lvt_Unknown;
02299 switch( view->getType() ) {
02300 case dt_Class:
02301 type = lvt_Class_Diagram;
02302 break;
02303
02304 case dt_UseCase:
02305 type = lvt_UseCase_Diagram;
02306 break;
02307
02308 case dt_Sequence:
02309 type = lvt_Sequence_Diagram;
02310 break;
02311
02312 case dt_Collaboration:
02313 type = lvt_Collaboration_Diagram;
02314 break;
02315
02316 case dt_State:
02317 type = lvt_State_Diagram;
02318 break;
02319
02320 case dt_Activity:
02321 type = lvt_Activity_Diagram;
02322 break;
02323
02324 case dt_Component:
02325 type = lvt_Component_Diagram;
02326 break;
02327
02328 case dt_Deployment:
02329 type = lvt_Deployment_Diagram;
02330 break;
02331
02332 case dt_EntityRelationship:
02333 type = lvt_EntityRelationship_Diagram;
02334 break;
02335
02336 default:
02337 kWarning() << "unknown diagram type in slotDiagramPopupMenu()" << endl;
02338 break;
02339 }
02340
02341 m_pTabPopupMenu = new ListPopupMenu(UMLApp::app()->getMainViewWidget(), type);
02342 m_pTabPopupMenu->popup(point);
02343 connect(m_pTabPopupMenu, SIGNAL(activated(int)), view, SLOT(slotMenuSelection(int)));
02344 }
02345
02346 void UMLDoc::addDefaultStereotypes() {
02347 CodeGenerator *gen = UMLApp::app()->getGenerator();
02348 if (gen)
02349 gen->createDefaultStereotypes();
02350 }
02351
02352 const UMLStereotypeList& UMLDoc::getStereotypes() {
02353 return m_stereoList;
02354 }
02355
02356
02357 #include "umldoc.moc"
02358