nodeeditor_doxy
|
00001 #include <QGraphicsScene> 00002 #include <QGraphicsSceneMouseEvent> 00003 #include <QPainter> 00004 #include <QStyleOption> 00005 //dw 00006 #include <QPointF> 00007 #include <QSize> 00008 #include <QGraphicsWidget> 00009 00010 //#include "edge.h" 00011 #include "nodeconnector.h" 00012 //#include "NodeItem.h" 00013 //#include "graphwidget.h" 00014 NodeConnector::~NodeConnector() { 00015 this->deleteConnections(); 00016 //dw super class destructor should do this, right? 00017 if (scene() != NULL) { 00018 this->scene()->removeItem(this); 00019 } 00020 } 00021 00022 NodeConnector::NodeConnector(NodeItem *parent1, QGraphicsScene *scene1, /*QLabel*/QWidget* widget, NodeConnector::ConnectorType conType1, const ConnectorAlignment connectorAlignment, bool singleConnection, bool disableWidgetOnConnection, int radius, bool selfConnections) 00023 //dw666 orig: 00024 : QGraphicsItem(parent1, scene1), 00025 //: QGraphicsItem(NULL, scene1), 00026 mConnectorType(conType1), parent(parent1), mWidget(widget), mConnectorAlignment(connectorAlignment), mSingleConnection(singleConnection), mDisableWidgetOnConnection(disableWidgetOnConnection), mSelfConnections(selfConnections), mRadius(radius) 00027 { 00028 //orig 00029 //setFlag(ItemIsMovable); 00030 //dw new4: is this a problem? check it 00031 setCacheMode(DeviceCoordinateCache); 00032 00033 //dw new: setZValue(1); 00034 setZValue(2); 00035 00036 //dw667: new try 00037 updatePosition(); 00038 00039 //setFlag(QGraphicsItem::ItemIsSelectable, true); 00040 00041 if (conType1 == ConnectorType::In) { 00042 darkColor = QColor(Qt::darkYellow); 00043 } 00044 else if (conType1 == ConnectorType::Out) { 00045 darkColor = QColor(Qt::darkRed).light(80); 00046 } 00047 else { 00048 darkColor = QColor(Qt::darkGreen); 00049 } 00050 highlight = false; 00051 } 00052 00053 //dw667 backmerge: was active 00054 /* 00055 void NodeConnector::updatePositionGeometry() { 00056 //prepareGeometryChange(); 00057 updatePosition(); 00058 foreach (NodeConnection *c, this->arrows) { 00059 //dw problem: label already deleted but connector tries to enable it? 00060 //c->paint(painter, option, w); 00061 c->updatePositionGeometry(); 00062 } 00063 update(); 00064 } 00065 */ 00066 00067 void NodeConnector::updatePosition() { 00068 this->prepareGeometryChange(); 00069 00070 //if we dont have parent, stay where we are 00071 if (parent == NULL || mWidget == NULL) { 00072 return; 00073 } 00074 00075 QPointF pPos = parent->pos(); 00076 //dw temp quick fix for refactoring 00077 QPointF newPos = pPos; 00078 00079 //dw FIXME: need to adapt to different partner classes? should ask parent about position? 00080 /* 00081 QSize widgetSize = mWidget->boundingRect(); 00082 //dw677: 00083 //QSizeF widgetSize = parent->boundingRect(); 00084 //radius = labelSize.height()/2; 00085 00086 QPointF newPos; 00087 if (connectorAlignment() == NodeConnector::Left) { 00088 newPos.setX(-mRadius); 00089 //newPos.setY(mWidget->pos().y() + widgetSize.height()/2.0); 00090 //dw677: 00091 //newPos.setY(parent->pos().y() + widgetSize.height()/2.0); 00092 //newPos.setY(mWidget->pos().y() + mWidget->boundingRect().height()/2.0); 00093 //newPos.setY(mWidget->pos().y() + mWidget->boundingRect().height()/2.0); 00094 //newPos.setY(mWidget->pos().y() + mWidget->height()/2.0); 00095 newPos.setY(parent->subWidgetRect(mWidget).y() + parent->subWidgetRect(mWidget).height()/2.0); 00096 } 00097 else if (connectorAlignment() == NodeConnector::Right) { 00098 //seems to be to big 00099 //newPos.setX(parent->boundingsize().width()+mRadius+1); 00100 //seems to be size of content??? too small 00101 //newPos.setX(parent->window()->boundingRect().width()+mRadius+1); 00102 //float rightx = dynamic_cast<NodeItem*>(parent)->widget()->width() 00103 // + mRadius + 1; 00104 //float rightx = dynamic_cast<NodeItem*>(parent)->widget()->geometry().size().width() 00105 // + mRadius + 1; 00106 /* 00107 float rightx = dynamic_cast<NodeItem*>(parent)->widget()->width() 00108 + dynamic_cast<NodeItem*>(parent)->widget()->baseSize().width() 00109 + mRadius + 1; 00110 */ 00111 /* 00112 //dw FIXME: ugly 00113 newPos.setX(parent->boundingRect().width() + mRadius); 00114 //newPos.setY(mWidget->pos().y()+ widgetSize.height()/2.0); 00115 newPos.setY(parent->subWidgetRect(mWidget).y()+ parent->subWidgetRect(mWidget).height()/2.0); 00116 } 00117 else if (connectorAlignment() == NodeConnector::Bottom) { 00118 //newPos.setX(mWidget->pos().x() + widgetSize.width()/2.0); 00119 newPos.setX(parent->subWidgetRect(mWidget).x() + parent->subWidgetRect(mWidget).width()/2.0); 00120 00121 //newPos.setY(parent->widget()->boundingRect().height() + mRadius); 00122 //newPos.setY(parent->boundingsize().height() + mRadius); 00123 newPos.setY(parent->boundingRect().height() + mRadius); 00124 } 00125 else if (connectorAlignment() == NodeConnector::Top) { 00126 //newPos.setX(mWidget->pos().x() + widgetSize.width()/2.0); 00127 newPos.setX(parent->subWidgetRect(mWidget).x() + parent->subWidgetRect(mWidget).width()/2.0); 00128 newPos.setY(-mRadius); 00129 } 00130 */ 00131 00132 this->setPos(newPos); 00133 //dw seems to always paint -> is already called from update? or will cause updatePos in next frame again? 00134 //update(); 00135 00136 foreach (NodeConnection *c, this->arrows) { 00137 //dw problem: label already deleted but connector tries to enable it? 00138 //c->paint(painter, option, w); 00139 c->updatePosition(); 00140 } 00141 update(); 00142 } 00143 00144 /* 00145 void NodeConnector::addEdge(Edge *edge) 00146 { 00147 edgeList << edge; 00148 edge->adjust(); 00149 } 00150 00151 QList<Edge *> NodeConnector::edges() const 00152 { 00153 return edgeList; 00154 } 00155 00156 void NodeConnector::calculateForces() 00157 { 00158 if (!scene() || scene()->mouseGrabberItem() == this) { 00159 newPos = pos(); 00160 return; 00161 } 00162 00163 // Sum up all forces pushing this item away 00164 qreal xvel = 0; 00165 qreal yvel = 0; 00166 foreach (QGraphicsItem *item, scene()->items()) { 00167 NodeConnector *node = qgraphicsitem_cast<NodeConnector *>(item); 00168 if (!node) 00169 continue; 00170 00171 QLineF line(mapFromItem(node, 0, 0), QPointF(0, 0)); 00172 qreal dx = line.dx(); 00173 qreal dy = line.dy(); 00174 double l = 2.0 * (dx * dx + dy * dy); 00175 if (l > 0) { 00176 xvel += (dx * 150.0) / l; 00177 yvel += (dy * 150.0) / l; 00178 } 00179 } 00180 00181 // Now subtract all forces pulling items together 00182 double weight = (edgeList.size() + 1) * 10; 00183 foreach (Edge *edge, edgeList) { 00184 QPointF pos; 00185 if (edge->sourceNodeConnector() == this) 00186 pos = mapFromItem(edge->destNodeConnector(), 0, 0); 00187 else 00188 pos = mapFromItem(edge->sourceNodeConnector(), 0, 0); 00189 xvel += pos.x() / weight; 00190 yvel += pos.y() / weight; 00191 } 00192 00193 if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1) 00194 xvel = yvel = 0; 00195 00196 QRectF sceneRect = scene()->scenesize(); 00197 newPos = pos() + QPointF(xvel, yvel); 00198 newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10)); 00199 newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10)); 00200 } 00201 00202 bool NodeConnector::advance() 00203 { 00204 if (newPos == pos()) 00205 return false; 00206 00207 setPos(newPos); 00208 return true; 00209 }*/ 00210 00211 void NodeConnector::setHighlight(bool highlight) { 00212 prepareGeometryChange(); 00213 this->highlight = highlight; 00214 this->updatePosition(); 00215 this->update(); 00216 } 00217 00218 00219 QRectF NodeConnector::boundingRect() const 00220 { 00221 qreal adjust = 1; 00222 return QRectF(-mRadius - adjust, -mRadius - adjust, 00223 2*(mRadius + adjust), 2*(mRadius + adjust)); 00224 00225 //dw new 00226 //return QGraphicsItem::boundingsize(); 00227 } 00228 00229 00230 QPainterPath NodeConnector::shape() const 00231 { 00232 00233 QPainterPath path; 00234 path.addEllipse(-mRadius, -mRadius, 2*mRadius, 2*mRadius); 00235 return path; 00236 00237 //dw new 00238 //return QGraphicsItem::shape(); 00239 00240 //dw new2 00241 /* 00242 QPainterPath path; 00243 path.addRect(boundingsize()); 00244 return path; 00245 */ 00246 } 00247 00248 00249 void NodeConnector::debugPaint(QPainter *painter) { 00250 //dw debug 00251 static int i = 0, j=0, k=0; 00252 painter->fillRect(boundingRect(), /*Qt::green*/ QColor(i=(i+19)%256 , j=(j+51)%256, k=(k+11)%256)); // to see item. 00253 } 00254 00255 00256 void NodeConnector::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget* w) 00257 { 00258 Q_UNUSED(option); 00259 Q_UNUSED(w); 00260 00261 //dw 699: 00262 painter->setRenderHint(QPainter::Antialiasing); 00263 00264 if (static_cast<DiagramScene*>(scene())->isDebugDraw()) { 00265 debugPaint(painter); 00266 } 00267 00268 painter->setPen(Qt::NoPen); 00269 painter->setBrush(Qt::darkGray); 00270 //painter->drawEllipse(-mRadius*0.8, -mRadius*0.8, mRadius, mRadius); 00271 //painter->drawEllipse(0, 0, 2*mRadius, 2*mRadius); 00272 QRadialGradient gradient(-mRadius/2, -mRadius/2, mRadius); 00273 if (/*option->state & QStyle::State_Sunken*/ highlight) { 00274 gradient.setCenter(mRadius/2, mRadius/2); 00275 gradient.setFocalPoint(mRadius/2, mRadius/2); 00276 //gradient.setColorAt(1, QColor(Qt::yellow).light(120)); 00277 //gradient.setColorAt(0, QColor(Qt::darkYellow).light(120)); 00278 gradient.setColorAt(1, darkColor.light(240)); 00279 gradient.setColorAt(0, darkColor.light(120)); 00280 } else { 00281 //gradient.setColorAt(0, Qt::yellow); 00282 //gradient.setColorAt(1, Qt::darkYellow); 00283 gradient.setColorAt(0, darkColor.light(240)); 00284 gradient.setColorAt(1, darkColor); 00285 } 00286 painter->setBrush(gradient); 00287 painter->setPen(QPen(Qt::black, 0)); 00288 //painter->drawEllipse(-mRadius, -mRadius, mRadius, mRadius); 00289 painter->drawEllipse(-mRadius, -mRadius, 2*mRadius, 2*mRadius); 00290 00291 //dw new2, is abstract 00292 //QGraphicsItem::paint(painter, option, w); 00293 00294 /* 00295 //dw hacky, good idea?? 00296 NodeConnection* a; 00297 a->p 00298 foreach(NodeConnection* a, arrows) { 00299 a->paint(painter, option, NULL); 00300 } 00301 */ 00302 00303 /* 00304 painter->drawEllipse(-7, -7, 20, 20); 00305 QRadialGradient gradient(-3, -3, 10); 00306 if (option->state & QStyle::State_Sunken) { 00307 gradient.setCenter(3, 3); 00308 gradient.setFocalPoint(3, 3); 00309 gradient.setColorAt(1, QColor(Qt::yellow).light(120)); 00310 gradient.setColorAt(0, QColor(Qt::darkYellow).light(120)); 00311 } else { 00312 gradient.setColorAt(0, Qt::yellow); 00313 gradient.setColorAt(1, Qt::darkYellow); 00314 } 00315 painter->setBrush(gradient); 00316 painter->setPen(QPen(Qt::black, 0)); 00317 painter->drawEllipse(-10, -10, 20, 20); 00318 */ 00319 } 00320 00321 //QVariant NodeConnector::itemChange(GraphicsItemChange change, const QVariant &value) 00322 //{ 00323 /* 00324 switch (change) { 00325 case ItemPositionHasChanged: 00326 // foreach (Edge *edge, edgeList) 00327 // edge->adjust(); 00328 // graph->itemMoved(); 00329 break; 00330 default: 00331 break; 00332 }; 00333 */ 00334 00335 // return QGraphicsItem::itemChange(change, value); 00336 //} 00337 00338 void NodeConnector::mousePressEvent(QGraphicsSceneMouseEvent *event) 00339 { 00340 //highlight = true; 00341 update(); 00342 QGraphicsItem::mousePressEvent(event); 00343 } 00344 00345 void NodeConnector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) 00346 { 00347 setHighlight(false); 00348 //highlight = false; 00349 //update(); 00350 QGraphicsItem::mouseReleaseEvent(event); 00351 } 00352 00353 /* 00354 //not called, does the event exist for this class??? 00355 void NodeConnector::mouseOverEvent(QGraphicsSceneMouseEvent *event) 00356 { 00357 highlight = true; 00358 update(); 00359 //QGraphicsItem::mouseOverEvent(event); 00360 } 00361 */ 00362 00363 void NodeConnector::addConnection(NodeConnection *arrow) 00364 { 00365 if (mSingleConnection && arrows.count() > 0) { 00366 //delete arrows.first(); 00367 //arrows.clear(); 00368 deleteConnections(); 00369 } 00370 00371 if (mDisableWidgetOnConnection) { 00372 mWidget->setEnabled(false); 00373 } 00374 00375 arrows.append(arrow); 00376 } 00377 00378 void NodeConnector::deleteConnection(NodeConnection *arrow) 00379 { 00380 //TODO: how to handle deletion exactly, when to emit signals 00381 //arrow->startConnector()->arrows.removeOne(arrow); 00382 //arrow->endConnector()->arrows.removeOne(arrow); 00383 00384 //deleting arrow will also remove it from this connector 00385 //dw new 00386 //arrow->setParentItem(NULL); 00387 delete arrow; 00388 //arrows removed during connection destruction, but attached outside => bad idea 00389 } 00390 00391 /* removes a connection, but does not delete it*/ 00392 void NodeConnector::removeConnection(NodeConnection *connection) { 00393 arrows.removeOne(connection); 00394 if (mDisableWidgetOnConnection && mWidget != NULL && arrows.count() == 0) { 00395 mWidget->setEnabled(true); 00396 } 00397 } 00398 00399 void NodeConnector::deleteConnections() 00400 { 00401 foreach(NodeConnection* arrow, arrows) { 00402 deleteConnection(arrow); 00403 } 00404 } 00405 00406 void NodeConnector::removeWidget() { 00407 mWidget = NULL; 00408 parent = NULL; 00409 } 00410 00411 /* 00412 void NodeConnector::enterEvent ( QEvent * event ) { 00413 highlight = true; 00414 //QGraphicsItem::enterEvent(event); 00415 } 00416 */ 00417 00418 //dw new3 00419 void NodeConnector::update(const QRectF & rect) { 00420 00421 //dw new3: why do ourself 00422 foreach (NodeConnection *c, this->arrows) { 00423 //dw problem: label already deleted but connector tries to enable it? 00424 //c->paint(painter, option, w); 00425 c->update(rect); 00426 } 00427 00428 QGraphicsItem::update(rect); 00429 }