PARP Research Group University of Murcia, Spain


src/qvgui/qvdesigner/slate/slatewindow.cpp

00001 /*
00002  *      Copyright (C) 2008. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
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 //#include "../designergui.h"
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         // si está en ejecución no se permite lincar
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         // primero borro solo los links, ya que al borrar un nodo pueden desaparecer links seleccionados, que se intentarian borrar y daría un core
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         // creo el nuevo grupo
00222     GroupNode *node = new GroupNode(0, scene);
00223     node->setText("Group");
00224 
00225         // si los items seleccionados estaban ya dentro de otro grupo, este se añade a el (sino a la escena)
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         // para cada item si es un nodo lo añado al nuevo grupo
00232         foreach (QGraphicsItem *item, group) {
00233                 Node *itemNode = dynamic_cast<Node *>(item);
00234                 if (itemNode) {
00235                         node->addNode(itemNode);
00236 
00237                         //se actualiza el tamaño de sus links
00238                         //y si la otra punta no se va a meter al grupo pasa a formar parte de este
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 /*                              else {
00248                                                 link->changeToNode(node);
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 /*                              else {
00260                                                 link->changeFromNode(node);
00261                                 }*/
00262                         }
00263                         itemNode->updateLinksPos(); // para que se actualiza la posición y tamaño de los links del nodo
00264                 }
00265         }
00266 }
00267 
00268 void SlateWindow::bringToFront()
00269 {
00270     maxZ += 2; // dos, uno para el y otro para sus link que serán: el + 1
00271     setZValue(maxZ);
00272 }
00273 
00274 void SlateWindow::sendToBack()
00275 {
00276     minZ += 2; // dos, uno para el y otro para sus link que serán: el + 1
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 //      bool isNodePair = (selectedNodePair() != NodePair());
00334         bool isNodeGroup = (selectedNodeGroup() != QList<QGraphicsItem *>());
00335 
00336         joinAction->setEnabled(isNodeGroup);
00337         // si está en ejecución no se permite borrar
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         // añado las acciones del menu insertar al desplegable del botón derecho (de dos formas distintas)
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); // para que se mantenga pulsada
00383         addALinkAction->setChecked(true); // por defecto está seleccionado asincrono
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); // para que se mantenga pulsada
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); // para que se mantenga pulsada
00394 
00395         // con esto conseguimos meterlas en un grupo exclusivo, o una o la otra
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); // para que se mantenga pulsada
00428         runAction->setChecked(true); // porque comienza en ejecución
00429         runAction->setEnabled(false); // porque comienza en ejecución
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); // porque comienza en ejecución
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         // generamos el insert menu a partir de la lista que nos devuelve el controlador
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 // devuelve la lista de onlyParents seleccionados, si son almenos 2 comparten padre (tambien devuelve los link de dicha lista)
00534 QList<QGraphicsItem *> SlateWindow::selectedNodeGroup() const
00535 {
00536     QList<QGraphicsItem *> items = onlyParents(scene->selectedItems());
00537 
00538         //si quedan almemos dos
00539     if (items.count() > 1) {
00540                 // y si comparten padre
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 // obtiene los QGraphicsItem de la lista cuyo padre no pertenece a la lista
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 //         statusBar()->showMessage(tr("Saving canceled"), 2000);
00590         return false;
00591     }
00592 //     setCurrentFile(fileName);
00593 //     statusBar()->showMessage(tr("File saved"), 2000);
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); // lo muestra 10 segundos
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         // obtengo los niveles en que se encuentran los items, organizandolos por columnas en "levels"
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         //muevo los items en la pizarra en función de los tamaños y niveles de estos
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; //le sumo a bottom el alto mas un margen
00644                                 int width = (int)node->boundingRect().width();
00645                                 if (maxWidth < width) maxWidth = width; //actualiza maxWidth
00646                         }
00647                 }
00648                 left += maxWidth + MARGIN; //le sumo a left maxWide mas un margen
00649                 bottom = 20;//reseteo bottom
00650         }
00651 
00652         // vacio la estructura usada
00653         foreach(QList<ItemNode *> *levelNodes, levels) {
00654                 levelNodes->clear();
00655                 delete levelNodes;
00656         }
00657 }
00658 
00659 



QVision framework. PARP research group, copyright 2007, 2008.