You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdesdk/umbrello/umbrello/umllistview.cpp

2703 lines
99 KiB

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* copyright (C) 2002-2007 *
* Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
***************************************************************************/
// own header
#include "umllistview.h"
// qt/kde includes
#include <tqregexp.h>
#include <tqpoint.h>
#include <tqrect.h>
#include <tqevent.h>
#include <tqheader.h>
#include <tqtooltip.h>
#include <kiconloader.h>
#include <kapplication.h>
#include <kdebug.h>
#include <tdefiledialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <kinputdialog.h>
// app includes
#include "actor.h"
#include "classifier.h"
#include "package.h"
#include "folder.h"
#include "component.h"
#include "node.h"
#include "artifact.h"
#include "enum.h"
#include "enumliteral.h"
#include "entity.h"
#include "docwindow.h"
#include "listpopupmenu.h"
#include "template.h"
#include "operation.h"
#include "attribute.h"
#include "entityattribute.h"
#include "uml.h"
#include "umldoc.h"
#include "umllistviewitemlist.h"
#include "umllistviewitem.h"
#include "umlview.h"
#include "umlviewimageexporter.h"
#include "usecase.h"
#include "model_utils.h"
#include "uniqueid.h"
#include "clipboard/idchangelog.h"
#include "clipboard/umldrag.h"
#include "dialogs/classpropdlg.h"
#include "dialogs/umlattributedialog.h"
#include "dialogs/umlentityattributedialog.h"
#include "dialogs/umloperationdialog.h"
#include "dialogs/umltemplatedialog.h"
#ifdef WANT_LVTOOLTIP
class LVToolTip : public TQToolTip
{
public:
LVToolTip (TQWidget* parent) : TQToolTip (parent) {}
virtual ~LVToolTip () {}
protected:
/**
* Reimplemented from TQToolTip for internal reasons.
* At classifiers, only the method names are shown in the list view -
* we use a tooltip for the full signature display.
* Once KListView's tooltip overriding mechanism works, we can kick
* this class out.
*/
virtual void maybeTip (const TQPoint& pos) {
UMLListView *lv = UMLApp::app()->getListView();
UMLListViewItem * item = (UMLListViewItem*)lv->itemAt(pos);
if (item == NULL)
return;
UMLObject *obj = item->getUMLObject();
if (obj == NULL || obj->getBaseType() != Uml::ot_Operation)
return;
UMLOperation *op = static_cast<UMLOperation*>(obj);
TQString text = op->toString(Uml::st_ShowSig);
TQRect rect = lv->itemRect(item);
tip(rect, text);
}
};
#endif
UMLListView::UMLListView(TQWidget *parent, const char *name)
: KListView(parent,name), m_pMenu(0), m_doc(UMLApp::app()->getDocument())
{
loadPixmaps();
//setup list view
setBackgroundColor(TQt::white);
setAcceptDrops(true);
setDropVisualizer(false);
setItemsMovable(true);
setItemsRenameable( true );
setSelectionModeExt(FileManager);
setFocusPolicy(TQ_StrongFocus);
setDragEnabled(true);
setColumnWidthMode( 0, Manual );
setDefaultRenameAction( Accept );
setResizeMode( LastColumn );
header()->setClickEnabled(true);
//add columns and initial items
addColumn(m_doc->getName());
#ifdef WANT_LVTOOLTIP
/* In KDE-3.3, we cannot use KListView's builtin mechanism for
overriding the tooltips. Instead, see the above class LVToolTip.
setShowToolTips( true );
setTooltipColumn( 0 );
*/
(void) new LVToolTip(viewport());
#endif
m_pMenu = NULL;
m_bStartedCut = m_bStartedCopy = false;
m_bIgnoreCancelRename = true;
m_bCreatingChildObject = false;
m_rv = NULL;
for (int i = 0; i < Uml::N_MODELTYPES; i++)
m_lv[i] = NULL;
m_datatypeFolder = NULL;
//setup slots/signals
connect(this, TQT_SIGNAL(dropped(TQDropEvent *, TQListViewItem *, TQListViewItem *)),
this, TQT_SLOT(slotDropped(TQDropEvent *, TQListViewItem *, TQListViewItem *)));
connect( this, TQT_SIGNAL( collapsed( TQListViewItem * ) ),
this, TQT_SLOT( slotCollapsed( TQListViewItem * ) ) );
connect( this, TQT_SIGNAL( expanded( TQListViewItem * ) ), this, TQT_SLOT( slotExpanded( TQListViewItem * ) ) );
connect( UMLApp::app(), TQT_SIGNAL( sigCutSuccessful() ), this, TQT_SLOT( slotCutSuccessful() ) );
}
UMLListView::~UMLListView() {}
bool UMLListView::eventFilter(TQObject *o, TQEvent *e) {
if (e->type() != TQEvent::MouseButtonPress || !o->isA(TQHEADER_OBJECT_NAME_STRING))
return TQListView::eventFilter(o, e);
TQMouseEvent *me = TQT_TQMOUSEEVENT(e);
if (me->button() == Qt::RightButton) {
if (m_pMenu) {
m_pMenu->hide();
disconnect(m_pMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(popupMenuSel(int)));
delete m_pMenu;
}
m_pMenu = new ListPopupMenu(this, Uml::lvt_Model);
m_pMenu->popup(me->globalPos());
connect(m_pMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(popupMenuSel(int)));
return true;
}
return TQListView::eventFilter(o, e);
}
void UMLListView::contentsMousePressEvent(TQMouseEvent *me) {
UMLView *currentView = UMLApp::app()->getCurrentView();
if (currentView)
currentView->clearSelected();
if( me -> state() != TQt::ShiftButton )
clearSelection();
TQPoint pt = this->TQScrollView::contentsToViewport( me->pos() );
UMLListViewItem * item = (UMLListViewItem*)itemAt(pt);
const TQt::ButtonState button = me->button();
if (!item || (button != Qt::RightButton && button != Qt::LeftButton)) {
UMLApp::app()->getDocWindow()->updateDocumentation(true);
return;
}
if (button == Qt::LeftButton) {
UMLObject *o = item->getUMLObject();
if (o)
UMLApp::app()->getDocWindow()->showDocumentation(o, false);
else
UMLApp::app()->getDocWindow()->updateDocumentation(true);
}
if (button == Qt::RightButton) {
if(m_pMenu != 0) {
m_pMenu->hide();
disconnect(m_pMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(popupMenuSel(int)));
delete m_pMenu;
m_pMenu = 0;
}
const Uml::ListView_Type type = item->getType();
m_pMenu = new ListPopupMenu(this, type);
m_pMenu->popup(me->globalPos());
connect(m_pMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(popupMenuSel(int)));
}//end if right button
this->KListView::contentsMousePressEvent(me);
}
void UMLListView::contentsMouseReleaseEvent(TQMouseEvent *me) {
if (me->button() != Qt::LeftButton) {
this->KListView::contentsMouseReleaseEvent(me);
return;
}
const TQPoint pt = this->TQScrollView::contentsToViewport( me->pos() );
UMLListViewItem *item = dynamic_cast<UMLListViewItem*>(itemAt(pt));
if (item == NULL || !Model_Utils::typeIsDiagram(item->getType())) {
this->KListView::contentsMouseReleaseEvent(me);
return;
}
// Switch to diagram on mouse release - not on mouse press
// because the user might intend a drag-to-note.
m_doc->changeCurrentView( item->getID() );
UMLApp::app()->getDocWindow()->showDocumentation(m_doc->findView(item->getID()), false);
this->KListView::contentsMouseReleaseEvent(me);
}
void UMLListView::keyPressEvent(TQKeyEvent *ke) {
UMLView *view = UMLApp::app()->getCurrentView();
if (view && view->getSelectCount()) {
// Widgets have been selected in the diagram area,
// assume they handle the keypress.
ke->accept(); // munge and do nothing
} else {
const int k = ke->key();
if (k == TQt::Key_Delete || k == TQt::Key_Backspace) {
// delete every selected item
UMLListViewItemList selecteditems;
getSelectedItemsRoot(selecteditems);
UMLListViewItemListIt it(selecteditems);
for (UMLListViewItem *item = 0; (item = it.current()); ++it) {
deleteItem(dynamic_cast<UMLListViewItem*>(item));
}
} else {
TQListView::keyPressEvent(ke); // let parent handle it
}
}
}
void UMLListView::popupMenuSel(int sel) {
UMLListViewItem * temp = (UMLListViewItem*)currentItem();
if ( !temp ) {
kDebug() << "popupMenuSel invoked without currently selectedItem" << endl;
return;
}
UMLObject * object = temp -> getUMLObject();
Uml::ListView_Type lvt = temp -> getType();
Uml::Object_Type umlType = Uml::ot_UMLObject;
ListPopupMenu::Menu_Type menuType = (ListPopupMenu::Menu_Type)sel;
TQString name;
switch (menuType) {
case ListPopupMenu::mt_Class:
addNewItem( temp, Uml::lvt_Class );
break;
case ListPopupMenu::mt_Package:
addNewItem(temp, Uml::lvt_Package);
break;
case ListPopupMenu::mt_Subsystem:
addNewItem(temp, Uml::lvt_Subsystem);
break;
case ListPopupMenu::mt_Component:
addNewItem(temp, Uml::lvt_Component);
break;
case ListPopupMenu::mt_Node:
addNewItem(temp, Uml::lvt_Node);
break;
case ListPopupMenu::mt_Artifact:
addNewItem(temp, Uml::lvt_Artifact);
break;
case ListPopupMenu::mt_Interface:
addNewItem(temp, Uml::lvt_Interface);
break;
case ListPopupMenu::mt_Enum:
addNewItem(temp, Uml::lvt_Enum);
break;
case ListPopupMenu::mt_EnumLiteral:
addNewItem(temp, Uml::lvt_EnumLiteral);
break;
case ListPopupMenu::mt_Template:
addNewItem(temp, Uml::lvt_Template);
break;
case ListPopupMenu::mt_Entity:
addNewItem(temp, Uml::lvt_Entity);
break;
case ListPopupMenu::mt_Datatype:
addNewItem(temp, Uml::lvt_Datatype);
break;
case ListPopupMenu::mt_Actor:
addNewItem( temp, Uml::lvt_Actor );
break;
case ListPopupMenu::mt_UseCase:
addNewItem( temp, Uml::lvt_UseCase );
break;
case ListPopupMenu::mt_Attribute:
addNewItem( temp, Uml::lvt_Attribute );
break;
case ListPopupMenu::mt_EntityAttribute:
addNewItem( temp, Uml::lvt_EntityAttribute );
break;
case ListPopupMenu::mt_Operation:
addNewItem( temp, Uml::lvt_Operation );
break;
case ListPopupMenu::mt_Import_Classes:
UMLApp::app()->slotImportClasses();
break;
case ListPopupMenu::mt_Expand_All:
expandAll(temp);
break;
case ListPopupMenu::mt_Collapse_All:
collapseAll(temp);
break;
case ListPopupMenu::mt_Export_Image:
m_doc->findView(temp->getID())->getImageExporter()->exportView();
break;
case ListPopupMenu::mt_Externalize_Folder:
{
UMLListViewItem *current = static_cast<UMLListViewItem*>(currentItem());
UMLFolder *modelFolder = dynamic_cast<UMLFolder*>(current->getUMLObject());
if (modelFolder == NULL) {
kError() << "UMLListView::popupMenuSel: modelFolder is NULL" << endl;
return;
}
// configure & show the file dialog
const TQString rootDir(m_doc->URL().directory());
KFileDialog fileDialog(rootDir, "*.xml", this, ":externalize-folder", true);
fileDialog.setCaption(i18n("Externalize Folder"));
fileDialog.setOperationMode(KFileDialog::Other);
// set a sensible default filename
TQString defaultFilename = current->getText().lower();
defaultFilename.replace(TQRegExp("\\W+"), "_");
defaultFilename.append(".xml"); // default extension
fileDialog.setSelection(defaultFilename);
fileDialog.exec();
KURL selURL = fileDialog.selectedURL();
if (selURL.isEmpty())
return;
TQString path = selURL.path();
TQString fileName = path;
if (fileName.startsWith(rootDir)) {
fileName.remove(rootDir);
} else {
// This should be done using a KMessageBox but we currently
// cannot add new i18n strings.
kError() << "Folder " << path
<< " must be relative to the main model directory, "
<< rootDir << endl;
return;
}
TQFile file(path);
// Warn if file exists.
if (file.exists()) {
// This should be done using a KMessageBox but we currently
// cannot add new i18n strings.
kWarning() << "file " << fileName << " already exists!" << endl;
kWarning() << "The existing file will be overwritten." << endl;
}
// Test if file is writable.
if (file.open(IO_WriteOnly)) {
file.close();
} else {
KMessageBox::error(0,
i18n("There was a problem saving file: %1").arg(fileName),
i18n("Save Error"));
return;
}
modelFolder->setFolderFile(fileName);
// Recompute text of the folder
TQString folderText = current->getText();
folderText.remove( TQRegExp("\\s*\\(.*$") );
folderText.append( " (" + fileName + ')' );
current->setText(folderText);
break;
}
case ListPopupMenu::mt_Internalize_Folder:
{
UMLListViewItem *current = static_cast<UMLListViewItem*>(currentItem());
UMLFolder *modelFolder = dynamic_cast<UMLFolder*>(current->getUMLObject());
if (modelFolder == NULL) {
kError() << "UMLListView::popupMenuSel: modelFolder is NULL" << endl;
return;
}
modelFolder->setFolderFile(TQString());
// Recompute text of the folder
TQString folderText = current->getText();
folderText.remove( TQRegExp("\\s*\\(.*$") );
current->setText(folderText);
break;
}
case ListPopupMenu::mt_Model:
{
bool ok = false;
TQString name = KInputDialog::getText( i18n("Enter Model Name"),
i18n("Enter the new name of the model:"),
m_doc->getName(), &ok, UMLApp::app() );
if (ok) {
setColumnText(0, name);
m_doc->setName(name);
}
break;
}
case ListPopupMenu::mt_Rename:
temp-> startRename(0);
break;
case ListPopupMenu::mt_Delete:
deleteItem(temp);
return;
break;
case ListPopupMenu::mt_Properties:
/* first check if we are on a diagram */
if( Model_Utils::typeIsDiagram(lvt) ) {
UMLView * pView = m_doc->findView( temp->getID() );
if( !pView ) {
return;
}
UMLApp::app()->getDocWindow()->updateDocumentation(false);
pView->showPropDialog();
UMLApp::app()->getDocWindow()->showDocumentation(pView, true);
temp->cancelRename(0);
return;
}
/* ok, we are on another object, so find out on which one */
umlType = object->getBaseType();
if ( Model_Utils::typeIsCanvasWidget(lvt) ) {
object->showProperties(ClassPropDlg::page_gen);
} else if(umlType == Uml::ot_Attribute) {
// show the attribute dialog
UMLAttribute* selectedAttribute = static_cast<UMLAttribute*>(object);
UMLAttributeDialog dialog( this, selectedAttribute );
dialog.exec();
} else if(umlType == Uml::ot_EntityAttribute) {
// show the attribute dialog
UMLEntityAttribute* selectedAttribute = static_cast<UMLEntityAttribute*>(object);
UMLEntityAttributeDialog dialog( this, selectedAttribute );
dialog.exec();
} else if(umlType == Uml::ot_Operation) {
// show the operation dialog
UMLOperation* selectedOperation = static_cast<UMLOperation*>(object);
UMLOperationDialog dialog( this, selectedOperation );
dialog.exec();
} else if(umlType == Uml::ot_Template) {
// show the template dialog
UMLTemplate* selectedTemplate = static_cast<UMLTemplate*>(object);
UMLTemplateDialog dialog( this, selectedTemplate );
dialog.exec();
} else {
kWarning() << "calling properties on unknown type" << endl;
}
temp -> cancelRename( 0 );
break;
case ListPopupMenu::mt_Logical_Folder:
addNewItem( temp, Uml::lvt_Logical_Folder );
break;
case ListPopupMenu::mt_UseCase_Folder:
addNewItem( temp, Uml::lvt_UseCase_Folder );
break;
case ListPopupMenu::mt_Component_Folder:
addNewItem(temp, Uml::lvt_Component_Folder);
break;
case ListPopupMenu::mt_Deployment_Folder:
addNewItem(temp, Uml::lvt_Deployment_Folder);
break;
case ListPopupMenu::mt_EntityRelationship_Folder:
addNewItem(temp, Uml::lvt_EntityRelationship_Folder);
break;
case ListPopupMenu::mt_Cut:
m_bStartedCut = true;
m_bStartedCopy = false;
UMLApp::app() -> slotEditCut();
break;
case ListPopupMenu::mt_Copy:
m_bStartedCut = false;
m_bStartedCopy = true;
UMLApp::app() -> slotEditCopy();
break;
case ListPopupMenu::mt_Paste:
UMLApp::app() -> slotEditPaste();
break;
default:
{
Uml::Diagram_Type dt = ListPopupMenu::convert_MT_DT(menuType);
if (dt == Uml::dt_Undefined) {
kWarning() << "UMLListView::popupMenuSel: unknown type"
<< sel << endl;
} else {
UMLFolder *f = dynamic_cast<UMLFolder*>(object);
if (f == NULL)
kError() << "UMLListView::popupMenuSel(" << menuType
<< "): current item's UMLObject is not a UMLFolder" << endl;
else
m_doc->createDiagram(f, dt);
}
}
break;
}//end switch
}
UMLListViewItem *UMLListView::findFolderForDiagram(Uml::Diagram_Type dt) {
UMLListViewItem *p = static_cast<UMLListViewItem*>(currentItem());
if (p && Model_Utils::typeIsFolder(p->getType())
&& !Model_Utils::typeIsRootView(p->getType())) {
return p;
}
switch (dt) {
case Uml::dt_UseCase:
p = m_lv[Uml::mt_UseCase];
break;
case Uml::dt_Component:
p = m_lv[Uml::mt_Component];
break;
case Uml::dt_Deployment:
p = m_lv[Uml::mt_Deployment];
break;
case Uml::dt_EntityRelationship:
p = m_lv[Uml::mt_EntityRelationship];
break;
default:
p = m_lv[Uml::mt_Logical];
break;
}
return p;
}
void UMLListView::slotDiagramCreated( Uml::IDType id ) {
if( m_doc->loading() )
return;
UMLView *v = m_doc -> findView( id );
if (!v)
return;
const Uml::Diagram_Type dt = v->getType();
UMLListViewItem * temp = 0, *p = findFolderForDiagram(dt);
temp = new UMLListViewItem(p, v->getName(), Model_Utils::convert_DT_LVT(dt), id);
setSelected( temp, true );
UMLApp::app() -> getDocWindow() -> showDocumentation( v , false );
}
UMLListViewItem* UMLListView::determineParentItem(UMLObject* object) const {
UMLListViewItem* parentItem = NULL;
UMLListViewItem* current = (UMLListViewItem*) currentItem();
Uml::ListView_Type lvt = Uml::lvt_Unknown;
if (current)
lvt = current->getType();
Uml::Object_Type t = object->getBaseType();
switch (t) {
case Uml::ot_Attribute:
case Uml::ot_Operation:
case Uml::ot_Template:
case Uml::ot_EnumLiteral:
case Uml::ot_EntityAttribute:
//this will be handled by childObjectAdded
return NULL;
break;
case Uml::ot_Association:
case Uml::ot_Role:
case Uml::ot_Stereotype:
return NULL; // currently no representation in list view
break;
default:
{
UMLPackage *pkg = object->getUMLPackage();
if (pkg) {
UMLListViewItem* pkgItem = findUMLObject(pkg);
if (pkgItem == NULL)
kError() << "UMLListView::determineParentItem: could not find "
<< "parent package " << pkg->getName() << endl;
else
parentItem = pkgItem;
} else if ((lvt == Uml::lvt_UseCase_Folder &&
(t == Uml::ot_Actor || t == Uml::ot_UseCase))
|| (lvt == Uml::lvt_Component_Folder && t == Uml::ot_Component)
|| (lvt == Uml::lvt_Deployment_Folder && t == Uml::ot_Node)
|| (lvt == Uml::lvt_EntityRelationship_Folder && t == Uml::ot_Entity)) {
parentItem = current;
} else if (t == Uml::ot_Datatype) {
parentItem = m_datatypeFolder;
} else {
Uml::Model_Type guess = Model_Utils::guessContainer(object);
parentItem = m_lv[guess];
}
}
break;
}
return parentItem;
}
bool UMLListView::mayHaveChildItems(Uml::Object_Type type) {
bool retval = false;
switch (type) {
case Uml::ot_Class:
case Uml::ot_Interface:
case Uml::ot_Enum:
case Uml::ot_Entity: // CHECK: more?
retval = true;
break;
default:
break;
}
return retval;
}
void UMLListView::slotObjectCreated(UMLObject* object) {
if (m_bCreatingChildObject) {
// @todo eliminate futile signal traffic
// e.g. we get here thru various indirections from
// ClassifierListPage::slot{Up,Down}Clicked()
return;
}
UMLListViewItem* newItem = findUMLObject(object);
if (newItem) {
kDebug() << "UMLListView::slotObjectCreated(" << object->getName()
<< ", id= " << ID2STR(object->getID())
<< "): item already exists." << endl;
Uml::Icon_Type icon = Model_Utils::convert_LVT_IT(newItem->getType());
newItem->setIcon(icon);
return;
}
UMLListViewItem* parentItem = determineParentItem(object);
if (parentItem == NULL)
return;
Uml::Object_Type type = object->getBaseType();
connectNewObjectsSlots(object);
const Uml::ListView_Type lvt = Model_Utils::convert_OT_LVT(object);
TQString name = object->getName();
if (type == Uml::ot_Folder) {
UMLFolder *f = static_cast<UMLFolder*>(object);
TQString folderFile = f->getFolderFile();
if (!folderFile.isEmpty())
name.append(" (" + folderFile + ')');
}
newItem = new UMLListViewItem(parentItem, name, lvt, object);
if (mayHaveChildItems(type)) {
UMLClassifier *c = static_cast<UMLClassifier*>(object);
UMLClassifierListItemList cListItems = c->getFilteredList(Uml::ot_UMLObject);
UMLClassifierListItem *cli;
for (UMLClassifierListItemListIt it(cListItems); (cli = it.current()) != NULL; ++it)
childObjectAdded(cli, c);
}
if (m_doc->loading())
return;
ensureItemVisible(newItem);
newItem->setOpen(true);
clearSelection();
setSelected(newItem, true);
UMLApp::app()->getDocWindow()->showDocumentation(object, false);
}
void UMLListView::connectNewObjectsSlots(UMLObject* object) {
Uml::Object_Type type = object->getBaseType();
switch( type )
{
case Uml::ot_Class:
case Uml::ot_Interface:
{
UMLClassifier *c = static_cast<UMLClassifier*>(object);
connect(c, TQT_SIGNAL(attributeAdded(UMLClassifierListItem*)),
this, TQT_SLOT(childObjectAdded(UMLClassifierListItem*)));
connect(c, TQT_SIGNAL(attributeRemoved(UMLClassifierListItem*)),
this, TQT_SLOT(childObjectRemoved(UMLClassifierListItem*)));
connect(c, TQT_SIGNAL(operationAdded(UMLClassifierListItem*)),
this, TQT_SLOT(childObjectAdded(UMLClassifierListItem*)));
connect(c, TQT_SIGNAL(operationRemoved(UMLClassifierListItem*)),
this, TQT_SLOT(childObjectRemoved(UMLClassifierListItem*)));
connect(c, TQT_SIGNAL(templateAdded(UMLClassifierListItem*)),
this, TQT_SLOT(childObjectAdded(UMLClassifierListItem*)));
connect(c, TQT_SIGNAL(templateRemoved(UMLClassifierListItem*)),
this, TQT_SLOT(childObjectRemoved(UMLClassifierListItem*)));
connect(object,TQT_SIGNAL(modified()),this,TQT_SLOT(slotObjectChanged()));
}
break;
case Uml::ot_Enum:
{
UMLEnum *e = static_cast<UMLEnum*>(object);
connect(e, TQT_SIGNAL(enumLiteralAdded(UMLClassifierListItem*)),
this, TQT_SLOT(childObjectAdded(UMLClassifierListItem*)));
connect(e, TQT_SIGNAL(enumLiteralRemoved(UMLClassifierListItem*)),
this, TQT_SLOT(childObjectRemoved(UMLClassifierListItem*)));
}
connect(object,TQT_SIGNAL(modified()),this,TQT_SLOT(slotObjectChanged()));
break;
case Uml::ot_Entity:
{
UMLEntity *ent = static_cast<UMLEntity*>(object);
connect(ent, TQT_SIGNAL(entityAttributeAdded(UMLClassifierListItem*)),
this, TQT_SLOT(childObjectAdded(UMLClassifierListItem*)));
connect(ent, TQT_SIGNAL(entityAttributeRemoved(UMLClassifierListItem*)),
this, TQT_SLOT(childObjectRemoved(UMLClassifierListItem*)));
}
connect(object,TQT_SIGNAL(modified()),this,TQT_SLOT(slotObjectChanged()));
break;
case Uml::ot_Datatype:
case Uml::ot_Attribute:
case Uml::ot_Operation:
case Uml::ot_Template:
case Uml::ot_EnumLiteral:
case Uml::ot_EntityAttribute:
case Uml::ot_Package:
case Uml::ot_Actor:
case Uml::ot_UseCase:
case Uml::ot_Component:
case Uml::ot_Artifact:
case Uml::ot_Node:
case Uml::ot_Folder:
connect(object,TQT_SIGNAL(modified()),this,TQT_SLOT(slotObjectChanged()));
break;
case Uml::ot_UMLObject:
case Uml::ot_Association:
case Uml::ot_Stereotype:
break;
default:
kWarning() << "unknown type in connectNewObjectsSlots" << endl;
break;
}
}
void UMLListView::slotObjectChanged() {
if (m_doc->loading()) { //needed for class wizard
return;
}
UMLObject* obj = const_cast<UMLObject*>( dynamic_cast<const UMLObject*>(sender()) );
UMLListViewItem* item = findUMLObject(obj);
if(item) {
item->updateObject();
}
}
void UMLListView::childObjectAdded(UMLClassifierListItem* obj) {
UMLClassifier *parent = const_cast<UMLClassifier*>(dynamic_cast<const UMLClassifier*>(sender()));
childObjectAdded(obj, parent);
}
void UMLListView::childObjectAdded(UMLClassifierListItem* child, UMLClassifier* parent) {
if (m_bCreatingChildObject)
return;
const TQString text = child->toString(Uml::st_SigNoVis);
UMLListViewItem *childItem = NULL;
UMLListViewItem *parentItem = findUMLObject(parent);
if (parentItem == NULL) {
kDebug() << "UMLListView::childObjectAdded(" << child->getName()
<< "): parent " << parent->getName()
<< " does not yet exist, creating it now." << endl;
const Uml::ListView_Type lvt = Model_Utils::convert_OT_LVT(parent);
parentItem = new UMLListViewItem(m_lv[Uml::mt_Logical], parent->getName(), lvt, parent);
} else {
childItem = parentItem->findChildObject(child);
}
if (childItem) {
childItem->setText(text);
} else {
const Uml::ListView_Type lvt = Model_Utils::convert_OT_LVT(child);
childItem = new UMLListViewItem(parentItem, text, lvt, child);
if (! m_doc->loading()) {
ensureItemVisible(childItem);
clearSelection();
setSelected(childItem, true);
}
connectNewObjectsSlots(child);
}
}
void UMLListView::childObjectRemoved(UMLClassifierListItem* obj) {
UMLClassifier *parent = const_cast<UMLClassifier*>(dynamic_cast<const UMLClassifier*>(sender()));
UMLListViewItem *parentItem = findUMLObject(parent);
if (parentItem == NULL) {
kError() << "UMLListView::childObjectRemoved(" << obj->getName()
<< "): cannot find parent UMLListViewItem" << endl;
return;
}
parentItem->deleteChildItem(obj);
}
void UMLListView::slotDiagramRenamed(Uml::IDType id) {
UMLListViewItem* temp;
UMLView* v = m_doc->findView(id);
if ((temp = findView(v)) == NULL) {
kError() << "UMLListView::slotDiagramRenamed: UMLDoc::findView("
<< ID2STR(id) << ") returns NULL" << endl;
return;
}
temp->setText( v->getName() );
}
void UMLListView::setDocument(UMLDoc *d) {
if( m_doc && m_doc != d)
{
//disconnect signals from old doc and reset view
}
m_doc = d;
connect(m_doc, TQT_SIGNAL(sigDiagramCreated(Uml::IDType)), this, TQT_SLOT(slotDiagramCreated(Uml::IDType)));
connect(m_doc, TQT_SIGNAL(sigDiagramRemoved(Uml::IDType)), this, TQT_SLOT(slotDiagramRemoved(Uml::IDType)));
connect(m_doc, TQT_SIGNAL(sigDiagramRenamed(Uml::IDType)), this, TQT_SLOT(slotDiagramRenamed(Uml::IDType)));
connect(m_doc, TQT_SIGNAL(sigObjectCreated(UMLObject *)), this, TQT_SLOT(slotObjectCreated(UMLObject *)));
connect(m_doc, TQT_SIGNAL(sigObjectRemoved(UMLObject *)), this, TQT_SLOT(slotObjectRemoved(UMLObject *)));
}
void UMLListView::slotObjectRemoved(UMLObject* object) {
if (m_doc->loading()) { //needed for class wizard
return;
}
disconnect(object,TQT_SIGNAL(modified()),this,TQT_SLOT(slotObjectChanged()));
UMLListViewItem* item = findItem(object->getID());
delete item;
UMLApp::app()->getDocWindow()->updateDocumentation(true);
}
void UMLListView::slotDiagramRemoved(Uml::IDType id) {
UMLListViewItem* item = findItem(id);
delete item;
UMLApp::app()->getDocWindow()->updateDocumentation(true);
}
TQDragObject* UMLListView::dragObject() {
UMLListViewItemList selecteditems;
getSelectedItems(selecteditems);
selecteditems.setAutoDelete( false );
UMLListViewItemListIt it(selecteditems);
UMLListViewItem * item = 0;
UMLListViewItemList list;
list.setAutoDelete( false );
while((item=it.current()) != 0) {
++it;
Uml::ListView_Type type = item->getType();
if (!Model_Utils::typeIsCanvasWidget(type) && !Model_Utils::typeIsDiagram(type)
&& !Model_Utils::typeIsClassifierList(type)) {
return 0;
}
list.append(item);
}
UMLDrag *t = new UMLDrag(list, this);
return t;
}
void UMLListView::startDrag() {
TQDragObject *o = dragObject();
if (o)
o->dragCopy();
}
UMLListViewItem * UMLListView::findUMLObjectInFolder(UMLListViewItem* folder, UMLObject* obj) {
UMLListViewItem *item = static_cast<UMLListViewItem *>(folder->firstChild());
while(item)
{
switch(item->getType())
{
case Uml::lvt_Actor :
case Uml::lvt_UseCase :
case Uml::lvt_Class :
case Uml::lvt_Package :
case Uml::lvt_Subsystem :
case Uml::lvt_Component :
case Uml::lvt_Node :
case Uml::lvt_Artifact :
case Uml::lvt_Interface :
case Uml::lvt_Datatype :
case Uml::lvt_Enum :
case Uml::lvt_Entity :
if(item->getUMLObject() == obj)
return item;
break;
case Uml::lvt_Logical_Folder :
case Uml::lvt_UseCase_Folder :
case Uml::lvt_Component_Folder :
case Uml::lvt_Deployment_Folder :
case Uml::lvt_EntityRelationship_Folder :
case Uml::lvt_Datatype_Folder :
{
UMLListViewItem *temp = findUMLObjectInFolder(item, obj);
if (temp)
return temp;
}
default:
break;
}
item = static_cast<UMLListViewItem *>(item->nextSibling());
}
return 0;
}
UMLListViewItem * UMLListView::findUMLObject(const UMLObject *p) const {
UMLListViewItem *item = static_cast<UMLListViewItem*>(firstChild());
while (item) {
UMLListViewItem *testItem = item->findUMLObject(p);
if (testItem)
return testItem;
item = static_cast<UMLListViewItem*>(item->nextSibling());
}
return item;
}
void UMLListView::changeIconOf(UMLObject *o, Uml::Icon_Type to) {
UMLListViewItem *item = findUMLObject(o);
if (item == NULL)
return;
item->setIcon(to);
}
UMLListViewItem* UMLListView::findView(UMLView* v) {
if (!v) {
kWarning() << "returning 0 from UMLListView::findView()" << endl;
return 0;
}
UMLListViewItem* item;
Uml::Diagram_Type dType = v->getType();
Uml::ListView_Type type = Model_Utils::convert_DT_LVT( dType );
Uml::IDType id = v->getID();
if (dType == Uml::dt_UseCase) {
item = m_lv[Uml::mt_UseCase];
} else if (dType == Uml::dt_Component) {
item = m_lv[Uml::mt_Component];
} else if (dType == Uml::dt_Deployment) {
item = m_lv[Uml::mt_Deployment];
} else if (dType == Uml::dt_EntityRelationship) {
item = m_lv[Uml::mt_EntityRelationship];
} else {
item = m_lv[Uml::mt_Logical];
}
UMLListViewItem* searchStartItem = (UMLListViewItem *)item->firstChild();
UMLListViewItem* foundItem = recursiveSearchForView(searchStartItem, type, id);
if (!foundItem) {
kWarning() << "returning 0 at UMLListView::findView" << endl;
}
return foundItem;
}
UMLListViewItem* UMLListView::recursiveSearchForView(UMLListViewItem* listViewItem,
Uml::ListView_Type type, Uml::IDType id) {
while (listViewItem) {
if ( Model_Utils::typeIsFolder(listViewItem->getType()) ) {
UMLListViewItem* child = (UMLListViewItem *)listViewItem->firstChild();
UMLListViewItem* resultListViewItem = recursiveSearchForView(child, type, id);
if (resultListViewItem) {
return resultListViewItem;
}
} else {
if(listViewItem->getType() == type && listViewItem->getID() == id) {
return listViewItem;
}
}
listViewItem = (UMLListViewItem*)listViewItem->nextSibling();
}
return 0;
}
UMLListViewItem* UMLListView::findItem(Uml::IDType id) {
UMLListViewItem *temp;
TQListViewItemIterator it(this);
for( ; (temp = (UMLListViewItem*)it.current()); ++it ) {
UMLListViewItem * item = temp->findItem(id);
if (item)
return item;
}
return 0;
}
//
// This method is called more than once during an instance's lifetime (by UMLDoc)!
// So we must not allocate any memory before freeing the previously allocated one
// or do connect()s.
//
void UMLListView::init() {
if (m_rv == NULL) {
m_rv = new UMLListViewItem(this, i18n("Views"), Uml::lvt_View);
for (int i = 0; i < Uml::N_MODELTYPES; i++) {
Uml::Model_Type mt = (Uml::Model_Type)i;
UMLFolder *sysFolder = m_doc->getRootFolder(mt);
Uml::ListView_Type lvt = Model_Utils::convert_MT_LVT(mt);
m_lv[i] = new UMLListViewItem(m_rv, sysFolder->getLocalName(), lvt, sysFolder);
}
} else {
for (int i = 0; i < Uml::N_MODELTYPES; i++)
deleteChildrenOf(m_lv[i]);
}
UMLFolder *datatypeFolder = m_doc->getDatatypeFolder();
m_datatypeFolder = new UMLListViewItem(m_lv[Uml::mt_Logical], datatypeFolder->getLocalName(),
Uml::lvt_Datatype_Folder, datatypeFolder);
m_rv->setOpen(true);
for (int i = 0; i < Uml::N_MODELTYPES; i++)
m_lv[i]->setOpen(true);
m_datatypeFolder->setOpen(false);
//setup misc.
delete m_pMenu;
m_pMenu = 0;
m_bStartedCut = m_bStartedCopy = false;
m_bIgnoreCancelRename = true;
m_bCreatingChildObject = false;
}
void UMLListView::setView(UMLView * v) {
if(!v)
return;
UMLListViewItem * temp = findView(v);
if(temp)
setSelected(temp, true);
}
void UMLListView::contentsMouseDoubleClickEvent(TQMouseEvent * me) {
UMLListViewItem * item = static_cast<UMLListViewItem *>( currentItem() );
if( !item || me -> button() != Qt::LeftButton )
return;
//see if on view
Uml::ListView_Type lvType = item -> getType();
if( Model_Utils::typeIsDiagram(lvType) ) {
UMLView * pView = m_doc -> findView( item -> getID() );
if( !pView )
return;
UMLApp::app() -> getDocWindow() -> updateDocumentation( false );
pView -> showPropDialog();
UMLApp::app() -> getDocWindow() -> showDocumentation( pView, true );
item -> cancelRename( 0 );
return;
}
//else see if an object
UMLObject * object = item -> getUMLObject();
//continue only if we are on a UMLObject
if(!object)
return;
Uml::Object_Type type = object -> getBaseType();
int page = ClassPropDlg::page_gen;
if(type == Uml::ot_Attribute || type == Uml::ot_Operation)
object = (UMLObject *)object -> parent();
//set what page to show
if(type == Uml::ot_Attribute)
page = ClassPropDlg::page_att;
else if(type == Uml::ot_Operation)
page = ClassPropDlg::page_op;
//FIXME for entityattributes
if(object)
object->showProperties(page);
item -> cancelRename( 0 );//double click can cause it to go into rename mode.
}
bool UMLListView::acceptDrag(TQDropEvent* event) const {
TQPoint mousePoint = ((UMLListView*)this)->contentsToViewport( event->pos() );
UMLListViewItem* item = (UMLListViewItem*)itemAt(mousePoint);
if(!item) {
kDebug() << "UMLListView::acceptDrag: itemAt(mousePoint) returns NULL"
<< endl;
return false;
}
((TQListView*)this)->setCurrentItem( (TQListViewItem*)item );
UMLDrag::LvTypeAndID_List list;
if (! UMLDrag::getClip3TypeAndID(event, list)) {
kDebug() << "UMLListView::acceptDrag: UMLDrag::getClip3TypeAndID returns false"
<< endl;
return false;
}
UMLDrag::LvTypeAndID_It it(list);
UMLDrag::LvTypeAndID * data = 0;
Uml::ListView_Type dstType = item->getType();
bool accept = true;
while(accept && ((data = it.current()) != 0)) {
++it;
Uml::ListView_Type srcType = data->type;
switch (srcType) {
case Uml::lvt_Class:
case Uml::lvt_Package:
case Uml::lvt_Interface:
case Uml::lvt_Enum:
if (dstType == Uml::lvt_Logical_View ||
dstType == Uml::lvt_Class ||
dstType == Uml::lvt_Package) {
accept = !item->isOwnParent(data->id);
} else {
accept = (dstType == Uml::lvt_Logical_Folder);
}
break;
case Uml::lvt_Attribute:
if (dstType == Uml::lvt_Class) {
accept = !item->isOwnParent(data->id);
}
break;
case Uml::lvt_EntityAttribute:
if (dstType == Uml::lvt_Entity) {
accept = !item->isOwnParent(data->id);
}
break;
case Uml::lvt_Operation:
if (dstType == Uml::lvt_Class ||
dstType == Uml::lvt_Interface) {
accept = !item->isOwnParent(data->id);
}
break;
case Uml::lvt_Datatype:
accept = (dstType == Uml::lvt_Logical_Folder ||
dstType == Uml::lvt_Datatype_Folder ||
dstType == Uml::lvt_Class ||
dstType == Uml::lvt_Interface ||
dstType == Uml::lvt_Package);
break;
case Uml::lvt_Class_Diagram:
case Uml::lvt_Collaboration_Diagram:
case Uml::lvt_State_Diagram:
case Uml::lvt_Activity_Diagram:
case Uml::lvt_Sequence_Diagram:
accept = (dstType == Uml::lvt_Logical_Folder ||
dstType == Uml::lvt_Logical_View);
break;
case Uml::lvt_Logical_Folder:
if (dstType == Uml::lvt_Logical_Folder) {
accept = !item->isOwnParent(data->id);
} else {
accept = (dstType == Uml::lvt_Logical_View);
}
break;
case Uml::lvt_UseCase_Folder:
if (dstType == Uml::lvt_UseCase_Folder) {
accept = !item->isOwnParent(data->id);
} else {
accept = (dstType == Uml::lvt_UseCase_View);
}
break;
case Uml::lvt_Component_Folder:
if (dstType == Uml::lvt_Component_Folder) {
accept = !item->isOwnParent(data->id);
} else {
accept = (dstType == Uml::lvt_Component_View);
}
break;
case Uml::lvt_Deployment_Folder:
if (dstType == Uml::lvt_Deployment_Folder) {
accept = !item->isOwnParent(data->id);
} else {
accept = (dstType == Uml::lvt_Deployment_View);
}
break;
case Uml::lvt_EntityRelationship_Folder:
if (dstType == Uml::lvt_EntityRelationship_Folder) {
accept = !item->isOwnParent(data->id);
} else {
accept = (dstType == Uml::lvt_EntityRelationship_Model);
}
break;
case Uml::lvt_Actor:
case Uml::lvt_UseCase:
case Uml::lvt_UseCase_Diagram:
accept = (dstType == Uml::lvt_UseCase_Folder ||
dstType == Uml::lvt_UseCase_View);
break;
case Uml::lvt_Subsystem:
accept = (dstType == Uml::lvt_Component_Folder ||
dstType == Uml::lvt_Subsystem);
break;
case Uml::lvt_Component:
accept = (dstType == Uml::lvt_Component_Folder ||
dstType == Uml::lvt_Component ||
dstType == Uml::lvt_Subsystem);
break;
case Uml::lvt_Artifact:
case Uml::lvt_Component_Diagram:
accept = (dstType == Uml::lvt_Component_Folder ||
dstType == Uml::lvt_Component_View);
break;
case Uml::lvt_Node:
case Uml::lvt_Deployment_Diagram:
accept = (dstType == Uml::lvt_Deployment_Folder);
break;
case Uml::lvt_Entity:
case Uml::lvt_EntityRelationship_Diagram:
accept = (dstType == Uml::lvt_EntityRelationship_Folder);
break;
default:
accept = false;
break;
}
}
//kDebug() << "UMLListView::acceptDrag: dstType = " << dstType
// << ", accept=" << accept << endl;
return accept;
}
void UMLListView::addAtContainer(UMLListViewItem *item, UMLListViewItem *parent) {
UMLCanvasObject *o = static_cast<UMLCanvasObject*>(item->getUMLObject());
if (o == NULL) {
kDebug() << "UMLListView::addAtContainer(" << item->getText()
<< "): item's UMLObject is NULL" << endl;
} else if (Model_Utils::typeIsContainer(parent->getType())) {
/**** TBC: Do this here?
If yes then remove that logic at the callers
and rename this method to moveAtContainer()
UMLPackage *oldPkg = o->getUMLPackage();
if (oldPkg)
oldPkg->removeObject(o);
*********/
UMLPackage *pkg = static_cast<UMLPackage*>(parent->getUMLObject());
o->setUMLPackage(pkg);
pkg->addObject(o);
} else {
kError() << "UMLListView::addAtContainer(" << item->getText()
<< "): parent type is " << parent->getType() << endl;
}
UMLView *currentView = UMLApp::app()->getCurrentView();
if (currentView)
currentView->updateContainment(o);
}
UMLListViewItem * UMLListView::moveObject(Uml::IDType srcId, Uml::ListView_Type srcType,
UMLListViewItem *newParent) {
if (newParent == NULL)
return NULL;
UMLListViewItem * move = findItem( srcId );
if (move == NULL)
return NULL;
UMLObject *newParentObj = NULL;
// Remove the source object at the old parent package.
UMLObject *srcObj = m_doc->findObjectById(srcId);
if (srcObj) {
newParentObj = newParent->getUMLObject();
if (srcObj == newParentObj) {
kError() << "UMLListView::moveObject(" << srcObj->getName()
<< "): Cannot move onto self" << endl;
return NULL;
}
UMLPackage *srcPkg = srcObj->getUMLPackage();
if (srcPkg) {
if (srcPkg == newParentObj) {
kError() << "UMLListView::moveObject(" << srcObj->getName()
<< "): Object is already in target package" << endl;
return NULL;
}
srcPkg->removeObject(srcObj);
}
}
Uml::ListView_Type newParentType = newParent->getType();
kDebug() << "UMLListView::moveObject: newParentType is " << newParentType << endl;
UMLListViewItem *newItem = NULL;
//make sure trying to place in correct location
switch (srcType) {
case Uml::lvt_UseCase_Folder:
case Uml::lvt_Actor:
case Uml::lvt_UseCase:
case Uml::lvt_UseCase_Diagram:
if (newParentType == Uml::lvt_UseCase_Folder ||
newParentType == Uml::lvt_UseCase_View) {
newItem = move->deepCopy(newParent);
if (m_doc->loading()) // deletion is not safe while loading
move->setVisible(false); // (the <listview> XMI may be corrupted)
else
delete move;
addAtContainer(newItem, newParent);
}
break;
case Uml::lvt_Component_Folder:
case Uml::lvt_Artifact:
case Uml::lvt_Component_Diagram:
if (newParentType == Uml::lvt_Component_Folder ||
newParentType == Uml::lvt_Component_View) {
newItem = move->deepCopy(newParent);
if (m_doc->loading()) // deletion is not safe while loading
move->setVisible(false); // (the <listview> XMI may be corrupted)
else
delete move;
addAtContainer(newItem, newParent);
}
break;
case Uml::lvt_Subsystem:
if (newParentType == Uml::lvt_Component_Folder ||
newParentType == Uml::lvt_Component_View ||
newParentType == Uml::lvt_Subsystem) {
newItem = move->deepCopy(newParent);
if (m_doc->loading()) // deletion is not safe while loading
move->setVisible(false); // (the <listview> XMI may be corrupted)
else
delete move;
addAtContainer(newItem, newParent);
}
break;
case Uml::lvt_Component:
if (newParentType == Uml::lvt_Component_Folder ||
newParentType == Uml::lvt_Component_View ||
newParentType == Uml::lvt_Component ||
newParentType == Uml::lvt_Subsystem) {
newItem = move->deepCopy(newParent);
if (m_doc->loading()) // deletion is not safe while loading
move->setVisible(false); // (the <listview> XMI may be corrupted)
else
delete move;
addAtContainer(newItem, newParent);
}
break;
case Uml::lvt_Deployment_Folder:
case Uml::lvt_Node:
case Uml::lvt_Deployment_Diagram:
if (newParentType == Uml::lvt_Deployment_Folder ||
newParentType == Uml::lvt_Deployment_View) {
newItem = move->deepCopy(newParent);
if (m_doc->loading()) // deletion is not safe while loading
move->setVisible(false); // (the <listview> XMI may be corrupted)
else
delete move;
addAtContainer(newItem, newParent);
}
break;
case Uml::lvt_EntityRelationship_Folder:
case Uml::lvt_Entity:
case Uml::lvt_EntityRelationship_Diagram:
if (newParentType == Uml::lvt_EntityRelationship_Folder ||
newParentType == Uml::lvt_EntityRelationship_Model) {
newItem = move->deepCopy(newParent);
if (m_doc->loading()) // deletion is not safe while loading
move->setVisible(false); // (the <listview> XMI may be corrupted)
else
delete move;
addAtContainer(newItem, newParent);
}
break;
case Uml::lvt_Collaboration_Diagram:
case Uml::lvt_Class_Diagram:
case Uml::lvt_State_Diagram:
case Uml::lvt_Activity_Diagram:
case Uml::lvt_Sequence_Diagram:
case Uml::lvt_Logical_Folder:
if (newParentType == Uml::lvt_Logical_Folder ||
newParentType == Uml::lvt_Logical_View) {
newItem = move->deepCopy(newParent);
if (m_doc->loading()) // deletion is not safe while loading
move->setVisible(false); // (the <listview> XMI may be corrupted)
else
delete move;
addAtContainer(newItem, newParent);
}
break;
case Uml::lvt_Class:
case Uml::lvt_Package:
case Uml::lvt_Interface:
case Uml::lvt_Enum:
case Uml::lvt_Datatype:
if (newParentType == Uml::lvt_Logical_Folder ||
newParentType == Uml::lvt_Datatype_Folder ||
newParentType == Uml::lvt_Logical_View ||
newParentType == Uml::lvt_Class ||
newParentType == Uml::lvt_Interface ||
newParentType == Uml::lvt_Package) {
newItem = move->deepCopy(newParent);
if (m_doc->loading()) // deletion is not safe while loading
move->setVisible(false); // (the <listview> XMI may be corrupted)
else
delete move;
UMLCanvasObject *o = static_cast<UMLCanvasObject*>(newItem->getUMLObject());
if (o == NULL) {
kDebug() << "moveObject: newItem's UMLObject is NULL" << endl;
} else if (newParentObj == NULL) {
kError() << "UMLListView::moveObject(" << o->getName()
<< "): newParentObj is NULL" << endl;
} else {
UMLPackage *pkg = static_cast<UMLPackage*>(newParentObj);
o->setUMLPackage( pkg );
pkg->addObject( o );
}
UMLView *currentView = UMLApp::app()->getCurrentView();
if (currentView)
currentView->updateContainment(o);
}
break;
case Uml::lvt_Attribute:
case Uml::lvt_Operation:
if (newParentType == Uml::lvt_Class ||
newParentType == Uml::lvt_Interface) {
// update list view
newItem = move->deepCopy(newParent);
// we don't delete move right away, it will be deleted in slots,
// called by subsequent steps
//delete move;
// update model objects
m_bCreatingChildObject = true;
UMLClassifier *oldParentClassifier = dynamic_cast<UMLClassifier*>(srcObj->parent());
UMLClassifier *newParentClassifier = dynamic_cast<UMLClassifier*>(newParentObj);
if (srcType == Uml::lvt_Attribute) {
UMLAttribute *att = dynamic_cast<UMLAttribute*>(srcObj);
// We can't use the existing 'att' directly
// because its parent is fixed to the old classifier
// and we have no way of changing that:
// TQObject does not permit changing the parent().
if (att == NULL) {
kError() << "moveObject internal error: srcObj "
<< srcObj->getName() << " is not a UMLAttribute" << endl;
} else if (oldParentClassifier->takeItem(att) == -1) {
kError() << "moveObject: oldParentClassifier->takeItem(att "
<< att->getName() << ") returns NULL" << endl;
} else {
const TQString& nm = att->getName();
UMLAttribute *newAtt = newParentClassifier->createAttribute(nm,
att->getType(),
att->getVisibility(),
att->getInitialValue());
newItem->setUMLObject(newAtt);
newParent->addClassifierListItem( newAtt, newItem );
connectNewObjectsSlots( newAtt );
// Let's not forget to update the DocWindow::m_pObject
// because the old one is about to be physically deleted !
UMLApp::app()->getDocWindow()->showDocumentation(newAtt, true);
delete att;
}
} else {
UMLOperation *op = dynamic_cast<UMLOperation*>(srcObj);
// We can't use the existing 'op' directly
// because its parent is fixed to the old classifier
// and we have no way of changing that:
// TQObject does not permit changing the parent().
if (op && oldParentClassifier->takeItem(op) != -1) {
bool isExistingOp;
Model_Utils::NameAndType_List ntDummyList;
// We need to provide a dummy NameAndType_List
// else UMLClassifier::createOperation will
// bring up an operation dialog.
UMLOperation *newOp = newParentClassifier->createOperation(
op->getName(), &isExistingOp, &ntDummyList);
newOp->setType(op->getType());
newOp->setVisibility(op->getVisibility());
UMLAttributeList parmList = op->getParmList();
for (UMLAttributeListIt plit(parmList); plit.current(); ++plit) {
UMLAttribute *parm = plit.current();
UMLAttribute *newParm = new UMLAttribute(newParentClassifier,
parm->getName(),
Uml::id_None,
parm->getVisibility(),
parm->getType(),
parm->getInitialValue());
newParm->setParmKind(parm->getParmKind());
newOp->addParm(newParm);
}
newItem->setUMLObject(newOp);
newParent->addClassifierListItem( newOp, newItem );
connectNewObjectsSlots( newOp );
// Let's not forget to update the DocWindow::m_pObject
// because the old one is about to be physically deleted !
UMLApp::app()->getDocWindow()->showDocumentation(newOp, true);
delete op;
} else {
kError() << "moveObject: oldParentClassifier->takeItem(op) returns NULL"
<< endl;
}
}
m_bCreatingChildObject = false;
}
break;
default:
break;
}
return newItem;
}
void UMLListView::slotDropped(TQDropEvent* de, TQListViewItem* /* parent */, TQListViewItem* item) {
item = (UMLListViewItem *)currentItem();
if(!item) {
kDebug() << "UMLListView::slotDropped: item is NULL - doing nothing" << endl;
return;
}
UMLDrag::LvTypeAndID_List srcList;
if (! UMLDrag::getClip3TypeAndID(de, srcList)) {
return;
}
UMLListViewItem *newParent = (UMLListViewItem*)item;
kDebug() << "slotDropped: newParent->getText() is " << newParent->getText() << endl;
UMLDrag::LvTypeAndID_It it(srcList);
UMLDrag::LvTypeAndID * src = 0;
while((src = it.current()) != 0) {
++it;
moveObject(src->id, src->type, newParent);
}
}
int UMLListView::getSelectedItems(UMLListViewItemList &ItemList) {
ItemList.setAutoDelete( false );
TQListViewItemIterator it(this);
// iterate through all items of the list view
for ( ; it.current(); ++it ) {
if ( it.current()->isSelected() ) {
UMLListViewItem *item = (UMLListViewItem*)it.current();
ItemList.append(item);
}
}
kDebug() << "UMLListView::getSelectedItems: selItems = " << ItemList.count() << endl;
return (int)ItemList.count();
}
int UMLListView::getSelectedItemsRoot(UMLListViewItemList &ItemList) {
ItemList.setAutoDelete( false );
TQListViewItemIterator it(this);
// iterate through all items of the list view
for ( ; it.current(); ++it ) {
if ( it.current()->isSelected() ) {
UMLListViewItem *item = (UMLListViewItem*)it.current();
// this is the trick, we select only the item with a parent unselected
// since we can't select a child and its grandfather without its parent
// we would be able to delete each item individually, without an invalid iterator
if (item && item->parent() && item->parent()->isSelected()==false) {
ItemList.append(item);
}
}
}
kDebug() << "UMLListView::getSelectedItemsRoot: selItems = " << ItemList.count() << endl;
return (int)ItemList.count();
}
UMLListViewItem* UMLListView::createDiagramItem(UMLView *v) {
Uml::ListView_Type lvt = Model_Utils::convert_DT_LVT(v->getType());
UMLListViewItem *parent = NULL;
UMLFolder *f = v->getFolder();
if (f) {
parent = findUMLObject(f);
if (parent == NULL)
kError() << "UMLListView::createDiagramItem(" << v->getName()
<< "): findUMLObject(" << f->getName() << ") returns NULL"
<< endl;
} else {
kDebug() << "UMLListView::createDiagramItem(" << v->getName()
<< "): no parent folder set, using predefined folder" << endl;
}
if (parent == NULL) {
parent = determineParentItem(lvt);
lvt = Model_Utils::convert_DT_LVT(v->getType());
}
UMLListViewItem *item = new UMLListViewItem(parent, v->getName(), lvt, v->getID());
return item;
}
/** Creates a new UMLListViewItem from a UMLListViewItem,
if parent is null the ListView Decides who is going to be
the parent */
UMLListViewItem* UMLListView::createItem(UMLListViewItem& Data, IDChangeLog& IDChanges,
UMLListViewItem* parent /*= 0*/) {
UMLObject* pObject = 0;
UMLListViewItem* item = 0;
Uml::ListView_Type lvt = Data.getType();
if(!parent) {
parent = determineParentItem(lvt);
if (!parent)
return 0;
}
switch(lvt) {
case Uml::lvt_Actor:
case Uml::lvt_UseCase:
case Uml::lvt_Class:
case Uml::lvt_Package:
case Uml::lvt_Subsystem:
case Uml::lvt_Component:
case Uml::lvt_Node:
case Uml::lvt_Artifact:
case Uml::lvt_Interface:
case Uml::lvt_Datatype:
case Uml::lvt_Enum:
case Uml::lvt_Entity:
case Uml::lvt_Logical_Folder:
case Uml::lvt_UseCase_Folder:
case Uml::lvt_Component_Folder:
case Uml::lvt_Deployment_Folder:
case Uml::lvt_EntityRelationship_Folder:
/***
int newID = IDChanges.findNewID(Data.getID());
//if there is no ListViewItem associated with the new ID,
//it could exist an Item already asocciated if the user chose to reuse an uml object
if(!(item = findItem(newID))) {
pObject = m_doc->findObjectById( IDChanges.findNewID(Data.getID()) );
item = new UMLListViewItem(parent, Data.getText(), lvt, pObject);
} ***/
pObject = m_doc->findObjectById( Data.getID() );
item = new UMLListViewItem(parent, Data.getText(), lvt, pObject);
break;
case Uml::lvt_Datatype_Folder:
item = new UMLListViewItem(parent, Data.getText(), lvt);
break;
case Uml::lvt_Attribute:
case Uml::lvt_EntityAttribute:
case Uml::lvt_Operation:
case Uml::lvt_Template:
case Uml::lvt_EnumLiteral:
{
UMLClassifier *pClass = static_cast<UMLClassifier*>(parent->getUMLObject());
Uml::IDType newID = IDChanges.findNewID( Data.getID() );
pObject = pClass->findChildObjectById(newID);
if (pObject) {
item = new UMLListViewItem( parent, Data.getText(), lvt, pObject );
} else {
item = 0;
}
break;
}
case Uml::lvt_UseCase_Diagram:
case Uml::lvt_Sequence_Diagram:
case Uml::lvt_Collaboration_Diagram:
case Uml::lvt_Class_Diagram:
case Uml::lvt_State_Diagram:
case Uml::lvt_Activity_Diagram:
case Uml::lvt_Component_Diagram:
case Uml::lvt_Deployment_Diagram:
case Uml::lvt_EntityRelationship_Diagram:
{
Uml::IDType newID = IDChanges.findNewID(Data.getID());
UMLView* v = m_doc->findView(newID);
if (v == NULL) {
return NULL;
}
const Uml::ListView_Type lvt = Model_Utils::convert_DT_LVT(v->getType());
item = new UMLListViewItem(parent, v->getName(), lvt, newID);
}
break;
default:
kWarning() << "createItem() called on unknown type" << endl;
break;
}
return item;
}
UMLListViewItem* UMLListView::determineParentItem(Uml::ListView_Type lvt) const {
UMLListViewItem* parent = 0;
switch (lvt) {
case Uml::lvt_Datatype:
parent = m_datatypeFolder;
break;
case Uml::lvt_Actor:
case Uml::lvt_UseCase:
case Uml::lvt_UseCase_Folder:
case Uml::lvt_UseCase_Diagram:
parent = m_lv[Uml::mt_UseCase];
break;
case Uml::lvt_Component_Diagram:
case Uml::lvt_Component:
case Uml::lvt_Artifact:
parent = m_lv[Uml::mt_Component];
break;
case Uml::lvt_Deployment_Diagram:
case Uml::lvt_Node:
parent = m_lv[Uml::mt_Deployment];
break;
case Uml::lvt_EntityRelationship_Diagram:
case Uml::lvt_Entity:
parent = m_lv[Uml::mt_EntityRelationship];
break;
default:
if (Model_Utils::typeIsDiagram(lvt) || !Model_Utils::typeIsClassifierList(lvt))
parent = m_lv[Uml::mt_Logical];
break;
}
return parent;
}
int UMLListView::getSelectedCount() {
TQListViewItemIterator it(this);
int count = 0;
// iterate through all items of the list view
for ( ; it.current(); ++it ) {
if ( it.current()->isSelected() ) {
count++;
}
}
return count;
}
void UMLListView::focusOutEvent ( TQFocusEvent * fe) {
if (fe->reason() != TQFocusEvent::Popup) {
clearSelection();
triggerUpdate();
}
//repaint();
TQListView::focusOutEvent(fe);
}
Uml::ListView_Type UMLListView::rootViewType(UMLListViewItem *item) {
if (item == m_rv)
return Uml::lvt_View;
if (item == m_lv[Uml::mt_Logical])
return Uml::lvt_Logical_View;
if (item == m_lv[Uml::mt_UseCase])
return Uml::lvt_UseCase_View;
if (item == m_lv[Uml::mt_Component])
return Uml::lvt_Component_View;
if (item == m_lv[Uml::mt_Deployment])
return Uml::lvt_Deployment_View;
if (item == m_lv[Uml::mt_EntityRelationship])
return Uml::lvt_EntityRelationship_Model;
UMLListViewItem *parent = dynamic_cast<UMLListViewItem*>(item->parent());
if (parent)
return rootViewType(parent);
return Uml::lvt_Unknown;
}
TQPixmap & UMLListView::getPixmap(Uml::Icon_Type type) {
if (type < Uml::it_Home || type >= Uml::N_ICONTYPES) {
kWarning() << "getPixmap() called on unknown icon " << type << endl;
// you'll know you have a problem if this shows up in the list
type = Uml::it_Home;
}
return m_Pixmaps[type];
}
void UMLListView::loadPixmaps() {
KStandardDirs * dirs = TDEGlobal::dirs();
TQString dataDir = dirs -> findResourceDir("data", "umbrello/pics/object.png");
dataDir += "/umbrello/pics/";
#define makeBarIcon(iconType, barIcon) m_Pixmaps[iconType] = BarIcon(barIcon)
makeBarIcon(Uml::it_Home, "folder_home");
makeBarIcon(Uml::it_Folder_Cyan, "folder");
makeBarIcon(Uml::it_Folder_Cyan_Open, "folder_open");
makeBarIcon(Uml::it_Folder_Green, "folder_green");
makeBarIcon(Uml::it_Folder_Green_Open, "folder_green_open");
makeBarIcon(Uml::it_Folder_Orange, "folder_orange");
makeBarIcon(Uml::it_Folder_Orange_Open, "folder_orange_open");
makeBarIcon(Uml::it_Folder_Grey, "folder_grey");
makeBarIcon(Uml::it_Folder_Grey_Open, "folder_grey_open");
makeBarIcon(Uml::it_Folder_Red, "folder_red");
makeBarIcon(Uml::it_Folder_Red_Open, "folder_red_open");
makeBarIcon(Uml::it_Folder_Violet, "folder_violet");
makeBarIcon(Uml::it_Folder_Violet_Open, "folder_violet_open");
makeBarIcon(Uml::it_Diagram_Activity, "umbrello_diagram_activity");
makeBarIcon(Uml::it_Diagram_Class, "umbrello_diagram_class");
makeBarIcon(Uml::it_Diagram_Component, "umbrello_diagram_component");
makeBarIcon(Uml::it_Diagram_State, "umbrello_diagram_state");
makeBarIcon(Uml::it_Diagram_Sequence, "umbrello_diagram_sequence");
makeBarIcon(Uml::it_Diagram_Deployment, "umbrello_diagram_deployment");
makeBarIcon(Uml::it_Diagram_EntityRelationship, "umbrello_diagram_deployment");
makeBarIcon(Uml::it_Diagram_Usecase, "umbrello_diagram_usecase");
makeBarIcon(Uml::it_Diagram_Collaboration, "umbrello_diagram_collaboration");
#undef makeBarIcon
#define loadPixmap(iconType, pngName) m_Pixmaps[iconType].load(dataDir + pngName)
loadPixmap(Uml::it_Diagram, "CVnamespace.png");
loadPixmap(Uml::it_Class, "class.png");
loadPixmap(Uml::it_Template, "template.png");
loadPixmap(Uml::it_Package, "package.png");
loadPixmap(Uml::it_Subsystem, "subsystem.png");
loadPixmap(Uml::it_Component, "component.png");
loadPixmap(Uml::it_Node, "node.png");
loadPixmap(Uml::it_Artifact, "artifact.png");
loadPixmap(Uml::it_Interface, "interface.png");
loadPixmap(Uml::it_Datatype, "datatype.png");
loadPixmap(Uml::it_Enum, "enum.png");
loadPixmap(Uml::it_Entity, "entity.png");
loadPixmap(Uml::it_Actor, "actor.png");
loadPixmap(Uml::it_UseCase, "usecase.png");
loadPixmap(Uml::it_Public_Method, "CVpublic_meth.png");
loadPixmap(Uml::it_Private_Method, "CVprivate_meth.png");
loadPixmap(Uml::it_Protected_Method, "CVprotected_meth.png");
loadPixmap(Uml::it_Public_Attribute, "CVpublic_var.png");
loadPixmap(Uml::it_Private_Attribute, "CVprivate_var.png");
loadPixmap(Uml::it_Protected_Attribute, "CVprotected_var.png");
#undef loadPixmap
}
bool UMLListView::isExpandable(Uml::ListView_Type lvt) {
if (Model_Utils::typeIsRootView(lvt) || Model_Utils::typeIsFolder(lvt))
return true;
switch (lvt) {
case Uml::lvt_Package:
case Uml::lvt_Component:
case Uml::lvt_Subsystem:
return true;
break;
default:
break;
}
return false;
}
void UMLListView::slotExpanded( TQListViewItem * item ) {
UMLListViewItem * myItem= static_cast<UMLListViewItem*>(item);
if (isExpandable(myItem->getType()))
myItem->updateFolder();
}
void UMLListView::slotCollapsed( TQListViewItem * item ) {
UMLListViewItem * myItem = static_cast<UMLListViewItem*>(item);
if (isExpandable(myItem->getType()))
myItem->updateFolder();
}
void UMLListView::slotCutSuccessful() {
if( m_bStartedCut ) {
popupMenuSel( ListPopupMenu::mt_Delete );
//deletion code here
m_bStartedCut = false;
}
}
void UMLListView::addNewItem(UMLListViewItem *parentItem, Uml::ListView_Type type) {
if (type == Uml::lvt_Datatype) {
parentItem = m_datatypeFolder;
}
UMLListViewItem * newItem = NULL;
parentItem->setOpen( true );
Uml::Icon_Type icon = Model_Utils::convert_LVT_IT(type);
TQString name;
if (Model_Utils::typeIsDiagram(type)) {
Uml::Diagram_Type dt = Model_Utils::convert_LVT_DT(type);
name = getUniqueDiagramName(dt);
newItem = new UMLListViewItem(parentItem, name, type, Uml::id_None);
} else {
Uml::Object_Type ot = Model_Utils::convert_LVT_OT(type);
if (ot == Uml::ot_UMLObject) {
kDebug() << "UMLListView::addNewItem: no UMLObject for listview type "
<< type << endl;
return;
}
UMLPackage *parentPkg =
dynamic_cast<UMLPackage*>(parentItem->getUMLObject());
if (parentPkg == NULL) {
kError() << "UMLListView::addNewItem(type " << type
<< "): parentPkg is NULL" << endl;
return;
}
if (Model_Utils::typeIsClassifierList(type)) {
UMLClassifier *parent = static_cast<UMLClassifier*>(parentPkg);
name = parent->uniqChildName(ot);
} else {
name = Model_Utils::uniqObjectName(ot, parentPkg);
}
newItem = new UMLListViewItem(parentItem, name, type, (UMLObject*)0);
}
m_bIgnoreCancelRename = false;
newItem->setIcon( icon );
newItem->setOpen( true );
newItem->setCreating( true );
newItem->startRename( 0 ); // calls TQListView::ensureItemVisible()
// When the user accepts the rename operation, UMLListViewItem::okRename()
// is called (automatically by TQListViewItem.)
}
bool UMLListView::itemRenamed( TQListViewItem * item , int /*col*/ ) {
//if true the item was cancel before this message
if( m_bIgnoreCancelRename ) {
return true;
}
m_bIgnoreCancelRename = true;
UMLListViewItem * renamedItem = static_cast< UMLListViewItem *>( item ) ;
Uml::ListView_Type type = renamedItem -> getType();
TQString newText = renamedItem -> text( 0 );
renamedItem -> setCreating( false );
// If the type is empty then delete it.
if (newText.isEmpty() || newText.contains(TQRegExp("^\\s+$"))) {
KMessageBox::error(
kapp -> mainWidget(),
i18n( "The name you entered was invalid.\nCreation process has been canceled." ),
i18n( "Name Not Valid" ) );
return false;
}
if( !isUnique( renamedItem, newText ) ) {
//if operation ask if ok not to be unique i.e overloading
if( type == Uml::lvt_Operation ) {
if( KMessageBox::warningYesNo(
kapp -> mainWidget(),
i18n( "The name you entered was not unique.\nIs this what you wanted?" ),
i18n( "Name Not Unique" ), i18n("Use Name"), i18n("Enter New Name") ) == KMessageBox::No ) {
return false;
}
} else {
KMessageBox::error(
kapp -> mainWidget(),
i18n( "The name you entered was not unique!\nCreation process has been canceled." ),
i18n( "Name Not Unique" ) );
return false;
}
}
switch( type ) {
case Uml::lvt_Actor:
case Uml::lvt_Class:
case Uml::lvt_Package:
case Uml::lvt_Logical_Folder:
case Uml::lvt_UseCase_Folder:
case Uml::lvt_Component_Folder:
case Uml::lvt_Deployment_Folder:
case Uml::lvt_EntityRelationship_Folder:
case Uml::lvt_Subsystem:
case Uml::lvt_Component:
case Uml::lvt_Node:
case Uml::lvt_Artifact:
case Uml::lvt_Interface:
case Uml::lvt_Datatype:
case Uml::lvt_Enum:
case Uml::lvt_Entity:
case Uml::lvt_UseCase:
{
Uml::Object_Type ot = Model_Utils::convert_LVT_OT(type);
if (! ot) {
kError() << "UMLListView::itemRenamed() internal" << endl;
return false;
}
UMLObject *o = createUMLObject( renamedItem, ot );
if (type == Uml::lvt_Subsystem)
o->setStereotype("subsystem");
else if (Model_Utils::typeIsFolder(type))
o->setStereotype("folder");
}
break;
case Uml::lvt_Attribute:
case Uml::lvt_EntityAttribute:
case Uml::lvt_Operation:
case Uml::lvt_Template:
case Uml::lvt_EnumLiteral:
return createChildUMLObject( renamedItem, Model_Utils::convert_LVT_OT(type) );
break;
case Uml::lvt_Class_Diagram:
createDiagram( renamedItem, Uml::dt_Class );
break;
case Uml::lvt_UseCase_Diagram:
createDiagram( renamedItem, Uml::dt_UseCase );
break;
case Uml::lvt_Sequence_Diagram:
createDiagram( renamedItem, Uml::dt_Sequence );
break;
case Uml::lvt_Collaboration_Diagram:
createDiagram( renamedItem, Uml::dt_Collaboration );
break;
case Uml::lvt_State_Diagram:
createDiagram( renamedItem, Uml::dt_State );
break;
case Uml::lvt_Activity_Diagram:
createDiagram( renamedItem, Uml::dt_Activity );
break;
case Uml::lvt_Component_Diagram:
createDiagram( renamedItem, Uml::dt_Component );
break;
case Uml::lvt_Deployment_Diagram:
createDiagram( renamedItem, Uml::dt_Deployment );
break;
case Uml::lvt_EntityRelationship_Diagram:
createDiagram( renamedItem, Uml::dt_EntityRelationship );
break;
default:
break;
}
return true;
}
UMLObject *UMLListView::createUMLObject( UMLListViewItem * item, Uml::Object_Type type ) {
TQString name = item -> text( 0 );
UMLObject * object = NULL;
switch( type ) {
case Uml::ot_UseCase:
object = new UMLUseCase( name );
break;
case Uml::ot_Actor:
object = new UMLActor( name );
break;
case Uml::ot_Class:
object = new UMLClassifier( name );
break;
case Uml::ot_Package:
object = new UMLPackage( name );
break;
case Uml::ot_Folder:
object = new UMLFolder( name );
break;
case Uml::ot_Component:
object = new UMLComponent( name );
break;
case Uml::ot_Node:
object = new UMLNode( name );
break;
case Uml::ot_Artifact:
object = new UMLArtifact( name );
break;
case Uml::ot_Interface:
{
UMLClassifier *c = new UMLClassifier(name);
c->setBaseType(Uml::ot_Interface);
object = c;
}
break;
case Uml::ot_Datatype:
{
UMLClassifier *c = new UMLClassifier(name);
c->setBaseType(Uml::ot_Datatype);
object = c;
}
break;
case Uml::ot_Enum:
object = new UMLEnum( name );
break;
case Uml::ot_Entity:
object = new UMLEntity( name );
break;
default:
kWarning() << "creating UML Object of unknown type" << endl;
return NULL;
}
UMLListViewItem * parentItem = static_cast<UMLListViewItem *>(item->parent());
const Uml::ListView_Type lvt = parentItem->getType();
if (! Model_Utils::typeIsContainer(lvt)) {
kError() << "UMLListView::createUMLObject(" << object->getName()
<< "): parentItem (" << lvt << " is not a container" << endl;
delete object;
return NULL;
}
UMLPackage *pkg = static_cast<UMLPackage*>(parentItem->getUMLObject());
object->setUMLPackage(pkg);
pkg->addObject(object);
connectNewObjectsSlots(object);
item -> setUMLObject( object );
item -> setText( name );
return object;
}
bool UMLListView::createChildUMLObject( UMLListViewItem * item, Uml::Object_Type type ) {
m_bCreatingChildObject = true;
TQString text = item->text( 0 );
UMLObject* parent = static_cast<UMLListViewItem *>( item->parent() )->getUMLObject();
if( !parent ) {
kError() << "UMLListView::createChildUMLObject: parent UMLObject is NULL" << endl;
m_bCreatingChildObject = false;
return false;
}
//kDebug() << "UMLListView::createChildUMLObject (" << text << ")" << endl;
UMLObject* newObject = NULL;
if ( type == Uml::ot_EnumLiteral ) {
UMLEnum *owningEnum = static_cast<UMLEnum*>(parent);
newObject = owningEnum->createEnumLiteral(text);
UMLEnumLiteral* enumLiteral = static_cast<UMLEnumLiteral*>(newObject);
text = enumLiteral->toString(Uml::st_SigNoVis);
} else if ( type == Uml::ot_Template ) {
UMLClassifier *owningClassifier = static_cast<UMLClassifier*>(parent);
Model_Utils::NameAndType nt;
Model_Utils::Parse_Status st = Model_Utils::parseTemplate(text, nt, owningClassifier);
if (st) {
KMessageBox::error( kapp->mainWidget(),
Model_Utils::psText(st),
i18n("Creation canceled") );
m_bCreatingChildObject = false;
return false;
}
newObject = owningClassifier->createTemplate(nt.m_name);
UMLTemplate *tmplParm = static_cast<UMLTemplate*>(newObject);
tmplParm->setType(nt.m_type);
text = tmplParm->toString(Uml::st_SigNoVis);
} else if (type == Uml::ot_Attribute || type == Uml::ot_EntityAttribute) {
UMLClassifier *owningClass = static_cast<UMLClassifier*>(parent);
Model_Utils::NameAndType nt;
Uml::Visibility vis;
Model_Utils::Parse_Status st;
st = Model_Utils::parseAttribute(text, nt, owningClass, &vis);
if (st) {
KMessageBox::error( kapp->mainWidget(),
Model_Utils::psText(st),
i18n("Creation canceled") );
m_bCreatingChildObject = false;
return false;
}
newObject = owningClass->createAttribute(nt.m_name, nt.m_type, vis, nt.m_initialValue);
UMLAttribute *att = static_cast<UMLAttribute*>(newObject);
att->setParmKind(nt.m_direction);
text = att->toString(Uml::st_SigNoVis);
} else if ( type == Uml::ot_Operation ) {
UMLClassifier *owningClassifier = static_cast<UMLClassifier*>(parent);
Model_Utils::OpDescriptor od;
Model_Utils::Parse_Status st = Model_Utils::parseOperation(text, od, owningClassifier);
if (st) {
KMessageBox::error( kapp->mainWidget(),
Model_Utils::psText(st),
i18n("Creation canceled") );
m_bCreatingChildObject = false;
return false;
}
bool isExistingOp = false;
newObject = owningClassifier->createOperation(od.m_name, &isExistingOp, &od.m_args);
if (newObject == NULL || isExistingOp) {
if (isExistingOp)
KMessageBox::error(
kapp -> mainWidget(),
i18n( "The name you entered was not unique!\nCreation process has been canceled." ),
i18n( "Name Not Unique" ) );
m_bCreatingChildObject = false;
return false;
}
UMLOperation *op = static_cast<UMLOperation*>(newObject);
if (od.m_pReturnType) {
op->setType(od.m_pReturnType);
}
text = op->toString(Uml::st_SigNoVis);
} else {
kError() << "UMLListView::createChildUMLObject called for type "
<< type << " (ignored)" << endl;
m_bCreatingChildObject = false;
return false;
}
// make changes to the object visible to this umllistviewitem
connectNewObjectsSlots( newObject );
item->setUMLObject( newObject );
item->setText( text );
ensureItemVisible(item);
// as it's a ClassifierListItem add it to the childObjectMap of the parent
UMLClassifierListItem* classifierListItem = static_cast<UMLClassifierListItem*>( newObject );
static_cast<UMLListViewItem*>( item->parent() )->addClassifierListItem(classifierListItem, item );
m_bCreatingChildObject = false;
if (! m_doc->loading())
m_doc->setModified();
return true;
}
void UMLListView::createDiagram( UMLListViewItem * item, Uml::Diagram_Type type ) {
TQString name = item -> text( 0 );
UMLView * view = m_doc -> findView( type, name );
if( view ) {
delete item;
return;
}
UMLListViewItem *parentItem = static_cast<UMLListViewItem*>(item->parent());
UMLFolder *parentFolder = dynamic_cast<UMLFolder*>(parentItem->getUMLObject());
if (parentFolder == NULL) {
kError() << "UMLListView::createDiagram(" << name
<< "): parent UMLObject is not a UMLFolder" << endl;
delete item;
return;
}
view = new UMLView(parentFolder);
view->setName( name );
view->setType( type );
view->setID( UniqueID::gen() );
m_doc -> addView( view );
view -> setOptionState( Settings::getOptionState() );
item -> setID( view -> getID() );
item -> setText( name );
view->activate();
m_doc -> changeCurrentView( view -> getID() );
}
TQString UMLListView::getUniqueDiagramName(Uml::Diagram_Type type) {
return m_doc->uniqViewName(type);
}
bool UMLListView::isUnique( UMLListViewItem * item, const TQString &name ) {
UMLListViewItem * parentItem = static_cast<UMLListViewItem *>( item -> parent() );
Uml::ListView_Type type = item -> getType();
switch( type ) {
case Uml::lvt_Class_Diagram:
return !m_doc -> findView( Uml::dt_Class, name );
break;
case Uml::lvt_Sequence_Diagram:
return !m_doc -> findView( Uml::dt_Sequence, name );
break;
case Uml::lvt_UseCase_Diagram:
return !m_doc -> findView( Uml::dt_UseCase, name );
break;
case Uml::lvt_Collaboration_Diagram:
return !m_doc -> findView( Uml::dt_Collaboration, name );
break;
case Uml::lvt_State_Diagram:
return !m_doc -> findView( Uml::dt_State, name );
break;
case Uml::lvt_Activity_Diagram:
return !m_doc -> findView( Uml::dt_Activity, name );
break;
case Uml::lvt_Component_Diagram:
return !m_doc->findView(Uml::dt_Component, name);
break;
case Uml::lvt_Deployment_Diagram:
return !m_doc->findView(Uml::dt_Deployment, name);
break;
case Uml::lvt_EntityRelationship_Diagram:
return !m_doc->findView(Uml::dt_EntityRelationship, name);
break;
case Uml::lvt_Actor:
case Uml::lvt_UseCase:
case Uml::lvt_Node:
case Uml::lvt_Artifact:
return !m_doc->findUMLObject( name, Model_Utils::convert_LVT_OT(type) );
break;
case Uml::lvt_Class:
case Uml::lvt_Package:
case Uml::lvt_Interface:
case Uml::lvt_Datatype:
case Uml::lvt_Enum:
case Uml::lvt_Entity:
case Uml::lvt_Component:
case Uml::lvt_Subsystem:
case Uml::lvt_Logical_Folder:
case Uml::lvt_UseCase_Folder:
case Uml::lvt_Component_Folder:
case Uml::lvt_Deployment_Folder:
case Uml::lvt_EntityRelationship_Folder:
{
Uml::ListView_Type lvt = parentItem->getType();
if (!Model_Utils::typeIsContainer(lvt))
return (m_doc->findUMLObject(name) == NULL);
UMLPackage *pkg = static_cast<UMLPackage*>(parentItem->getUMLObject());
if (pkg == NULL) {
kError() << "UMLListView::isUnique: internal error - "
<< "parent listviewitem is package but has no UMLObject" << endl;
return true;
}
return (pkg->findObject(name) == NULL);
break;
}
case Uml::lvt_Template:
case Uml::lvt_Attribute:
case Uml::lvt_EntityAttribute:
case Uml::lvt_Operation:
case Uml::lvt_EnumLiteral:
{
UMLClassifier *parent = static_cast<UMLClassifier*>(parentItem->getUMLObject());
return (parent->findChildObject(name) == NULL);
break;
}
default:
break;
}
return false;
}
void UMLListView::cancelRename( TQListViewItem * item ) {
if( !m_bIgnoreCancelRename ) {
delete item;
m_bIgnoreCancelRename = true;
}
}
void UMLListView::saveToXMI( TQDomDocument & qDoc, TQDomElement & qElement) {
TQDomElement listElement = qDoc.createElement( "listview" );
m_rv->saveToXMI(qDoc, listElement);
qElement.appendChild( listElement );
}
bool UMLListView::loadFromXMI( TQDomElement & element ) {
/*
deleteChildrenOf( m_ucv );
deleteChildrenOf( m_lv );
deleteChildrenOf( m_cmpv );
deleteChildrenOf( m_dplv );
*/
TQDomNode node = element.firstChild();
TQDomElement domElement = node.toElement();
m_doc->writeToStatusBar( i18n("Loading listview...") );
while( !domElement.isNull() ) {
if( domElement.tagName() == "listitem" ) {
TQString type = domElement.attribute( "type", "-1" );
if( type == "-1" )
return false;
Uml::ListView_Type lvType = (Uml::ListView_Type)type.toInt();
if( lvType == Uml::lvt_View ) {
if( !loadChildrenFromXMI( m_rv, domElement ) )
return false;
} else
return false;
}
node = node.nextSibling();
domElement = node.toElement();
}//end while
return true;
}
bool UMLListView::loadChildrenFromXMI( UMLListViewItem * parent, TQDomElement & element ) {
TQDomNode node = element.firstChild();
TQDomElement domElement = node.toElement();
const TQString pfx("UMLListView::loadChildrenFromXMI: ");
while( !domElement.isNull() ) {
node = domElement.nextSibling();
if( domElement.tagName() != "listitem" ) {
domElement = node.toElement();
continue;
}
TQString id = domElement.attribute( "id", "-1" );
TQString type = domElement.attribute( "type", "-1" );
TQString label = domElement.attribute( "label", "" );
TQString open = domElement.attribute( "open", "1" );
if( type == "-1" )
return false;
Uml::ListView_Type lvType = (Uml::ListView_Type)type.toInt();
bool bOpen = (bool)open.toInt();
Uml::IDType nID = STR2ID(id);
UMLObject * pObject = 0;
UMLListViewItem * item = 0;
if (nID != Uml::id_None) {
// The following is an ad hoc hack for the copy/paste code.
// The clip still contains the old children although new
// UMLCLassifierListItems have already been created.
// If the IDChangeLog finds new IDs this means we are in
// copy/paste and need to adjust the child listitems to the
// new UMLCLassifierListItems.
IDChangeLog *idchanges = m_doc->getChangeLog();
if (idchanges != NULL) {
Uml::IDType newID = idchanges->findNewID(nID);
if (newID != Uml::id_None) {
kDebug() << pfx << " using id " << ID2STR(newID)
<< " instead of " << ID2STR(nID) << endl;
nID = newID;
}
}
/************ End of hack for copy/paste code ************/
pObject = m_doc->findObjectById(nID);
if (pObject) {
if (label.isEmpty())
label = pObject->getName();
} else if (Model_Utils::typeIsFolder(lvType)) {
// Synthesize the UMLFolder here
UMLObject *umlParent = parent->getUMLObject();
UMLPackage *parentPkg = dynamic_cast<UMLPackage*>(umlParent);
if (parentPkg == NULL) {
kError() << pfx << "umlParent(" << umlParent << ") is not a UMLPackage"
<< endl;
domElement = node.toElement();
continue;
}
UMLFolder *f = new UMLFolder(label, nID);
f->setUMLPackage(parentPkg);
parentPkg->addObject(f);
pObject = f;
item = new UMLListViewItem(parent, label, lvType, pObject);
// Moving all relevant UMLObjects to the new UMLFolder is done below,
// in the switch(lvType)
}
} else if (Model_Utils::typeIsRootView(lvType)) {
// Predefined folders did not have their ID set.
const Uml::Model_Type mt = Model_Utils::convert_LVT_MT(lvType);
nID = m_doc->getRootFolder(mt)->getID();
} else if (Model_Utils::typeIsFolder(lvType)) {
// Pre-1.2 format: Folders did not have their ID set.
// Pull a new ID now.
nID = UniqueID::get();
} else {
kError() << pfx << "item of type " << type << " has no ID, skipping." << endl;
domElement = node.toElement();
continue;
}
switch( lvType ) {
case Uml::lvt_Actor:
case Uml::lvt_UseCase:
case Uml::lvt_Class:
case Uml::lvt_Interface:
case Uml::lvt_Datatype:
case Uml::lvt_Enum:
case Uml::lvt_Entity:
case Uml::lvt_Package:
case Uml::lvt_Subsystem:
case Uml::lvt_Component:
case Uml::lvt_Node:
case Uml::lvt_Artifact:
case Uml::lvt_Logical_Folder:
case Uml::lvt_UseCase_Folder:
case Uml::lvt_Component_Folder:
case Uml::lvt_Deployment_Folder:
case Uml::lvt_EntityRelationship_Folder:
item = findItem(nID);
if (item == NULL) {
kError() << pfx << "INTERNAL ERROR: "
<< "findItem(id " << ID2STR(nID) << ") returns NULL" << endl;
/*
if (pObject && pObject->getUMLPackage() &&
parent->getType() != Uml::lvt_Package) {
// Pre-1.2 file format:
// Objects were not nested in their packages.
// Synthesize the nesting here.
UMLPackage *umlpkg = pObject->getUMLPackage();
UMLListViewItem *pkgItem = findUMLObject(umlpkg);
if (pkgItem == NULL) {
kDebug() << pfx << "synthesizing ListViewItem for package "
<< ID2STR(umlpkg->getID()) << endl;
pkgItem = new UMLListViewItem(parent, umlpkg->getName(),
Uml::lvt_Package, umlpkg);
pkgItem->setOpen(true);
}
item = new UMLListViewItem(pkgItem, label, lvType, pObject);
} else {
item = new UMLListViewItem(parent, label, lvType, pObject);
}
*/
}
else if (parent != item->parent()) {
// The existing item was created by the slot event triggered
// by the loading of the corresponding model object from the
// XMI file.
// This early creation is done in order to support the loading
// of foreign XMI files that do not have the umbrello specific
// <listview> tag.
// However, now that we encountered the real <listview> info,
// we need to delete the existing item: Its parent is always
// one of the default predefined folders, but the actual
// listview item might be located in a user created folder.
// Thanks to Achim Spangler for spotting the problem.
UMLListViewItem *itmParent = dynamic_cast<UMLListViewItem*>(item->parent());
kDebug() << pfx << item->getText() << " parent "
<< parent->getText() << " (" << parent << ") != "
<< itmParent->getText() << " (" << itmParent << ")" << endl;
if (item == m_datatypeFolder && itmParent == m_lv[Uml::mt_Logical]) {
kDebug() << pfx << "Reparenting the Datatypes folder is prohibited" << endl;
} else {
UMLListViewItem *newItem = moveObject(nID, lvType, parent);
item = newItem;
if (item) {
kDebug() << pfx << "Attempted reparenting of " << item->getText()
<< "(current parent: " << (itmParent ? itmParent->getText() : "NULL")
<< ", new parent: " << parent->getText() << ")" << endl;
}
}
}
break;
case Uml::lvt_Attribute:
case Uml::lvt_EntityAttribute:
case Uml::lvt_Template:
case Uml::lvt_Operation:
case Uml::lvt_EnumLiteral:
item = findItem(nID);
if (item == NULL) {
kDebug() << pfx << "item " << ID2STR(nID) << " (of type "
<< lvType << ") does not yet exist..." << endl;
UMLObject* umlObject = parent->getUMLObject();
if (!umlObject) {
kDebug() << "And also the parent->getUMLObject() does not exist" << endl;
return false;
}
if (nID == Uml::id_None) {
kWarning() << pfx << "lvtype " << lvType << " has id -1" << endl;
} else {
UMLClassifier *classifier = dynamic_cast<UMLClassifier*>(umlObject);
if (classifier) {
umlObject = classifier->findChildObjectById(nID);
if (umlObject) {
connectNewObjectsSlots(umlObject);
label = umlObject->getName();
item = new UMLListViewItem( parent, label, lvType, umlObject);
} else {
kDebug() << pfx << "lvtype " << lvType << " child object "
<< ID2STR(nID) << " not found" << endl;
}
} else {
kDebug() << pfx << "cast to classifier object failed" << endl;
}
}
}
break;
case Uml::lvt_Logical_View:
item = m_lv[Uml::mt_Logical];
break;
case Uml::lvt_Datatype_Folder:
item = m_datatypeFolder;
break;
case Uml::lvt_UseCase_View:
item = m_lv[Uml::mt_UseCase];
break;
case Uml::lvt_Component_View:
item = m_lv[Uml::mt_Component];
break;
case Uml::lvt_Deployment_View:
item = m_lv[Uml::mt_Deployment];
break;
case Uml::lvt_EntityRelationship_Model:
item = m_lv[Uml::mt_EntityRelationship];
break;
default:
if (Model_Utils::typeIsDiagram(lvType)) {
item = new UMLListViewItem( parent, label, lvType, nID );
} else {
kError() << pfx << "INTERNAL ERROR: unexpected listview type "
<< lvType << " (ID " << ID2STR(nID) << ")" << endl;
}
break;
}//end switch
if (item) {
item->setOpen( (bool)bOpen );
if ( !loadChildrenFromXMI(item, domElement) ) {
return false;
}
} else {
kWarning() << "unused list view item " << ID2STR(nID)
<< " of lvtype " << lvType << endl;
}
domElement = node.toElement();
}//end while
return true;
}
/** Open all items in the list view*/
void UMLListView::expandAll(TQListViewItem *item) {
if(!item) item = firstChild();
for (item = item->firstChild(); item; item = item->nextSibling()) {
item->setOpen(true);
}
}
/** Close all items in the list view*/
void UMLListView::collapseAll(TQListViewItem *item) {
if(!item) item = firstChild();
for( item = item->firstChild(); item; item = item->nextSibling())
item->setOpen(false);
}
void UMLListView::setStartedCut(bool startedCut) {
m_bStartedCut = startedCut;
}
void UMLListView::setStartedCopy(bool startedCopy) {
m_bStartedCopy = startedCopy;
}
bool UMLListView::startedCopy() const {
return m_bStartedCopy;
}
UMLListViewItem *UMLListView::rootView(Uml::ListView_Type type) {
UMLListViewItem *theView = NULL;
switch (type) {
case Uml::lvt_View:
theView = m_rv;
break;
case Uml::lvt_Logical_View:
theView = m_lv[Uml::mt_Logical];
break;
case Uml::lvt_UseCase_View:
theView = m_lv[Uml::mt_UseCase];
break;
case Uml::lvt_Component_View:
theView = m_lv[Uml::mt_Component];
break;
case Uml::lvt_Deployment_View:
theView = m_lv[Uml::mt_Deployment];
break;
case Uml::lvt_EntityRelationship_Model:
theView = m_lv[Uml::mt_EntityRelationship];
break;
case Uml::lvt_Datatype_Folder: // @todo fix asymmetric naming
theView = m_datatypeFolder;
break;
default:
break;
}
return theView;
}
void UMLListView::deleteChildrenOf(TQListViewItem* parent) {
if ( !parent ) {
return;
}
if (parent == m_lv[Uml::mt_Logical])
m_datatypeFolder = NULL;
while ( parent->firstChild() ) {
delete parent->firstChild();
}
}
void UMLListView::closeDatatypesFolder() {
m_datatypeFolder->setOpen(false);
}
bool UMLListView::deleteItem(UMLListViewItem *temp) {
if (!temp)
return false;
UMLObject *object = temp->getUMLObject();
Uml::ListView_Type lvt = temp->getType();
if ( Model_Utils::typeIsDiagram(lvt) ) {
m_doc->removeDiagram( temp->getID() );
} else if (temp == m_datatypeFolder) {
// we can't delete the datatypeFolder because umbrello will crash without a special handling
return false;
} else if (Model_Utils::typeIsCanvasWidget(lvt) || Model_Utils::typeIsClassifierList(lvt)) {
UMLPackage *nmSpc = dynamic_cast<UMLPackage*>(object);
if (nmSpc) {
UMLObjectList contained = nmSpc->containedObjects();
if (contained.count()) {
KMessageBox::error(
kapp->mainWidget(),
i18n("The folder must be emptied before it can be deleted."),
i18n("Folder Not Empty"));
return false;
}
}
UMLCanvasObject *canvasObj = dynamic_cast<UMLCanvasObject*>(object);
if (canvasObj) {
/**
* We cannot just delete canvasObj here: What if the object
* is still being used by others (for example, as a parameter
* or return type of an operation) ?
* Deletion should not have been permitted in the first place
* if the object still has users - but Umbrello is lacking
* that logic.
*/
canvasObj->removeAllChildObjects();
}
if (object) {
m_doc->removeUMLObject(object);
// Physical deletion of `temp' will be done by TQt signal, see
// UMLDoc::removeUMLObject()
} else {
delete temp;
}
} else {
kWarning() << "umllistview::listpopupmenu::mt_Delete called with unknown type"
<< endl;
}
return true;
}
#include "umllistview.moc"