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         // Now we will open all cameras:
00117         foreach(QVPropertyContainer* qvp, qvps)
00118                 {
00119                 QVCamera* camera;
00120                 if((camera = dynamic_cast<QVCamera*>(qvp)) != NULL)
00121                         if(camera->isClosed())
00122                                 if(not camera->openCam())
00123                                         {
00124                                         std::cerr << "Error initializing QVApplication: "
00125                                                         << "could not open camera: "
00126                                                         << qPrintable(camera->getName()) << std::endl;
00127                                         return false;
00128                                         }
00129                 }
00130         qDebug() << "QVApplication::initItems(): cameras opened";
00131 
00132         // Now we will init all Plots, that are PropertyContainer:
00133         foreach(QVPropertyContainer* qvp, qvps)
00134                 {
00135                 QVPlot* plot;
00136                 if((plot = dynamic_cast<QVPlot*>(qvp)) != NULL)
00137                         {
00138                         if (!plot->isInitied()) plot->init();
00139                         if (plot->isAutoShow()) plot->show();
00140                         }
00141                 }
00142         qDebug() << "QVApplication::initItems(): plots initied";
00143 
00144         // Now we will show all canvas
00145         foreach(QVPropertyContainer* qvp, qvps)
00146                 {
00147                 QVImageCanvas* canvas;
00148                 if((canvas = dynamic_cast<QVImageCanvas*>(qvp)) != NULL)
00149                         canvas->show();
00150                 }
00151         qDebug() << "QVApplication::initItems(): canvas shown";
00152 
00153         // Now we will start all workers:
00154         foreach(QVPropertyContainer* qvp, qvps)
00155                 {
00156                 QVWorker* worker;
00157                 if((worker = dynamic_cast<QVWorker*>(qvp)) != NULL)
00158                         {
00159                                 workerCount++;
00160                                 worker->moveToThread(worker);
00161                                 connect(worker,SIGNAL(finished()),this,SLOT(workerFinished()));
00162                                 worker->start();
00163                         }
00164                 }
00165         isRunningFlag = TRUE;
00166         qDebug() << "QVApplication::initItems(): workers started";
00167         return true;
00168         }
00169 
00170 void QVApplication::quit()
00171         {
00172         quitItems();
00173         deregisterGUI();
00174         this->exit(0);
00175         }
00176 
00177 void QVApplication::quitItems()
00178         {
00179         qDebug() << "QVApplication::quitItems()";
00180 
00181         // We order all workers to finish...
00182         foreach(QVPropertyContainer* qvp, qvps)
00183                 {
00184                 QVWorker* worker;
00185                 if((worker = dynamic_cast<QVWorker*>(qvp)) != NULL)
00186                         worker->finish();
00187                 }
00188         // ... and then wait for all of them (Warning, it won't work if we try to
00189         // finish and wait in the same loop).
00190         foreach(QVPropertyContainer* qvp, qvps)
00191                 {
00192                 QVWorker* worker;
00193                 if((worker = dynamic_cast<QVWorker*>(qvp)) != NULL)
00194                         {
00195                         // Needed to treat possible pending Qt::BlockingQueuedConnection
00196                         // signals from qvpropertycontainer.h:
00197                         while(not worker->wait(10/*ms*/)) processEvents();
00198                         deregisterQVPropertyContainer(worker);
00199                         }
00200                 }
00201         qDebug() << "QVApplication::quitItems(): workers finished";
00202 
00203         // Now we will hide all canvas
00204         foreach(QVPropertyContainer* qvp, qvps)
00205                 {
00206                 QVImageCanvas* canvas;
00207                 if((canvas = dynamic_cast<QVImageCanvas*>(qvp)) != NULL)
00208                         {
00209                         canvas->hide();
00210                         deregisterQVPropertyContainer(canvas);
00211                         }
00212                 }
00213         qDebug() << "QVApplication::quitItems(): canvas hiden";
00214 
00215         // Now we will stop all Plots, that are PropertyContainer:
00216         foreach(QVPropertyContainer* qvp, qvps)
00217                 {
00218                 QVPlot* plot;
00219                 if((plot = dynamic_cast<QVPlot*>(qvp)) != NULL)
00220                         {
00221                         plot->stop();
00222                         plot->hide();
00223                         deregisterQVPropertyContainer(plot);
00224                         }
00225                 }
00226         qDebug() << "QVApplication::quitItems(): plots initied";
00227 
00228         // Now we will close all cameras:
00229         foreach(QVPropertyContainer* qvp, qvps)
00230                 {
00231                 QVCamera* camera;
00232                 if((camera = dynamic_cast<QVCamera*>(qvp)) != NULL)
00233                         {
00234                         if(!camera->isClosed()) camera->closeCam();
00235                         deregisterQVPropertyContainer(camera);
00236                         }
00237                 }
00238         isRunningFlag = FALSE; // para que se pueda parar y realizar nuevos enlaces
00239         qDebug() << "QVApplication::quitItems(): cameras closed";
00240         }
00241 
00242 QStringList QVApplication::getUnusedArguments()
00243         { return unusedArguments; }
00244 
00245 void QVApplication::setArgumentAsUsed(QString argument)
00246         {
00247         qDebug() << "QVApplication::setArgumentAsUsed(QString,bool)";
00248         int index = unusedArguments.indexOf(argument);
00249         if(index != -1)
00250                 unusedArguments.removeAt(index);
00251         qDebug() << "QVApplication::setArgumentAsUsed(QString,bool) <- return";
00252         }
00253 
00254 void QVApplication::registerQVPropertyContainer(QVPropertyContainer *qvp)
00255         {
00256         qDebug() << "QVApplication::registerQVPropertyContainer(" << qvp->getName() << ")";
00257         qvps.insert(qvp);
00258         qDebug() << "QVApplication::registerQVPropertyContainer(" << qvp->getName() << ") -> return";
00259         }
00260 
00261 void QVApplication::deregisterQVPropertyContainer(QVPropertyContainer *qvp)
00262         {
00263         qDebug() << "QVApplication::registerQVPropertyContainer(" << qvp->getName() << ")";
00264         qvps.remove(qvp);
00265         qDebug() << "QVApplication::registerQVPropertyContainer(" << qvp->getName() << ") -> return";
00266         }
00267 
00268 void QVApplication::registerGUI(QVGUI *visionInterface)
00269         {
00270         this->visionInterface = visionInterface;
00271         }
00272 
00273 void QVApplication::deregisterGUI()
00274         {
00275         this->visionInterface = 0;
00276         }
00277 
00278 void QVApplication::printHelp() const
00279         {
00280         qDebug() << "QVApplication::printHelp()";
00281 
00282         std::cout << "Usage: " << qPrintable(arguments().first())
00283                           << " [OPTIONS]" << std::endl;
00284         if (info != QString())
00285                 std::cout << qPrintable(info) << std::endl;
00286         std::cout << std::endl;
00287         QSetIterator<QVPropertyContainer *> iq(qvps);
00288         while (iq.hasNext())
00289                 {
00290                 QString infoHolder = iq.next()->infoInputProperties();
00291                 if(infoHolder != QString() )
00292                         std::cout << qPrintable(infoHolder) << std::endl;
00293                 }
00294         qDebug() << "QVApplication::printHelp() <~ return";
00295         }
00296 
00297 void QVApplication::workerFinished()
00298 {
00299         workerCount--;
00300         if(workerCount == 0)
00301                 if(terminateOnLastWorker)
00302                         quit();
00303 }
00304