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 #include <QVMPlayerCamera>
00028 #include <QVWorker>
00029 #include <QVImageCanvas>
00030 #include <qvgui/qvplot.h>
00031 #include <qvgui/qvdesigner/facade/workerdialog.h>
00032 #include <qvgui/qvdesigner/facade/cameradialog.h>
00033 #include <qvgui/qvdesigner/facade/imagecanvasdialog.h>
00034
00035 QVDesignerGUI::QVDesignerGUI(): QObject(), factory(), slate(this), informer(&slate)
00036 {
00037 qDebug() << "QVDesignerGUI::QVDesignerGUI()";
00038 if (qvApp == NULL)
00039 {
00040 QString str = "QVDesignerGUI::QVDesignerGUI(): the SlateGUI cannot be created before the QVApplication instance. Aborting now.";
00041 std::cerr << qPrintable(str) << std::endl;
00042 exit(1);
00043 }
00044
00045
00046 if (qvApp->forHelp()) return;
00047
00048 connect(&slate, SIGNAL(closed()), this, SLOT(quit()));
00049
00050 qvApp->registerGUI(this);
00051 qvApp->setTerminateOnLastWorker(false);
00052
00053
00054
00055
00056
00057 qDebug() << "QVDesignerGUI::QVDesignerGUI() <~ return";
00058 }
00059
00060 void QVDesignerGUI::init()
00061 {
00062
00063 foreach(QVPropertyContainer* qvp, qvApp->getQVPropertyContainers()) {
00064
00065 QVWorker* worker;
00066 if((worker = dynamic_cast<QVWorker*>(qvp)) != NULL) {
00067 QString registered = factory.registerUserWorker(worker);
00068 if (!registered.isEmpty())
00069 slate.includeItemType(registered);
00070 }
00071
00072
00073 QString type = factory.containerType(qvp);
00074 QString name = qvp->getName();
00075
00076 initialContainers.insert(name, qvp);
00077 createdItems.insert(name, CreatedItem(type, name));
00078
00079 connect(qvp->getInformer(), SIGNAL(changed(QVPropertyContainerChange)), this, SLOT(processChange(QVPropertyContainerChange)));
00080 slate.addItemNode(type, name, new ItemProperties(type, qvp));
00081
00082 createDialog(name);
00083 }
00084
00085
00086 foreach(QVPropertyContainer* qvp, qvApp->getQVPropertyContainers()) {
00087 foreach(QString prop, qvp->getPropertyList()) {
00088 QVPropertyContainer *source = qvp->getSourceContainer(prop);
00089 QString sourceProp = qvp->getSourceProperty(prop);
00090 bool sync = qvp->isSynchronous(prop);
00091 bool sequ = qvp->isSequential(prop);
00092
00093 if ( (source != NULL) && (!sourceProp.isEmpty()) ) {
00094 QString fromName = source->getName();
00095 QString fromProp = sourceProp;
00096 QString toName = qvp->getName();
00097 QString toProp = prop;
00098 QString linkName = getLinkName(fromName, fromProp, toName, toProp);
00099 createdLinks.insert(linkName, CreatedLink(fromName, fromProp, toName, toProp, sync, sequ));
00100 slate.addLinkLine(fromName, fromProp, toName, toProp, sync, sequ);
00101
00102 }
00103 }
00104 }
00105
00106
00107 slate.arrangeItems();
00108 }
00109
00110 void QVDesignerGUI::show()
00111 {
00112 slate.show();
00113 }
00114
00115 QList<QString> QVDesignerGUI::getItemTypes() const
00116 {
00117 return factory.getItemTypes();
00118 }
00119
00120 QList<QString> QVDesignerGUI::getInputItemTypes() const
00121 {
00122 return factory.getInputItemTypes();
00123 }
00124
00125 QList<QString> QVDesignerGUI::getMiddleItemTypes() const
00126 {
00127 return factory.getMiddleItemTypes();
00128 }
00129
00130 QList<QString> QVDesignerGUI::getOutputItemTypes() const
00131 {
00132 return factory.getOutputItemTypes();
00133 }
00134
00136 bool QVDesignerGUI::addItem(QString type, QString name)
00137 {
00138 if (containers.contains(name)) return FALSE;
00139
00140
00141 QVPropertyContainer *cont = factory.createContainer(type, name);
00142 if (cont != 0) {
00143 containers.insert(name, cont);
00144 createdItems.insert(name, CreatedItem(type, name));
00145
00146 connect(cont->getInformer(), SIGNAL(changed(QVPropertyContainerChange)), this, SLOT(processChange(QVPropertyContainerChange)));
00147
00148 slate.addItemNode(type, name, new ItemProperties(type, cont));
00149 return TRUE;
00150 }
00151 return FALSE;
00152 }
00153
00154 bool QVDesignerGUI::addLink(QString fromName, QString fromProp, QString toName, QString toProp, bool synchronous, bool sequential)
00155 {
00157 if (containers.contains(fromName) && containers.contains(toName)) {
00158 QVPropertyContainer *fromCont = containers.value(fromName);
00159 QVPropertyContainer *toCont = containers.value(toName);
00160
00161 QVMPlayerCamera* camera;
00162 QVImageCanvas* canvas;
00163 QVPlot* plot;
00164 QVPropertyContainer::LinkType linkType = QVWorker::AsynchronousLink;
00165 if (synchronous) linkType = QVWorker::SynchronousLink;
00166 if (sequential) linkType = QVWorker::SequentialLink;
00167
00168
00169 if((camera = dynamic_cast<QVMPlayerCamera*>(fromCont)) != NULL)
00170 fromCont->linkProperty(toCont, toProp, linkType);
00171
00172 else if((canvas = dynamic_cast<QVImageCanvas*>(toCont)) != NULL)
00173 fromCont->linkProperty(fromProp, toCont, linkType);
00174
00175 else if((plot = dynamic_cast<QVPlot*>(toCont)) != NULL)
00176 fromCont->linkProperty(fromProp, toCont, linkType);
00177
00178 else if(!fromCont->containsProperty(fromProp))
00179 fromCont->linkProperty(toCont, toProp, linkType);
00180
00181 else if(!toCont->containsProperty(toProp))
00182 fromCont->linkProperty(fromProp, toCont, linkType);
00183
00184 else
00185 fromCont->linkProperty(fromProp, toCont, toProp, linkType);
00186 }
00187 return TRUE;
00188 }
00189
00190 bool QVDesignerGUI::delItem(const QString name)
00191 {
00192 if (containers.contains(name)) {
00193
00194 factory.deleteContainer(containers.value(name));
00195 return true;
00196 }
00197 return false;
00198 }
00199
00200 bool QVDesignerGUI::delLink(const QString fromName, const QString fromProp, const QString toName, const QString toProp)
00201 {
00202 if (containers.contains(fromName) && containers.contains(toName))
00203 return containers.value(fromName)->unlinkProperty(fromProp, containers.value(toName), toProp);
00204 else
00205 return false;
00206 }
00207
00208 template <class Type> bool QVDesignerGUI::setProperty(const QString fromName, const QString fromProp, const Type &value)
00209 {
00210 return false;
00211 }
00212
00213 QString QVDesignerGUI::getLinkName(QVPropertyContainerChange change)
00214 {
00215 return getLinkName(change.getOrigName(), change.getOrigProp(), change.getDestName(), change.getDestProp());
00216 }
00217
00218 QString QVDesignerGUI::getLinkName(QString fromName, QString fromProp, QString toName, QString toProp)
00219 {
00220 return getAbsPropName(fromName, fromProp) + " => " + getAbsPropName(toName, toProp);
00221 }
00222
00223 QString QVDesignerGUI::getAbsPropName(QString fromName, QString fromProp)
00224 {
00225 return fromName + "[" + fromProp + "]";
00226 }
00227
00228
00229 void QVDesignerGUI::processChange(QVPropertyContainerChange change)
00230 {
00231 switch (change.getChangeType())
00232 {
00233 case QVPropertyContainerChange::Name:
00234 if (createdItems.contains(change.getSourceName()))
00235 ;
00236 break;
00237
00238
00239
00240
00241
00242 case QVPropertyContainerChange::ContainerDel:
00243 {
00244 QString name = change.getSourceName();
00245 containers.remove(name);
00246 createdItems.remove(name);
00247 slate.delItemNode(name);
00248
00249
00250 deleteDialog(name);
00251
00252
00253 }
00254 break;
00255
00256 case QVPropertyContainerChange::PropertyAdd:
00257 if (createdItems.contains(change.getSourceName()))
00258 {
00259 QString srcName = change.getSourceName();
00260 QString propName = change.getPropName();
00261
00262 if (containers.contains(srcName))
00263 {
00264 QVPropertyContainer *cont = containers.value(srcName);
00265 int type = cont->getPropertyType(propName);
00266 bool in = cont->isInput(propName);
00267 bool out = cont->isOutput(propName);
00268 slate.addProperty(srcName, propName, type, in, out);
00269 }
00270
00271 }
00272 break;
00273
00274 case QVPropertyContainerChange::PropertyDel:
00275 if (createdItems.contains(change.getSourceName()))
00276 {
00277 QString srcName = change.getSourceName();
00278 QString propName = change.getPropName();
00279 slate.delProperty(srcName, propName);
00280
00281 }
00282 break;
00283
00284 case QVPropertyContainerChange::PropertyValue:
00285 break;
00286
00287 case QVPropertyContainerChange::LinkAdd:
00288 {
00289 QString fromName = change.getOrigName();
00290 QString fromProp = change.getOrigProp();
00291 QString toName = change.getDestName();
00292 QString toProp = change.getDestProp();
00293 QString linkName = getLinkName(change);
00294 if ( createdItems.contains(change.getOrigName()) && createdItems.contains(change.getDestName()) )
00295 {
00296 createdLinks.insert(linkName, CreatedLink(fromName, fromProp, toName, toProp, change.isSinc(), change.isSequ()));
00297 slate.addLinkLine(fromName, fromProp, toName, toProp, change.isSinc(), change.isSequ());
00298
00299 }
00300
00301
00302 }
00303 break;
00304
00305 case QVPropertyContainerChange::LinkDel:
00306 {
00307 QString fromName = change.getOrigName();
00308 QString fromProp = change.getOrigProp();
00309 QString toName = change.getDestName();
00310 QString toProp = change.getDestProp();
00311 QString linkName = getLinkName(change);
00312 if (createdLinks.contains(linkName))
00313 {
00314 createdLinks.remove(linkName);
00315 slate.delLinkLine(fromName, fromProp, toName, toProp);
00316
00317 }
00318 }
00319 break;
00320
00321 case QVPropertyContainerChange::All:
00322
00323 break;
00324
00325 default:
00326 break;
00327 }
00328 }
00329 void QVDesignerGUI::dialogChange(QVPropertyContainerChange change)
00330 {
00331 switch (change.getChangeType())
00332 {
00333 case QVPropertyContainerChange::PropertyValue:
00334 {
00335 QString cont = change.getSourceName(); cont.remove(0, 28);
00336 QString prop = change.getPropName();
00337 propertyChanges.insert(getAbsPropName(cont, prop), PropertyChange(cont, prop, change.getValue()));
00338 break;
00339 }
00340
00341 default:
00342 break;
00343 }
00344 }
00345
00346 void QVDesignerGUI::showProperties(const QString itemName)
00347 {
00348 if (containers.contains(itemName)) {
00349 if (dialogs.contains(itemName)) {
00350 (dialogs.value(itemName))->show();
00351 }
00352 else {
00353 if (createDialog(itemName))
00354 (dialogs.value(itemName))->show();
00355 }
00356 }
00357 else if (initialContainers.contains(itemName)) {
00358 if (dialogs.contains(itemName)) {
00359 (dialogs.value(itemName))->show();
00360 }
00361 else {
00362 if (createDialog(itemName))
00363 (dialogs.value(itemName))->show();
00364 }
00365 }
00366 }
00367
00368 bool QVDesignerGUI::createDialog(const QString itemName)
00369 {
00370 QVPropertyContainer *cont;
00371 if (containers.contains(itemName))
00372 cont = containers.value(itemName);
00373 else
00374 cont = initialContainers.value(itemName);
00375
00376 QVWorker* worker;
00377 QVMPlayerCamera* camera;
00378 QVImageCanvas* imageCanvas;
00379 if((worker = dynamic_cast<QVWorker*>(cont)) != NULL) {
00380 WorkerDialog *dialog = new WorkerDialog(worker);
00381 dialogs.insert(itemName, dialog);
00382 connect(dialog->getInformer(), SIGNAL(changed(QVPropertyContainerChange)), this, SLOT(dialogChange(QVPropertyContainerChange)));
00383 return true;
00384 }
00385 else if((camera = dynamic_cast<QVMPlayerCamera*>(cont)) != NULL) {
00386 CameraDialog * dialog = new CameraDialog(camera);
00387 dialogs.insert(itemName, dialog);
00388 connect(dialog->getInformer(), SIGNAL(changed(QVPropertyContainerChange)), this, SLOT(dialogChange(QVPropertyContainerChange)));
00389 return true;
00390 }
00391 else if((imageCanvas = dynamic_cast<QVImageCanvas*>(cont)) != NULL) {
00392 ImageCanvasDialog * dialog = new ImageCanvasDialog(imageCanvas);
00393 dialogs.insert(itemName, dialog);
00394 connect(dialog->getInformer(), SIGNAL(changed(QVPropertyContainerChange)), this, SLOT(dialogChange(QVPropertyContainerChange)));
00395 return true;
00396 }
00397 return false;
00398 }
00399
00400 void QVDesignerGUI::deleteDialog(const QString itemName)
00401 {
00402
00403 if (dialogs.contains(itemName)) {
00404 delete dialogs.value(itemName);
00405 dialogs.remove(itemName);
00406 }
00407 }
00408
00409 void QVDesignerGUI::run()
00410 {
00411
00412 foreach (QString itemName, containers.keys()) {
00413 if (!dialogs.contains(itemName))
00414 createDialog(itemName);
00415 }
00416
00417
00418 qvApp->startItems();
00419 }
00420
00421 void QVDesignerGUI::stop()
00422 {
00423
00424 QList<CreatedItem> lastItems = createdItems.values();
00425 QList<CreatedLink> lastLinks = createdLinks.values();
00426 QList<PropertyChange> lastChanges = propertyChanges.values();
00427
00428
00429 qvApp->quitItems();
00430
00431
00432 qApp->processEvents();
00433
00434
00435 foreach (QVPropertyContainer * cont, initialContainers) {
00436 QString name = cont->getName();
00437 slate.delItemNode(name);
00438 deleteDialog(name);
00439 }
00440 initialContainers.clear();
00441
00442
00443 foreach (QVPropertyContainer * cont, containers) {
00444 factory.deleteContainer(cont);
00445 }
00446
00447
00448 foreach (CreatedItem item, lastItems) {
00449 if (!addItem(item.type, item.name))
00450 std::cerr << "QVDesignerGUI - resetItems(): error al crear el Item " + item.name.toStdString() + "\n";
00451 }
00452
00453
00454 foreach (CreatedLink link, lastLinks) {
00455 if (!addLink(link.fromName, link.fromProp, link.toName, link.toProp, link.synchronous, link.sequential))
00456 std::cerr << "QVDesignerGUI - resetItems(): error al crear el Link " + link.fromName.toStdString() + " -> " + link.toName.toStdString() + "\n";
00457 }
00458
00459
00460 foreach (PropertyChange change, lastChanges) {
00461 QString itemName = change.contName;
00462
00463 if (containers.contains(itemName)) {
00464 QVPropertyContainer *cont = containers.value(itemName);
00465 QString prop = change.propName;
00466 QVariant value = change.value;
00467
00468 if (cont->isType<int>(prop))
00469 cont->setPropertyValue<int>(prop, value.value<int>());
00470 else if (cont->isType<bool>(prop))
00471 cont->setPropertyValue<bool>(prop, value.value<bool>());
00472 else if (cont->isType<double>(prop))
00473 cont->setPropertyValue<double>(prop, value.value<double>());
00474 else if (cont->isType<QString>(prop))
00475 cont->setPropertyValue<QString>(prop, value.value<QString>());
00476 else if (cont->isType<QVIndexedStringList>(prop))
00477 cont->setPropertyValue<QVIndexedStringList>(prop, value.value<QVIndexedStringList>());
00478 else
00479 std::cerr << "QVDesignerGUI - resetItems(): error al restaurar valor: " + getAbsPropName(change.contName, change.propName).toStdString() + "\n";
00480 }
00481 else
00482 std::cerr << "QVDesignerGUI - resetItems(): error al restaurar valor: " + getAbsPropName(change.contName, change.propName).toStdString() + "\n";
00483 }
00484 }
00485
00486 void QVDesignerGUI::quit()
00487 {
00488 qvApp->deregisterGUI();
00489 qvApp->quit();
00490 }
00491
00492 QString QVDesignerGUI::getCppText() const
00493 {
00494 QString result;
00495
00496
00497 result += "/*\n * Copyright (C) 2007, 2008. 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";
00498
00499
00500 result += "#include <QVApplication>\n#include <QVDefaultGUI>\n";
00501 QList<QString> types;
00502 foreach(CreatedItem item, createdItems.values()) {
00503 QString chopType = item.type;
00504 int espInd = chopType.indexOf(' ');
00505 int lesInd = chopType.indexOf('<');
00506 if ((espInd > 0) && (espInd < lesInd))
00507 types.append(chopType.left(espInd));
00508 else
00509 types.append(chopType.left(lesInd));
00510 }
00511 QSet<QString> unrepeatedTypes = types.toSet();
00512 foreach(QString unrepType, unrepeatedTypes) {
00513 if (factory.isUserType(unrepType))
00514 result += QString("class ") + unrepType + QString(";\n");
00515 else
00516 result += QString("#include <") + unrepType + QString(">\n");
00517 }
00518
00519 bool QVISLadded = FALSE;
00520 foreach(CreatedItem item, createdItems.values()) {
00521 foreach(PropertyChange change, propertyChanges.values()) {
00522 if ( (change.contName == item.name) && (containers.value(item.name)->isType<QVIndexedStringList>(change.propName)) ) {
00523 result += QString("#include <QVIndexedStringList>\n");
00524 QVISLadded = TRUE;
00525 break;
00526 }
00527 }
00528 if (QVISLadded) break;
00529 }
00530
00531
00532 result += "\n#ifndef DOXYGEN_IGNORE_THIS\n\n";
00533 result += "int main(int argc, char *argv[])\n {\n QVApplication app(argc, argv, \"Example program for QVision library.\");\n\n";
00534
00535
00536 foreach(CreatedItem item, createdItems.values()) {
00537 result += QString(" ") + item.type + QString(" ") + item.name + QString("(\"") + item.name + QString("\");\n");
00538 }
00539 result += "\n QVDefaultGUI interface;\n\n";
00540
00541
00542 foreach(CreatedLink link, createdLinks.values()) {
00543 if (containers.contains(link.fromName) && containers.contains(link.toName)) {
00544 QVPropertyContainer *fromCont = containers.value(link.fromName);
00545 QVPropertyContainer *toCont = containers.value(link.toName);
00546
00547 QVMPlayerCamera* camera;
00548 QVWorker* worker;
00549 QVWorker* worker2;
00550 QVImageCanvas* canvas;
00551 QVPlot* plot;
00552
00553 if((camera = dynamic_cast<QVMPlayerCamera*>(fromCont)) != NULL) {
00554 if((worker = dynamic_cast<QVWorker*>(toCont)) != NULL) {
00555 result += QString(" ") + link.fromName + QString(".link(&") + link.toName + QString(", \"") + link.toProp + QString("\");\n");
00556 }
00557 }
00558 else if((worker = dynamic_cast<QVWorker*>(fromCont)) != NULL) {
00559 if((worker2 = dynamic_cast<QVWorker*>(toCont)) != NULL) {
00560 result += QString(" ") + link.fromName + QString(".linkProperty(\"") + link.fromProp + QString("\", &");
00561 result += link.toName + QString(", \"") + link.toProp;
00562 if (link.synchronous)
00563 result += QString("\", QVWorker::SynchronousLink);\n");
00564 else
00565 result += QString("\", QVWorker::AsynchronousLink);\n");
00566 }
00567 else if((canvas = dynamic_cast<QVImageCanvas*>(toCont)) != NULL) {
00568 result += QString(" ") + link.toName + QString(".linkProperty(") + link.fromName + QString(", \"") + link.fromProp + QString("\");\n");
00569 }
00570 else if((plot = dynamic_cast<QVPlot*>(toCont)) != NULL) {
00571 result += QString(" ") + link.toName + QString(".linkProperty(") + link.fromName + QString(", \"") + link.fromProp + QString("\");\n");
00572 }
00573 }
00574 }
00575 }
00576
00577
00578 result += "\n";
00579 foreach(CreatedItem item, createdItems.values()) {
00580 foreach(PropertyChange change, propertyChanges.values()) {
00581 if (change.contName == item.name) {
00582 QVPropertyContainer *cont = containers.value(item.name);
00583 QString prop = change.propName;
00584 QVariant value = change.value;
00585
00586 if (cont->isType<int>(prop))
00587 result += QString(" ") + item.name + ".setPropertyValue<int>(\"" + prop + "\", " + value.toString() + ");\n";
00588 else if (cont->isType<bool>(prop))
00589 result += QString(" ") + item.name + ".setPropertyValue<bool>(\"" + prop + "\", " + value.toString() + ");\n";
00590 else if (cont->isType<double>(prop))
00591 result += QString(" ") + item.name + ".setPropertyValue<double>(\"" + prop + "\", " + value.toString() + ");\n";
00592 else if (cont->isType<QString>(prop))
00593 result += QString(" ") + item.name + ".setPropertyValue<QString>(\"" + prop + "\", " + value.toString() + ");\n";
00594 else if (cont->isType<QVIndexedStringList>(prop)) {
00595 QVIndexedStringList indlist = value.value<QVIndexedStringList>();
00596 result += QString(" QVIndexedStringList ") + "QVISLfor_" + item.name + ";\n";
00597 foreach (QString option, indlist) {
00598 result += QString(" QVISLfor_") + item.name + ".append(\"" + option + "\");\n";
00599 }
00600 result += QString(" QVISLfor_") + item.name + QString(".setIndex(%1);\n").arg(indlist.getIndex());
00601 result += QString(" ") + item.name + ".setPropertyValue<QVIndexedStringList>(\"" + prop + "\", QVISLfor_" + item.name + ");\n";
00602 }
00603 }
00604 }
00605 }
00606
00607
00608 result += "\n return app.exec();\n }\n\n#endif\n\n";
00609 return result;
00610 }
00611
00612 QString QVDesignerGUI::getXMLText() const
00613 {
00614 return "Este es el texto\npara el fichero XML\n";
00615 }
00616