TinkerCell Core 1.0
TinkerCell's Core library providing all basic functionalities
CloneItems.cpp
Go to the documentation of this file.
00001 #include <QHash>
00002 #include "NodeGraphicsItem.h"
00003 #include "ConnectionGraphicsItem.h"
00004 #include "TextGraphicsItem.h"
00005 #include "ItemHandle.h"
00006 #include "UndoCommands.h"
00007 #include "MainWindow.h"
00008 #include "Tool.h"
00009 #include "CloneItems.h"
00010 
00011 namespace Tinkercell
00012 {
00013         /*
00014         * \param a pointer to a QGraphicsItem
00015         * \return a QGraphicsItem that is either a NodeGraphicsItem, ConnectionGraphicsItem, ControlPoint, or TextGraphicsItem
00016         */
00017         QGraphicsItem * getGraphicsItem( QGraphicsItem * item )
00018         {
00019                 NodeGraphicsItem * node = 0;
00020                 ConnectionGraphicsItem * connection = 0;
00021                 ControlPoint * controlPoint = 0;
00022                 TextGraphicsItem * text = 0;
00023 
00024                 QGraphicsItem * p = item;
00025 
00026                 while (p/* && !MainWindow::invalidPointers.contains((void*)p)*/)
00027                 {
00028                         text = TextGraphicsItem::cast(p);
00029                         if (text)
00030                         {
00031                                 if (!ToolGraphicsItem::cast(text->topLevelItem()))
00032                                         return (QGraphicsItem*)(text);
00033                         }
00034 
00035                         connection = ConnectionGraphicsItem::cast(p);
00036                         if (connection)
00037                         {
00038                                 if (!ToolGraphicsItem::cast(connection->topLevelItem()))
00039                                         return (QGraphicsItem*)connection;
00040                         }
00041 
00042                         node = NodeGraphicsItem::cast(p);
00043                         if (node)
00044                         {
00045                                 if (!ToolGraphicsItem::cast(node->topLevelItem()))
00046                                         return (QGraphicsItem*)node;
00047                         }
00048 
00049                         controlPoint = qgraphicsitem_cast<ControlPoint*>(p);
00050                         if (controlPoint == 0) controlPoint = qgraphicsitem_cast<ConnectionGraphicsItem::ControlPoint*>(p);
00051                         if (controlPoint == 0) controlPoint = qgraphicsitem_cast<NodeGraphicsItem::ControlPoint*>(p);
00052                         if (controlPoint)
00053                         {
00054                                 if (!ToolGraphicsItem::cast(controlPoint->topLevelItem()))
00055                                         return (QGraphicsItem*)controlPoint;
00056                         }
00057 
00058                         p = p->parentItem();
00059                 }
00060 
00061                 return (0);
00062         }
00063 
00064         /* Clone a graphics item
00065         * \param a pointer to a QGraphicsItem
00066         * \return a QGraphicsItem that is one of the Tinkercell Graphics Items
00067         */
00068         QGraphicsItem * cloneGraphicsItem( QGraphicsItem * item )
00069         {
00070                 ArrowHeadItem* arrow = 0;
00071                 NodeGraphicsItem * node = 0;
00072                 ConnectionGraphicsItem * connection = 0;
00073                 ControlPoint * controlPoint0 = 0;
00074                 ConnectionGraphicsItem::ControlPoint * controlPoint1 = 0;
00075                 NodeGraphicsItem::ControlPoint * controlPoint2 = 0;
00076                 TextGraphicsItem * text = 0;
00077 
00078                 QGraphicsItem * p = item;
00079 
00080                 while (p && (ToolGraphicsItem::cast(p->topLevelItem()) == 0))
00081                 {
00082                         text = TextGraphicsItem::cast(p);
00083                         if (text) return (QGraphicsItem*)(text->clone());
00084 
00085                         connection = ConnectionGraphicsItem::cast(p);
00086                         if (connection) return (QGraphicsItem*)(connection->clone());
00087                         
00088                         arrow = ArrowHeadItem::cast(p);
00089                         if (arrow) return (QGraphicsItem*)(arrow->clone());
00090 
00091                         node = NodeGraphicsItem::cast(p);
00092                         if (node) return (QGraphicsItem*)(node->clone());
00093 
00094                         controlPoint0 = qgraphicsitem_cast<ControlPoint*>(p);
00095                         if (controlPoint0)
00096                                 return (QGraphicsItem*)(controlPoint0->clone());
00097 
00098                         controlPoint1 = qgraphicsitem_cast<ConnectionGraphicsItem::ControlPoint*>(p);
00099                         if (controlPoint1)
00100                                 return (QGraphicsItem*)(controlPoint1->clone());
00101 
00102                         controlPoint2 = qgraphicsitem_cast<NodeGraphicsItem::ControlPoint*>(p);
00103                         if (controlPoint2)
00104                                 return (QGraphicsItem*)(controlPoint2->clone());
00105 
00106                         if (p != p->parentItem())
00107                                 p = p->parentItem();
00108                         else
00109                                 p = 0;
00110                 }
00111 
00112                 return (0);
00113         }
00114 
00115         QList<QGraphicsItem*> cloneGraphicsItems( QList<QGraphicsItem*>& items0, QList<ItemHandle*>& allNewHandles, bool deep)
00116         {
00117                 QList<QGraphicsItem*> duplicateItems;
00118                 QList< QPair<ItemHandle*,ItemHandle*> > originalAndCloneHandles;
00119 
00120                 //for connections
00121                 QList< QPair<NodeGraphicsItem*,NodeGraphicsItem*> > originalsAndClones;
00122                 QList< ConnectionGraphicsItem* > connectionItems;
00123                 NodeGraphicsItem *node1 = 0, *node2 = 0;
00124                 ConnectionGraphicsItem* connection = 0;
00125                 QList<ArrowHeadItem*> arrowHeads;
00126 
00127                 //for copying handles
00128                 ItemHandle * handle, *cloneHandle, *cloneChildHandle;
00129                 QList<ItemHandle*> oldHandles;
00130                 QList<ItemHandle*> childHandles;
00131                 allNewHandles.clear();
00132 
00133                 //copy connected nodes
00134                 QList<NodeGraphicsItem*> connectedNodes;
00135                 QList<QGraphicsItem*> items, visited;
00136                 
00137                 //copy child items
00138                 for (int i=0; i < items0.size(); ++i)
00139             if (items0[i] && !items.contains(items0[i]))
00140             {
00141                 items << items0[i];
00142                         
00143                 if (connection = ConnectionGraphicsItem::cast(items0[i]))
00144                         {
00145                                 connectedNodes = connection->nodes();
00146                                 for (int j=0; j < connectedNodes.size(); ++j)
00147                                         if (!items0.contains(connectedNodes[j]))
00148                                         {
00149                                                 if (ArrowHeadItem::cast(connectedNodes[j]))
00150                                                 {
00151                                                         if (static_cast<ArrowHeadItem*>(connectedNodes[j])->connectionItem &&
00152                                                                 !items0.contains(static_cast<ArrowHeadItem*>(connectedNodes[j])->connectionItem))
00153                                                                 items0 += static_cast<ArrowHeadItem*>(connectedNodes[j])->connectionItem;
00154                                                         }
00155                                                         else
00156                                                         items0 += connectedNodes[j];
00157                                         }
00158                         }
00159 
00160                 if (handle = getHandle(items0[i]))
00161                 {
00162                     QList<QGraphicsItem*> list = handle->allGraphicsItems();
00163                     for (int j=0; j < list.size(); ++j)
00164                         if (!items.contains(list[j]))
00165                         {
00166                             items << list[j];
00167                             if (list[j]->scene() && (list[j]->scene() == items0[i]->scene()))
00168                                 items0 << list[j];
00169                         }
00170                 }
00171             }
00172 
00173         //top level handles
00174                 for (int i=0; i < items.size(); ++i)
00175             if (!visited.contains(items[i]) && 
00176                 !ArrowHeadItem::cast(items[i]) &&
00177                 !ControlPoint::cast(items[i]))
00178             {
00179                 visited << items[i];
00180                 handle = getHandle(items[i]);
00181                 
00182                 QGraphicsItem * itemClone = cloneGraphicsItem(items[i]);
00183 
00184                 if (itemClone)
00185                 {
00186                     setHandle(itemClone,0);
00187                    if (items0.contains(items[i]))
00188                    {
00189                             duplicateItems << itemClone;
00190                        }
00191 
00192                     if ((connection = ConnectionGraphicsItem::cast(itemClone)))
00193                     {
00194                         connectionItems += connection;
00195                         if (connection->centerRegionItem)
00196                         {
00197                                 node2 = connection->centerRegionItem;
00198                                 connection = ConnectionGraphicsItem::cast(items[i]);
00199                             if (connection && node2)
00200                             {
00201                                 node1 = connection->centerRegionItem;
00202                                 if (node1 && node2)
00203                                 {
00204                                     originalsAndClones += QPair<NodeGraphicsItem*,NodeGraphicsItem*>(node1,node2);
00205                                     if (items0.contains(node1))
00206                                             duplicateItems << node2;
00207                                 }
00208                             }
00209                         }
00210                     }
00211                     else
00212                         if ((node1 = NodeGraphicsItem::cast(items[i]))
00213                             && (node2 = NodeGraphicsItem::cast(itemClone)))
00214                         {
00215                             originalsAndClones += QPair<NodeGraphicsItem*,NodeGraphicsItem*>(node1,node2);
00216                         }
00217 
00218                     if (handle)
00219                     {
00220                         cloneHandle = 0;
00221                                                 
00222                                                 if (deep)
00223                                                 {
00224                                                         for (int j=0; j < originalAndCloneHandles.size(); ++j)
00225                                                                 if (originalAndCloneHandles[j].first == handle)
00226                                                                 {
00227                                                                         cloneHandle = originalAndCloneHandles[j].second;
00228                                                                         break;
00229                                                                 }
00230 
00231                                                         if (!cloneHandle)
00232                                                         {
00233                                                                 cloneHandle = handle->clone();
00234                                                                 
00235                                                                 cloneHandle->setParent(0,false);
00236                                                                 cloneHandle->children.clear();
00237                                                                 cloneHandle->graphicsItems.clear();
00238                                                                 allNewHandles << cloneHandle;
00239                                                                 originalAndCloneHandles << QPair<ItemHandle*,ItemHandle*>(handle,cloneHandle);
00240                                                                 
00241                                                                 childHandles = handle->children;
00242                                                                 for (int j=0; j < childHandles.size(); ++j)
00243                                                                         if ((handle = childHandles[j]) && handle->graphicsItems.isEmpty())
00244                                                                         {
00245                                                                                 cloneChildHandle = handle->clone();
00246                                                                                 cloneChildHandle->setParent(0,false);
00247                                                                                 cloneChildHandle->children.clear();
00248                                                                                 cloneChildHandle->graphicsItems.clear();
00249                                                                                 
00250                                                                                 for (int k=0; k < handle->children.size(); ++k)
00251                                                                                         if (!childHandles.contains(handle->children[k]))
00252                                                                                                 childHandles << handle->children[k];
00253                                                                                 
00254                                                                                 allNewHandles << cloneChildHandle;
00255                                                                                 originalAndCloneHandles << QPair<ItemHandle*,ItemHandle*>(handle,cloneChildHandle);
00256                                                                         }
00257 
00258                                                         }
00259                                                 }
00260                                                 else
00261                                                         cloneHandle = handle;
00262 
00263                         setHandle(itemClone,cloneHandle);
00264                     }
00265                 }
00266            }
00267 
00268                 for (int i=0; i < connectionItems.size(); ++i)
00269                 {
00270                         QList<NodeGraphicsItem*> nodes = connectionItems[i]->nodes();
00271                         for (int k=0; k < originalsAndClones.size(); ++k)
00272                         {
00273                                 if (nodes.contains(originalsAndClones[k].first) && originalsAndClones[k].first && originalsAndClones[k].second)
00274                                 {
00275                                         connectionItems[i]->replaceNode(originalsAndClones[k].first,originalsAndClones[k].second);
00276                                 }
00277                         }
00278                 }
00279 
00280                 //replace parent handles
00281                 bool parentCopied = false;
00282                 for (int i=0; i < originalAndCloneHandles.size(); ++i)
00283                 {
00284                         if (originalAndCloneHandles[i].first->parent != 0)
00285                         {
00286                                 parentCopied = false;
00287                                 for (int j=0; j < originalAndCloneHandles.size(); ++j)
00288                                 {
00289                                         if (originalAndCloneHandles[i].first->parent == originalAndCloneHandles[j].first)
00290                                         {
00291                                                 originalAndCloneHandles[i].second->setParent(originalAndCloneHandles[j].second,false);
00292                                                 parentCopied = true;
00293                                                 break;
00294                                         }
00295                                 }
00296                                 if (!parentCopied)
00297                                 {
00298                                         QString oldName = originalAndCloneHandles[i].first->fullName();
00299                                         QString newName = originalAndCloneHandles[i].second->fullName();
00300                                         RenameCommand::findReplaceAllHandleData(allNewHandles,oldName,newName);
00301                                 }
00302                         }
00303                 }
00304 
00305                 return duplicateItems;
00306         }
00307         
00308         QList<ItemHandle*> cloneHandles(const QList<ItemHandle*>& oldHandles)
00309         {
00310                 QList<ItemHandle*> newHandles;
00311                 QHash<ItemHandle*,ItemHandle*> hash;
00312 
00313                 ItemHandle * handle = 0, * handle2 = 0;
00314                 ConnectionHandle * connection = 0, * connection2 = 0;
00315                 for (int i=0; i < oldHandles.size(); ++i)
00316                         if ((handle = oldHandles[i]) && !hash.contains(handle))
00317                         {
00318                                 handle2 = handle->clone();
00319                                 newHandles << handle2;
00320                                 handle2->setParent(0,false);
00321                                 handle2->children.clear();
00322                                 handle2->graphicsItems.clear();
00323                                 hash[handle] = handle2;
00324                         }
00325 
00326                 NodeHandle * node;
00327                 for (int i=0; i < oldHandles.size(); ++i)
00328                 {
00329                         handle = oldHandles[i];
00330                         if (handle && (handle2 = hash[handle]))
00331                         {
00332                                 if (handle && handle->parent && hash.contains(handle->parent))
00333                                 {
00334                                         handle2->setParent( hash[ handle->parent ],false );
00335                                 }
00336                         
00337                                 if (handle &&
00338                                         (connection = ConnectionHandle::cast(handle)) && 
00339                                         (connection2 = ConnectionHandle::cast(handle2)))
00340                                 {
00341                                         connection2->nodesWithRoles.clear();
00342                                         for (int j=0; j < connection->nodesWithRoles.size(); ++j)
00343                                                 if (hash.contains(connection->nodesWithRoles[j].first) &&
00344                                                         (node = NodeHandle::cast(hash[connection->nodesWithRoles[j].first])))
00345                                                 {
00346                                                         connection2->addNode(node,connection->nodesWithRoles[j].second);
00347                                                 }
00348                                 }
00349                         }
00350                 }
00351                 return newHandles;
00352         }
00353 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines