ThreadManager.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2006-2008 by Antonello Lobianco                         *
00003  *   http://regmas.org                                                     *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 3 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include <iostream>
00021 
00022 #include <QtCore>
00023 //#include <QMutex>
00024 #include <QMutexLocker>
00025 
00026 #include "ThreadManager.h"
00027 #include "BaseRegmas.h"
00028 #include "MainProgram.h"
00029 #include "MainWindow.h"
00030 
00031 using namespace std;
00032 
00033 ThreadManager::ThreadManager(){
00034     running=false;
00035     stopped=false;
00036     layerQueryPos = -1;
00037 
00038     // initializing pointers...
00039     RD = NULL;
00040     GIS = NULL;
00041     SAM = NULL;
00042     INIT = NULL;
00043     SCD = NULL;
00044     DO = NULL;
00045     
00046     GUI = false;
00047 
00048     scenarioName="";
00049     inputFileName="";
00050     baseDirectory="";
00051 
00052 }
00053 
00054 void
00055 ThreadManager::setMessage(const QString &message){
00056     messageStr = message;
00057 }
00058 
00059 void ThreadManager::run(){
00060     running=true;
00061     stopped=false;
00062 
00063     srand(1);
00064     GUI=true;
00065 
00066     emit upgradeLogArea("**INFO: Start running the model...");
00067 
00068     MainProgram* myProgram;
00069     try{
00070         deleteDeadOldPointers();
00071         emit resetGUIForNewSimulation();
00072 
00073 
00074         QFileInfo file(inputFileName);
00075         QDir baseDir = file.absoluteDir();
00076         baseDirectory = baseDir.absolutePath()+"/";
00077         myProgram = new MainProgram(this);
00078 
00079         //myProgram->setBaseDirectory(baseDirectory);
00080     
00081         vector<string> scenarios = RD->getScenarios();
00082         QVector<QString> qscenarios;
00083         for(uint i=0;i<scenarios.size();i++){
00084             qscenarios.push_back(scenarios.at(i).c_str());
00085         }
00086         running = false;
00087         emit sendScenarioOptionsToGUI(qscenarios);
00088         refreshGUI();
00089 
00090         myProgram->run();
00091 
00092         // Here the model has come to an end...
00093         running=false;
00094         stopped=true;
00095         delete myProgram;
00096         refreshGUI();
00097         
00098     }catch (...) { // TODO.. perform a better exception handing..
00099         emit upgradeLogArea("**INFO: Model has stopped or rised an error (read previous line).");
00100     }   
00101     emit upgradeLogArea("**INFO: Model has ended.");
00102     
00103 }
00104 
00105 void
00106 ThreadManager::retrieveScenarioNameFromGUI(const QString &scenarioName_h){
00107     scenarioName = scenarioName_h;
00108     msgOut(MSG_INFO, "Selected scenario: "+scenarioName.toStdString());
00109     cout << "Selected scenario: "+scenarioName.toStdString() << endl;
00110     resume();
00111 }
00112 
00113 void
00114 ThreadManager::runFromConsole(QString inputFileName_h, QString scenarioName_h){
00115         GUI = false;
00116         scenarioName = scenarioName_h;
00117         inputFileName = inputFileName_h;
00118         QFileInfo file(inputFileName);
00119         QDir baseDir = file.absoluteDir();
00120         baseDirectory = baseDir.absolutePath()+"/";
00121         cout <<"Using base directory: "<< baseDirectory.toStdString() << endl;
00122 
00123 
00124         MainProgram* myProgram = new MainProgram(this);
00125 
00126         if( scenarioName_h == ""){ // if the scenario option has not been shoosed, go for the first one!
00127             vector<string> scenarios = RD->getScenarios();
00128             scenarioName = scenarios.at(0).c_str();
00129         }
00130 
00131         //myProgram->setBaseDirectory(baseDirectory);
00132         myProgram->run();
00133 }
00134 
00135 void
00136 ThreadManager::setInputFileName(QString inputFileName_h){
00137     inputFileName= inputFileName_h;
00138     QFileInfo file(inputFileName);
00139     QDir baseDir = file.absoluteDir();
00140     baseDirectory = baseDir.absolutePath()+"/";
00141 }
00142 
00149 void
00150 ThreadManager::deleteDeadOldPointers(){
00151     if (DO) {delete DO; DO=0;}
00152     if (SAM) {delete SAM; SAM=0;}
00153     if (INIT) {delete INIT; INIT=0;}
00154     if (SCD) {delete SCD; SCD=0;}
00155     if (GIS) {delete GIS; GIS=0;}
00156     if (RD) {delete RD; RD=0;}
00157 }
00158 
00159 
00160 void
00161 ThreadManager::stop(){
00162     stopped = true;
00163     emit upgradeLogArea("STOP cliccked stopping");
00164 }
00165 
00166 void
00167 ThreadManager::pauseOrResume(){
00168     if(!stopped){
00169         if(running){
00170             running= false;
00171             emit upgradeLogArea("PAUSE cliccked PAUSING");
00172         }
00173         else {
00174             running=true;
00175             emit upgradeLogArea("PAUSE cliccked RESUMING");
00176             emit setGUIUnsavedStatus(true);
00177         }
00178     }
00179     return;
00180 }
00181 
00182 void
00183 ThreadManager::pause(){
00184     if(!stopped){
00185         if(running){
00186             running= false;
00187         }
00188         else {
00189             return;
00190         }
00191     }
00192     return;
00193 }
00194 
00195 void
00196 ThreadManager::resume(){
00197     if(!stopped){
00198         if(running){
00199             return;
00200         }
00201         else {
00202             running=true;
00203             emit setGUIUnsavedStatus(true);
00204         }
00205     }
00206     return;
00207 }
00208 
00209 void
00210 ThreadManager::refreshGUI(){
00211         checkQuery(0,0,false);
00212         while (!running){
00213             if(stopped){
00214                 break;
00215             }
00216         }
00217         if (stopped){
00218             emit upgradeLogArea("Model has been stopped.");
00219             running= false;
00220             throw(2);
00221         }
00222 }
00223 
00224 void
00225 ThreadManager::msgOut(const int msgCode_h, const string message_h){
00226     QString message = message_h.c_str();
00227     emit upgradeLogArea(message);
00228     if (msgCode_h == 2){
00229         emit upgradeMainSBLabelToGui(message);
00230     }
00231 }
00232 
00233 void
00234 ThreadManager::setOutputDirName(string outputDirname_h){
00235     emit setOutputDirNameToGui(outputDirname_h);
00236 }
00237 
00238 void 
00239 ThreadManager::addLayer(string layerName_h, string layerLabel_h){
00240     QString layerName = layerName_h.c_str();
00241     QString layerLabel = layerLabel_h.c_str();
00242     emit addLayerToGui(layerName, layerLabel);
00243 }
00244 
00245 void
00246 ThreadManager::updatePixel(string layerName_h, int x_h, int y_h, QColor color_h){
00247     emit updatePixelToGui(layerName_h.c_str(), x_h, y_h, color_h);
00248 }
00249 
00250 void
00251 ThreadManager::updateImage(string layerName_h, const QImage &image_h){
00252     emit updateImageToGui(layerName_h.c_str(), image_h);
00253 }
00254 
00255 void
00256 ThreadManager::upgradeMainSBLabel(const string message_h){
00257     emit upgradeMainSBLabelToGui(message_h.c_str());
00258 }
00259 
00260 void
00261 ThreadManager::upgradeYearSBLabel(int year){
00262     QString temp;
00263     temp= i2s(year).c_str();
00264     emit upgradeYearSBLabelToGui(temp);
00265 }
00266 
00272 void
00273 ThreadManager::checkQuery(int px_ID, int currentLayerIndex, bool newRequest){
00274     QMutexLocker locker(&mutex);
00275     if(newRequest){
00276         pxQueryID = px_ID;
00277         layerQueryPos = currentLayerIndex;
00278         if(stopped){computeQuery(pxQueryID, layerQueryPos);layerQueryPos = -1;} // model is stopped, no way the model thread will do the query work
00279         else{emit publishQueryResults("<i>..wait.. processing query..</i>");} // model is running.. it will be the model thread to execute the query        
00280         return;
00281     } else {
00282         if(layerQueryPos<0){
00283             return;
00284         } else {
00285             computeQuery(pxQueryID, layerQueryPos);
00286             layerQueryPos = -1;
00287             return;
00288         }
00289     }
00290 }
00291 
00292 void
00293 ThreadManager::computeQuery(int px_ID, int currentLayerIndex){
00294     
00295     // IMPORTANT: this function is called at refreshGUI() times, so if there are output messages, call them with the option to NOT refresh the gui, otherwise we go to an infinite loop...
00296 
00297     vector<Layers*> layers;
00298     try {
00299         layers = GIS->getLayerPointers();
00300     }catch (...) {
00301         emit activateTab(2); // tell the gui to activate the 3rd page, those with the pixel info
00302         emit publishQueryResults("GIS pointer is dead.. maybe simulation has ended???");
00303         return;
00304     }
00305     QString result= "";
00306     int realID = GIS->sub2realID(px_ID);
00307     if (realID<0) {
00308         emit publishQueryResults("Query result: Spatial data is not yet ready in the model. Please click again later.");
00309         return; // on early stage we may have errors, and here we prevent this error to have further consequences.
00310     }
00311     Pixel* px;
00312     try {
00313         px = GIS->getPixel(realID);
00314     }catch (...) {
00315         emit activateTab(2); // tell the gui to activate the 3rd page, those with the pixel info
00316         emit publishQueryResults("Query result: Spatial data is not yet ready in the model. Please click again later.");
00317         return;
00318     }   
00319     result += "Pixel: ";
00320     result += i2s(realID).c_str();
00321     result += " (";
00322     result += i2s(px->getX()).c_str();
00323     result += ",";
00324     result += i2s(px->getY()).c_str();
00325     result += ")";
00326     result +="<p><table>";
00327     for (uint i=0;i<layers.size();i++){
00328         QString boldStart="";
00329         QString boldEnd = "";
00330         if (i == currentLayerIndex){
00331             boldStart = "<b>";
00332             boldEnd   = "</b>";
00333         }
00334         result += "<tr>";
00335         string layerName = layers[i]->getName();
00336         double value = px->getDoubleValue(layerName);
00337         string category = layers[i]->getCategory(value);
00338         //QColor color = layers[i]->getColor(value);
00339         result += "<td>";
00340         result += boldStart;
00341         result += layerName.c_str();
00342         result += boldEnd;
00343         result += "</td><td>";
00344         result += boldStart;
00345         result += category.c_str();
00346         result += boldEnd;
00347         result += "</td>";
00348         result += "</tr>";
00349     }
00350     result += "</table>";
00351     emit activateTab(2); // tell the gui to activate the 3rd page, those with the pixel info
00352     emit publishQueryResults(result);
00353 }
00354 
00355