00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "umlclipboard.h"
00014
00015
00016 #include <kdebug.h>
00017 #include <kmessagebox.h>
00018 #include <klocale.h>
00019
00020
00021 #include "umldrag.h"
00022 #include "idchangelog.h"
00023 #include "../associationwidget.h"
00024 #include "../attribute.h"
00025 #include "../classifier.h"
00026 #include "../floatingtextwidget.h"
00027 #include "../operation.h"
00028 #include "../umldoc.h"
00029 #include "../umllistview.h"
00030 #include "../umllistviewitem.h"
00031 #include "../umlobjectlist.h"
00032 #include "../umlview.h"
00033 #include "../umlwidget.h"
00034 #include "../uml.h"
00035 #include "../model_utils.h"
00036
00037 UMLClipboard::UMLClipboard() {
00038 m_type = clip1;
00039 }
00040
00041 UMLClipboard::~UMLClipboard() {
00042 }
00043
00044 QMimeSource* UMLClipboard::copy(bool fromView) {
00045
00046 m_AssociationList.clear();
00047 m_ItemList.clear();
00048 m_ObjectList.clear();
00049 m_ViewList.clear();
00050
00051 UMLDrag *data = 0;
00052 QPixmap* png = 0;
00053
00054 UMLListView * listView = UMLApp::app()->getListView();
00055 UMLListViewItemList selectedItems;
00056 selectedItems.setAutoDelete(false);
00057
00058 if(fromView) {
00059 m_type = clip4;
00060 UMLView *view = UMLApp::app()->getCurrentView();
00061 view->checkSelections();
00062 if(!view->getSelectedWidgets(m_WidgetList)) {
00063 return 0;
00064 }
00065
00066 if(!m_WidgetList.count()) {
00067 return 0;
00068 }
00069 m_AssociationList = view->getSelectedAssocs();
00070 view->copyAsImage(png);
00071
00072 } else {
00073 if(!listView->getSelectedItems(selectedItems)) {
00074 return 0;
00075 }
00076
00077
00078 setCopyType(selectedItems);
00079
00080
00081
00082
00083 if(m_type == clip2) {
00084
00085
00086 selectedItems.clear();
00087
00088
00089 for (UMLViewListIt vit(m_ViewList); vit.current(); ++vit) {
00090 UMLObjectList objects = vit.current()->getUMLObjects();
00091 for (UMLObjectListIt oit(objects); oit.current(); ++oit) {
00092 UMLObject *o = oit.current();
00093 UMLListViewItem *item = listView->findUMLObject(o);
00094 if(item) {
00095 listView->setSelected(item, true);
00096 }
00097 }
00098 }
00099 if(!listView->getSelectedItems(selectedItems)) {
00100 return 0;
00101 }
00102 }
00103 if(!fillSelectionLists(selectedItems)) {
00104 return 0;
00105 }
00106 }
00107 int i =0;
00108 switch(m_type) {
00109 case clip1:
00110 data = new UMLDrag(m_ObjectList);
00111 break;
00112 case clip2:
00113 data = new UMLDrag(m_ObjectList, m_ItemList, m_ViewList);
00114 break;
00115 case clip3:
00116 data = new UMLDrag(m_ItemList);
00117 break;
00118 case clip4:
00119 if(png) {
00120 UMLView *view = UMLApp::app()->getCurrentView();
00121 data = new UMLDrag(m_ObjectList, m_WidgetList,
00122 m_AssociationList, *png, view->getType());
00123 } else {
00124 return 0;
00125 }
00126 break;
00127 case clip5:
00128 data = new UMLDrag(m_ObjectList, i);
00129
00130
00131 break;
00132 }
00133
00134 return (QMimeSource*)data;
00135 }
00136
00137 bool UMLClipboard::paste(QMimeSource* data) {
00138 UMLDoc *doc = UMLApp::app()->getDocument();
00139 bool result = false;
00140 doc->beginPaste();
00141 switch(UMLDrag::getCodingType(data)) {
00142 case 1:
00143 result = pasteClip1(data);
00144 break;
00145 case 2:
00146 result = pasteClip2(data);
00147 break;
00148 case 3:
00149 result = pasteClip3(data);
00150 break;
00151 case 4:
00152 result = pasteClip4(data);
00153 break;
00154 case 5:
00155 result = pasteClip5(data);
00156 break;
00157 default:
00158 break;
00159 }
00160 doc->endPaste();
00161 return result;
00162 }
00163
00164 bool UMLClipboard::fillSelectionLists(UMLListViewItemList& SelectedItems) {
00165 UMLListViewItemListIt it(SelectedItems);
00166 UMLListViewItem* item = 0;
00167 Uml::ListView_Type type;
00168 switch(m_type) {
00169 case clip4:
00170 break;
00171 case clip3:
00172 for ( ; it.current(); ++it ) {
00173 item = (UMLListViewItem*)it.current();
00174 type = item->getType();
00175 if ( !Model_Utils::typeIsClassifierList(type) ) {
00176 m_ItemList.append(item);
00177 insertItemChildren(item, SelectedItems);
00178
00179
00180
00181
00182
00183
00184 }
00185 }
00186 break;
00187 case clip2:
00188 case clip1:
00189 for ( ; it.current(); ++it ) {
00190 item = (UMLListViewItem*)it.current();
00191 type = item->getType();
00192 if ( !Model_Utils::typeIsClassifierList(type) ) {
00193
00194 m_ItemList.append(item);
00195
00196 if ( Model_Utils::typeIsCanvasWidget(type) ) {
00197 m_ObjectList.append(item->getUMLObject());
00198 }
00199 insertItemChildren(it.current(), SelectedItems);
00200 }
00201 }
00202 break;
00203 case clip5:
00204 for ( ; it.current(); ++it ) {
00205 item = (UMLListViewItem*)it.current();
00206 type = item->getType();
00207 if( Model_Utils::typeIsClassifierList(type) ) {
00208 m_ItemList.append(item);
00209 m_ObjectList.append(item->getUMLObject());
00210
00211 } else {
00212 return false;
00213 }
00214 }
00215 break;
00216 }
00217
00218 return true;
00219 }
00220
00221 void UMLClipboard::setCopyType(UMLListViewItemList& SelectedItems) {
00222 bool withDiagrams = false;
00223 bool withObjects = false;
00224 bool onlyAttsOps = false;
00225 UMLListViewItemListIt it(SelectedItems);
00226 for ( ; it.current(); ++it ) {
00227 checkItemForCopyType(it.current(), withDiagrams, withObjects, onlyAttsOps);
00228 }
00229 if(onlyAttsOps) {
00230 m_type = clip5;
00231 } else if(withDiagrams) {
00232 m_type = clip2;
00233 } else if(withObjects) {
00234 m_type = clip1;
00235 } else {
00236 m_type = clip3;
00237 }
00238 }
00239
00240 void UMLClipboard::checkItemForCopyType(UMLListViewItem* Item, bool & WithDiagrams, bool &WithObjects,
00241 bool &OnlyAttsOps) {
00242 if(!Item) {
00243 return;
00244 }
00245 UMLDoc *doc = UMLApp::app()->getDocument();
00246 OnlyAttsOps = true;
00247 UMLView * view = 0;
00248 UMLListViewItem * child = 0;
00249 Uml::ListView_Type type = Item->getType();
00250 if ( Model_Utils::typeIsCanvasWidget(type) ) {
00251 WithObjects = true;
00252 OnlyAttsOps = false;
00253 } else if ( Model_Utils::typeIsDiagram(type) ) {
00254 WithDiagrams = true;
00255 OnlyAttsOps = false;
00256 view = doc->findView( Item->getID() );
00257 m_ViewList.append( view );
00258 } else if ( Model_Utils::typeIsFolder(type) ) {
00259 OnlyAttsOps = false;
00260 if(Item->childCount()) {
00261 child = (UMLListViewItem*)Item->firstChild();
00262 while(child) {
00263 checkItemForCopyType(child, WithDiagrams, WithObjects, OnlyAttsOps);
00264 child = (UMLListViewItem*)child->nextSibling();
00265 }
00266 }
00267 }
00268 }
00269
00271 bool UMLClipboard::insertItemChildren(UMLListViewItem * Item, UMLListViewItemList& SelectedItems) {
00272 if(Item->childCount()) {
00273 UMLListViewItem * child = (UMLListViewItem*)Item->firstChild();
00274 int type;
00275 while(child) {
00276 m_ItemList.append(child);
00277 type = child->getType();
00278 if(type == Uml::lvt_Actor || type == Uml::lvt_UseCase || type == Uml::lvt_Class) {
00279 m_ObjectList.append(child->getUMLObject());
00280 }
00281
00282
00283 if(child->isSelected()) {
00284 SelectedItems.remove(SelectedItems.find(child) );
00285 }
00286 insertItemChildren(child, SelectedItems);
00287 child = (UMLListViewItem*)child->nextSibling();
00288 }
00289 }
00290 return true;
00291 }
00292
00293 bool UMLClipboard::pasteChildren(UMLListViewItem *parent, IDChangeLog *chgLog) {
00294 if (!parent) {
00295 kWarning() << "Paste Children Error, parent missing" << endl;
00296 return false;
00297 }
00298 UMLDoc *doc = UMLApp::app()->getDocument();
00299 UMLListView *listView = UMLApp::app()->getListView();
00300 UMLListViewItem *childItem = static_cast<UMLListViewItem*>(parent->firstChild());
00301 while (childItem) {
00302 Uml::IDType oldID = childItem->getID();
00303 Uml::IDType newID = chgLog->findNewID(oldID);
00304 UMLListViewItem *shouldNotExist = listView->findItem(newID);
00305 if (shouldNotExist) {
00306 kError() << "UMLClipboard::pasteChildren: new list view item " << ID2STR(newID)
00307 << " already exists (internal error)" << endl;
00308 childItem = static_cast<UMLListViewItem*>(childItem->nextSibling());
00309 continue;
00310 }
00311 UMLObject *newObj = doc->findObjectById(newID);
00312 if (newObj) {
00313 kDebug() << "UMLClipboard::pasteChildren: adjusting lvitem(" << ID2STR(oldID)
00314 << ") to new UMLObject(" << ID2STR(newID) << ")" << endl;
00315 childItem->setUMLObject(newObj);
00316 childItem->setText(newObj->getName());
00317 } else {
00318 kDebug() << "UMLClipboard::pasteChildren: no UMLObject found for lvitem "
00319 << ID2STR(newID) << endl;
00320 }
00321 childItem = static_cast<UMLListViewItem*>(childItem->nextSibling());
00322 }
00323 return true;
00324 }
00325
00328 void UMLClipboard::CleanAssociations(AssociationWidgetList& associations) {
00329 AssociationWidgetListIt it(associations);
00330 AssociationWidget* assoc = it.current();
00331
00332 while (assoc) {
00333 ++it;
00334 assoc = it.current();
00335 }
00336 }
00337
00340 bool UMLClipboard::pasteClip1(QMimeSource* data) {
00341 UMLObjectList objects;
00342 if (! UMLDrag::decodeClip1(data, objects)) {
00343 return false;
00344 }
00345 UMLListView *lv = UMLApp::app()->getListView();
00346 if ( !lv->startedCopy() )
00347 return true;
00348 lv->setStartedCopy(false);
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 return true;
00363 }
00364
00367 bool UMLClipboard::pasteClip2(QMimeSource* data) {
00368 UMLDoc *doc = UMLApp::app()->getDocument();
00369 UMLListViewItemList itemdatalist;
00370 UMLObjectList objects;
00371 objects.setAutoDelete(false);
00372 UMLViewList views;
00373 IDChangeLog* idchanges = 0;
00374
00375 bool result = UMLDrag::decodeClip2(data, objects, itemdatalist, views);
00376 if(!result) {
00377 return false;
00378 }
00379 UMLObject *obj = 0;
00380 UMLObjectListIt object_it(objects);
00381 idchanges = doc->getChangeLog();
00382 if(!idchanges) {
00383 return false;
00384 }
00385 while ( (obj=object_it.current()) != 0 ) {
00386 ++object_it;
00387 if(!doc->assignNewIDs(obj)) {
00388 kDebug()<<"UMLClipboard: error adding umlobject"<<endl;
00389 return false;
00390 }
00391 }
00392
00393 UMLView * pView = 0;
00394 UMLViewListIt view_it( views );
00395 while ( ( pView =view_it.current()) != 0 ) {
00396 ++view_it;
00397 if( !doc->addUMLView( pView ) ) {
00398 return false;
00399 }
00400 }
00401
00402 UMLListView *listView = UMLApp::app()->getListView();
00403 UMLListViewItem* item = 0;
00404 UMLListViewItem* itemdata = 0;
00405 UMLListViewItemListIt it(itemdatalist);
00406 while ( (itemdata=it.current()) != 0 ) {
00407 item = listView->createItem(*itemdata, *idchanges);
00408 if(!item) {
00409 return false;
00410 }
00411 if(itemdata -> childCount()) {
00412 if(!pasteChildren(item, idchanges)) {
00413 return false;
00414 }
00415 }
00416 ++it;
00417 }
00418
00419 return result;
00420 }
00421
00424 bool UMLClipboard::pasteClip3(QMimeSource* data) {
00425 UMLDoc *doc = UMLApp::app()->getDocument();
00426 UMLListViewItemList itemdatalist;
00427 UMLListViewItem* item = 0;
00428 UMLListViewItem* itemdata = 0;
00429 IDChangeLog* idchanges = doc->getChangeLog();
00430
00431 if(!idchanges) {
00432 return false;
00433 }
00434
00435 UMLListView *listView = UMLApp::app()->getListView();
00436 bool result = UMLDrag::decodeClip3(data, itemdatalist, listView);
00437 if(!result) {
00438 return false;
00439 }
00440 UMLListViewItemListIt it(itemdatalist);
00441 while ( (itemdata=it.current()) != 0 ) {
00442 item = listView->createItem(*itemdata, *idchanges);
00443 if(itemdata -> childCount()) {
00444 if(!pasteChildren(item, idchanges)) {
00445 return false;
00446 }
00447 }
00448 ++it;
00449 }
00450
00451 return result;
00452 }
00453
00456 bool UMLClipboard::pasteClip4(QMimeSource* data) {
00457 UMLDoc *doc = UMLApp::app()->getDocument();
00458
00459 UMLObjectList objects;
00460 objects.setAutoDelete(false);
00461
00462
00463 UMLWidgetList widgets;
00464 widgets.setAutoDelete(false);
00465
00466 AssociationWidgetList assocs;
00467 assocs.setAutoDelete(false);
00468
00469 IDChangeLog* idchanges = 0;
00470
00471 Uml::Diagram_Type diagramType;
00472
00473 if( !UMLDrag::decodeClip4(data, objects, widgets, assocs, diagramType) ) {
00474 return false;
00475 }
00476
00477 if( diagramType != UMLApp::app()->getCurrentView()->getType() ) {
00478 if( !checkPasteWidgets(widgets) ) {
00479 assocs.setAutoDelete(true);
00480 assocs.clear();
00481 return false;
00482 }
00483 }
00484 UMLObjectListIt object_it(objects);
00485 idchanges = doc->getChangeLog();
00486 if(!idchanges) {
00487 return false;
00488 }
00489
00490
00491 UMLObject* obj = 0;
00492 while ( (obj=object_it.current()) != 0 ) {
00493 ++object_it;
00494
00495 if(!doc->assignNewIDs(obj)) {
00496 return false;
00497 }
00498
00499 }
00500
00501
00502 bool objectAlreadyExists = false;
00503 UMLView *currentView = UMLApp::app()->getCurrentView();
00504 currentView->beginPartialWidgetPaste();
00505 UMLWidget* widget =0;
00506 UMLWidgetListIt widget_it(widgets);
00507 while ( (widget=widget_it.current()) != 0 ) {
00508 ++widget_it;
00509
00510 Uml::IDType oldId = widget->getID();
00511 Uml::IDType newId = idchanges->findNewID(oldId);
00512 if (currentView->findWidget(newId)) {
00513 kError() << "UMLClipboard::pasteClip4: widget (oldID=" << ID2STR(oldId)
00514 << ", newID=" << ID2STR(newId) << ") already exists in target view."
00515 << endl;
00516 widgets.remove(widget);
00517 delete widget;
00518 objectAlreadyExists = true;
00519 } else if (! currentView->addWidget(widget, true)) {
00520 currentView->endPartialWidgetPaste();
00521 return false;
00522 }
00523 }
00524
00525
00526 AssociationWidget* assoc;
00527 AssociationWidgetListIt assoc_it(assocs);
00528 while ( (assoc=assoc_it.current()) != 0 ) {
00529 ++assoc_it;
00530 if (!currentView->addAssociation(assoc, true)) {
00531 currentView->endPartialWidgetPaste();
00532 return false;
00533 }
00534 }
00535
00536
00537 currentView->activate();
00538 currentView->endPartialWidgetPaste();
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 if (objectAlreadyExists) {
00559 pasteItemAlreadyExists();
00560 }
00561 return true;
00562 }
00563
00566 bool UMLClipboard::pasteClip5(QMimeSource* data) {
00567 UMLDoc *doc = UMLApp::app()->getDocument();
00568 UMLListView *listView = UMLApp::app()->getListView();
00569 UMLListViewItem* lvitem = dynamic_cast<UMLListViewItem *>( listView->currentItem() );
00570 if (!lvitem ||
00571 (lvitem->getType() != Uml::lvt_Class && lvitem->getType() != Uml::lvt_Interface)) {
00572 return false;
00573 }
00574 UMLClassifier *parent = dynamic_cast<UMLClassifier *>(lvitem->getUMLObject());
00575 if (parent == NULL) {
00576 kError() << "UMLClipboard::pasteClip5: parent is not a UMLClassifier"
00577 << endl;
00578 return false;
00579 }
00580
00581 UMLObjectList objects;
00582 objects.setAutoDelete(false);
00583 IDChangeLog* idchanges = 0;
00584 bool result = UMLDrag::decodeClip5(data, objects, parent);
00585
00586 if(!result) {
00587 return false;
00588 }
00589
00590 UMLObject *obj = 0;
00591 doc->setModified(true);
00592 idchanges = doc->getChangeLog();
00593
00594 if (objects.count())
00595 result = false;
00596
00597 for (UMLObjectListIt it(objects); (obj = it.current()) != NULL; ++it) {
00598 obj->setID(doc->assignNewID(obj->getID()));
00599 switch(obj->getBaseType()) {
00600 case Uml::ot_Attribute :
00601 {
00602 UMLObject *exist = parent->findChildObject(obj->getName(), Uml::ot_Attribute);
00603 if (exist) {
00604 QString newName = parent->uniqChildName(Uml::ot_Attribute, obj->getName());
00605 obj->setName(newName);
00606 }
00607 UMLAttribute *att = static_cast<UMLAttribute*>(obj);
00608 if (parent->addAttribute(att, idchanges)) {
00609 result = true;
00610 } else {
00611 kError() << "UMLClipboard::pasteClip5: " << parent->getName()
00612 << "->addAttribute(" << att->getName() << ") failed" << endl;
00613 }
00614 break;
00615 }
00616 case Uml::ot_Operation :
00617 {
00618 UMLOperation *op = static_cast<UMLOperation*>(obj);
00619 UMLOperation *exist = parent->checkOperationSignature(op->getName(), op->getParmList());
00620 if (exist) {
00621 QString newName = parent->uniqChildName(Uml::ot_Operation, obj->getName());
00622 op->setName(newName);
00623 }
00624 if (parent->addOperation(op, idchanges)) {
00625 result = true;
00626 } else {
00627 kError() << "UMLClipboard::pasteClip5: " << parent->getName()
00628 << "->addOperation(" << op->getName() << ") failed" << endl;
00629 }
00630 break;
00631 }
00632 default :
00633 kWarning() << "pasting unknown children type in clip type 5" << endl;
00634 return false;
00635 }
00636 }
00637
00638 return result;
00639 }
00640
00641 bool UMLClipboard::insertItemChildren( UMLListViewItem * item ) {
00642 if( item -> childCount() ) {
00643 UMLListViewItem * child =dynamic_cast<UMLListViewItem *>( item -> firstChild() );
00644 while( child ) {
00645 m_ItemList.append( child );
00646 insertItemChildren( child );
00647 child = dynamic_cast<UMLListViewItem *>( child->nextSibling() );
00648 }
00649 }
00650 return true;
00651 }
00652
00653 bool UMLClipboard::checkPasteWidgets( UMLWidgetList & widgetList ) {
00654 bool retval = true;
00655 UMLWidget * p = 0;
00656 UMLWidgetListIt it( widgetList );
00657 while ( ( p = it.current()) != 0 ) {
00658 ++it;
00659 switch( p -> getBaseType() ) {
00660 case Uml::wt_Note:
00661 break;
00662
00663 case Uml::wt_Text:
00664 {
00665 FloatingTextWidget *ft = static_cast<FloatingTextWidget*>(p);
00666 if (ft->getRole() != Uml::tr_Floating) {
00667 widgetList.remove(p);
00668 delete ft;
00669 retval = false;
00670 }
00671 }
00672 break;
00673
00674 default:
00675 widgetList.remove(p);
00676 delete p;
00677 retval = false;
00678 break;
00679 }
00680 }
00681 return retval;
00682 }
00683
00684 void UMLClipboard::pasteItemAlreadyExists() {
00685 UMLView *currentView = UMLApp::app()->getCurrentView();
00686 KMessageBox::sorry( currentView,
00687 i18n("At least one of the items in the clipboard "
00688 "could not be pasted because an item of the "
00689 "same name already exists. Any other items "
00690 "have been pasted."),
00691 i18n("Paste Error") );
00692 }
00693