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 "sequenlink.h"
00030 #include "node.h"
00031 #include "groupnode.h"
00032 #include "inputnode.h"
00033 #include "middlenode.h"
00034 #include "outputnode.h"
00035 #include "slateview.h"
00036 #include "insertaction.h"
00037
00038 #include <QVDesignerGUI>
00039
00040 #include "../facade/itemproperties.h"
00041
00042
00043 SlateWindow::SlateWindow(QVDesignerGUI *desig, QWidget * parent): QMainWindow(parent), designer(desig)
00044 {
00045 scene = new QGraphicsScene(-1180, -900, 3200, 2400);
00046
00047 view = new SlateView;
00048 view->setScene(scene);
00049 view->setDragMode(QGraphicsView::RubberBandDrag);
00050 view->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
00051 view->setContextMenuPolicy(Qt::ActionsContextMenu);
00052 setCentralWidget(view);
00053
00054 minZ = 0;
00055 maxZ = 0;
00056 seqNumber = 0;
00057
00058 createMenus();
00059 createToolBars();
00060
00061 statusbar = new QStatusBar();
00062 setStatusBar(statusbar);
00063
00064 connect(scene, SIGNAL(selectionChanged()), this, SLOT(updateActions()));
00065
00066 scene->setBackgroundBrush(QPixmap(":/images/background1.png"));
00067
00068 setWindowTitle(tr("Slate"));
00069 updateActions();
00070 }
00071
00072 void SlateWindow::closeEvent(QCloseEvent *)
00073 {
00074 emit closed();
00075 }
00076
00078 bool SlateWindow::createLink(Node *fromNode, int fromPoint, Node *toNode, int toPoint)
00079 {
00080
00081 if (stopAction->isEnabled()) return false;
00082
00083 if (addSLinkAction->isChecked())
00084 designer->addLink(fromNode->getName(), fromNode->propName(fromPoint), toNode->getName(), toNode->propName(toPoint), true, false);
00085 else if (addALinkAction->isChecked())
00086 designer->addLink(fromNode->getName(), fromNode->propName(fromPoint), toNode->getName(), toNode->propName(toPoint), false, false);
00087 else
00088 designer->addLink(fromNode->getName(), fromNode->propName(fromPoint), toNode->getName(), toNode->propName(toPoint), false, true);
00089
00090 return true;
00091 }
00092
00093 void SlateWindow::addLinkLine(QString fromNode, QString fromProp, QString toNode, QString toProp, bool sinc, bool sequential)
00094 {
00095 Link *link;
00096 QString linkName = fromNode + "[" + fromProp + "] => " + toNode + "[" + toProp + "]";
00097
00098 if ( insertNodes.contains(fromNode) && insertNodes.contains(toNode) ) {
00099 ItemNode *from = insertNodes.value(fromNode);
00100 ItemNode *to = insertNodes.value(toNode);
00101
00102 if (sequential) {
00103 link = new SequenLink(from, fromProp, to, toProp, 0, scene);
00104 insertLinks.insert(linkName, link);
00105 link->trackNodes();
00106 }
00107 else if (sinc) {
00108 link = new SincLink(from, fromProp, to, toProp, 0, scene);
00109 insertLinks.insert(linkName, link);
00110 link->trackNodes();
00111 }
00112 else {
00113 link = new AsincLink(from, fromProp, to, toProp, 0, scene);
00114 insertLinks.insert(linkName, link);
00115 link->trackNodes();
00116 }
00117 }
00118 }
00119
00120 void SlateWindow::delLinkLine(QString fromNode, QString fromProp, QString toNode, QString toProp)
00121 {
00122 QString linkName = fromNode + "[" + fromProp + "] => " + toNode + "[" + toProp + "]";
00123 if (insertLinks.contains(linkName)) {
00124 delete insertLinks.value(linkName);
00125 insertLinks.remove(linkName);
00126 }
00127 }
00128
00129 void SlateWindow::insertItem(QString type)
00130 {
00131 QString name = type.toLower();
00132 name.replace('<', '_');
00133 name.replace(',', '_');
00134 name.replace('>', '_');
00135 name.replace(' ', "");
00136 name += QString("_%1").arg(seqNumber);
00137
00138 designer->addItem(type, name);
00139 }
00140
00141 void SlateWindow::addItemNode(QString type, QString name, ItemProperties *item)
00142 {
00144 if (designer->getInputItemTypes().contains(type)) {
00145 InputNode *node = new InputNode(*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 else if (designer->getMiddleItemTypes().contains(type)) {
00154 MiddleNode *node = new MiddleNode(*item, name, this, 0, scene);
00155 insertNodes.insert(node->getName(), node);
00156 setupNode(node);
00157 if (insertNodesPos.contains(name))
00158 node->setPos(insertNodesPos.value(name));
00159 else
00160 insertNodesPos.insert(name, node->pos());
00161 }
00162 else if (designer->getOutputItemTypes().contains(type)) {
00163 OutputNode *node = new OutputNode(*item, name, this, 0, scene);
00164 insertNodes.insert(node->getName(), node);
00165 setupNode(node);
00166 if (insertNodesPos.contains(name))
00167 node->setPos(insertNodesPos.value(name));
00168 else
00169 insertNodesPos.insert(name, node->pos());
00170 }
00171 }
00172
00173 void SlateWindow::delItemNode(QString name)
00174 {
00175 if (insertNodes.contains(name)) {
00176 insertNodesPos.remove(name);
00177 insertNodesPos.insert(name, insertNodes.value(name)->pos());
00178 delete insertNodes.value(name);
00179 insertNodes.remove(name);
00180 }
00181 }
00182
00183 void SlateWindow::addProperty(QString srcName, QString propName, int type, bool in, bool out)
00184 {
00185 if (insertNodes.contains(srcName)) {
00186 insertNodes.value(srcName)->insertProperty(propName, type, in, out);
00187 }
00188 }
00189
00190 void SlateWindow::delProperty(QString srcName, QString propName)
00191 {
00192 if (insertNodes.contains(srcName)) {
00193 insertNodes.value(srcName)->removeProperty(propName);
00194 }
00195 }
00196
00197 void SlateWindow::del()
00198 {
00199
00200 foreach(QGraphicsItem *item, scene->selectedItems()) {
00201 Link *link = dynamic_cast<Link *>(item);
00202
00203 if (link && (link->fromNode() != NULL) && (link->toNode() != NULL)) {
00204 designer->delLink(link->fromNode()->getName(), link->fromProp(), link->toNode()->getName(), link->toProp());
00205 }
00206 }
00207
00208 foreach(QGraphicsItem *item, scene->selectedItems()) {
00209 Node *node = dynamic_cast<Node *>(item);
00210
00211 if (node) {
00212 designer->delItem(node->getName());
00213 }
00214 }
00215 }
00216
00217 void SlateWindow::join()
00218 {
00219 QList<QGraphicsItem *> group = selectedNodeGroup();
00220
00221
00222 GroupNode *node = new GroupNode(0, scene);
00223 node->setText("Group");
00224
00225
00226 if ( group.first() && group.first()->parentItem() ) {
00227 GroupNode *parentNode = dynamic_cast<GroupNode *>(group.first()->parentItem());
00228 if (parentNode) parentNode->addNode(node);
00229 }
00230
00231
00232 foreach (QGraphicsItem *item, group) {
00233 Node *itemNode = dynamic_cast<Node *>(item);
00234 if (itemNode) {
00235 node->addNode(itemNode);
00236
00237
00238
00239 foreach (Link *link, itemNode->getInLinks()) {
00240 Node *other = link->fromNode();
00241 if (group.contains(other)) {
00242 QPen pen = link->pen();
00243 pen.setWidthF(pen.width()*0.5);
00244 link->setPen(pen);
00245 link->update();
00246 }
00247
00248
00249
00250 }
00251 foreach (Link *link, itemNode->getOutLinks()) {
00252 Node *other = link->toNode();
00253 if (group.contains(other)) {
00254 QPen pen = link->pen();
00255 pen.setWidthF(pen.width()*0.5);
00256 link->setPen(pen);
00257 link->update();
00258 }
00259
00260
00261
00262 }
00263 itemNode->updateLinksPos();
00264 }
00265 }
00266 }
00267
00268 void SlateWindow::bringToFront()
00269 {
00270 maxZ += 2;
00271 setZValue(maxZ);
00272 }
00273
00274 void SlateWindow::sendToBack()
00275 {
00276 minZ += 2;
00277 setZValue(minZ);
00278 }
00279
00280 void SlateWindow::run()
00281 {
00282 foreach (QAction *action, insertMenu->actions()) {
00283 action->setEnabled(false);
00284 }
00285
00286 deleteAction->setEnabled(false);
00287
00288 runAction->setEnabled(false);
00289 stopAction->setEnabled(true);
00290 designer->run();
00291 }
00292
00293 void SlateWindow::stop()
00294 {
00295 designer->stop();
00296 stopAction->setEnabled(false);
00297 runAction->setChecked(false);
00298 runAction->setEnabled(true);
00299
00300 bool hasSelection = !scene->selectedItems().isEmpty();
00301 deleteAction->setEnabled(hasSelection);
00302
00303 foreach (QAction *action, insertMenu->actions()) {
00304 action->setEnabled(true);
00305 }
00306 }
00307
00308 void SlateWindow::setZValue(int z)
00309 {
00310 Node *node = selectedNode();
00311 if (node) {
00312 node->setZValue(z);
00313 node->updateLinksPos();
00314 }
00315 }
00316
00317 void SlateWindow::showProperties()
00318 {
00319 Node *node = selectedNode();
00320
00321 if (node) showProperties(node);
00322 }
00323
00324 void SlateWindow::showProperties(Node *node)
00325 {
00326 designer->showProperties(node->getName());
00327 }
00328
00329 void SlateWindow::updateActions()
00330 {
00331 bool hasSelection = !scene->selectedItems().isEmpty();
00332 bool isNode = (selectedNode() != 0);
00333
00334 bool isNodeGroup = (selectedNodeGroup() != QList<QGraphicsItem *>());
00335
00336 joinAction->setEnabled(isNodeGroup);
00337
00338 if (runAction->isEnabled()) deleteAction->setEnabled(hasSelection);
00339 bringToFrontAction->setEnabled(isNode);
00340 sendToBackAction->setEnabled(isNode);
00341 propertiesAction->setEnabled(isNode);
00342
00343 foreach (QAction *action, view->actions())
00344 view->removeAction(action);
00345
00346 foreach (QAction *action, editMenu->actions()) {
00347 if (action->isEnabled())
00348 view->addAction(action);
00349 }
00350
00351
00352 QAction *ma = new QAction(tr("..."), this);
00353 ma->setMenu(new QMenu("insert_menu", this));
00354 ma->menu()->addMenu(insertMenu);
00355 view->addAction(ma);
00356
00357 foreach (QAction *action, insertMenu->actions()) {
00358 view->addAction(action);
00359 }
00360 }
00361
00362 void SlateWindow::setupNode(Node *node)
00363 {
00364 node->setPos( QPoint(10 + (seqNumber % 10) * 6, 20 + (seqNumber % 10) * 6) );
00365 ++seqNumber;
00366
00367 scene->clearSelection();
00368 node->setSelected(true);
00369 bringToFront();
00370 }
00371
00372 void SlateWindow::createMenus()
00373 {
00375 exitAction = new QAction(tr("E&xit"), this);
00376 exitAction->setShortcut(tr("Ctrl+Q"));
00377 connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
00378
00379 addALinkAction = new QAction(tr("Add &Asynchronous Link"), this);
00380 addALinkAction->setIcon(QIcon(":/images/alink.png"));
00381 addALinkAction->setShortcut(tr("Ctrl+A"));
00382 addALinkAction->setCheckable(true);
00383 addALinkAction->setChecked(true);
00384
00385 addSLinkAction = new QAction(tr("Add &Synchronous Link"), this);
00386 addSLinkAction->setIcon(QIcon(":/images/slink.png"));
00387 addSLinkAction->setShortcut(tr("Ctrl+S"));
00388 addSLinkAction->setCheckable(true);
00389
00390 addQLinkAction = new QAction(tr("Add Se&quential Link"), this);
00391 addQLinkAction->setIcon(QIcon(":/images/qlink.png"));
00392 addQLinkAction->setShortcut(tr("Ctrl+Q"));
00393 addQLinkAction->setCheckable(true);
00394
00395
00396 linkGroup = new QActionGroup(this);
00397 linkGroup->setExclusive(true);
00398 linkGroup->addAction(addALinkAction);
00399 linkGroup->addAction(addSLinkAction);
00400 linkGroup->addAction(addQLinkAction);
00401
00402
00403 joinAction = new QAction(tr("&Join"), this);
00404 joinAction->setIcon(QIcon(":/images/join.png"));
00405 joinAction->setShortcut(tr("Ctrl+J"));
00406 connect(joinAction, SIGNAL(triggered()), this, SLOT(join()));
00407
00408 deleteAction = new QAction(tr("&Delete"), this);
00409 deleteAction->setIcon(QIcon(":/images/delete.png"));
00410 deleteAction->setShortcut(tr("Del"));
00411 deleteAction->setEnabled(false);
00412 connect(deleteAction, SIGNAL(triggered()), this, SLOT(del()));
00413
00414 bringToFrontAction = new QAction(tr("Bring to &Front"), this);
00415 bringToFrontAction->setIcon(QIcon(":/images/bringtofront.png"));
00416 connect(bringToFrontAction, SIGNAL(triggered()),this, SLOT(bringToFront()));
00417
00418 sendToBackAction = new QAction(tr("&Send to Back"), this);
00419 sendToBackAction->setIcon(QIcon(":/images/sendtoback.png"));
00420 connect(sendToBackAction, SIGNAL(triggered()), this, SLOT(sendToBack()));
00421
00422 propertiesAction = new QAction(tr("P&roperties..."), this);
00423 connect(propertiesAction, SIGNAL(triggered()), this, SLOT(showProperties()));
00424
00425 runAction = new QAction(tr("&Run"), this);
00426 runAction->setIcon(QIcon(":/images/run.png"));
00427 runAction->setCheckable(true);
00428 runAction->setChecked(true);
00429 runAction->setEnabled(false);
00430 connect(runAction, SIGNAL(triggered()), this, SLOT(run()));
00431
00432 stopAction = new QAction(tr("&Run"), this);
00433 stopAction->setIcon(QIcon(":/images/stop.png"));
00434 stopAction->setEnabled(true);
00435 connect(stopAction, SIGNAL(triggered()), this, SLOT(stop()));
00436
00437 saveAsAction = new QAction(tr("&Export"), this);
00438 saveAsAction->setShortcut(tr("Ctrl+E"));
00439 connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs()));
00440
00441
00442 fileMenu = menuBar()->addMenu(tr("&File"));
00443 fileMenu->addAction(saveAsAction);
00444 fileMenu->addAction(exitAction);
00445
00446 editMenu = menuBar()->addMenu(tr("&Edit"));
00447 editMenu->addAction(addALinkAction);
00448 editMenu->addAction(addSLinkAction);
00449 editMenu->addAction(addQLinkAction);
00450
00451 editMenu->addSeparator();
00452 editMenu->addAction(joinAction);
00453 editMenu->addAction(deleteAction);
00454 editMenu->addSeparator();
00455 editMenu->addAction(bringToFrontAction);
00456 editMenu->addAction(sendToBackAction);
00457 editMenu->addSeparator();
00458 editMenu->addAction(propertiesAction);
00459
00460
00461
00462 insertMenu = menuBar()->addMenu(tr("&Insert"));
00463
00464 foreach (QString item, designer->getItemTypes())
00465 {
00466 InsertAction *action = new InsertAction(item, this);
00467 action->setEnabled(false);
00468 connect(action, SIGNAL(triggered(QString)), this, SLOT(insertItem(QString)));
00469 insertMenu->addAction(action);
00470 }
00471 }
00472
00473 void SlateWindow::includeItemType(QString itemType)
00474 {
00475 InsertAction *action = new InsertAction(itemType, this);
00476 action->setEnabled(false);
00477 connect(action, SIGNAL(triggered(QString)), this, SLOT(insertItem(QString)));
00478 insertMenu->addAction(action);
00479
00480 updateActions();
00481 }
00482
00483 void SlateWindow::createToolBars()
00484 {
00485 editToolBar = addToolBar(tr("Edit"));
00486 editToolBar->addAction(addALinkAction);
00487 editToolBar->addAction(addSLinkAction);
00488 editToolBar->addAction(addQLinkAction);
00489 editToolBar->addAction(joinAction);
00490 editToolBar->addAction(deleteAction);
00491 editToolBar->addSeparator();
00492 editToolBar->addSeparator();
00493 editToolBar->addAction(bringToFrontAction);
00494 editToolBar->addAction(sendToBackAction);
00495
00496 editToolBar->addSeparator();
00497 editToolBar->addAction(runAction);
00498 editToolBar->addAction(stopAction);
00499 }
00500
00501 Node *SlateWindow::selectedNode() const
00502 {
00503 QList<QGraphicsItem *> items = scene->selectedItems();
00504 if (items.count() == 1) {
00505 return dynamic_cast<Node *>(items.first());
00506 } else {
00507 return 0;
00508 }
00509 }
00510
00511 Link *SlateWindow::selectedLink() const
00512 {
00513 QList<QGraphicsItem *> items = scene->selectedItems();
00514 if (items.count() == 1) {
00515 return dynamic_cast<Link *>(items.first());
00516 } else {
00517 return 0;
00518 }
00519 }
00520
00521 SlateWindow::NodePair SlateWindow::selectedNodePair() const
00522 {
00523 QList<QGraphicsItem *> items = scene->selectedItems();
00524 if (items.count() == 2) {
00525 Node *first = dynamic_cast<Node *>(items.first());
00526 Node *second = dynamic_cast<Node *>(items.last());
00527 if (first && second)
00528 return NodePair(first, second);
00529 }
00530 return NodePair();
00531 }
00532
00533
00534 QList<QGraphicsItem *> SlateWindow::selectedNodeGroup() const
00535 {
00536 QList<QGraphicsItem *> items = onlyParents(scene->selectedItems());
00537
00538
00539 if (items.count() > 1) {
00540
00541 QGraphicsItem * parent = 0;
00542 QMutableListIterator<QGraphicsItem *> i(items);
00543 if (i.hasNext()) parent = i.next()->parentItem();
00544
00545 while (i.hasNext())
00546 if ( i.next()->parentItem() != parent) return QList<QGraphicsItem *>();
00547
00548 return items;
00549 }
00550 return QList<QGraphicsItem *>();
00551 }
00552
00553
00554 QList<QGraphicsItem *> SlateWindow::onlyParents(QList<QGraphicsItem *> items) const
00555 {
00556 QList<QGraphicsItem *> parentItems;
00557
00558 QMutableListIterator<QGraphicsItem *> i(items);
00559 while (i.hasNext()) {
00560 i.next();
00561 bool parent = true;
00562 QMutableListIterator<QGraphicsItem *> j(items);
00563 while (j.hasNext()) {
00564 j.next();
00565 if ( (i.value()) && (i.value()->parentItem() == j.value()) ) {
00566 parent = false;
00567 break;
00568 }
00569 }
00570 if (parent) parentItems.append(i.value());
00571 }
00572
00573 return parentItems;
00574 }
00575
00576 bool SlateWindow::saveAs()
00577 {
00578 QString fileName = QFileDialog::getSaveFileName(this,
00579 tr("Save C++"), ".",
00580 tr("C++ files (*.cpp)"));
00581 if (fileName.isEmpty())
00582 return false;
00583 return saveFile(fileName);
00584 }
00585
00586 bool SlateWindow::saveFile(const QString &fileName)
00587 {
00588 if (!writeCppFile(fileName)) {
00589
00590 return false;
00591 }
00592
00593
00594 return true;
00595 }
00596
00597 bool SlateWindow::writeCppFile(const QString &fileName)
00598 {
00599 QFile file(fileName);
00600 if (!file.open(QIODevice::WriteOnly)) {
00601 QMessageBox::warning(this, tr("QVDesignerGUI"),
00602 tr("Cannot write file %1:\n%2.")
00603 .arg(file.fileName())
00604 .arg(file.errorString()));
00605 return false;
00606 }
00607
00608 QTextStream out(&file);
00609 out << designer->getCppText();
00610
00611 return true;
00612 }
00613
00614
00615 void SlateWindow::showMessage(QString message)
00616 {
00617 if (statusbar)
00618 statusbar->showMessage(message, 10000);
00619 }
00620
00621
00622 void SlateWindow::arrangeItems()
00623 {
00624 QList<QList<ItemNode *> *> levels;
00625 int left = 10;
00626 int bottom = 20;
00627 const int MARGIN = 20;
00628
00629
00630 foreach(ItemNode *node, insertNodes) {
00631 int level = node->precursors();
00632 while(levels.size() <= level)
00633 levels.append(new QList<ItemNode *>);
00634 levels[level]->append(node);
00635 }
00636
00637
00638 foreach(QList<ItemNode *> *levelNodes, levels) {
00639 int maxWidth = 0;
00640 if (levelNodes) {
00641 foreach(ItemNode *node, *levelNodes) {
00642 node->setPos(QPoint(left, bottom));
00643 bottom += (int)node->boundingRect().height() + MARGIN;
00644 int width = (int)node->boundingRect().width();
00645 if (maxWidth < width) maxWidth = width;
00646 }
00647 }
00648 left += maxWidth + MARGIN;
00649 bottom = 20;
00650 }
00651
00652
00653 foreach(QList<ItemNode *> *levelNodes, levels) {
00654 levelNodes->clear();
00655 delete levelNodes;
00656 }
00657 }
00658
00659