![]() |
TinkerCell Core 1.0
TinkerCell's Core library providing all basic functionalities
|
00001 /**************************************************************************** 00002 Copyright (c) 2008 Deepak Chandran 00003 Contact: Deepak Chandran (dchandran1@gmail.com) 00004 See COPYRIGHT.TXT 00005 00006 This is the source file for the connection graphics item, which is a Qt graphics path item 00007 that draws a connection between two or more nodes. 00008 00009 The connection graphics items defines a new control point item inside itself. 00010 00011 This header file also contains the arrow head item class. The arrow head item inherits from 00012 node graphics item and is used to draw the arrow heads at the end of the connection items. 00013 00014 ****************************************************************************/ 00015 #include <math.h> 00016 #include <QPainterPathStroker> 00017 #include "GraphicsScene.h" 00018 #include "MainWindow.h" 00019 #include "ConnectionGraphicsItem.h" 00020 #include "ItemHandle.h" 00021 #include "fileIO/NodeGraphicsReader.h" 00022 #include "UndoCommands.h" 00023 #include "TextGraphicsItem.h" 00024 #include "Tool.h" 00025 00026 namespace Tinkercell 00027 { 00028 const QString ArrowHeadItem::CLASSNAME = QString("ArrowHeadItem"); 00029 const QString ConnectionGraphicsItem::CLASSNAME = QString("ConnectionGraphicsItem"); 00030 QString ConnectionGraphicsItem::DefaultMiddleItemFile(":/images/defaultarrow.xml"); 00031 QString ConnectionGraphicsItem::DefaultArrowHeadFile(":/images/defaultarrow.xml"); 00032 00033 ItemHandle * ConnectionGraphicsItem::handle() const 00034 { 00035 return itemHandle; 00036 } 00037 00038 void ConnectionGraphicsItem::setHandle(ItemHandle * handle) 00039 { 00040 if (handle != 0 && !handle->graphicsItems.contains(this)) 00041 { 00042 handle->graphicsItems += this; 00043 } 00044 00045 if (itemHandle) 00046 { 00047 if (itemHandle != handle) 00048 { 00049 itemHandle->graphicsItems.removeAll(this); 00050 itemHandle = handle; 00051 } 00052 } 00053 else 00054 { 00055 itemHandle = handle; 00056 } 00057 } 00058 00059 ItemHandle * ConnectionGraphicsItem::ControlPoint::handle() const 00060 { 00061 /*if (connectionItem) 00062 return connectionItem->handle();*/ 00063 return 0; 00064 } 00065 00066 void ConnectionGraphicsItem::ControlPoint::setHandle(ItemHandle * h) 00067 { 00068 if (connectionItem) 00069 connectionItem->setHandle(h); 00070 } 00071 00072 00073 ControlPoint * ControlPoint::cast(QGraphicsItem* item) 00074 { 00075 //if (MainWindow::invalidPointers.contains( (void*)item )) return 0; 00076 if (!item || ToolGraphicsItem::cast(item->topLevelItem())) return 0; 00077 00078 ControlPoint * idptr = 0; 00079 00080 QGraphicsItem * p = item; 00081 00082 while (p) 00083 { 00084 idptr = qgraphicsitem_cast<ControlPoint*>(p); 00085 if (idptr != 0) return idptr; 00086 00087 idptr = (ControlPoint*)qgraphicsitem_cast<NodeGraphicsItem::ControlPoint*>(p); 00088 if (idptr != 0) return idptr; 00089 00090 idptr = (ControlPoint*)qgraphicsitem_cast<ConnectionGraphicsItem::ControlPoint*>(p); 00091 if (idptr != 0) return idptr; 00092 00093 if (p != p->parentItem()) 00094 p = p->parentItem(); 00095 else 00096 break; 00097 } 00098 00099 return 0; 00100 } 00101 00102 QList<ControlPoint*> ControlPoint::cast(const QList<QGraphicsItem*>& items) 00103 { 00104 QList<ControlPoint*> items2; 00105 ControlPoint * cp = 0; 00106 for (int i=0; i < items.size(); ++i) 00107 if ((cp = ControlPoint::cast(items[i])) && !items2.contains(cp)) 00108 items2 << cp; 00109 return items2; 00110 } 00111 00113 ArrowHeadItem::ArrowHeadItem(ConnectionGraphicsItem* connection) : NodeGraphicsItem() 00114 { 00115 className = ArrowHeadItem::CLASSNAME; 00116 connectionItem = connection; 00117 angle = 0.0; 00118 } 00119 00121 ArrowHeadItem::ArrowHeadItem(const QString& filename, ConnectionGraphicsItem* connection) : NodeGraphicsItem(filename) 00122 { 00123 className = ArrowHeadItem::CLASSNAME; 00124 connectionItem = connection; 00125 angle = 0.0; 00126 } 00127 00129 ArrowHeadItem::ArrowHeadItem(const ArrowHeadItem& copy) : NodeGraphicsItem(copy) 00130 { 00131 connectionItem = copy.connectionItem; 00132 angle = copy.angle; 00133 } 00134 00136 NodeGraphicsItem* ArrowHeadItem::clone() const 00137 { 00138 return new ArrowHeadItem(*this); 00139 } 00140 00141 ArrowHeadItem* ArrowHeadItem::cast(QGraphicsItem * q) 00142 { 00143 //if (MainWindow::invalidPointers.contains( (void*)q )) return 0; 00144 if (!q || ToolGraphicsItem::cast(q->topLevelItem())) return 0; 00145 return qgraphicsitem_cast<ArrowHeadItem*>(q); 00146 } 00147 00148 00150 ConnectionGraphicsItem::ConnectionGraphicsItem(QGraphicsItem * parent) : QGraphicsItemGroup (parent), itemHandle(0) 00151 { 00152 setCacheMode(QGraphicsItem::DeviceCoordinateCache); 00153 setFlag(QGraphicsItem::ItemIsMovable, false); 00154 setFlag(QGraphicsItem::ItemIsSelectable, false); 00155 00156 className = ConnectionGraphicsItem::CLASSNAME; 00157 lineType = bezier; 00158 arrowHeadDistance = 10.0; 00159 centerRegionItem = 0; 00160 centerRegion = QSizeF(20,20); 00161 defaultPen = QPen(QColor(50,50,255,255),5.0); 00162 defaultPen.setJoinStyle(Qt::RoundJoin); 00163 00164 boundaryPathItem = new QGraphicsPathItem(this); 00165 boundaryPathItem->setVisible(false); 00166 boundaryPathItem->setPen(QPen(QColor(255,150,150,150),4.0,Qt::DotLine)); 00167 boundaryPathItem->setBrush(Qt::NoBrush); 00168 00169 outerPathItem = new QGraphicsPathItem(this); 00170 outerPathItem->setVisible(true); 00171 outerPathItem->setPen(QPen(GraphicsScene::BackgroundColor,6.0,Qt::SolidLine)); 00172 outerPathItem->setBrush(Qt::NoBrush); 00173 00174 mainPathItem = new QGraphicsPathItem(this); 00175 mainPathItem->setVisible(true); 00176 mainPathItem->setPen(defaultPen); 00177 mainPathItem->setBrush(Qt::NoBrush); 00178 00179 /*ArrowHeadItem * node = new ArrowHeadItem; 00180 node->connectionItem = this; 00181 NodeGraphicsReader imageReader; 00182 imageReader.readXml(node,DefaultMiddleItemFile); 00183 if (node->isValid()) 00184 { 00185 node->normalize(); 00186 node->scale(25.0/node->sceneBoundingRect().height(),25.0/node->sceneBoundingRect().height()); 00187 }*/ 00188 centerRegionItem = 0; 00189 } 00190 00192 ConnectionGraphicsItem::ConnectionGraphicsItem(const ConnectionGraphicsItem& copy) : QGraphicsItemGroup () 00193 { 00194 setFlag(QGraphicsItem::ItemIsMovable, false); 00195 setFlag(QGraphicsItem::ItemIsSelectable, false); 00196 setVisible(copy.isVisible()); 00197 00198 className = copy.className; 00199 groupID = copy.groupID; 00200 centerRegionItem = 0; 00201 00202 defaultPen = copy.defaultPen; 00203 00204 boundaryPathItem = new QGraphicsPathItem(this); 00205 boundaryPathItem->setVisible(false); 00206 boundaryPathItem->setPen(QPen(QColor(255,150,150,150),4.0,Qt::DotLine)); 00207 boundaryPathItem->setBrush(Qt::NoBrush); 00208 00209 outerPathItem = new QGraphicsPathItem(this); 00210 outerPathItem->setVisible(true); 00211 outerPathItem->setPen(QPen(GraphicsScene::BackgroundColor,6.0,Qt::SolidLine)); 00212 outerPathItem->setBrush(Qt::NoBrush); 00213 00214 mainPathItem = new QGraphicsPathItem(this); 00215 mainPathItem->setVisible(true); 00216 mainPathItem->setPen(defaultPen); 00217 mainPathItem->setBrush(Qt::NoBrush); 00218 00219 if (copy.centerRegionItem) 00220 { 00221 centerRegionItem = new ArrowHeadItem(*copy.centerRegionItem); 00222 centerRegionItem->connectionItem = this; 00223 } 00224 00225 centerRegion = copy.centerRegion; 00226 00227 itemHandle = copy.itemHandle; 00228 00229 if (itemHandle) 00230 setHandle(itemHandle); 00231 00232 curveSegments = copy.curveSegments; 00233 lineType = copy.lineType; 00234 arrowHeadDistance = copy.arrowHeadDistance; 00235 setPos(copy.scenePos()); 00236 setTransform(copy.sceneTransform()); 00237 00238 for (int i=0; i < copy.curveSegments.size(); ++i) 00239 { 00240 if (copy.curveSegments[i].arrowStart) 00241 { 00242 curveSegments[i].arrowStart = new ArrowHeadItem(*copy.curveSegments[i].arrowStart); 00243 curveSegments[i].arrowStart->connectionItem = this; 00244 } 00245 if (copy.curveSegments[i].arrowEnd) 00246 { 00247 curveSegments[i].arrowEnd = new ArrowHeadItem(*copy.curveSegments[i].arrowEnd); 00248 curveSegments[i].arrowEnd->connectionItem = this; 00249 } 00250 } 00251 00252 QList<ConnectionGraphicsItem::ControlPoint*> uniquePoints; 00253 QList<QPoint> locations, positions; 00254 00255 for (int i=0; i < copy.curveSegments.size(); ++i) 00256 for (int j=0; j < copy.curveSegments[i].size(); ++j) 00257 { 00258 positions += QPoint(i,j); 00259 00260 int k = uniquePoints.indexOf(copy.curveSegments[i][j]); 00261 if (k > -1) 00262 { 00263 locations += locations[k]; 00264 uniquePoints += 0; 00265 } 00266 else 00267 { 00268 locations += QPoint(i,j); 00269 uniquePoints += (copy.curveSegments[i][j]); 00270 } 00271 } 00272 00273 NodeGraphicsItem * parentNode = 0; 00274 for (int k=0; k < uniquePoints.size() && k < locations.size() && k < positions.size(); ++k) 00275 { 00276 int i = positions[k].x(), 00277 j = positions[k].y(); 00278 if (copy.curveSegments[i][j]) 00279 { 00280 if (uniquePoints[k]) 00281 { 00282 curveSegments[i][j] = new ConnectionGraphicsItem::ControlPoint(*copy.curveSegments[i][j]); 00283 curveSegments[i][j]->connectionItem = this; 00284 curveSegments[i][j]->setVisible(false); 00285 00286 if (copy.curveSegments[i][j]->parentItem()) 00287 { 00288 parentNode = NodeGraphicsItem::cast(copy.curveSegments[i][j]->parentItem()); 00289 if (parentNode == copy.curveSegments[i].arrowEnd) 00290 curveSegments[i][j]->setParentItem(curveSegments[i].arrowEnd); 00291 else 00292 if (parentNode == copy.curveSegments[i].arrowStart) 00293 curveSegments[i][j]->setParentItem(curveSegments[i].arrowStart); 00294 else 00295 curveSegments[i][j]->setParentItem(copy.curveSegments[i][j]->parentItem()); 00296 00297 } 00298 } 00299 else 00300 { 00301 curveSegments[i][j] = curveSegments[locations[k].x()][locations[k].y()]; 00302 } 00303 } 00304 } 00305 } 00306 00308 ConnectionGraphicsItem* ConnectionGraphicsItem::clone() const 00309 { 00310 ConnectionGraphicsItem * c = new ConnectionGraphicsItem(*this); 00311 //c->className = ConnectionGraphicsItem::CLASSNAME; 00312 return c; 00313 } 00314 00316 ConnectionGraphicsItem& ConnectionGraphicsItem::operator = (const ConnectionGraphicsItem& copy) 00317 { 00318 clear(true); 00319 00320 if (copy.centerRegionItem) 00321 { 00322 QList<QGraphicsItem*> children; 00323 if (centerRegionItem) 00324 children = centerRegionItem->childItems(); 00325 centerRegionItem = new ArrowHeadItem(*copy.centerRegionItem); 00326 centerRegionItem->connectionItem = this; 00327 for (int i=0; i < children.size(); ++i) 00328 if (ControlPoint::cast(children[i])) 00329 { 00330 children[i]->setParentItem(centerRegionItem); 00331 } 00332 } 00333 else 00334 { 00335 centerRegionItem = 0; 00336 } 00337 centerRegion = copy.centerRegion; 00338 00339 itemHandle = copy.itemHandle; 00340 00341 if (itemHandle) 00342 setHandle(itemHandle); 00343 00344 curveSegments = copy.curveSegments; 00345 lineType = copy.lineType; 00346 arrowHeadDistance = copy.arrowHeadDistance; 00347 if (mainPathItem && outerPathItem) 00348 { 00349 mainPathItem->setPen(defaultPen = copy.defaultPen); 00350 outerPathItem->setPen( QPen(QBrush(defaultPen.color()), defaultPen.widthF() + 1.0 ) ); 00351 } 00352 00353 setPos(copy.scenePos()); 00354 setTransform(copy.sceneTransform()); 00355 00356 for (int i=0; i < copy.curveSegments.size(); ++i) 00357 { 00358 if (copy.curveSegments[i].arrowStart) 00359 { 00360 curveSegments[i].arrowStart = new ArrowHeadItem(*copy.curveSegments[i].arrowStart); 00361 curveSegments[i].arrowStart->connectionItem = this; 00362 } 00363 if (copy.curveSegments[i].arrowEnd) 00364 { 00365 curveSegments[i].arrowEnd = new ArrowHeadItem(*copy.curveSegments[i].arrowEnd); 00366 curveSegments[i].arrowEnd->connectionItem = this; 00367 } 00368 } 00369 00370 QList<ConnectionGraphicsItem::ControlPoint*> uniquePoints; 00371 QList<QPoint> locations, positions; 00372 00373 for (int i=0; i < copy.curveSegments.size(); ++i) 00374 for (int j=0; j < copy.curveSegments[i].size(); ++j) 00375 { 00376 positions += QPoint(i,j); 00377 00378 int k = uniquePoints.indexOf(copy.curveSegments[i][j]); 00379 if (k > -1) 00380 { 00381 locations += locations[k]; 00382 uniquePoints += 0; 00383 } 00384 else 00385 { 00386 locations += QPoint(i,j); 00387 uniquePoints += (copy.curveSegments[i][j]); 00388 } 00389 } 00390 00391 NodeGraphicsItem * parentNode = 0; 00392 for (int k=0; k < uniquePoints.size() && k < locations.size() && k < positions.size(); ++k) 00393 { 00394 int i = positions[k].x(), 00395 j = positions[k].y(); 00396 if (copy.curveSegments[i][j]) 00397 { 00398 if (uniquePoints[k]) 00399 { 00400 curveSegments[i][j] = new ConnectionGraphicsItem::ControlPoint(*copy.curveSegments[i][j]); 00401 curveSegments[i][j]->connectionItem = this; 00402 curveSegments[i][j]->setVisible(false); 00403 00404 if (copy.curveSegments[i][j]->parentItem()) 00405 { 00406 parentNode = NodeGraphicsItem::cast(copy.curveSegments[i][j]->parentItem()); 00407 if (parentNode == copy.curveSegments[i].arrowEnd) 00408 curveSegments[i][j]->setParentItem(curveSegments[i].arrowEnd); 00409 else 00410 if (parentNode == copy.curveSegments[i].arrowStart) 00411 curveSegments[i][j]->setParentItem(curveSegments[i].arrowStart); 00412 else 00413 curveSegments[i][j]->setParentItem(copy.curveSegments[i][j]->parentItem()); 00414 00415 } 00416 } 00417 else 00418 { 00419 curveSegments[i][j] = curveSegments[locations[k].x()][locations[k].y()]; 00420 } 00421 } 00422 } 00423 return *this; 00424 } 00425 00426 QPen ConnectionGraphicsItem::pen() const 00427 { 00428 if (mainPathItem) 00429 return mainPathItem->pen(); 00430 else 00431 return QPen(); 00432 } 00433 00434 void ConnectionGraphicsItem::setPen(QPen pen, bool permanent) 00435 { 00436 if (permanent) 00437 defaultPen = pen; 00438 if (mainPathItem) 00439 mainPathItem->setPen(pen); 00440 } 00441 00442 void ConnectionGraphicsItem::setPath(const QPainterPath& path) 00443 { 00444 if (mainPathItem && outerPathItem) 00445 { 00446 QPen pen = mainPathItem->pen(); 00447 00448 if (pen.style() == Qt::SolidLine) 00449 { 00450 mainPathItem->setPath(this->pathShape); 00451 outerPathItem->setPath(this->pathShape); 00452 } 00453 else 00454 { 00455 mainPathItem->setPath(path); 00456 outerPathItem->setPath(path); 00457 } 00458 00459 outerPathItem->setPen( QPen( QBrush(GraphicsScene::BackgroundColor), pen.widthF() + 2.0 )); 00460 } 00461 } 00462 00464 ConnectionGraphicsItem& ConnectionGraphicsItem::copyPoints (const ConnectionGraphicsItem& copy) 00465 { 00466 clear(); 00467 00468 lineType = copy.lineType; 00469 arrowHeadDistance = copy.arrowHeadDistance; 00470 00471 centerRegion = copy.centerRegion; 00472 00473 //itemHandle = copy.itemHandle; 00474 setPen(defaultPen = copy.defaultPen); 00475 00476 for (int i=0; i < copy.curveSegments.size() && i < curveSegments.size(); ++i) 00477 for (int j=0; j < copy.curveSegments[i].size() && j < curveSegments[i].size(); ++j) 00478 if (copy.curveSegments[i][j] && curveSegments[i][j] && curveSegments[i][j]->parentItem() == 0) 00479 curveSegments[i][j]->setPos(copy.curveSegments[i][j]->scenePos()); 00480 00481 return *this; 00482 } 00483 00485 ConnectionGraphicsItem::~ConnectionGraphicsItem() 00486 { 00487 clear(true); 00488 if (!itemHandle) return; 00489 setHandle(0); 00490 } 00491 00493 bool ConnectionGraphicsItem::isValid() 00494 { 00495 for (int i=0; i < curveSegments.size(); ++i) 00496 if (curveSegments[i].size() < 4) 00497 return false; 00498 return (curveSegments.size() > 0); 00499 } 00500 00501 /* 00502 void ConnectionGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget) 00503 { 00504 //painter->setClipRect( option->exposedRect ); 00505 //refresh(); 00506 00507 painter->setBrush(Qt::NoBrush); 00508 painter->setPen(QPen(GraphicsScene::BackgroundColor,pen().width()+4)); 00509 painter->drawPath(path());//this->pathShape); 00510 00511 painter->setBrush(brush()); 00512 painter->setPen(pen()); 00513 painter->drawPath(path());//this->pathShape); 00514 }*/ 00515 00517 ConnectionGraphicsItem::ControlPoint::ControlPoint(ConnectionGraphicsItem * reaction_ptr, QGraphicsItem * parent) : 00518 Tinkercell::ControlPoint(parent) 00519 { 00520 connectionItem = reaction_ptr; 00521 setPen( defaultPen = QPen( QColor(100,100,255) ) ); 00522 setBrush( defaultBrush = QBrush( QColor(0,0,255,10)) ); 00523 setRect(QRectF(-10,-10,20,20)); 00524 setZValue(1); 00525 } 00526 00528 ConnectionGraphicsItem::ControlPoint::ControlPoint(const QPointF& pos, ConnectionGraphicsItem * reaction_ptr, QGraphicsItem * parent) : 00529 Tinkercell::ControlPoint(parent) 00530 { 00531 connectionItem = reaction_ptr; 00532 setPen( defaultPen = QPen( QColor(100,100,255) ) ); 00533 setBrush( defaultBrush = QBrush( QColor(0,0,255,10)) ); 00534 setRect(QRectF(-10,-10,20,20)); 00535 setZValue(1); 00536 setPos(pos); 00537 } 00539 ConnectionGraphicsItem::ControlPoint::ControlPoint(const ControlPoint& copy) : Tinkercell::ControlPoint(copy.parentItem()) 00540 { 00541 connectionItem = copy.connectionItem; 00542 setPos(copy.scenePos()); 00543 setRect(copy.rect()); 00544 setBrush(defaultBrush = copy.defaultBrush); 00545 setPen(defaultPen = copy.defaultPen); 00546 //setTransform(copy.transform()); 00547 } 00548 00550 ControlPoint* ConnectionGraphicsItem::ControlPoint::clone() const 00551 { 00552 return new ConnectionGraphicsItem::ControlPoint(*this); 00553 } 00554 00556 ConnectionGraphicsItem::ControlPoint::~ControlPoint() 00557 { 00558 if (connectionItem) 00559 { 00560 for (int i=0; i < connectionItem->curveSegments.size(); ++i) 00561 for (int j=0; j < connectionItem->curveSegments[i].size(); ++j) 00562 if (connectionItem->curveSegments[i][j] == this) 00563 connectionItem->curveSegments[i][j] = 0; 00564 } 00565 } 00566 00568 ConnectionGraphicsItem::ControlPoint& ConnectionGraphicsItem::ControlPoint::operator =(const ControlPoint& copy) 00569 { 00570 connectionItem = copy.connectionItem; 00571 setPos(copy.scenePos()); 00572 setRect(copy.rect()); 00573 setBrush(defaultBrush = copy.defaultBrush); 00574 setPen(defaultPen = copy.defaultPen); 00575 return *this; 00576 } 00577 00579 QPainterPath ConnectionGraphicsItem::shape() const 00580 { 00581 return pathShape; 00582 } 00583 00585 ConnectionGraphicsItem::ControlPoint * ConnectionGraphicsItem::centerPoint() const 00586 { 00587 for (int i=0; i < curveSegments.size(); ++i) 00588 { 00589 if (curveSegments[i].last() && (NodeGraphicsItem::cast(curveSegments[i].last()->parentItem()) == 0) 00590 && curveSegments.size() > 1 && curveSegments[i].arrowEnd == 0) 00591 return curveSegments[i].last(); 00592 } 00593 if (curveSegments.size() > 0 && curveSegments[0].size() >= 4) 00594 { 00595 int i = curveSegments[0].size()/2; 00596 if (lineType == line || curveSegments[0].size() > 4) 00597 i = 3 * (int)(i/3); 00598 return curveSegments[0][i]; 00599 } 00600 return 0; 00601 } 00602 00604 QPointF ConnectionGraphicsItem::centerLocation() const 00605 { 00606 QPointF p(0,0); 00607 if (scene()) 00608 { 00609 if (pathShape.elementCount() > 0 && curveSegments.size() == 1 && curveSegments[0].size() < 5) 00610 { 00611 p = pathShape.pointAtPercent(0.25); 00612 } 00613 else 00614 { 00615 ConnectionGraphicsItem::ControlPoint * cp = centerPoint(); 00616 if (cp && cp->scene()) 00617 p = centerPoint()->scenePos(); 00618 } 00619 if (!p.isNull()) 00620 return p; 00621 } 00622 00623 p = QPointF(0,0); 00624 00625 NodeGraphicsItem * node; 00626 int n = 0; 00627 for (int i=0; i < curveSegments.size(); ++i) 00628 if (curveSegments[i].size() > 0 && curveSegments[i][0]) 00629 { 00630 node = NodeGraphicsItem::cast(curveSegments[i][0]->parentItem()); 00631 if (node && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 00632 { 00633 p += node->scenePos(); 00634 ++n; 00635 } 00636 if (curveSegments[i].size() > 1 && curveSegments[i][curveSegments[i].size()-1]) 00637 { 00638 node = NodeGraphicsItem::cast(curveSegments[i][curveSegments[i].size()-1]->parentItem()); 00639 if (node && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 00640 { 00641 p += node->scenePos(); 00642 ++n; 00643 } 00644 } 00645 } 00646 p /= n; 00647 return p; 00648 } 00649 00653 void ConnectionGraphicsItem::adjustEndPoints(bool arrowTransform) 00654 { 00655 if (!scene()) return; 00656 00657 //firstPoint = point on the node, lastPoint = point at the center (might be modifier) 00658 //cp0 = point just before firstPoint, cp1 = point just before lastPoint 00659 ControlPoint * firstPoint, *lastPoint, * cp0, * cp1; 00660 int truePaths = 0; //number of non-modifier paths 00661 00662 //when there is only one path (1-to-1), the situation is totally different 00663 for (int i=0; i < curveSegments.size(); ++i) 00664 { 00665 firstPoint = curveSegments[i].first(); 00666 lastPoint = curveSegments[i].last(); 00667 00668 if (curveSegments[i].size() < 4 || !lastPoint || !firstPoint) continue; 00669 00670 if (firstPoint->parentItem() != 0 && 00671 ((lastPoint->parentItem() != 0 && 00672 lastPoint->parentItem() != curveSegments[i].arrowEnd) 00673 || (lastPoint->parentItem() == 0))) 00674 ++truePaths; 00675 00676 if (lineType == bezier) 00677 cp0 = curveSegments[i][ 1 ]; 00678 else 00679 cp0 = curveSegments[i][ 3 ]; 00680 00681 if (lineType == bezier) 00682 cp1 = curveSegments[i][ curveSegments[i].size()-2 ]; 00683 else 00684 cp1 = curveSegments[i][ curveSegments[i].size()-4 ]; 00685 00686 //adjust firstPoint so that it lies on the boundary rect of the item it points to 00687 NodeGraphicsItem * node = 0; 00688 if (firstPoint != 0 && cp0 != 0 && (node = NodeGraphicsItem::cast(firstPoint->parentItem())) != 0) 00689 { 00690 QRectF parentRect = node->sceneBoundingRect(); 00691 //QPainterPath parentShape = node->mapToScene(node->shape()); 00692 00693 if (firstPoint->isVisible()) 00694 firstPoint->setVisible(false); 00695 if (curveSegments[i].arrowStart != 0) 00696 { 00697 QPointF p = pointOnEdge(*node, cp0->scenePos(), arrowHeadDistance , lineType == line); 00698 00699 firstPoint->setPos( node->mapFromScene(p) ); 00700 00701 if (curveSegments[i].arrowStart->scene() != scene() && scene()) 00702 { 00703 if (curveSegments[i].arrowStart->scene()) 00704 curveSegments[i].arrowStart->scene()->removeItem(curveSegments[i].arrowStart); 00705 (static_cast<GraphicsScene*>(scene()))->addItem(curveSegments[i].arrowStart); 00706 } 00707 00708 curveSegments[i].arrowStart->setZValue(zValue() + 0.1); 00709 00710 if (curveSegments[i].arrowStart->handle() != 0) //arrow should not have handles 00711 Tinkercell::setHandle(curveSegments[i].arrowStart,0); 00712 00713 if (curveSegments[i].arrowStart->parentItem() == 0) 00714 { 00715 QPointF p2 = p;//pointOnEdge( *node, cp0->scenePos(), arrowHeadDistance, lineType == line); 00716 curveSegments[i].arrowStart->setPos(p2); 00717 } 00718 00719 qreal angle; 00720 if (cp0->x() == p.x()) 00721 if (cp0->y() < p.y()) 00722 angle = 90.0; 00723 else 00724 angle = -90.0; 00725 00726 else 00727 angle = atan((cp0->y()-p.y())/(cp0->x()-p.x())) * 180.0/3.14159; 00728 00729 if (cp0->x() > p.x()) 00730 if (cp0->y() < p.y()) 00731 angle += 180.0; 00732 else 00733 angle -= 180.0; 00734 00735 00736 if (curveSegments[i].arrowStart->angle != angle) 00737 { 00738 double dx = angle - curveSegments[i].arrowStart->angle; 00739 00740 if (arrowTransform) 00741 { 00742 double sinx = sin(dx * 3.14159/180.0), 00743 cosx = cos(dx * 3.14159/180.0); 00744 QTransform rotate(cosx, sinx, -sinx, cosx, 0, 0); 00745 QTransform t = curveSegments[i].arrowStart->transform(); 00746 curveSegments[i].arrowStart->setTransform(t * rotate); 00747 } 00748 curveSegments[i].arrowStart->angle = angle; 00749 } 00750 } 00751 else 00752 { 00753 firstPoint->setPos( 00754 node->mapFromScene( 00755 pointOnEdge(*node, cp0->scenePos(), arrowHeadDistance/2.0, lineType == line))); 00756 } 00757 } 00758 00759 //adjust modifier arrows (if exists) by using center region 00760 ControlPoint * centerPoint = this->centerPoint(); 00761 if (cp1 != 0 && centerPoint && lastPoint != centerPoint && curveSegments[i].arrowEnd != 0 00762 && (lastPoint->parentItem() == 0 || lastPoint->parentItem() == curveSegments[i].arrowEnd) 00763 && curveSegments.size() > 1) 00764 { 00765 QPointF centerPoint = this->centerPoint()->scenePos(); 00766 QRectF centerRect(centerPoint - QPointF(centerRegion.width(),centerRegion.height())/2.0, centerRegion); 00767 QPointF p = pointOnEdge(centerRect, cp1->scenePos(), arrowHeadDistance + 2.0,lineType == line); 00768 QPointF p2 = cp1->scenePos(); 00769 if (lastPoint->parentItem() != curveSegments[i].arrowEnd) 00770 lastPoint->setParentItem(curveSegments[i].arrowEnd); 00771 00772 curveSegments[i].arrowEnd->setPos(p); 00773 lastPoint->setPos(curveSegments[i].arrowEnd->mapFromScene(p) ); 00774 00775 if (curveSegments[i].arrowEnd->scene() != scene() && scene()) 00776 { 00777 if (curveSegments[i].arrowEnd->scene()) 00778 curveSegments[i].arrowEnd->scene()->removeItem(curveSegments[i].arrowEnd); 00779 (static_cast<GraphicsScene*>(scene()))->addItem(curveSegments[i].arrowEnd); 00780 } 00781 00782 curveSegments[i].arrowEnd->setZValue(zValue() + 0.1); 00783 00784 qreal angle; 00785 if (cp1->x() == p.x()) 00786 if (cp1->y() < p.y()) 00787 angle = 90.0; 00788 else 00789 angle = -90.0; 00790 else 00791 angle = atan((cp1->y() - p.y())/(cp1->x() - p.x())) * 180.0/3.14159; 00792 if (cp1->x() > p.x()) 00793 if (cp1->y() < p.y()) 00794 angle += 180.0; 00795 else 00796 angle -= 180.0; 00797 00798 if (curveSegments[i].arrowEnd->angle != angle) 00799 { 00800 double dx = angle - curveSegments[i].arrowEnd->angle; 00801 if (arrowTransform) 00802 { 00803 double sinx = sin(dx * 3.14159/180.0), 00804 cosx = cos(dx * 3.14159/180.0); 00805 QTransform rotate(cosx, sinx, -sinx, cosx, 0, 0); 00806 QTransform t = curveSegments[i].arrowEnd->transform(); 00807 curveSegments[i].arrowEnd->setTransform(t * rotate); 00808 } 00809 curveSegments[i].arrowEnd->angle = angle; 00810 } 00811 } 00812 } 00813 00814 if (truePaths == 1 && curveSegments[0].size() >= 4) 00815 { 00816 firstPoint = curveSegments[0].last(); 00817 lastPoint = curveSegments[0].first(); 00818 00819 if (lineType == bezier) 00820 cp0 = curveSegments[0][ curveSegments[0].size()-2 ]; 00821 else 00822 cp0 = curveSegments[0][ curveSegments[0].size()-4 ]; 00823 00824 NodeGraphicsItem * node = NodeGraphicsItem::cast(firstPoint->parentItem()); 00825 NodeGraphicsItem * node2 = NodeGraphicsItem::cast(lastPoint->parentItem()); 00826 if (firstPoint != 0 && cp0 != 0 && node && node2) 00827 { 00828 QRectF parentRect1 = node->sceneBoundingRect(), 00829 parentRect2 = node2->sceneBoundingRect(); 00830 //QPainterPath parentShape = node->mapToScene(node->shape()); 00831 00832 if (firstPoint->isVisible()) 00833 firstPoint->setVisible(false); 00834 00835 QPointF p0 = cp0->scenePos(); 00836 00837 if (curveSegments[0].arrowEnd != 0) 00838 { 00839 QPointF p = pointOnEdge(*node, cp0->scenePos(), arrowHeadDistance,lineType == line); 00840 00841 if (lineType == line && curveSegments[0].size() == 4) 00842 { 00843 if (p.rx() == p0.rx()) 00844 { 00845 if (parentRect1.center().rx() > parentRect2.left() && parentRect1.center().rx() < parentRect2.right()) 00846 p.rx() = parentRect1.center().rx(); 00847 else 00848 if (parentRect2.center().rx() > parentRect1.left() && parentRect2.center().rx() < parentRect1.right()) 00849 p.rx() = parentRect2.center().rx(); 00850 } 00851 else 00852 if (p.ry() == p0.ry()) 00853 { 00854 if (parentRect1.center().ry() > parentRect2.top() && parentRect1.center().ry() < parentRect2.bottom()) 00855 p.ry() = parentRect1.center().ry(); 00856 else 00857 if (parentRect2.center().ry() > parentRect1.top() && parentRect2.center().ry() < parentRect1.bottom()) 00858 p.ry() = parentRect2.center().ry(); 00859 } 00860 } 00861 00862 firstPoint->setPos( node->mapFromScene(p) ); 00863 00864 if (curveSegments[0].arrowEnd->scene() != scene() && scene()) 00865 { 00866 if (curveSegments[0].arrowEnd->scene()) 00867 curveSegments[0].arrowEnd->scene()->removeItem(curveSegments[0].arrowEnd); 00868 (static_cast<GraphicsScene*>(scene()))->addItem(curveSegments[0].arrowEnd); 00869 } 00870 00871 if (curveSegments[0].arrowEnd->parentItem() == 0) 00872 { 00873 QPointF p2 = p;//pointOnEdge(*node, cp0->scenePos(), arrowHeadDistance,lineType == line); 00874 curveSegments[0].arrowEnd->setPos(p2); 00875 } 00876 00877 curveSegments[0].arrowEnd->setZValue(zValue() + 0.1); 00878 00879 qreal angle; 00880 if (cp0->x() == p.x()) 00881 if (cp0->y() < p.y()) 00882 angle = 90.0; 00883 else 00884 angle = -90.0; 00885 else 00886 angle = atan((cp0->y()-p.y())/(cp0->x()-p.x())) * 180.0/3.14159; 00887 if (cp0->x() > p.x()) 00888 if (cp0->y() < p.y()) 00889 angle += 180.0; 00890 else 00891 angle -= 180.0; 00892 00893 if (curveSegments[0].arrowEnd->angle != angle) 00894 { 00895 double dx = angle - curveSegments[0].arrowEnd->angle; 00896 if (arrowTransform) 00897 { 00898 double sinx = sin(dx * 3.14159/180.0), 00899 cosx = cos(dx * 3.14159/180.0); 00900 QTransform rotate(cosx, sinx, -sinx, cosx, 0, 0); 00901 QTransform t = curveSegments[0].arrowEnd->transform(); 00902 curveSegments[0].arrowEnd->setTransform(t * rotate); 00903 } 00904 curveSegments[0].arrowEnd->angle = angle; 00905 } 00906 } 00907 else 00908 { 00909 QRectF parentRect1 = node->sceneBoundingRect(), 00910 parentRect2 = node2->sceneBoundingRect(); 00911 00912 QPointF p = pointOnEdge(*node,cp0->scenePos(),arrowHeadDistance/2.0,lineType == line); 00913 00914 if (lineType == line && curveSegments[0].size() == 4) 00915 { 00916 if (p.rx() == p0.rx()) 00917 { 00918 if (parentRect1.center().rx() > parentRect2.left() && parentRect1.center().rx() < parentRect2.right()) 00919 p.rx() = parentRect1.center().rx(); 00920 else 00921 if (parentRect2.center().rx() > parentRect1.left() && parentRect2.center().rx() < parentRect1.right()) 00922 p.rx() = parentRect2.center().rx(); 00923 } 00924 else 00925 if (p.ry() == p0.ry()) 00926 { 00927 if (parentRect1.center().ry() > parentRect2.top() && parentRect1.center().ry() < parentRect2.bottom()) 00928 p.ry() = parentRect1.center().ry(); 00929 else 00930 if (parentRect2.center().ry() > parentRect1.top() && parentRect2.center().ry() < parentRect1.bottom()) 00931 p.ry() = parentRect2.center().ry(); 00932 } 00933 } 00934 00935 firstPoint->setPos( node->mapFromScene(p) ); 00936 } 00937 } 00938 } 00939 00940 } 00941 00945 void ConnectionGraphicsItem::refresh(bool arrowTransform) 00946 { 00947 setPos(0,0); 00948 adjustEndPoints(arrowTransform); 00949 qreal z = zValue(); 00950 00951 if (MainWindow::invalidPointers.contains(centerRegionItem)) 00952 { 00953 centerRegionItem = 0; 00954 } 00955 00956 if (centerRegionItem)// && centerRegionItem->parentItem() == 0) 00957 { 00958 centerRegionItem->connectionItem = this; 00959 if (centerRegionItem->scene() != this->scene() && this->scene()) 00960 { 00961 QList<QGraphicsItem*> children = centerRegionItem->childItems(); 00962 for (int i=0; i < children.size(); ++i) 00963 if (qgraphicsitem_cast<ConnectionGraphicsItem::ControlPoint*>(children[i])) 00964 { 00965 if (centerRegionItem->scene()) 00966 centerRegionItem->scene()->removeItem(centerRegionItem); 00967 (static_cast<GraphicsScene*>(scene()))->addItem(centerRegionItem); 00968 break; 00969 } 00970 } 00971 00972 centerRegionItem->setPos( centerLocation() ); 00973 centerRegionItem->setZValue(z + 0.01); 00974 00975 QList<ConnectionGraphicsItem*> otherConnections = centerRegionItem->connections(); 00976 for (int i=0; i < otherConnections.size(); ++i) 00977 if (otherConnections[i] && otherConnections[i] != this) 00978 otherConnections[i]->refresh(); 00979 } 00980 00981 QPainterPath path; 00982 00983 //text items 00984 QList<TextGraphicsItem*> textItems; 00985 if (itemHandle) 00986 { 00987 TextGraphicsItem * textItem; 00988 QList<QGraphicsItem*> & gitems = itemHandle->graphicsItems; 00989 QPointF center = centerLocation(); 00990 for (int i=0; i < gitems.size(); ++i) 00991 if ( !gitems[i]->parentItem() && 00992 (textItem = TextGraphicsItem::cast(gitems[i])) && 00993 textItem->sceneBoundingRect().intersects(pathBoundingRect.adjusted(-10,-10,10,10))) 00994 { 00995 textItem->relativePosition.first = this; 00996 textItem->relativePosition.second = textItem->scenePos() - center; 00997 textItems << textItem; 00998 } 00999 } 01000 01001 if (lineType == line) 01002 { 01003 QPointF pos; 01004 for (int i=0; i < curveSegments.size(); ++i) 01005 { 01006 if (MainWindow::invalidPointers.contains(curveSegments[i].arrowStart)) 01007 curveSegments[i].arrowStart = 0; 01008 if (curveSegments[i].arrowStart) 01009 { 01010 if (curveSegments[i].arrowStart->scene() != this->scene() && this->scene()) 01011 { 01012 if (curveSegments[i].arrowStart->scene()) 01013 curveSegments[i].arrowStart->scene()->removeItem(curveSegments[i].arrowStart); 01014 (static_cast<GraphicsScene*>(scene()))->addItem(curveSegments[i].arrowStart); 01015 } 01016 curveSegments[i].arrowStart->setZValue(z + 0.1); 01017 } 01018 01019 if (MainWindow::invalidPointers.contains(curveSegments[i].arrowEnd)) 01020 curveSegments[i].arrowEnd = 0; 01021 01022 if (curveSegments[i].arrowEnd) 01023 { 01024 if (curveSegments[i].arrowEnd->scene() != this->scene() && this->scene()) 01025 { 01026 if (curveSegments[i].arrowEnd->scene()) 01027 curveSegments[i].arrowEnd->scene()->removeItem(curveSegments[i].arrowEnd); 01028 (static_cast<GraphicsScene*>(scene()))->addItem(curveSegments[i].arrowEnd); 01029 } 01030 curveSegments[i].arrowEnd->setZValue(z + 0.1); 01031 } 01032 01033 NodeGraphicsItem * node = nodeAt(i); 01034 if (curveSegments[i].size() > 0 && 01035 curveSegments[i][0] && 01036 node && node->scene() == scene()) 01037 { 01038 curveSegments[i][0]->setZValue(z + 0.02); 01039 pos = curveSegments[i][0]->scenePos(); 01040 path.moveTo(pos); 01041 for (int j=0; j+3 < curveSegments[i].size(); j+=3) 01042 if (curveSegments[i][j] && curveSegments[i][j+1] && curveSegments[i][j+2] && curveSegments[i][j+3]) 01043 { 01044 curveSegments[i][j+1]->setZValue(z + 0.02); 01045 curveSegments[i][j+2]->setZValue(z + 0.02); 01046 curveSegments[i][j+3]->setZValue(z + 0.02); 01047 pos = curveSegments[i][j+3]->scenePos(); 01048 path.lineTo(pos); 01049 } 01050 } 01051 } 01052 } 01053 else 01054 { 01055 QPointF pos1,pos2,pos3; 01056 for (int i=0; i < curveSegments.size(); ++i) 01057 { 01058 if (curveSegments[i].arrowStart) 01059 { 01060 if (curveSegments[i].arrowStart->scene() != this->scene() && this->scene()) 01061 { 01062 if (curveSegments[i].arrowStart->scene()) 01063 curveSegments[i].arrowStart->scene()->removeItem(curveSegments[i].arrowStart); 01064 (static_cast<GraphicsScene*>(scene()))->addItem(curveSegments[i].arrowStart); 01065 } 01066 curveSegments[i].arrowStart->setZValue(z + 0.1); 01067 } 01068 if (curveSegments[i].arrowEnd) 01069 { 01070 if (curveSegments[i].arrowEnd->scene() != this->scene() && this->scene()) 01071 { 01072 if (curveSegments[i].arrowEnd->scene()) 01073 curveSegments[i].arrowEnd->scene()->removeItem(curveSegments[i].arrowEnd); 01074 (static_cast<GraphicsScene*>(scene()))->addItem(curveSegments[i].arrowEnd); 01075 } 01076 curveSegments[i].arrowEnd->setZValue(z + 0.1); 01077 } 01078 01079 NodeGraphicsItem * node = nodeAt(i); 01080 if (curveSegments[i].size() > 0 && curveSegments[i][0] && 01081 node && node->scene() == scene()) 01082 { 01083 curveSegments[i][0]->setZValue(z + 0.02); 01084 01085 pos1 = curveSegments[i][0]->scenePos(); 01086 curveSegments[i][0]->setZValue(z + 0.02); 01087 path.moveTo(pos1); 01088 for (int j=0; j+3 < curveSegments[i].size(); j+=3) 01089 if (curveSegments[i][j+1] && curveSegments[i][j+2] && curveSegments[i][j+3]) 01090 { 01091 curveSegments[i][j+1]->setZValue(z + 0.02); 01092 curveSegments[i][j+2]->setZValue(z + 0.02); 01093 curveSegments[i][j+3]->setZValue(z + 0.02); 01094 01095 pos1 = curveSegments[i][j+1]->scenePos(); 01096 pos2 = curveSegments[i][j+2]->scenePos(); 01097 pos3 = curveSegments[i][j+3]->scenePos(); 01098 01099 path.cubicTo(pos1,pos2,pos3); 01100 } 01101 } 01102 } 01103 } 01104 01105 QPainterPathStroker stroker; 01106 stroker.setJoinStyle(Qt::RoundJoin); 01107 stroker.setCapStyle(Qt::RoundCap); 01108 //stroker.setDashPattern(pen().style()); 01109 stroker.setWidth(0.0); 01110 this->pathShape = stroker.createStroke(path); 01111 01112 if (pen().style() == Qt::SolidLine) 01113 setPath(this->pathShape); 01114 else 01115 setPath(path); 01116 01117 pathBoundingRect = this->pathShape.controlPointRect().adjusted(-10,-10,10,10); 01118 refreshBoundaryPath(); 01119 update(); 01120 01121 //text items 01122 if (itemHandle && !textItems.isEmpty()) 01123 { 01124 QPointF center = centerLocation(); 01125 for (int i=0; i < textItems.size(); ++i) 01126 { 01127 textItems[i]->setPos( center + textItems[i]->relativePosition.second ); 01128 } 01129 } 01130 } 01131 01133 void ConnectionGraphicsItem::refreshBoundaryPath() 01134 { 01135 //boundaryPathItem->setVisible(true); 01136 QPainterPath boundary; 01137 for (int i=0; i < curveSegments.size(); ++i) 01138 { 01139 for (int j=0; j < curveSegments[i].size(); ++j) 01140 { 01141 if (curveSegments[i][j]) 01142 if (j == 0) 01143 boundary.moveTo(curveSegments[i][j]->scenePos()); 01144 else 01145 boundary.lineTo(curveSegments[i][j]->scenePos()); 01146 } 01147 } 01148 01149 if (boundaryPathItem && mainPathItem && outerPathItem) 01150 { 01151 boundaryPathItem->setPath(boundary); 01152 boundaryPathItem->update(); 01153 outerPathItem->setZValue(0.1); 01154 boundaryPathItem->setZValue(0.5); 01155 mainPathItem->setZValue(1.0); 01156 } 01157 } 01158 01162 void ConnectionGraphicsItem::clear(bool all) 01163 { 01164 QList<ConnectionGraphicsItem::ControlPoint*> visited; 01165 for (int i=0; i < curveSegments.size(); ++i) 01166 for (int j=0; j < curveSegments[i].size(); ++j) 01167 if (curveSegments[i][j] && !visited.contains(curveSegments[i][j])) 01168 { 01169 visited += curveSegments[i][j]; 01170 01171 curveSegments[i][j]->setParentItem(0); 01172 01173 if (curveSegments[i][j]->scene()) 01174 { 01175 curveSegments[i][j]->scene()->removeItem(curveSegments[i][j]); 01176 } 01177 01178 curveSegments[i][j]->connectionItem = 0; 01179 01180 delete curveSegments[i][j]; 01181 curveSegments[i][j] = 0; 01182 01183 if (all) 01184 { 01185 if (curveSegments[i].arrowStart && 01186 !MainWindow::invalidPointers.contains( (void*)curveSegments[i].arrowStart) ) 01187 { 01188 if (curveSegments[i].arrowStart->scene()) 01189 curveSegments[i].arrowStart->scene()->removeItem(curveSegments[i].arrowStart); 01190 MainWindow::invalidPointers[ curveSegments[i].arrowStart ] = true; 01191 delete curveSegments[i].arrowStart; 01192 } 01193 01194 if (curveSegments[i].arrowEnd && 01195 !MainWindow::invalidPointers.contains( (void*)curveSegments[i].arrowEnd) ) 01196 { 01197 if (curveSegments[i].arrowEnd->scene()) 01198 curveSegments[i].arrowEnd->scene()->removeItem(curveSegments[i].arrowEnd); 01199 MainWindow::invalidPointers[ (void*)curveSegments[i].arrowEnd ] = true; 01200 delete curveSegments[i].arrowEnd; 01201 } 01202 01203 curveSegments[i].arrowStart = 0; 01204 curveSegments[i].arrowEnd = 0; 01205 } 01206 } 01207 curveSegments.clear(); 01208 01209 if (centerRegionItem && all && !MainWindow::invalidPointers.contains(centerRegionItem)) 01210 { 01211 centerRegionItem->setParentItem(0); 01212 centerRegionItem->connectionItem = 0; 01213 01214 if (centerRegionItem->scene()) 01215 centerRegionItem->scene()->removeItem(centerRegionItem); 01216 01217 MainWindow::invalidPointers[ (void*)centerRegionItem ] = true; 01218 delete centerRegionItem; 01219 centerRegionItem = 0; 01220 } 01221 } 01222 01224 qreal ConnectionGraphicsItem::slopeAtPoint(const QPointF& point) 01225 { 01226 if (!mainPathItem) return 0.0; 01227 01228 qreal percent = 1, dpercent = 1; 01229 QPainterPath path = mainPathItem->path(); 01230 QPointF p1 = path.pointAtPercent(0), p2; 01231 01232 while (percent < 100) 01233 { 01234 p2 = path.pointAtPercent(percent); 01235 if ( ((point.x() - p1.x())*(point.x() - p1.x()) + (point.y() - p1.y())*(point.y() - p1.y())) < 01236 ((point.x() - p2.x())*(point.x() - p2.x()) + (point.y() - p2.y())*(point.y() - p2.y())) ) 01237 01238 break; 01239 01240 percent += dpercent; 01241 } 01242 return path.slopeAtPercent(percent); 01243 } 01244 01248 void ConnectionGraphicsItem::setControlPointsVisible(bool visible) 01249 { 01250 controlPointsVisible = visible; 01251 if (boundaryPathItem && lineType == bezier) 01252 boundaryPathItem->setVisible(visible); 01253 else 01254 boundaryPathItem->setVisible(false); 01255 01256 for (int i=0; i < curveSegments.size(); ++i) 01257 for (int j=0; j < curveSegments[i].size(); ++j) 01258 { 01259 if (curveSegments[i][j]) 01260 { 01261 curveSegments[i][j]->connectionItem = this; 01262 if (lineType == bezier || (j%3)==0) 01263 { 01264 curveSegments[i][j]->setVisible(visible); 01265 if (visible && scene() != curveSegments[i][j]->scene()) 01266 { 01267 if (curveSegments[i][j]->scene()) 01268 { 01269 curveSegments[i][j]->setParentItem(0); 01270 curveSegments[i][j]->scene()->removeItem(curveSegments[i][j]); 01271 } 01272 if (scene()) 01273 (static_cast<GraphicsScene*>(scene()))->addItem(curveSegments[i][j]); 01274 } 01275 } 01276 else 01277 { 01278 curveSegments[i][j]->setVisible(false); 01279 } 01280 } 01281 } 01282 refresh(); 01283 } 01284 01285 void ConnectionGraphicsItem::showControlPoints() 01286 { 01287 setControlPointsVisible(true); 01288 } 01289 01290 void ConnectionGraphicsItem::hideControlPoints() 01291 { 01292 setControlPointsVisible(false); 01293 } 01294 01296 QRectF ConnectionGraphicsItem::boundingRect() const 01297 { 01298 //return pathShape.controlPointRect(); 01299 return pathBoundingRect; 01300 } 01302 QRectF ConnectionGraphicsItem::sceneBoundingRect() const 01303 { 01304 //return pathShape.controlPointRect(); 01305 return pathBoundingRect; 01306 } 01308 QList<ConnectionGraphicsItem::ControlPoint*> ConnectionGraphicsItem::controlPoints(bool includeEnds) const 01309 { 01310 QList<ControlPoint*> list; 01311 for (int i=0; i < curveSegments.size(); ++i) 01312 for (int j=0; j < curveSegments[i].size(); ++j) 01313 { 01314 if (curveSegments[i][j] && !list.contains(curveSegments[i][j]) && 01315 (curveSegments[i][j]->parentItem() == 0 || includeEnds) 01316 ) 01317 list.append(curveSegments[i][j]); 01318 } 01319 return list; 01320 } 01322 QList<QGraphicsItem*> ConnectionGraphicsItem::controlPointsAsGraphicsItems(bool includeEnds) const 01323 { 01324 QList<QGraphicsItem*> list; 01325 for (int i=0; i < curveSegments.size(); ++i) 01326 for (int j=0; j < curveSegments[i].size(); ++j) 01327 { 01328 if (curveSegments[i][j] && !list.contains(curveSegments[i][j]) && 01329 (curveSegments[i][j]->parentItem() == 0 || includeEnds) 01330 ) 01331 list.append(curveSegments[i][j]); 01332 } 01333 return list; 01334 } 01335 01337 ConnectionGraphicsItem * ConnectionGraphicsItem::topLevelConnectionItem(QGraphicsItem* item,bool includeControlPoints) 01338 { 01339 ConnectionGraphicsItem * idptr = 0, * idptr2 = 0; 01340 ConnectionGraphicsItem::ControlPoint * cp = 0; 01341 01342 QGraphicsItem * p = item; 01343 01344 while (p) 01345 { 01346 idptr = qgraphicsitem_cast<ConnectionGraphicsItem*>(p); 01347 if (!idptr && includeControlPoints) 01348 { 01349 cp = qgraphicsitem_cast<ConnectionGraphicsItem::ControlPoint*>(p); 01350 if (cp && cp->connectionItem) 01351 idptr = cp->connectionItem; 01352 } 01353 01354 if (idptr != 0) idptr2 = idptr; 01355 01356 if (p != p->parentItem()) 01357 p = p->parentItem(); 01358 else 01359 break; 01360 } 01361 01362 return idptr2; 01363 } 01364 01365 bool ConnectionGraphicsItem::isModifier() const 01366 { 01367 NodeGraphicsItem* node; 01368 ArrowHeadItem * arrow; 01369 01370 for (int i=0; i < curveSegments.size(); ++i) 01371 if (curveSegments[i].size() > 0 && curveSegments[i][0]) 01372 { 01373 node = NodeGraphicsItem::cast(curveSegments[i][0]->parentItem()); 01374 if (node && (arrow = ArrowHeadItem::cast(node))) 01375 { 01376 if (arrow->connectionItem && arrow->connectionItem->centerRegionItem == arrow) 01377 return true; 01378 } 01379 if (curveSegments[i].size() > 1 && curveSegments[i][curveSegments[i].size()-1]) 01380 { 01381 node = NodeGraphicsItem::cast(curveSegments[i][curveSegments[i].size()-1]->parentItem()); 01382 if (node && (arrow = ArrowHeadItem::cast(node))) 01383 { 01384 if (arrow->connectionItem && arrow->connectionItem->centerRegionItem == arrow) 01385 return true; 01386 } 01387 } 01388 } 01389 return false; 01390 } 01391 01394 QList<NodeGraphicsItem*> ConnectionGraphicsItem::nodes() const 01395 { 01396 QList<NodeGraphicsItem*> nodes; 01397 NodeGraphicsItem* node; 01398 01399 for (int i=0; i < curveSegments.size(); ++i) 01400 if (curveSegments[i].size() > 0 && curveSegments[i][0]) 01401 { 01402 node = NodeGraphicsItem::cast(curveSegments[i][0]->parentItem()); 01403 if (node && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01404 nodes += node; 01405 if (curveSegments[i].size() > 1 && curveSegments[i][curveSegments[i].size()-1]) 01406 { 01407 node = NodeGraphicsItem::cast(curveSegments[i][curveSegments[i].size()-1]->parentItem()); 01408 if (node && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01409 nodes += node; 01410 } 01411 } 01412 01413 return nodes; 01414 } 01415 01416 01419 QList<NodeGraphicsItem*> ConnectionGraphicsItem::nodesWithArrows() const 01420 { 01421 QList<NodeGraphicsItem*> nodes; 01422 NodeGraphicsItem* node; 01423 01424 for (int i=0; i < curveSegments.size(); ++i) 01425 if (curveSegments[i].size() > 0 && curveSegments[i][0]) 01426 { 01427 node = NodeGraphicsItem::cast(curveSegments[i][0]->parentItem()); 01428 if (node && curveSegments[i].arrowStart && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01429 nodes += node; 01430 if (curveSegments[i].size() > 1 && curveSegments[i][curveSegments[i].size()-1]) 01431 { 01432 node = NodeGraphicsItem::cast(curveSegments[i][curveSegments[i].size()-1]->parentItem()); 01433 if (node && curveSegments[i].arrowEnd && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01434 nodes += node; 01435 } 01436 } 01437 01438 return nodes; 01439 } 01440 01443 QList<NodeGraphicsItem*> ConnectionGraphicsItem::nodesWithoutArrows() const 01444 { 01445 QList<NodeGraphicsItem*> nodes; 01446 NodeGraphicsItem* node; 01447 01448 for (int i=0; i < curveSegments.size(); ++i) 01449 if (curveSegments[i].size() > 0 && curveSegments[i][0]) 01450 { 01451 node = NodeGraphicsItem::cast(curveSegments[i][0]->parentItem()); 01452 if (node && !curveSegments[i].arrowStart && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01453 nodes += node; 01454 if (curveSegments[i].size() > 1 && curveSegments[i][curveSegments[i].size()-1]) 01455 { 01456 node = NodeGraphicsItem::cast(curveSegments[i][curveSegments[i].size()-1]->parentItem()); 01457 if (node && !curveSegments[i].arrowEnd && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01458 nodes += node; 01459 } 01460 } 01461 01462 return nodes; 01463 } 01464 01467 QList<NodeGraphicsItem*> ConnectionGraphicsItem::nodesDisconnected() const 01468 { 01469 QList<NodeGraphicsItem*> nodes; 01470 NodeGraphicsItem* node; 01471 01472 ControlPoint * center = centerPoint(); 01473 01474 for (int i=0; i < curveSegments.size(); ++i) 01475 if (curveSegments[i].size() > 1 && curveSegments[i][0] && !curveSegments[i].contains(center)) 01476 { 01477 node = NodeGraphicsItem::cast(curveSegments[i][0]->parentItem()); 01478 if (node) 01479 nodes += node; 01480 } 01481 01482 return nodes; 01483 } 01484 01487 QList<QGraphicsItem*> ConnectionGraphicsItem::nodesAsGraphicsItems() const 01488 { 01489 QList<QGraphicsItem*> nodes; 01490 NodeGraphicsItem* node; 01491 01492 for (int i=0; i < curveSegments.size(); ++i) 01493 if (curveSegments[i].size() > 0 && curveSegments[i][0]) 01494 { 01495 node = NodeGraphicsItem::cast(curveSegments[i][0]->parentItem()); 01496 if (node && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01497 nodes += node; 01498 if (curveSegments[i].size() > 1) 01499 { 01500 node = NodeGraphicsItem::cast(curveSegments[i][curveSegments[i].size()-1]->parentItem()); 01501 if (node && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01502 nodes += node; 01503 } 01504 } 01505 01506 return nodes; 01507 } 01508 01511 QList<ArrowHeadItem*> ConnectionGraphicsItem::arrowHeads() const 01512 { 01513 QList<ArrowHeadItem*> arrows; 01514 NodeGraphicsItem* node; 01515 01516 for (int i=0; i < curveSegments.size(); ++i) 01517 if (curveSegments[i].size() > 0 && curveSegments[i][0]) 01518 { 01519 node = NodeGraphicsItem::cast(curveSegments[i][0]->parentItem()); 01520 if (node && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01521 arrows += curveSegments[i].arrowStart; 01522 if (curveSegments[i].size() > 1) 01523 { 01524 node = NodeGraphicsItem::cast(curveSegments[i][curveSegments[i].size()-1]->parentItem()); 01525 if (node && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01526 arrows += curveSegments[i].arrowEnd; 01527 } 01528 } 01529 01530 return arrows; 01531 } 01532 01535 QList<QGraphicsItem*> ConnectionGraphicsItem::arrowHeadsAsGraphicsItems() const 01536 { 01537 QList<QGraphicsItem*> arrows; 01538 NodeGraphicsItem* node; 01539 01540 for (int i=0; i < curveSegments.size(); ++i) 01541 if (curveSegments[i].size() > 0 && curveSegments[i][0]) 01542 { 01543 node = NodeGraphicsItem::cast(curveSegments[i][0]->parentItem()); 01544 if (node && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01545 arrows += curveSegments[i].arrowStart; 01546 if (curveSegments[i].size() > 1) 01547 { 01548 node = NodeGraphicsItem::cast(curveSegments[i][curveSegments[i].size()-1]->parentItem()); 01549 if (node && node != curveSegments[i].arrowStart && node != curveSegments[i].arrowEnd) 01550 arrows += curveSegments[i].arrowEnd; 01551 } 01552 } 01553 01554 return arrows; 01555 } 01556 01559 QList<ArrowHeadItem*> ConnectionGraphicsItem::modifierArrowHeads() const 01560 { 01561 QList<ArrowHeadItem*> arrows; 01562 NodeGraphicsItem* node; 01563 01564 for (int i=0; i < curveSegments.size(); ++i) 01565 if (curveSegments[i].size() > 0 && curveSegments[i][0]) 01566 { 01567 node = NodeGraphicsItem::cast(curveSegments[i][0]->parentItem()); 01568 if (node && node == curveSegments[i].arrowStart) 01569 arrows += curveSegments[i].arrowStart; 01570 if (curveSegments[i].size() > 1) 01571 { 01572 node = NodeGraphicsItem::cast(curveSegments[i][curveSegments[i].size()-1]->parentItem()); 01573 if (node && node == curveSegments[i].arrowEnd) 01574 arrows += curveSegments[i].arrowEnd; 01575 } 01576 } 01577 01578 return arrows; 01579 } 01580 01584 NodeGraphicsItem* ConnectionGraphicsItem::nodeAt(int index) const 01585 { 01586 NodeGraphicsItem * node = 0; 01587 if (curveSegments.size() == 1) 01588 { 01589 if (index < 0 || index > 1 || 01590 curveSegments[0].size() < 4 || curveSegments[0][curveSegments[0].size()-1] == 0) return 0; 01591 01592 if (index == 0) 01593 node = NodeGraphicsItem::cast(curveSegments[0][0]->parentItem()); 01594 else 01595 node = NodeGraphicsItem::cast(curveSegments[0][curveSegments[0].size()-1]->parentItem()); 01596 01597 if (node == curveSegments[0].arrowStart || node == curveSegments[0].arrowEnd) 01598 node = 0; 01599 01600 return node; 01601 } 01602 01603 if (index < 0 || index >= curveSegments.size() || 01604 curveSegments[index].size() < 4 || 01605 curveSegments[index][0] == 0) 01606 return 0; 01607 01608 node = NodeGraphicsItem::cast(curveSegments[index][0]->parentItem()); 01609 if (node == curveSegments[index].arrowStart || node == curveSegments[index].arrowEnd) 01610 node = 0; 01611 01612 if (node) 01613 return node; 01614 01615 return 0; 01616 } 01617 01621 int ConnectionGraphicsItem::indexOf(QGraphicsItem * target) const 01622 { 01623 if (!target) return -1; 01624 01625 if (curveSegments.size() == 1 && (curveSegments[0].size() > 1 && curveSegments[0][0])) 01626 { 01627 for (int i=0; i < curveSegments[0].size(); ++i) 01628 if (target == curveSegments[0][i]) 01629 return 0; 01630 01631 if (target == curveSegments[0].arrowStart) return 0; 01632 01633 if (target == curveSegments[0].arrowEnd) return 1; 01634 01635 if (target == curveSegments[0][0]->parentItem()) return 0; 01636 01637 if (curveSegments[0][curveSegments[0].size()-1] && 01638 (target == curveSegments[0][curveSegments[0].size()-1]->parentItem())) return 1; 01639 } 01640 01641 for (int i=0; i < curveSegments.size(); ++i) 01642 if (curveSegments[i].size() > 1 && curveSegments[i][0]) 01643 { 01644 if (target == curveSegments[i].arrowStart || 01645 target == curveSegments[i].arrowEnd || 01646 target == curveSegments[i][0]->parentItem()) return i; 01647 01648 if (curveSegments[i][curveSegments[i].size()-1] && 01649 target == curveSegments[i][curveSegments[i].size()-1]->parentItem()) return i; 01650 01651 for (int j=0; j < curveSegments[i].size(); ++j) 01652 if (target == curveSegments[i][j]) 01653 return i; 01654 } 01655 01656 return -1; 01657 } 01658 01662 ArrowHeadItem* ConnectionGraphicsItem::arrowAt(int index) const 01663 { 01664 ArrowHeadItem* arrow = 0; 01665 NodeGraphicsItem * node; 01666 if (curveSegments.size() == 1) 01667 { 01668 if (index < 0 || index > 1 || 01669 curveSegments[0].size() < 4 || curveSegments[0][curveSegments[0].size()-1] == 0) return 0; 01670 01671 if (index == 0) 01672 { 01673 node = NodeGraphicsItem::cast(curveSegments[0][0]->parentItem()); 01674 arrow = curveSegments[0].arrowStart; 01675 } 01676 else 01677 { 01678 node = NodeGraphicsItem::cast(curveSegments[0][curveSegments[0].size()-1]->parentItem()); 01679 arrow = curveSegments[0].arrowEnd; 01680 } 01681 if (node == curveSegments[0].arrowStart || node == curveSegments[0].arrowEnd) 01682 { 01683 node = 0; 01684 arrow = 0; 01685 } 01686 } 01687 01688 if (index < 0 || index >= curveSegments.size() || 01689 curveSegments[index].size() < 4 || 01690 curveSegments[index][0] == 0) 01691 return 0; 01692 01693 node = NodeGraphicsItem::cast(curveSegments[index][0]->parentItem()); 01694 arrow = curveSegments[index].arrowStart; 01695 if (node == curveSegments[index].arrowStart || node == curveSegments[index].arrowEnd) 01696 { 01697 node = 0; 01698 arrow = 0; 01699 } 01700 01701 if (arrow) 01702 return arrow; 01703 01704 return 0; 01705 } 01706 01710 ArrowHeadItem* ConnectionGraphicsItem::modifierArrowAt(int index) const 01711 { 01712 if (index < 0 || index >= curveSegments.size()) 01713 return 0; 01714 01715 if (arrowAt(index) == curveSegments[index].arrowEnd) return 0; 01716 01717 return curveSegments[index].arrowEnd; 01718 } 01719 01720 void ConnectionGraphicsItem::replaceNode(NodeGraphicsItem* oldNode, NodeGraphicsItem* newNode) 01721 { 01722 if (oldNode == 0 || newNode == 0) return; 01723 01724 for (int i=0; i < curveSegments.size(); ++i) 01725 { 01726 if (curveSegments[i].size() > 0) 01727 { 01728 if (curveSegments[i][0]->parentItem() == oldNode) 01729 curveSegments[i][0]->setParentItem(newNode); 01730 if (curveSegments[i][curveSegments[i].size() - 1]->parentItem() == oldNode) 01731 curveSegments[i][curveSegments[i].size() - 1]->setParentItem(newNode); 01732 } 01733 } 01734 } 01735 01736 void ConnectionGraphicsItem::replaceNodeAt(int index, NodeGraphicsItem* nodeItem) 01737 { 01738 if (nodeItem == 0) return; 01739 01740 if (curveSegments.size() == 1) 01741 { 01742 if (index < 0 || index > 1 || 01743 curveSegments[0].size() < 4 || curveSegments[0][0] == 0) return; 01744 01745 if (index == 0) 01746 curveSegments[0][0]->setParentItem(nodeItem); 01747 else 01748 curveSegments[0][curveSegments[0].size()-1]->setParentItem(nodeItem); 01749 01750 return; 01751 } 01752 01753 if (index < 0 || index >= curveSegments.size() || 01754 curveSegments[index].size() < 4 || 01755 curveSegments[index][0] == 0) return; 01756 01757 curveSegments[index][0]->setParentItem(nodeItem); 01758 } 01759 01760 void ArrowHeadItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option ,QWidget *widget) 01761 { 01762 if (!boundaryControlPoints.isEmpty()) 01763 { 01764 for (int i=0; i < boundaryControlPoints.size(); ++i) 01765 if (boundaryControlPoints[i]) 01766 { 01767 boundaryControlPoints[i]->nodeItem = 0; 01768 boundaryControlPoints[i]->setParentItem(0); 01769 if (!boundaryControlPoints[i]->scene()) 01770 delete boundaryControlPoints[i]; 01771 } 01772 boundaryControlPoints.clear(); 01773 } 01774 if (connectionItem && connectionItem->scene() == this->scene()) 01775 { 01776 NodeGraphicsItem::paint(painter,option,widget); 01777 } 01778 else 01779 { 01780 this->setParentItem(0); 01781 if (this->scene()) 01782 scene()->removeItem(this); 01783 } 01784 } 01785 01786 ConnectionGraphicsItem::CurveSegment::CurveSegment() : QVector<ConnectionGraphicsItem::ControlPoint*>() 01787 { 01788 arrowStart = arrowEnd = 0; 01789 } 01790 01791 ConnectionGraphicsItem::CurveSegment::CurveSegment(int n) : QVector<ConnectionGraphicsItem::ControlPoint*>(n) 01792 { 01793 arrowStart = arrowEnd = 0; 01794 } 01795 01796 ConnectionGraphicsItem::CurveSegment::CurveSegment(int n,ConnectionGraphicsItem::ControlPoint* p) 01797 : QVector<ConnectionGraphicsItem::ControlPoint*>(n,p) 01798 { 01799 arrowStart = arrowEnd = 0; 01800 } 01801 01802 ConnectionGraphicsItem::CurveSegment::CurveSegment(const ConnectionGraphicsItem::CurveSegment& copy) : 01803 QVector<ConnectionGraphicsItem::ControlPoint*>(copy) 01804 { 01805 arrowStart = copy.arrowStart; 01806 arrowEnd = copy.arrowEnd; 01807 } 01808 01815 QPointF pointOnEdge(const QRectF& rect0, const QPointF& p1, qreal dist, bool straight) 01816 { 01817 QRectF rect1 = rect0; 01818 01819 if (dist > 0) 01820 { 01821 rect1.adjust(-dist,-dist,dist,dist); 01822 } 01823 01824 if (straight) 01825 { 01826 if (p1.x() > rect0.left() && p1.x() < rect0.right()) 01827 if (p1.y() > rect0.center().y()) 01828 return QPointF(p1.x(),rect1.bottom()); 01829 else 01830 return QPointF(p1.x(),rect1.top()); 01831 01832 if (p1.y() > rect0.top() && p1.y() < rect0.bottom()) 01833 if (p1.x() > rect0.center().x()) 01834 return QPointF(rect1.right(),p1.y()); 01835 else 01836 return QPointF(rect1.left(),p1.y()); 01837 } 01838 01839 QPointF p0 = rect1.center(), p; 01840 qreal w1 = rect1.width() / 2.0, 01841 h1 = rect1.height() / 2.0; 01842 01843 if (p1.x() < p0.x()) { w1 = -w1; } 01844 if (p1.y() < p0.y()) { h1 = -h1; } 01845 01846 if (p1.x() != p0.x()) 01847 { 01848 qreal slope = (p1.y() - p0.y())/(p1.x() - p0.x()); 01849 if (abs((int)(w1 * slope)) < abs((int)h1)) 01850 { 01851 p.rx() = p0.x() + w1; 01852 p.ry() = p0.y() + (w1*slope); 01853 01854 } 01855 else 01856 { 01857 p.rx() = p0.x() + (h1/slope); 01858 p.ry() = p0.y() + h1; 01859 } 01860 } 01861 else 01862 { 01863 p.rx() = p0.x(); 01864 p.ry() = p0.y() + h1; 01865 } 01866 01867 return p; 01868 } 01869 01876 QPointF pointOnEdge(const NodeGraphicsItem& node, const QPointF& pt, qreal dist, bool straight) 01877 { 01878 QRectF rect0 = node.sceneBoundingRect(); 01879 //QPointF p0 = pointOnEdge(rect0,pt,dist,straight); 01880 QPointF p0 = pt; 01881 QPointF p1, p; 01882 qreal d = 0; 01883 01884 for (int i=0; i < node.shapes.size(); ++i) 01885 if (node.shapes[i]) 01886 { 01887 QRectF rect1 = node.shapes[i]->sceneBoundingRect().adjusted(-dist,-dist,dist,dist); 01888 01889 if (!straight || d == 0 || 01890 (straight && 01891 ( (pt.x() > rect1.left() && pt.x() < rect1.right()) || 01892 (pt.y() > rect1.top() && pt.y() < rect1.bottom())) )) 01893 { 01894 p1 = pointOnEdge(rect1,pt,dist,straight); 01895 if (d==0 || (((p1.rx() - p0.rx())*(p1.rx() - p0.rx()) + (p1.ry() - p0.ry())*(p1.ry() - p0.ry())) < d)) 01896 { 01897 d = ((p1.rx() - p0.rx())*(p1.rx() - p0.rx()) + (p1.ry() - p0.ry())*(p1.ry() - p0.ry())); 01898 p = p1; 01899 } 01900 } 01901 } 01902 01903 return p; 01904 } 01905 01906 ConnectionGraphicsItem* ConnectionGraphicsItem::cast(QGraphicsItem * q) 01907 { 01908 //if (MainWindow::invalidPointers.contains( (void*)q )) return 0; 01909 if (!q || ToolGraphicsItem::cast(q->topLevelItem())) return 0; 01910 return qgraphicsitem_cast<ConnectionGraphicsItem*>(q); 01911 } 01912 01913 QList<ConnectionGraphicsItem*> ConnectionGraphicsItem::cast(const QList<QGraphicsItem*>& list) 01914 { 01915 QList<ConnectionGraphicsItem*> connections; 01916 ConnectionGraphicsItem* q; 01917 for (int i=0; i < list.size(); ++i) 01918 if (!MainWindow::invalidPointers.contains( (void*)(list[i]) ) && 01919 (q = qgraphicsitem_cast<ConnectionGraphicsItem*>(list[i]))) 01920 connections << q; 01921 return connections; 01922 } 01923 01924 ConnectionGraphicsItem::ConnectionGraphicsItem(const QList<NodeGraphicsItem*>& from, const QList<NodeGraphicsItem*>& to, QGraphicsItem * parent) : 01925 QGraphicsItemGroup (parent), itemHandle(0) 01926 { 01927 setCacheMode(QGraphicsItem::DeviceCoordinateCache); 01928 setFlag(QGraphicsItem::ItemIsMovable, false); 01929 setFlag(QGraphicsItem::ItemIsSelectable, false); 01930 01931 className = ConnectionGraphicsItem::CLASSNAME; 01932 lineType = line; 01933 01934 arrowHeadDistance = 10.0; 01935 centerRegionItem = 0; 01936 centerRegion = QSizeF(20,20); 01937 defaultPen = QPen(QColor(50,50,255,255),5.0,Qt::SolidLine); 01938 defaultPen.setJoinStyle(Qt::RoundJoin); 01939 01940 boundaryPathItem = new QGraphicsPathItem(this); 01941 boundaryPathItem->setVisible(false); 01942 boundaryPathItem->setPen(QPen(QColor(255,150,150,150),4.0,Qt::DotLine)); 01943 boundaryPathItem->setBrush(Qt::NoBrush); 01944 01945 outerPathItem = new QGraphicsPathItem(this); 01946 outerPathItem->setVisible(true); 01947 outerPathItem->setPen(QPen(GraphicsScene::BackgroundColor,6.0,Qt::SolidLine)); 01948 outerPathItem->setBrush(Qt::NoBrush); 01949 01950 mainPathItem = new QGraphicsPathItem(this); 01951 mainPathItem->setVisible(true); 01952 mainPathItem->setPen(defaultPen); 01953 mainPathItem->setBrush(Qt::NoBrush); 01954 01955 addToGroup(boundaryPathItem); 01956 addToGroup(outerPathItem); 01957 addToGroup(mainPathItem); 01958 01959 NodeGraphicsReader imageReader; 01960 /*ArrowHeadItem * node = new ArrowHeadItem; 01961 node->connectionItem = this; 01962 imageReader.readXml(node,DefaultMiddleItemFile); 01963 if (node->isValid()) 01964 { 01965 node->normalize(); 01966 node->scale(25.0/node->sceneBoundingRect().height(),25.0/node->sceneBoundingRect().height()); 01967 }*/ 01968 centerRegionItem = 0; 01969 01970 if (from.size() < 1 || to.size() < 1) return; 01971 01972 QPointF center; 01973 01974 for (int i=0; i < from.size(); ++i) 01975 if (from[i]) 01976 center += from[i]->scenePos(); 01977 01978 for (int i=0; i < to.size(); ++i) 01979 if (to[i]) 01980 center += to[i]->scenePos(); 01981 01982 center /= (from.size() + to.size()); 01983 ControlPoint * centerPoint = new ControlPoint(center,this,0); 01984 01985 for (int i=0; i < from.size(); ++i) 01986 if (from[i]) 01987 { 01988 CurveSegment cv; 01989 cv << new ControlPoint(from[i]->scenePos(),this,from[i]) 01990 << new ControlPoint((from[i]->scenePos() + center)/2.0,this,0) 01991 << new ControlPoint((from[i]->scenePos() + center)/2.0,this,0) 01992 << centerPoint; 01993 curveSegments.append(cv); 01994 } 01995 01996 for (int i=0; i < to.size(); ++i) 01997 if (to[i]) 01998 { 01999 CurveSegment cv; 02000 cv << new ControlPoint(to[i]->scenePos(),this,to[i]) 02001 << new ControlPoint((to[i]->scenePos() + center)/2.0,this,0) 02002 << new ControlPoint((to[i]->scenePos() + center)/2.0,this,0) 02003 << centerPoint; 02004 cv.arrowStart = new ArrowHeadItem(this); 02005 imageReader.readXml(cv.arrowStart,DefaultArrowHeadFile); 02006 if (cv.arrowStart->isValid()) 02007 { 02008 cv.arrowStart->normalize(); 02009 cv.arrowStart->scale(25.0/cv.arrowStart->sceneBoundingRect().height(),25.0/cv.arrowStart->sceneBoundingRect().height()); 02010 } 02011 curveSegments.append(cv); 02012 } 02013 } 02014 } 02015