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 lineSpacing = metrics.lineSpacing();
00040 outlinerect = metrics.boundingRect(itemProp.getType());
00041
00042 const QList<QString> props = itemProp.getProperties();
00043 for (int i = 0; i < props.size(); i++)
00044 outlinerect |= metrics.boundingRect(props[i]);
00045
00046 outlinerect.adjust(0.0, 0.0, lineSpacing*4, props.size()*lineSpacing);
00047
00048
00049
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() + lineSpacing), (int)rect.right(), (int)(rect.top() + lineSpacing));
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() + lineSpacing*0.25), (int)(rect.top() + lineSpacing*(i + 1.25)), (int)(lineSpacing*0.5), (int)(lineSpacing*0.5));
00090 if (itemProp.isOutput(i))
00091 painter->drawEllipse((int)(rect.right() - lineSpacing*0.75), (int)(rect.top() + lineSpacing*(i + 1.25)), (int)(lineSpacing*0.5), (int)(lineSpacing*0.5));
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() + lineSpacing*0.25), (int)(rect.top() + lineSpacing*(markedPoint + 1.25)), (int)(lineSpacing*0.5), (int)(lineSpacing*0.5));
00102 else
00103 painter->drawEllipse((int)(rect.right() - lineSpacing*0.75), (int)(rect.top() + lineSpacing*(markedPoint - numProp + 1.25)), (int)(lineSpacing*0.5), (int)(lineSpacing*0.5));
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() + lineSpacing*0.5, rect.top() + lineSpacing*(point + 1.5)) );
00114 if (point < 2 * numProp) return mapToScene( QPointF(rect.right() - lineSpacing*0.5, rect.top() + lineSpacing*(point-numProp + 1.5)) );
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
00124 int ItemNode::numProps() const
00125 {
00126 return numProp;
00127 }
00128
00129
00130 void ItemNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
00131 {
00132 window->showProperties(this);
00133 }
00134
00135
00136
00137 void ItemNode::mousePressEvent(QGraphicsSceneMouseEvent * event)
00138 {
00139 clickedPoint = pointAt(event->pos());
00140
00141 if (clickedPoint < 0)
00142 {
00143
00144 Node::mousePressEvent(event);
00145 }
00146 else
00147 {
00148
00149 line = new QGraphicsLineItem( QLineF(event->scenePos(), event->scenePos()) );
00150 line->setZValue(1000);
00151 scene()->addItem(line);
00152 }
00153 }
00154
00155 void ItemNode::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
00156 {
00157 if (clickedPoint < 0)
00158 {
00159
00160 Node::mouseMoveEvent(event);
00161 }
00162 else
00163 {
00164
00165
00166 QLineF shortLine = QLineF(line->line().p1(), event->scenePos());
00167 shortLine.setLength(shortLine.length() - 0.5);
00168 line->setLine(shortLine);
00169
00170
00171 if (externalMarkedPoint >= 0)
00172 {
00173 externalMarkedItem->unmarkPoint();
00174 externalMarkedPoint = -1;
00175 }
00176
00177
00178 ItemNode *target = dynamic_cast<ItemNode *>(scene()->itemAt(event->scenePos()));
00179 if (target)
00180 {
00181
00182 int pointPos = target->pointAt(target->mapFromScene(event->scenePos()));
00183 if (pointPos >= 0)
00184 {
00185 externalMarkedPoint = pointPos;
00186 externalMarkedItem = target;
00187 externalMarkedItem->markPoint(externalMarkedPoint, isValidLink(this, clickedPoint, target, pointPos));
00188 }
00189 }
00190 }
00191 }
00192
00193 void ItemNode::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
00194 {
00195 if (clickedPoint < 0)
00196 {
00197
00198 Node::mouseReleaseEvent(event);
00199 }
00200 else
00201 {
00202
00203 delete(line);
00204
00205
00206 if (externalMarkedPoint >= 0)
00207 {
00208 externalMarkedItem->unmarkPoint();
00209 externalMarkedPoint = -1;
00210 }
00211
00212
00213 ItemNode *target = dynamic_cast<ItemNode *>(scene()->itemAt(event->scenePos()));
00214 if (target)
00215 {
00216
00217 int pointPos = target->pointAt(target->mapFromScene(event->scenePos()));
00218
00219
00220 if ( (pointPos >= 0) && isValidLink(this, clickedPoint, target, pointPos) )
00221 {
00222 if (clickedPoint >= numProp)
00223 window->createLink(this, clickedPoint, target, pointPos);
00224 else
00225 window->createLink(target, pointPos, this, clickedPoint);
00226 }
00227 }
00228
00229 clickedPoint = -1;
00230 }
00231 }
00232
00233 void ItemNode::markPoint(int point, bool validity)
00234 {
00235 markedPoint = point;
00236 markedValidity = validity;
00237 update();
00238 }
00239
00240 void ItemNode::unmarkPoint()
00241 {
00242 markedPoint = -1;
00243 update();
00244 }
00245
00246
00248 bool ItemNode::isValidLink(ItemNode *fromNode, int fromPoint, ItemNode *toNode, int toPoint) const
00249 {
00250 int fromNumProp = fromNode->numProp;
00251 int toNumProp = toNode->numProp;
00252
00253 if (fromNode == toNode) return false;
00254 if (fromNode->parentItem() != toNode->parentItem()) return false;
00255 if ( (fromPoint < 0) || (toPoint < 0) ) return false;
00256 if ( (fromPoint < fromNumProp) && (toPoint < toNumProp) ) return false;
00257 if ( (fromPoint >= fromNumProp) && (toPoint >= toNumProp) ) return false;
00258 if ( (fromPoint >= 2 * fromNumProp) || (toPoint >= 2 * toNumProp) ) return false;
00259 return true;
00260 }
00261
00262 int ItemNode::insertPos() const
00263 {
00264 return numProp;
00265 }
00266
00267 void ItemNode::insertProperty(QString name, int type, bool input, bool output)
00268 {
00269 insertProperty(insertPos(), name, type, input, output);
00270 }
00271
00272 void ItemNode::insertProperty(int pos, QString name, int type, bool input, bool output)
00273 {
00274 prepareGeometryChange();
00275 itemProp.insertProperty(pos, name, type, input, output);
00276 numProp = itemProp.getProperties().size();
00277
00278
00279 QFontMetricsF metrics = qApp->font();
00280 lineSpacing = metrics.lineSpacing();
00281 outlinerect = metrics.boundingRect(itemProp.getType());
00282
00283 const QList<QString> props = itemProp.getProperties();
00284 for (int i = 0; i < props.size(); i++)
00285 outlinerect |= metrics.boundingRect(props[i]);
00286
00287 outlinerect.adjust(0.0, 0.0, lineSpacing*4, props.size()*metrics.lineSpacing());
00288
00289
00290
00291 QRectF rect = outlineRect();
00292 QString nameAndProp(itemProp.getType());
00293 for (int i = 0; i < props.size(); i++)
00294 nameAndProp += "\n" + props[i];
00295
00296 setText(nameAndProp);
00297 updateLinksPos();
00298 update();
00299 }
00300
00301 void ItemNode::removeProperty(QString name)
00302 {
00303 prepareGeometryChange();
00304 itemProp.deleteProperty(name);
00305 numProp = itemProp.getProperties().size();
00306
00307
00308 QFontMetricsF metrics = qApp->font();
00309 lineSpacing = metrics.lineSpacing();
00310 outlinerect = metrics.boundingRect(itemProp.getType());
00311
00312 const QList<QString> props = itemProp.getProperties();
00313 for (int i = 0; i < props.size(); i++)
00314 outlinerect |= metrics.boundingRect(props[i]);
00315
00316 outlinerect.adjust(0.0, 0.0, lineSpacing*4, props.size()*metrics.lineSpacing());
00317
00318
00319
00320 QRectF rect = outlineRect();
00321 QString nameAndProp(itemProp.getType());
00322 for (int i = 0; i < props.size(); i++)
00323 nameAndProp += "\n" + props[i];
00324
00325 setText(nameAndProp);
00326 updateLinksPos();
00327 update();
00328 }
00329
00330 void ItemNode::deleteProperty(int pos)
00331 {
00332 prepareGeometryChange();
00333 itemProp.deleteProperty(pos);
00334 numProp = itemProp.getProperties().size();
00335
00336
00337 QFontMetricsF metrics = qApp->font();
00338 lineSpacing = metrics.lineSpacing();
00339 outlinerect = metrics.boundingRect(itemProp.getType());
00340
00341 const QList<QString> props = itemProp.getProperties();
00342 for (int i = 0; i < props.size(); i++)
00343 outlinerect |= metrics.boundingRect(props[i]);
00344
00345 outlinerect.adjust(0.0, 0.0, lineSpacing*4, props.size()*metrics.lineSpacing());
00346
00347
00348
00349 QRectF rect = outlineRect();
00350 QString nameAndProp(itemProp.getType());
00351 for (int i = 0; i < props.size(); i++)
00352 nameAndProp += "\n" + props[i];
00353
00354 setText(nameAndProp);
00355 updateLinksPos();
00356 update();
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366 void ItemNode::delLastProp()
00367 {
00368 prepareGeometryChange();
00369 deleteProperty(numProp - 2);
00370 update();
00371 }
00372
00373 QVariant ItemNode::itemChange(GraphicsItemChange change,
00374 const QVariant &value)
00375 {
00376 if (change == ItemPositionHasChanged)
00377 updateLinksPos();
00378
00379 return QGraphicsItem::itemChange(change, value);
00380 }
00381
00382 void ItemNode::updateLinksPos()
00383 {
00384 foreach (Link *link, getLinks())
00385 link->trackNodes();
00386 }
00387
00388 QRectF ItemNode::outlineRect() const
00389 {
00390 return outlinerect;
00391 }
00392
00393 int ItemNode::roundness(double size) const
00394 {
00395 const int Diameter = 12;
00396 return 100 * Diameter / int(size);
00397 }
00398
00399
00400
00401
00402 int ItemNode::pointAt(QPointF pos) const
00403 {
00404 QRectF rect = outlineRect();
00405 if ((pos.x() >= rect.left() + lineSpacing*0.25) && (pos.x() <= rect.left() + lineSpacing*0.75))
00406 {
00407 if (pos.y() - rect.top() >= lineSpacing*1.25)
00408 {
00409 int relativePos = (int)(pos.y() - rect.top() - lineSpacing*1.25);
00410 if (relativePos % (int)lineSpacing <= lineSpacing*0.5)
00411 if (itemProp.isInput((int)(relativePos / lineSpacing))) return (int)(relativePos / lineSpacing);
00412 }
00413 }
00414 else if ((pos.x() >= rect.right() - lineSpacing*0.75) && (pos.x() <= rect.right() - lineSpacing*0.25))
00415 {
00416 if (pos.y() - rect.top() >= lineSpacing*1.25)
00417 {
00418 int relativePos = (int)(pos.y() - rect.top() - lineSpacing*1.25);
00419 if (relativePos % (int)lineSpacing <= lineSpacing*0.5)
00420 if (itemProp.isOutput((int)(relativePos / lineSpacing))) return (int)(relativePos / lineSpacing + numProp);
00421 }
00422 }
00423 return -1;
00424 }
00425
00426 QString ItemNode::propName(int point) const
00427 {
00428 if ( (point < 0) && (point >= 2 * numProp) ) return QString();
00429
00430 if (point >= numProp) point = point - numProp;
00431 return itemProp.getProperties()[point];
00432 }
00433
00434 int ItemNode::propPoint(QString name, bool in) const
00435 {
00436 int pos = itemProp.getProperties().indexOf(name);
00437 if (pos < 0) return pos;
00438 if (!in) return pos += numProp;
00439 return pos;
00440 }
00441
00442 int ItemNode::propType(int point) const
00443 {
00444 if ( (point < 0) && (point >= 2 * numProp) ) return 0;
00445
00446 if (point >= numProp) point = point - numProp;
00447 return itemProp.propertyType(point);
00448 }
00449
00450