Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

omgmainwindow.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Tim Sutton   *
00003  *   tim@linfiniti.com   *
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 2 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 "omgabout.h"
00021 #include "omgalgorithm.h"
00022 #include "omgalgorithmmanager.h"
00023 #include "omgclimateconverter.h"
00024 #include "omgexperimentdesigner.h"
00025 #include "omgexperimentselector.h"
00026 #include "omggdalconverter.h"
00027 #include "omggdalrastercontour.h"
00028 #include "omggdalwarp.h"
00029 #include "omglayersetmanager.h"
00030 #include "omgmainwindow.h"
00031 #include "omgoptions.h"
00032 #include "omgrasterthreshold.h"
00033 #include "omgdatafetcherwizard.h"
00034 #include "omgtermsandconditions.h"
00035 #include "omgtextfilesplitter.h"
00036 #include "omgtipfactory.h"
00037 #include "omgsurveywizard.h"
00038 #include "omgpublishtocatalogue.h"
00039 #include "omgmodellerplugininterface.h"
00040 #include "omgmodellerpluginregistry.h"
00041 #include <omgui.h>  // for version
00042 
00043 #ifdef WITH_QGIS
00044 //this next include is COPIED into omg sources
00045 //from qgis sources since I needed to modify it
00046 //It is needed to enable qgis plugins to work in 
00047 //omdesktop.
00048 #include "qgisappinterface.h"
00049 //
00050 // QGIS Includes
00051 //
00052 #include <qgsproject.h>
00053 #include <qgisplugin.h>
00054 #include <qgsapplication.h>
00055 #include <qgsmapcanvas.h>
00056 #include <qgsmaplayerregistry.h>
00057 #include <qgspluginregistry.h>
00058 #include <qgsproviderregistry.h>
00059 #include <qgsrasterlayer.h>
00060 #include <qgsuniquevaluerenderer.h>
00061 #include <qgssinglesymbolrenderer.h>
00062 #include <qgssymbol.h>
00063 #include <qgsvectorlayer.h>
00064 #include <qgsvectordataprovider.h>
00065 #include <qgsfield.h>
00066 
00067 //
00068 // QGIS Map tools
00069 //
00070 #include "qgsmaptoolpan.h"
00071 #include "qgsmaptoolzoom.h"
00072 //#include "qgsmaptoolidentify.h"
00073 //#include "qgsmeasure.h"
00074 //
00075 // These are the other headers for available map tools (not used in this example)
00076 //
00077 //#include "qgsmaptoolcapture.h"
00078 //#include "qgsmaptoolselect.h"
00079 //#include "qgsmaptoolvertexedit.h"
00080 #endif
00081 
00082 #include <QAction>
00083 #include <QCloseEvent>
00084 #include <QDebug>
00085 #include <QDesktopWidget>
00086 #include <QFileDialog>
00087 #include <QFrame>
00088 #include <QHeaderView>
00089 #include <QImage>
00090 #include <QLayout>
00091 #include <QLibrary>
00092 #include <QListWidget>
00093 #include <QMap>
00094 #include <QMenuBar>
00095 #include <QMessageBox>
00096 #include <QPair>
00097 #include <QPixmap>
00098 #include <QPrinter>
00099 #include <QScrollArea>
00100 #include <QSettings>
00101 #include <QStatusBar>
00102 #include <QString>
00103 #include <QTextDocument>
00104 #include <QTextEdit>
00105 #include <QToolBar>
00106 #include <QTreeWidget>
00107 #include <QWhatsThis>
00108 #include <QWidget>
00109 
00110 
00111 //needed for loading qgis plugins
00112 typedef QgisPlugin *create_ui(QgisInterface * qI);
00113 
00114 OmgMainWindow::OmgMainWindow(QWidget* parent, Qt::WFlags fl)
00115     : QMainWindow(parent,fl),
00116       //needed for loading qgis plugins
00117       mpQgisInterface(new QgisAppInterface(this)),
00118       mpCurrentModel(new OmgModel()),
00119       mpLocalitiesModel(new OmgLocalitiesModel())
00120 
00121 {
00122   //required by Qt4 to initialise the ui
00123   setupUi(this);
00124   
00125   //setUnifiedTitleAndToolBarOnMac ( true );
00126   connect(splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(setTreeColumnSizes(int, int)));
00127   connect(cboReportMode, SIGNAL(currentIndexChanged(QString)), this, SLOT(reportModeChanged(QString)));
00128  
00129   // Set view mode
00130   setViewMode("Browse");
00131 
00132 
00133   //Set up experiment tree
00134   treeExperiment->clear();
00135   tableView->setModel(mpLocalitiesModel); 
00136   setEnableModelDetailWidgets(false);
00137 
00138   //QScrollArea *mypScrollArea = new QScrollArea(frameImage);
00139   //mypScrollArea->setWidget(mPictureWidget);
00140   //setCentralWidget(mypScrollArea);
00141   //setCentralWidget(frameImage);
00142   createActions();
00143   createTrayIcon();
00144   createMenus();
00145   createToolBars();
00146   createStatusBar();
00147 
00148 #ifdef WITH_QGIS
00149   //make sure the toolbars and actions are created first
00150   //ie dont move this defined block above the preceding lines ^
00151   
00152   // Instantiate Provider Registry
00153   QString myPluginDirName        = QgsApplication::pluginPath(); 
00154   QgsProviderRegistry::instance(myPluginDirName);
00155 
00156   // Create the Map Canvas
00157   mpMapCanvas= new QgsMapCanvas(0, 0);
00158   //qDebug(mpMapCanvas->extent().stringRep(2));
00159   mpMapCanvas->enableAntiAliasing(true);
00160   mpMapCanvas->useQImageToRender(false);
00161   mpMapCanvas->setCanvasColor(QColor(255, 255, 255));
00162   mpMapCanvas->freeze(false);
00163   mpMapCanvas->setVisible(true);
00164   mpMapCanvas->refresh();
00165   mpMapCanvas->show();
00166   //load the north arrow and scale bar plugins
00167   //note: any qgis plugins found will be loaded automatically
00168   //so just drop in additional ones as needed
00169 #ifdef WIN32
00170   QString pluginExt = "*.dll";
00171 #else
00172   QString pluginExt = "*.so*";
00173 #endif
00174 
00175   // check all libs in the current plugin directory and get name and descriptions
00176   QDir myPluginDir(myPluginDirName, pluginExt, QDir::Name | QDir::IgnoreCase, QDir::Files | QDir::NoSymLinks);
00177 
00178   for (uint i = 0; i < myPluginDir.count(); i++)
00179   {
00180     QString myFullPath = myPluginDirName + QDir::separator() + myPluginDir[i];
00181     qDebug("Examining " + myFullPath.toLocal8Bit());
00182     //check its a plugin we actually want
00183     //on some platforms e.g. linux we dont have plugins
00184     //bundled specifically with openModeller Desktop app
00185     //and some of them may cause segfault so we screen 
00186     //for just the ones we want
00187     bool myPluginWantedFlag=false;
00188     QStringList myPluginList;
00189     myPluginList << "north" << "copyright" << "scalebar";
00190     QStringListIterator myIterator(myPluginList);
00191     while (myIterator.hasNext())
00192     {
00193       if (myFullPath.contains(myIterator.next()))
00194       {
00195         myPluginWantedFlag=true;
00196         break; 
00197       }
00198     }
00199     if (!myPluginWantedFlag)
00200     {
00201       continue;
00202     }
00203 
00204 
00205     QLibrary *myLib = new QLibrary(myFullPath);
00206     bool myLoadedFlag = myLib->load();
00207     if (myLoadedFlag)
00208     {
00209         //purposely leaving this one to stdout!
00210         std::cout << "Loaded " << myLib->library().toLocal8Bit().data() << std::endl;
00211         
00212         name_t * myName = (name_t *) myLib->resolve("name");
00213         description_t *  myDescription = (description_t *)  myLib->resolve("description");
00214         version_t *  myVersion =  (version_t *) myLib->resolve("version");
00215         if (myName && myDescription  && myVersion )
00216         {
00217           //check if the plugin was active on last session
00218           QString myEntryName = myName();
00219           // Windows stores a "true" value as a 1 in the registry so we
00220           // have to use readBoolEntry in this function
00221 
00222           qDebug("Loading plugin: " + myEntryName.toLocal8Bit());
00223 
00224           loadQGisPlugin(myName(), myDescription(), myFullPath);
00225         }
00226         else
00227         {
00228           qDebug("Failed to get name, description, or type for " + 
00229               myLib->library().toLocal8Bit());
00230         }
00231     }
00232     else
00233     {
00234       qDebug("Failed to load " + myLib->library().toLocal8Bit());
00235       qDebug("Reason: " + myLib->errorString().toLocal8Bit());
00236     }
00237     delete myLib;
00238   }
00239 
00240   
00241   // Lay our widgets out in the main window
00242   delete lblOutputMap; //dont need this when using qgis integration
00243   tabMap->layout()->addWidget(mpMapCanvas);
00244   //create the maptools
00245   mpPanTool = new QgsMapToolPan(mpMapCanvas);
00246   mpPanTool->setAction(mpPanAct);
00247   mpZoomInTool = new QgsMapToolZoom(mpMapCanvas, FALSE); // false = in
00248   mpZoomInTool->setAction(mpZoomInAct);
00249   mpZoomOutTool = new QgsMapToolZoom(mpMapCanvas, TRUE ); //true = out
00250   mpZoomOutTool->setAction(mpZoomOutAct);
00251   /*
00252   mpIdentifyTool = new QgsMapToolIdentify(mpMapCanvas);
00253   mpIdentifyTool->setAction(mpIdentifyAct);
00254   mpMeasureTool = new QgsMeasure(FALSE , mpMapCanvas); //FALSE = non area mode
00255   mpMeasureTool->setAction(mpMeasureAct);
00256   mpMeasureAreaTool = new QgsMeasure(TRUE , mpMapCanvas); //TRUE = area mode
00257   mpMeasureAreaTool->setAction(mpMeasureAreaAct);
00258   */
00259 #endif //with qgis  
00260 
00261 #ifdef OMG_NO_EXPERIMENTAL
00262   //* Disable these tools until they are properly useable
00263   mpToolsContourAct->setVisible(false);
00264   mpToolsWarpAct->setVisible(false);
00265   mpCloseAct->setVisible(false);
00266   mpToolsClimateConvertAct->setVisible(false);
00267   //mpToolsRasterThresholdAct->setVisible(false);
00268 
00269   mpDataPrepToolBar->removeAction(mpToolsWarpAct);
00270   mpDataPrepToolBar->removeAction(mpToolsClimateConvertAct);
00271   mpPostProcessingToolBar->removeAction(mpToolsContourAct);
00272   //mpPostProcessingToolBar->removeAction(mpToolsRasterThresholdAct);
00273 
00274   mpSaveAct->setVisible(false);
00275   mpFileToolBar->removeAction(mpSaveAct);
00276 #endif  
00277   
00278 
00279   readSettings();
00280   setTreeColumnSizes(0,0);
00281   disableMapControls();
00282 
00283   showHelp();
00284 
00285   
00286   //hide the report mode widgets
00287   //eventually delete this I think since I dont think average
00288   //users care about it
00289   cboReportMode->hide();
00290   lblReportMode->hide();
00291   
00292   // default sort mode
00293   //mSortMode=BY_TAXON; //or BY_ALGORITHM
00294   mSortMode = BY_ALGORITHM;
00295   //set up the ossim planet widget
00296 #ifdef WITH_OSSIMPLANET_QT
00297   initialiseOssimPlanet();
00298 #else
00299   tabModelViewDetails->removeTab(3);
00300 #endif
00301   listThumbnails->hide();
00302 
00303   //icon displayed next to tree items to show they are running
00304   //start with a fall back to a non animated icon
00305   mRunningIcon = QIcon(":/status_running.png");
00306   //now try to setup icon animation...
00307   if (!QFile::exists(":/status_running.gif"))
00308   {
00309     //logMessage(" ****** Running movie does not exist ! ******** ");
00310   }
00311   else
00312   {
00313     mpRunningMovie = new QMovie(":/status_running.gif");
00314     if (mpRunningMovie->isValid())
00315     {
00316       //this will enable an animated icon next to the actively run model
00317       connect(mpRunningMovie, SIGNAL(updated(const QRect)), this, SLOT(updateRunningIcon(const QRect)));
00318     }
00319     else
00320     {
00321       //logMessage(" ****** Running movie is invalid ! ******** ");
00322     }
00323   }
00324   //copy in the default user profiles if they dont exist
00325   QString myPath = Omgui::userAlgorithmProfilesDirPath();
00326   QStringList myList;
00327   myList << "algorithm-EnvironmentalDistance-Chebyshev.xml";
00328   myList << "algorithm-EnvironmentalDistance-Mahalanobis.xml";
00329   myList << "algorithm-EnvironmentalDistance-Manhattan.xml";
00330   myList << "algorithm-SVM-C-SVC.xml";
00331   myList << "algorithm-SVM-Nu-SVC.xml";
00332   myList << "algorithm-SVM-One-Class.xml";
00333   QStringListIterator myIterator(myList);
00334   while (myIterator.hasNext())
00335   {
00336     QString myProfile = myIterator.next();
00337     if (!QFile::exists(myPath+myProfile))
00338     {
00339       //copy from resource bundle to filesystem
00340       if (!QFile::exists(":/" + myProfile))
00341       {
00342         qDebug("Resouce file :/" + myProfile.toLocal8Bit()
00343             + " does not exist...skipping");
00344         continue;
00345       }
00346 
00347       bool myResult = QFile::copy(":/" + myProfile,
00348           myPath+myProfile);
00349       QString myMessage = "Copying :/" + myProfile +
00350         " to " + myPath + myProfile; 
00351       if (myResult)
00352       {
00353         myMessage += " succeeded";
00354       }
00355       else
00356       {
00357         myMessage += " failed";
00358       }
00359       qDebug(myMessage.toLocal8Bit());
00360     }
00361   }
00362 }
00363 
00364 
00365 OmgMainWindow::~OmgMainWindow()
00366 {
00367 }
00368 
00369 void OmgMainWindow::loadQGisPlugin(QString theName, 
00370     QString theDescription, QString theFullPathName)
00371 {
00372   QSettings mySettings;
00373   // first check to see if its already loaded
00374   QgsPluginRegistry *mypRegistry = QgsPluginRegistry::instance();
00375   QString myLibName = mypRegistry->library(theName);
00376   if (myLibName.length() > 0)
00377   {
00378     // plugin is loaded
00379     // QMessageBox::warning(this, "Already Loaded", description + " is already loaded");
00380   }
00381   else
00382   {
00383     QLibrary *mypLib = new QLibrary(theFullPathName);
00384     qDebug("Library name is " + mypLib->library().toLocal8Bit());
00385 
00386     bool myLoadedFlag = mypLib->load();
00387     if (myLoadedFlag)
00388     {
00389       std::cerr << "Loaded test plugin library" << std::endl;
00390       std::cerr << "Attempting to resolve the classFactory function" << std::endl;
00391 
00392       type_t *mypType = (type_t *) mypLib->resolve("type");
00393 
00394 
00395       switch (mypType())
00396       {
00397         case QgisPlugin::UI:
00398           {
00399             create_ui *cf = (create_ui *) mypLib->resolve("classFactory");
00400             if (cf)
00401             {
00402               QgisPlugin *mypPlugin = cf(mpQgisInterface);
00403               if (mypPlugin)
00404               {
00405                 mypPlugin->initGui();
00406                 // add it to the plugin registry
00407                 mypRegistry->addPlugin(mypLib->library(), theName, mypPlugin);
00408                 //add it to the qsettings file [ts]
00409                 mySettings.setValue("/QGisPlugins/" + theName, true);
00410               }
00411               else
00412               {
00413                 // something went wrong
00414                 QMessageBox::warning(this, tr("Error Loading Plugin"), tr("There was an error loading %1."));
00415                 //disable it to the qsettings file [ts]
00416                 mySettings.setValue("/QGisPlugins/" + theName, false);
00417               }
00418             }
00419             else
00420             {
00421               //#ifdef QGISDEBUG
00422               std::cerr << "Unable to find the class factory for " 
00423                 << theFullPathName.toLocal8Bit().data() << std::endl;
00424               //#endif
00425             }
00426 
00427           }
00428           break;
00429         case QgisPlugin::MAPLAYER:
00430         default:
00431           // type is unknown
00432           //#ifdef QGISDEBUG
00433           std::cerr << "Plugin " << theFullPathName.toLocal8Bit().data() << " did not return a valid type and cannot be loaded" << std::endl;
00434           //#endif
00435           break;
00436       }
00437     }
00438     else
00439     {
00440       //#ifdef QGISDEBUG
00441       std::cerr << "Failed to load " << theFullPathName.toLocal8Bit().data() << "\n";
00442       //#endif
00443     }
00444     delete mypLib;
00445   }
00446 }
00447 
00448 void OmgMainWindow::fileExit()
00449 {
00450 #ifdef WITH_QGIS  
00451   mpMapCanvas->freeze(true);
00452   delete mpMapCanvas;
00453 #endif
00454   writeSettings();
00455   if (QSystemTrayIcon::isSystemTrayAvailable ())
00456   {
00457     mTrayIcon->hide();
00458     if (mTrayIcon) //QPointer guarded pointer
00459     {
00460       delete mTrayIcon;
00461     }
00462   }
00463   qApp->quit();
00464 }
00465 
00466 void OmgMainWindow::closeEvent(QCloseEvent *thepEvent)
00467 {
00468   QSettings mySettings;
00469   bool myUseSytemTrayFlag = mySettings.value("openModeller/useSystemTray", false).toBool();
00470   bool myMinimiseToSystemTrayFlag = mySettings.value("openModeller/closeToSystemTray", false).toBool();
00471   if (QSystemTrayIcon::isSystemTrayAvailable() && 
00472       myUseSytemTrayFlag &&
00473       myMinimiseToSystemTrayFlag)
00474   {
00475     QSettings mySettings;
00476     if (mySettings.value("openModeller/closeToSystemTray", true).toBool())
00477     { 
00478       QMessageBox::information(this, tr("Systray"),
00479           tr("The program will keep running in the "
00480             "system tray. To terminate the program, "
00481             "choose <b>Quit</b> in the context menu "
00482             "of the system tray entry, or choose exit "
00483             "from the file menu. You can disable this "
00484             "behaviour in the options dialog."));
00485       hide();
00486       thepEvent->ignore();
00487       return;
00488     }
00489   }
00490   //otherwise exit like normal
00491   fileExit();
00492 }
00493 
00494 void OmgMainWindow::fileNew()
00495 {
00496   //fist check we have some layersets available and if not 
00497   //suggest to the user to do that first!
00498   if ( Omgui::getAvailableLayerSets().count() < 1)
00499   {
00500     QMessageBox myMessage;
00501     myMessage.setText(tr("You have not created any LayerSets yet. Before attempting to create an") +
00502                       tr(" experiment you need to have at least one LayerSet defined. Would") +
00503                       tr(" you like to open the LayerSet Manager now?"));
00504     myMessage.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
00505     switch (myMessage.exec()) {
00506       case QMessageBox::Yes:
00507         // yes was clicked
00508         showLayerSetManager();
00509         return;
00510         break;
00511       case QMessageBox::No:
00512         // no was clicked
00513         return;
00514         break;
00515       default:
00516         // should never be reached
00517         break;
00518     }
00519   }
00520 
00521 
00522   OmgExperimentDesigner myOmgExperimentDesigner(this) ;
00523   connect(&myOmgExperimentDesigner, SIGNAL(experimentCreated(OmgExperiment *)), 
00524       this, SLOT(setCurrentExperiment(OmgExperiment *)));
00525   myOmgExperimentDesigner.exec();
00526 }
00527 void OmgMainWindow::resetExperiment()
00528 {
00529   if (!mpCurrentExperiment)
00530   {
00531     return;
00532   }
00533   QMessageBox myMessage;
00534   myMessage.setText(tr("Resetting an experiment will mark"
00535         " all models as 'not run'. You will need to rerun the "
00536         " experiment to have the models considered complete."
00537         " No existing model outputs will be deleted, but when you "
00538         " rerun the experiment they will be overwritten."
00539         " Are you sure you want to reset the experiment now?"));
00540   myMessage.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
00541   switch (myMessage.exec()) 
00542   {
00543     case QMessageBox::Yes:
00544       // yes was clicked
00545       mpCurrentExperiment->reset();
00546       populateTree();
00547       return;
00548       break;
00549     case QMessageBox::No:
00550       // no was clicked
00551       //do nothing
00552       break;
00553     default:
00554       // should never be reached
00555       break;
00556   }
00557 }
00558 void OmgMainWindow::runExperiment()
00559 {
00560   if (!mpCurrentExperiment)
00561   {
00562     return;
00563   }
00564   mpRunningMovie->start();
00565 
00566   //make sure the modeller plugin is set...
00567   OmgModellerPluginInterface * mypModellerPlugin = 
00568     OmgModellerPluginRegistry::instance()->getPlugin();
00569   mpCurrentExperiment->setModellerPlugin(mypModellerPlugin);
00570 
00571 
00572   //
00573   // Get the messenger instance that arbitrates comms 
00574   // between the plugin and our gui
00575   //
00576   const OmgPluginMessenger * mypMessenger = 
00577     mpCurrentExperiment->modellerPlugin()->getMessenger();
00578 
00579   //
00580   // Disconnect the experiment and messenger in case
00581   // we are resuming / rerunning the same experiment
00582   //
00583   disconnect(mpCurrentExperiment, SIGNAL(experimentProgress(int )),
00584       this, SLOT(setExperimentProgress(int)));
00585   disconnect(mpCurrentExperiment, SIGNAL(experimentMaximum(int )),
00586       this, SLOT(setExperimentMaximum(int)));
00587   disconnect(mpCurrentExperiment, SIGNAL(logMessage(QString )),
00588       this, SLOT(logMessage(QString)));
00589   disconnect(mpCurrentExperiment, SIGNAL(experimentStopped()),
00590       this, SLOT(experimentStopped()));
00591   disconnect(mpCurrentExperiment, SIGNAL(modelCompleted(QString)),
00592       this, SLOT(modelCompleted(QString)));
00593   // disconnect the signals from the modeller adapter
00594   // used for monitoring the progress of individual models
00595   disconnect(mypMessenger, SIGNAL(modelCreationProgress(QString,int )),
00596       this, SLOT(setModelCreationProgress(QString,int)));
00597   disconnect(mypMessenger, SIGNAL(modelProjectionProgress(QString,int )),
00598       this, SLOT(setModelProjectionProgress(QString,int)));
00599   disconnect(mypMessenger, SIGNAL(modelMessage(QString,QString )),
00600       this, SLOT(logMessage(QString,QString)));
00601   disconnect(mypMessenger, SIGNAL(modelError(QString,QString )),
00602       this, SLOT(logError(QString,QString)));
00603 
00604   //
00605   // Connect the signals of our om experiment to our progress monitor
00606   // Used for showing progress of the experiment as it runs
00607   //
00608   connect(mpCurrentExperiment, SIGNAL(experimentProgress(int )),
00609       this, SLOT(setExperimentProgress(int)));
00610   connect(mpCurrentExperiment, SIGNAL(experimentMaximum(int )),
00611       this, SLOT(setExperimentMaximum(int)));
00612   connect(mpCurrentExperiment, SIGNAL(logMessage(QString )),
00613       this, SLOT(logMessage(QString)));
00614   connect(mpCurrentExperiment, SIGNAL(experimentStopped()),
00615       this, SLOT(experimentStopped()));
00616   // Connect the signals from the modeller adapter
00617   // used for monitoring the progress of individual models
00618   connect(mypMessenger, SIGNAL(modelCreationProgress(QString,int )),
00619       this, SLOT(setModelCreationProgress(QString,int)));
00620   connect(mypMessenger, SIGNAL(modelProjectionProgress(QString,int )),
00621       this, SLOT(setModelProjectionProgress(QString,int)));
00622   connect(mypMessenger, SIGNAL(modelMessage(QString,QString )),
00623       this, SLOT(logMessage(QString,QString)));
00624   connect(mypMessenger, SIGNAL(modelError(QString,QString )),
00625       this, SLOT(logError(QString,QString)));
00626   connect(mpCurrentExperiment, SIGNAL(modelCompleted(QString)),
00627       this, SLOT(modelCompleted(QString)));
00628 
00629   mpModelProgress->show();
00630   mpExperimentProgress->show();
00631 
00632   //reconfigure the run tool to cancel rather
00633   mpRunAct->setIcon(QIcon(":/status_aborted.png"));
00634   mpRunAct->setText(tr("Cancel cu&rrent experiment"));
00635   mpRunAct->setShortcut(tr("Ctrl+R"));
00636   mpRunAct->setStatusTip(tr("Cancel current experiment"));
00637   disconnect(mpRunAct);
00638   connect(mpRunAct, SIGNAL(triggered()), this, SLOT(stopExperiment()));
00639   disableControlsWhileRunning();
00640 
00641   QSettings mySettings;
00642   //clear the log file first
00643   bool myLogToFileFlag = mySettings.value("openModeller/logToFile", false).toBool();
00644   if (myLogToFileFlag)
00645   {
00646     QString myFileName = mySettings.value("openModeller/logFile","/tmp/omglog.txt").toString();
00647     QFile myFile( myFileName );
00648     if ( myFile.exists() )
00649     {
00650       myFile.remove(myFileName);
00651     }
00652   }
00653 
00654 
00655   //
00656   // Show some help info in the textbrowser to let the user
00657   // know what is going on
00658   //
00659   QString myString;
00660   myString = "<h1>" + tr("Experiment in progress") + "</h1>\n";
00661   myString += "<table>";
00662   myString += experimentHelpText();
00663   // finish up
00664 
00665   myString += "</table>";
00666   tabModelViewDetails->setEnabled(true);
00667   setReportStyleSheet();
00668   tbReport->setHtml(myString); 
00669 
00670   //
00671   // Make sure this comes last
00672   //
00673 
00674   bool myThreadingFlag = mySettings.value("openModeller/runExperimentInThread", true).toBool();
00675   if (myThreadingFlag)
00676   {
00677     //we call the qthread start method which in turn will
00678     //call the run method of our experiment after creating
00679     //a new thread.
00680     logMessage ("Running experiment in its own thread is enabled");
00681     mpCurrentExperiment->start();
00682   }
00683   else
00684   {
00685     logMessage ("Running experiment in its own thread is disabled");
00686     mpCurrentExperiment->run();
00687   }
00688 }
00689 
00690 void OmgMainWindow::closeExperiment()
00691 {
00692   //qDebug("Closing current experiment...");
00693   clearCurrentExperiment();
00694 
00695 }
00696 
00697 void OmgMainWindow::fileFetch()
00698 {
00699   OmgDataFetcherWizard myWizard;
00700   myWizard.exec();
00701 }
00702 
00703 bool OmgMainWindow::toolsConvert()
00704 {
00705   OmgGdalConverter myConverter;
00706   if (myConverter.exec()==QDialog::Accepted)
00707   {
00708     return true;
00709   }
00710   else
00711   {
00712     return false;
00713   }
00714 }
00715 
00716 bool OmgMainWindow::toolsContour()
00717 {
00718   OmgGdalRasterContour myContour;
00719   if (myContour.exec()==QDialog::Accepted)
00720   {
00721     return true;
00722   }
00723   else
00724   {
00725     return false;
00726   }
00727 }
00728 
00729 bool OmgMainWindow::toolsRasterThreshold()
00730 {
00731   OmgRasterThreshold myRasterThreshold;
00732   myRasterThreshold.setExperiment(mpCurrentExperiment);
00733   if (myRasterThreshold.exec()==QDialog::Accepted)
00734   {
00735     return true;
00736   }
00737   else
00738   {
00739     return false;
00740   }
00741 }
00742 
00743 bool OmgMainWindow::toolsClimateConvert()
00744 {
00745   OmgClimateConverter myConverter;
00746   if (myConverter.exec()==QDialog::Accepted)
00747   {
00748     return true;
00749   }
00750   else
00751   {
00752     return false;
00753   }
00754 }
00755 
00756 bool OmgMainWindow::toolsWarp()
00757 {
00758   OmgGdalWarp myWarp;
00759   if (myWarp.exec()==QDialog::Accepted)
00760   {
00761     return true;
00762   }
00763   else
00764   {
00765     return false;
00766   }
00767 }
00768 
00769 bool OmgMainWindow::toolsFileSplitter()
00770 {
00771   OmgTextFileSplitter mySplitter;
00772   if (mySplitter.exec()==QDialog::Accepted)
00773   {
00774     return true;
00775   }
00776   else
00777   {
00778     return false;
00779   }
00780 }
00781 
00782 bool OmgMainWindow::checkLicenseIsAgreed()
00783 {
00784   QSettings mySettings;
00785   if (mySettings.value("licensing/termsAgreedFlag",0).toInt()==1)
00786   {
00787     return true;
00788   }
00789   else
00790   {
00791     OmgTermsAndConditions myTerms;
00792     if (myTerms.exec()==QDialog::Accepted)
00793     {
00794       return true;
00795     }
00796     else
00797     {
00798       return false;
00799     }
00800   }
00801 }
00802 
00803 void OmgMainWindow::showLicense()
00804 {
00805   OmgTermsAndConditions myTerms;
00806   myTerms.show();
00807   myTerms.exec();
00808         
00809 }
00810 
00811 
00812 void OmgMainWindow::about()
00813 {
00814   OmgAbout myAbout;
00815   myAbout.show();
00816   myAbout.exec();
00817 }
00818 
00819 void OmgMainWindow::settingsOptions()
00820 {
00821   OmgOptions myOptions(this);
00822   myOptions.exec();
00823   //after the options closes lets see if the 
00824   //systray icon behaviour is changed
00825   QSettings mySettings;
00826   bool myUseSytemTrayFlag = mySettings.value("openModeller/useSystemTray", false).toBool();
00827   if (myUseSytemTrayFlag)
00828   {
00829     mTrayIcon->show();
00830   }
00831   else
00832   {
00833     mTrayIcon->hide();
00834   }
00835 }
00836 
00837 void OmgMainWindow::createActions()
00838 {
00839   mpNewAct = new QAction(QIcon(":/filenewExperiment.png"), tr("&New Experiment"), this);
00840   mpNewAct->setShortcut(tr("Ctrl+N"));
00841   mpNewAct->setStatusTip(tr("Create a new experiment"));
00842   connect(mpNewAct, SIGNAL(triggered()), this, SLOT(fileNew()));
00843 
00844   mpPrintPdfAct = new QAction(QIcon(":/pdf.png"), tr("&Save as pdf"), this);
00845   mpPrintPdfAct->setShortcut(tr("Ctrl+P"));
00846   mpPrintPdfAct->setStatusTip(tr("Save the experiment report as a pdf"));
00847   connect(mpPrintPdfAct, SIGNAL(triggered()), this, SLOT(printPdf()));
00848 
00849   mpRefreshReportsAct = new QAction(QIcon(":/refresh.png"), tr("Refresh all reports"), this);
00850   mpRefreshReportsAct->setStatusTip(tr("Refresh all reports"));
00851   connect(mpRefreshReportsAct, SIGNAL(triggered()), this, SLOT(refreshReports()));
00852 
00853   mpRunAct = new QAction(QIcon(":/status_restart.png"), tr("&Run / Resume current experiment"), this);
00854   mpRunAct->setShortcut(tr("Ctrl+R"));
00855   mpRunAct->setStatusTip(tr("Run / Resume current experiment"));
00856   connect(mpRunAct, SIGNAL(triggered()), this, SLOT(runExperiment()));
00857 
00858   mpResetAct = new QAction(QIcon(":/status_reset.png"), tr("&Reset the current experiment"), this);
00859   mpResetAct->setStatusTip(tr("Reset the current experiment"));
00860   connect(mpResetAct, SIGNAL(triggered()), this, SLOT(resetExperiment()));
00861 
00862   mpOpenAct = new QAction(QIcon(":/fileopen.png"), tr("&Open..."), this);
00863   mpOpenAct->setShortcut(tr("Ctrl+O"));
00864   mpOpenAct->setStatusTip(tr("Open a previously saved experiment"));
00865   connect(mpOpenAct, SIGNAL(triggered()), this, SLOT(fileOpen()));
00866   mpOpenAct->setEnabled(true);
00867   
00868   mpSaveAct = new QAction(QIcon(":/filesave.png"), tr("&Save..."), this);
00869   mpSaveAct->setShortcut(tr("Ctrl+S"));
00870   mpSaveAct->setStatusTip(tr("Save the experiment"));
00871   connect(mpSaveAct, SIGNAL(triggered()), this, SLOT(fileSave()));
00872   mpSaveAct->setEnabled(true);
00873   
00874 
00875   mpCloseAct = new QAction(QIcon(":/fileclose.png"), tr("&Close"), this);
00876   mpCloseAct->setStatusTip(tr("Close current experiment"));
00877   connect(mpCloseAct, SIGNAL(triggered()), this, SLOT(closeExperiment()));
00878   
00879   mpFetchAct = new QAction(QIcon(":/filefetch.png"), tr("&Search for locality data..."), this);
00880   mpFetchAct->setShortcut(tr("Ctrl+W"));
00881   mpFetchAct->setStatusTip(tr("Search for locality data on GBIF and other data sources"));
00882   connect(mpFetchAct, SIGNAL(triggered()), this, SLOT(fileFetch()));
00883 
00884   mpExitAct = new QAction(QIcon(":/exit.png"), tr("&Exit..."), this);
00885   mpExitAct->setShortcut(tr("Ctrl+Q"));
00886   mpExitAct->setStatusTip(tr("Close this application"));
00887   connect(mpExitAct, SIGNAL(triggered()), this, SLOT(fileExit()));
00888 
00889   mpToolsConvertAct = new QAction(QIcon(":/tools_converter.png"), tr("Convert &GIS Formats"), this);
00890   mpToolsConvertAct->setShortcut(tr("Ctrl+G"));
00891   mpToolsConvertAct->setStatusTip(tr("Convert model and environmental data"));
00892   connect(mpToolsConvertAct, SIGNAL(triggered()), this, SLOT(toolsConvert()));
00893 
00894   mpToolsClimateConvertAct = new QAction(QIcon(":/hadleyicon.png"), tr("&Import Climate Data"), this);
00895   mpToolsClimateConvertAct->setShortcut(tr("Ctrl+I"));
00896   mpToolsClimateConvertAct->setStatusTip(tr("Convert climate data to generic GIS format"));
00897   connect(mpToolsClimateConvertAct, SIGNAL(triggered()), this, SLOT(toolsClimateConvert()));
00898   
00899   mpToolsContourAct = new QAction(QIcon(":/contour.png"), tr("&Convert to Contours"), this);
00900   mpToolsContourAct->setShortcut(tr("Ctrl+C"));
00901   mpToolsContourAct->setStatusTip(tr("Create contours at equal intervals from raster data"));
00902   connect(mpToolsContourAct, SIGNAL(triggered()), this, SLOT(toolsContour()));
00903 
00904   
00905   mpToolsRasterThresholdAct = new QAction(QIcon(":/threshold.png"), tr("Compute &Thresholds and Hotspots..."), this);
00906   mpToolsRasterThresholdAct->setShortcut(tr("Ctrl+t"));
00907   mpToolsRasterThresholdAct->setStatusTip(tr("Perform postprocessing functions to calculate thresholds and hotspots"));
00908   connect(mpToolsRasterThresholdAct, SIGNAL(triggered()), this, SLOT(toolsRasterThreshold()));
00909 
00910   mpExportToCsvAct = new QAction(QIcon(":/export_csv.png"), tr("Export current model samples to CSV..."), this);
00911   //mpExportToCsvAct->setShortcut(tr("Ctrl+t"));
00912   mpExportToCsvAct->setStatusTip(tr("Export current model samples to CSV"));
00913   connect(mpExportToCsvAct, SIGNAL(triggered()), this, SLOT(exportSamplesToCsv()));
00914       
00915   mpToolsWarpAct = new QAction(QIcon(":/resize.png"), tr("&Resize Raster..."), this);
00916   mpToolsWarpAct->setShortcut(tr("Ctrl+R"));
00917   mpToolsWarpAct->setStatusTip(tr("Resize a raster file"));
00918   connect(mpToolsWarpAct, SIGNAL(triggered()), this, SLOT(toolsWarp()));
00919 
00920   mpToolsFileSplitterAct = new QAction(QIcon(":/filesplitter.png"), tr("&Split Text File..."), this);
00921   mpToolsFileSplitterAct->setShortcut(tr("Ctrl+S"));
00922   mpToolsFileSplitterAct->setStatusTip(tr("Split a text file into several parts"));
00923   connect(mpToolsFileSplitterAct, SIGNAL(triggered()), this, SLOT(toolsFileSplitter()));
00924 
00925   mpOptionsAct = new QAction(QIcon(":/configure.png"), tr("&Preferences..."), this);
00926   mpOptionsAct->setShortcut(tr("Ctrl+P"));
00927   mpOptionsAct->setStatusTip(tr("Configure preferences for this application"));
00928   connect(mpOptionsAct, SIGNAL(triggered()), this, SLOT(settingsOptions()));
00929 
00930   mpAboutOmgAct = new QAction(QIcon(":/om_logo.png"), tr("About &openModeller Desktop"), this);
00931   mpAboutOmgAct->setStatusTip(tr("Show this application's About box"));
00932   connect(mpAboutOmgAct, SIGNAL(triggered()), this, SLOT(about()));
00933 
00934   mpLicenseAct = new QAction(tr("License Agreement"), this);
00935   mpLicenseAct->setStatusTip(tr("Show this application's licensing terms"));
00936   connect(mpLicenseAct, SIGNAL(triggered()), this, SLOT(showLicense()));
00937 
00938   mpHelpAct = new QAction(QIcon(":/help.png"),tr("Documentation"), this);
00939   mpHelpAct->setStatusTip(tr("Show help text for openModeller Desktop"));
00940   connect(mpHelpAct, SIGNAL(triggered()), this, SLOT(showHelp()));
00941 
00942   mpSurveyAct = new QAction(QIcon(":/survey.png"),tr("User Survey"), this);
00943   mpSurveyAct->setStatusTip(tr("Participate in the  openModeller Desktop user survey"));
00944   connect(mpSurveyAct, SIGNAL(triggered()), this, SLOT(showSurvey()));
00945 
00946   mpLayerSetManagerAct = new QAction(QIcon(":/layersetmanager.png"),tr("LayerSets"), this);
00947   mpLayerSetManagerAct->setStatusTip(tr("Edit layerSets"));
00948   connect(mpLayerSetManagerAct, SIGNAL(triggered()), this, SLOT(showLayerSetManager()));
00949 
00950   mpAlgorithmManagerAct = new QAction(QIcon(":/algorithmmanager.png"),tr("Algorithm profiles"), this);
00951   mpAlgorithmManagerAct->setShortcut(tr("Ctrl+A"));
00952   mpAlgorithmManagerAct->setStatusTip(tr("Edit algorithm profiles"));
00953   connect(mpAlgorithmManagerAct, SIGNAL(triggered()), this, SLOT(showAlgorithmManager()));
00954 
00955   mpAvailableAlgorithmsReportAct = new QAction(QIcon(":/algorithmReport.png"),tr("Algorithm Profiles Report"), this);
00956   mpAvailableAlgorithmsReportAct->setStatusTip(tr("Print a report showing the various algorithm profiles that have been defined"));
00957   mpAvailableAlgorithmsReportAct->setEnabled(true);
00958   connect(mpAvailableAlgorithmsReportAct, SIGNAL(triggered()), this, SLOT(printAlgorithmProfilesReport()));
00959 
00960   mpExperimentReportAct = new QAction(QIcon(":/experimentReport.png"),tr("Experiment Report"), this);
00961   mpExperimentReportAct->setStatusTip(tr("Print a report showing all the models in this experiment"));
00962   mpExperimentReportAct->setEnabled(true);
00963   connect(mpExperimentReportAct, SIGNAL(triggered()), this, SLOT(printExperimentReport()));
00964 
00965 #ifdef WITH_QGIS  
00966   //qDebug("QGIS Support enabled");
00967   mpSaveAsImageAct = new QAction(QIcon(":/export_image.png"), tr("Export map image &as..."), this);
00968   mpSaveAsImageAct->setShortcut(tr("Ctrl+A"));
00969   mpSaveAsImageAct->setStatusTip(tr("Save map current map view as an image"));
00970   connect(mpSaveAsImageAct, SIGNAL(triggered()), this, SLOT(saveMapAsImage()));
00971   mpSaveAsImageAct->setEnabled(true);
00972   
00973   mpZoomInAct = new QAction(QIcon(":/zoomIn.png"),tr("Zoom In"), this);
00974   mpZoomInAct->setStatusTip(tr("Zoom in on the map by dragging a rectangle"));
00975   mpZoomInAct->setEnabled(true);
00976   connect(mpZoomInAct, SIGNAL(triggered()), this, SLOT(zoomInMode()));
00977 
00978   mpZoomOutAct = new QAction(QIcon(":/zoomOut.png"),tr("Zoom Out"), this);
00979   mpZoomOutAct->setStatusTip(tr("Zoom out on the map by dragging a rectangle"));
00980   mpZoomOutAct->setEnabled(true);
00981   connect(mpZoomOutAct, SIGNAL(triggered()), this, SLOT(zoomOutMode()));
00982 
00983   mpPanAct = new QAction(QIcon(":/pan.png"),tr("Pan"), this);
00984   mpPanAct->setStatusTip(tr("Pan the map by dragging it"));
00985   mpPanAct->setEnabled(true);
00986   connect(mpPanAct, SIGNAL(triggered()), this, SLOT(panMode()));
00987 
00988   mpZoomFullAct = new QAction(QIcon(":/zoomFull.png"),tr("Zoom to all"), this);
00989   mpZoomFullAct->setStatusTip(tr("Zoom to the full extents of the layers"));
00990   mpZoomFullAct->setEnabled(true);
00991   connect(mpZoomFullAct, SIGNAL(triggered()), this, SLOT(zoomFull()));
00992 
00993   mpZoomPreviousAct = new QAction(QIcon(":/zoomPrevious.png"),tr("Zoom to previous"), this);
00994   mpZoomPreviousAct->setStatusTip(tr("Zoom to the previous extents"));
00995   mpZoomPreviousAct->setEnabled(true);
00996   connect(mpZoomPreviousAct, SIGNAL(triggered()), this, SLOT(zoomPrevious()));
00997 
00998   /*
00999   mpIdentifyAct = new QAction(QIcon(":/identify.png"),tr("Identify"), this);
01000   mpIdentifyAct->setStatusTip(tr("Identify raster cell values on the map by clicking them"));
01001   mpIdentifyAct->setEnabled(true);
01002   connect(mpIdentifyAct, SIGNAL(triggered()), this, SLOT(identifyMode()));
01003 
01004   mpMeasureAct = new QAction(QIcon(":/measureDist.png"),tr("Measure Distances"), this);
01005   mpMeasureAct->setStatusTip(tr("Measure distances on the map"));
01006   mpMeasureAct->setEnabled(true);
01007   connect(mpMeasureAct, SIGNAL(triggered()), this, SLOT(measureMode()));
01008 
01009   mpMeasureAreaAct = new QAction(QIcon(":/measureArea.png"),tr("Measure Areas"), this);
01010   mpMeasureAreaAct->setStatusTip(tr("Measure areas on the map"));
01011   mpMeasureAreaAct->setEnabled(true);
01012   connect(mpMeasureAreaAct, SIGNAL(triggered()), this, SLOT(measureAreaMode()));
01013   */
01014 #endif
01015 
01016 
01017   //
01018   // These are special actions for our systray icon
01019   //
01020   mMinimizeAct = new QAction(tr("Mi&nimize"), this);
01021   connect(mMinimizeAct, SIGNAL(triggered()), this, SLOT(hide()));
01022 
01023   mMaximizeAct = new QAction(tr("Ma&ximize"), this);
01024   connect(mMaximizeAct, SIGNAL(triggered()), this, SLOT(showMaximized()));
01025 
01026   mRestoreAct = new QAction(tr("&Restore"), this);
01027   connect(mRestoreAct, SIGNAL(triggered()), this, SLOT(showNormal()));
01028 
01029   mQuitAct = new QAction(tr("&Quit"), this);
01030   connect(mQuitAct, SIGNAL(triggered()), this, SLOT(fileExit()));
01031 
01032   //
01033   // Thes are actions for context menus
01034   //
01035   mpDeleteModelAct = new QAction(tr("Delete &model"), this);
01036   connect(mpDeleteModelAct, SIGNAL(triggered()), this, SLOT(removeModelFromExperiment()));
01037   mpPublishModelAct = new QAction(tr("Publish &model"), this);
01038   connect(mpPublishModelAct, SIGNAL(triggered()), this, SLOT(publishModel()));
01039 
01040   mpDeleteAlgorithmAct = new QAction(tr("Delete &algorithm "), this);
01041   connect(mpDeleteAlgorithmAct, SIGNAL(triggered()), this, SLOT(removeAlgorithmFromExperiment()));
01042   mpDeleteTaxonAct = new QAction(tr("Delete &taxon"), this);
01043   connect(mpDeleteTaxonAct, SIGNAL(triggered()), this, SLOT(removeTaxonFromExperiment()));
01044 }
01045 
01046 void OmgMainWindow::createMenus()
01047 {
01048   mpFileMenu = menuBar()->addMenu(tr("&File"));
01049   mpFileMenu->addSeparator();
01050   mpFileMenu->addAction(mpNewAct);
01051   mpFileMenu->addAction(mpRunAct);
01052   mpFileMenu->addAction(mpResetAct);
01053   mpFileMenu->addAction(mpOpenAct);
01054   mpFileMenu->addAction(mpCloseAct);
01055   mpFileMenu->addAction(mpSaveAct);
01056   mpFileMenu->addAction(mpSaveAsImageAct);
01057   mpFileMenu->addAction(mpPrintPdfAct);
01058   mpFileMenu->addAction(mpRefreshReportsAct);
01059   mpFileMenu->addSeparator();
01060   mpFileMenu->addAction(mpExitAct);
01061 
01062   mpEditMenu = menuBar()->addMenu(tr("&Edit"));
01063   mpEditMenu->addAction(mpLayerSetManagerAct);
01064   mpEditMenu->addAction(mpAlgorithmManagerAct);
01065   mpEditMenu->addSeparator();
01066   mpEditMenu->addAction(mpOptionsAct);
01067 
01068   mpDataPrepMenu = menuBar()->addMenu(tr("&Data Preparation"));
01069   mpDataPrepMenu->addAction(mpFetchAct);
01070   mpDataPrepMenu->addAction(mpToolsConvertAct);
01071   mpDataPrepMenu->addAction(mpToolsClimateConvertAct);
01072   mpDataPrepMenu->addAction(mpToolsWarpAct);
01073   mpDataPrepMenu->addAction(mpToolsFileSplitterAct);
01074 
01075   mpReportsMenu = menuBar()->addMenu(tr("&Reports"));
01076   mpReportsMenu->addAction(mpAvailableAlgorithmsReportAct);
01077   mpReportsMenu->addAction(mpExperimentReportAct);
01078 
01079   mpPostProcessingMenu = menuBar()->addMenu(tr("&Post Processing"));
01080   mpPostProcessingMenu->addAction(mpToolsRasterThresholdAct);
01081 #ifndef OMG_NO_EXPERIMENTAL
01082   mpPostProcessingMenu->addAction(mpToolsContourAct);
01083 #endif
01084   mpPostProcessingMenu->addAction(mpExportToCsvAct);
01085   menuBar()->addSeparator();
01086 
01087   mpHelpMenu = menuBar()->addMenu(tr("&Help"));
01088   mpHelpMenu->addAction(mpHelpAct);
01089   mpHelpMenu->addAction(mpLicenseAct);
01090   //mpHelpMenu->addAction(mpSurveyAct);
01091   mpHelpMenu->addSeparator();
01092   mpHelpMenu->addAction(mpAboutOmgAct);
01093 
01094 
01095   //
01096   // Context menus
01097   //
01098 
01099   mpExperimentContextMenu = new QMenu(this);
01100   
01101   mpTaxonContextMenu = new QMenu(this);
01102   mpTaxonContextMenu->addAction(mpDeleteTaxonAct);
01103   
01104   mpModelContextMenu = new QMenu(this);
01105   mpModelContextMenu->addAction(mpDeleteModelAct); 
01106 #ifdef OMG_WEBCATALOGUE
01107   mpModelContextMenu->addAction(mpPublishModelAct);
01108 #endif
01109 
01110   mpAlgorithmContextMenu = new QMenu(this);
01111   mpAlgorithmContextMenu->addAction(mpDeleteAlgorithmAct); 
01112 }
01113 
01114 void OmgMainWindow::createToolBars()
01115 {
01116   //NOTE that the objectname needs to be set for each
01117   //tool bar for the QMainWindow::saveState method to work properly
01118   
01119   //file toolbar
01120   mpFileToolBar = addToolBar(tr("File"));
01121   mpFileToolBar->setIconSize(QSize(32,32));
01122   mpFileToolBar->setObjectName("FileToolBar");
01123   mpFileToolBar->addAction(mpLayerSetManagerAct);
01124   mpFileToolBar->addAction(mpAlgorithmManagerAct);
01125   mpFileToolBar->addAction(mpNewAct);
01126   mpFileToolBar->addAction(mpRunAct);
01127   mpFileToolBar->addAction(mpSaveAct);
01128   mpFileToolBar->addAction(mpOpenAct);
01129   mpFileToolBar->addAction(mpPrintPdfAct);
01130   mpFileToolBar->addAction(mpOptionsAct);
01131   //Data Preparation toolbar
01132   mpDataPrepToolBar = addToolBar(tr("Data Preparation Tools"));
01133   mpDataPrepToolBar->setIconSize(QSize(32,32));
01134   mpDataPrepToolBar->setObjectName("DataPrepToolBar");
01135   mpDataPrepToolBar->addAction(mpFetchAct);
01136   mpDataPrepToolBar->addAction(mpToolsConvertAct);
01137   mpDataPrepToolBar->addAction(mpToolsClimateConvertAct);
01138   mpDataPrepToolBar->addAction(mpToolsWarpAct);
01139   mpDataPrepToolBar->addAction(mpToolsFileSplitterAct);
01140 
01141   //Post processing toolbar
01142   mpPostProcessingToolBar = addToolBar(tr("Post Processing Tools"));
01143   mpPostProcessingToolBar->setIconSize(QSize(32,32));
01144   mpPostProcessingToolBar->setObjectName("PostProcessingToolBar");
01145   mpPostProcessingToolBar->addAction(mpToolsRasterThresholdAct);
01146   mpPostProcessingToolBar->addAction(mpToolsContourAct);
01147   mpPostProcessingToolBar->addAction(mpExportToCsvAct);
01148   
01149   //reports toolbar
01150   mpReportsToolBar = addToolBar(tr("Reports"));
01151   mpReportsToolBar->setIconSize(QSize(32,32));
01152   mpReportsToolBar->setObjectName("ReportsToolBar");
01153   mpReportsToolBar->addAction(mpAvailableAlgorithmsReportAct);
01154   mpReportsToolBar->addAction(mpExperimentReportAct);
01155 
01156 #ifdef WITH_QGIS  
01157   //qDebug("QGIS Support enabled - adding toolbar");
01158   //map browser toolbar
01159   mpMapToolBar = addToolBar(tr("Map"));
01160   mpMapToolBar->setIconSize(QSize(32,32));
01161   mpMapToolBar->setObjectName("MapToolBar");
01162   //mpMapToolBar->addAction(mpActionAddLayer);
01163   mpMapToolBar->addAction(mpSaveAsImageAct);
01164   mpMapToolBar->addAction(mpZoomInAct);
01165   mpMapToolBar->addAction(mpZoomOutAct);
01166   mpMapToolBar->addAction(mpZoomFullAct);
01167   mpMapToolBar->addAction(mpZoomPreviousAct);
01168   mpMapToolBar->addAction(mpPanAct);
01169   /*
01170   mpMapToolBar->addAction(mpIdentifyAct);
01171   mpMapToolBar->addAction(mpMeasureAct);
01172   mpMapToolBar->addAction(mpMeasureAreaAct);
01173   */
01174 #endif
01175 }
01176 void OmgMainWindow::createStatusBar()
01177 {
01178   //a progress bar for models
01179   //initially we make it a child of statusbar,
01180   //but during model run it will become a child of
01181   //each tree widget in turn
01182   mpModelProgress = new QProgressBar(statusBar());
01183   //just big enough to replace the icon next to the tree item
01184   mpModelProgress->setMaximumWidth(100);
01185   mpModelProgress->hide();
01186   QWhatsThis::add(mpModelProgress, tr("This bar displays how far any running model job has progressed."));
01187   statusBar()->addWidget(mpModelProgress, 1,true);
01188   //a progress bar for model creation
01189   mpExperimentProgress = new QProgressBar(statusBar());
01190   mpExperimentProgress->setMaximumWidth(100);
01191   mpExperimentProgress->hide();
01192   QWhatsThis::add(mpExperimentProgress, tr("This bar displays how far the current running experiment has progressed."));
01193   statusBar()->addWidget(mpExperimentProgress, 1,true);
01194 
01195   //experiment progress label
01196   QFont myFont( "Arial", 9 );
01197   statusBar()->setFont(myFont);
01198   mpExperimentProgressLabel = new QLabel(QString(),statusBar());
01199   mpExperimentProgressLabel->setFont(myFont);
01200   mpExperimentProgressLabel->setMinimumWidth(10);
01201   mpExperimentProgressLabel->setMargin(3);
01202   mpExperimentProgressLabel->setAlignment(Qt::AlignCenter);
01203   mpExperimentProgressLabel->setFrameStyle(QFrame::NoFrame);
01204   mpExperimentProgressLabel->setText("");
01205   statusBar()->addWidget(mpExperimentProgressLabel, 0,true);
01206 
01207   statusBar()->showMessage(tr("Ready"));
01208 }
01209 
01210 void OmgMainWindow::readSettings()
01211 {
01212   // restore window and toolbar positions
01213   QSettings mySettings;
01214   // restore the toolbar etc state
01215   QVariant myState = mySettings.value("/Geometry/state");
01216   this->restoreState(myState.toByteArray());
01217   //Save the splitter state splitter
01218   splitter->restoreState(mySettings.value("/Geometry/splitterState").toByteArray());
01219   // restore window geometry
01220   QDesktopWidget *myDesktop = QApplication::desktop();
01221   int myDesktopWidth = myDesktop->width();          // returns desktop width
01222   int myDesktopHeight = myDesktop->height();         // returns desktop height
01223   int myWidth = mySettings.value("/Geometry/width", 600).toInt();
01224   int myHeight = mySettings.value("/Geometry/height", 400).toInt();
01225   int myPosX = mySettings.value("/Geometry/x", (myDesktopWidth - 600) / 2).toInt();
01226   int myPosY = mySettings.value("/Geometry/y", (myDesktopHeight - 400) / 2).toInt();
01227   resize(myWidth,myHeight);
01228   move(myPosX,myPosY);
01229   if (mySettings.value("/Geometry/maximized", false).toBool())
01230   {
01231     showMaximized();
01232   }
01233   /*
01234   resize((myWidth < myDesktopWidth ? myWidth : myDesktopWidth ) ,
01235          (myHeight < myDesktopHeight ? myHeight : myDesktopHeight ));
01236   //only move teh window if its still has its top left corner on the screen
01237   //after the move
01238   if ((myPosX >= 0) && (myPosX < myDesktopWidth) && (myPosY >= 0) && (myPosY < myDesktopHeight))
01239   {
01240     move(myPosX, myPosY);
01241   }
01242   */
01243 
01244 }
01245 
01246 void OmgMainWindow::writeSettings()
01247 {
01248   // restore the toolbar and dock widgets postions using Qt4 settings API
01249   QSettings mySettings;
01250   //record if the window was maximised
01251   mySettings.setValue("/Geometry/maximized", this->isMaximized());
01252   // we dont want to store the maximised geometry so unmaximise first
01253   showNormal();
01254 
01255 
01256   // store the toolbar/dock widget settings using Qt4 settings API
01257   mySettings.setValue("/Geometry/state", this->saveState());
01258   mySettings.setValue("/Geometry/splitterState", splitter->saveState());
01259   
01260 
01261   // store window geometry
01262   QPoint myPoint = this->pos();
01263   QSize mySize = this->size();
01264   mySettings.setValue("/Geometry/x", myPoint.x());
01265   mySettings.setValue("/Geometry/y", myPoint.y());
01266   mySettings.setValue("/Geometry/width", mySize.width());
01267   mySettings.setValue("/Geometry/height", mySize.height());
01268 }
01269 
01270 void OmgMainWindow::publishModel()
01271 {
01272     OmgPublishToCatalogue myPublisher;
01273     myPublisher.setModel(mpCurrentModel);
01274     myPublisher.exec();
01275 }
01276 
01277 #ifdef WITH_QGIS
01278 
01289 static QString createFileFilter_(QString const &theLongName, QString const &glob)
01290 {
01291   return theLongName + " (" + glob.toLower() + " " + glob.toUpper() + ");;";
01292 }  // createFileFilter
01293 
01294 #endif
01295 
01296 
01297 
01298 void OmgMainWindow::fileSave()
01299 {
01300 
01301 }
01302 void OmgMainWindow::fileOpen()
01303 {
01304   OmgExperimentSelector mySelector(this);
01305   //mySelector.show();
01306   connect(&mySelector, SIGNAL(loadExperiment(OmgExperiment *)), this, SLOT(setCurrentExperiment(OmgExperiment *)));
01307   mySelector.exec();
01308 }
01309 void OmgMainWindow::exportSamplesToCsv()
01310 {
01311   QSettings myQSettings;  // where we keep last used filter in persistant state
01312   QString myLastUsedDir = myQSettings.value("openModeller/lastSaveAsCsvDir",".").toString();
01313 
01314   //create a file dialog using the filter list generated above
01315   std::auto_ptr < QFileDialog > myQFileDialog
01316   (
01317     new QFileDialog(
01318       this,
01319       QFileDialog::tr("Save samples to delimited file"),
01320       myLastUsedDir,
01321       "Comma delimited (*.csv);;Tab delimited (*.txt)"
01322       )
01323   );
01324   myQFileDialog->setFileMode(QFileDialog::AnyFile);
01325   myQFileDialog->setAcceptMode(QFileDialog::AcceptSave);
01326 
01327   //prompt the user for a filename
01328   QString myOutputFileName; 
01329   if (myQFileDialog->exec() == QDialog::Accepted)
01330   {
01331     QStringList myFiles = myQFileDialog->selectedFiles();
01332     if (!myFiles.isEmpty())
01333     {
01334       myOutputFileName = myFiles[0];
01335     }
01336   }
01337 
01338   if (!myOutputFileName.isEmpty())
01339   {
01340     if (myQFileDialog->selectedFilter()=="Comma delimited (*.csv)")
01341     {
01342       //ensure the user never ommitted the extension from the filename
01343       if (!myOutputFileName.toUpper().endsWith(".CSV")) 
01344       {
01345         myOutputFileName+=".csv";
01346       }
01347       Omgui::createTextFile(myOutputFileName , mpCurrentModel->localitiesToCsv(","));
01348     }
01349     else if (myQFileDialog->selectedFilter()=="Tab delimited (*.txt)")
01350     {
01351       //ensure the user never ommitted the extension from the filename
01352       if (!myOutputFileName.toUpper().endsWith(".TXT")) 
01353       {
01354         myOutputFileName+=".txt";
01355       }
01356       Omgui::createTextFile(myOutputFileName , mpCurrentModel->localitiesToCsv("\t"));
01357     }
01358     else
01359     {
01360       QMessageBox::warning( this,tr("openModeller Desktop"),tr("Unknown delimited format: ") +
01361              myQFileDialog->selectedFilter());
01362 
01363     }
01364     //QFile::copy(mpCurrentModel->csvFileName(), myOutputFileName);
01365     myQSettings.setValue("openModeller/lastSaveAsCsvDir", myQFileDialog->directory().dirName());
01366   }
01367 }
01368 
01369 void OmgMainWindow::saveMapAsImage()
01370 {
01371 #ifdef WITH_QGIS
01372   //qDebug("QGIS Support enabled - save map as image using QGIS");
01373   //create a map to hold the QImageIO names and the filter names
01374   //the QImageIO name must be passed to the pixmap saveas image function
01375   typedef QMap<QString, QString> FilterMap;
01376   FilterMap myFilterMap;
01377 
01378   //find out the last used filter
01379   QSettings myQSettings;  // where we keep last used filter in persistant state
01380   QString myLastUsedFilter = myQSettings.value("openModeller/saveAsImageFilter").toString();
01381   QString myLastUsedDir = myQSettings.value("openModeller/lastSaveAsImageDir",".").toString();
01382 
01383   QList<QByteArray> myFormats = QPictureIO::outputFormats();
01384   // Workaround for a problem with Qt4 - calls to outputFormats tend
01385   // to return nothing :(
01386   if (myFormats.count() == 0)
01387   {
01388     myFormats.append("png");
01389     myFormats.append("jpg");
01390   }
01391   // get a list of supported output image types
01392   int myCounterInt=0;
01393   QString myFilters;
01394   for ( ; myCounterInt < myFormats.count(); myCounterInt++ )
01395   {
01396     QString myFormat=QString(myFormats.at( myCounterInt ));
01397     QString myFilter = createFileFilter_(myFormat + " format", "*."+myFormat);
01398     myFilters += myFilter;
01399     myFilterMap[myFilter] = myFormat;
01400   }
01401 
01402   //qDebug() << "Available Filters Map: " ;
01403   //FilterMap::Iterator myIterator;
01404   //for ( myIterator = myFilterMap.begin(); myIterator != myFilterMap.end(); ++myIterator )
01405   //{
01406   //    //qDebug() << myIterator.key() << "  :  " << myIterator.data() ;
01407   //}
01408 
01409   //create a file dialog using the filter list generated above
01410   std::auto_ptr < QFileDialog > myQFileDialog
01411   (
01412     new QFileDialog(
01413       this,
01414       QFileDialog::tr("Save file dialog"),
01415       myLastUsedDir,
01416       myFilters
01417     )
01418   );
01419 
01420 
01421   // allow for selection of more than one file
01422   myQFileDialog->setFileMode(QFileDialog::AnyFile);
01423 
01424   if (myLastUsedFilter!=QString::null)       // set the filter to the last one used
01425   {
01426     myQFileDialog->selectFilter(myLastUsedFilter);
01427   }
01428 
01429 
01430   //prompt the user for a filename
01431   QString myOutputFileName; // = myQFileDialog->getSaveFileName(); //delete this
01432   if (myQFileDialog->exec() == QDialog::Accepted)
01433   {
01434     QStringList myFiles = myQFileDialog->selectedFiles();
01435     if (!myFiles.isEmpty())
01436     {
01437       myOutputFileName = myFiles[0];
01438     }
01439   }
01440 
01441   QString myFilterString = myQFileDialog->selectedFilter()+";;";
01442 
01443   //  std::cout << "Selected filter: " << myFilterString << std::endl;
01444   //  std::cout << "Image type to be passed to pixmap saver: " << myFilterMap[myFilterString] << std::endl;
01445 
01446   myQSettings.setValue("openModeller/lastSaveAsImageFilter" , myFilterString);
01447   myQSettings.setValue("openModeller/lastSaveAsImageDir", myQFileDialog->directory().dirName());
01448 
01449   if (!myOutputFileName.isEmpty())
01450   {
01451     mpMapCanvas->saveAsImage(myOutputFileName,NULL,myFilterMap[myFilterString]);
01452     statusBar()->message(tr("Saved map image to") + " " + myOutputFileName);
01453   }
01454 #endif
01455 }
01456 
01457 
01458 void OmgMainWindow::setCurrentModel(OmgModel * thepModel)
01459 {
01460   if (thepModel == NULL) 
01461   { 
01462     return;
01463   }
01464   else if (thepModel->hasError())
01465   {
01466     QString myBusyText = tr("This model failed. See log report below for "
01467       "possible reasons why.");
01468     tbReport->clear();
01469     setReportStyleSheet();
01470           tbReport->setHtml(
01471       "<center>"
01472       "<table>"
01473       "<tr>"
01474       "<td><center><img src=\":/status_aborted.png\"></center></td>"
01475       "</tr><tr>"
01476       "<td><h2><center>" + myBusyText + "</center></h2></td>"
01477       "</tr>"
01478       "</table>"
01479       "</center>"
01480       "<pre>"
01481       + thepModel->modelLog() +
01482       "</pre>"
01483       );
01484     return;
01485   }
01486   else if (thepModel->isCompleted() != true)
01487   {
01488     QString myBusyText = tr("This model is currently"
01489       " running or has not yet been run.");
01490     tbReport->clear();
01491     setReportStyleSheet();
01492           tbReport->setHtml(
01493       "<center>"
01494       "<table>"
01495       "<tr>"
01496       "<td><center><img src=\":/status_queued.png\"></center></td>"
01497       "</tr><tr>"
01498       "<td><h2><center>" + myBusyText + "</center></h2></td>"
01499       "</tr>"
01500       "</table>"
01501       "</center>");
01502     return;
01503   }
01504   mpCurrentModel = thepModel;
01505   mpLocalitiesModel->setModel(mpCurrentModel);
01506   disableMapControls();
01507   //qDebug("Setting model to : "+mpCurrentModel->taxonName().toLocal8Bit());
01508   showReport(cboReportMode->currentText());
01509   
01510 #ifdef WITH_QGIS
01511   QSettings mySettings;
01512   //
01513   // Set the copyrightlabel plugin text to the 
01514   // species name and alg name
01515   //
01516   QString myLabel(mpCurrentModel->algorithm().name() +
01517         "<br/>" +
01518         mpCurrentModel->taxonName());
01519   QgsProject::instance()->writeEntry("CopyrightLabel","/Label", myLabel);
01520   //now we need to call projectRead signal
01521   //on the copyright plugin to get it to update
01522   //itself
01523   emit projectRead();
01524     
01525   //qDebug("QGIS Support enabled - loading layers");
01526   //create a layerset
01527   QList<QgsMapCanvasLayer> myList;
01528   mpMapCanvas->freeze(true);
01529   QgsMapLayerRegistry::instance()->removeAllMapLayers();
01530   mpMapCanvas->freeze(false);
01531   //
01532   // First the vector layer for occurrences and absences
01533   //
01534   //try to create and add the vectore layer of points for occurrences
01535   //if the provider is not found or some other problem occurred
01536   //we continue with just the raster
01537   QString myShapeFile (mpCurrentModel->workDir() + mpCurrentModel->shapefileName());
01538   qDebug("Trying to load: " + mpCurrentModel->shapefileName().toLocal8Bit());
01539   QString myRasterFile (mpCurrentModel->workDir() + mpCurrentModel->rawImageFileName());
01540   if (!QFile::exists(myShapeFile))
01541   {
01542     qDebug("Vector layer does not exist");
01543     logMessage ("Vector Layer does not exist in file system");
01544   }
01545   else
01546   {
01547     QString myProviderName      = "ogr";
01548     QFileInfo myVectorFileInfo(myShapeFile);
01549     QgsVectorLayer * mypVectorLayer = new QgsVectorLayer(myVectorFileInfo.filePath(), 
01550         myVectorFileInfo.completeBaseName(), myProviderName);
01551     if (mypVectorLayer->isValid())
01552     {
01553       //qDebug("Vector Layer is valid");
01554       //
01555       // For backwards compatibility we need to check
01556       // if this layer has a status field. If not
01557       // we display as a single symble, otherwise we
01558       // use a unique value renderer
01559       //
01560       QgsVectorDataProvider *mypProvider = 
01561         dynamic_cast<QgsVectorDataProvider *>(mypVectorLayer->getDataProvider());    
01562       if (mypProvider)
01563       { 
01564         int mySymbolSize(mySettings.value("mapping/localitySymbolSize",10).toInt());
01565         QgsFieldMap myFields = mypProvider->fields();
01566         bool myNewFormatFlag = false;
01567         for (int i = 0; i < myFields.size(); i++ )
01568         {
01569           if (myFields[i].name()=="status")
01570           {
01571             myNewFormatFlag=true;
01572             break;
01573           }
01574         }
01575         if (myNewFormatFlag) // uniquevalue renderer
01576         {
01577           QColor myPresenceColor(mySettings.value("mapping/presenceColour",QColor(Qt::green).name()).toString());
01578           QColor myAbsenceColor(mySettings.value("mapping/absenceColour",QColor(Qt::red).name()).toString());
01579           //
01580           // Presence with samples symbol
01581           //
01582           QgsSymbol *  mypPresenceSymbol = new QgsSymbol(mypVectorLayer->vectorType(),"Present","");
01583           mypPresenceSymbol->setNamedPointSymbol("hard:circle");
01584           mypPresenceSymbol->setFillColor(myPresenceColor);
01585           mypPresenceSymbol->setColor(Qt::black); //outline
01586           mypPresenceSymbol->setPointSize(mySymbolSize);
01587           mypPresenceSymbol->setFillStyle(Qt::SolidPattern);
01588 
01589           //
01590           // Presence with NO samples symbol
01591           //
01592           QgsSymbol *  mypPresence2Symbol = new QgsSymbol(mypVectorLayer->vectorType(),"Present - Not Used","");
01593           mypPresence2Symbol->setNamedPointSymbol("hard:triangle");
01594           mypPresence2Symbol->setFillColor(myPresenceColor);
01595           mypPresence2Symbol->setColor(Qt::black); //outline
01596           mypPresence2Symbol->setPointSize(mySymbolSize);
01597           mypPresence2Symbol->setFillStyle(Qt::SolidPattern);
01598 
01599           // 
01600           // Absence with samples symbol
01601           //
01602           QgsSymbol *  mypAbsenceSymbol = new QgsSymbol(mypVectorLayer->vectorType(),"Absent","");
01603           mypAbsenceSymbol->setNamedPointSymbol("hard:circle");
01604           mypAbsenceSymbol->setFillColor(myAbsenceColor);
01605           mypAbsenceSymbol->setColor(Qt::black); //outline
01606           mypAbsenceSymbol->setPointSize(mySymbolSize);
01607           mypAbsenceSymbol->setFillStyle(Qt::SolidPattern);
01608 
01609           // 
01610           // Absence with NO samples symbol
01611           //
01612           QgsSymbol *  mypAbsence2Symbol = new QgsSymbol(mypVectorLayer->vectorType(),"Absent","");
01613           mypAbsence2Symbol->setNamedPointSymbol("hard:triangle");
01614           mypAbsence2Symbol->setFillColor(myAbsenceColor);
01615           mypAbsence2Symbol->setColor(Qt::black); //outline
01616           mypAbsence2Symbol->setPointSize(mySymbolSize);
01617           mypAbsence2Symbol->setFillStyle(Qt::SolidPattern);
01618 
01619 
01620 
01621           //create renderer
01622           QgsUniqueValueRenderer *mypRenderer = new QgsUniqueValueRenderer(mypVectorLayer->vectorType());
01623           qDebug("Provider ok...getting status field");
01624           int myFieldIndex = mypProvider->indexFromFieldName("status");
01625           if(myFieldIndex > 0) 
01626           {
01627             qDebug("Status field found");
01628             mypRenderer->setClassificationField(myFieldIndex);
01629             mypRenderer->insertValue("Present",mypPresenceSymbol);
01630             mypRenderer->insertValue("Present - Not Used",mypPresence2Symbol);
01631             mypRenderer->insertValue("Absent",mypAbsenceSymbol);
01632             mypRenderer->insertValue("Absent - Not Used",mypAbsence2Symbol);
01633             mypVectorLayer->setRenderer(mypRenderer);
01634             // Add the layer to the Layer Registry
01635             QgsMapLayerRegistry::instance()->addMapLayer(mypVectorLayer, TRUE);
01636             myList.append(QgsMapCanvasLayer(mypVectorLayer, TRUE)); //bool visibility
01637           } // field index
01638         }
01639         else // old format so use single symbol renderer
01640         {
01641           // old format did not support absence
01642           QgsSymbol *  mypSymbol = new QgsSymbol(mypVectorLayer->vectorType());
01643           QColor myPresenceColor(mySettings.value("mapping/presenceColour",QColor(Qt::green).name()).toString());
01644           mypSymbol->setFillColor(myPresenceColor);
01645           mypSymbol->setColor(Qt::black); //outline
01646           mypSymbol->setPointSize(mySymbolSize);
01647           mypSymbol->setFillStyle(Qt::SolidPattern);
01648           QgsSingleSymbolRenderer *mypRenderer = new QgsSingleSymbolRenderer(mypVectorLayer->vectorType());
01649           mypRenderer->addSymbol(mypSymbol);
01650           mypVectorLayer->setRenderer(mypRenderer);
01651           // Add the layer to the Layer Registry
01652           QgsMapLayerRegistry::instance()->addMapLayer(mypVectorLayer, TRUE);
01653           myList.append(QgsMapCanvasLayer(mypVectorLayer, TRUE)); //bool visibility
01654         } //old format
01655       } //provider valid
01656     } //vector layer valid
01657     else
01658     {
01659       //qDebug("Vector Layer is NOT valid, and Not Loaded");
01660     }
01661   }
01662   //
01663   // Next the user defined country boundaries layer (if any)
01664   //
01665   myShapeFile = mySettings.value("mapping/contextLayer").toString();
01666   QFileInfo myVectorFileInfo(myShapeFile);
01667   if (myVectorFileInfo.exists())
01668   {
01669     qDebug("Loading context layer");
01670     QString myProviderName      = "ogr";
01671     QgsVectorLayer * mypVectorLayer = new QgsVectorLayer(myVectorFileInfo.filePath(), 
01672         myVectorFileInfo.completeBaseName(), myProviderName);
01673     if (mypVectorLayer->isValid())
01674     {
01675       //qDebug("Vector Layer is valid");
01676       //
01677       // For backwards compatibility we need to check
01678       // if this layer has a status field. If not
01679       // we display as a single symble, otherwise we
01680       // use a unique value renderer
01681       //
01682       QgsVectorDataProvider *mypProvider = 
01683         dynamic_cast<QgsVectorDataProvider *>(mypVectorLayer->getDataProvider());    
01684       if (mypProvider)
01685       {
01686         QgsSymbol *  mypSymbol = new QgsSymbol(mypVectorLayer->vectorType());
01687         QColor myContextColor(mySettings.value("mapping/contextLineColour",QColor(Qt::gray).name()).toString());
01688         mypSymbol->setFillColor(myContextColor); //ignored since we paint with nobrush
01689         mypSymbol->setColor(myContextColor); //outline
01690         mypSymbol->setLineWidth(mySettings.value("mapping/contextLineWidth",1).toInt());
01691         mypSymbol->setFillStyle(Qt::NoBrush);
01692         QgsSingleSymbolRenderer *mypRenderer = new QgsSingleSymbolRenderer(mypVectorLayer->vectorType());
01693         mypRenderer->addSymbol(mypSymbol);
01694         mypVectorLayer->setRenderer(mypRenderer);
01695         // Add the layer to the Layer Registry
01696         QgsMapLayerRegistry::instance()->addMapLayer(mypVectorLayer, TRUE);
01697         myList.append(QgsMapCanvasLayer(mypVectorLayer, TRUE)); //bool visibility
01698       } 
01699     }//context vector layer is valid
01700   }//context vector layer exists
01701 
01702   //
01703   //next the raster...
01704   //
01705   //check the file exists first
01706   if (!QFile::exists(myRasterFile))
01707   {
01708     qDebug("Layer does not exist in file system");
01709     //zoom to the extent of all vectors in this case
01710     mpMapCanvas->zoomFullExtent();
01711   }
01712   else //layer exists
01713   {
01714     QFileInfo myRasterFileInfo(myRasterFile);
01715     QgsRasterLayer * mypRasterLayer = new QgsRasterLayer(myRasterFileInfo.filePath(), 
01716         myRasterFileInfo.completeBaseName());
01717 
01718     if (mypRasterLayer->isValid())
01719     {
01720       QString myFormat = mpCurrentModel->modelRasterFormat();
01721       //float myInputNoData = Omgui::getOutputFormatNoData().value(myFormat);
01722       float myFormatMinimum = Omgui::getOutputFormatRanges().value(myFormat).first;
01723       float myFormatMaximum = Omgui::getOutputFormatRanges().value(myFormat).second;
01724       mypRasterLayer->setDrawingStyle(QgsRasterLayer::SINGLE_BAND_PSEUDO_COLOR);
01725       mypRasterLayer->setColorShadingAlgorithm(QgsRasterLayer::PSEUDO_COLOR);  
01726       mypRasterLayer->setMinimumValue(mypRasterLayer->getGrayBandName(),myFormatMinimum, false);
01727       mypRasterLayer->setMaximumValue(mypRasterLayer->getGrayBandName(),myFormatMaximum);
01728       mypRasterLayer->setContrastEnhancementAlgorithm(
01729           QgsContrastEnhancement::STRETCH_TO_MINMAX, false);
01730       qDebug("Raster Layer is valid");
01731       // Add the layer to the Layer Registry
01732       QgsMapLayerRegistry::instance()->addMapLayer(mypRasterLayer, TRUE);
01733       // Add the raster layer to the Layer Set
01734       myList.append(QgsMapCanvasLayer(mypRasterLayer, TRUE));
01735 
01736 
01737       // set the canvas to the extent of our layer
01738       bool myResetExtentsFlag= mySettings.value("mapping/resetExtents", false).toBool();
01739       if (myResetExtentsFlag || mResetExtentsFlag)
01740       {
01741         mpMapCanvas->setExtent(mypRasterLayer->extent());
01742         mResetExtentsFlag=false;
01743       }
01744     } //raster is valid
01745     else
01746     {
01747       qDebug("Raster Layer is NOT valid");
01748     }
01749   }//raster exists
01750   // Set the Map Canvas Layer Set
01751   mpMapCanvas->setLayerSet(myList);
01752   enableMapControls();
01753 #else
01754   lblOutputMap->setPixmap(QPixmap(mpCurrentModel->workDir() + mpCurrentModel->colouredImageFileName()));
01755 #endif
01756   
01757 }
01758 
01759 
01760 void OmgMainWindow::on_cboSortBy_currentIndexChanged(QString theString)
01761 {
01762   if (theString==tr("Algorithm"))
01763   {
01764     mSortMode= BY_ALGORITHM;
01765   }
01766   else
01767   {
01768     mSortMode= BY_TAXON;
01769   }
01770   populateTree();
01771 }
01772 void OmgMainWindow::setCurrentExperiment(OmgExperiment * theExperiment)
01773 {
01774   if (mpCurrentExperiment)
01775   {
01776     delete mpCurrentExperiment; 
01777   }
01778   mpCurrentExperiment = theExperiment;
01779   //force zoom to extents of first layer clicked
01780   mResetExtentsFlag=true;
01781   //Set up experiment tree  
01782   bool myHasIncompleteModelsFlag = populateTree();
01783   
01784   //Turn on all the model details widgets
01785   setEnableModelDetailWidgets(true);
01786   //adjust the window title to reflect the name of the experiment
01787   setWindowTitle("openModeller Desktop - " + mpCurrentExperiment->name());
01788   //prompt the user to run the experiment if it still has unrun models
01789   if ( myHasIncompleteModelsFlag )
01790   {
01791     QMessageBox myMessage;
01792     myMessage.setText(tr("Would you like to run this experiment now?"));
01793     myMessage.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
01794     switch (myMessage.exec()) {
01795       case QMessageBox::Yes:
01796         // yes was clicked
01797         runExperiment();
01798         return;
01799         break;
01800       case QMessageBox::No:
01801         // no was clicked
01802         //do nothing
01803         break;
01804       default:
01805         // should never be reached
01806         break;
01807     }
01808   }
01809 }
01810 bool OmgMainWindow::populateTree()
01811 {
01812   if (!mpCurrentExperiment)
01813   {
01814     return false;
01815   }
01816   bool myHasIncompleteModelsFlag=false;
01817   disconnect(treeExperiment, SIGNAL(currentItemChanged(QTreeWidgetItem * ,QTreeWidgetItem *)), 0, 0);
01818   treeExperiment->clear();
01819   int myCount = mpCurrentExperiment->count();
01820   //make a node for the experiment
01821   QTreeWidgetItem * mypExperimentItem = new QTreeWidgetItem(treeExperiment);
01822   mypExperimentItem->setText(0,tr("Experiment"));
01823   QIcon myExperimentIcon;
01824   myExperimentIcon.addFile(":/filenewExperiment.png");
01825   mypExperimentItem->setIcon(0,myExperimentIcon);
01826   treeExperiment->setItemExpanded(mypExperimentItem,true);
01827   //select the experiemnt as active item 
01828   treeExperiment->setItemSelected(mypExperimentItem,true);
01829   currentItemChanged(mypExperimentItem,mypExperimentItem);
01830   //
01831   //make a parent node for each alg type or taxon (depending on sort order)
01832   //
01833   QMap <QString,QTreeWidgetItem *> myParentMap;
01834   for (int i=0; i<myCount; i++)
01835   {
01836     OmgModel * mypModel=mpCurrentExperiment->getModel(i);
01837     if (mypModel==NULL)
01838     {
01839       emit logMessage("Model is null is NULL, skipping");
01840       continue;
01841     }
01842     QString myName;
01843     QString myParentType;
01844     QString myIconFileName;
01845     if (mSortMode==BY_TAXON)
01846     {
01847       myName = mypModel->taxonName();
01848       myParentType = "Taxon";
01849       myIconFileName = ":/taxon.png";
01850     }
01851     else //BY_ALGORITHM
01852     {
01853       myName = mypModel->algorithm().name();
01854       myParentType = "Algorithm";
01855       myIconFileName = ":/algorithmmanager.png";
01856     }
01857     if (!myParentMap.contains(myName))
01858     {
01859       QTreeWidgetItem * mypParentItem = new QTreeWidgetItem(mypExperimentItem);
01860       mypParentItem->setText(0,myName);
01861       QIcon myParentIcon;
01862       myParentIcon.addFile(myIconFileName);
01863       mypParentItem->setIcon(0,myParentIcon);
01864       myParentMap[myName]=mypParentItem;
01865       //used later to detect if an alg/taxon node was clicked
01866       mypParentItem->setText(1,myParentType); 
01867       
01868       //expand the tree
01869       treeExperiment->setItemExpanded(mypParentItem,true);
01870     }
01871   }
01872   //
01873   // Loop through all models now, adding a nore for each
01874   // to the appropriate parent.
01875   //
01876   mTreeItemsHash.clear();
01877   for (int i=0; i<myCount; i++)
01878   {
01879     OmgModel * mypModel=mpCurrentExperiment->getModel(i);
01880     if (mypModel==NULL)
01881     {
01882       emit logMessage("Model is null is NULL, skipping");
01883       continue;
01884     }
01885     //determine the correct parent for this model in the tree
01886     QTreeWidgetItem * mypParentItem;
01887     QString myItemText;
01888     if (mSortMode==BY_TAXON)
01889     {
01890       mypParentItem = myParentMap.value(mypModel->taxonName());
01891       myItemText = mypModel->algorithm().name();
01892     }
01893     else // BY_ALGORITHM
01894     {
01895       mypParentItem = myParentMap.value(mypModel->algorithm().name());
01896       myItemText = mypModel->taxonName();
01897     }
01898     //now the model
01899     QTreeWidgetItem * mypItem = new QTreeWidgetItem(mypParentItem);
01900     mypItem->setText(0,myItemText);
01901     //add the item to the items hash so we can find it easily later
01902     mTreeItemsHash.insert(mypModel->guid(),mypItem);
01903     if (mypModel->isCompleted())
01904     {
01905       QIcon myIcon;
01906       myIcon.addFile(":/status_complete.png");
01907       mypItem->setIcon(0,myIcon);
01908     }
01909     else if (mypModel->hasError())
01910     {
01911       QIcon myIcon;
01912       myIcon.addFile(":/status_aborted.png");
01913       mypItem->setIcon(0,myIcon);
01914     }
01915     else
01916     {
01917       QIcon myIcon;
01918       myIcon.addFile(":/status_queued.png");
01919       mypItem->setIcon(0,myIcon);
01920       myHasIncompleteModelsFlag=true;
01921     }
01922     mypItem->setText(1,mypModel->guid());
01923   }
01924   treeExperiment->sortItems (0, Qt::AscendingOrder );
01925   // 
01926   // For trapping right mouse clicks on the tree
01927   // See the qt docs on thie but in essence we 
01928   // need to tell teh treewidget that we have
01929   // a custom context menu handler otherwise
01930   // we wont receive events.
01931   // 
01932   //
01933   treeExperiment->setContextMenuPolicy ( Qt::CustomContextMenu );
01934   connect(treeExperiment, SIGNAL(customContextMenuRequested (const QPoint & )), 
01935                this, SLOT(treeContextMenuEvent(const QPoint & )));
01936   //for trapping selections in the tree
01937   connect(treeExperiment, SIGNAL(currentItemChanged(QTreeWidgetItem * ,QTreeWidgetItem *)), 
01938                this, SLOT(currentItemChanged(QTreeWidgetItem * ,QTreeWidgetItem *)));
01939   return myHasIncompleteModelsFlag;
01940 }
01941 void OmgMainWindow::showAlgorithmSummary(QString theAlgorithmName)
01942 {
01943   if (!mpCurrentExperiment)
01944   {
01945     return;
01946   }
01947   //disconnect(listThumbnails, SIGNAL(currentItemChanged(QListWidgetItem * ,QListWidgetItem *)), 0, 0);
01948   tbReport->hide();
01949   listThumbnails->show();
01950   listThumbnails->clear();
01951   int myCount = mpCurrentExperiment->count();
01952   //
01953   // Loop through all models now, adding a list widget item for each
01954   //
01955   for (int i=0; i<myCount; i++)
01956   {
01957     OmgModel * mypModel=mpCurrentExperiment->getModel(i);
01958     if (mypModel==NULL)
01959     {
01960       emit logMessage("Model is null is NULL, skipping");
01961       continue;
01962     }
01963     //determine the correct parent for this model in the tree
01964     QString myItemText;
01965     myItemText = mypModel->algorithm().name();
01966     if (myItemText==theAlgorithmName)
01967     {
01968       QFileInfo myFileInfo(mypModel->workDir() + mypModel->thumbnailFileName());
01969       if (myFileInfo.exists() && !mypModel->thumbnailFileName().isEmpty())
01970       {
01971         //now the model
01972         QListWidgetItem * mypItem = new QListWidgetItem(listThumbnails);
01973         QIcon myIcon;
01974         myIcon.addFile(mypModel->workDir() + mypModel->thumbnailFileName());
01975         mypItem->setIcon(myIcon);
01976       }
01977       else
01978       {
01979         emit logMessage(mypModel->thumbnailFileName() + " is missing, not added to thumbnail view");
01980       }
01981     }
01982   }
01983   //connect(listThumbnails, SIGNAL(currentItemChanged(QListWidgetItem * ,QListWidgetItem *)), 
01984         //       this, SLOT(currentItemChanged(QListWidgetItem * ,QListWidgetItem *)));
01985 }
01986 
01987 void OmgMainWindow::showTaxonSummary(QString theTaxonName)
01988 {
01989   if (!mpCurrentExperiment)
01990   {
01991     return;
01992   }
01993   //disconnect(listThumbnails, SIGNAL(currentItemChanged(QListWidgetItem * ,QListWidgetItem *)), 0, 0);
01994   tbReport->hide();
01995   listThumbnails->show();
01996   listThumbnails->clear();
01997   int myCount = mpCurrentExperiment->count();
01998   //
01999   // Loop through all models now, adding a list widget item for each
02000   //
02001   for (int i=0; i<myCount; i++)
02002   {
02003     OmgModel * mypModel=mpCurrentExperiment->getModel(i);
02004     if (mypModel==NULL)
02005     {
02006       emit logMessage("Model is null is NULL, skipping");
02007       continue;
02008     }
02009     //determine the correct parent for this model in the tree
02010     QString myItemText = mypModel->taxonName();
02011     if (myItemText==theTaxonName)
02012     {
02013       QFileInfo myFileInfo(mypModel->workDir() + mypModel->thumbnailFileName());
02014       if (myFileInfo.exists() && !mypModel->thumbnailFileName().isEmpty())
02015       {
02016         //now the model
02017         QListWidgetItem * mypItem = new QListWidgetItem(listThumbnails);
02018         QIcon myIcon;
02019         myIcon.addFile(mypModel->workDir() + mypModel->thumbnailFileName());
02020         mypItem->setIcon(myIcon);
02021       }
02022     }
02023   }
02024   //connect(listThumbnails, SIGNAL(currentItemChanged(QListWidgetItem * ,QListWidgetItem *)), 
02025         //       this, SLOT(currentItemChanged(QListWidgetItem * ,QListWidgetItem *)));
02026 }
02027 
02028 void OmgMainWindow::currentItemChanged(QTreeWidgetItem * thepCurrentItem, QTreeWidgetItem * thepPreviousItem)
02029 {
02030   if (!mpCurrentExperiment)
02031   {
02032     return;
02033   }
02034   //is this the top level experiement node? if yes then show an experiment wide report
02035   if (thepCurrentItem->text(0) == tr("Experiment"))
02036   {
02037     listThumbnails->hide();
02038     tbReport->show();
02039     QString myUrl = mpCurrentExperiment->toSummaryHtml();
02040     //logMessage(myUrl);
02041     setReportStyleSheet();
02042           tbReport->setSource(QUrl::fromLocalFile( myUrl ));
02043     tabModelViewDetails->setCurrentIndex(0);
02044     return;
02045   }
02046   else if (thepCurrentItem->text(1) == "Algorithm")
02047   {
02048     qDebug("Algorithm node clicked");
02049     qDebug(thepCurrentItem->text(0));
02050     tabModelViewDetails->setCurrentIndex(0);
02051     showAlgorithmSummary(thepCurrentItem->text(0));
02052     return;
02053   }
02054   else if (thepCurrentItem->text(1) == "Taxon")
02055   {
02056     qDebug("Taxon node clicked");
02057     qDebug(thepCurrentItem->text(0));
02058           //tbReport->setSource(QUrl(mpCurrentExperiment->toTaxonSummaryHtml(thepCurrentItem->text(0))));
02059     tabModelViewDetails->setCurrentIndex(0);
02060     showTaxonSummary(thepCurrentItem->text(0));
02061     return;
02062   }
02063 
02064   listThumbnails->hide();
02065   tbReport->show();
02066   
02067   
02068   //This is a model node. So render its report
02069 
02070   OmgModel * mypModel =
02071     mpCurrentExperiment->getModel(thepCurrentItem->text(1));
02072 
02073   //qDebug(thepCurrentItem->text(1).toLocal8Bit());
02074   if (mypModel)
02075   {
02076     setCurrentModel(mypModel);
02077     return;
02078   }
02079 
02080 }
02081 void OmgMainWindow::treeContextMenuEvent(const QPoint & thePoint)
02082 {
02083   QTreeWidgetItem* mypItem = treeExperiment->itemAt(thePoint);
02084   currentItemChanged (mypItem,mypItem);
02085   //check if its a model item and if so 
02086   //we can let the user remove / rerun just that model
02087   //by providing a context menu
02088   if (mypItem->text(0) == tr("Experiment"))
02089   {
02090     qDebug("Experiment context");
02091     return;
02092   }
02093   else if (mypItem->text(1) == "Algorithm")
02094   {
02095     qDebug("Algorithm context");
02096     mpAlgorithmContextMenu->popup(treeExperiment->mapToGlobal(thePoint));
02097     return;
02098   }
02099   else if (mypItem->text(1) == "Taxon")
02100   {
02101     qDebug("Taxon context");
02102     mpTaxonContextMenu->popup(treeExperiment->mapToGlobal(thePoint));
02103     return;
02104   }
02105   else //model node
02106   {
02107     qDebug("Model context");
02108     mpModelContextMenu->popup(treeExperiment->mapToGlobal(thePoint));
02109     return;
02110   }
02111 }
02112 void OmgMainWindow::removeModelFromExperiment()
02113 {
02114   QString myGuid = mpCurrentModel->guid();
02115   mpCurrentExperiment->removeModel(myGuid);
02116   mpCurrentExperiment->save();
02117   mpCurrentExperiment->toSummaryHtml(true);
02118   populateTree();
02119 }
02120 void OmgMainWindow::removeAlgorithmFromExperiment()
02121 {
02122   QList<QTreeWidgetItem *> myList = treeExperiment->selectedItems();
02123   QTreeWidgetItem * mypItem = myList.at(0);
02124   if (mypItem->text(1) != "Algorithm")
02125   {
02126     return;
02127   }
02128   QString myAlgorithmName = mypItem->text(0);
02129   mpCurrentExperiment->removeAlgorithm(myAlgorithmName);
02130   mpCurrentExperiment->save();
02131   mpCurrentExperiment->toSummaryHtml(true);
02132   populateTree();
02133 }
02134 void OmgMainWindow::removeTaxonFromExperiment()
02135 {
02136   QList<QTreeWidgetItem *> myList = treeExperiment->selectedItems();
02137   QTreeWidgetItem * mypItem = myList.at(0);
02138   if (mypItem->text(1) != "Taxon")
02139   {
02140     return;
02141   }
02142   QString myTaxonName = mypItem->text(0);
02143   mpCurrentExperiment->removeTaxon(myTaxonName);
02144   mpCurrentExperiment->save();
02145   mpCurrentExperiment->toSummaryHtml(true);
02146   populateTree();
02147 
02148 }
02149 void OmgMainWindow::reportModeChanged(QString theReportMode)
02150 {
02151   //qDebug("Report mode changed to : "+theReportMode.toLocal8Bit());
02152   showReport(theReportMode);
02153 }
02154 
02155 void OmgMainWindow::setTreeColumnSizes(int position,int index)
02156 {
02157   QString myWidth = QString::number(treeExperiment->width());
02158   //qDebug("setTreeColumnSizes function called when tree width = "+myWidth.toLocal8Bit());
02159   treeExperiment->header()->resizeSection(0,treeExperiment->width());
02160   treeExperiment->header()->resizeSection(1,0);  
02161 }
02162 
02163 void OmgMainWindow::resizeEvent ( QResizeEvent * theEvent )
02164 {
02165   setTreeColumnSizes(0,0);
02166 }
02167 
02168 void OmgMainWindow::showReport(QString theReportMode)
02169 {
02170   //qDebug("The report mode = "+theReportMode.toLocal8Bit());
02171   if (theReportMode==QString("HTML"))
02172   {
02173     tbReport->clear();
02174     setReportStyleSheet();
02175           tbReport->setSource(QUrl::fromLocalFile(mpCurrentModel->toHtml()));
02176   }
02177   else if(theReportMode=="Text")
02178   {
02179     tbReport->clear();
02180     tbReport->insertPlainText(mpCurrentModel->toString());
02181   }
02182   else if(theReportMode=="XML")
02183   {
02184     tbReport->clear();
02185     //qDebug ("Getting xml report for " + mpCurrentModel->taxonName().toLocal8Bit());
02186     tbReport->insertPlainText(mpCurrentModel->toXml());
02187     // next two lines for testing only
02188     OmgAlgorithm myAlgorithm=mpCurrentModel->algorithm();
02189     //qDebug(myAlgorithm.toString().toLocal8Bit());
02190   }
02191   else
02192   {
02193     //qDebug("Invalid report mode");
02194   }
02195 }
02196 
02197 void OmgMainWindow::setEnableModelDetailWidgets(bool theBool)
02198 {
02199     //qDebug("Enable/Disable model detail widgets");
02200     //Enable/Disable widgets that display model details
02201     treeExperiment->setEnabled(theBool);
02202     tabModelViewDetails->setEnabled(theBool);
02203     cboSortBy->setEnabled(theBool);
02204 
02205     if(theBool)
02206     {
02207        treeExperiment->showColumn(1);
02208        setTreeColumnSizes(0,0);
02209     }
02210     else
02211     {
02212        treeExperiment->hideColumn(1);
02213     }
02214 }
02215 
02216 void OmgMainWindow::clearCurrentExperiment()
02217 {
02218   
02219  //qDebug("Clear experiment widgets");
02220  //Empty widgets
02221  treeExperiment->clear();
02222  lblOutputMap->clear();
02223  tbReport->clear();
02224  
02225  //Turn off all the model details widgets
02226  setEnableModelDetailWidgets(false);
02227 
02228 }
02229 
02230 void OmgMainWindow::showLayerSetManager()
02231 {
02232  OmgLayerSetManager myManager;
02233  myManager.show();
02234  myManager.exec();
02235       
02236 }
02237 
02238 
02239 void OmgMainWindow::showAlgorithmManager()
02240 {
02241  //OmgAlgorithmManager myManager(this,Qt::Tool);
02242  OmgAlgorithmManager myManager(this,Qt::Dialog);
02243  myManager.exec();
02244       
02245 }
02246 
02247 
02248 void OmgMainWindow::setViewMode(QString theMode)
02249 {
02250 //Set the mode of the main window by hiding/showing relevent widgets
02251   if(theMode=="Browse")
02252   { 
02253     //qDebug("Setting view to browse mode");
02254     setEnableModelDetailWidgets(true);
02255     //frameBrowseExperimentWidgets->show();
02256     //frameProgressDetails->hide();
02257   }
02258   else if (theMode=="Process")
02259   {
02260     //qDebug("Setting view to process mode");
02261     setEnableModelDetailWidgets(true);
02262     //frameBrowseExperimentWidgets->hide();
02263     //frameProgressDetails->show();
02264   }
02265   else
02266   {
02267     //qDebug("Error setting view mode -unknown type");
02268   }
02269 
02270 }
02271 
02272 void OmgMainWindow::printAlgorithmProfilesReport()
02273 {
02274   QTextDocument myTextDocument;
02275   QString myReport;
02276   myReport += "<center><h1>openModeller Algorithm Profiles</h1>";
02277   myReport += "<hr/>";
02278   OmgAlgorithmSet myAlgorithmSet = OmgAlgorithmSet::getFromActivePlugin();
02279   myAlgorithmSet.loadAlgorithms(Omgui::userAlgorithmProfilesDirPath());
02280   myReport += myAlgorithmSet.toHtml();
02281   myTextDocument.setHtml(myReport);
02282   statusBar()->showMessage(tr("Printing Algorithm Profiles Report..."));
02283   myTextDocument.setHtml(myReport);
02284   QPrinter myPrinter;
02285   //pdf (not used)
02286   //myPrinter.setOutputFormat(QPrinter::PdfFormat);
02287   //myPrinter.setOutputFileName(myOutputFileName);
02288   
02289   //print device
02290   myPrinter.setOutputFormat(QPrinter::NativeFormat);
02291   myPrinter.setDocName("openModellerDesktopExperimentReport");
02292   myTextDocument.print(&myPrinter);
02293 }
02294 
02295 void OmgMainWindow::printExperimentReport()
02296 {
02297   if (!mpCurrentExperiment)
02298   {
02299     return;
02300   }
02301   QTextDocument myTextDocument;
02302   QString myReport;
02303   myReport += "<center><h1>openModeller Experiment Report</h1>";
02304   myReport += "<hr/>";
02305   myReport += Omgui::readTextFile(mpCurrentExperiment->toSummaryHtml());
02306   int myCount = mpCurrentExperiment->count();
02307   for (int i=0; i<myCount; i++)
02308   {
02309     OmgModel *  mypModel=mpCurrentExperiment->getModel(i);
02310     if (mypModel==NULL)
02311     {
02312       emit logMessage("Model is null is NULL, skipping");
02313       continue;
02314     }
02315     myReport += Omgui::readTextFile(mypModel->toHtml());  
02316   }
02317   myTextDocument.setHtml(myReport);
02318   QPrinter myPrinter;
02319   //pdf (not used)
02320   //myPrinter.setOutputFormat(QPrinter::PdfFormat);
02321   //myPrinter.setOutputFileName(myOutputFileName);
02322   
02323   //print device
02324   myPrinter.setOutputFormat(QPrinter::NativeFormat);
02325   myPrinter.setDocName("openModellerDesktopExperimentReport");
02326   myTextDocument.print(&myPrinter);
02327 }
02328 
02329 void OmgMainWindow::printPdf()
02330 {
02331   QSettings myQSettings;  // where we keep last used filter in persistant state
02332   QString myLastUsedDir = myQSettings.value("openModeller/lastSaveAsPdfDir",".").toString();
02333 
02334   //create a file dialog 
02335   std::auto_ptr < QFileDialog > myFileDialog
02336   (
02337     new QFileDialog(
02338       this,
02339       QFileDialog::tr("Save experiment report to portable document format (.pdf)"),
02340       myLastUsedDir,
02341       tr("Portable Document Format (*.pdf)")
02342       )
02343   );
02344   myFileDialog->setFileMode(QFileDialog::AnyFile);
02345   myFileDialog->setAcceptMode(QFileDialog::AcceptSave);
02346 
02347   //prompt the user for a filename
02348   QString myOutputFileName; 
02349   if (myFileDialog->exec() == QDialog::Accepted)
02350   {
02351     QStringList myFiles = myFileDialog->selectedFiles();
02352     if (!myFiles.isEmpty())
02353     {
02354       myOutputFileName = myFiles[0];
02355     }
02356   }
02357 
02358   if (!myOutputFileName.isEmpty())
02359   {
02360     if (myFileDialog->selectedFilter()==tr("Portable Document Format (*.pdf)"))
02361     {
02362       //ensure the user never ommitted the extension from the filename
02363       if (!myOutputFileName.toUpper().endsWith(".PDF")) 
02364       {
02365         myOutputFileName+=".pdf";
02366       }
02367 
02368       QPrinter myPrinter;
02369       myPrinter.setPageSize(QPrinter::A4);
02370       myPrinter.setOutputFormat(QPrinter::PdfFormat);
02371       myPrinter.setOutputFileName(myOutputFileName);
02372       myPrinter.setDocName("openModellerDesktopExperimentReport");
02373       // set the experiment printer up
02374       if (!mpExperimentPrinter)
02375       {
02376         mpExperimentPrinter = new OmgExperimentPrinter();
02377       }
02378       mProgressDialog.setValue(0);
02379       mProgressDialog.setLabelText(tr("Please wait while your report is generated"));
02380       mProgressDialog.show();
02381       mProgressDialog.setWindowModality(Qt::WindowModal);
02382       mProgressDialog.setAutoClose(true);
02383       connect(mpExperimentPrinter, SIGNAL(progress(int)), &mProgressDialog, SLOT(setValue(int)));
02384       connect(mpExperimentPrinter, SIGNAL(maximum(int)), &mProgressDialog, SLOT(setMaximum(int)));
02385       mpExperimentPrinter->setExperiment(mpCurrentExperiment);
02386       mpExperimentPrinter->setPrinter(myPrinter);
02387       //crashes when I use it in thread mode..
02388       //mpExperimentPrinter->start();
02389       mpExperimentPrinter->run();
02390       //new to qt4.3 - bounce dock icon or flash menu bar entry
02391       //only does anything if this window is not focussed
02392       QApplication::alert(this);
02393     }
02394     else
02395     {
02396       QMessageBox::warning( this,tr("openModeller Desktop"),tr("Unknown delimited format: ") +
02397              myFileDialog->selectedFilter());
02398 
02399     }
02400     myQSettings.setValue("openModeller/lastSaveAsPdfDir", myFileDialog->directory().absolutePath());
02401   }
02402 }
02403 
02404 void OmgMainWindow::on_tabModelViewDetails_currentChanged(int theIndex)
02405 {
02406 #ifdef WITH_QGIS
02407   //disable gis tools based on context
02408   if (theIndex==0)
02409   {
02410     disableMapControls();
02411   }
02412   else
02413   {
02414     enableMapControls();
02415   }
02416 #endif
02417 }
02418 void OmgMainWindow::disableControlsWhileRunning()
02419 {
02420   mpSaveAsImageAct->setEnabled(false);
02421   mpNewAct->setEnabled(false);
02422   mpResetAct->setEnabled(false);
02423   mpOpenAct->setEnabled(false);
02424   mpCloseAct->setEnabled(false);
02425   mpSaveAct->setEnabled(false);
02426   mpPrintPdfAct->setEnabled(false);
02427   mpRefreshReportsAct->setEnabled(false);
02428   mpLayerSetManagerAct->setEnabled(false);
02429   mpAlgorithmManagerAct->setEnabled(false);
02430   mpOptionsAct->setEnabled(false);
02431   mpToolsConvertAct->setEnabled(false);
02432   mpToolsClimateConvertAct->setEnabled(false);
02433   mpAvailableAlgorithmsReportAct->setEnabled(false);
02434   mpExperimentReportAct->setEnabled(false);
02435   mpToolsRasterThresholdAct->setEnabled(false);
02436 #ifndef OMG_NO_EXPERIMENTAL
02437   mpToolsContourAct->setEnabled(false);
02438 #endif
02439 }
02440 void OmgMainWindow::enableControlsAfterRunning()
02441 {
02442   mpSaveAsImageAct->setEnabled(true);
02443   mpNewAct->setEnabled(true);
02444   mpResetAct->setEnabled(true);
02445   mpOpenAct->setEnabled(true);
02446   mpCloseAct->setEnabled(true);
02447   mpSaveAct->setEnabled(true);
02448   mpPrintPdfAct->setEnabled(true);
02449   mpRefreshReportsAct->setEnabled(true);
02450   mpLayerSetManagerAct->setEnabled(true);
02451   mpAlgorithmManagerAct->setEnabled(true);
02452   mpOptionsAct->setEnabled(true);
02453   mpToolsConvertAct->setEnabled(true);
02454   mpToolsClimateConvertAct->setEnabled(true);
02455   mpAvailableAlgorithmsReportAct->setEnabled(true);
02456   mpExperimentReportAct->setEnabled(true);
02457   mpToolsRasterThresholdAct->setEnabled(true);
02458 #ifndef OMG_NO_EXPERIMENTAL
02459   mpToolsContourAct->setEnabled(true);
02460 #endif
02461 }
02462 void OmgMainWindow::disableMapControls()
02463 {
02464 #ifdef WITH_QGIS
02465   mpSaveAsImageAct->setEnabled(false);
02466   mpZoomInAct->setEnabled(false);
02467   mpZoomOutAct->setEnabled(false);
02468   mpPanAct->setEnabled(false);
02469   mpZoomFullAct->setEnabled(false);
02470   mpZoomPreviousAct->setEnabled(false);
02471 #endif
02472 }
02473 void OmgMainWindow::enableMapControls()
02474 {
02475 #ifdef WITH_QGIS
02476   
02477   if (QFile::exists(mpCurrentModel->workDir() + mpCurrentModel->rawImageFileName()) && 
02478       tabModelViewDetails->currentIndex()==2 )
02479   {
02480     mpSaveAsImageAct->setEnabled(true);
02481     mpZoomInAct->setEnabled(true);
02482     mpZoomOutAct->setEnabled(true);
02483     mpPanAct->setEnabled(true);
02484     mpZoomFullAct->setEnabled(true);
02485     mpZoomPreviousAct->setEnabled(true);
02486   }
02487   else
02488   {
02489     disableMapControls();
02490   }
02491 #endif
02492 }
02493 
02494 
02495 #ifdef WITH_QGIS
02496 void OmgMainWindow::zoomInMode()
02497 {
02498   //qDebug("Setting map canvas to ZOOM IN MODE");
02499   mpMapCanvas->setMapTool(mpZoomInTool);
02500 }
02501 void OmgMainWindow::zoomOutMode()
02502 {
02503   //qDebug("Setting map canvas to ZOOM OUT MODE");
02504   mpMapCanvas->setMapTool(mpZoomOutTool);
02505 }
02506 void OmgMainWindow::panMode()
02507 {
02508   //qDebug("Setting map canvas to PAN mode");
02509   mpMapCanvas->setMapTool(mpPanTool);
02510 }
02511 void OmgMainWindow::zoomFull()
02512 {
02513   //qDebug("Setting map canvas to ZOOM FULL EXTENT");
02514   mpMapCanvas->zoomFullExtent();
02515 }
02516 
02517 void OmgMainWindow::zoomPrevious()
02518 {
02519   //qDebug("Setting map canvas to ZOOM FULL PREVIOUS");
02520   mpMapCanvas->zoomPreviousExtent();
02521 }
02522 /*
02523 void OmgMainWindow::identifyMode()
02524 {
02525   mpMapCanvas->setMapTool(mpIdentifyTool);
02526 }
02527 
02528 void OmgMainWindow::measureMode()
02529 {
02530   mpMapCanvas->setMapTool(mpMeasureTool);
02531 }
02532 
02533 void OmgMainWindow::measureAreaMode()
02534 {
02535   mpMapCanvas->setMapTool(mpMeasureAreaTool);
02536 }
02537 */
02538 void OmgMainWindow::addLayer()
02539 {
02540 }
02541 #endif
02542 
02543 #ifdef WITH_OSSIMPLANET_QT
02544 void OmgMainWindow::initialiseOssimPlanet()
02545 {
02546    QGLFormat myFormat;
02547    myFormat.setSwapInterval(1);
02548    mpPlanet = new ossimPlanetQtGlWidget(myFormat, planetWidget);
02549 }
02550 #endif
02551 
02552 void OmgMainWindow::createTrayIcon()
02553 {
02554   QSettings mySettings;
02555   bool myUseSytemTrayFlag = mySettings.value("openModeller/useSystemTray", false).toBool();
02556   if ( QSystemTrayIcon::isSystemTrayAvailable() )
02557   {
02558     mTrayIconMenu = new QMenu(this);
02559     mTrayIconMenu->addAction(mMinimizeAct);
02560     mTrayIconMenu->addAction(mMaximizeAct);
02561     mTrayIconMenu->addAction(mRestoreAct);
02562     mTrayIconMenu->addAction(mpRunAct);
02563     mTrayIconMenu->addSeparator();
02564     mTrayIconMenu->addAction(mQuitAct);
02565 
02566     mTrayIcon = new QSystemTrayIcon(QIcon(":/om_logo.png"),this);
02567     mTrayIcon->setContextMenu(mTrayIconMenu);
02568     // only make the tray icon visible if the user wants it
02569     // user can change at run time so we need to do above
02570     // steps regardless
02571     if (myUseSytemTrayFlag)
02572     {
02573       mTrayIcon->show();
02574       bool myShowSystemTrayMessagesFlag = mySettings.value("openModeller/showSystemTrayMessages", false).toBool();
02575       if (QSystemTrayIcon::supportsMessages() && myShowSystemTrayMessagesFlag)
02576       {
02577         mTrayIcon->showMessage("openModeller Desktop",
02578             Omgui::version(),QSystemTrayIcon::Information,1000);
02579       }
02580     }
02581   }
02582   else
02583   {
02584     logMessage(tr("No system tray available on this platform, tray icon disabled"));
02585   }
02586 }
02587 
02588 void OmgMainWindow::setModelCreationProgress (QString theModelGuid, int theProgress)
02589 {
02590   QSettings mySettings;
02591   bool myUseSytemTrayFlag = mySettings.value("openModeller/useSystemTray", false).toBool();
02592   QTreeWidgetItem * mypTreeItem = mTreeItemsHash[theModelGuid];
02593   mpModelProgress->setValue(theProgress);
02594   if (theProgress==0)
02595   {
02596     mypTreeItem->setIcon(0,mRunningIcon);
02597     if (QSystemTrayIcon::isSystemTrayAvailable() && myUseSytemTrayFlag)
02598     {
02599       mTrayIcon->setIcon(mRunningIcon);
02600     }
02601     //only need to do this when creation of model starts
02602     //set custom colours for the progress bar
02603     QPalette myPalette = mpModelProgress->palette();
02604     // Set the bar red
02605     myPalette.setColor(QPalette::Highlight, QColor("red"));
02606     // Set the percentage text yellow
02607     myPalette.setColor(QPalette::WindowText, QColor("yellow"));
02608     // Set the background green
02609     //myPalette.setColor(QPalette::Window, QColor("green"));
02610     mpModelProgress->setPalette(myPalette);
02611     statusBar()->showMessage(mpCurrentExperiment->currentStatus());
02612   }
02613   else
02614   {
02615     mypTreeItem->setIcon(0,mRunningIcon);
02616     if (QSystemTrayIcon::isSystemTrayAvailable() && myUseSytemTrayFlag)
02617     {
02618       mTrayIcon->setIcon(mRunningIcon);
02619     }
02620     statusBar()->showMessage(mpCurrentExperiment->currentStatus());
02621   }
02622 }
02623 
02624 void OmgMainWindow::setModelProjectionProgress (QString theModelGuid, int theProgress)
02625 {
02626   if (!mpCurrentExperiment)
02627   {
02628     return;
02629   }
02630   QSettings mySettings;
02631   bool myUseSytemTrayFlag = 
02632     mySettings.value("openModeller/useSystemTray", false).toBool();
02633   //bool myShowSystemTrayMessagesFlag = 
02634   //  mySettings.value("openModeller/showSystemTrayMessages", false).toBool();
02635   QTreeWidgetItem * mypTreeItem = mTreeItemsHash[theModelGuid];
02636   mpModelProgress->setValue(theProgress);
02637   if (theProgress >= 100)
02638   {
02639     //show user we are starting postprocessing now
02640   }
02641   else if (theProgress == 0)
02642   {
02643     mypTreeItem->setIcon(0,mRunningIcon);
02644     QSettings mySettings;
02645     if (QSystemTrayIcon::isSystemTrayAvailable() && myUseSytemTrayFlag)
02646     {
02647       mTrayIcon->setIcon(mRunningIcon);
02648     }
02649     QPalette myPalette = mpModelProgress->palette();
02650     // Set the bar red
02651     myPalette.setColor(QPalette::Highlight, QColor("green"));
02652     // Set the percentage text yellow
02653     myPalette.setColor(QPalette::WindowText, QColor("yellow"));
02654     // Set the background green
02655     //myPalette.setColor(QPalette::Window, QColor("green"));
02656     mpModelProgress->setPalette(myPalette);
02657     statusBar()->showMessage(mpCurrentExperiment->currentStatus());
02658   }
02659   else //progress is somewhere between 0 and 100
02660   {
02661     mypTreeItem->setIcon(0,mRunningIcon);
02662     if (QSystemTrayIcon::isSystemTrayAvailable() && myUseSytemTrayFlag)
02663     {
02664       mTrayIcon->setIcon(mRunningIcon);
02665       statusBar()->showMessage(mpCurrentExperiment->currentStatus());
02666     }
02667   }
02668 }
02669 
02670 //slot called after each model completes all processing
02671 //(including post processing)
02672 void OmgMainWindow::modelCompleted(QString theModelGuid)
02673 {
02674   if (!mpCurrentExperiment)
02675   {
02676     return;
02677   }
02678   //
02679   // First update the report for the current node in the experiment tree
02680   //
02681   QTreeWidgetItem * mypItem = treeExperiment->currentItem();
02682   if (mypItem)
02683   {
02684     if (theModelGuid==mypItem->text(1))
02685     {
02686       OmgModel * mypModel =
02687         mpCurrentExperiment->getModel(mypItem->text(1));
02688 
02689       //qDebug(thepCurrentItem->text(1).toLocal8Bit());
02690       if (mypModel)
02691       {
02692         setCurrentModel(mypModel);
02693       }
02694     }
02695     //
02696     // Note that the following three if clauses duplicate
02697     // logic from currentItemChanged() but I didnt 
02698     // want to call currentItemChanged directly since it
02699     // will have the side effect of refreshing the focussed
02700     // model report if it is not the one which just completed
02701     // (i.e. the logic above is different in this case for model
02702     // nodes)
02703     // There are also some different behaviours e.g.
02704     // list controls dont force focus is another tab is 
02705     // active
02706     else if (mypItem->text(0) == tr("Experiment"))
02707     {
02708       listThumbnails->hide();
02709       tbReport->show();
02710       QString myUrl = mpCurrentExperiment->toSummaryHtml();
02711       setReportStyleSheet();
02712       tbReport->setSource(QUrl::fromLocalFile( myUrl ));
02713       tabModelViewDetails->setCurrentIndex(0);
02714       logMessage("Experiment report updated as a model just completed");
02715       logMessage(myUrl);
02716     }
02717     else if (mypItem->text(1) == "Algorithm")
02718     {
02719       showAlgorithmSummary(mypItem->text(0));
02720     }
02721     else if (mypItem->text(1) == "Taxon")
02722     {
02723       showTaxonSummary(mypItem->text(0));
02724     }
02725   }
02726   //
02727   // Now show task bar notifications if the user has enabled them
02728   //
02729   QSettings mySettings;
02730   bool myUseSytemTrayFlag = 
02731     mySettings.value("openModeller/useSystemTray", false).toBool();
02732   bool myShowSystemTrayMessagesFlag = 
02733     mySettings.value("openModeller/showSystemTrayMessages", false).toBool();
02734   QTreeWidgetItem * mypTreeItem = mTreeItemsHash[theModelGuid];
02735   QIcon myIcon;
02736   myIcon.addFile(":/status_complete.png");
02737   mypTreeItem->setIcon(0,myIcon);
02738 
02739   if (QSystemTrayIcon::isSystemTrayAvailable() && myUseSytemTrayFlag)
02740   {
02741     mTrayIcon->setIcon(myIcon);
02742     if (QSystemTrayIcon::supportsMessages() && myShowSystemTrayMessagesFlag)
02743     {
02744       QString myAlgorithmName = 
02745         mpCurrentExperiment->getModel(theModelGuid)->algorithm().name();
02746       mTrayIcon->showMessage("openModeller Desktop",myAlgorithmName + "\n" 
02747           +mypTreeItem->text(0) + 
02748           tr(" model and projection completed."),QSystemTrayIcon::Information, 1000);
02749     }
02750   }
02751 }
02752 
02753 void OmgMainWindow::setExperimentProgress (int theProgress)
02754 {
02755   mpExperimentProgressLabel->setText(tr("Experiment Progress (")
02756       + QString::number(theProgress) 
02757       + "/"
02758       + QString::number(mpExperimentProgress->maximum()) +")");
02759   mpExperimentProgress->setValue(theProgress);
02760 }
02761 
02762 void OmgMainWindow::setExperimentMaximum(int theMaximum)
02763 {
02764   mpExperimentProgressLabel->setText(tr("Experiment Progress (") 
02765       +"0/" 
02766       + QString::number(theMaximum) +")");
02767   mpExperimentProgress->setMaximum(theMaximum);
02768   mpExperimentProgress->setValue(0);
02769 }
02770 void OmgMainWindow::logMessage(QString theMessage)
02771 {
02772   tbLog->append(theMessage);
02773   tbLog->ensureCursorVisible();
02774   //
02775   // log to file too if needed
02776   //
02777   QSettings mySettings;
02778   bool myLogToFileFlag = mySettings.value("openModeller/logToFile", false).toBool();
02779   if (myLogToFileFlag)
02780   {
02781     QString myFileName = mySettings.value("openModeller/logFile","/tmp/omglog.txt").toString();
02782     QFile myFile( myFileName );
02783     if ( myFile.open( QIODevice::Append ) )
02784     {
02785       QTextStream myQTextStream( &myFile );
02786       myQTextStream << theMessage << "\n";
02787       myFile.close();
02788     }
02789   }
02790 }
02791 void OmgMainWindow::logMessage(QString theModelGuid, QString theMessage)
02792 {
02793   //logMessage("For " + theModelGuid);
02794   logMessage(theMessage);
02795 }
02796 void OmgMainWindow::logError(QString theModelGuid, QString theMessage)
02797 {
02798   //since we want to insert html and there is no append option
02799   //for html, we need to manually make sure we are at the end of the file
02800   tbLog->textCursor().movePosition(QTextCursor::End);
02801   tbLog->insertHtml("<br/><font color=\"red\">" + theMessage + "</font><font color=\"black\"> * </font><br/>");
02802   tbLog->ensureCursorVisible();
02803 
02804   //
02805   // log to file too if needed
02806   //
02807   QSettings mySettings;
02808   bool myLogToFileFlag = mySettings.value("openModeller/logToFile", false).toBool();
02809   if (myLogToFileFlag)
02810   {
02811     QString myFileName = mySettings.value("openModeller/logFile","/tmp/omglog.txt").toString();
02812     QFile myFile( myFileName );
02813     if ( myFile.open( QIODevice::Append) )
02814     {
02815       QTextStream myQTextStream( &myFile );
02816       //myQTextStream << theModelGuid << "\n";
02817       myQTextStream << theMessage;
02818       myFile.close();
02819     }
02820   }
02821 
02822   //
02823   // Update teh icon of the model entry in the 
02824   // experiment tree 
02825   //
02826   mpModelProgress->setValue(100);
02827   QTreeWidgetItem * mypTreeItem = mTreeItemsHash[theModelGuid];
02828   QIcon myIcon;
02829   myIcon.addFile(":/status_aborted.png");
02830   mypTreeItem->setIcon(0,myIcon);
02831   treeExperiment->setItemWidget(mypTreeItem,0,NULL);
02832 
02833   //
02834   // Show systray icon
02835   //
02836   bool myUseSytemTrayFlag = 
02837     mySettings.value("openModeller/useSystemTray", false).toBool();
02838   bool myShowSystemTrayMessagesFlag = 
02839     mySettings.value("openModeller/showSystemTrayMessages", false).toBool();
02840   if (QSystemTrayIcon::isSystemTrayAvailable() && myUseSytemTrayFlag)
02841   {
02842     mTrayIcon->setIcon(myIcon);
02843     if (QSystemTrayIcon::supportsMessages() && myShowSystemTrayMessagesFlag)
02844     {
02845       QString myAlgorithmName = 
02846         mpCurrentExperiment->getModel(theModelGuid)->algorithm().name();
02847       mTrayIcon->showMessage("openModeller Desktop",myAlgorithmName + "\n" 
02848           +mypTreeItem->text(0) + 
02849           tr(" model and projection failed!"),QSystemTrayIcon::Warning, 1000);
02850     }
02851   }
02852 }
02853 
02854 void OmgMainWindow::stopExperiment()
02855 {
02856   if (!mpCurrentExperiment)
02857   {
02858     return;
02859   }
02860   mpCurrentExperiment->abort();
02861   //now we need to wait for the stopped signal to be sure the
02862   //experiment is really stopped (see next method below)
02863 }
02864 void OmgMainWindow::experimentStopped()
02865 {
02866   mpModelProgress->hide();
02867   mpExperimentProgress->hide();
02868   statusBar()->showMessage(tr("Experiment processing completed!"));
02869   //reconfigure the run tool
02870   mpRunAct->setIcon(QIcon(":/status_restart.png"));
02871   mpRunAct->setText(tr("&Run / Resume current experiment"));
02872   mpRunAct->setShortcut(tr("Ctrl+R"));
02873   mpRunAct->setStatusTip(tr("Run / Resume current experiment"));
02874   disconnect(mpRunAct);
02875   connect(mpRunAct, SIGNAL(triggered()), this, SLOT(runExperiment()));
02876   mpRunningMovie->stop();
02877   enableControlsAfterRunning();
02878   //new to qt4.3 - bounce dock icon or flash menu bar entry
02879   //only does anything if this window is not focussed
02880   QApplication::alert(this);
02881   //update teh systray icon
02882   QSettings mySettings;
02883   bool myUseSytemTrayFlag = mySettings.value("openModeller/useSystemTray", false).toBool();
02884   if (QSystemTrayIcon::isSystemTrayAvailable() && myUseSytemTrayFlag)
02885   {
02886     mTrayIcon->setIcon(QIcon(":/om_logo.png"));
02887     bool myShowSystemTrayMessagesFlag = 
02888       mySettings.value("openModeller/showSystemTrayMessages", false).toBool();
02889     if (QSystemTrayIcon::supportsMessages() && myShowSystemTrayMessagesFlag)
02890     {
02891       mTrayIcon->showMessage("openModeller Desktop",
02892           tr("Experiment completed"),QSystemTrayIcon::Information,1000);
02893     }
02894   }
02895 }
02896 void OmgMainWindow::updateRunningIcon(const QRect & theRect )
02897 {
02898   //logMessage("Updating running icon...");
02899   mRunningIcon = QIcon(mpRunningMovie->currentPixmap());
02900 }
02901 
02902 
02903 void OmgMainWindow::refreshReports()
02904 {
02905   if (!mpCurrentExperiment) return;
02906   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
02907   mpCurrentExperiment->toSummaryHtml(true);
02908   int myCount = mpCurrentExperiment->count();
02909   for (int i=0; i<myCount; i++)
02910   {
02911     OmgModel * mypModel=mpCurrentExperiment->getModel(i);
02912     mypModel->toHtml(true);
02913     mypModel->createThumbnail();
02914   }
02915   QApplication::restoreOverrideCursor();
02916 }
02917 
02918 void OmgMainWindow::setReportStyleSheet()
02919 {
02920   QString myStyle = Omgui::defaultStyleSheet(); 
02921   tbReport->document()->setDefaultStyleSheet(myStyle);
02922 }
02923 
02924 QString OmgMainWindow::helpText()
02925 {
02926   //
02927   // Show some help info in the textbrowser until the user loads an 
02928   // experiment.
02929   //
02930   QString myString;
02931   myString += "<h1><center>";
02932   myString += ("openModeller Desktop - Documentation");
02933   myString += "</center></h1>";
02934   myString += "<p>";  
02935   myString += tr("This is the help documentation for"
02936       " openModeller Desktop. You can return to this help"
02937       " document at any stage by using Help->Documentation"
02938       " from the menu. Please visit the openModeller home"
02939       " page at http://openmodeller.sf.net for additional"
02940       " information about openModeller.");
02941   myString += "</p>";  
02942   myString += "<br/>";  
02943   myString += "<table>";
02944   // input file format help 
02945   myString += "<tr>";
02946   myString += "<td rowspan=\"2\">";
02947   myString +="<img src=\":/localities_file.png\">\n";
02948   myString += "</td>";
02949   myString += "<td>";
02950   myString += "<h2>";
02951   myString += tr("Important notes about the occurrences file format");
02952   myString += "</h2>";
02953   myString += "</td>";
02954   myString += "</tr>";
02955   myString += "<tr>";
02956   myString += "<td>";
02957   myString +=tr("As of openModellerDesktop version 1.0.6 your occurrence "
02958                 "files need to be in the following format:" 
02959                 );
02960   myString += "<p><pre>";
02961   myString +=tr("#ID-tab-Taxon Name-tab-Longitude-tab-Latitude-tab-Abundance (optional)");
02962   myString += "</p></pre>";
02963   myString += "<ul>";
02964   myString += "<li>";
02965   myString +=tr("Lines starting with # are ignored."
02966                 );
02967   myString += "<li>";
02968   myString +=tr("The -tab-  markers above should be the inserted by pressing the tab key "
02969                 "on your keyboard." 
02970                 );
02971   myString += "<li>";
02972   myString +=tr("The Id can be a number, text or combination there-of."
02973                 );
02974   myString += "<li>";
02975   myString +=tr("The taxon name should be separated with spaces and may include "
02976                 "specific and subspecific epithet. Note that names should be identical "
02977                 "for the ths same taxon otherwise openModeller Desktop will treat "
02978                 "each name variation as a separate taxon."
02979              );
02980   myString += "<li>";
02981   myString +=tr("The abundance column is optional. An abundance of 0 is used "
02982                 "to indicate an absence record. Note that not all openModeller "
02983                 "algorithms support the use of absence data."
02984              );
02985   myString += "<li>";
02986   myString +=tr("You can automatically retrieve occurrence data using the "
02987                 "openModeller Desktop localities search tool (see below). "
02988                 "We recommend using the 'GBIF Rest' option for best results."
02989                 );
02990   myString += "</ul>";
02991   myString +=tr("Here is a worked example of a typical occurrences file:"
02992                 );
02993   myString += "<p><pre>";
02994   myString +=tr("#ID    Taxon Name  Longitude   Latitude    Abundance\n");
02995   myString += "23842684 Acacia cyclops  115.76  -31.98  1\n"
02996               "23842770 Acacia cyclops  120.867 -33.7166    1\n"
02997               "23842772 Acacia cyclops  121.33  -33.8   1\n"
02998               "23842910 Acacia cyclops  115.767 -32.115 0\n"
02999               "23843184 Acacia cyclops  115.733 -32.05  1\n";
03000   myString += "</p></pre>";
03001   myString += "</td>";
03002   myString += "</tr>";
03003   // localities search help 
03004   myString += "<tr>";
03005   myString += "<td rowspan=\"2\">";
03006   myString +="<img src=\":/filefetch.png\">\n";
03007   myString += "</td>";
03008   myString += "<td>";
03009   myString += "<h2>";
03010   myString += tr("Localities Search Tool");
03011   myString += "</h2>";
03012   myString += "</td>";
03013   myString += "</tr>";
03014   myString += "<tr>";
03015   myString += "<td>";
03016   myString +=tr("You can use the localities search tool to"
03017                 " automatically retrieve species occurrence data."
03018                 " The localities search tool is plugin based so"
03019                 " we provide search functionality against various"
03020                 " online resources such as GBIF and speciesLink."
03021                 " More data sources will be added over time."
03022                 " If you need a custom search plugin for your "
03023                 " institution please contact us (tim@linfiniti.com)"
03024                 " - we may be able to help"
03025                 );
03026   myString += "</td>";
03027   myString += "</tr>";
03028   // layerset manager help
03029   myString += "<tr>";
03030   myString += "<td rowspan=\"2\">";
03031   myString +="<img src=\":/layersetmanager.png\">\n";
03032   myString += "</td>";
03033   myString += "<td>";
03034   myString += "<h2>";
03035   myString += tr("Layer Set Manager");
03036   myString += "</h2>";
03037   myString += "</tr>";
03038   myString += "<tr>";
03039   myString += "</td>";
03040   myString += "<td>";
03041   myString +=tr("Use the layer set manager to define layer sets."
03042                 " Layer sets are named groups of layers. In openModeller"
03043                 " Desktop you use layer sets to specify the raster"
03044                 " layers that should be used for creating models and "
03045                 " for projecting models."
03046                 );
03047   myString += "</td>";
03048   myString += "</tr>";
03049   // algorithm manager
03050   myString += "<tr>";
03051   myString += "<td rowspan=\"2\">";
03052   myString +="<img src=\":/algorithmmanager.png\">\n";
03053   myString += "</td>";
03054   myString += "<td>";
03055   myString += "<h2>";
03056   myString +=tr("Algorithm Manager");
03057   myString += "</h2>";
03058   myString += "</tr>";
03059   myString += "<tr>";
03060   myString += "</td>";
03061   myString += "<td>";
03062   myString += tr("The authors of openModeller algorithms"
03063       " provide sensible defaults for each algorithm. With the"
03064       " algorithm manager you can cutomise these defaults to"
03065       " make the algorithm perform in a way more suited to your needs."
03066       " The default algorithm parameters are called 'System Profiles'."
03067       " You can clone any profile using the algorithm manager to create"
03068       " a 'User Profile', and then customise the user profile as you like."
03069       );
03070   myString += "</td>";
03071   myString += "</tr>";
03072   // experiment designer
03073   myString += "<tr>";
03074   myString += "<td rowspan=\"2\">";
03075   myString +="<img src=\":/filenewExperiment.png\">\n";
03076   myString += "</td>";
03077   myString += "<td>";
03078   myString += "<h2>";
03079   myString += tr("Experiment Designer");
03080   myString += "</h2>";
03081   myString += "</tr>";
03082   myString += "<tr>";
03083   myString += "</td>";
03084   myString += "<td>";
03085   myString +=tr("Once you have defined at least one layer set"
03086       " and have some occurrence data available, you can use"
03087       " the experiment designer to prepare an experiment. An"
03088       " experiment is a collection of models. Once the"
03089       " experiment has been created, it will be loaded"
03090       " in the experiment tree on the left of this window, and"
03091       " you will be asked if you wish to start running the experiment."
03092      );
03093   // threshold tool
03094   myString += "<tr>";
03095   myString += "<td rowspan=\"2\">";
03096   myString +="<img src=\":/threshold.png\">\n";
03097   myString += "</td>";
03098   myString += "<td>";
03099   myString += "<h2>";
03100   myString += tr("Threshold Tool");
03101   myString += "</h2>";
03102   myString += "</tr>";
03103   myString += "<tr>";
03104   myString += "</td>";
03105   myString += "<td>";
03106   myString +=tr("The threshold tool creates boolean model projection"
03107       " rasters from probability range rasters using a Minimum Cut-off "
03108       " Threshold Percentage. Using this tool you "
03109       " can:");
03110   myString += "<ul>";
03111   myString += "<li>";
03112   myString +=tr("Create a model projection map that shows only cells"
03113       " that were above a specific probabilty of occurrence.");
03114   myString += "</li>";
03115   myString += "<li>";
03116   myString +=tr("Create a 'hotspot' map showing predicted alpha"
03117       " biodiversity based on the number of thresholded probability"
03118       " layers for different taxa predicting presence in each cell."
03119       );
03120   myString += "</li>";
03121   myString += "<li>";
03122   myString +=tr("Create a 'concensus' model showing "
03123       " number of thresholded models predicting presence in each cell."
03124       );
03125   myString += "</li>";
03126   myString += "</ul>";
03127   myString += tr("To perform a threshold analysis, you can select any "
03128     "number of models from the experiment tree. Only succaessfully "
03129     "completed model projections are shown in the tree. A thumbnail "
03130     "preview of each model is drawn next to each entry in the tree. "
03131     "By sorting the tree by taxon or by algorithm, you can easily "
03132     "select a group of model projections.");
03133   myString += "\n";
03134   myString += tr("Selecting one or more taxa from the same algorithm "
03135     "group (sort by algorithm view) will effectively perform a "
03136     "'hotspot' analysis, where each cell in the output raster "
03137     "represents the number of taxa predicted presence in that cell "
03138     "based on the defined Minimum Cut-off Threshold Percentage.");
03139   myString += "\n";
03140   myString += tr("Selecting one or more algorithms for a given taxon "
03141       "(sort by taxon view) will allow you to create a 'concensus model'."
03142       "In a concensus model, the value of each cell in the output raster "
03143       "indicates the number of algorithms that predict presence for that "
03144       "cell - based on the Minimum Cut-off Threshold Percentage selected.");
03145   myString += "\n";
03146   myString += tr("Optionally you can write out each model projection "
03147       "as a boolean layer where 0 indicates absence and 1 indicates "
03148       "presence, based on the Minimum Cut-off Threshold Percentage selected.");
03149   myString += "</td>";
03150   myString += "</tr>";
03151   //nest the experiment help table in this cell
03152   myString += "</td>";
03153   myString += "</tr>";
03154   myString += experimentHelpText();
03155   /* template
03156   myString += "<tr>";
03157   myString += "<td rowspan=\"2\">";
03158   myString +="<img src=\":/.png\">\n";
03159   myString += "</td>";
03160   myString += "<td>";
03161   myString += "<h2>";
03162   myString += tr("");
03163   myString += "</h2>";
03164   myString += "</tr>";
03165   myString += "<tr>";
03166   myString += "</td>";
03167   myString += "<td>";
03168   myString +=tr(""
03169                 );
03170   myString += "</td>";
03171   myString += "</tr>";
03172   */
03173 
03174   
03175   myString += "<table>";
03176   return myString;
03177 }
03178 
03179 QString OmgMainWindow::experimentHelpText()
03180 {
03181   QString myString;
03182   // experiment progress help
03183   myString += "<tr>";
03184   myString += "<td>";
03185   myString += "</td>";
03186   myString += "<td>";
03187   myString +=tr("While the "
03188       " experiment is running you can browse the results "
03189       " of models as they are completed. Click on "
03190       " a taxon node (when sort by taxon is enabled) "
03191       " or an algorithm node (when sort by algorithm is "
03192       " enabled) for a thumbnail overview of completed "
03193       " model projections. Model nodes in the tree are "
03194       " marked with the following symbols according to "
03195       " the model status:");
03196   myString += "</td>";
03197   myString += "</tr>";
03198   // queued
03199   myString += "<tr>";
03200   myString += "<td rowspan=\"2\">";
03201   myString +="<img src=\":/status_queued.png\">\n";
03202   myString += "</td>";
03203   myString += "<td>";
03204   myString += "<h2>";
03205   myString += tr("Model queued for execution ...");
03206   myString += "</h2>";
03207   myString += "</td>";
03208   myString += "</tr>";
03209   myString += "<tr>";
03210   myString += "<td>";
03211   myString +=tr("When you see this icon next to a model node "
03212       " it means the model is queued, awaiting execution."
03213       );
03214   myString += "</td>";
03215   myString += "</tr>";
03216   // queued
03217   myString += "<tr>";
03218   myString += "<td rowspan=\"2\">";
03219   myString +="<img src=\":/status_running.png\">\n";
03220   myString += "</td>";
03221   myString += "<td>";
03222   myString += "<h2>";
03223   myString += tr("Model is running ...");
03224   myString += "</h2>";
03225   myString += "</td>";
03226   myString += "</tr>";
03227   myString += "<tr>";
03228   myString += "<td>";
03229   myString +=tr("When you see this icon next to a model node "
03230       " it means the model is busy running. "
03231       " The status bar help and the progress bars at the "
03232       " bottom of this windows will update you with the "
03233       " progress of the model. For more detailed information "
03234       " use the 'log' tab."
03235       );
03236   myString += "</td>";
03237   myString += "</tr>";
03238   // completed
03239   myString += "<tr>";
03240   myString += "<td rowspan=\"2\">";
03241   myString +="<img src=\":/status_complete.png\">\n";
03242   myString += "</td>";
03243   myString += "<td>";
03244   myString += "<h2>";
03245   myString += tr("Model is complete ...");
03246   myString += "</h2>";
03247   myString += "</td>";
03248   myString += "</tr>";
03249   myString += "<tr>";
03250   myString += "<td>";
03251   myString +=tr("When you see this icon next to a model node "
03252       " it means the model is finished running, "
03253       " and it has been projected. "
03254       " If you click on the model node you will be "
03255       " able to view a detailed report for the model."
03256       );
03257   myString += "</td>";
03258   myString += "</tr>";
03259   // aborted
03260   myString += "<tr>";
03261   myString += "<td rowspan=\"2\">";
03262   myString +="<img src=\":/status_aborted.png\">\n";
03263   myString += "</td>";
03264   myString += "<td>";
03265   myString += "<h2>";
03266   myString += tr("Model is aborted ...");
03267   myString += "</h2>";
03268   myString += "</td>";
03269   myString += "</tr>";
03270   myString += "<tr>";
03271   myString += "<td>";
03272   myString +=tr("When you see this icon next to a model node "
03273       " it means the model is finished running, "
03274       " but it had errors and did not complete successfully. "
03275       " You may be able to find more information as "
03276       " to the cause of the model failure by consulting "
03277       " the logs in the log tab."
03278       );
03279   myString += "</td>";
03280   myString += "</tr>";
03281 
03282   return myString;
03283 }
03284 
03285 void OmgMainWindow::showSurvey()
03286 {
03287   OmgSurveyWizard myWizard;
03288   myWizard.exec();
03289 }
03290 void OmgMainWindow::showHelp()
03291 {
03292   //ensure the tab is not disabled since we are 
03293   //showing some help info on first load
03294   tabModelViewDetails->setEnabled(true);
03295         tbReport->setSearchPaths(QStringList(":/"));
03296   setReportStyleSheet();
03297   QString myHelpText;
03298   QSettings mySettings;
03299   if (mySettings.value("tipOfTheDay/tipOfTheDay",true).toBool()==true)
03300   {
03301     OmgTipFactory myFactory;
03302     OmgTip myTip = myFactory.getTip();
03303     QString myTipString; 
03304     myTipString += "<h1><center>";
03305     myTipString += tr("Tip of the day: ") + myTip.title();
03306     myTipString += "</center></h1><br/>";
03307     myTipString +="<p><img src=\":/tip.png\" align=\"left\">\n";
03308     myTipString += myTip.content() + "</p>";
03309     myTipString += "<hr/>";
03310     myHelpText += myTipString;
03311   }
03312   myHelpText += helpText();
03313   tbReport->setHtml(myHelpText);  
03314 }

Generated on Mon Apr 28 15:07:31 2008 for openModellerDesktop by  doxygen 1.4.1-20050210