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

omglayerselector.cpp

Go to the documentation of this file.
00001 
00002 /***************************************************************************
00003  *   Copyright (C) 2003 by Tim Sutton                                      *
00004  *   tim@linfiniti.com                                                     *
00005  *                                                                         *
00006  *   Gyps - Species Distribution Modelling Toolkit                         *
00007  *   This toolkit provides data transformation and visualisation           *
00008  *   tools for use in species distribution modelling tools such as GARP,   *
00009  *   CSM, Bioclim etc.                                                     *
00010  *   This program is free software; you can redistribute it and/or modify  *
00011  *   it under the terms of the GNU General Public License as published by  *
00012  *   the Free Software Foundation; either version 2 of the License, or     *
00013  *   (at your option) any later version.                                   *
00014  ***************************************************************************/
00015 #include "omglayerselector.h"
00016 #include <omgmodellerplugininterface.h>
00017 #include <omgui.h>
00018 #include <omgmodellerpluginregistry.h>
00019 
00020 //qt includes
00021 #include <QAbstractItemView>
00022 #include <QCoreApplication>
00023 #include <QDir>
00024 #include <QFile>
00025 #include <QDomDocument>
00026 #include <QDomElement>
00027 #include <QFileDialog>
00028 #include <QFileInfo>
00029 #include <QHeaderView>
00030 #include <QLabel>
00031 #include <QListView>
00032 #include <QMessageBox>
00033 #include <QPixmap>
00034 #include <QResizeEvent>
00035 #include <QSettings>
00036 #include <QString>
00037 #include <QStringList>
00038 #include <QStyle>
00039 #include <QTreeWidget>
00040 //standard includes
00041 #include <iostream>
00042 
00043 
00044 
00045 
00046 OmgLayerSelector::OmgLayerSelector( QString theBaseDir, QWidget* parent, Qt::WFlags fl )
00047  : QDialog(parent,fl),
00048  mBaseDirName(theBaseDir)
00049 {
00050   setupUi(this);
00051   //show the user some useful help info so they know what is going on...
00052   showInfo();
00053   show();
00054   mFolderIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon),
00055                                      QIcon::Normal, QIcon::Off);
00056   mFolderIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirOpenIcon),
00057                                           QIcon::Normal, QIcon::On);
00058   mProjectionOkIcon.addPixmap(QPixmap(":/projectionOk.png"));
00059   mProjectionErrorIcon.addPixmap(QPixmap(":/projectionError.png"));
00060   
00061   treeFiles->setRootIsDecorated(true);
00062   QStringList myList;
00063   myList << "File Name";
00064   treeFiles->setColumnCount(1);
00065   treeFiles->setHeaderLabels(myList);
00066   treeFiles->setAlternatingRowColors ( true );
00067   treeFiles->header()->setResizeMode(0,QHeaderView::Stretch);
00068   //this hides the title row in the tree view
00069   //treeFiles->header()->setHidden(1);
00070 
00071   // When using a local plugin we can browse the filesystem
00072   // This is is a hard coded way to keep track of that
00073   // but I cant think of a neater way to do that at the moment
00074   QSettings mySettings;
00075   QString myModellerAdapterName = mySettings.value("openModeller/modellerPluginType", "Local Modeller Plugin" ).toString();
00076   bool myPluginIsLocalFlag=false;
00077   if (myModellerAdapterName =="Local Modeller Plugin")
00078   {
00079     toolDirectorySelector->setEnabled(true);
00080     lblBaseDir->setText(tr("Base Dir: ") + mBaseDirName);
00081     myPluginIsLocalFlag=true;
00082   }
00083   else
00084   {
00085     toolDirectorySelector->setEnabled(false);
00086     lblBaseDir->setText(myModellerAdapterName);
00087   }
00088   
00089   QFileInfo myFileInfo(mBaseDirName);
00090   if ( (myFileInfo.exists() && !mBaseDirName.isEmpty()) || (!myPluginIsLocalFlag) )
00091   {
00092     //std::cout << "Provided directory found - traversing subdirectories" << std::endl;
00093     treeFiles->clear();
00094     mpListParent = new QTreeWidgetItem(treeFiles);
00095     mpListParent->setText(0,myModellerAdapterName);
00096     buildTree(mBaseDirName,mpListParent);
00097     treeFiles->setItemExpanded(mpListParent,true);
00098   }
00099   else
00100   {
00101     //std::cout << "Provided directory does not exist - prompting for directory" << std::endl;
00102     mBaseDirName=QCoreApplication::applicationDirPath();
00103     on_toolDirectorySelector_clicked();
00104   }
00105   tbNotes->hide();
00106 }
00107 
00108 OmgLayerSelector::~OmgLayerSelector()
00109 {
00110 
00111 }
00112 
00113 void OmgLayerSelector::resizeEvent ( QResizeEvent * theEvent )
00114 {
00115   treeFiles->header()->resizeSection(0,(theEvent->size().width()));
00116 }
00117 void OmgLayerSelector::on_toolDirectorySelector_clicked()
00118 {
00119   toolDirectorySelector->setEnabled(false);
00120   //@NOTE: Why am I not using QFileDialog::getExistingDir static call?
00121   //under windows and Qt4.2 doing that was causing an assert deep in Qt
00122   //wheras using an object as below resolves the issue  
00123   QFileDialog myDialog(this);
00124   myDialog.setDirectory(mBaseDirName);
00125   myDialog.setFileMode(QFileDialog::DirectoryOnly);
00126   if (myDialog.exec())
00127   {
00128     mBaseDirName = myDialog.selectedFiles()[0];
00129   }
00130   lblBaseDir->setText(tr("Base Dir: ") + mBaseDirName);
00131   tbNotes->show();
00132   treeFiles->clear();
00133   mpListParent = new QTreeWidgetItem(treeFiles);
00134   mpListParent->setText(0,mBaseDirName);
00135   buildTree(mBaseDirName,mpListParent,true); //force rescan of the layers dir
00136   treeFiles->setItemExpanded(mpListParent,true);
00137   tbNotes->hide();
00138   toolDirectorySelector->setEnabled(true);
00139 }
00140 
00141 void OmgLayerSelector::on_toolRefresh_clicked()
00142 {
00143   tbNotes->show();
00144   treeFiles->clear();
00145   mpListParent = new QTreeWidgetItem(treeFiles);
00146   mpListParent->setText(0,mBaseDirName);
00147   buildTree(mBaseDirName,mpListParent,true); //force rescan of the layers dir
00148   treeFiles->setItemExpanded(mpListParent,true);
00149   tbNotes->hide();
00150 }
00151 
00152 void OmgLayerSelector::updateFileList()
00153 {
00154    mSelectedLayersList.clear();
00155    QListIterator<QTreeWidgetItem*> myIterator(treeFiles->selectedItems());
00156    while (myIterator.hasNext())
00157    {
00158      QString myId = myIterator.next()->data(0,Qt::UserRole).toString();
00159      if (!myId.isEmpty())
00160      {
00161        mSelectedLayersList << myId;
00162      }
00163    }
00164 }
00165 
00166 void OmgLayerSelector::accept()
00167 {
00168   qDebug("LayerSelector::accept() called");
00169   updateFileList();
00170   done(1);
00171 }
00172 
00173 
00174 void OmgLayerSelector::reject()
00175 {
00176   qDebug("LayerSelector::reject() called");
00177   mSelectedLayersList.clear();
00178   done(0);
00179 }
00180 
00181 QStringList OmgLayerSelector::getSelectedLayers() 
00182 {
00183    return mSelectedLayersList;
00184 }
00185 
00186 QString OmgLayerSelector::getBaseDir() 
00187 {
00188   return mBaseDirName;
00189 }
00190 
00191 void OmgLayerSelector::setSelectionMode(QAbstractItemView::SelectionMode theMode)
00192 {
00193    treeFiles->setSelectionMode(theMode); 
00194 }
00195 
00196 void OmgLayerSelector::buildTree(const QString& theDirName, 
00197     QTreeWidgetItem* theParentListViewItem, 
00198     bool theForceScanFlag)
00199 {
00200   if (theDirName.isEmpty()) return;
00201   if (!theParentListViewItem) return;
00202   //try to read the cache file first otherwise get the modeller plugin to give us
00203   //the file list xml
00204   QString myCachePath = Omgui::fileSelectorCachePath();
00205   QString myCacheFileName = myCachePath + QDir::separator() + "layerSelectorCache.xml";
00206   QString myDocumentText;
00207   //just read the cache file
00208   bool myResult = false;
00209   if (!theForceScanFlag)
00210   {
00211     QFile myFile( myCacheFileName );
00212     if ( myFile.open( QIODevice::ReadOnly ) )
00213     {
00214       myDocumentText = myFile.readAll();
00215       myFile.close();
00216       myResult=true;
00217     }
00218     else
00219     {
00220       qDebug("Failed to open "  + myCacheFileName.toLocal8Bit() + " layer selector cache file ");
00221       //@TODO Error handler!
00222       myResult=false;
00223     }
00224   }
00225   // if above failed we use the plugin to get the file list
00226   if (!myResult)
00227   {
00228     tbNotes->show();
00229     OmgModellerPluginInterface * mypModellerPlugin = OmgModellerPluginRegistry::instance()->getPlugin();
00230     //qDebug("Layer selector testing if returned modeller plugin is ok");
00231     if(!mypModellerPlugin)
00232     {
00233       //this is bad! TODO notify user he has no useable adapters
00234       //TODO handle this more gracefully than asserting!
00235       //qDebug("LayerSelector no valid modelling adapters could be loaded");
00236       QMessageBox::critical( this,tr("openModeller Desktop"),tr("No modelling plugins could be found.\nPlease report this problem to you system administrator or the openModeller developers."));
00237       //assert ("Undefined adapter type in __FILE__  , line  __LINE__");
00238       return;
00239     }
00240     else
00241     {
00242       //qDebug("Plugin is good to go....");
00243     }
00244 
00245     connect (mypModellerPlugin->getMessenger(), SIGNAL(refresh()),this,SLOT(refresh()));
00246     myDocumentText=mypModellerPlugin->getLayers(theDirName);
00247     tbNotes->hide();
00248   }
00249   //cache the file tree
00250   Omgui::createTextFile(myCachePath + QDir::separator() + "layerSelectorCache.xml", myDocumentText);
00251   QString myError;
00252   int myErrorLine;
00253   int myErrorColumn;
00254   QDomDocument myDocument;
00255   if (!myDocument.setContent(myDocumentText.toAscii(), true, &myError, &myErrorLine, &myErrorColumn)) 
00256   {
00257     QMessageBox::information(window(), tr("Available Layers"),
00258         tr("Parse error at line %1, column %2:\n%3")
00259         .arg(myErrorLine)
00260         .arg(myErrorColumn)
00261         .arg(myError));
00262     return;
00263   }
00264   QDomElement myRoot = myDocument.documentElement();
00265   QDomElement myChild = myRoot.firstChildElement("LayersGroup");
00266   //qDebug("LayerSelector: set root element to " + myChild.attribute("Id").toLocal8Bit());
00267   while (!myChild.isNull()) 
00268   {
00269     parseLayerGroup(myChild,theParentListViewItem);
00270     myChild = myChild.nextSiblingElement("LayersGroup");
00271   }
00272   //this next part is a kludge because for some reason the root node is not
00273   //expandable until the list is sorted.
00274   //@TODO work out how to get rid of this hack
00275   treeFiles->sortItems(0,Qt::AscendingOrder);
00276   treeFiles->setItemExpanded(theParentListViewItem,true);
00277 }   
00278 
00279 void OmgLayerSelector::parseLayerGroup(const QDomElement &theElement, QTreeWidgetItem *thepParentItem)
00280 {
00281   QTreeWidgetItem * mypItem = createItem(theElement, thepParentItem);
00282 
00283   QString myLabel = theElement.firstChildElement("Label").text();
00284   if (myLabel.isEmpty())
00285   {
00286     myLabel = QObject::tr("Unnamed Folder");
00287   }
00288   //qDebug("LayerSelector found layer group: " + myLabel.toLocal8Bit());
00289   mypItem->setIcon(0, mFolderIcon);
00290   mypItem->setText(0, myLabel);
00291   treeFiles->setItemExpanded(mypItem,true);
00292 
00293 
00294   QDomElement myChildElement = theElement.firstChildElement();
00295   while (!myChildElement.isNull()) 
00296   {
00297     if (myChildElement.tagName() == "LayersGroup") 
00298     {
00299       parseLayerGroup(myChildElement,mypItem);
00300     }
00301     else if (myChildElement.tagName() == "Layer") 
00302     {
00303       QTreeWidgetItem *mypChildItem = createItem(myChildElement,mypItem);
00304       QString myLabel = myChildElement.firstChildElement("Label").text();
00305       if (myLabel.isEmpty())
00306       {
00307         myLabel = QObject::tr("Unnamed Layer");
00308       }
00309       //qDebug("LayerSelector found layer: " + mypChildItem->text(0).toLocal8Bit());
00310       mypChildItem->setFlags(mypItem->flags() | Qt::ItemIsEditable);
00311       if (myChildElement.attribute("HasProjection")=="1")
00312       {
00313         mypChildItem->setIcon(0, mProjectionOkIcon);
00314       }
00315       else
00316       {
00317         mypChildItem->setIcon(0, mProjectionErrorIcon);
00318       }
00319       mypChildItem->setText(0, myLabel);
00320       mypChildItem->setData(0, Qt::UserRole, myChildElement.attribute("Id"));
00321       
00322     } 
00323     myChildElement = myChildElement.nextSiblingElement();
00324   }
00325 }
00326 
00327 QTreeWidgetItem * OmgLayerSelector::createItem(const QDomElement &theElement,
00328                                             QTreeWidgetItem * thepParentItem)
00329 {
00330   QTreeWidgetItem * mypItem=0;
00331   if (thepParentItem) 
00332   {
00333     //qDebug("OmgLayerSelector::createItem with parent  " + thepParentItem->text(1).toLocal8Bit());
00334     mypItem = new QTreeWidgetItem(thepParentItem);
00335   } 
00336   return mypItem;
00337 }
00338 
00339 void OmgLayerSelector::refresh()
00340 {
00341   QCoreApplication::processEvents();
00342 }
00343 
00344 void OmgLayerSelector::showInfo()
00345 {
00346   QString myStyle = Omgui::defaultStyleSheet(); 
00347   tbNotes->document()->setDefaultStyleSheet(myStyle);
00348   QString myInfo = 
00349     "<h2>" + tr("Scanning for GIS layers") + "</h2>" +
00350     tr("openModeller Desktop is now searching for"
00351       " valid gis layers. This may take a while. The layers list"
00352       " will be cached so the next time you use this layer selector"
00353       " tool you will not need to wait.");
00354   tbNotes->setHtml(myInfo);
00355 }

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