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