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 #include <QDebug>
00024 #include <iostream>
00025
00026 #include "slatewindow.h"
00027 #include "sinclink.h"
00028 #include "asinclink.h"
00029 #include "node.h"
00030 #include "groupnode.h"
00031 #include "inputnode.h"
00032 #include "middlenode.h"
00033 #include "outputnode.h"
00034 #include "slateview.h"
00035 #include "insertaction.h"
00036
00037 #include "facade/designergui.h"
00038 #include "facade/itemproperties.h"
00039
00040
00041 SlateWindow::SlateWindow(DesignerGUI *desig, QWidget * parent): QMainWindow(parent), designer(desig)
00042 {
00043 scene = new QGraphicsScene(0, 0, 800, 600);
00044
00045 view = new SlateView;
00046 view->setScene(scene);
00047 view->setDragMode(QGraphicsView::RubberBandDrag);
00048 view->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
00049 view->setContextMenuPolicy(Qt::ActionsContextMenu);
00050 setCentralWidget(view);
00051
00052 minZ = 0;
00053 maxZ = 0;
00054 seqNumber = 0;
00055
00056 createMenus();
00057 createToolBars();
00058
00059 connect(scene, SIGNAL(selectionChanged()), this, SLOT(updateActions()));
00060
00061 scene->setBackgroundBrush(QPixmap(":/images/background1.png"));
00062
00063 setWindowTitle(tr("Slate"));
00064 updateActions();
00065 }
00066
00067 void SlateWindow::closeEvent(QCloseEvent *)
00068 {
00069 emit closed();
00070 }
00071
00073 bool SlateWindow::createLink(Node *fromNode, int fromPoint, Node *toNode, int toPoint)
00074 {
00075
00076 if (stopAction->isEnabled()) return false;
00077
00078 if (addSLinkAction->isChecked())
00079 designer->addLink(fromNode->getName(), fromNode->propName(fromPoint), toNode->getName(), toNode->propName(toPoint), true);
00080 else
00081 designer->addLink(fromNode->getName(), fromNode->propName(fromPoint), toNode->getName(), toNode->propName(toPoint), false);
00082 return true;
00083 }
00084
00085 void SlateWindow::addLinkLine(QString fromNode, QString fromProp, QString toNode, QString toProp, bool sinc)
00086 {
00087 Link *link;
00088 QString linkName = fromNode + "[" + fromProp + "] => " + toNode + "[" + toProp + "]";
00089
00090 if ( insertNodes.contains(fromNode) && insertNodes.contains(toNode) ) {
00091 ItemNode *from = insertNodes.value(fromNode);
00092 ItemNode *to = insertNodes.value(toNode);
00093
00094 if (sinc) {
00095 link = new SincLink(from, fromProp, to, toProp, 0, scene);
00096 insertLinks.insert(linkName, link);
00097 link->trackNodes();
00098 }
00099 else {
00100 link = new AsincLink(from, fromProp, to, toProp, 0, scene);
00101 insertLinks.insert(linkName, link);
00102 link->trackNodes();
00103 }
00104 }
00105 }
00106
00107 void SlateWindow::delLinkLine(QString fromNode, QString fromProp, QString toNode, QString toProp)
00108 {
00109 QString linkName = fromNode + "[" + fromProp + "] => " + toNode + "[" + toProp + "]";
00110 if (insertLinks.contains(linkName)) {
00111 delete insertLinks.value(linkName);
00112 insertLinks.remove(linkName);
00113 }
00114 }
00115
00116 void SlateWindow::insertItem(QString type)
00117 {
00118 QString name = type + QString("_%1").arg(seqNumber);
00119
00120 designer->addItem(type, name);
00121 }
00122
00123 void SlateWindow::addItemNode(QString type, QString name, ItemProperties *item)
00124 {
00126 if (designer->getInputItemTypes().contains(type)) {
00127 InputNode *node = new InputNode(*item, name, this, 0, scene);
00128 insertNodes.insert(node->getName(), node);
00129 setupNode(node);
00130 if (insertNodesPos.contains(name))
00131 node->setPos(insertNodesPos.value(name));
00132 else
00133 insertNodesPos.insert(name, node->pos());
00134 }
00135 else if (designer->getMiddleItemTypes().contains(type)) {
00136 MiddleNode *node = new MiddleNode(*item, name, this, 0, scene);
00137 insertNodes.insert(node->getName(), node);
00138 setupNode(node);
00139 if (insertNodesPos.contains(name))
00140 node->setPos(insertNodesPos.value(name));
00141 else
00142 insertNodesPos.insert(name, node->pos());
00143 }
00144 else if (designer->getOutputItemTypes().contains(type)) {
00145 OutputNode *node = new OutputNode(*item, name, this, 0, scene);
00146 insertNodes.insert(node->getName(), node);
00147 setupNode(node);
00148 if (insertNodesPos.contains(name))
00149 node->setPos(insertNodesPos.value(name));
00150 else
00151 insertNodesPos.insert(name, node->pos());
00152 }
00153 }
00154
00155 void SlateWindow::delItemNode(QString name)
00156 {
00157 if (insertNodes.contains(name)) {
00158 insertNodesPos.remove(name);
00159 insertNodesPos.insert(name, insertNodes.value(name)->pos());
00160 delete insertNodes.value(name);
00161 insertNodes.remove(name);
00162 }
00163 }
00164
00165 void SlateWindow::addProperty(QString srcName, QString propName, int type, bool in, bool out)
00166 {
00167 if (insertNodes.contains(srcName)) {
00168 insertNodes.value(srcName)->insertProperty(propName, type, in, out);
00169 }
00170 }
00171
00172 void SlateWindow::delProperty(QString srcName, QString propName)
00173 {
00174 if (insertNodes.contains(srcName)) {
00175 insertNodes.value(srcName)->removeProperty(propName);
00176 }
00177 }
00178
00179 void SlateWindow::del()
00180 {
00181 foreach(QGraphicsItem *item, scene->selectedItems()) {
00182 Link *link = dynamic_cast<Link *>(item);
00183 Node *node = dynamic_cast<Node *>(item);
00184
00185 if (link && (link->fromNode() != NULL) && (link->toNode() != NULL)) {
00186 designer->delLink(link->fromNode()->getName(), link->fromProp(), link->toNode()->getName(), link->toProp());
00187 }
00188 else if (node) {
00189 designer->delItem(node->getName());
00190 }
00191 }
00192 }
00193
00194 void SlateWindow::join()
00195 {
00196 QList<QGraphicsItem *> group = selectedNodeGroup();
00197
00198
00199 GroupNode *node = new GroupNode(0, scene);
00200 node->setText("Group");
00201
00202
00203 if ( group.first() && group.first()->parentItem() ) {
00204 GroupNode *parentNode = dynamic_cast<GroupNode *>(group.first()->parentItem());
00205 if (parentNode) parentNode->addNode(node);
00206 }
00207
00208
00209 foreach (QGraphicsItem *item, group) {
00210 Node *itemNode = dynamic_cast<Node *>(item);
00211 if (itemNode) {
00212 node->addNode(itemNode);
00213
00214
00215
00216 foreach (Link *link, itemNode->getInLinks()) {
00217 Node *other = link->fromNode();
00218 if (group.contains(other)) {
00219 QPen pen = link->pen();
00220 pen.setWidthF(pen.width()*0.5);
00221 link->setPen(pen);
00222 link->update();
00223 }
00224
00225
00226
00227 }
00228 foreach (Link *link, itemNode->getOutLinks()) {
00229 Node *other = link->toNode();
00230 if (group.contains(other)) {
00231 QPen pen = link->pen();
00232 pen.setWidthF(pen.width()*0.5);
00233 link->setPen(pen);
00234 link->update();
00235 }
00236
00237
00238
00239 }
00240 itemNode->updateLinksPos();
00241 }
00242 }
00243 }
00244
00245 void SlateWindow::bringToFront()
00246 {
00247 maxZ += 2;
00248 setZValue(maxZ);
00249 }
00250
00251 void SlateWindow::sendToBack()
00252 {
00253 minZ += 2;
00254 setZValue(minZ);
00255 }
00256
00257 void SlateWindow::run()
00258 {
00259 foreach (QAction *action, insertMenu->actions()) {
00260 action->setEnabled(false);
00261 }
00262
00263 deleteAction->setEnabled(false);
00264
00265 runAction->setEnabled(false);
00266 stopAction->setEnabled(true);
00267 designer->run();
00268 }
00269
00270 void SlateWindow::stop()
00271 {
00272 designer->stop();
00273 stopAction->setEnabled(false);
00274 runAction->setChecked(false);
00275 runAction->setEnabled(true);
00276
00277 bool hasSelection = !scene->selectedItems().isEmpty();
00278 deleteAction->setEnabled(hasSelection);
00279
00280 foreach (QAction *action, insertMenu->actions()) {
00281 action->setEnabled(true);
00282 }
00283 }
00284
00285 void SlateWindow::setZValue(int z)
00286 {
00287 Node *node = selectedNode();
00288 if (node) {
00289 node->setZValue(z);
00290 node->updateLinksPos();
00291 }
00292 }
00293
00294 void SlateWindow::showProperties()
00295 {
00296 Node *node = selectedNode();
00297
00298 if (node) showProperties(node);
00299 }
00300
00301 void SlateWindow::showProperties(Node *node)
00302 {
00303 designer->showProperties(node->getName());
00304 }
00305
00306 void SlateWindow::updateActions()
00307 {
00308 bool hasSelection = !scene->selectedItems().isEmpty();
00309 bool isNode = (selectedNode() != 0);
00310
00311
00312
00313 joinAction->setEnabled(false);
00314
00315 if (runAction->isEnabled()) deleteAction->setEnabled(hasSelection);
00316 bringToFrontAction->setEnabled(isNode);
00317 sendToBackAction->setEnabled(isNode);
00318 propertiesAction->setEnabled(isNode);
00319
00320 foreach (QAction *action, view->actions())
00321 view->removeAction(action);
00322
00323 foreach (QAction *action, editMenu->actions()) {
00324 if (action->isEnabled())
00325 view->addAction(action);
00326 }
00327
00328
00329 QAction *ma = new QAction(tr("..."), this);
00330 ma->setMenu(new QMenu("insert_menu", this));
00331 ma->menu()->addMenu(insertMenu);
00332 view->addAction(ma);
00333
00334 foreach (QAction *action, insertMenu->actions()) {
00335 view->addAction(action);
00336 }
00337 }
00338
00339 void SlateWindow::setupNode(Node *node)
00340 {
00341 node->setPos( QPoint(10 + (seqNumber % 10) * 6, 20 + (seqNumber % 10) * 6) );
00342 ++seqNumber;
00343
00344 scene->clearSelection();
00345 node->setSelected(true);
00346 bringToFront();
00347 }
00348
00349 void SlateWindow::createMenus()
00350 {
00352 exitAction = new QAction(tr("E&xit"), this);
00353 exitAction->setShortcut(tr("Ctrl+Q"));
00354 connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
00355
00356 addSLinkAction = new QAction(tr("Add &Synchronous Link"), this);
00357 addSLinkAction->setIcon(QIcon(":/images/slink.png"));
00358 addSLinkAction->setShortcut(tr("Ctrl+S"));
00359 addSLinkAction->setCheckable(true);
00360
00361 addALinkAction = new QAction(tr("Add &Asynchronous Link"), this);
00362 addALinkAction->setIcon(QIcon(":/images/alink.png"));
00363 addALinkAction->setShortcut(tr("Ctrl+A"));
00364 addALinkAction->setCheckable(true);
00365 addALinkAction->setChecked(true);
00366
00367
00368 linkGroup = new QActionGroup(this);
00369 linkGroup->setExclusive(true);
00370 linkGroup->addAction(addSLinkAction);
00371 linkGroup->addAction(addALinkAction);
00372
00373
00374 joinAction = new QAction(tr("&Join"), this);
00375 joinAction->setIcon(QIcon(":/images/join.png"));
00376 joinAction->setShortcut(tr("Ctrl+J"));
00377 connect(joinAction, SIGNAL(triggered()), this, SLOT(join()));
00378
00379 deleteAction = new QAction(tr("&Delete"), this);
00380 deleteAction->setIcon(QIcon(":/images/delete.png"));
00381 deleteAction->setShortcut(tr("Del"));
00382 deleteAction->setEnabled(false);
00383 connect(deleteAction, SIGNAL(triggered()), this, SLOT(del()));
00384
00385 bringToFrontAction = new QAction(tr("Bring to &Front"), this);
00386 bringToFrontAction->setIcon(QIcon(":/images/bringtofront.png"));
00387 connect(bringToFrontAction, SIGNAL(triggered()),
00388 this, SLOT(bringToFront()));
00389
00390 sendToBackAction = new QAction(tr("&Send to Back"), this);
00391 sendToBackAction->setIcon(QIcon(":/images/sendtoback.png"));
00392 connect(sendToBackAction, SIGNAL(triggered()),
00393 this, SLOT(sendToBack()));
00394
00395 propertiesAction = new QAction(tr("P&roperties..."), this);
00396 connect(propertiesAction, SIGNAL(triggered()),
00397 this, SLOT(showProperties()));
00398
00399 runAction = new QAction(tr("&Run"), this);
00400 runAction->setIcon(QIcon(":/images/run.png"));
00401 runAction->setCheckable(true);
00402 runAction->setChecked(true);
00403 runAction->setEnabled(false);
00404 connect(runAction, SIGNAL(triggered()),
00405 this, SLOT(run()));
00406
00407 stopAction = new QAction(tr("&Run"), this);
00408 stopAction->setIcon(QIcon(":/images/stop.png"));
00409 stopAction->setEnabled(true);
00410 connect(stopAction, SIGNAL(triggered()),
00411 this, SLOT(stop()));
00412
00413
00414 fileMenu = menuBar()->addMenu(tr("&File"));
00415 fileMenu->addAction(exitAction);
00416
00417 editMenu = menuBar()->addMenu(tr("&Edit"));
00418 editMenu->addAction(addSLinkAction);
00419 editMenu->addAction(addALinkAction);
00420
00421 editMenu->addSeparator();
00422 editMenu->addAction(joinAction);
00423 editMenu->addAction(deleteAction);
00424 editMenu->addSeparator();
00425 editMenu->addAction(bringToFrontAction);
00426 editMenu->addAction(sendToBackAction);
00427 editMenu->addSeparator();
00428 editMenu->addAction(propertiesAction);
00429
00430
00431
00432 insertMenu = menuBar()->addMenu(tr("&Insert"));
00433
00434 foreach (QString item, designer->getInputItemTypes())
00435 {
00436 InsertAction *action = new InsertAction(item, this);
00437 action->setEnabled(false);
00438 connect(action, SIGNAL(triggered(QString)), this, SLOT(insertItem(QString)));
00439 insertMenu->addAction(action);
00440 }
00441
00442 foreach (QString item, designer->getMiddleItemTypes())
00443 {
00444 InsertAction *action = new InsertAction(item, this);
00445 action->setEnabled(false);
00446 connect(action, SIGNAL(triggered(QString)), this, SLOT(insertItem(QString)));
00447 insertMenu->addAction(action);
00448 }
00449
00450 foreach (QString item, designer->getOutputItemTypes())
00451 {
00452 InsertAction *action = new InsertAction(item, this);
00453 action->setEnabled(false);
00454 connect(action, SIGNAL(triggered(QString)), this, SLOT(insertItem(QString)));
00455 insertMenu->addAction(action);
00456 }
00457 }
00458
00459 void SlateWindow::createToolBars()
00460 {
00461 editToolBar = addToolBar(tr("Edit"));
00462 editToolBar->addAction(addSLinkAction);
00463 editToolBar->addAction(addALinkAction);
00464 editToolBar->addAction(joinAction);
00465 editToolBar->addAction(deleteAction);
00466 editToolBar->addSeparator();
00467 editToolBar->addSeparator();
00468 editToolBar->addAction(bringToFrontAction);
00469 editToolBar->addAction(sendToBackAction);
00470
00471 editToolBar->addSeparator();
00472 editToolBar->addAction(runAction);
00473 editToolBar->addAction(stopAction);
00474 }
00475
00476 Node *SlateWindow::selectedNode() const
00477 {
00478 QList<QGraphicsItem *> items = scene->selectedItems();
00479 if (items.count() == 1) {
00480 return dynamic_cast<Node *>(items.first());
00481 } else {
00482 return 0;
00483 }
00484 }
00485
00486 Link *SlateWindow::selectedLink() const
00487 {
00488 QList<QGraphicsItem *> items = scene->selectedItems();
00489 if (items.count() == 1) {
00490 return dynamic_cast<Link *>(items.first());
00491 } else {
00492 return 0;
00493 }
00494 }
00495
00496 SlateWindow::NodePair SlateWindow::selectedNodePair() const
00497 {
00498 QList<QGraphicsItem *> items = scene->selectedItems();
00499 if (items.count() == 2) {
00500 Node *first = dynamic_cast<Node *>(items.first());
00501 Node *second = dynamic_cast<Node *>(items.last());
00502 if (first && second)
00503 return NodePair(first, second);
00504 }
00505 return NodePair();
00506 }
00507
00508
00509 QList<QGraphicsItem *> SlateWindow::selectedNodeGroup() const
00510 {
00511 QList<QGraphicsItem *> items = onlyParents(scene->selectedItems());
00512
00513
00514 if (items.count() > 1) {
00515
00516 QGraphicsItem * parent = 0;
00517 QMutableListIterator<QGraphicsItem *> i(items);
00518 if (i.hasNext()) parent = i.next()->parentItem();
00519
00520 while (i.hasNext())
00521 if ( i.next()->parentItem() != parent) return QList<QGraphicsItem *>();
00522
00523 return items;
00524 }
00525 return QList<QGraphicsItem *>();
00526 }
00527
00528
00529 QList<QGraphicsItem *> SlateWindow::onlyParents(QList<QGraphicsItem *> items) const
00530 {
00531 QList<QGraphicsItem *> parentItems;
00532
00533 QMutableListIterator<QGraphicsItem *> i(items);
00534 while (i.hasNext()) {
00535 i.next();
00536 bool parent = true;
00537 QMutableListIterator<QGraphicsItem *> j(items);
00538 while (j.hasNext()) {
00539 j.next();
00540 if ( (i.value()) && (i.value()->parentItem() == j.value()) ) {
00541 parent = false;
00542 break;
00543 }
00544 }
00545 if (parent) parentItems.append(i.value());
00546 }
00547
00548 return parentItems;
00549 }
00550