umbrello API Documentation

umllistview.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) 2002-2007                                                *
00009  *  Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                   *
00010  ***************************************************************************/
00011 
00012 // own header
00013 #include "umllistview.h"
00014 
00015 // qt/kde includes
00016 #include <qregexp.h>
00017 #include <qpoint.h>
00018 #include <qrect.h>
00019 #include <qevent.h>
00020 #include <qheader.h>
00021 #include <qtooltip.h>
00022 #include <kiconloader.h>
00023 #include <kapplication.h>
00024 #include <kdebug.h>
00025 #include <kfiledialog.h>
00026 #include <klocale.h>
00027 #include <kmessagebox.h>
00028 #include <kstandarddirs.h>
00029 #include <kinputdialog.h>
00030 
00031 // app includes
00032 #include "actor.h"
00033 #include "classifier.h"
00034 #include "package.h"
00035 #include "folder.h"
00036 #include "component.h"
00037 #include "node.h"
00038 #include "artifact.h"
00039 #include "enum.h"
00040 #include "entity.h"
00041 #include "docwindow.h"
00042 #include "listpopupmenu.h"
00043 #include "template.h"
00044 #include "operation.h"
00045 #include "attribute.h"
00046 #include "entityattribute.h"
00047 #include "uml.h"
00048 #include "umldoc.h"
00049 #include "umllistviewitemlist.h"
00050 #include "umllistviewitem.h"
00051 #include "umlview.h"
00052 #include "umlviewimageexporter.h"
00053 #include "usecase.h"
00054 #include "model_utils.h"
00055 #include "uniqueid.h"
00056 #include "clipboard/idchangelog.h"
00057 #include "clipboard/umldrag.h"
00058 #include "dialogs/classpropdlg.h"
00059 #include "dialogs/umlattributedialog.h"
00060 #include "dialogs/umlentityattributedialog.h"
00061 #include "dialogs/umloperationdialog.h"
00062 #include "dialogs/umltemplatedialog.h"
00063 
00064 #ifdef WANT_LVTOOLTIP
00065 class LVToolTip : public QToolTip
00066 {
00067 public:
00068     LVToolTip (QWidget* parent) : QToolTip (parent) {}
00069     virtual ~LVToolTip () {}
00070 protected:
00078     virtual void maybeTip (const QPoint& pos) {
00079         UMLListView *lv = UMLApp::app()->getListView();
00080         UMLListViewItem * item = (UMLListViewItem*)lv->itemAt(pos);
00081         if (item == NULL)
00082             return;
00083         UMLObject *obj = item->getUMLObject();
00084         if (obj == NULL || obj->getBaseType() != Uml::ot_Operation)
00085             return;
00086         UMLOperation *op = static_cast<UMLOperation*>(obj);
00087         QString text = op->toString(Uml::st_ShowSig);
00088         QRect rect = lv->itemRect(item);
00089         tip(rect, text);
00090     }
00091 };
00092 #endif
00093 
00094 
00095 UMLListView::UMLListView(QWidget *parent, const char *name)
00096         : KListView(parent,name), m_pMenu(0), m_doc(UMLApp::app()->getDocument())
00097 {
00098     loadPixmaps();
00099 
00100     //setup list view
00101     setBackgroundColor(Qt::white);
00102     setAcceptDrops(true);
00103     setDropVisualizer(false);
00104     setItemsMovable(true);
00105     setItemsRenameable( true );
00106     setSelectionModeExt(FileManager);
00107     setFocusPolicy(QWidget::StrongFocus);
00108     setDragEnabled(true);
00109     setColumnWidthMode( 0, Manual );
00110     setDefaultRenameAction( Accept );
00111     setResizeMode( LastColumn );
00112     header()->setClickEnabled(true);
00113     //add columns and initial items
00114     addColumn(m_doc->getName());
00115 
00116 #ifdef WANT_LVTOOLTIP
00117     /* In KDE-3.3, we cannot use KListView's builtin mechanism for
00118        overriding the tooltips. Instead, see the above class LVToolTip.
00119     setShowToolTips( true );
00120     setTooltipColumn( 0 );
00121      */
00122     (void) new LVToolTip(viewport());
00123 #endif
00124     m_pMenu = NULL;
00125     m_bStartedCut = m_bStartedCopy = false;
00126     m_bIgnoreCancelRename = true;
00127     m_bCreatingChildObject = false;
00128     m_rv = NULL;
00129     for (int i = 0; i < Uml::N_MODELTYPES; i++)
00130         m_lv[i] = NULL;
00131     m_datatypeFolder = NULL;
00132     //setup slots/signals
00133     connect(this, SIGNAL(dropped(QDropEvent *, QListViewItem *, QListViewItem *)),
00134             this, SLOT(slotDropped(QDropEvent *, QListViewItem *, QListViewItem *)));
00135     connect( this, SIGNAL( collapsed( QListViewItem * ) ),
00136              this, SLOT( slotCollapsed( QListViewItem * ) ) );
00137     connect( this, SIGNAL( expanded( QListViewItem * ) ), this, SLOT( slotExpanded( QListViewItem * ) ) );
00138     connect( UMLApp::app(), SIGNAL( sigCutSuccessful() ), this, SLOT( slotCutSuccessful() ) );
00139 }
00140 
00141 UMLListView::~UMLListView() {}
00142 
00143 bool UMLListView::eventFilter(QObject *o, QEvent *e) {
00144     if (e->type() != QEvent::MouseButtonPress || !o->isA("QHeader"))
00145         return QListView::eventFilter(o, e);
00146     QMouseEvent *me = static_cast<QMouseEvent*>(e);
00147     if (me->button() == Qt::RightButton) {
00148         if (m_pMenu) {
00149             m_pMenu->hide();
00150             disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(popupMenuSel(int)));
00151             delete m_pMenu;
00152         }
00153         m_pMenu = new ListPopupMenu(this, Uml::lvt_Model);
00154         m_pMenu->popup(me->globalPos());
00155         connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(popupMenuSel(int)));
00156         return true;
00157     }
00158     return QListView::eventFilter(o, e);
00159 }
00160 
00161 void UMLListView::contentsMousePressEvent(QMouseEvent *me) {
00162     UMLView *currentView = UMLApp::app()->getCurrentView();
00163     if (currentView)
00164         currentView->clearSelected();
00165     if( me -> state() != Qt::ShiftButton )
00166         clearSelection();
00167     QPoint pt = this->QScrollView::contentsToViewport( me->pos() );
00168     UMLListViewItem * item = (UMLListViewItem*)itemAt(pt);
00169     const Qt::ButtonState button = me->button();
00170 
00171     if (!item || (button != Qt::RightButton && button != Qt::LeftButton)) {
00172         UMLApp::app()->getDocWindow()->updateDocumentation(true);
00173         return;
00174     }
00175 
00176     if (button == Qt::LeftButton) {
00177         UMLObject *o = item->getUMLObject();
00178         if (o)
00179             UMLApp::app()->getDocWindow()->showDocumentation(o, false);
00180         else
00181             UMLApp::app()->getDocWindow()->updateDocumentation(true);
00182     }
00183     if (button == Qt::RightButton) {
00184         if(m_pMenu != 0) {
00185             m_pMenu->hide();
00186             disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(popupMenuSel(int)));
00187             delete m_pMenu;
00188             m_pMenu = 0;
00189         }
00190         const Uml::ListView_Type type = item->getType();
00191         m_pMenu = new ListPopupMenu(this, type);
00192         m_pMenu->popup(me->globalPos());
00193         connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(popupMenuSel(int)));
00194     }//end if right button
00195 
00196     this->KListView::contentsMousePressEvent(me);
00197 }
00198 
00199 void UMLListView::contentsMouseReleaseEvent(QMouseEvent *me) {
00200     if (me->button() != Qt::LeftButton) {
00201         this->KListView::contentsMouseReleaseEvent(me);
00202         return;
00203     }
00204     const QPoint pt = this->QScrollView::contentsToViewport( me->pos() );
00205     UMLListViewItem *item = dynamic_cast<UMLListViewItem*>(itemAt(pt));
00206     if (item == NULL || !Model_Utils::typeIsDiagram(item->getType())) {
00207         this->KListView::contentsMouseReleaseEvent(me);
00208         return;
00209     }
00210     // Switch to diagram on mouse release - not on mouse press
00211     // because the user might intend a drag-to-note.
00212     m_doc->changeCurrentView( item->getID() );
00213     UMLApp::app()->getDocWindow()->showDocumentation(m_doc->findView(item->getID()), false);
00214     this->KListView::contentsMouseReleaseEvent(me);
00215 }
00216 
00217 void UMLListView::keyPressEvent(QKeyEvent *ke) {
00218     UMLView *view = UMLApp::app()->getCurrentView();
00219     if (view && view->getSelectCount()) {
00220         // Widgets have been selected in the diagram area,
00221         // assume they handle the keypress.
00222         ke->accept();                 // munge and do nothing
00223     } else {
00224         const int k = ke->key();
00225         if (k == Qt::Key_Delete || k == Qt::Key_Backspace) {
00226             // delete every selected item
00227             UMLListViewItemList selecteditems;
00228             getSelectedItemsRoot(selecteditems);
00229             UMLListViewItemListIt it(selecteditems);
00230             for (UMLListViewItem *item = 0; (item = it.current()); ++it) {
00231                 deleteItem(dynamic_cast<UMLListViewItem*>(item));
00232             }
00233         } else {
00234             QListView::keyPressEvent(ke); // let parent handle it
00235         }
00236     }
00237 }
00238 
00239 void UMLListView::popupMenuSel(int sel) {
00240     UMLListViewItem * temp = (UMLListViewItem*)currentItem();
00241     if ( !temp ) {
00242         kDebug() << "popupMenuSel invoked without currently selectedItem" << endl;
00243         return;
00244     }
00245     UMLObject * object = temp -> getUMLObject();
00246     Uml::ListView_Type lvt = temp -> getType();
00247     Uml::Object_Type umlType = Uml::ot_UMLObject;
00248     ListPopupMenu::Menu_Type menuType = (ListPopupMenu::Menu_Type)sel;
00249     QString name;
00250 
00251     switch (menuType) {
00252     case ListPopupMenu::mt_Class:
00253         addNewItem( temp, Uml::lvt_Class );
00254         break;
00255 
00256     case ListPopupMenu::mt_Package:
00257         addNewItem(temp, Uml::lvt_Package);
00258         break;
00259 
00260     case ListPopupMenu::mt_Subsystem:
00261         addNewItem(temp, Uml::lvt_Subsystem);
00262         break;
00263 
00264     case ListPopupMenu::mt_Component:
00265         addNewItem(temp, Uml::lvt_Component);
00266         break;
00267 
00268     case ListPopupMenu::mt_Node:
00269         addNewItem(temp, Uml::lvt_Node);
00270         break;
00271 
00272     case ListPopupMenu::mt_Artifact:
00273         addNewItem(temp, Uml::lvt_Artifact);
00274         break;
00275 
00276     case ListPopupMenu::mt_Interface:
00277         addNewItem(temp, Uml::lvt_Interface);
00278         break;
00279 
00280     case ListPopupMenu::mt_Enum:
00281         addNewItem(temp, Uml::lvt_Enum);
00282         break;
00283 
00284     case ListPopupMenu::mt_Template:
00285         addNewItem(temp, Uml::lvt_Template);
00286         break;
00287 
00288     case ListPopupMenu::mt_Entity:
00289         addNewItem(temp, Uml::lvt_Entity);
00290         break;
00291 
00292     case ListPopupMenu::mt_Datatype:
00293         addNewItem(temp, Uml::lvt_Datatype);
00294         break;
00295 
00296     case ListPopupMenu::mt_Actor:
00297         addNewItem( temp, Uml::lvt_Actor );
00298         break;
00299 
00300     case ListPopupMenu::mt_UseCase:
00301         addNewItem( temp, Uml::lvt_UseCase );
00302         break;
00303 
00304     case ListPopupMenu::mt_Attribute:
00305         addNewItem( temp, Uml::lvt_Attribute );
00306         break;
00307 
00308     case ListPopupMenu::mt_EntityAttribute:
00309         addNewItem( temp, Uml::lvt_EntityAttribute );
00310         break;
00311 
00312     case ListPopupMenu::mt_Operation:
00313         addNewItem( temp, Uml::lvt_Operation );
00314         break;
00315 
00316     case ListPopupMenu::mt_Import_Classes:
00317         UMLApp::app()->slotImportClasses();
00318         break;
00319 
00320     case ListPopupMenu::mt_Expand_All:
00321         expandAll(temp);
00322         break;
00323 
00324     case ListPopupMenu::mt_Collapse_All:
00325         collapseAll(temp);
00326         break;
00327 
00328     case ListPopupMenu::mt_Export_Image:
00329         m_doc->findView(temp->getID())->getImageExporter()->exportView();
00330         break;
00331 
00332     case ListPopupMenu::mt_Externalize_Folder:
00333         {
00334             UMLListViewItem *current = static_cast<UMLListViewItem*>(currentItem());
00335             UMLFolder *modelFolder = dynamic_cast<UMLFolder*>(current->getUMLObject());
00336             if (modelFolder == NULL) {
00337                 kError() << "UMLListView::popupMenuSel: modelFolder is NULL" << endl;
00338                 return;
00339             }
00340             // configure & show the file dialog
00341             const QString rootDir(m_doc->URL().directory());
00342             KFileDialog fileDialog(rootDir, "*.xm1", this, ":externalize-folder", true);
00343             fileDialog.setCaption(i18n("Externalize Folder"));
00344             fileDialog.setOperationMode(KFileDialog::Other);
00345             // set a sensible default filename
00346             QString defaultFilename = current->getText().lower();
00347             defaultFilename.replace(QRegExp("\\W+"), "_");
00348             defaultFilename.append(".xm1");  // default extension
00349             fileDialog.setSelection(defaultFilename);
00350             fileDialog.exec();
00351             KURL selURL = fileDialog.selectedURL();
00352             if (selURL.isEmpty())
00353                 return;
00354             QString path = selURL.path();
00355             QString fileName = path;
00356             if (fileName.startsWith(rootDir)) {
00357                 fileName.remove(rootDir);
00358             } else {
00359                 // This should be done using a KMessageBox but we currently
00360                 // cannot add new i18n strings.
00361                 kError() << "Folder " << path
00362                     << " must be relative to the main model directory, "
00363                     << rootDir << endl;
00364                 return;
00365             }
00366             QFile file(path);
00367             // Warn if file exists.
00368             if (file.exists()) {
00369                 // This should be done using a KMessageBox but we currently
00370                 // cannot add new i18n strings.
00371                 kWarning() << "file " << fileName << " already exists!" << endl;
00372                 kWarning() << "The existing file will be overwritten." << endl;
00373             }
00374             // Test if file is writable.
00375             if (file.open(IO_WriteOnly)) {
00376                 file.close();
00377             } else {
00378                 KMessageBox::error(0,
00379                                    i18n("There was a problem saving file: %1").arg(fileName),
00380                                    i18n("Save Error"));
00381                 return;
00382             }
00383             modelFolder->setFolderFile(fileName);
00384             // Recompute text of the folder
00385             QString folderText = current->getText();
00386             folderText.remove( QRegExp("\\s*\\(.*$") );
00387             folderText.append( " (" + fileName + ')' );
00388             current->setText(folderText);
00389             break;
00390         }
00391 
00392     case ListPopupMenu::mt_Internalize_Folder:
00393         {
00394             UMLListViewItem *current = static_cast<UMLListViewItem*>(currentItem());
00395             UMLFolder *modelFolder = dynamic_cast<UMLFolder*>(current->getUMLObject());
00396             if (modelFolder == NULL) {
00397                 kError() << "UMLListView::popupMenuSel: modelFolder is NULL" << endl;
00398                 return;
00399             }
00400             modelFolder->setFolderFile(QString::null);
00401             // Recompute text of the folder
00402             QString folderText = current->getText();
00403             folderText.remove( QRegExp("\\s*\\(.*$") );
00404             current->setText(folderText);
00405             break;
00406         }
00407 
00408     case ListPopupMenu::mt_Model:
00409         {
00410             bool ok = false;
00411             QString name = KInputDialog::getText( i18n("Enter Model Name"),
00412                                                   i18n("Enter the new name of the model:"),
00413                                                   m_doc->getName(), &ok, UMLApp::app() );
00414             if (ok) {
00415                 setColumnText(0, name);
00416                 m_doc->setName(name);
00417             }
00418             break;
00419         }
00420 
00421     case ListPopupMenu::mt_Rename:
00422         temp-> startRename(0);
00423         break;
00424 
00425     case ListPopupMenu::mt_Delete:
00426         deleteItem(temp);
00427 
00428         return;
00429         break;
00430 
00431     case ListPopupMenu::mt_Properties:
00432         /* first check if we are on a diagram */
00433         if( Model_Utils::typeIsDiagram(lvt) ) {
00434             UMLView * pView = m_doc->findView( temp->getID() );
00435             if( !pView ) {
00436                 return;
00437             }
00438             UMLApp::app()->getDocWindow()->updateDocumentation(false);
00439             pView->showPropDialog();
00440             UMLApp::app()->getDocWindow()->showDocumentation(pView, true);
00441             temp->cancelRename(0);
00442             return;
00443         }
00444 
00445         /* ok, we are on another object, so find out on which one */
00446         umlType = object->getBaseType();
00447 
00448         if ( Model_Utils::typeIsCanvasWidget(lvt) ) {
00449             object->showProperties(ClassPropDlg::page_gen);
00450         } else if(umlType == Uml::ot_Attribute) {
00451             // show the attribute dialog
00452             UMLAttribute* selectedAttribute = static_cast<UMLAttribute*>(object);
00453             UMLAttributeDialog dialog( this, selectedAttribute );
00454             dialog.exec();
00455         } else if(umlType == Uml::ot_EntityAttribute) {
00456             // show the attribute dialog
00457             UMLEntityAttribute* selectedAttribute = static_cast<UMLEntityAttribute*>(object);
00458             UMLEntityAttributeDialog dialog( this, selectedAttribute );
00459             dialog.exec();
00460         } else if(umlType == Uml::ot_Operation) {
00461             // show the operation dialog
00462             UMLOperation* selectedOperation = static_cast<UMLOperation*>(object);
00463             UMLOperationDialog dialog( this, selectedOperation );
00464             dialog.exec();
00465         } else if(umlType == Uml::ot_Template) {
00466             // show the template dialog
00467             UMLTemplate* selectedTemplate = static_cast<UMLTemplate*>(object);
00468             UMLTemplateDialog dialog( this, selectedTemplate );
00469             dialog.exec();
00470         } else {
00471             kWarning() << "calling properties on unknown type" << endl;
00472         }
00473         temp -> cancelRename( 0 );
00474         break;
00475 
00476     case ListPopupMenu::mt_Logical_Folder:
00477         addNewItem( temp, Uml::lvt_Logical_Folder );
00478         break;
00479 
00480     case ListPopupMenu::mt_UseCase_Folder:
00481         addNewItem( temp, Uml::lvt_UseCase_Folder );
00482         break;
00483 
00484     case ListPopupMenu::mt_Component_Folder:
00485         addNewItem(temp, Uml::lvt_Component_Folder);
00486         break;
00487 
00488     case ListPopupMenu::mt_Deployment_Folder:
00489         addNewItem(temp, Uml::lvt_Deployment_Folder);
00490         break;
00491 
00492     case ListPopupMenu::mt_EntityRelationship_Folder:
00493         addNewItem(temp, Uml::lvt_EntityRelationship_Folder);
00494         break;
00495 
00496     case ListPopupMenu::mt_Cut:
00497         m_bStartedCut = true;
00498         m_bStartedCopy = false;
00499         UMLApp::app() -> slotEditCut();
00500         break;
00501 
00502     case ListPopupMenu::mt_Copy:
00503         m_bStartedCut = false;
00504         m_bStartedCopy = true;
00505         UMLApp::app() -> slotEditCopy();
00506         break;
00507 
00508     case ListPopupMenu::mt_Paste:
00509         UMLApp::app() -> slotEditPaste();
00510         break;
00511 
00512     default:
00513         {
00514             Uml::Diagram_Type dt = ListPopupMenu::convert_MT_DT(menuType);
00515             if (dt == Uml::dt_Undefined) {
00516                 kWarning() << "UMLListView::popupMenuSel: unknown type"
00517                     << sel << endl;
00518             } else {
00519                 UMLFolder *f = dynamic_cast<UMLFolder*>(object);
00520                 if (f == NULL)
00521                     kError() << "UMLListView::popupMenuSel(" << menuType
00522                         << "): current item's UMLObject is not a UMLFolder" << endl;
00523                 else
00524                     m_doc->createDiagram(f, dt);
00525             }
00526         }
00527         break;
00528     }//end switch
00529 }
00530 
00531 UMLListViewItem *UMLListView::findFolderForDiagram(Uml::Diagram_Type dt) {
00532     UMLListViewItem *p = static_cast<UMLListViewItem*>(currentItem());
00533     if (p && Model_Utils::typeIsFolder(p->getType())
00534          && !Model_Utils::typeIsRootView(p->getType())) {
00535         return p;
00536     }
00537     switch (dt) {
00538         case Uml::dt_UseCase:
00539             p = m_lv[Uml::mt_UseCase];
00540             break;
00541         case Uml::dt_Component:
00542             p = m_lv[Uml::mt_Component];
00543             break;
00544         case Uml::dt_Deployment:
00545             p = m_lv[Uml::mt_Deployment];
00546             break;
00547         case Uml::dt_EntityRelationship:
00548             p = m_lv[Uml::mt_EntityRelationship];
00549             break;
00550         default:
00551             p = m_lv[Uml::mt_Logical];
00552             break;
00553     }
00554     return p;
00555 }
00556 
00557 void UMLListView::slotDiagramCreated( Uml::IDType id ) {
00558     if( m_doc->loading() )
00559         return;
00560     UMLView *v = m_doc -> findView( id );
00561     if (!v)
00562         return;
00563     const Uml::Diagram_Type dt = v->getType();
00564     UMLListViewItem * temp = 0, *p = findFolderForDiagram(dt);
00565     temp = new UMLListViewItem(p, v->getName(), Model_Utils::convert_DT_LVT(dt), id);
00566     setSelected( temp, true );
00567     UMLApp::app() -> getDocWindow() -> showDocumentation( v , false );
00568 }
00569 
00570 UMLListViewItem* UMLListView::determineParentItem(UMLObject* object) const {
00571     UMLListViewItem* parentItem = NULL;
00572     UMLListViewItem* current = (UMLListViewItem*) currentItem();
00573     Uml::ListView_Type lvt = Uml::lvt_Unknown;
00574     if (current)
00575         lvt = current->getType();
00576     Uml::Object_Type t = object->getBaseType();
00577 
00578     switch (t) {
00579     case Uml::ot_Attribute:
00580     case Uml::ot_Operation:
00581     case Uml::ot_Template:
00582     case Uml::ot_EnumLiteral:
00583     case Uml::ot_EntityAttribute:
00584         //this will be handled by childObjectAdded
00585         return NULL;
00586         break;
00587     case Uml::ot_Association:
00588     case Uml::ot_Role:
00589     case Uml::ot_Stereotype:
00590         return NULL;  // currently no representation in list view
00591         break;
00592     default:
00593         {
00594             UMLPackage *pkg = object->getUMLPackage();
00595             if (pkg) {
00596                 UMLListViewItem* pkgItem = findUMLObject(pkg);
00597                 if (pkgItem == NULL)
00598                     kError() << "UMLListView::determineParentItem: could not find "
00599                         << "parent package " << pkg->getName() << endl;
00600                 else
00601                     parentItem = pkgItem;
00602             } else if ((lvt == Uml::lvt_UseCase_Folder &&
00603                            (t == Uml::ot_Actor || t == Uml::ot_UseCase))
00604                     || (lvt == Uml::lvt_Component_Folder && t == Uml::ot_Component)
00605                     || (lvt == Uml::lvt_Deployment_Folder && t == Uml::ot_Node)
00606                     || (lvt == Uml::lvt_EntityRelationship_Folder && t == Uml::ot_Entity)) {
00607                 parentItem = current;
00608             } else if (t == Uml::ot_Datatype) {
00609                 parentItem = m_datatypeFolder;
00610             } else {
00611                 Uml::Model_Type guess = Model_Utils::guessContainer(object);
00612                 parentItem = m_lv[guess];
00613             }
00614         }
00615         break;
00616     }
00617     return parentItem;
00618 }
00619 
00620 bool UMLListView::mayHaveChildItems(Uml::Object_Type type) {
00621     bool retval = false;
00622     switch (type) {
00623         case Uml::ot_Class:
00624         case Uml::ot_Interface:
00625         case Uml::ot_Enum:
00626         case Uml::ot_Entity:  // CHECK: more?
00627             retval = true;
00628             break;
00629         default:
00630             break;
00631     }
00632     return retval;
00633 }
00634 
00635 void UMLListView::slotObjectCreated(UMLObject* object) {
00636     if (m_bCreatingChildObject) {
00637         // @todo eliminate futile signal traffic
00638         // e.g. we get here thru various indirections from
00639         // ClassifierListPage::slot{Up,Down}Clicked()
00640         return;
00641     }
00642     UMLListViewItem* newItem = findUMLObject(object);
00643     if (newItem) {
00644         kDebug() << "UMLListView::slotObjectCreated(" << object->getName()
00645             << ", id= " << ID2STR(object->getID())
00646             << "): item already exists." << endl;
00647         Uml::Icon_Type icon = Model_Utils::convert_LVT_IT(newItem->getType());
00648         newItem->setIcon(icon);
00649         return;
00650     }
00651     UMLListViewItem* parentItem = determineParentItem(object);
00652     if (parentItem == NULL)
00653         return;
00654     Uml::Object_Type type = object->getBaseType();
00655 
00656     connectNewObjectsSlots(object);
00657     const Uml::ListView_Type lvt = Model_Utils::convert_OT_LVT(object);
00658     QString name = object->getName();
00659     if (type == Uml::ot_Folder) {
00660         UMLFolder *f = static_cast<UMLFolder*>(object);
00661         QString folderFile = f->getFolderFile();
00662         if (!folderFile.isEmpty())
00663             name.append(" (" + folderFile + ')');
00664     }
00665     newItem = new UMLListViewItem(parentItem, name, lvt, object);
00666     if (mayHaveChildItems(type)) {
00667         UMLClassifier *c = static_cast<UMLClassifier*>(object);
00668         UMLClassifierListItemList cListItems = c->getFilteredList(Uml::ot_UMLObject);
00669         UMLClassifierListItem *cli;
00670         for (UMLClassifierListItemListIt it(cListItems); (cli = it.current()) != NULL; ++it)
00671             childObjectAdded(cli, c);
00672     }
00673     if (m_doc->loading())
00674         return;
00675     ensureItemVisible(newItem);
00676     newItem->setOpen(true);
00677     clearSelection();
00678     setSelected(newItem, true);
00679     UMLApp::app()->getDocWindow()->showDocumentation(object, false);
00680 }
00681 
00682 void UMLListView::connectNewObjectsSlots(UMLObject* object) {
00683     Uml::Object_Type type = object->getBaseType();
00684     switch( type )
00685     {
00686     case Uml::ot_Class:
00687     case Uml::ot_Interface:
00688         {
00689             UMLClassifier *c = static_cast<UMLClassifier*>(object);
00690             connect(c, SIGNAL(attributeAdded(UMLClassifierListItem*)),
00691                     this, SLOT(childObjectAdded(UMLClassifierListItem*)));
00692             connect(c, SIGNAL(attributeRemoved(UMLClassifierListItem*)),
00693                     this, SLOT(childObjectRemoved(UMLClassifierListItem*)));
00694             connect(c, SIGNAL(operationAdded(UMLClassifierListItem*)),
00695                     this, SLOT(childObjectAdded(UMLClassifierListItem*)));
00696             connect(c, SIGNAL(operationRemoved(UMLClassifierListItem*)),
00697                     this, SLOT(childObjectRemoved(UMLClassifierListItem*)));
00698             connect(c, SIGNAL(templateAdded(UMLClassifierListItem*)),
00699                     this, SLOT(childObjectAdded(UMLClassifierListItem*)));
00700             connect(c, SIGNAL(templateRemoved(UMLClassifierListItem*)),
00701                     this, SLOT(childObjectRemoved(UMLClassifierListItem*)));
00702             connect(object,SIGNAL(modified()),this,SLOT(slotObjectChanged()));
00703         }
00704         break;
00705     case Uml::ot_Enum:
00706         {
00707             UMLEnum *e = static_cast<UMLEnum*>(object);
00708             connect(e, SIGNAL(enumLiteralAdded(UMLClassifierListItem*)),
00709                     this, SLOT(childObjectAdded(UMLClassifierListItem*)));
00710             connect(e, SIGNAL(enumLiteralRemoved(UMLClassifierListItem*)),
00711                     this, SLOT(childObjectRemoved(UMLClassifierListItem*)));
00712         }
00713         connect(object,SIGNAL(modified()),this,SLOT(slotObjectChanged()));
00714         break;
00715     case Uml::ot_Entity:
00716         {
00717             UMLEntity *ent = static_cast<UMLEntity*>(object);
00718             connect(ent, SIGNAL(entityAttributeAdded(UMLClassifierListItem*)),
00719                     this, SLOT(childObjectAdded(UMLClassifierListItem*)));
00720             connect(ent, SIGNAL(entityAttributeRemoved(UMLClassifierListItem*)),
00721                     this, SLOT(childObjectRemoved(UMLClassifierListItem*)));
00722         }
00723         connect(object,SIGNAL(modified()),this,SLOT(slotObjectChanged()));
00724         break;
00725     case Uml::ot_Datatype:
00726     case Uml::ot_Attribute:
00727     case Uml::ot_Operation:
00728     case Uml::ot_Template:
00729     case Uml::ot_EnumLiteral:
00730     case Uml::ot_EntityAttribute:
00731     case Uml::ot_Package:
00732     case Uml::ot_Actor:
00733     case Uml::ot_UseCase:
00734     case Uml::ot_Component:
00735     case Uml::ot_Artifact:
00736     case Uml::ot_Node:
00737     case Uml::ot_Folder:
00738         connect(object,SIGNAL(modified()),this,SLOT(slotObjectChanged()));
00739         break;
00740     case Uml::ot_UMLObject:
00741     case Uml::ot_Association:
00742     case Uml::ot_Stereotype:
00743         break;
00744     default:
00745         kWarning() << "unknown type in connectNewObjectsSlots" << endl;
00746         break;
00747     }
00748 }
00749 
00750 void UMLListView::slotObjectChanged() {
00751     if (m_doc->loading()) { //needed for class wizard
00752         return;
00753     }
00754     UMLObject* obj = const_cast<UMLObject*>( dynamic_cast<const UMLObject*>(sender()) );
00755     UMLListViewItem* item = findUMLObject(obj);
00756     if(item) {
00757         item->updateObject();
00758     }
00759 }
00760 
00761 void UMLListView::childObjectAdded(UMLClassifierListItem* obj) {
00762     UMLClassifier *parent = const_cast<UMLClassifier*>(dynamic_cast<const UMLClassifier*>(sender()));
00763     childObjectAdded(obj, parent);
00764 }
00765 
00766 void UMLListView::childObjectAdded(UMLClassifierListItem* child, UMLClassifier* parent) {
00767     if (m_bCreatingChildObject)
00768         return;
00769     const QString text = child->toString(Uml::st_SigNoVis);
00770     UMLListViewItem *childItem = NULL;
00771     UMLListViewItem *parentItem = findUMLObject(parent);
00772     if (parentItem == NULL) {
00773         kDebug() << "UMLListView::childObjectAdded(" << child->getName()
00774             << "): parent " << parent->getName()
00775             << " does not yet exist, creating it now." << endl;
00776         const Uml::ListView_Type lvt = Model_Utils::convert_OT_LVT(parent);
00777         parentItem = new UMLListViewItem(m_lv[Uml::mt_Logical], parent->getName(), lvt, parent);
00778     } else {
00779         childItem = parentItem->findChildObject(child);
00780     }
00781     if (childItem) {
00782         childItem->setText(text);
00783     } else {
00784         const Uml::ListView_Type lvt = Model_Utils::convert_OT_LVT(child);
00785         childItem = new UMLListViewItem(parentItem, text, lvt, child);
00786         if (! m_doc->loading()) {
00787             ensureItemVisible(childItem);
00788             clearSelection();
00789             setSelected(childItem, true);
00790         }
00791         connectNewObjectsSlots(child);
00792     }
00793 }
00794 
00795 void UMLListView::childObjectRemoved(UMLClassifierListItem* obj) {
00796     UMLClassifier *parent = const_cast<UMLClassifier*>(dynamic_cast<const UMLClassifier*>(sender()));
00797     UMLListViewItem *parentItem = findUMLObject(parent);
00798     if (parentItem == NULL) {
00799         kError() << "UMLListView::childObjectRemoved(" << obj->getName()
00800             << "): cannot find parent UMLListViewItem" << endl;
00801         return;
00802     }
00803     parentItem->deleteChildItem(obj);
00804 }
00805 
00806 void UMLListView::slotDiagramRenamed(Uml::IDType id) {
00807     UMLListViewItem* temp;
00808     UMLView* v = m_doc->findView(id);
00809     if ((temp = findView(v)) == NULL) {
00810         kError() << "UMLListView::slotDiagramRenamed: UMLDoc::findView("
00811             << ID2STR(id) << ") returns NULL" << endl;
00812         return;
00813     }
00814     temp->setText( v->getName() );
00815 }
00816 
00817 void UMLListView::setDocument(UMLDoc *d) {
00818     if( m_doc && m_doc != d)
00819     {
00820         //disconnect signals from old doc and reset view
00821     }
00822     m_doc = d;
00823 
00824     connect(m_doc, SIGNAL(sigDiagramCreated(Uml::IDType)), this, SLOT(slotDiagramCreated(Uml::IDType)));
00825     connect(m_doc, SIGNAL(sigDiagramRemoved(Uml::IDType)), this, SLOT(slotDiagramRemoved(Uml::IDType)));
00826     connect(m_doc, SIGNAL(sigDiagramRenamed(Uml::IDType)), this, SLOT(slotDiagramRenamed(Uml::IDType)));
00827     connect(m_doc, SIGNAL(sigObjectCreated(UMLObject *)), this, SLOT(slotObjectCreated(UMLObject *)));
00828     connect(m_doc, SIGNAL(sigObjectRemoved(UMLObject *)), this, SLOT(slotObjectRemoved(UMLObject *)));
00829 }
00830 
00831 void UMLListView::slotObjectRemoved(UMLObject* object) {
00832     if (m_doc->loading()) { //needed for class wizard
00833         return;
00834     }
00835     disconnect(object,SIGNAL(modified()),this,SLOT(slotObjectChanged()));
00836     UMLListViewItem* item = findItem(object->getID());
00837     delete item;
00838     UMLApp::app()->getDocWindow()->updateDocumentation(true);
00839 }
00840 
00841 void UMLListView::slotDiagramRemoved(Uml::IDType id) {
00842     UMLListViewItem* item = findItem(id);
00843     delete item;
00844     UMLApp::app()->getDocWindow()->updateDocumentation(true);
00845 }
00846 
00847 QDragObject* UMLListView::dragObject() {
00848     UMLListViewItemList selecteditems;
00849     getSelectedItems(selecteditems);
00850     selecteditems.setAutoDelete( false );
00851     UMLListViewItemListIt it(selecteditems);
00852     UMLListViewItem * item = 0;
00853     UMLListViewItemList  list;
00854     list.setAutoDelete( false );
00855     while((item=it.current()) != 0) {
00856         ++it;
00857         Uml::ListView_Type type = item->getType();
00858         if (!Model_Utils::typeIsCanvasWidget(type) && !Model_Utils::typeIsDiagram(type)
00859                 && !Model_Utils::typeIsClassifierList(type)) {
00860             return 0;
00861         }
00862         list.append(item);
00863     }
00864     UMLDrag *t = new UMLDrag(list, this);
00865 
00866     return t;
00867 }
00868 
00869 void UMLListView::startDrag() {
00870     QDragObject *o = dragObject();
00871     if (o)
00872         o->dragCopy();
00873 }
00874 
00875 UMLListViewItem * UMLListView::findUMLObjectInFolder(UMLListViewItem* folder, UMLObject* obj) {
00876     UMLListViewItem *item = static_cast<UMLListViewItem *>(folder->firstChild());
00877     while(item)
00878     {
00879         switch(item->getType())
00880         {
00881         case Uml::lvt_Actor :
00882         case Uml::lvt_UseCase :
00883         case Uml::lvt_Class :
00884         case Uml::lvt_Package :
00885         case Uml::lvt_Subsystem :
00886         case Uml::lvt_Component :
00887         case Uml::lvt_Node :
00888         case Uml::lvt_Artifact :
00889         case Uml::lvt_Interface :
00890         case Uml::lvt_Datatype :
00891         case Uml::lvt_Enum :
00892         case Uml::lvt_Entity :
00893             if(item->getUMLObject() == obj)
00894                 return item;
00895             break;
00896         case Uml::lvt_Logical_Folder :
00897         case Uml::lvt_UseCase_Folder :
00898         case Uml::lvt_Component_Folder :
00899         case Uml::lvt_Deployment_Folder :
00900         case Uml::lvt_EntityRelationship_Folder :
00901         case Uml::lvt_Datatype_Folder :
00902             {
00903                 UMLListViewItem *temp = findUMLObjectInFolder(item, obj);
00904                 if (temp)
00905                     return temp;
00906             }
00907         default:
00908             break;
00909         }
00910         item = static_cast<UMLListViewItem *>(item->nextSibling());
00911     }
00912     return 0;
00913 }
00914 
00915 UMLListViewItem * UMLListView::findUMLObject(const UMLObject *p) const {
00916     UMLListViewItem *item = static_cast<UMLListViewItem*>(firstChild());
00917     while (item) {
00918         UMLListViewItem *testItem = item->findUMLObject(p);
00919         if (testItem)
00920             return testItem;
00921         item = static_cast<UMLListViewItem*>(item->nextSibling());
00922     }
00923     return item;
00924 }
00925 
00926 void UMLListView::changeIconOf(UMLObject *o, Uml::Icon_Type to) {
00927     UMLListViewItem *item = findUMLObject(o);
00928     if (item == NULL)
00929         return;
00930     item->setIcon(to);
00931 }
00932 
00933 UMLListViewItem* UMLListView::findView(UMLView* v) {
00934     if (!v) {
00935         kWarning() << "returning 0 from UMLListView::findView()" << endl;
00936         return 0;
00937     }
00938     UMLListViewItem* item;
00939     Uml::Diagram_Type dType = v->getType();
00940     Uml::ListView_Type type = Model_Utils::convert_DT_LVT( dType );
00941     Uml::IDType id = v->getID();
00942     if (dType == Uml::dt_UseCase) {
00943         item = m_lv[Uml::mt_UseCase];
00944     } else if (dType == Uml::dt_Component) {
00945         item = m_lv[Uml::mt_Component];
00946     } else if (dType == Uml::dt_Deployment) {
00947         item = m_lv[Uml::mt_Deployment];
00948     } else if (dType == Uml::dt_EntityRelationship) {
00949         item = m_lv[Uml::mt_EntityRelationship];
00950     } else {
00951         item = m_lv[Uml::mt_Logical];
00952     }
00953 
00954     UMLListViewItem* searchStartItem = (UMLListViewItem *)item->firstChild();
00955 
00956     UMLListViewItem* foundItem = recursiveSearchForView(searchStartItem, type, id);
00957 
00958     if (!foundItem) {
00959         kWarning() << "returning 0 at UMLListView::findView" << endl;
00960     }
00961     return foundItem;
00962 }
00963 
00964 UMLListViewItem* UMLListView::recursiveSearchForView(UMLListViewItem* listViewItem,
00965         Uml::ListView_Type type, Uml::IDType id) {
00966     while (listViewItem) {
00967         if ( Model_Utils::typeIsFolder(listViewItem->getType()) ) {
00968             UMLListViewItem* child = (UMLListViewItem *)listViewItem->firstChild();
00969             UMLListViewItem* resultListViewItem = recursiveSearchForView(child, type, id);
00970             if (resultListViewItem) {
00971                 return resultListViewItem;
00972             }
00973         } else {
00974             if(listViewItem->getType() == type && listViewItem->getID() == id) {
00975                 return listViewItem;
00976             }
00977         }
00978         listViewItem = (UMLListViewItem*)listViewItem->nextSibling();
00979     }
00980     return 0;
00981 }
00982 
00983 UMLListViewItem* UMLListView::findItem(Uml::IDType id) {
00984     UMLListViewItem *temp;
00985     QListViewItemIterator it(this);
00986     for( ; (temp = (UMLListViewItem*)it.current()); ++it ) {
00987         UMLListViewItem * item = temp->findItem(id);
00988         if (item)
00989             return item;
00990     }
00991     return 0;
00992 }
00993 
00994 
00995 //
00996 // This method is called more than once during an instance's lifetime (by UMLDoc)!
00997 // So we must not allocate any memory before freeing the previously allocated one
00998 // or do connect()s.
00999 //
01000 void UMLListView::init() {
01001     if (m_rv == NULL) {
01002         m_rv =  new UMLListViewItem(this, i18n("Views"), Uml::lvt_View);
01003         for (int i = 0; i < Uml::N_MODELTYPES; i++) {
01004             Uml::Model_Type mt = (Uml::Model_Type)i;
01005             UMLFolder *sysFolder = m_doc->getRootFolder(mt);
01006             Uml::ListView_Type lvt = Model_Utils::convert_MT_LVT(mt);
01007             m_lv[i] = new UMLListViewItem(m_rv, sysFolder->getLocalName(), lvt, sysFolder);
01008         }
01009     } else {
01010         for (int i = 0; i < Uml::N_MODELTYPES; i++)
01011             deleteChildrenOf(m_lv[i]);
01012     }
01013     UMLFolder *datatypeFolder = m_doc->getDatatypeFolder();
01014     m_datatypeFolder = new UMLListViewItem(m_lv[Uml::mt_Logical], datatypeFolder->getLocalName(),
01015                                            Uml::lvt_Datatype_Folder, datatypeFolder);
01016     m_rv->setOpen(true);
01017     for (int i = 0; i < Uml::N_MODELTYPES; i++)
01018         m_lv[i]->setOpen(true);
01019     m_datatypeFolder->setOpen(false);
01020 
01021     //setup misc.
01022     delete m_pMenu;
01023     m_pMenu = 0;
01024     m_bStartedCut = m_bStartedCopy = false;
01025     m_bIgnoreCancelRename = true;
01026     m_bCreatingChildObject = false;
01027 }
01028 
01029 void UMLListView::setView(UMLView * v) {
01030     if(!v)
01031         return;
01032     UMLListViewItem * temp = findView(v);
01033     if(temp)
01034         setSelected(temp, true);
01035 }
01036 
01037 void UMLListView::contentsMouseDoubleClickEvent(QMouseEvent * me) {
01038     UMLListViewItem * item = static_cast<UMLListViewItem *>( currentItem() );
01039     if( !item || me -> button() != Qt::LeftButton )
01040         return;
01041     //see if on view
01042     Uml::ListView_Type lvType = item -> getType();
01043     if( Model_Utils::typeIsDiagram(lvType) ) {
01044         UMLView * pView = m_doc -> findView( item -> getID() );
01045         if( !pView )
01046             return;
01047         UMLApp::app() -> getDocWindow() -> updateDocumentation( false );
01048         pView -> showPropDialog();
01049         UMLApp::app() -> getDocWindow() -> showDocumentation( pView, true );
01050         item -> cancelRename( 0 );
01051         return;
01052     }
01053     //else see if an object
01054     UMLObject * object = item -> getUMLObject();
01055     //continue only if we are on a UMLObject
01056     if(!object)
01057         return;
01058 
01059 
01060     Uml::Object_Type type = object -> getBaseType();
01061     int page = ClassPropDlg::page_gen;
01062     if(type == Uml::ot_Attribute || type == Uml::ot_Operation)
01063         object = (UMLObject *)object -> parent();
01064     //set what page to show
01065     if(type == Uml::ot_Attribute)
01066         page = ClassPropDlg::page_att;
01067     else if(type == Uml::ot_Operation)
01068         page = ClassPropDlg::page_op;
01069     //FIXME for entityattributes
01070 
01071     if(object)
01072         object->showProperties(page);
01073     item -> cancelRename( 0 );//double click can cause it to go into rename mode.
01074 }
01075 
01076 
01077 bool UMLListView::acceptDrag(QDropEvent* event) const {
01078     QPoint mousePoint = ((UMLListView*)this)->contentsToViewport( event->pos() );
01079 
01080     UMLListViewItem* item = (UMLListViewItem*)itemAt(mousePoint);
01081     if(!item) {
01082         kDebug() << "UMLListView::acceptDrag: itemAt(mousePoint) returns NULL"
01083             << endl;
01084         return false;
01085     }
01086     ((QListView*)this)->setCurrentItem( (QListViewItem*)item );
01087 
01088     UMLDrag::LvTypeAndID_List list;
01089     if (! UMLDrag::getClip3TypeAndID(event, list)) {
01090         kDebug() << "UMLListView::acceptDrag: UMLDrag::getClip3TypeAndID returns false"
01091             << endl;
01092         return false;
01093     }
01094 
01095     UMLDrag::LvTypeAndID_It it(list);
01096     UMLDrag::LvTypeAndID * data = 0;
01097     Uml::ListView_Type dstType = item->getType();
01098     bool accept = true;
01099     while(accept && ((data = it.current()) != 0)) {
01100         ++it;
01101         Uml::ListView_Type srcType = data->type;
01102         switch (srcType) {
01103         case Uml::lvt_Class:
01104         case Uml::lvt_Package:
01105         case Uml::lvt_Interface:
01106         case Uml::lvt_Enum:
01107             if (dstType == Uml::lvt_Logical_View ||
01108                     dstType == Uml::lvt_Class ||
01109                     dstType == Uml::lvt_Package) {
01110                 accept = !item->isOwnParent(data->id);
01111             } else {
01112                 accept = (dstType == Uml::lvt_Logical_Folder);
01113             }
01114             break;
01115         case Uml::lvt_Attribute:
01116             if (dstType == Uml::lvt_Class) {
01117                 accept = !item->isOwnParent(data->id);
01118             }
01119             break;
01120         case Uml::lvt_EntityAttribute:
01121             if (dstType == Uml::lvt_Entity) {
01122                 accept = !item->isOwnParent(data->id);
01123             }
01124             break;
01125         case Uml::lvt_Operation:
01126             if (dstType == Uml::lvt_Class ||
01127                     dstType == Uml::lvt_Interface) {
01128                 accept = !item->isOwnParent(data->id);
01129             }
01130             break;
01131         case Uml::lvt_Datatype:
01132             accept = (dstType == Uml::lvt_Logical_Folder ||
01133                       dstType == Uml::lvt_Datatype_Folder ||
01134                       dstType == Uml::lvt_Class ||
01135                       dstType == Uml::lvt_Interface ||
01136                       dstType == Uml::lvt_Package);
01137             break;
01138         case Uml::lvt_Class_Diagram:
01139         case Uml::lvt_Collaboration_Diagram:
01140         case Uml::lvt_State_Diagram:
01141         case Uml::lvt_Activity_Diagram:
01142         case Uml::lvt_Sequence_Diagram:
01143             accept = (dstType == Uml::lvt_Logical_Folder ||
01144                       dstType == Uml::lvt_Logical_View);
01145             break;
01146         case Uml::lvt_Logical_Folder:
01147             if (dstType == Uml::lvt_Logical_Folder) {
01148                 accept = !item->isOwnParent(data->id);
01149             } else {
01150                 accept = (dstType == Uml::lvt_Logical_View);
01151             }
01152             break;
01153         case Uml::lvt_UseCase_Folder:
01154             if (dstType == Uml::lvt_UseCase_Folder) {
01155                 accept = !item->isOwnParent(data->id);
01156             } else {
01157                 accept = (dstType == Uml::lvt_UseCase_View);
01158             }
01159             break;
01160         case Uml::lvt_Component_Folder:
01161             if (dstType == Uml::lvt_Component_Folder) {
01162                 accept = !item->isOwnParent(data->id);
01163             } else {
01164                 accept = (dstType == Uml::lvt_Component_View);
01165             }
01166             break;
01167         case Uml::lvt_Deployment_Folder:
01168             if (dstType == Uml::lvt_Deployment_Folder) {
01169                 accept = !item->isOwnParent(data->id);
01170             } else {
01171                 accept = (dstType == Uml::lvt_Deployment_View);
01172             }
01173             break;
01174         case Uml::lvt_EntityRelationship_Folder:
01175             if (dstType == Uml::lvt_EntityRelationship_Folder) {
01176                 accept = !item->isOwnParent(data->id);
01177             } else {
01178                 accept = (dstType == Uml::lvt_EntityRelationship_Model);
01179             }
01180             break;
01181         case Uml::lvt_Actor:
01182         case Uml::lvt_UseCase:
01183         case Uml::lvt_UseCase_Diagram:
01184             accept = (dstType == Uml::lvt_UseCase_Folder ||
01185                       dstType == Uml::lvt_UseCase_View);
01186             break;
01187         case Uml::lvt_Subsystem:
01188             accept = (dstType == Uml::lvt_Component_Folder ||
01189                       dstType == Uml::lvt_Subsystem);
01190             break;
01191         case Uml::lvt_Component:
01192             accept = (dstType == Uml::lvt_Component_Folder ||
01193                       dstType == Uml::lvt_Component ||
01194                       dstType == Uml::lvt_Subsystem);
01195             break;
01196         case Uml::lvt_Artifact:
01197         case Uml::lvt_Component_Diagram:
01198             accept = (dstType == Uml::lvt_Component_Folder ||
01199                       dstType == Uml::lvt_Component_View);
01200             break;
01201         case Uml::lvt_Node:
01202         case Uml::lvt_Deployment_Diagram:
01203             accept = (dstType == Uml::lvt_Deployment_Folder);
01204             break;
01205         case Uml::lvt_Entity:
01206         case Uml::lvt_EntityRelationship_Diagram:
01207             accept = (dstType == Uml::lvt_EntityRelationship_Folder);
01208             break;
01209         default:
01210             accept = false;
01211             break;
01212         }
01213     }
01214 
01215     //kDebug() << "UMLListView::acceptDrag: dstType = " << dstType
01216     //    << ", accept=" << accept << endl;
01217     return accept;
01218 }
01219 
01220 void UMLListView::addAtContainer(UMLListViewItem *item, UMLListViewItem *parent) {
01221     UMLCanvasObject *o = static_cast<UMLCanvasObject*>(item->getUMLObject());
01222     if (o == NULL) {
01223         kDebug() << "UMLListView::addAtContainer(" << item->getText()
01224             << "): item's UMLObject is NULL" << endl;
01225     } else if (Model_Utils::typeIsContainer(parent->getType())) {
01226         /**** TBC: Do this here?
01227                    If yes then remove that logic at the callers
01228                    and rename this method to moveAtContainer()
01229         UMLPackage *oldPkg = o->getUMLPackage();
01230         if (oldPkg)
01231             oldPkg->removeObject(o);
01232          *********/
01233         UMLPackage *pkg = static_cast<UMLPackage*>(parent->getUMLObject());
01234         o->setUMLPackage(pkg);
01235         pkg->addObject(o);
01236     } else {
01237         kError() << "UMLListView::addAtContainer(" << item->getText()
01238             << "): parent type is " << parent->getType() << endl;
01239     }
01240     UMLView *currentView = UMLApp::app()->getCurrentView();
01241     if (currentView)
01242         currentView->updateContainment(o);
01243 }
01244 
01245 UMLListViewItem * UMLListView::moveObject(Uml::IDType srcId, Uml::ListView_Type srcType,
01246                                           UMLListViewItem *newParent) {
01247     if (newParent == NULL)
01248         return NULL;
01249     UMLListViewItem * move = findItem( srcId );
01250     if (move == NULL)
01251         return NULL;
01252 
01253     UMLObject *newParentObj = NULL;
01254     // Remove the source object at the old parent package.
01255     UMLObject *srcObj = m_doc->findObjectById(srcId);
01256     if (srcObj) {
01257         newParentObj = newParent->getUMLObject();
01258         if (srcObj == newParentObj) {
01259             kError() << "UMLListView::moveObject(" << srcObj->getName()
01260                 << "): Cannot move onto self" << endl;
01261             return NULL;
01262         }
01263         UMLPackage *srcPkg = srcObj->getUMLPackage();
01264         if (srcPkg) {
01265             if (srcPkg == newParentObj) {
01266                 kError() << "UMLListView::moveObject(" << srcObj->getName()
01267                     << "): Object is already in target package" << endl;
01268                 return NULL;
01269             }
01270             srcPkg->removeObject(srcObj);
01271         }
01272     }
01273 
01274     Uml::ListView_Type newParentType = newParent->getType();
01275     kDebug() << "UMLListView::moveObject: newParentType is " << newParentType << endl;
01276     UMLListViewItem *newItem = NULL;
01277 
01278     //make sure trying to place in correct location
01279     switch (srcType) {
01280     case Uml::lvt_UseCase_Folder:
01281     case Uml::lvt_Actor:
01282     case Uml::lvt_UseCase:
01283     case Uml::lvt_UseCase_Diagram:
01284         if (newParentType == Uml::lvt_UseCase_Folder ||
01285                 newParentType == Uml::lvt_UseCase_View) {
01286             newItem = move->deepCopy(newParent);
01287             if (m_doc->loading())         // deletion is not safe while loading
01288                 move->setVisible(false);  // (the <listview> XMI may be corrupted)
01289             else
01290                 delete move;
01291             addAtContainer(newItem, newParent);
01292         }
01293         break;
01294     case Uml::lvt_Component_Folder:
01295     case Uml::lvt_Artifact:
01296     case Uml::lvt_Component_Diagram:
01297         if (newParentType == Uml::lvt_Component_Folder ||
01298                 newParentType == Uml::lvt_Component_View) {
01299             newItem = move->deepCopy(newParent);
01300             if (m_doc->loading())         // deletion is not safe while loading
01301                 move->setVisible(false);  // (the <listview> XMI may be corrupted)
01302             else
01303                 delete move;
01304             addAtContainer(newItem, newParent);
01305         }
01306         break;
01307     case Uml::lvt_Subsystem:
01308         if (newParentType == Uml::lvt_Component_Folder ||
01309             newParentType == Uml::lvt_Component_View ||
01310             newParentType == Uml::lvt_Subsystem) {
01311             newItem = move->deepCopy(newParent);
01312             if (m_doc->loading())         // deletion is not safe while loading
01313                 move->setVisible(false);  // (the <listview> XMI may be corrupted)
01314             else
01315                 delete move;
01316             addAtContainer(newItem, newParent);
01317         }
01318         break;
01319     case Uml::lvt_Component:
01320         if (newParentType == Uml::lvt_Component_Folder ||
01321             newParentType == Uml::lvt_Component_View ||
01322             newParentType == Uml::lvt_Component ||
01323             newParentType == Uml::lvt_Subsystem) {
01324             newItem = move->deepCopy(newParent);
01325             if (m_doc->loading())         // deletion is not safe while loading
01326                 move->setVisible(false);  // (the <listview> XMI may be corrupted)
01327             else
01328                 delete move;
01329             addAtContainer(newItem, newParent);
01330         }
01331         break;
01332     case Uml::lvt_Deployment_Folder:
01333     case Uml::lvt_Node:
01334     case Uml::lvt_Deployment_Diagram:
01335         if (newParentType == Uml::lvt_Deployment_Folder ||
01336                 newParentType == Uml::lvt_Deployment_View) {
01337             newItem = move->deepCopy(newParent);
01338             if (m_doc->loading())         // deletion is not safe while loading
01339                 move->setVisible(false);  // (the <listview> XMI may be corrupted)
01340             else
01341                 delete move;
01342             addAtContainer(newItem, newParent);
01343         }
01344         break;
01345     case Uml::lvt_EntityRelationship_Folder:
01346     case Uml::lvt_Entity:
01347     case Uml::lvt_EntityRelationship_Diagram:
01348         if (newParentType == Uml::lvt_EntityRelationship_Folder ||
01349                 newParentType == Uml::lvt_EntityRelationship_Model) {
01350             newItem = move->deepCopy(newParent);
01351             if (m_doc->loading())         // deletion is not safe while loading
01352                 move->setVisible(false);  // (the <listview> XMI may be corrupted)
01353             else
01354                 delete move;
01355             addAtContainer(newItem, newParent);
01356         }
01357         break;
01358     case Uml::lvt_Collaboration_Diagram:
01359     case Uml::lvt_Class_Diagram:
01360     case Uml::lvt_State_Diagram:
01361     case Uml::lvt_Activity_Diagram:
01362     case Uml::lvt_Sequence_Diagram:
01363     case Uml::lvt_Logical_Folder:
01364         if (newParentType == Uml::lvt_Logical_Folder ||
01365                 newParentType == Uml::lvt_Logical_View) {
01366             newItem = move->deepCopy(newParent);
01367             if (m_doc->loading())         // deletion is not safe while loading
01368                 move->setVisible(false);  // (the <listview> XMI may be corrupted)
01369             else
01370                 delete move;
01371             addAtContainer(newItem, newParent);
01372         }
01373         break;
01374     case Uml::lvt_Class:
01375     case Uml::lvt_Package:
01376     case Uml::lvt_Interface:
01377     case Uml::lvt_Enum:
01378     case Uml::lvt_Datatype:
01379         if (newParentType == Uml::lvt_Logical_Folder ||
01380                 newParentType == Uml::lvt_Datatype_Folder ||
01381                 newParentType == Uml::lvt_Logical_View ||
01382                 newParentType == Uml::lvt_Class ||
01383                 newParentType == Uml::lvt_Interface ||
01384                 newParentType == Uml::lvt_Package) {
01385             newItem = move->deepCopy(newParent);
01386             if (m_doc->loading())         // deletion is not safe while loading
01387                 move->setVisible(false);  // (the <listview> XMI may be corrupted)
01388             else
01389                 delete move;
01390             UMLCanvasObject *o = static_cast<UMLCanvasObject*>(newItem->getUMLObject());
01391             if (o == NULL) {
01392                 kDebug() << "moveObject: newItem's UMLObject is NULL" << endl;
01393             } else if (newParentObj == NULL) {
01394                 kError() << "UMLListView::moveObject(" << o->getName()
01395                     << "): newParentObj is NULL" << endl;
01396             } else {
01397                 UMLPackage *pkg = static_cast<UMLPackage*>(newParentObj);
01398                 o->setUMLPackage( pkg );
01399                 pkg->addObject( o );
01400             }
01401             UMLView *currentView = UMLApp::app()->getCurrentView();
01402             if (currentView)
01403                 currentView->updateContainment(o);
01404         }
01405         break;
01406     case Uml::lvt_Attribute:
01407     case Uml::lvt_Operation:
01408         if (newParentType == Uml::lvt_Class ||
01409                 newParentType == Uml::lvt_Interface) {
01410             // update list view
01411 
01412             newItem = move->deepCopy(newParent);
01413             // we don't delete move right away, it will be deleted in slots,
01414             // called by subsequent steps
01415             //delete move;
01416 
01417             // update model objects
01418             m_bCreatingChildObject = true;
01419 
01420             UMLClassifier *oldParentClassifier = dynamic_cast<UMLClassifier*>(srcObj->parent());
01421             UMLClassifier *newParentClassifier = dynamic_cast<UMLClassifier*>(newParentObj);
01422             if (srcType == Uml::lvt_Attribute) {
01423                 UMLAttribute *att = dynamic_cast<UMLAttribute*>(srcObj);
01424                 // We can't use the existing 'att' directly
01425                 // because its parent is fixed to the old classifier
01426                 // and we have no way of changing that:
01427                 // QObject does not permit changing the parent().
01428                 if (att == NULL) {
01429                     kError() << "moveObject internal error: srcObj "
01430                         << srcObj->getName() << " is not a UMLAttribute" << endl;
01431                 } else if (oldParentClassifier->takeItem(att) == -1) {
01432                     kError() << "moveObject: oldParentClassifier->takeItem(att "
01433                         << att->getName() << ") returns NULL" << endl;
01434                 } else {
01435                     const QString& nm = att->getName();
01436                     UMLAttribute *newAtt = newParentClassifier->createAttribute(nm,
01437                                                                                 att->getType(),
01438                                                                                 att->getVisibility(),
01439                                                                                 att->getInitialValue());
01440                     newItem->setUMLObject(newAtt);
01441                     newParent->addClassifierListItem( newAtt, newItem );
01442 
01443                     connectNewObjectsSlots( newAtt );
01444                     // Let's not forget to update the DocWindow::m_pObject
01445                     // because the old one is about to be physically deleted !
01446                     UMLApp::app()->getDocWindow()->showDocumentation(newAtt, true);
01447                     delete att;
01448                 }
01449             } else {
01450                 UMLOperation *op = dynamic_cast<UMLOperation*>(srcObj);
01451                 // We can't use the existing 'op' directly
01452                 // because its parent is fixed to the old classifier
01453                 // and we have no way of changing that:
01454                 // QObject does not permit changing the parent().
01455                 if (op && oldParentClassifier->takeItem(op) != -1) {
01456                     bool isExistingOp;
01457                     Model_Utils::NameAndType_List ntDummyList;
01458                     // We need to provide a dummy NameAndType_List
01459                     // else UMLClassifier::createOperation will
01460                     // bring up an operation dialog.
01461                     UMLOperation *newOp = newParentClassifier->createOperation(
01462                                               op->getName(), &isExistingOp, &ntDummyList);
01463                     newOp->setType(op->getType());
01464                     newOp->setVisibility(op->getVisibility());
01465                     UMLAttributeList parmList = op->getParmList();
01466                     for (UMLAttributeListIt plit(parmList); plit.current(); ++plit) {
01467                         UMLAttribute *parm = plit.current();
01468                         UMLAttribute *newParm = new UMLAttribute(newParentClassifier,
01469                                                                  parm->getName(),
01470                                                                  Uml::id_None,
01471                                                                  parm->getVisibility(),
01472                                                                  parm->getType(),
01473                                                                  parm->getInitialValue());
01474                         newParm->setParmKind(parm->getParmKind());
01475                         newOp->addParm(newParm);
01476                     }
01477                     newItem->setUMLObject(newOp);
01478                     newParent->addClassifierListItem( newOp, newItem );
01479 
01480                     connectNewObjectsSlots( newOp );
01481 
01482                     // Let's not forget to update the DocWindow::m_pObject
01483                     // because the old one is about to be physically deleted !
01484                     UMLApp::app()->getDocWindow()->showDocumentation(newOp, true);
01485                     delete op;
01486                 } else {
01487                     kError() << "moveObject: oldParentClassifier->takeItem(op) returns NULL"
01488                         << endl;
01489                 }
01490             }
01491             m_bCreatingChildObject = false;
01492         }
01493         break;
01494     default:
01495         break;
01496     }
01497     return newItem;
01498 }
01499 
01500 void UMLListView::slotDropped(QDropEvent* de, QListViewItem* /* parent */, QListViewItem* item) {
01501     item = (UMLListViewItem *)currentItem();
01502     if(!item) {
01503         kDebug() << "UMLListView::slotDropped: item is NULL - doing nothing" << endl;
01504         return;
01505     }
01506     UMLDrag::LvTypeAndID_List srcList;
01507     if (! UMLDrag::getClip3TypeAndID(de, srcList)) {
01508         return;
01509     }
01510     UMLListViewItem *newParent = (UMLListViewItem*)item;
01511     kDebug() << "slotDropped: newParent->getText() is " << newParent->getText() << endl;
01512     UMLDrag::LvTypeAndID_It it(srcList);
01513     UMLDrag::LvTypeAndID * src = 0;
01514     while((src = it.current()) != 0) {
01515         ++it;
01516         moveObject(src->id, src->type, newParent);
01517     }
01518 }
01519 
01520 int UMLListView::getSelectedItems(UMLListViewItemList &ItemList) {
01521     ItemList.setAutoDelete( false );
01522     QListViewItemIterator it(this);
01523     // iterate through all items of the list view
01524     for ( ; it.current(); ++it ) {
01525         if ( it.current()->isSelected() ) {
01526             UMLListViewItem *item = (UMLListViewItem*)it.current();
01527             ItemList.append(item);
01528         }
01529     }
01530     kDebug() << "UMLListView::getSelectedItems: selItems = " << ItemList.count() << endl;
01531 
01532     return (int)ItemList.count();
01533 }
01534 
01535 int UMLListView::getSelectedItemsRoot(UMLListViewItemList &ItemList) {
01536     ItemList.setAutoDelete( false );
01537     QListViewItemIterator it(this);
01538 
01539     // iterate through all items of the list view
01540     for ( ; it.current(); ++it ) {
01541         if ( it.current()->isSelected() ) {
01542             UMLListViewItem *item = (UMLListViewItem*)it.current();
01543             // this is the trick, we select only the item with a parent unselected
01544             // since we can't select a child and its grandfather without its parent
01545             // we would be able to delete each item individually, without an invalid iterator
01546             if (item && item->parent() && item->parent()->isSelected()==false) {
01547               ItemList.append(item);
01548             }
01549         }
01550     }
01551     kDebug() << "UMLListView::getSelectedItemsRoot: selItems = " << ItemList.count() << endl;
01552 
01553     return (int)ItemList.count();
01554 }
01555 
01556 UMLListViewItem* UMLListView::createDiagramItem(UMLView *v) {
01557     Uml::ListView_Type lvt = Model_Utils::convert_DT_LVT(v->getType());
01558     UMLListViewItem *parent = NULL;
01559     UMLFolder *f = v->getFolder();
01560     if (f) {
01561         parent = findUMLObject(f);
01562         if (parent == NULL)
01563             kError() << "UMLListView::createDiagramItem(" << v->getName()
01564                 << "): findUMLObject(" << f->getName() << ") returns NULL"
01565                 << endl;
01566     } else {
01567         kDebug() << "UMLListView::createDiagramItem(" << v->getName()
01568             << "): no parent folder set, using predefined folder" << endl;
01569     }
01570     if (parent == NULL) {
01571         parent = determineParentItem(lvt);
01572         lvt = Model_Utils::convert_DT_LVT(v->getType());
01573     }
01574     UMLListViewItem *item = new UMLListViewItem(parent, v->getName(), lvt, v->getID());
01575     return item;
01576 }
01577 
01581 UMLListViewItem* UMLListView::createItem(UMLListViewItem& Data, IDChangeLog& IDChanges,
01582         UMLListViewItem* parent /*= 0*/) {
01583     UMLObject* pObject = 0;
01584     UMLListViewItem* item = 0;
01585     Uml::ListView_Type lvt = Data.getType();
01586     if(!parent) {
01587         parent = determineParentItem(lvt);
01588         if (!parent)
01589             return 0;
01590     }
01591 
01592     switch(lvt) {
01593     case Uml::lvt_Actor:
01594     case Uml::lvt_UseCase:
01595     case Uml::lvt_Class:
01596     case Uml::lvt_Package:
01597     case Uml::lvt_Subsystem:
01598     case Uml::lvt_Component:
01599     case Uml::lvt_Node:
01600     case Uml::lvt_Artifact:
01601     case Uml::lvt_Interface:
01602     case Uml::lvt_Datatype:
01603     case Uml::lvt_Enum:
01604     case Uml::lvt_Entity:
01605     case Uml::lvt_Logical_Folder:
01606     case Uml::lvt_UseCase_Folder:
01607     case Uml::lvt_Component_Folder:
01608     case Uml::lvt_Deployment_Folder:
01609     case Uml::lvt_EntityRelationship_Folder:
01610         /***
01611         int newID = IDChanges.findNewID(Data.getID());
01612         //if there is no ListViewItem associated with the new ID,
01613         //it could exist an Item already asocciated if the user chose to reuse an uml object
01614         if(!(item = findItem(newID))) {
01615                 pObject = m_doc->findObjectById( IDChanges.findNewID(Data.getID()) );
01616                 item = new UMLListViewItem(parent, Data.getText(), lvt, pObject);
01617         } ***/
01618         pObject = m_doc->findObjectById( Data.getID() );
01619         item = new UMLListViewItem(parent, Data.getText(), lvt, pObject);
01620         break;
01621     case Uml::lvt_Datatype_Folder:
01622         item = new UMLListViewItem(parent, Data.getText(), lvt);
01623         break;
01624     case Uml::lvt_Attribute:
01625     case Uml::lvt_EntityAttribute:
01626     case Uml::lvt_Operation:
01627     case Uml::lvt_Template:
01628     case Uml::lvt_EnumLiteral:
01629         {
01630             UMLClassifier *pClass =  static_cast<UMLClassifier*>(parent->getUMLObject());
01631             Uml::IDType newID = IDChanges.findNewID( Data.getID() );
01632             pObject = pClass->findChildObjectById(newID);
01633             if (pObject) {
01634                 item = new UMLListViewItem( parent, Data.getText(), lvt, pObject );
01635             } else {
01636                 item = 0;
01637             }
01638             break;
01639         }
01640     case Uml::lvt_UseCase_Diagram:
01641     case Uml::lvt_Sequence_Diagram:
01642     case Uml::lvt_Collaboration_Diagram:
01643     case Uml::lvt_Class_Diagram:
01644     case Uml::lvt_State_Diagram:
01645     case Uml::lvt_Activity_Diagram:
01646     case Uml::lvt_Component_Diagram:
01647     case Uml::lvt_Deployment_Diagram:
01648     case Uml::lvt_EntityRelationship_Diagram:
01649         {
01650             Uml::IDType newID = IDChanges.findNewID(Data.getID());
01651             UMLView* v = m_doc->findView(newID);
01652             if (v == NULL) {
01653                 return NULL;
01654             }
01655             const Uml::ListView_Type lvt = Model_Utils::convert_DT_LVT(v->getType());
01656             item = new UMLListViewItem(parent, v->getName(), lvt, newID);
01657         }
01658         break;
01659     default:
01660         kWarning() << "createItem() called on unknown type" << endl;
01661         break;
01662     }
01663     return item;
01664 }
01665 
01666 UMLListViewItem* UMLListView::determineParentItem(Uml::ListView_Type lvt) const {
01667     UMLListViewItem* parent = 0;
01668     switch (lvt) {
01669     case Uml::lvt_Datatype:
01670         parent = m_datatypeFolder;
01671         break;
01672     case Uml::lvt_Actor:
01673     case Uml::lvt_UseCase:
01674     case Uml::lvt_UseCase_Folder:
01675     case Uml::lvt_UseCase_Diagram:
01676         parent = m_lv[Uml::mt_UseCase];
01677         break;
01678     case Uml::lvt_Component_Diagram:
01679     case Uml::lvt_Component:
01680     case Uml::lvt_Artifact:
01681         parent = m_lv[Uml::mt_Component];
01682         break;
01683     case Uml::lvt_Deployment_Diagram:
01684     case Uml::lvt_Node:
01685         parent = m_lv[Uml::mt_Deployment];
01686         break;
01687     case Uml::lvt_EntityRelationship_Diagram:
01688     case Uml::lvt_Entity:
01689         parent = m_lv[Uml::mt_EntityRelationship];
01690         break;
01691     default:
01692         if (Model_Utils::typeIsDiagram(lvt) || !Model_Utils::typeIsClassifierList(lvt))
01693             parent = m_lv[Uml::mt_Logical];
01694         break;
01695     }
01696     return parent;
01697 }
01698 
01699 int UMLListView::getSelectedCount() {
01700     QListViewItemIterator it(this);
01701     int count = 0;
01702     // iterate through all items of the list view
01703     for ( ; it.current(); ++it ) {
01704         if ( it.current()->isSelected() ) {
01705             count++;
01706         }
01707     }
01708 
01709     return count;
01710 }
01711 
01712 void UMLListView::focusOutEvent ( QFocusEvent * fe) {
01713     QFocusEvent::Reason reason = fe->reason();
01714     if (reason != QFocusEvent::Popup) {
01715         clearSelection();
01716         triggerUpdate();
01717     }
01718     //repaint();
01719 
01720     QListView::focusOutEvent(fe);
01721 }
01722 
01723 Uml::ListView_Type UMLListView::rootViewType(UMLListViewItem *item) {
01724     if (item == m_rv)
01725         return Uml::lvt_View;
01726     if (item == m_lv[Uml::mt_Logical])
01727         return Uml::lvt_Logical_View;
01728     if (item == m_lv[Uml::mt_UseCase])
01729         return Uml::lvt_UseCase_View;
01730     if (item == m_lv[Uml::mt_Component])
01731         return Uml::lvt_Component_View;
01732     if (item == m_lv[Uml::mt_Deployment])
01733         return Uml::lvt_Deployment_View;
01734     if (item == m_lv[Uml::mt_EntityRelationship])
01735         return Uml::lvt_EntityRelationship_Model;
01736     UMLListViewItem *parent = dynamic_cast<UMLListViewItem*>(item->parent());
01737     if (parent)
01738         return rootViewType(parent);
01739     return Uml::lvt_Unknown;
01740 }
01741 
01742 QPixmap & UMLListView::getPixmap(Uml::Icon_Type type) {
01743     if (type < Uml::it_Home || type >= Uml::N_ICONTYPES) {
01744         kWarning() << "getPixmap() called on unknown icon " << type << endl;
01745         // you'll know you have a problem if this shows up in the list
01746         type = Uml::it_Home;
01747     }
01748     return m_Pixmaps[type];
01749 }
01750 
01751 void UMLListView::loadPixmaps() {
01752     KStandardDirs * dirs = KGlobal::dirs();
01753     QString dataDir = dirs -> findResourceDir("data", "umbrello/pics/object.png");
01754     dataDir += "/umbrello/pics/";
01755 
01756 #define makeBarIcon(iconType, barIcon)   m_Pixmaps[iconType] = BarIcon(barIcon)
01757     makeBarIcon(Uml::it_Home,               "folder_home");
01758     makeBarIcon(Uml::it_Folder_Cyan,        "folder");
01759     makeBarIcon(Uml::it_Folder_Cyan_Open,   "folder_open");
01760     makeBarIcon(Uml::it_Folder_Green,       "folder_green");
01761     makeBarIcon(Uml::it_Folder_Green_Open,  "folder_green_open");
01762     makeBarIcon(Uml::it_Folder_Orange,      "folder_orange");
01763     makeBarIcon(Uml::it_Folder_Orange_Open, "folder_orange_open");
01764     makeBarIcon(Uml::it_Folder_Grey,        "folder_grey");
01765     makeBarIcon(Uml::it_Folder_Grey_Open,   "folder_grey_open");
01766     makeBarIcon(Uml::it_Folder_Red,         "folder_red");
01767     makeBarIcon(Uml::it_Folder_Red_Open,    "folder_red_open");
01768     makeBarIcon(Uml::it_Folder_Violet,      "folder_violet");
01769     makeBarIcon(Uml::it_Folder_Violet_Open, "folder_violet_open");
01770 
01771     makeBarIcon(Uml::it_Diagram_Activity,           "umbrello_diagram_activity");
01772     makeBarIcon(Uml::it_Diagram_Class,              "umbrello_diagram_class");
01773     makeBarIcon(Uml::it_Diagram_Component,          "umbrello_diagram_component");
01774     makeBarIcon(Uml::it_Diagram_State,              "umbrello_diagram_state");
01775     makeBarIcon(Uml::it_Diagram_Sequence,           "umbrello_diagram_sequence");
01776     makeBarIcon(Uml::it_Diagram_Deployment,         "umbrello_diagram_deployment");
01777     makeBarIcon(Uml::it_Diagram_EntityRelationship, "umbrello_diagram_deployment");
01778     makeBarIcon(Uml::it_Diagram_Usecase,            "umbrello_diagram_usecase");
01779     makeBarIcon(Uml::it_Diagram_Collaboration,      "umbrello_diagram_collaboration");
01780 #undef makeBarIcon
01781 
01782 #define loadPixmap(iconType, pngName)   m_Pixmaps[iconType].load(dataDir + pngName)
01783     loadPixmap(Uml::it_Diagram,    "CVnamespace.png");
01784     loadPixmap(Uml::it_Class,      "class.png");
01785     loadPixmap(Uml::it_Template,   "template.png");
01786     loadPixmap(Uml::it_Package,    "package.png");
01787     loadPixmap(Uml::it_Subsystem,  "subsystem.png");
01788     loadPixmap(Uml::it_Component,  "component.png");
01789     loadPixmap(Uml::it_Node,       "node.png");
01790     loadPixmap(Uml::it_Artifact,   "artifact.png");
01791     loadPixmap(Uml::it_Interface,  "interface.png");
01792     loadPixmap(Uml::it_Datatype,   "datatype.png");
01793     loadPixmap(Uml::it_Enum,       "enum.png");
01794     loadPixmap(Uml::it_Entity,     "entity.png");
01795     loadPixmap(Uml::it_Actor,      "actor.png");
01796     loadPixmap(Uml::it_UseCase,    "usecase.png");
01797     loadPixmap(Uml::it_Public_Method,  "CVpublic_meth.png");
01798     loadPixmap(Uml::it_Private_Method,  "CVprivate_meth.png");
01799     loadPixmap(Uml::it_Protected_Method, "CVprotected_meth.png");
01800     loadPixmap(Uml::it_Public_Attribute,  "CVpublic_var.png");
01801     loadPixmap(Uml::it_Private_Attribute,  "CVprivate_var.png");
01802     loadPixmap(Uml::it_Protected_Attribute, "CVprotected_var.png");
01803 #undef loadPixmap
01804 }
01805 
01806 bool UMLListView::isExpandable(Uml::ListView_Type lvt) {
01807     if (Model_Utils::typeIsRootView(lvt) || Model_Utils::typeIsFolder(lvt))
01808         return true;
01809     switch (lvt) {
01810         case Uml::lvt_Package:
01811         case Uml::lvt_Component:
01812         case Uml::lvt_Subsystem:
01813             return true;
01814             break;
01815         default:
01816             break;
01817     }
01818     return false;
01819 }
01820 
01821 void UMLListView::slotExpanded( QListViewItem * item ) {
01822     UMLListViewItem * myItem= static_cast<UMLListViewItem*>(item);
01823     if (isExpandable(myItem->getType()))
01824         myItem->updateFolder();
01825 }
01826 
01827 void UMLListView::slotCollapsed( QListViewItem * item ) {
01828     UMLListViewItem * myItem = static_cast<UMLListViewItem*>(item);
01829     if (isExpandable(myItem->getType()))
01830         myItem->updateFolder();
01831 }
01832 
01833 void UMLListView::slotCutSuccessful() {
01834     if( m_bStartedCut ) {
01835         popupMenuSel( ListPopupMenu::mt_Delete );
01836         //deletion code here
01837         m_bStartedCut = false;
01838     }
01839 }
01840 
01841 void UMLListView::addNewItem(UMLListViewItem *parentItem, Uml::ListView_Type type) {
01842      if (type == Uml::lvt_Datatype) {
01843          parentItem = m_datatypeFolder;
01844      }
01845 
01846     UMLPackage *parentPkg = dynamic_cast<UMLPackage*>(parentItem->getUMLObject());
01847     if (parentPkg == NULL)
01848         kError() << "UMLListView::addNewItem(type " << type
01849             << "): parentPkg is NULL" << endl;
01850     UMLListViewItem * newItem = NULL;
01851     parentItem->setOpen( true );
01852 
01853     Uml::Icon_Type icon = Model_Utils::convert_LVT_IT(type);
01854 
01855     QString name;
01856     if (Model_Utils::typeIsDiagram(type)) {
01857         Uml::Diagram_Type dt = Model_Utils::convert_LVT_DT(type);
01858         name = getUniqueDiagramName(dt);
01859         newItem = new UMLListViewItem(parentItem, name, type, Uml::id_None);
01860     } else {
01861         Uml::Object_Type ot = Model_Utils::convert_LVT_OT(type);
01862         if (ot == Uml::ot_UMLObject) {
01863             kDebug() << "UMLListView::addNewItem: no UMLObject for listview type "
01864                 << type << endl;
01865             return;
01866         }
01867         if (Model_Utils::typeIsClassifierList(type)) {
01868             UMLClassifier *parent = static_cast<UMLClassifier*>(parentPkg);
01869             name = parent->uniqChildName(ot);
01870         } else {
01871             name = Model_Utils::uniqObjectName(ot, parentPkg);
01872         }
01873         newItem = new UMLListViewItem(parentItem, name, type, (UMLObject*)0);
01874         newItem->setIcon(icon);
01875     }
01876     m_bIgnoreCancelRename = false;
01877     newItem->setIcon( icon );
01878     newItem->setOpen( true );
01879     newItem->setCreating( true );
01880     newItem->startRename( 0 );  // calls QListView::ensureItemVisible()
01881     // When the user accepts the rename operation, UMLListViewItem::okRename()
01882     // is called (automatically by QListViewItem.)
01883 }
01884 
01885 bool UMLListView::itemRenamed( QListViewItem * item , int /*col*/ ) {
01886     //if true the item was cancel before this message
01887     if( m_bIgnoreCancelRename ) {
01888         return true;
01889     }
01890     m_bIgnoreCancelRename = true;
01891     UMLListViewItem * renamedItem = static_cast< UMLListViewItem *>( item ) ;
01892     Uml::ListView_Type type = renamedItem -> getType();
01893     QString newText = renamedItem -> text( 0 );
01894     renamedItem -> setCreating( false );
01895 
01896     // If the type is empty then delete it.
01897     if (newText.isEmpty() || newText.contains(QRegExp("^\\s+$"))) {
01898         KMessageBox::error(
01899             kapp -> mainWidget(),
01900             i18n( "The name you entered was invalid.\nCreation process has been canceled." ),
01901             i18n( "Name Not Valid" ) );
01902         return false;
01903     }
01904 
01905     if( !isUnique( renamedItem, newText ) ) {
01906         //if operation ask if ok not to be unique i.e overloading
01907         if( type == Uml::lvt_Operation ) {
01908             if( KMessageBox::warningYesNo(
01909                         kapp -> mainWidget(),
01910                         i18n( "The name you entered was not unique.\nIs this what you wanted?" ),
01911                         i18n( "Name Not Unique" ), i18n("Use Name"), i18n("Enter New Name") ) == KMessageBox::No ) {
01912                 return false;
01913             }
01914         } else {
01915             KMessageBox::error(
01916                 kapp -> mainWidget(),
01917                 i18n( "The name you entered was not unique!\nCreation process has been canceled." ),
01918                 i18n( "Name Not Unique" ) );
01919             return false;
01920         }
01921     }
01922 
01923     switch( type ) {
01924     case Uml::lvt_Actor:
01925     case Uml::lvt_Class:
01926     case Uml::lvt_Package:
01927     case Uml::lvt_Logical_Folder:
01928     case Uml::lvt_UseCase_Folder:
01929     case Uml::lvt_Component_Folder:
01930     case Uml::lvt_Deployment_Folder:
01931     case Uml::lvt_EntityRelationship_Folder:
01932     case Uml::lvt_Subsystem:
01933     case Uml::lvt_Component:
01934     case Uml::lvt_Node:
01935     case Uml::lvt_Artifact:
01936     case Uml::lvt_Interface:
01937     case Uml::lvt_Datatype:
01938     case Uml::lvt_Enum:
01939     case Uml::lvt_Entity:
01940     case Uml::lvt_UseCase:
01941         {
01942             Uml::Object_Type ot = Model_Utils::convert_LVT_OT(type);
01943             if (! ot) {
01944                 kError() << "UMLListView::itemRenamed() internal" << endl;
01945                 return false;
01946             }
01947             UMLObject *o = createUMLObject( renamedItem, ot );
01948             if (type == Uml::lvt_Subsystem)
01949                 o->setStereotype("subsystem");
01950             else if (Model_Utils::typeIsFolder(type))
01951                 o->setStereotype("folder");
01952         }
01953         break;
01954 
01955     case Uml::lvt_Attribute:
01956     case Uml::lvt_EntityAttribute:
01957     case Uml::lvt_Operation:
01958     case Uml::lvt_Template:
01959     case Uml::lvt_EnumLiteral:
01960         return createChildUMLObject( renamedItem, Model_Utils::convert_LVT_OT(type) );
01961         break;
01962 
01963     case Uml::lvt_Class_Diagram:
01964         createDiagram( renamedItem, Uml::dt_Class );
01965         break;
01966 
01967     case Uml::lvt_UseCase_Diagram:
01968         createDiagram( renamedItem, Uml::dt_UseCase );
01969         break;
01970 
01971     case Uml::lvt_Sequence_Diagram:
01972         createDiagram( renamedItem, Uml::dt_Sequence );
01973         break;
01974 
01975     case Uml::lvt_Collaboration_Diagram:
01976         createDiagram( renamedItem, Uml::dt_Collaboration );
01977         break;
01978 
01979     case Uml::lvt_State_Diagram:
01980         createDiagram( renamedItem, Uml::dt_State );
01981         break;
01982 
01983     case Uml::lvt_Activity_Diagram:
01984         createDiagram( renamedItem, Uml::dt_Activity );
01985         break;
01986 
01987     case Uml::lvt_Component_Diagram:
01988         createDiagram( renamedItem, Uml::dt_Component );
01989         break;
01990 
01991     case Uml::lvt_Deployment_Diagram:
01992         createDiagram( renamedItem, Uml::dt_Deployment );
01993         break;
01994 
01995     case Uml::lvt_EntityRelationship_Diagram:
01996         createDiagram( renamedItem, Uml::dt_EntityRelationship );
01997         break;
01998 
01999     default:
02000         break;
02001     }
02002     return true;
02003 }
02004 
02005 UMLObject *UMLListView::createUMLObject( UMLListViewItem * item, Uml::Object_Type type ) {
02006     QString name = item -> text( 0 );
02007     UMLObject * object = NULL;
02008     switch( type ) {
02009     case Uml::ot_UseCase:
02010         object = new UMLUseCase( name );
02011         break;
02012 
02013     case Uml::ot_Actor:
02014         object = new UMLActor( name );
02015         break;
02016 
02017     case Uml::ot_Class:
02018         object = new UMLClassifier( name );
02019         break;
02020 
02021     case Uml::ot_Package:
02022         object = new UMLPackage( name );
02023         break;
02024 
02025     case Uml::ot_Folder:
02026         object = new UMLFolder( name );
02027         break;
02028 
02029     case Uml::ot_Component:
02030         object = new UMLComponent( name );
02031         break;
02032 
02033     case Uml::ot_Node:
02034         object = new UMLNode( name );
02035         break;
02036 
02037     case Uml::ot_Artifact:
02038         object = new UMLArtifact( name );
02039         break;
02040 
02041     case Uml::ot_Interface:
02042         {
02043             UMLClassifier *c = new UMLClassifier(name);
02044             c->setBaseType(Uml::ot_Interface);
02045             object = c;
02046         }
02047         break;
02048 
02049     case Uml::ot_Datatype:
02050         {
02051             UMLClassifier *c = new UMLClassifier(name);
02052             c->setBaseType(Uml::ot_Datatype);
02053             object = c;
02054         }
02055         break;
02056 
02057     case Uml::ot_Enum:
02058         object = new UMLEnum( name );
02059         break;
02060 
02061     case Uml::ot_Entity:
02062         object = new UMLEntity( name );
02063         break;
02064 
02065     default:
02066         kWarning() << "creating UML Object of unknown type" << endl;
02067         return NULL;
02068     }
02069 
02070     UMLListViewItem * parentItem = static_cast<UMLListViewItem *>(item->parent());
02071     const Uml::ListView_Type lvt = parentItem->getType();
02072     if (! Model_Utils::typeIsContainer(lvt)) {
02073         kError() << "UMLListView::createUMLObject(" << object->getName()
02074             << "): parentItem (" << lvt << " is not a container" << endl;
02075         delete object;
02076         return NULL;
02077     }
02078     UMLPackage *pkg = static_cast<UMLPackage*>(parentItem->getUMLObject());
02079     object->setUMLPackage(pkg);
02080     pkg->addObject(object);
02081     connectNewObjectsSlots(object);
02082     item -> setUMLObject( object );
02083     item -> setText( name );
02084     return object;
02085 }
02086 
02087 bool UMLListView::createChildUMLObject( UMLListViewItem * item, Uml::Object_Type type ) {
02088     m_bCreatingChildObject = true;
02089     QString text = item->text( 0 );
02090     UMLObject* parent = static_cast<UMLListViewItem *>( item->parent() )->getUMLObject();
02091     if( !parent ) {
02092         kError() << "UMLListView::createChildUMLObject: parent UMLObject is NULL" << endl;
02093         m_bCreatingChildObject = false;
02094         return false;
02095     }
02096 
02097     //kDebug() << "UMLListView::createChildUMLObject (" << text << ")" << endl;
02098     UMLObject* newObject = NULL;
02099     if ( type == Uml::ot_Template )  {
02100         UMLClassifier *owningClassifier = static_cast<UMLClassifier*>(parent);
02101         Model_Utils::NameAndType nt;
02102         Model_Utils::Parse_Status st = Model_Utils::parseTemplate(text, nt, owningClassifier);
02103         if (st) {
02104             KMessageBox::error( kapp->mainWidget(),
02105                                 Model_Utils::psText(st),
02106                                 i18n("Creation canceled") );
02107             m_bCreatingChildObject = false;
02108             return false;
02109         }
02110         newObject = owningClassifier->createTemplate(nt.m_name);
02111         UMLTemplate *tmplParm = static_cast<UMLTemplate*>(newObject);
02112         tmplParm->setType(nt.m_type);
02113         text = tmplParm->toString(Uml::st_SigNoVis);
02114     } else if (type == Uml::ot_Attribute || type == Uml::ot_EntityAttribute)  {
02115         UMLClassifier *owningClass = static_cast<UMLClassifier*>(parent);
02116         Model_Utils::NameAndType nt;
02117         Uml::Visibility vis;
02118         Model_Utils::Parse_Status st;
02119         st = Model_Utils::parseAttribute(text, nt, owningClass, &vis);
02120         if (st) {
02121             KMessageBox::error( kapp->mainWidget(),
02122                                 Model_Utils::psText(st),
02123                                 i18n("Creation canceled") );
02124             m_bCreatingChildObject = false;
02125             return false;
02126         }
02127         newObject = owningClass->createAttribute(nt.m_name, nt.m_type, vis, nt.m_initialValue);
02128         UMLAttribute *att = static_cast<UMLAttribute*>(newObject);
02129         att->setParmKind(nt.m_direction);
02130         text = att->toString(Uml::st_SigNoVis);
02131     } else if ( type == Uml::ot_Operation ) {
02132         UMLClassifier *owningClassifier = static_cast<UMLClassifier*>(parent);
02133         Model_Utils::OpDescriptor od;
02134         Model_Utils::Parse_Status st = Model_Utils::parseOperation(text, od, owningClassifier);
02135         if (st) {
02136             KMessageBox::error( kapp->mainWidget(),
02137                                 Model_Utils::psText(st),
02138                                 i18n("Creation canceled") );
02139             m_bCreatingChildObject = false;
02140             return false;
02141         }
02142         bool isExistingOp = false;
02143         newObject = owningClassifier->createOperation(od.m_name, &isExistingOp, &od.m_args);
02144         if (newObject == NULL || isExistingOp) {
02145             if (isExistingOp)
02146                 KMessageBox::error(
02147                     kapp -> mainWidget(),
02148                     i18n( "The name you entered was not unique!\nCreation process has been canceled." ),
02149                     i18n( "Name Not Unique" ) );
02150             m_bCreatingChildObject = false;
02151             return false;
02152         }
02153         UMLOperation *op = static_cast<UMLOperation*>(newObject);
02154         if (od.m_pReturnType) {
02155             op->setType(od.m_pReturnType);
02156         }
02157         text = op->toString(Uml::st_SigNoVis);
02158     } else {
02159         kError() << "UMLListView::createChildUMLObject called for type "
02160             << type << " (ignored)" << endl;
02161         m_bCreatingChildObject = false;
02162         return false;
02163     }
02164 
02165     // make changes to the object visible to this umllistviewitem
02166     connectNewObjectsSlots( newObject );
02167     item->setUMLObject( newObject );
02168     item->setText( text );
02169     ensureItemVisible(item);
02170 
02171     // as it's a ClassifierListItem add it to the childObjectMap of the parent
02172     UMLClassifierListItem* classifierListItem = static_cast<UMLClassifierListItem*>( newObject );
02173     static_cast<UMLListViewItem*>( item->parent() )->addClassifierListItem(classifierListItem, item );
02174 
02175     m_bCreatingChildObject = false;
02176 
02177     if (! m_doc->loading())
02178         m_doc->setModified();
02179     return true;
02180 }
02181 
02182 void UMLListView::createDiagram( UMLListViewItem * item, Uml::Diagram_Type type ) {
02183     QString name = item -> text( 0 );
02184     UMLView * view = m_doc -> findView( type, name );
02185     if( view ) {
02186         delete item;
02187         return;
02188     }
02189     UMLListViewItem *parentItem = static_cast<UMLListViewItem*>(item->parent());
02190     UMLFolder *parentFolder = dynamic_cast<UMLFolder*>(parentItem->getUMLObject());
02191     if (parentFolder == NULL) {
02192         kError() << "UMLListView::createDiagram(" << name
02193             << "): parent UMLObject is not a UMLFolder" << endl;
02194         delete item;
02195         return;
02196     }
02197     view = new UMLView(parentFolder);
02198     view->setName( name );
02199     view->setType( type );
02200     view->setID( UniqueID::gen() );
02201     m_doc -> addView( view );
02202     view -> setOptionState( Settings::getOptionState() );
02203     item -> setID( view -> getID() );
02204     item -> setText( name );
02205     view->activate();
02206     m_doc -> changeCurrentView( view -> getID() );
02207 }
02208 
02209 QString UMLListView::getUniqueDiagramName(Uml::Diagram_Type type) {
02210     return m_doc->uniqViewName(type);
02211 }
02212 
02213 bool UMLListView::isUnique( UMLListViewItem * item, const QString &name ) {
02214     UMLListViewItem * parentItem = static_cast<UMLListViewItem *>( item -> parent() );
02215     Uml::ListView_Type type = item -> getType();
02216     switch( type ) {
02217     case Uml::lvt_Class_Diagram:
02218         return !m_doc -> findView( Uml::dt_Class, name );
02219         break;
02220 
02221     case Uml::lvt_Sequence_Diagram:
02222         return !m_doc -> findView( Uml::dt_Sequence, name );
02223         break;
02224 
02225     case Uml::lvt_UseCase_Diagram:
02226         return !m_doc -> findView( Uml::dt_UseCase, name );
02227         break;
02228 
02229     case Uml::lvt_Collaboration_Diagram:
02230         return !m_doc -> findView( Uml::dt_Collaboration, name );
02231         break;
02232 
02233     case Uml::lvt_State_Diagram:
02234         return !m_doc -> findView( Uml::dt_State, name );
02235         break;
02236 
02237     case Uml::lvt_Activity_Diagram:
02238         return !m_doc -> findView( Uml::dt_Activity, name );
02239         break;
02240 
02241     case Uml::lvt_Component_Diagram:
02242         return !m_doc->findView(Uml::dt_Component, name);
02243         break;
02244 
02245     case Uml::lvt_Deployment_Diagram:
02246         return !m_doc->findView(Uml::dt_Deployment, name);
02247         break;
02248 
02249     case Uml::lvt_EntityRelationship_Diagram:
02250         return !m_doc->findView(Uml::dt_EntityRelationship, name);
02251         break;
02252 
02253     case Uml::lvt_Actor:
02254     case Uml::lvt_UseCase:
02255     case Uml::lvt_Node:
02256     case Uml::lvt_Artifact:
02257         return !m_doc->findUMLObject( name, Model_Utils::convert_LVT_OT(type) );
02258         break;
02259 
02260     case Uml::lvt_Class:
02261     case Uml::lvt_Package:
02262     case Uml::lvt_Interface:
02263     case Uml::lvt_Datatype:
02264     case Uml::lvt_Enum:
02265     case Uml::lvt_Entity:
02266     case Uml::lvt_Component:
02267     case Uml::lvt_Subsystem:
02268     case Uml::lvt_Logical_Folder:
02269     case Uml::lvt_UseCase_Folder:
02270     case Uml::lvt_Component_Folder:
02271     case Uml::lvt_Deployment_Folder:
02272     case Uml::lvt_EntityRelationship_Folder:
02273         {
02274             Uml::ListView_Type lvt = parentItem->getType();
02275             if (!Model_Utils::typeIsContainer(lvt))
02276                 return (m_doc->findUMLObject(name) == NULL);
02277             UMLPackage *pkg = static_cast<UMLPackage*>(parentItem->getUMLObject());
02278             if (pkg == NULL) {
02279                 kError() << "UMLListView::isUnique: internal error - "
02280                     << "parent listviewitem is package but has no UMLObject" << endl;
02281                 return true;
02282             }
02283             return (pkg->findObject(name) == NULL);
02284             break;
02285         }
02286 
02287     case Uml::lvt_Template:
02288     case Uml::lvt_Attribute:
02289     case Uml::lvt_EntityAttribute:
02290     case Uml::lvt_Operation:
02291     case Uml::lvt_EnumLiteral:
02292         {
02293             UMLClassifier *parent = static_cast<UMLClassifier*>(parentItem->getUMLObject());
02294             return (parent->findChildObject(name) == NULL);
02295             break;
02296         }
02297 
02298     default:
02299         break;
02300     }
02301     return false;
02302 }
02303 
02304 void UMLListView::cancelRename( QListViewItem * item ) {
02305     if( !m_bIgnoreCancelRename ) {
02306         delete item;
02307         m_bIgnoreCancelRename = true;
02308     }
02309 }
02310 
02311 void UMLListView::saveToXMI( QDomDocument & qDoc, QDomElement & qElement) {
02312     QDomElement listElement = qDoc.createElement( "listview" );
02313     m_rv->saveToXMI(qDoc, listElement);
02314     qElement.appendChild( listElement );
02315 }
02316 
02317 bool UMLListView::loadFromXMI( QDomElement & element ) {
02318     /*
02319         deleteChildrenOf( m_ucv );
02320         deleteChildrenOf( m_lv );
02321         deleteChildrenOf( m_cmpv );
02322         deleteChildrenOf( m_dplv );
02323      */
02324     QDomNode node = element.firstChild();
02325     QDomElement domElement = node.toElement();
02326     m_doc->writeToStatusBar( i18n("Loading listview...") );
02327     while( !domElement.isNull() ) {
02328         if( domElement.tagName() == "listitem" ) {
02329             QString type = domElement.attribute( "type", "-1" );
02330             if( type == "-1" )
02331                 return false;
02332             Uml::ListView_Type lvType = (Uml::ListView_Type)type.toInt();
02333             if( lvType == Uml::lvt_View ) {
02334                 if( !loadChildrenFromXMI( m_rv, domElement ) )
02335                     return false;
02336             } else
02337                 return false;
02338         }
02339         node = node.nextSibling();
02340         domElement = node.toElement();
02341 
02342     }//end while
02343     return true;
02344 }
02345 
02346 bool UMLListView::loadChildrenFromXMI( UMLListViewItem * parent, QDomElement & element ) {
02347     QDomNode node = element.firstChild();
02348     QDomElement domElement = node.toElement();
02349     const QString pfx("UMLListView::loadChildrenFromXMI: ");
02350     while( !domElement.isNull() ) {
02351         node = domElement.nextSibling();
02352         if( domElement.tagName() != "listitem" ) {
02353             domElement = node.toElement();
02354             continue;
02355         }
02356         QString id = domElement.attribute( "id", "-1" );
02357         QString type = domElement.attribute( "type", "-1" );
02358         QString label = domElement.attribute( "label", "" );
02359         QString open = domElement.attribute( "open", "1" );
02360         if( type == "-1" )
02361             return false;
02362         Uml::ListView_Type lvType = (Uml::ListView_Type)type.toInt();
02363         bool bOpen = (bool)open.toInt();
02364         Uml::IDType nID = STR2ID(id);
02365         UMLObject * pObject = 0;
02366         UMLListViewItem * item = 0;
02367         if (nID != Uml::id_None) {
02368             // The following is an ad hoc hack for the copy/paste code.
02369             // The clip still contains the old children although new
02370             // UMLCLassifierListItems have already been created.
02371             // If the IDChangeLog finds new IDs this means we are in
02372             // copy/paste and need to adjust the child listitems to the
02373             // new UMLCLassifierListItems.
02374             IDChangeLog *idchanges = m_doc->getChangeLog();
02375             if (idchanges != NULL) {
02376                 Uml::IDType newID = idchanges->findNewID(nID);
02377                 if (newID != Uml::id_None) {
02378                     kDebug() << pfx << " using id " << ID2STR(newID)
02379                         << " instead of " << ID2STR(nID) << endl;
02380                     nID = newID;
02381                 }
02382             }
02383             /************ End of hack for copy/paste code ************/
02384 
02385             pObject = m_doc->findObjectById(nID);
02386             if (pObject) {
02387                 if (label.isEmpty())
02388                     label = pObject->getName();
02389             } else if (Model_Utils::typeIsFolder(lvType)) {
02390                 // Synthesize the UMLFolder here
02391                 UMLObject *umlParent = parent->getUMLObject();
02392                 UMLPackage *parentPkg = dynamic_cast<UMLPackage*>(umlParent);
02393                 if (parentPkg == NULL) {
02394                     kError() << pfx << "umlParent(" << umlParent << ") is not a UMLPackage"
02395                         << endl;
02396                     domElement = node.toElement();
02397                     continue;
02398                 }
02399                 UMLFolder *f = new UMLFolder(label, nID);
02400                 f->setUMLPackage(parentPkg);
02401                 parentPkg->addObject(f);
02402                 pObject = f;
02403                 item = new UMLListViewItem(parent, label, lvType, pObject);
02404                 // Moving all relevant UMLObjects to the new UMLFolder is done below,
02405                 // in the switch(lvType)
02406             }
02407         } else if (Model_Utils::typeIsRootView(lvType)) {
02408             // Predefined folders did not have their ID set.
02409             const Uml::Model_Type mt = Model_Utils::convert_LVT_MT(lvType);
02410             nID = m_doc->getRootFolder(mt)->getID();
02411         } else if (Model_Utils::typeIsFolder(lvType)) {
02412             // Pre-1.2 format: Folders did not have their ID set.
02413             // Pull a new ID now.
02414             nID = UniqueID::get();
02415         } else {
02416             kError() << pfx << "item of type " << type << " has no ID, skipping." << endl;
02417             domElement = node.toElement();
02418             continue;
02419         }
02420 
02421         switch( lvType ) {
02422         case Uml::lvt_Actor:
02423         case Uml::lvt_UseCase:
02424         case Uml::lvt_Class:
02425         case Uml::lvt_Interface:
02426         case Uml::lvt_Datatype:
02427         case Uml::lvt_Enum:
02428         case Uml::lvt_Entity:
02429         case Uml::lvt_Package:
02430         case Uml::lvt_Subsystem:
02431         case Uml::lvt_Component:
02432         case Uml::lvt_Node:
02433         case Uml::lvt_Artifact:
02434         case Uml::lvt_Logical_Folder:
02435         case Uml::lvt_UseCase_Folder:
02436         case Uml::lvt_Component_Folder:
02437         case Uml::lvt_Deployment_Folder:
02438         case Uml::lvt_EntityRelationship_Folder:
02439             item = findItem(nID);
02440             if (item == NULL) {
02441                 kError() << pfx << "INTERNAL ERROR: "
02442                     << "findItem(id " << ID2STR(nID) << ") returns NULL" << endl;
02443                 /*
02444                 if (pObject && pObject->getUMLPackage() &&
02445                         parent->getType() != Uml::lvt_Package) {
02446                     // Pre-1.2 file format:
02447                     // Objects were not nested in their packages.
02448                     // Synthesize the nesting here.
02449                     UMLPackage *umlpkg = pObject->getUMLPackage();
02450                     UMLListViewItem *pkgItem = findUMLObject(umlpkg);
02451                     if (pkgItem == NULL) {
02452                         kDebug() << pfx << "synthesizing ListViewItem for package "
02453                             << ID2STR(umlpkg->getID()) << endl;
02454                         pkgItem = new UMLListViewItem(parent, umlpkg->getName(),
02455                                                       Uml::lvt_Package, umlpkg);
02456                         pkgItem->setOpen(true);
02457                     }
02458                     item = new UMLListViewItem(pkgItem, label, lvType, pObject);
02459                 } else {
02460                     item = new UMLListViewItem(parent, label, lvType, pObject);
02461                 }
02462                  */
02463             }
02464             else if (parent != item->parent()) {
02465                 // The existing item was created by the slot event triggered
02466                 // by the loading of the corresponding model object from the
02467                 // XMI file.
02468                 // This early creation is done in order to support the loading
02469                 // of foreign XMI files that do not have the umbrello specific
02470                 // <listview> tag.
02471                 // However, now that we encountered the real <listview> info,
02472                 // we need to delete the existing item: Its parent is always
02473                 // one of the default predefined folders, but the actual
02474                 // listview item might be located in a user created folder.
02475                 // Thanks to Achim Spangler for spotting the problem.
02476                 UMLListViewItem *itmParent = dynamic_cast<UMLListViewItem*>(item->parent());
02477                 kDebug() << pfx << item->getText() << " parent "
02478                     << parent->getText() << " (" << parent << ") != "
02479                     << itmParent->getText() << " (" << itmParent << ")" << endl;
02480                 if (item == m_datatypeFolder && itmParent == m_lv[Uml::mt_Logical]) {
02481                     kDebug() << pfx << "Reparenting the Datatypes folder is prohibited" << endl;
02482                 } else {
02483                     UMLListViewItem *newItem = moveObject(nID, lvType, parent);
02484                     item = newItem;
02485                     if (item) {
02486                         kDebug() << pfx << "Attempted reparenting of " << item->getText()
02487                             << "(current parent: " << (itmParent ? itmParent->getText() : "NULL")
02488                             << ", new parent: " << parent->getText() << ")" << endl;
02489                     }
02490                 }
02491             }
02492             break;
02493         case Uml::lvt_Attribute:
02494         case Uml::lvt_EntityAttribute:
02495         case Uml::lvt_Template:
02496         case Uml::lvt_Operation:
02497         case Uml::lvt_EnumLiteral:
02498             item = findItem(nID);
02499             if (item == NULL) {
02500                 kDebug() << pfx << "item " << ID2STR(nID) << " (of type "
02501                     << lvType << ") does not yet exist..." << endl;
02502                 UMLObject* umlObject = parent->getUMLObject();
02503                 if (!umlObject) {
02504                     kDebug() << "And also the parent->getUMLObject() does not exist" << endl;
02505                     return false;
02506                 }
02507                 if (nID == Uml::id_None) {
02508                     kWarning() << pfx << "lvtype " << lvType << " has id -1" << endl;
02509                 } else {
02510                     UMLClassifier *classifier = dynamic_cast<UMLClassifier*>(umlObject);
02511                     if (classifier) {
02512                         umlObject = classifier->findChildObjectById(nID);
02513                         if (umlObject) {
02514                             connectNewObjectsSlots(umlObject);
02515                             label = umlObject->getName();
02516                             item = new UMLListViewItem( parent, label, lvType, umlObject);
02517                         } else {
02518                             kDebug() << pfx << "lvtype " << lvType << " child object "
02519                                 << ID2STR(nID) << " not found" << endl;
02520                         }
02521                     } else {
02522                         kDebug() << pfx << "cast to classifier object failed" << endl;
02523                     }
02524                 }
02525             }
02526             break;
02527         case Uml::lvt_Logical_View:
02528             item = m_lv[Uml::mt_Logical];
02529             break;
02530         case Uml::lvt_Datatype_Folder:
02531             item = m_datatypeFolder;
02532             break;
02533         case Uml::lvt_UseCase_View:
02534             item = m_lv[Uml::mt_UseCase];
02535             break;
02536         case Uml::lvt_Component_View:
02537             item = m_lv[Uml::mt_Component];
02538             break;
02539         case Uml::lvt_Deployment_View:
02540             item = m_lv[Uml::mt_Deployment];
02541             break;
02542         case Uml::lvt_EntityRelationship_Model:
02543             item = m_lv[Uml::mt_EntityRelationship];
02544             break;
02545         default:
02546             if (Model_Utils::typeIsDiagram(lvType)) {
02547                 item = new UMLListViewItem( parent, label, lvType, nID );
02548             } else {
02549                 kError() << pfx << "INTERNAL ERROR: unexpected listview type "
02550                     << lvType << " (ID " << ID2STR(nID) << ")" << endl;
02551             }
02552             break;
02553         }//end switch
02554 
02555         if (item)  {
02556             item->setOpen( (bool)bOpen );
02557             if ( !loadChildrenFromXMI(item, domElement) ) {
02558                 return false;
02559             }
02560         } else {
02561             kWarning() << "unused list view item " << ID2STR(nID)
02562                 << " of lvtype " << lvType << endl;
02563         }
02564         domElement = node.toElement();
02565     }//end while
02566     return true;
02567 }
02568 
02570 void UMLListView::expandAll(QListViewItem *item) {
02571     if(!item) item = firstChild();
02572     for (item = item->firstChild(); item; item = item->nextSibling())  {
02573         item->setOpen(true);
02574     }
02575 }
02577 void UMLListView::collapseAll(QListViewItem *item) {
02578     if(!item) item = firstChild();
02579     for( item = item->firstChild(); item; item = item->nextSibling())
02580         item->setOpen(false);
02581 }
02582 
02583 void UMLListView::setStartedCut(bool startedCut) {
02584     m_bStartedCut = startedCut;
02585 }
02586 
02587 void UMLListView::setStartedCopy(bool startedCopy) {
02588     m_bStartedCopy = startedCopy;
02589 }
02590 
02591 bool UMLListView::startedCopy() const {
02592     return m_bStartedCopy;
02593 }
02594 
02595 UMLListViewItem *UMLListView::rootView(Uml::ListView_Type type) {
02596     UMLListViewItem *theView = NULL;
02597     switch (type) {
02598         case Uml::lvt_View:
02599             theView = m_rv;
02600             break;
02601         case Uml::lvt_Logical_View:
02602             theView = m_lv[Uml::mt_Logical];
02603             break;
02604         case Uml::lvt_UseCase_View:
02605             theView = m_lv[Uml::mt_UseCase];
02606             break;
02607         case Uml::lvt_Component_View:
02608             theView = m_lv[Uml::mt_Component];
02609             break;
02610         case Uml::lvt_Deployment_View:
02611             theView = m_lv[Uml::mt_Deployment];
02612             break;
02613         case Uml::lvt_EntityRelationship_Model:
02614             theView = m_lv[Uml::mt_EntityRelationship];
02615             break;
02616         case Uml::lvt_Datatype_Folder:   // @todo fix asymmetric naming
02617             theView = m_datatypeFolder;
02618             break;
02619         default:
02620             break;
02621     }
02622     return theView;
02623 }
02624 
02625 void UMLListView::deleteChildrenOf(QListViewItem* parent) {
02626     if ( !parent ) {
02627         return;
02628     }
02629     if (parent == m_lv[Uml::mt_Logical])
02630         m_datatypeFolder = NULL;
02631     while ( parent->firstChild() ) {
02632         delete parent->firstChild();
02633     }
02634 }
02635 
02636 void UMLListView::closeDatatypesFolder()  {
02637     m_datatypeFolder->setOpen(false);
02638 }
02639 
02640 
02641 bool UMLListView::deleteItem(UMLListViewItem *temp) {
02642     if (!temp)
02643         return false;
02644     UMLObject *object = temp->getUMLObject();
02645     Uml::ListView_Type lvt = temp->getType();
02646     if ( Model_Utils::typeIsDiagram(lvt) ) {
02647         m_doc->removeDiagram( temp->getID() );
02648     } else if (temp == m_datatypeFolder) {
02649         // we can't delete the datatypeFolder because umbrello will crash without a special handling
02650         return false;
02651     } else if (Model_Utils::typeIsCanvasWidget(lvt) || Model_Utils::typeIsClassifierList(lvt)) {
02652         UMLPackage *nmSpc = dynamic_cast<UMLPackage*>(object);
02653         if (nmSpc) {
02654             UMLObjectList contained = nmSpc->containedObjects();
02655             if (contained.count()) {
02656                 KMessageBox::error(
02657                     kapp->mainWidget(),
02658                     i18n("The folder must be emptied before it can be deleted."),
02659                     i18n("Folder Not Empty"));
02660                 return false;
02661             }
02662         }
02663         UMLCanvasObject *canvasObj = dynamic_cast<UMLCanvasObject*>(object);
02664         if (canvasObj) {
02673             canvasObj->removeAllChildObjects();
02674         }
02675         if (object) {
02676             m_doc->removeUMLObject(object);
02677             // Physical deletion of `temp' will be done by Qt signal, see
02678             // UMLDoc::removeUMLObject()
02679         } else {
02680             delete temp;
02681         }
02682     } else {
02683         kWarning() << "umllistview::listpopupmenu::mt_Delete called with unknown type"
02684             << endl;
02685     }
02686     return true;
02687 }
02688 
02689 
02690 #include "umllistview.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:08:01 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003