00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <QVDesignerGUI>
00024 #include <QVApplication>
00025 #include <QVPropertyContainer>
00026 #include <QVPropertyContainerChange>
00027
00028 #include <QVVideoReaderBlock>
00029 #include <QVProcessingBlock>
00030 #include <QVImageCanvas>
00031 #include <QXmlStreamWriter>
00032 #include <QXmlStreamReader>
00033 #include "../qvplot.h"
00034 #include "facade/blockdialog.h"
00035
00036 #include "facade/imagecanvasdialog.h"
00037 #include "facade/camerablockdialog.h"
00038
00039 QVDesignerGUI::QVDesignerGUI(): QObject(), factory(), slate(this), informer(&slate)
00040 {
00041 qDebug() << "QVDesignerGUI::QVDesignerGUI()";
00042 if (qvApp == NULL)
00043 {
00044 QString str = "QVDesignerGUI::QVDesignerGUI(): the SlateGUI cannot be created before the QVApplication instance. Aborting now.";
00045 std::cerr << qPrintable(str) << std::endl;
00046 exit(1);
00047 }
00048
00049
00050 if (qvApp->forHelp()) return;
00051
00052 connect(&slate, SIGNAL(closed()), this, SLOT(quit()));
00053
00054 qvApp->registerGUI(this);
00055 qvApp->setTerminateOnLastBlock(false);
00056
00057
00058
00059
00060
00061 qDebug() << "QVDesignerGUI::QVDesignerGUI() <~ return";
00062 }
00063
00064 void QVDesignerGUI::init()
00065 {
00066
00067 foreach(QVPropertyContainer* qvp, qvApp->getQVPropertyContainers()) {
00068
00069 QVProcessingBlock* block;
00070 if((block = dynamic_cast<QVProcessingBlock*>(qvp)) != NULL) {
00071 QString registered = factory.registerUserBlock(block);
00072 if (!registered.isEmpty())
00073 slate.includeItemType(registered);
00074 }
00075
00076
00077 QString type = factory.containerType(qvp);
00078 QString name = qvp->getName();
00079 uint id = qvp->getId();
00080
00081 initialContainers.insert(id, qvp);
00082 createdItems.insert(id, CreatedItem(type, name, id));
00083
00084 connect(qvp->getInformer(), SIGNAL(changed(QVPropertyContainerChange)), this, SLOT(processChange(QVPropertyContainerChange)));
00085 slate.addItemNode(type, name, id, new ItemProperties(type, qvp));
00086
00087 createDialog(id);
00088 }
00089
00090
00091 foreach(QVPropertyContainer* qvp, qvApp->getQVPropertyContainers()) {
00092 foreach(QString prop, qvp->getPropertyList()) {
00093 QVPropertyContainer *source = qvp->getSourceContainer(prop);
00094 QString sourceProp = qvp->getSourceProperty(prop);
00095 bool sync = qvp->isSynchronous(prop);
00096 bool sequ = qvp->isSequential(prop);
00097
00098 if ( (source != NULL) && (!sourceProp.isEmpty()) ) {
00099 QString fromId = QString("%1").arg(source->getId());
00100 QString fromProp = sourceProp;
00101 QString toId = QString("%1").arg(qvp->getId());
00102 QString toProp = prop;
00103 QString linkName = getLinkName(fromId, fromProp, toId, toProp);
00104 createdLinks.insert(linkName, CreatedLink(source->getId(), fromProp, qvp->getId(), toProp, sync, sequ));
00105 slate.addLinkLine(source->getId(), fromProp, qvp->getId(), toProp, sync, sequ);
00106
00107 }
00108 }
00109 }
00110
00111
00112 slate.arrangeItems();
00113 }
00114
00115 void QVDesignerGUI::show()
00116 {
00117 slate.show();
00118 }
00119
00120 QMap<QString, QList<QString> > QVDesignerGUI::getItemTypes() const
00121 {
00122 return factory.getItemTypes();
00123 }
00124
00125 QMap<QString, QList<QString> > QVDesignerGUI::getInputItemTypes() const
00126 {
00127 return factory.getInputItemTypes();
00128 }
00129
00130 QMap<QString, QList<QString> > QVDesignerGUI::getMiddleItemTypes() const
00131 {
00132 return factory.getMiddleItemTypes();
00133 }
00134
00135 QMap<QString, QList<QString> > QVDesignerGUI::getOutputItemTypes() const
00136 {
00137 return factory.getOutputItemTypes();
00138 }
00139
00140 uint QVDesignerGUI::addItem(QString type, QString name, uint lastId)
00141 {
00142
00143 QVPropertyContainer *cont = factory.createContainer(type, name);
00144 if (cont != 0) {
00145 containers.insert(cont->getId(), cont);
00146 createdItems.insert(cont->getId(), CreatedItem(type, name, cont->getId()));
00147
00148 connect(cont->getInformer(), SIGNAL(changed(QVPropertyContainerChange)), this, SLOT(processChange(QVPropertyContainerChange)));
00149
00150 slate.addItemNode(type, name, cont->getId(), new ItemProperties(type, cont), lastId);
00151 return cont->getId();
00152 }
00153 return 0;
00154 }
00155
00156 bool QVDesignerGUI::setName(const uint id, const QString name)
00157 {
00158 if (containers.contains(id))
00159 containers.value(id)->setName(name);
00160 else if (initialContainers.contains(id))
00161 initialContainers.value(id)->setName(name);
00162 else
00163 return FALSE;
00164
00165 return TRUE;
00166 }
00167
00168 bool QVDesignerGUI::addLink(uint fromId, QString fromProp, uint toId, QString toProp, bool synchronous, bool sequential)
00169 {
00171 if (containers.contains(fromId) && containers.contains(toId)) {
00172 QVPropertyContainer *fromCont = containers.value(fromId);
00173 QVPropertyContainer *toCont = containers.value(toId);
00174
00175 QVVideoReaderBlock *cameraBlock;
00176 QVPropertyContainer::LinkType linkType = QVProcessingBlock::AsynchronousLink;
00177 if (synchronous) linkType = QVProcessingBlock::SynchronousLink;
00178 if (sequential) linkType = QVProcessingBlock::SequentialLink;
00179
00180
00182
00183
00184
00185 if((cameraBlock = dynamic_cast<QVVideoReaderBlock*>(fromCont)) != NULL)
00186 cameraBlock->linkProperty(toCont, toProp);
00187
00188 else if((dynamic_cast<QVImageCanvas*>(toCont)) != NULL)
00189 fromCont->linkProperty(fromProp, toCont, linkType);
00190
00191 else if((dynamic_cast<QVPlot*>(toCont)) != NULL)
00192 fromCont->linkProperty(fromProp, toCont, linkType);
00193
00194 else if(!fromCont->containsProperty(fromProp))
00195 fromCont->linkProperty(toCont, toProp, linkType);
00196
00197 else if(!toCont->containsProperty(toProp))
00198 fromCont->linkProperty(fromProp, toCont, linkType);
00199
00200 else
00201 fromCont->linkProperty(fromProp, toCont, toProp, linkType);
00202 }
00203 else
00204 return FALSE;
00205
00206 return TRUE;
00207 }
00208
00209 bool QVDesignerGUI::delItem(const uint id)
00210 {
00211 if (containers.contains(id)) {
00212
00213 factory.deleteContainer(containers.value(id));
00214 return true;
00215 }
00216 return false;
00217 }
00218
00219 bool QVDesignerGUI::delLink(const uint fromId, const QString fromProp, const uint toId, const QString toProp)
00220 {
00221 if (containers.contains(fromId) && containers.contains(toId))
00222 return containers.value(fromId)->unlinkProperty(fromProp, containers.value(toId), toProp);
00223 else
00224 return false;
00225 }
00226
00227 template <class Type> bool QVDesignerGUI::setProperty(const uint fromId, const QString fromProp, const Type &value)
00228 {
00229 return false;
00230 }
00231
00232 QString QVDesignerGUI::getLinkName(QVPropertyContainerChange change)
00233 {
00234 return getLinkName(QString("%1").arg(change.getOrigId()), change.getOrigProp(), QString("%1").arg(change.getDestId()), change.getDestProp());
00235 }
00236
00237 QString QVDesignerGUI::getLinkName(QString fromIdName, QString fromProp, QString toIdName, QString toProp)
00238 {
00239 return getAbsPropName(fromIdName, fromProp) + " => " + getAbsPropName(toIdName, toProp);
00240 }
00241
00242 QString QVDesignerGUI::getAbsPropName(QString fromIdName, QString fromProp)
00243 {
00244 return fromIdName + "[" + fromProp + "]";
00245 }
00246
00247
00248 void QVDesignerGUI::processChange(QVPropertyContainerChange change)
00249 {
00250 switch (change.getChangeType())
00251 {
00252 case QVPropertyContainerChange::Name:
00253 {
00254 uint id = change.getSourceId();
00255 QString name = change.getSourceName();
00256 if (createdItems.contains(id)) {
00257
00258 slate.setItemName(id, name);
00259 if (createdItems.contains(id)) createdItems[id].name = name;
00260 }
00261 }
00262 break;
00263
00264 case QVPropertyContainerChange::ContainerDel:
00265 {
00266 uint id = change.getSourceId();
00267 containers.remove(id);
00268 createdItems.remove(id);
00269 slate.delItemNode(id);
00270
00271
00272 deleteDialog(id);
00273
00274
00275 }
00276 break;
00277
00278 case QVPropertyContainerChange::PropertyAdd:
00279 if (createdItems.contains(change.getSourceId()))
00280 {
00281 uint srcId = change.getSourceId();
00282 QString propName = change.getPropName();
00283
00284 if (containers.contains(srcId))
00285 {
00286 QVPropertyContainer *cont = containers.value(srcId);
00287 int type = cont->getPropertyType(propName);
00288 bool in = cont->isInput(propName);
00289 bool out = cont->isOutput(propName);
00290 slate.addProperty(srcId, propName, type, in, out);
00291 }
00292
00293 }
00294 break;
00295
00296 case QVPropertyContainerChange::PropertyDel:
00297 if (createdItems.contains(change.getSourceId()))
00298 {
00299 uint srcId = change.getSourceId();
00300 QString propName = change.getPropName();
00301 slate.delProperty(srcId, propName);
00302
00303 }
00304 break;
00305
00306 case QVPropertyContainerChange::PropertyValue:
00307 break;
00308
00309 case QVPropertyContainerChange::LinkAdd:
00310 {
00311 uint fromId = change.getOrigId();
00312 QString fromProp = change.getOrigProp();
00313 uint toId = change.getDestId();
00314 QString toProp = change.getDestProp();
00315 QString linkName = getLinkName(change);
00316 if ( createdItems.contains(fromId) && createdItems.contains(toId) )
00317 {
00318 createdLinks.insert(linkName, CreatedLink(fromId, fromProp, toId, toProp, change.isSinc(), change.isSequ()));
00319 slate.addLinkLine(fromId, fromProp, toId, toProp, change.isSinc(), change.isSequ());
00320
00321 }
00322
00323
00324 }
00325 break;
00326
00327 case QVPropertyContainerChange::LinkDel:
00328 {
00329 uint fromId = change.getOrigId();
00330 QString fromProp = change.getOrigProp();
00331 uint toId = change.getDestId();
00332 QString toProp = change.getDestProp();
00333 QString linkName = getLinkName(change);
00334 if (createdLinks.contains(linkName))
00335 {
00336 createdLinks.remove(linkName);
00337 slate.delLinkLine(fromId, fromProp, toId, toProp);
00338
00339 }
00340 }
00341 break;
00342
00343 case QVPropertyContainerChange::All:
00344
00345 break;
00346
00347 default:
00348 break;
00349 }
00350 }
00351
00352
00353 void QVDesignerGUI::dialogChange(QVPropertyContainerChange change)
00354 {
00355 switch (change.getChangeType())
00356 {
00357 case QVPropertyContainerChange::PropertyValue:
00358 {
00359 uint dialogId = change.getSourceId();
00360 if (dialogsToContainers.contains(dialogId))
00361 {
00362 uint contId = dialogsToContainers.value(dialogId);
00363 QString prop = change.getPropName();
00364 propertyChanges.insert(getAbsPropName(QString("%1").arg(contId), prop), PropertyChange(contId, prop, change.getValue()));
00365 }
00366 break;
00367 }
00368
00369 default:
00370 break;
00371 }
00372 }
00373
00374 void QVDesignerGUI::showProperties(const uint id)
00375 {
00376 if (containers.contains(id)) {
00377 if (dialogs.contains(id)) {
00378 (dialogs.value(id))->show();
00379 }
00380 else {
00381 if (createDialog(id))
00382 (dialogs.value(id))->show();
00383 }
00384 }
00385 else if (initialContainers.contains(id)) {
00386 if (dialogs.contains(id)) {
00387 (dialogs.value(id))->show();
00388 }
00389 else {
00390 if (createDialog(id))
00391 (dialogs.value(id))->show();
00392 }
00393 }
00394 }
00395
00396 bool QVDesignerGUI::createDialog(const uint itemId)
00397 {
00398 QVPropertyContainer *cont;
00399 if (containers.contains(itemId))
00400 cont = containers.value(itemId);
00401 else if (initialContainers.contains(itemId))
00402 cont = initialContainers.value(itemId);
00403 else
00404 return false;
00405
00406 QVVideoReaderBlock *cameraBlock;
00407 QVProcessingBlock* block;
00408
00409 QVImageCanvas* imageCanvas;
00410 if((cameraBlock = dynamic_cast<QVVideoReaderBlock*>(cont)) != NULL) {
00411 CameraBlockDialog *dialog = new CameraBlockDialog(cameraBlock);
00412 dialogs.insert(itemId, dialog);
00413 dialogsToContainers.insert(dialog->getNodeId(), itemId);
00414 connect(dialog->getInformer(), SIGNAL(changed(QVPropertyContainerChange)), this, SLOT(dialogChange(QVPropertyContainerChange)));
00415 return true;
00416 }
00417 else if((block = dynamic_cast<QVProcessingBlock*>(cont)) != NULL) {
00418 BlockDialog *dialog = new BlockDialog(block);
00419 dialogs.insert(itemId, dialog);
00420 dialogsToContainers.insert(dialog->getNodeId(), itemId);
00421 connect(dialog->getInformer(), SIGNAL(changed(QVPropertyContainerChange)), this, SLOT(dialogChange(QVPropertyContainerChange)));
00422 return true;
00423 }
00425
00426
00427
00428
00429
00430
00431
00432 else if((imageCanvas = dynamic_cast<QVImageCanvas*>(cont)) != NULL) {
00433 ImageCanvasDialog * dialog = new ImageCanvasDialog(imageCanvas);
00434 dialogs.insert(itemId, dialog);
00435 dialogsToContainers.insert(dialog->getNodeId(), itemId);
00436 connect(dialog->getInformer(), SIGNAL(changed(QVPropertyContainerChange)), this, SLOT(dialogChange(QVPropertyContainerChange)));
00437 return true;
00438 }
00439 return false;
00440 }
00441
00442 void QVDesignerGUI::deleteDialog(const uint itemId)
00443 {
00444
00445 if (dialogs.contains(itemId)) {
00446 delete dialogs.value(itemId);
00447 dialogs.remove(itemId);
00448 }
00449 }
00450
00451 void QVDesignerGUI::run()
00452 {
00453
00454 foreach (uint id, containers.keys()) {
00455 if (!dialogs.contains(id))
00456 createDialog(id);
00457 }
00458
00459
00460 qvApp->startItems();
00461 }
00462
00463 void QVDesignerGUI::stop()
00464 {
00465
00466 QList<CreatedItem> lastItems = createdItems.values();
00467 QList<CreatedLink> lastLinks = createdLinks.values();
00468 QMap<uint, uint> oldId_To_NewId;
00469 QList<GroupInfo> lastGroups = slate.getGroups();
00470
00471
00472 qvApp->quitItems();
00473
00474
00475 qApp->processEvents();
00476
00477
00478 foreach (QVPropertyContainer * cont, initialContainers) {
00479 uint id = cont->getId();
00480 slate.delItemNode(id);
00481 deleteDialog(id);
00482 createdItems.remove(id);
00483 }
00484 initialContainers.clear();
00485
00486
00487 slate.eraseGroups();
00488
00489
00490 foreach (QVPropertyContainer * cont, containers) {
00491 factory.deleteContainer(cont);
00492 }
00493 dialogsToContainers.clear();
00494 createdLinks.clear();
00495
00496
00497 foreach (CreatedItem item, lastItems) {
00498 uint newId = addItem(item.type, item.name, item.id);
00499 oldId_To_NewId.insert(item.id, newId);
00500 if (newId == 0) std::cerr << "QVDesignerGUI - resetItems(): error al crear el Item " + item.name.toStdString() + "\n";
00501 }
00502
00503
00504 foreach (CreatedLink link, lastLinks) {
00505 if (oldId_To_NewId.contains(link.fromId) && (oldId_To_NewId.value(link.fromId) > 0) &&
00506 oldId_To_NewId.contains(link.toId) && (oldId_To_NewId.value(link.toId) > 0) ) {
00507 if (!addLink(oldId_To_NewId.value(link.fromId), link.fromProp, oldId_To_NewId.value(link.toId), link.toProp, link.synchronous, link.sequential))
00508 std::cerr << "QVDesignerGUI - resetItems(): error al crear el Link " + QString("%1").arg(link.fromId).toStdString() + " -> " + QString("%1").arg(link.toId).toStdString() + "\n";
00509 }
00510 }
00511
00512
00513 for (QMap<QString, PropertyChange>::iterator it = propertyChanges.begin(); it != propertyChanges.end(); it++) {
00514 if ( oldId_To_NewId.contains(it.value().id) && (oldId_To_NewId.value(it.value().id) > 0) ) {
00515 it.value().id = oldId_To_NewId.value(it.value().id);
00516 QVPropertyContainer *cont = containers.value(it.value().id);
00517 QString prop = it.value().propName;
00518 QVariant value = it.value().value;
00519
00520 if (cont->isType<int>(prop))
00521 cont->setPropertyValue<int>(prop, value.value<int>());
00522 else if (cont->isType<float>(prop))
00523 cont->setPropertyValue<float>(prop, value.value<float>());
00524 else if (cont->isType<bool>(prop))
00525 cont->setPropertyValue<bool>(prop, value.value<bool>());
00526 else if (cont->isType<double>(prop))
00527 cont->setPropertyValue<double>(prop, value.value<double>());
00528 else if (cont->isType<QString>(prop))
00529 cont->setPropertyValue<QString>(prop, value.value<QString>());
00530 else if (cont->isType<QVIndexedStringList>(prop))
00531 cont->setPropertyValue<QVIndexedStringList>(prop, value.value<QVIndexedStringList>());
00532 else
00533 std::cerr << "QVDesignerGUI - resetItems(): error al restaurar valor: " + getAbsPropName(QString("%1").arg(it.value().id), it.value().propName).toStdString() + "\n";
00534 }
00535 else
00536 std::cerr << "QVDesignerGUI - resetItems(): error al restaurar valor: " + getAbsPropName(QString("%1").arg(it.value().id), it.value().propName).toStdString() + "\n";
00537 }
00538
00540 createGroups(lastGroups, oldId_To_NewId);
00541 }
00542
00543 void QVDesignerGUI::createGroups(QList<GroupInfo> &lastGroups, QMap<uint, uint> &oldId_To_NewId) {
00544
00545
00546 for (QList<GroupInfo>::iterator it = lastGroups.begin(); it != lastGroups.end(); it++) {
00547
00548
00549 foreach (uint oldId, (*it).getNodes()) {
00550
00551
00552 if (oldId_To_NewId.contains(oldId)) {
00553 (*it).updateNodeId(oldId, oldId_To_NewId.value(oldId));
00554
00555 }
00556
00557 }
00558 }
00559
00560 bool reloop = true;
00561 while (reloop) {
00562
00563 QMap<uint, uint> changes;
00564 QList<GroupInfo>::iterator it = lastGroups.begin();
00565 while (it != lastGroups.end()) {
00566 uint oldId = (*it).getId();
00567
00568 uint newId = slate.createGroup(*it);
00569
00570
00571 if (newId > 0) {
00572 changes.insert(oldId, newId);
00573 it = lastGroups.erase(it);
00574
00575 }
00576 else it++;
00577
00578 }
00579 foreach (uint idChanged, changes.keys()) {
00580 for (QList<GroupInfo>::iterator it = lastGroups.begin(); it != lastGroups.end(); it++)
00581 foreach (uint oldId, (*it).getSubgroups())
00582 if (oldId == idChanged)
00583 (*it).updateSubgroupId(idChanged, changes.value(idChanged));
00584 }
00585 reloop = !changes.isEmpty();
00586 }
00587 }
00588
00589 void QVDesignerGUI::quit()
00590 {
00591 qvApp->deregisterGUI();
00592 qvApp->quit();
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00606
00607
00608 QString QVDesignerGUI::getCppText() const
00609 {
00610 QString result;
00611
00612
00613 result += "/*\n * Copyright (C) 2007, 2008, 2009. PARP Research Group.\n * <http://perception.inf.um.es>\n * University of Murcia, Spain.\n *\n * This file is part of the QVision library.\n *\n * QVision is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as\n * published by the Free Software Foundation, version 3 of the License.\n *\n * QVision is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with QVision. If not, see <http://www.gnu.org/licenses/>.\n */\n\n";
00614
00615
00616 result += "#include <QVApplication>\n#include <QVDefaultGUI>\n";
00617 QList<QString> types;
00618 foreach(CreatedItem item, createdItems.values()) {
00619 QString chopType = item.type;
00620 int espInd = chopType.indexOf(' ');
00621 int lesInd = chopType.indexOf('<');
00622 if ((espInd > 0) && (espInd < lesInd))
00623 types.append(chopType.left(espInd));
00624 else
00625 types.append(chopType.left(lesInd));
00626 }
00627 QSet<QString> unrepeatedTypes = types.toSet();
00628 foreach(QString unrepType, unrepeatedTypes) {
00629 if (factory.isUserType(unrepType))
00630 result += QString("class ") + unrepType + QString(";\n");
00631 else
00632 result += QString("#include <") + unrepType + QString(">\n");
00633 }
00634
00635 bool QVISLadded = FALSE;
00636 foreach(CreatedItem item, createdItems.values()) {
00637 foreach(PropertyChange change, propertyChanges.values()) {
00638 if ( (change.id == item.id) && (containers.value(item.id)->isType<QVIndexedStringList>(change.propName)) ) {
00639 result += QString("#include <QVIndexedStringList>\n");
00640 QVISLadded = TRUE;
00641 break;
00642 }
00643 }
00644 if (QVISLadded) break;
00645 }
00646
00647
00648 result += "\n#ifndef DOXYGEN_IGNORE_THIS\n\n";
00649 result += "int main(int argc, char *argv[])\n {\n QVApplication app(argc, argv, \"Example program for QVision library.\");\n\n";
00650
00651
00652 foreach(CreatedItem item, createdItems.values()) {
00653 result += QString(" ") + item.type + QString(" ") + item.name + QString("(\"") + item.name + QString("\");\n");
00654 }
00655 result += "\n QVDefaultGUI interface;\n\n";
00656
00657
00658 foreach(CreatedLink link, createdLinks.values()) {
00659 if (containers.contains(link.fromId) && containers.contains(link.toId)) {
00660 QVPropertyContainer *fromCont = containers.value(link.fromId);
00661 QVPropertyContainer *toCont = containers.value(link.toId);
00662
00663
00664 QVProcessingBlock* block;
00665 QVProcessingBlock* block2;
00666 QVImageCanvas* canvas;
00667 QVPlot* plot;
00668
00670
00671
00672
00673
00674
00675 if((block = dynamic_cast<QVProcessingBlock*>(fromCont)) != NULL) {
00676 if((block2 = dynamic_cast<QVProcessingBlock*>(toCont)) != NULL) {
00677 result += QString(" ") + fromCont->getName() + QString(".linkProperty(\"") + link.fromProp + QString("\", &");
00678 result += toCont->getName() + QString(", \"") + link.toProp;
00679 if (link.synchronous)
00680 result += QString("\", QVProcessingBlock::SynchronousLink);\n");
00681 else
00682 result += QString("\", QVProcessingBlock::AsynchronousLink);\n");
00683 }
00684 else if((canvas = dynamic_cast<QVImageCanvas*>(toCont)) != NULL) {
00685 result += QString(" ") + toCont->getName() + QString(".linkProperty(") + fromCont->getName() + QString(", \"") + link.fromProp + QString("\");\n");
00686 }
00687 else if((plot = dynamic_cast<QVPlot*>(toCont)) != NULL) {
00688 result += QString(" ") + toCont->getName() + QString(".linkProperty(") + fromCont->getName() + QString(", \"") + link.fromProp + QString("\");\n");
00689 }
00690 }
00691 }
00692 }
00693
00694
00695 result += "\n";
00696 foreach(CreatedItem item, createdItems.values()) {
00697 foreach(PropertyChange change, propertyChanges.values()) {
00698 if (change.id == item.id) {
00699 QVPropertyContainer *cont = containers.value(item.id);
00700 QString prop = change.propName;
00701 QVariant value = change.value;
00702
00703 if (cont->isType<int>(prop))
00704 result += QString(" ") + item.name + ".setPropertyValue<int>(\"" + prop + "\", " + value.toString() + ");\n";
00705 else if (cont->isType<bool>(prop))
00706 result += QString(" ") + item.name + ".setPropertyValue<bool>(\"" + prop + "\", " + value.toString() + ");\n";
00707 else if (cont->isType<double>(prop))
00708 result += QString(" ") + item.name + ".setPropertyValue<double>(\"" + prop + "\", " + value.toString() + ");\n";
00709 else if (cont->isType<QString>(prop))
00710 result += QString(" ") + item.name + ".setPropertyValue<QString>(\"" + prop + "\", " + value.toString() + ");\n";
00711 else if (cont->isType<QVIndexedStringList>(prop)) {
00712 QVIndexedStringList indlist = value.value<QVIndexedStringList>();
00713 result += QString(" QVIndexedStringList ") + "QVISLfor_" + item.name + ";\n";
00714 foreach (QString option, indlist) {
00715 result += QString(" QVISLfor_") + item.name + ".append(\"" + option + "\");\n";
00716 }
00717 result += QString(" QVISLfor_") + item.name + QString(".setIndex(%1);\n").arg(indlist.getIndex());
00718 result += QString(" ") + item.name + ".setPropertyValue<QVIndexedStringList>(\"" + prop + "\", QVISLfor_" + item.name + ");\n";
00719 }
00720 }
00721 }
00722 }
00723
00724
00725 result += "\n return app.exec();\n }\n\n#endif\n\n";
00726 return result;
00727 }
00728
00729 QString QVDesignerGUI::getXMLText()
00730 {
00731 QString text;
00732 QXmlStreamWriter xmlWriter(&text);
00733 xmlWriter.setAutoFormatting(true);
00734 uint xmlId = 1;
00735 QMap<uint, uint> ItemId_To_xmlId;
00736
00737 xmlWriter.writeStartDocument("1.0");
00738 xmlWriter.writeStartElement("QVApplication");
00739
00740
00741 xmlWriter.writeStartElement("Nodes");
00742 foreach(CreatedItem item, createdItems.values()) {
00743 xmlWriter.writeStartElement("Node");
00744 xmlWriter.writeAttribute("Type", item.type);
00745 xmlWriter.writeAttribute("Id", QString("%1").arg(xmlId));
00746 ItemId_To_xmlId.insert(item.id, xmlId++);
00747 xmlWriter.writeAttribute("Name", item.name);
00748 QPointF pos = slate.getNodePos(item.id);
00749 xmlWriter.writeAttribute("X", QString("%1").arg(pos.x()));
00750 xmlWriter.writeAttribute("Y", QString("%1").arg(pos.y()));
00751
00752
00753 foreach(PropertyChange change, propertyChanges.values()) {
00754 if (change.id == item.id) {
00755 QString strValue = change.value.toString();
00756 if (!strValue.isEmpty()) {
00757 xmlWriter.writeStartElement("Property");
00758 xmlWriter.writeAttribute("Name", change.propName);
00759 xmlWriter.writeAttribute("Value", strValue);
00760 xmlWriter.writeEndElement();
00761 }
00762 }
00763 }
00764 xmlWriter.writeEndElement();
00765 }
00766 xmlWriter.writeEndElement();
00767
00768
00769 xmlWriter.writeStartElement("Links");
00770 foreach (CreatedLink link, createdLinks.values()) {
00771 if ( (containers.contains(link.fromId) && containers.contains(link.toId)) ||
00772 (initialContainers.contains(link.fromId) && initialContainers.contains(link.toId)) ) {
00773 if (link.synchronous) xmlWriter.writeStartElement("SynchronousLink");
00774 else if (link.sequential) xmlWriter.writeStartElement("SequentialLink");
00775 else xmlWriter.writeStartElement("AsynchronousLink");
00776 xmlWriter.writeAttribute("FromId", QString("%1").arg(ItemId_To_xmlId.value(link.fromId)));
00777 xmlWriter.writeAttribute("FromProp", link.fromProp);
00778 xmlWriter.writeAttribute("ToId", QString("%1").arg(ItemId_To_xmlId.value(link.toId)));
00779 xmlWriter.writeAttribute("ToProp", link.toProp);
00780 xmlWriter.writeEndElement();
00781 }
00782 }
00783 xmlWriter.writeEndElement();
00784
00785
00786 xmlWriter.writeStartElement("Groups");
00787 QList<GroupInfo> groupList = slate.getGroups();
00788 foreach (GroupInfo group, groupList) {
00789 xmlWriter.writeStartElement("Group");
00790 xmlWriter.writeAttribute("Id", QString("%1").arg(group.getId()));
00791 xmlWriter.writeAttribute("Name", group.getName());
00792 QPointF pos =group.getPos();
00793 xmlWriter.writeAttribute("X", QString("%1").arg(pos.x()));
00794 xmlWriter.writeAttribute("Y", QString("%1").arg(pos.y()));
00795 foreach (uint nodeId, group.getNodes()) {
00796 xmlWriter.writeStartElement("ChildNode");
00797 xmlWriter.writeAttribute("Id", QString("%1").arg(ItemId_To_xmlId.value(nodeId)));
00798 xmlWriter.writeEndElement();
00799 }
00800 foreach (uint subId, group.getSubgroups()) {
00801 xmlWriter.writeStartElement("ChildGroup");
00802 xmlWriter.writeAttribute("Id", QString("%1").arg(subId));
00803 xmlWriter.writeEndElement();
00804 }
00805 foreach (LinkInfo link, group.getNodeLinks()) {
00806 xmlWriter.writeStartElement("VisibleNodeLink");
00807 xmlWriter.writeAttribute("ChildNode", QString("%1").arg(ItemId_To_xmlId.value(link.getNode())));
00808 xmlWriter.writeAttribute("Prop", link.getProp());
00809 xmlWriter.writeAttribute("Direction", link.getInput() ? "Input" : "Output");
00810 xmlWriter.writeEndElement();
00811 }
00812 foreach (LinkInfo link, group.getSubgroupLinks()) {
00813 xmlWriter.writeStartElement("VisibleGroupLink");
00814 xmlWriter.writeAttribute("ChildGroup", QString("%1").arg(link.getNode()));
00815 xmlWriter.writeAttribute("Prop", link.getProp());
00816 xmlWriter.writeAttribute("Direction", link.getInput() ? "Input" : "Output");
00817 xmlWriter.writeEndElement();
00818 }
00819 xmlWriter.writeEndElement();
00820 }
00821 xmlWriter.writeEndElement();
00822
00823 xmlWriter.writeEndElement();
00824 xmlWriter.writeEndDocument();
00825
00826 return text;
00827 }
00828
00829 bool QVDesignerGUI::loadXML(QString text)
00830 {
00831
00832 slate.eraseGroups();
00833 createdLinks.clear();
00834
00835 foreach (QVPropertyContainer * cont, containers) {
00836 factory.deleteContainer(cont);
00837 }
00838
00839 propertyChanges.clear();
00840 dialogsToContainers.clear();
00841
00842
00843
00844
00845
00846 QXmlStreamReader xmlReader(text);
00847
00848 while (!xmlReader.atEnd()) {
00849 xmlReader.readNext();
00850
00851 if (xmlReader.isEndElement())
00852 break;
00853
00854 if (xmlReader.isStartElement()) {
00855 if (xmlReader.name() == "QVApplication")
00856 readXMLQVApplication(xmlReader);
00857 else
00858 readXMLUnknownElement(xmlReader);
00859 }
00860 }
00861
00862 XMLId_To_ContainersId.clear();
00863
00864 if (xmlReader.hasError()) return false;
00865
00866 return true;
00867 }
00868
00869 bool QVDesignerGUI::readXMLQVApplication(QXmlStreamReader &xmlReader)
00870 {
00871 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "QVApplication");
00872
00873 while (!xmlReader.atEnd()) {
00874 xmlReader.readNext();
00875
00876 if (xmlReader.isEndElement())
00877 break;
00878
00879 if (xmlReader.isStartElement()) {
00880 if (xmlReader.name() == "Nodes")
00881 readXMLNodes(xmlReader);
00882 else if (xmlReader.name() == "Links")
00883 readXMLLinks(xmlReader);
00884 else if (xmlReader.name() == "Groups")
00885 readXMLGroups(xmlReader);
00886 else
00887 readXMLUnknownElement(xmlReader);
00888 }
00889 }
00890
00891 return true;
00892 }
00893
00894 bool QVDesignerGUI::readXMLNodes(QXmlStreamReader &xmlReader)
00895 {
00896 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "Nodes");
00897
00898 while (!xmlReader.atEnd()) {
00899 xmlReader.readNext();
00900
00901 if (xmlReader.isEndElement())
00902 break;
00903
00904 if (xmlReader.isStartElement()) {
00905 if (xmlReader.name() == "Node")
00906 readXMLNode(xmlReader);
00907 else
00908 readXMLUnknownElement(xmlReader);
00909 }
00910 }
00911
00912 return true;
00913 }
00914
00915 bool QVDesignerGUI::readXMLNode(QXmlStreamReader &xmlReader)
00916 {
00917 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "Node");
00918
00919 QXmlStreamAttributes attributes = xmlReader.attributes();
00920 QString type = attributes.value("Type").toString();
00921 QString XMLid = attributes.value("Id").toString();
00922 QString name = attributes.value("Name").toString();
00923 QString x = attributes.value("X").toString();
00924 QString y = attributes.value("Y").toString();
00925
00926
00927 uint itemId = addItem(type, name);
00928
00929 XMLId_To_ContainersId.insert(XMLid.toInt(), itemId);
00930 slate.moveNode(itemId, QPointF(x.toFloat(), y.toFloat()));
00931
00932 while (!xmlReader.atEnd()) {
00933 xmlReader.readNext();
00934
00935 if (xmlReader.isEndElement())
00936 break;
00937
00938 if (xmlReader.isStartElement()) {
00939 if (xmlReader.name() == "Property")
00940 readXMLProperty(xmlReader, itemId);
00941 else
00942 readXMLUnknownElement(xmlReader);
00943 }
00944 }
00945
00946 return true;
00947 }
00948
00949 bool QVDesignerGUI::readXMLProperty(QXmlStreamReader &xmlReader, uint id)
00950 {
00951 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "Property");
00952
00953 QXmlStreamAttributes attributes = xmlReader.attributes();
00954 QString name = attributes.value("Name").toString();
00955 QString value = attributes.value("Value").toString();
00956
00957 if (containers.contains(id)) {
00958 QVPropertyContainer *cont = containers.value(id);
00959
00960 if (cont->isType<int>(name)) {
00961 cont->setPropertyValue<int>(name, value.toInt());
00962 propertyChanges.insert(getAbsPropName(QString("%1").arg(id), name), PropertyChange(id, name, QVariant(value.toInt())));
00963 }
00964 if (cont->isType<float>(name)) {
00965 cont->setPropertyValue<float>(name, value.toFloat());
00966 propertyChanges.insert(getAbsPropName(QString("%1").arg(id), name), PropertyChange(id, name, QVariant(value.toFloat())));
00967 }
00968 else if (cont->isType<bool>(name)) {
00969 cont->setPropertyValue<bool>(name, (value == "true" ? true : false));
00970 propertyChanges.insert(getAbsPropName(QString("%1").arg(id), name), PropertyChange(id, name, QVariant((value == "true" ? true : false))));
00971 }
00972 else if (cont->isType<double>(name)) {
00973 cont->setPropertyValue<double>(name, value.toDouble());
00974 propertyChanges.insert(getAbsPropName(QString("%1").arg(id), name), PropertyChange(id, name, QVariant(value.toDouble())));
00975 }
00976 else if (cont->isType<QString>(name)) {
00977 cont->setPropertyValue<QString>(name, value);
00978 propertyChanges.insert(getAbsPropName(QString("%1").arg(id), name), PropertyChange(id, name, QVariant(value)));
00979 }
00980 }
00981
00982 while (!xmlReader.atEnd()) {
00983 xmlReader.readNext();
00984
00985 if (xmlReader.isEndElement())
00986 break;
00987
00988 if (xmlReader.isStartElement()) {
00989 readXMLUnknownElement(xmlReader);
00990 }
00991 }
00992
00993 return true;
00994 }
00995
00996 bool QVDesignerGUI::readXMLLinks(QXmlStreamReader &xmlReader)
00997 {
00998 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "Links");
00999
01000 while (!xmlReader.atEnd()) {
01001 xmlReader.readNext();
01002
01003 if (xmlReader.isEndElement())
01004 break;
01005
01006 if (xmlReader.isStartElement()) {
01007 if (xmlReader.name() == "AsynchronousLink")
01008 readXMLAsynchronousLink(xmlReader);
01009 else if (xmlReader.name() == "SynchronousLink")
01010 readXMLSynchronousLink(xmlReader);
01011 else if (xmlReader.name() == "SequentialLink")
01012 readXMLSequentialLink(xmlReader);
01013 else
01014 readXMLUnknownElement(xmlReader);
01015 }
01016 }
01017
01018 return true;
01019 }
01020
01021 bool QVDesignerGUI::readXMLAsynchronousLink(QXmlStreamReader &xmlReader)
01022 {
01023 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "AsynchronousLink");
01024
01025 QXmlStreamAttributes attributes = xmlReader.attributes();
01026 QString fromId = attributes.value("FromId").toString();
01027 QString fromProp = attributes.value("FromProp").toString();
01028 QString toId = attributes.value("ToId").toString();
01029 QString toProp = attributes.value("ToProp").toString();
01030
01031 addLink(XMLId_To_ContainersId.value(fromId.toUInt()), fromProp, XMLId_To_ContainersId.value(toId.toUInt()), toProp, false, false);
01032
01033 while (!xmlReader.atEnd()) {
01034 xmlReader.readNext();
01035
01036 if (xmlReader.isEndElement())
01037 break;
01038
01039 if (xmlReader.isStartElement()) {
01040 readXMLUnknownElement(xmlReader);
01041 }
01042 }
01043
01044 return true;
01045 }
01046
01047 bool QVDesignerGUI::readXMLSynchronousLink(QXmlStreamReader &xmlReader)
01048 {
01049 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "SynchronousLink");
01050
01051 QXmlStreamAttributes attributes = xmlReader.attributes();
01052 QString fromId = attributes.value("FromId").toString();
01053 QString fromProp = attributes.value("FromProp").toString();
01054 QString toId = attributes.value("ToId").toString();
01055 QString toProp = attributes.value("ToProp").toString();
01056
01057 addLink(XMLId_To_ContainersId.value(fromId.toUInt()), fromProp, XMLId_To_ContainersId.value(toId.toUInt()), toProp, true, false);
01058
01059 while (!xmlReader.atEnd()) {
01060 xmlReader.readNext();
01061
01062 if (xmlReader.isEndElement())
01063 break;
01064
01065 if (xmlReader.isStartElement()) {
01066 readXMLUnknownElement(xmlReader);
01067 }
01068 }
01069
01070 return true;
01071 }
01072
01073 bool QVDesignerGUI::readXMLSequentialLink(QXmlStreamReader &xmlReader)
01074 {
01075 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "SequentialLink");
01076
01077 QXmlStreamAttributes attributes = xmlReader.attributes();
01078 QString fromId = attributes.value("FromId").toString();
01079 QString fromProp = attributes.value("FromProp").toString();
01080 QString toId = attributes.value("ToId").toString();
01081 QString toProp = attributes.value("ToProp").toString();
01082
01083 addLink(XMLId_To_ContainersId.value(fromId.toUInt()), fromProp, XMLId_To_ContainersId.value(toId.toUInt()), toProp, false, true);
01084
01085 while (!xmlReader.atEnd()) {
01086 xmlReader.readNext();
01087
01088 if (xmlReader.isEndElement())
01089 break;
01090
01091 if (xmlReader.isStartElement()) {
01092 readXMLUnknownElement(xmlReader);
01093 }
01094 }
01095
01096 return true;
01097 }
01098
01099 bool QVDesignerGUI::readXMLGroups(QXmlStreamReader &xmlReader) {
01100 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "Groups");
01101
01102 QList<GroupInfo> groupInfos;
01103
01104 while (!xmlReader.atEnd()) {
01105 xmlReader.readNext();
01106
01107 if (xmlReader.isEndElement())
01108 break;
01109
01110 if (xmlReader.isStartElement()) {
01111 if (xmlReader.name() == "Group")
01112 readXMLGroup(xmlReader, groupInfos);
01113 else
01114 readXMLUnknownElement(xmlReader);
01115 }
01116 }
01117
01118 createGroups(groupInfos, XMLId_To_ContainersId);
01119
01120 return true;
01121 }
01122
01123 bool QVDesignerGUI::readXMLGroup(QXmlStreamReader &xmlReader, QList<GroupInfo> &groupInfos) {
01124 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "Group");
01125
01126 QXmlStreamAttributes attributes = xmlReader.attributes();
01127 QString XMLid = attributes.value("Id").toString();
01128 QString name = attributes.value("Name").toString();
01129 QString x = attributes.value("X").toString();
01130 QString y = attributes.value("Y").toString();
01131
01132 GroupInfo groupInfo(XMLid.toInt(), name);
01133 groupInfo.setPos(QPointF(x.toFloat(), y.toFloat()));
01134 groupInfo.setAbstract(false);
01135
01136 while (!xmlReader.atEnd()) {
01137 xmlReader.readNext();
01138
01139 if (xmlReader.isEndElement())
01140 break;
01141
01142 if (xmlReader.isStartElement()) {
01143 if (xmlReader.name() == "ChildNode")
01144 readXMLChildNode(xmlReader, groupInfo);
01145 else if (xmlReader.name() == "ChildGroup")
01146 readXMLChildGroup(xmlReader, groupInfo);
01147 else if (xmlReader.name() == "VisibleNodeLink")
01148 readXMLVisibleNodeLink(xmlReader, groupInfo);
01149 else if (xmlReader.name() == "VisibleGroupLink")
01150 readXMLVisibleGroupLink(xmlReader, groupInfo);
01151 else
01152 readXMLUnknownElement(xmlReader);
01153 }
01154 }
01155
01156 groupInfos.append(groupInfo);
01157
01158 return true;
01159 }
01160
01161 bool QVDesignerGUI::readXMLChildNode(QXmlStreamReader &xmlReader, GroupInfo &groupInfo) {
01162 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "ChildNode");
01163
01164 QXmlStreamAttributes attributes = xmlReader.attributes();
01165 QString XMLid = attributes.value("Id").toString();
01166
01167 groupInfo.addNode(XMLid.toInt());
01168
01169 while (!xmlReader.atEnd()) {
01170 xmlReader.readNext();
01171
01172 if (xmlReader.isEndElement())
01173 break;
01174
01175 if (xmlReader.isStartElement()) {
01176 readXMLUnknownElement(xmlReader);
01177 }
01178 }
01179
01180 return true;
01181 }
01182
01183 bool QVDesignerGUI::readXMLChildGroup(QXmlStreamReader &xmlReader, GroupInfo &groupInfo) {
01184 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "ChildGroup");
01185
01186 QXmlStreamAttributes attributes = xmlReader.attributes();
01187 QString XMLid = attributes.value("Id").toString();
01188
01189 groupInfo.addSubgroup(XMLid.toInt());
01190
01191 while (!xmlReader.atEnd()) {
01192 xmlReader.readNext();
01193
01194 if (xmlReader.isEndElement())
01195 break;
01196
01197 if (xmlReader.isStartElement()) {
01198 readXMLUnknownElement(xmlReader);
01199 }
01200 }
01201
01202 return true;
01203 }
01204
01205 bool QVDesignerGUI::readXMLVisibleNodeLink(QXmlStreamReader &xmlReader, GroupInfo &groupInfo) {
01206 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "VisibleNodeLink");
01207
01208 QXmlStreamAttributes attributes = xmlReader.attributes();
01209 QString XMLid = attributes.value("ChildNode").toString();
01210 QString prop = attributes.value("Prop").toString();
01211 QString direction = attributes.value("Direction").toString();
01212
01213 groupInfo.addNodeLink(LinkInfo(XMLid.toInt(), prop, direction == "Input" ? true : false));
01214
01215 while (!xmlReader.atEnd()) {
01216 xmlReader.readNext();
01217
01218 if (xmlReader.isEndElement())
01219 break;
01220
01221 if (xmlReader.isStartElement()) {
01222 readXMLUnknownElement(xmlReader);
01223 }
01224 }
01225
01226 return true;
01227 }
01228
01229 bool QVDesignerGUI::readXMLVisibleGroupLink(QXmlStreamReader &xmlReader, GroupInfo &groupInfo) {
01230 Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == "VisibleGroupLink");
01231
01232 QXmlStreamAttributes attributes = xmlReader.attributes();
01233 QString XMLid = attributes.value("ChildGroup").toString();
01234 QString prop = attributes.value("Prop").toString();
01235 QString direction = attributes.value("Direction").toString();
01236
01237 groupInfo.addSubgroupLink(LinkInfo(XMLid.toInt(), prop, direction == "Input" ? true : false));
01238
01239 while (!xmlReader.atEnd()) {
01240 xmlReader.readNext();
01241
01242 if (xmlReader.isEndElement())
01243 break;
01244
01245 if (xmlReader.isStartElement()) {
01246 readXMLUnknownElement(xmlReader);
01247 }
01248 }
01249
01250 return true;
01251 }
01252
01253 bool QVDesignerGUI::readXMLUnknownElement(QXmlStreamReader &xmlReader)
01254 {
01255 Q_ASSERT(xmlReader.isStartElement());
01256
01257
01258
01259 while (!xmlReader.atEnd()) {
01260 xmlReader.readNext();
01261
01262 if (xmlReader.isEndElement())
01263 break;
01264
01265 if (xmlReader.isStartElement())
01266 readXMLUnknownElement(xmlReader);
01267 }
01268
01269 return true;
01270 }
01271