![]() |
TinkerCell Core 1.0
TinkerCell's Core library providing all basic functionalities
|
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 }