PARP Research Group University of Murcia, Spain


src/qvcore/qvapplication.cpp

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



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