PARP Research Group University of Murcia, Spain


src/qvcore/qvapplication.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 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 
00024 
00025 #include <QDebug>
00026 #include <QMetaType>
00027 #include <QSet>
00028 #include <QGLWidget>
00029 
00030 #include <QVApplication>
00031 #include <QVGUI>
00032 #include <QVImageCanvas>
00033 #include <QVCamera>
00034 #include <QVWorker>
00035 
00036 #include <qvgui/qvplot.h>
00037 
00038 QVApplication::QVApplication (int &argc,char **argv, QString infoString,bool GUIenabled) : QApplication(argc,argv,GUIenabled), info(infoString), unusedArguments(), qvps(), visionInterface(NULL), isRunningFlag(FALSE), workerCount(0), terminateOnLastWorker(TRUE), forHelpFlag(FALSE)
00039         {
00040 
00041         if (GUIenabled and not QGLFormat::hasOpenGL() )
00042                 qFatal("This system has no OpenGL support, and QVision GUI needs it. Exiting.");
00043 
00044         qRegisterMetaType< QVariant >("QVariant");
00045         qRegisterMetaType< QVCamera::TCameraStatus >("QVCamera::TCameraStatus");
00046         qRegisterMetaType< QVWorker::TWorkerStatus >("QVWorker::TWorkerStatus");
00047         qRegisterMetaType< QVImage<uChar,1> >("QVImage<uChar,1>");
00048         qRegisterMetaType< QVImage<sShort,1> >("QVImage<sShort,1>");
00049         qRegisterMetaType< QVImage<sFloat,1> >("QVImage<sFloat,1>");
00050         qRegisterMetaType< QVImage<uChar,3> >("QVImage<uChar,3>");
00051         qRegisterMetaType< QVImage<sShort,3> >("QVImage<sShort,3>");
00052         qRegisterMetaType< QVImage<sFloat,3> >("QVImage<sFloat,3>");
00053         qRegisterMetaType< QVPropertyContainerChange >("QVPropertyContainerChange");
00054 
00055         unusedArguments = arguments();
00056         unusedArguments.removeAt(0); // Application name removed.
00057 
00058         if(unusedArguments.contains("--help")) forHelpFlag = TRUE;
00059         }
00060 
00061 int QVApplication::exec()
00062         {
00063         qDebug() << "QVApplication::exec()";
00064 
00065         // If --help parameter was given, show help and exit:
00066         if(unusedArguments.contains("--help")) 
00067                 {
00068                 printHelp();
00069                 return 0;
00070                 }
00071 
00072         // An initialization error of any QVPropertyContainer aborts execution:
00073         foreach(QVPropertyContainer* qvp, qvps)
00074                 {
00075                 QString lastError;
00076                 if((lastError = qvp->getLastError()) != QString())
00077                         {
00078                         std::cerr << "Error initializing QVApplication: "
00079                                           << qPrintable(lastError) << std::endl;
00080                         return -1;
00081                         }
00082                 }
00083 
00084         // If there are unused arguments, show error and exit
00085         if(not unusedArguments.isEmpty())
00086                 {
00087                 foreach(QString argument, unusedArguments)
00088                         std::cerr << "Error initializing QVApplication: "
00089                                           << "unknown command line parameter: "
00090                                           << qPrintable(argument) << std::endl;
00091                 return -1;
00092                 }
00093 
00094         // Now we init the GUI, in order to register all cameras and workers, and create its widgets
00095         if (visionInterface)
00096                 {
00097                 visionInterface->init();
00098                 visionInterface->show();
00099                 }
00100                 qDebug() << "QVApplication::exec(): GUI initied";
00101         
00102         // Now we init all registered items (cameras, plots,canvas, workers, ...)
00103         if (!startItems()) return -1;
00104 
00105         qDebug() << "Entering in QApplication::exec()";
00106         isRunningFlag = TRUE;
00107         int returnvalue = QApplication::exec();
00108         qDebug() << "Back from QApplication::exec()";
00109 
00110         qDebug() << "QVApplication::exec() <- return";
00111         return returnvalue;
00112         }
00113 
00114 bool QVApplication::startItems()
00115         {
00116         // TODO: mover la inicialización de los QVImageCanvas al principio de esta función. Problema con el alumno de PFC.
00117 
00118         // Now we will open all cameras:
00119         foreach(QVPropertyContainer* qvp, qvps)
00120                 {
00121                 QVCamera* camera;
00122                 if((camera = dynamic_cast<QVCamera*>(qvp)) != NULL)
00123                         //{
00124                         //std::cout << "QVApplication::startItems(" << qPrintable(qvp->getName()) << "), camera" << std::endl;
00125                         if(camera->isClosed())
00126                                 {
00127                                 if(not camera->openCam())
00128                                         {
00129                                         std::cerr << "Error initializing QVApplication: "
00130                                                         << "could not open camera: "
00131                                                         << qPrintable(camera->getName()) << std::endl;
00132                                         return false;
00133                                         }
00134                                 }
00135                         //else
00136                         //      std::cout << "QVApplication::startItems(" << qPrintable(qvp->getName()) << "): camera not closed" << std::endl;
00137                         //}
00138                 }
00139         qDebug() << "QVApplication::initItems(): cameras opened";
00140 
00141         // Now we will init all Plots, that are PropertyContainer:
00142         foreach(QVPropertyContainer* qvp, qvps)
00143                 {
00144                 QVPlot* plot;
00145                 if((plot = dynamic_cast<QVPlot*>(qvp)) != NULL)
00146                         {
00147                         if (!plot->isInitied()) plot->init();
00148                         if (plot->isAutoShow()) plot->show();
00149                         }
00150                 }
00151         qDebug() << "QVApplication::initItems(): plots initied";
00152 
00153         // Now we will show all canvas
00154         foreach(QVPropertyContainer* qvp, qvps)
00155                 {
00156                 QVImageCanvas* canvas;
00157                 if((canvas = dynamic_cast<QVImageCanvas*>(qvp)) != NULL)
00158                         canvas->show();
00159                 }
00160         qDebug() << "QVApplication::initItems(): canvas shown";
00161 
00162         // Now we will start all workers:
00163         foreach(QVPropertyContainer* qvp, qvps)
00164                 {
00165                 QVWorker* worker;
00166                 if((worker = dynamic_cast<QVWorker*>(qvp)) != NULL)
00167                         {
00168                                 QVWorker* masterWorker;
00169                                 // The worker must be moved to his master thread (if its a worker), that will be usualy himself
00170                                 if((masterWorker = dynamic_cast<QVWorker*>(qvp->getMaster())) != NULL)
00171                                         worker->moveToThread(masterWorker);
00172                                 connect(worker,SIGNAL(finished()),this,SLOT(workerFinished()));
00173                                 // only start the masters threads, and only count this workers to the endOnLastIteration condition
00174                                 if (worker->isSequentialGroupMaster()) {
00175                                         workerCount++;
00176                                         worker->start();
00177                                 }
00178                         }
00179                 }
00180         isRunningFlag = TRUE;
00181         qDebug() << "QVApplication::initItems(): workers started";
00182         return true;
00183         }
00184 
00185 void QVApplication::quit()
00186         {
00187         quitItems();
00188         deregisterGUI();
00189         this->exit(0);
00190         }
00191 
00192 void QVApplication::quitItems()
00193         {
00194         qDebug() << "QVApplication::quitItems()";
00195 
00196         // We order all workers to finish...
00197         foreach(QVPropertyContainer* qvp, qvps)
00198                 {
00199                 QVWorker* worker;
00200                 if((worker = dynamic_cast<QVWorker*>(qvp)) != NULL)
00201                         worker->finish();
00202                 }
00203         // ... and then wait for all of them (Warning, it won't work if we try to
00204         // finish and wait in the same loop).
00205         foreach(QVPropertyContainer* qvp, qvps)
00206                 {
00207                 QVWorker* worker;
00208                 if((worker = dynamic_cast<QVWorker*>(qvp)) != NULL)
00209                         {
00210                         // Needed to treat possible pending Qt::BlockingQueuedConnection
00211                         // signals from qvpropertycontainer.h:
00212                         // if it is not a master the threat was not started, and wait do nothing
00213                         while(not worker->wait(10/*ms*/)) processEvents();
00214                         deregisterQVPropertyContainer(worker);
00215                         }
00216                 }
00217         qDebug() << "QVApplication::quitItems(): workers finished";
00218 
00219         // Now we will hide all canvas
00220         foreach(QVPropertyContainer* qvp, qvps)
00221                 {
00222                 QVImageCanvas* canvas;
00223                 if((canvas = dynamic_cast<QVImageCanvas*>(qvp)) != NULL)
00224                         {
00225                         canvas->hide();
00226                         deregisterQVPropertyContainer(canvas);
00227                         }
00228                 }
00229         qDebug() << "QVApplication::quitItems(): canvas hiden";
00230 
00231         // Now we will stop all Plots, that are PropertyContainer:
00232         foreach(QVPropertyContainer* qvp, qvps)
00233                 {
00234                 QVPlot* plot;
00235                 if((plot = dynamic_cast<QVPlot*>(qvp)) != NULL)
00236                         {
00237                         plot->stop();
00238                         plot->hide();
00239                         deregisterQVPropertyContainer(plot);
00240                         }
00241                 }
00242         qDebug() << "QVApplication::quitItems(): plots initied";
00243 
00244         // Now we will close all cameras:
00245         foreach(QVPropertyContainer* qvp, qvps)
00246                 {
00247                 QVCamera* camera;
00248                 if((camera = dynamic_cast<QVCamera*>(qvp)) != NULL)
00249                         {
00250                         if(!camera->isClosed()) camera->closeCam();
00251                         deregisterQVPropertyContainer(camera);
00252                         }
00253                 }
00254         isRunningFlag = FALSE; // para que se pueda parar y realizar nuevos enlaces
00255         qDebug() << "QVApplication::quitItems(): cameras closed";
00256         }
00257 
00258 void QVApplication::quitWorker(QVWorker *worker)
00259         {
00260                 if (qvps.contains(worker)) {
00261                         worker->finish();
00262 
00263                         while(not worker->wait(10/*ms*/)) processEvents();
00264                         deregisterQVPropertyContainer(worker);
00265 
00266 //                      delete worker; // no se puede si no se crean con new
00267                 }
00268         }
00269 
00270 QStringList QVApplication::getUnusedArguments()
00271         { return unusedArguments; }
00272 
00273 void QVApplication::setArgumentAsUsed(QString argument)
00274         {
00275         qDebug() << "QVApplication::setArgumentAsUsed(QString,bool)";
00276         int index = unusedArguments.indexOf(argument);
00277         if(index != -1)
00278                 unusedArguments.removeAt(index);
00279         qDebug() << "QVApplication::setArgumentAsUsed(QString,bool) <- return";
00280         }
00281 
00282 void QVApplication::registerQVPropertyContainer(QVPropertyContainer *qvp)
00283         {
00284         qDebug() << "QVApplication::registerQVPropertyContainer(" << qvp->getName() << ")";
00285         qvps.insert(qvp);
00286         qDebug() << "QVApplication::registerQVPropertyContainer(" << qvp->getName() << ") -> return";
00287         }
00288 
00289 void QVApplication::deregisterQVPropertyContainer(QVPropertyContainer *qvp)
00290         {
00291         qDebug() << "QVApplication::registerQVPropertyContainer(" << qvp->getName() << ")";
00292         qvps.remove(qvp);
00293         qDebug() << "QVApplication::registerQVPropertyContainer(" << qvp->getName() << ") -> return";
00294         }
00295 
00296 void QVApplication::registerGUI(QVGUI *visionInterface)
00297         {
00298         this->visionInterface = visionInterface;
00299         }
00300 
00301 void QVApplication::deregisterGUI()
00302         {
00303         this->visionInterface = 0;
00304         }
00305 
00306 void QVApplication::printHelp() const
00307         {
00308         qDebug() << "QVApplication::printHelp()";
00309 
00310         std::cout << "Usage: " << qPrintable(arguments().first())
00311                           << " [OPTIONS]" << std::endl;
00312         if (info != QString())
00313                 std::cout << qPrintable(info) << std::endl;
00314         std::cout << std::endl;
00315         QSetIterator<QVPropertyContainer *> iq(qvps);
00316         while (iq.hasNext())
00317                 {
00318                 QString infoHolder = iq.next()->infoInputProperties();
00319                 if(infoHolder != QString() )
00320                         std::cout << qPrintable(infoHolder) << std::endl;
00321                 }
00322         qDebug() << "QVApplication::printHelp() <~ return";
00323         }
00324 
00325 void QVApplication::workerFinished()
00326 {
00327         workerCount--;
00328         if(workerCount == 0)
00329                 if(terminateOnLastWorker)
00330                         quit();
00331 }
00332 



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