00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <QtGui>
00023
00024 #include "itemnode.h"
00025 #include "slatewindow.h"
00026
00027 ItemNode::ItemNode(ItemProperties item, QString _name, SlateWindow *wind, QGraphicsItem * parent, QGraphicsScene * scene): Node(parent, scene),
00028 itemProp(item), numProp(itemProp.getProperties().size()), window(wind), clickedPoint(-1), externalMarkedPoint(-1), markedPoint(-1)
00029 {
00030 myTextColor = Qt::darkGreen;
00031 myOutlineColor = Qt::darkBlue;
00032 myBackgroundColor = Qt::white;
00033
00034 setFlags(ItemIsMovable | ItemIsSelectable);
00035
00036
00037
00038 QFontMetricsF metrics = qApp->font();
00039 outlinerect = metrics.boundingRect(itemProp.getType());
00040
00041 const QList<QString> props = itemProp.getProperties();
00042 for (int i = 0; i < props.size(); i++)
00043 outlinerect |= metrics.boundingRect(props[i]);
00044
00045 outlinerect.adjust(0.0, 0.0, 60.0, props.size()*metrics.lineSpacing());
00046
00047
00048
00049 QRectF rect = outlineRect();
00050 QString nameAndProp(itemProp.getType());
00051 for (int i = 0; i < props.size(); i++)
00052 nameAndProp += "\n" + props[i];
00053
00054 setText(nameAndProp);
00055
00056 type = itemProp.getType();
00057 name = _name;
00058 }
00059
00060 ItemNode::~ItemNode()
00061 {
00062 foreach (Link *link, getLinks())
00063 delete link;
00064 }
00065
00066 void ItemNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * )
00067 {
00068 QPen pen(myOutlineColor);
00069 if (option->state & QStyle::State_Selected) {
00070 pen.setStyle(Qt::DotLine);
00071 pen.setWidth(2);
00072 }
00073 painter->setPen(pen);
00074 painter->setBrush(myBackgroundColor);
00075
00076 QRectF rect = outlineRect();
00077 painter->drawRect(rect);
00078 painter->drawLine((int)rect.left(), (int)rect.top() + 16, (int)rect.right(), (int)rect.top() + 16);
00079
00080 painter->setPen(myTextColor);
00081 painter->drawText(rect, Qt::AlignTop | Qt::AlignHCenter, myText);
00082
00083
00084 painter->setPen(Qt::white);
00085 painter->setBrush(Qt::black);
00086 for (int i = 0; i < numProp; i++)
00087 {
00088 if (itemProp.isInput(i))
00089 painter->drawEllipse((int)rect.left() + 4, (int)rect.top() + 16*i + 20, 8, 8);
00090 if (itemProp.isOutput(i))
00091 painter->drawEllipse((int)rect.right() - 12, (int)rect.top() + 16*i + 20, 8, 8);
00092 }
00093
00094
00095 if (markedPoint >= 0)
00096 {
00097 if (markedValidity) painter->setBrush(Qt::green);
00098 else painter->setBrush(Qt::red);
00099
00100 if (markedPoint < numProp)
00101 painter->drawEllipse((int)rect.left() + 4, (int)rect.top() + 16*markedPoint + 20, 8, 8);
00102 else
00103 painter->drawEllipse((int)rect.right() - 12, (int)rect.top() + 16*(markedPoint - numProp) + 20, 8, 8);
00104 }
00105 }
00106
00107
00108 QPointF ItemNode::scenePointPos(int point) const
00109 {
00110 QRectF rect = outlineRect();
00111
00112 if (point < 0) return this->scenePos();
00113 if (point < numProp) return mapToScene( QPointF(rect.left() + 8, rect.top() + 16*point + 24) );
00114 if (point < 2 * numProp) return mapToScene( QPointF(rect.right() - 8, rect.top() + 16*(point-numProp) + 24) );
00115 return this->scenePos();
00116 }
00117
00118 QPointF ItemNode::scenePointPos(QString name, bool in) const
00119 {
00120 return scenePointPos(propPoint(name, in));
00121 }
00122
00123 void ItemNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
00124 {
00125 window->showProperties(this);
00126 }
00127
00128
00129
00130 void ItemNode::mousePressEvent(QGraphicsSceneMouseEvent * event)
00131 {
00132 clickedPoint = pointAt(event->pos());
00133
00134 if (clickedPoint < 0)
00135 {
00136
00137 Node::mousePressEvent(event);
00138 }
00139 else
00140 {
00141
00142 line = new QGraphicsLineItem( QLineF(event->scenePos(), event->scenePos()) );
00143 line->setZValue(1000);
00144 scene()->addItem(line);
00145 }
00146 }
00147
00148 void ItemNode::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
00149 {
00150 if (clickedPoint < 0)
00151 {
00152
00153 Node::mouseMoveEvent(event);
00154 }
00155 else
00156 {
00157
00158
00159 QLineF shortLine = QLineF(line->line().p1(), event->scenePos());
00160 shortLine.setLength(shortLine.length() - 0.5);
00161 line->setLine(shortLine);
00162
00163
00164 if (externalMarkedPoint >= 0)
00165 {
00166 externalMarkedItem->unmarkPoint();
00167 externalMarkedPoint = -1;
00168 }
00169
00170
00171 ItemNode *target = dynamic_cast<ItemNode *>(scene()->itemAt(event->scenePos()));
00172 if (target)
00173 {
00174
00175 int pointPos = target->pointAt(target->mapFromScene(event->scenePos()));
00176 if (pointPos >= 0)
00177 {
00178 externalMarkedPoint = pointPos;
00179 externalMarkedItem = target;
00180 externalMarkedItem->markPoint(externalMarkedPoint, isValidLink(this, clickedPoint, target, pointPos));
00181 }
00182 }
00183 }
00184 }
00185
00186 void ItemNode::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
00187 {
00188 if (clickedPoint < 0)
00189 {
00190
00191 Node::mouseReleaseEvent(event);
00192 }
00193 else
00194 {
00195
00196 delete(line);
00197
00198
00199 if (externalMarkedPoint >= 0)
00200 {
00201 externalMarkedItem->unmarkPoint();
00202 externalMarkedPoint = -1;
00203 }
00204
00205
00206 ItemNode *target = dynamic_cast<ItemNode *>(scene()->itemAt(event->scenePos()));
00207 if (target)
00208 {
00209
00210 int pointPos = target->pointAt(target->mapFromScene(event->scenePos()));
00211
00212
00213 if ( (pointPos >= 0) && isValidLink(this, clickedPoint, target, pointPos) )
00214 {
00215 if (clickedPoint >= numProp)
00216 {
00217
00218
00219
00220
00221
00222
00223
00224 window->createLink(this, clickedPoint, target, pointPos);
00225 }
00226 else
00227 {
00228
00229
00230
00231
00232
00233
00234
00235 window->createLink(target, pointPos, this, clickedPoint);
00236 }
00237 }
00238 }
00239
00240 clickedPoint = -1;
00241 }
00242 }
00243
00244 void ItemNode::markPoint(int point, bool validity)
00245 {
00246 markedPoint = point;
00247 markedValidity = validity;
00248 update();
00249 }
00250
00251 void ItemNode::unmarkPoint()
00252 {
00253 markedPoint = -1;
00254 update();
00255 }
00256
00257
00259 bool ItemNode::isValidLink(ItemNode *fromNode, int fromPoint, ItemNode *toNode, int toPoint) const
00260 {
00261 int fromNumProp = fromNode->numProp;
00262 int toNumProp = toNode->numProp;
00263
00264 if (fromNode == toNode) return false;
00265 if (fromNode->parentItem() != toNode->parentItem()) return false;
00266 if ( (fromPoint < 0) || (toPoint < 0) ) return false;
00267 if ( (fromPoint < fromNumProp) && (toPoint < toNumProp) ) return false;
00268 if ( (fromPoint >= fromNumProp) && (toPoint >= toNumProp) ) return false;
00269 if ( (fromPoint >= 2 * fromNumProp) || (toPoint >= 2 * toNumProp) ) return false;
00270 return true;
00271 }
00272
00273 int ItemNode::insertPos() const
00274 {
00275 return numProp;
00276 }
00277
00278 void ItemNode::insertProperty(QString name, int type, bool input, bool output)
00279 {
00280 insertProperty(insertPos(), name, type, input, output);
00281 }
00282
00283 void ItemNode::insertProperty(int pos, QString name, int type, bool input, bool output)
00284 {
00285 prepareGeometryChange();
00286 itemProp.insertProperty(pos, name, type, input, output);
00287 numProp = itemProp.getProperties().size();
00288
00289
00290 QFontMetricsF metrics = qApp->font();
00291 outlinerect = metrics.boundingRect(itemProp.getType());
00292
00293 const QList<QString> props = itemProp.getProperties();
00294 for (int i = 0; i < props.size(); i++)
00295 outlinerect |= metrics.boundingRect(props[i]);
00296
00297 outlinerect.adjust(0.0, 0.0, 60.0, props.size()*metrics.lineSpacing());
00298
00299
00300
00301 QRectF rect = outlineRect();
00302 QString nameAndProp(itemProp.getType());
00303 for (int i = 0; i < props.size(); i++)
00304 nameAndProp += "\n" + props[i];
00305
00306 setText(nameAndProp);
00307 updateLinksPos();
00308 update();
00309 }
00310
00311 void ItemNode::removeProperty(QString name)
00312 {
00313 prepareGeometryChange();
00314 itemProp.deleteProperty(name);
00315 numProp = itemProp.getProperties().size();
00316
00317
00318 QFontMetricsF metrics = qApp->font();
00319 outlinerect = metrics.boundingRect(itemProp.getType());
00320
00321 const QList<QString> props = itemProp.getProperties();
00322 for (int i = 0; i < props.size(); i++)
00323 outlinerect |= metrics.boundingRect(props[i]);
00324
00325 outlinerect.adjust(0.0, 0.0, 60.0, props.size()*metrics.lineSpacing());
00326
00327
00328
00329 QRectF rect = outlineRect();
00330 QString nameAndProp(itemProp.getType());
00331 for (int i = 0; i < props.size(); i++)
00332 nameAndProp += "\n" + props[i];
00333
00334 setText(nameAndProp);
00335 updateLinksPos();
00336 update();
00337 }
00338
00339 void ItemNode::deleteProperty(int pos)
00340 {
00341 prepareGeometryChange();
00342 itemProp.deleteProperty(pos);
00343 numProp = itemProp.getProperties().size();
00344
00345
00346 QFontMetricsF metrics = qApp->font();
00347 outlinerect = metrics.boundingRect(itemProp.getType());
00348
00349 const QList<QString> props = itemProp.getProperties();
00350 for (int i = 0; i < props.size(); i++)
00351 outlinerect |= metrics.boundingRect(props[i]);
00352
00353 outlinerect.adjust(0.0, 0.0, 60.0, props.size()*metrics.lineSpacing());
00354
00355
00356
00357 QRectF rect = outlineRect();
00358 QString nameAndProp(itemProp.getType());
00359 for (int i = 0; i < props.size(); i++)
00360 nameAndProp += "\n" + props[i];
00361
00362 setText(nameAndProp);
00363 updateLinksPos();
00364 update();
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374 void ItemNode::delLastProp()
00375 {
00376 prepareGeometryChange();
00377 deleteProperty(numProp - 2);
00378 update();
00379 }
00380
00381 QVariant ItemNode::itemChange(GraphicsItemChange change,
00382 const QVariant &value)
00383 {
00384 if (change == ItemPositionHasChanged)
00385 updateLinksPos();
00386
00387 return QGraphicsItem::itemChange(change, value);
00388 }
00389
00390 void ItemNode::updateLinksPos()
00391 {
00392 foreach (Link *link, getLinks())
00393 link->trackNodes();
00394 }
00395
00396 QRectF ItemNode::outlineRect() const
00397 {
00398 return outlinerect;
00399 }
00400
00401 int ItemNode::roundness(double size) const
00402 {
00403 const int Diameter = 12;
00404 return 100 * Diameter / int(size);
00405 }
00406
00407
00408
00409
00410 int ItemNode::pointAt(QPointF pos) const
00411 {
00412 QRectF rect = outlineRect();
00413 if ((pos.x() >= rect.left() + 4) && (pos.x() <= rect.left() + 12))
00414 {
00415 if (pos.y() - rect.top() >= 20)
00416 {
00417 int relativePos = (int)(pos.y() - rect.top() - 20);
00418 if (relativePos % 16 <= 8)
00419 if (itemProp.isInput(relativePos / 16)) return relativePos / 16;
00420 }
00421 }
00422 else if ((pos.x() >= rect.right() - 12) && (pos.x() <= rect.right() - 4))
00423 {
00424 if (pos.y() - rect.top() >= 20)
00425 {
00426 int relativePos = (int)(pos.y() - rect.top() - 20);
00427 if (relativePos % 16 <= 8)
00428 if (itemProp.isOutput(relativePos / 16)) return (relativePos / 16) + numProp;
00429 }
00430 }
00431 return -1;
00432 }
00433
00434 QString ItemNode::propName(int point) const
00435 {
00436 if ( (point < 0) && (point >= 2 * numProp) ) return QString();
00437
00438 if (point >= numProp) point = point - numProp;
00439 return itemProp.getProperties()[point];
00440 }
00441
00442 int ItemNode::propPoint(QString name, bool in) const
00443 {
00444 int pos = itemProp.getProperties().indexOf(name);
00445 if (pos < 0) return pos;
00446 if (!in) return pos += numProp;
00447 return pos;
00448 }
00449
00450 int ItemNode::propType(int point) const
00451 {
00452 if ( (point < 0) && (point >= 2 * numProp) ) return 0;
00453
00454 if (point >= numProp) point = point - numProp;
00455 return itemProp.propertyType(point);
00456 }
00457
00458