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 "groupnode.h"
00025 #include <QGraphicsSceneDragDropEvent>
00026 #include <iostream>
00027 #include "grouplink.h"
00028
00029
00030 uint GroupNode::maxId = 0;
00031
00032 GroupNode::GroupNode(QString _name, SlateWindow *wind, QGraphicsItem * parent, QGraphicsScene * scene): Node(_name, wind, parent, scene), abstractPaint(false)
00033 {
00034 myTextColor = Qt::darkGreen;
00035 myOutlineColor = Qt::darkBlue;
00036 myBackgroundColor = Qt::white;
00037
00038 QFontMetricsF metrics = qApp->font();
00039 lineSpacing = metrics.lineSpacing();
00040
00041 setFlags(ItemIsMovable | ItemIsSelectable);
00042
00043 type = "Group";
00044 if (_name.isEmpty()) name = type;
00045 else name = _name;
00046 id = getNewId();
00047 }
00048
00049 GroupNode::~GroupNode()
00050 {
00051
00052 foreach (Link *interLink, internalLinks.keys()) {
00053 Link *exterLink = internalLinks.value(interLink);
00054 if (exterLink) {
00055 if (exterLink->toNode() == this)
00056 exterLink->changeToPoint(interLink->toNode(), interLink->toProp());
00057 else
00058 exterLink->changeFromPoint(interLink->fromNode(), interLink->fromProp());
00059 }
00060 delete interLink;
00061 }
00062
00063
00064 prepareGeometryChange();
00065 foreach (QGraphicsItem *child, children()) {
00066 child->setParentItem(this->parentItem());
00067 if (!this->parentItem()) {
00068 child->scale(1.0 / SUBSCALE, 1.0 / SUBSCALE);
00069 child->setPos(child->pos() / SUBSCALE);
00070 }
00071 if (dynamic_cast<Node *>(child))
00072 ((Node *)child)->setHide(false);
00073 }
00074 update();
00075 }
00076
00077 void GroupNode::addNode(Node *node)
00078 {
00079 node->setParentItem(this);
00080 node->scale(SUBSCALE, SUBSCALE);
00081 node->setPos(node->pos() * SUBSCALE);
00082
00083
00084 foreach(Link *link, node->getInLinks()) {
00085 changeLinkToGroup(link, true);
00086 }
00087
00088
00089 foreach(Link *link, node->getOutLinks()) {
00090 changeLinkToGroup(link, false);
00091 }
00092 }
00093
00094 void GroupNode::changeLinkToGroup(Link *link, bool toNode)
00095 {
00096 Node *addedNode = (toNode) ? link->toNode() : link->fromNode();
00097 Node *linkedNode = (toNode) ? link->fromNode() : link->toNode();
00098 QString addedNodeProp = (toNode) ? link->toProp() : link->fromProp();
00099 QString linkedNodeProp = (toNode) ? link->fromProp() : link->toProp();
00100
00101 bool isGroup = (dynamic_cast<GroupNode*>(addedNode)) ? true : false;
00102 if ( (isGroup) && (((GroupNode*)addedNode)->internalLinks.contains(link)) ) return;
00103
00104
00105
00106 if (linkedNode != this) {
00107 int nodePos = addedNode->itemProp.getProperties().indexOf(addedNodeProp);
00108 QString thisNameProp = ( (isGroup) ? QString("") : QString("%1: ").arg(addedNode->getId()) ) + addedNodeProp;
00109
00110 insertProperty(thisNameProp, addedNode->itemProp.propertyType(nodePos), toNode, !toNode);
00111 if (toNode) {
00112 internalLinks.insert(new GroupLink(this, thisNameProp, addedNode, addedNodeProp, true, 0, scene()), link);
00113 link->changeToPoint(this, thisNameProp);
00114 }
00115 else {
00116 internalLinks.insert(new GroupLink(addedNode, addedNodeProp, this, thisNameProp, false, 0, scene()), link);
00117 link->changeFromPoint(this, thisNameProp);
00118 }
00119 }
00120 else {
00121
00122 Link *interLink = internalLinks.key(link);
00123 if (interLink) {
00124 if (toNode) {
00125 link->changeFromPoint(interLink->fromNode(), interLink->fromProp());
00126 internalLinks.remove(interLink);
00127 removeProperty(interLink->toProp());
00128 delete interLink;
00129 }
00130 else {
00131 link->changeToPoint(interLink->toNode(), interLink->toProp());
00132 internalLinks.remove(interLink);
00133 removeProperty(interLink->fromProp());
00134 delete interLink;
00135 }
00136 }
00137
00138 }
00139 }
00140
00141 void GroupNode::removeLink(Link *link)
00142 {
00143 Node::removeLink(link);
00144
00145 if (internalLinks.contains(link)) {
00146 internalLinks.remove(link);
00147 }
00148 if (internalLinks.values().contains(link)) {
00149 internalLinks[internalLinks.key(link)] = NULL;
00150 }
00151 }
00152
00153 void GroupNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
00154 {
00155
00156
00157 if (abstractPaint)
00158 paintProps(painter, option, widget);
00159 else
00160 paintGroup(painter, option, widget);
00161 }
00162
00163 void GroupNode::paintProps(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * )
00164 {
00165 QPen pen(myOutlineColor);
00166 if (option->state & QStyle::State_Selected) {
00167 pen.setStyle(Qt::DotLine);
00168 pen.setWidth(2);
00169 }
00170 painter->setPen(pen);
00171 painter->setBrush(myBackgroundColor);
00172
00173 QRectF rect = outlineRect();
00174 painter->drawRoundRect(rect.adjusted(0.0, lineSpacing-2, 0.0, 0.0), roundness(rect.width()),
00175 roundness(rect.height()));
00176
00177 painter->setPen(myTextColor);
00178 painter->drawText(rect, Qt::AlignTop, name);
00179 painter->drawText(rect.adjusted(0.0, lineSpacing, 0.0, 0.0), Qt::AlignTop | Qt::AlignHCenter, myText);
00180
00181
00182 QRectF arrowRect((int)rect.right() - 15, (int)rect.bottom() - 10, 13, 8);
00183 drawCurvArrow(arrowRect, painter);
00184
00185
00186 painter->setPen(Qt::white);
00187 painter->setBrush(Qt::black);
00188 for (int i = 0; i < numProp; i++) {
00189 if (itemProp.isInput(i))
00190 painter->drawEllipse((int)(rect.left() + lineSpacing*0.1), (int)(rect.top() + lineSpacing*(i + 1.1)), (int)(lineSpacing*0.8), (int)(lineSpacing*0.8));
00191 if (itemProp.isOutput(i))
00192 painter->drawEllipse((int)(rect.right() - lineSpacing*0.9), (int)(rect.top() + lineSpacing*(i + 1.1)), (int)(lineSpacing*0.8), (int)(lineSpacing*0.8));
00193 }
00194
00195
00196 if (markedPoint >= 0) {
00197 if (markedValidity) painter->setBrush(Qt::green);
00198 else painter->setBrush(Qt::red);
00199
00200 if (markedPoint < numProp)
00201 painter->drawEllipse((int)(rect.left() + lineSpacing*0.1), (int)(rect.top() + lineSpacing*(markedPoint + 1.1)), (int)(lineSpacing*0.8), (int)(lineSpacing*0.8));
00202 else
00203 painter->drawEllipse((int)(rect.right() - lineSpacing*0.9), (int)(rect.top() + lineSpacing*(markedPoint - numProp + 1.1)), (int)(lineSpacing*0.8), (int)(lineSpacing*0.8));
00204 }
00205 }
00206
00207 void GroupNode::paintGroup(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * )
00208 {
00209 QPen pen(myOutlineColor);
00210 if (option->state & QStyle::State_Selected) {
00211 pen.setStyle(Qt::DotLine);
00212 pen.setWidth(2);
00213 }
00214 painter->setPen(pen);
00215 painter->setBrush(myBackgroundColor);
00216
00217 QRectF rect = outlineRect();
00218 painter->drawRoundRect(rect.adjusted(0.0, lineSpacing-2, 0.0, .0), roundness(rect.width()),
00219 roundness(rect.height()));
00220
00221 painter->setPen(myTextColor);
00222 painter->drawText(rect, Qt::AlignTop, name);
00223
00224
00225 QRectF arrowRect((int)rect.right() - 15, (int)rect.bottom() - 10, 13, 8);
00226 drawCurvArrow(arrowRect, painter);
00227
00228
00229 painter->setPen(Qt::white);
00230 painter->setBrush(Qt::black);
00231 for (int i = 0; i < numProp; i++) {
00232 if (itemProp.isInput(i))
00233 painter->drawEllipse((int)(rect.left() + lineSpacing*0.1), (int)(rect.top() + lineSpacing*(i + 1.1)), (int)(lineSpacing*0.8), (int)(lineSpacing*0.8));
00234 if (itemProp.isOutput(i))
00235 painter->drawEllipse((int)(rect.right() - lineSpacing*0.9), (int)(rect.top() + lineSpacing*(i + 1.1)), (int)(lineSpacing*0.8), (int)(lineSpacing*0.8));
00236 }
00237
00238
00239 if (markedPoint >= 0) {
00240 if (markedValidity) painter->setBrush(Qt::green);
00241 else painter->setBrush(Qt::red);
00242
00243 if (markedPoint < numProp)
00244 painter->drawEllipse((int)(rect.left() + lineSpacing*0.1), (int)(rect.top() + lineSpacing*(markedPoint + 1.1)), (int)(lineSpacing*0.8), (int)(lineSpacing*0.8));
00245 else
00246 painter->drawEllipse((int)(rect.right() - lineSpacing*0.9), (int)(rect.top() + lineSpacing*(markedPoint - numProp + 1.1)), (int)(lineSpacing*0.8), (int)(lineSpacing*0.8));
00247 }
00248
00249
00250
00251
00252
00253
00254 }
00255
00256 void GroupNode::drawCurvArrow(const QRectF rect, QPainter *painter)
00257 {
00258 QRectF smallCurveRect = QRectF(rect.x(), rect.y() - rect.height() * 2/5, rect.width() * 2/3, rect.height() * 4/5);
00259 QRectF bigCurveRect = QRectF(rect.x() - rect.width() * 1/3, rect.y() - rect.height() * 4/5, rect.width() * 4/3, rect.height() * 8/5);
00260
00261 painter->drawArc(smallCurveRect, 270 * 16, 90 * 16);
00262 painter->drawArc(bigCurveRect, 270 * 16, 90 * 16);
00263
00264 painter->drawLine(QPointF(rect.x() + rect.width() * 2/3, rect.y()), QPointF(rect.x() + rect.width() * 19/24, rect.y() + rect.height() * 1/5));
00265 painter->drawLine(QPointF(rect.x() + rect.width() * 19/24, rect.y() + rect.height() * 1/5), QPointF(rect.x() + rect.width(), rect.y()));
00266
00267 painter->drawLine(QPointF(rect.x() + rect.width() * 1/3, rect.y() + rect.height() * 2/5), QPointF(rect.x() + rect.width() * 1/3, rect.y() + rect.height() * 1/5));
00268 painter->drawLine(QPointF(rect.x() + rect.width() * 1/3, rect.y() + rect.height() * 1/5), QPointF(rect.x(), rect.y() + rect.height() * 3/5));
00269 painter->drawLine(QPointF(rect.x(), rect.y() + rect.height() * 3/5), QPointF(rect.x() + rect.width() * 1/3, rect.y() + rect.height()));
00270 painter->drawLine(QPointF(rect.x() + rect.width() * 1/3, rect.y() + rect.height()), QPointF(rect.x() + rect.width() * 1/3, rect.y() + rect.height() * 4/5));
00271 }
00272
00273 void GroupNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
00274 {
00275 QRectF rect = outlineRect();
00276 QPointF click = mapFromScene(event->scenePos());
00277
00278 prepareHierarchy();
00279 if ((click.x() > rect.right() - 15) && (click.y() > rect.bottom() - 10)) {
00280
00281 prepareGeometryChange();
00282 abstractPaint = abstractPaint ? false : true;
00283 foreach(QGraphicsItem *item, children()) {
00284 if (dynamic_cast<Node *>(item))
00285 ((Node *)item)->setHide(abstractPaint);
00286 }
00287 update();
00288 }
00289 else {
00290 QString text = QInputDialog::getText(event->widget(), tr("Edit Text"), tr("Enter new text:"), QLineEdit::Normal, name);
00291 prepareGeometryChange();
00292 name = text;
00293 update();
00294 }
00295 updateLinksPos();
00296 updateHierarchy();
00297 }
00298
00299 void GroupNode::abstractView(bool mode)
00300 {
00301 if (abstractPaint == mode) return;
00302
00303
00304 prepareHierarchy();
00305 prepareGeometryChange();
00306 abstractPaint = mode;
00307 foreach(QGraphicsItem *item, children()) {
00308 if (dynamic_cast<Node *>(item))
00309 ((Node *)item)->setHide(abstractPaint);
00310 }
00311 update();
00312 updateLinksPos();
00313 updateHierarchy();
00314 }
00315
00316 void GroupNode::updateLinksPos()
00317 {
00318 foreach (Link *link, getLinks())
00319 link->trackNodes();
00320
00321 foreach (QGraphicsItem *child, children()) {
00322 Node *nodeChild = dynamic_cast<Node *>(child);
00323 if (nodeChild)
00324 nodeChild->updateLinksPos();
00325 }
00326 }
00327
00328 QRectF GroupNode::outlineRect() const
00329 {
00330 if (abstractPaint) {
00331 QFontMetricsF metrics = qApp->font();
00332 double width = metrics.boundingRect(name).width();
00333
00334 const QList<QString> props = itemProp.getProperties();
00335 for (int i = 0; i < props.size(); i++)
00336 if (width < metrics.boundingRect(props[i]).width()) width = metrics.boundingRect(props[i]).width();
00337
00338 width += lineSpacing*4;
00339 double height = (numProp+2)*lineSpacing;
00340 double xPos = childrenBoundingRect().left()-lineSpacing;
00341 double yPos = childrenBoundingRect().top()-lineSpacing;
00342
00343 return QRectF(xPos, yPos, width, height);
00344 }
00345 else {
00346 QRectF rect = childrenBoundingRect();
00347 if (rect.height() < numProp*lineSpacing) rect.setHeight(numProp*lineSpacing);
00348 return rect.adjusted(0.0-lineSpacing*2, 0.0-lineSpacing, lineSpacing*2, lineSpacing);
00349 }
00350 }
00351
00352
00353 void GroupNode::setHide(bool hide)
00354 {
00355 foreach(Link *link, getLinks())
00356 if (internalLinks.contains(link))
00357 link->setVisible(!hide && !abstractPaint);
00358 else
00359 link->setVisible(!hide);
00360
00361 foreach(QGraphicsItem *item, children()) {
00362 if (dynamic_cast<Node *>(item))
00363 ((Node *)item)->setHide(hide || abstractPaint);
00364 }
00365
00366 setVisible(!hide);
00367 }
00368
00369 GroupInfo GroupNode::getInfo()
00370 {
00371 GroupInfo info(id, name);
00372
00373
00374 foreach(QGraphicsItem *item, children()) {
00375 if (dynamic_cast<Node *>(item)) {
00376 if (dynamic_cast<GroupNode *>(item)) {
00377 info.addSubgroup( ((GroupNode *)item)->getId() );
00378
00379 }
00380 else {
00381 info.addNode( ((Node *)item)->getId() );
00382
00383 }
00384 }
00385 }
00386
00387 foreach(Link *link, internalLinks.keys()) {
00388 if (link->fromNode() == this) {
00389 if (dynamic_cast<GroupNode *>(link->toNode()))
00390 info.addSubgroupLink(LinkInfo(link->toNode()->getId(), link->toProp(), true));
00391 else
00392 info.addNodeLink(LinkInfo(link->toNode()->getId(), link->toProp(), true));
00393
00394 }
00395 else {
00396 if (dynamic_cast<GroupNode *>(link->fromNode()))
00397 info.addSubgroupLink(LinkInfo(link->fromNode()->getId(), link->fromProp(), false));
00398 else
00399 info.addNodeLink(LinkInfo(link->fromNode()->getId(), link->fromProp(), false));
00400
00401 }
00402 }
00403
00404 info.setPos(pos());
00405 info.setAbstract(abstractPaint);
00406
00407
00408 return info;
00409 }
00410
00411