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