mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	Removed gdal deps in qgisapp.
Moved raster load stuff to a group at the end of qgisapp.cpp file. Removed generically useable raster fns from qgisapp to static methods of qgsrasterlayer. Some renaming of variable names etc. Added addRaster(QgsRasterLayer *) private method to qgisapp - which is intended for use via plugins that want to load 'ready made' / symbolised raster layer into the mapCanvas. git-svn-id: http://svn.osgeo.org/qgis/trunk@1576 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
		
							parent
							
								
									0629fbc080
								
							
						
					
					
						commit
						72089002c9
					
				
							
								
								
									
										738
									
								
								src/qgisapp.cpp
									
									
									
									
									
								
							
							
						
						
									
										738
									
								
								src/qgisapp.cpp
									
									
									
									
									
								
							@ -73,9 +73,6 @@
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef GDAL_PRIV_H_INCLUDED
 | 
			
		||||
#include <gdal_priv.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "qgsrect.h"
 | 
			
		||||
@ -100,7 +97,6 @@
 | 
			
		||||
#endif
 | 
			
		||||
#include "qgshelpviewer.h"
 | 
			
		||||
#include "qgsmaplayerregistry.h"
 | 
			
		||||
#include "qgsrasterlayer.h"
 | 
			
		||||
#include "qgsrasterlayerproperties.h"
 | 
			
		||||
#include "qgsvectorlayer.h"
 | 
			
		||||
#include "qgspluginmanager.h"
 | 
			
		||||
@ -273,7 +269,6 @@ QgisApp::QgisApp(QWidget * parent, const char *name, WFlags fl):QgisAppBase(pare
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // register all GDAL and OGR plug-ins
 | 
			
		||||
  GDALAllRegister();           
 | 
			
		||||
  OGRRegisterAll();
 | 
			
		||||
 | 
			
		||||
  QPixmap icon;
 | 
			
		||||
@ -1037,518 +1032,6 @@ bool QgisApp::addLayer(QStringList const &theLayerQStringList)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   The subset of GDAL formats that we currently support.
 | 
			
		||||
   
 | 
			
		||||
   @note
 | 
			
		||||
   
 | 
			
		||||
   Some day this won't be necessary as there'll be a time when
 | 
			
		||||
   theoretically we'll support everything that GDAL can throw at us.
 | 
			
		||||
   
 | 
			
		||||
   These are GDAL driver description strings.
 | 
			
		||||
*/
 | 
			
		||||
static const char *const supportedRasterFormats_[] = {
 | 
			
		||||
  "SDTS",
 | 
			
		||||
  "AIG",
 | 
			
		||||
  "AAIGrid",
 | 
			
		||||
  "GTiff",
 | 
			
		||||
  "USGSDEM",
 | 
			
		||||
  "HFA",
 | 
			
		||||
  "GRASS",
 | 
			
		||||
  "DTED",
 | 
			
		||||
  ""                            // used to indicate end of list
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   returns true if the given raster driver name is one currently
 | 
			
		||||
   supported, otherwise it returns false
 | 
			
		||||
   
 | 
			
		||||
   @param driverName GDAL driver description string
 | 
			
		||||
*/
 | 
			
		||||
static bool isSupportedRasterDriver_(QString const &driverName)
 | 
			
		||||
{
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
 | 
			
		||||
  while (supportedRasterFormats_[i][0]) // while not end of string list
 | 
			
		||||
    {
 | 
			
		||||
      // If we've got a case-insensitive match for a GDAL aware driver
 | 
			
		||||
      // description, then we've got a match.  Why case-insensitive?
 | 
			
		||||
      // I'm just being paranoid in that I can envision a situation
 | 
			
		||||
      // whereby GDAL slightly changes driver description string case,
 | 
			
		||||
      // in which case we'd catch it here.  Not that that would likely
 | 
			
		||||
      // happen, but if it does, we'll already compensate.
 | 
			
		||||
      // GS - At Qt 3.1.2, the case sensitive argument. So we change the
 | 
			
		||||
      // driverName to lower case before testing
 | 
			
		||||
      QString format = supportedRasterFormats_[i];
 | 
			
		||||
      if (driverName.lower().startsWith(format.lower()))
 | 
			
		||||
        {
 | 
			
		||||
          return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      i++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}                               // isSupportedRasterDriver_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   Builds the list of file filter strings to later be used by
 | 
			
		||||
   QgisApp::addRasterLayer()
 | 
			
		||||
   
 | 
			
		||||
   We query GDAL for a list of supported raster formats; we then build
 | 
			
		||||
   a list of file filter strings from that list.  We return a string
 | 
			
		||||
   that contains this list that is suitable for use in a a
 | 
			
		||||
   QFileDialog::getOpenFileNames() call.
 | 
			
		||||
   
 | 
			
		||||
 */
 | 
			
		||||
static void buildSupportedRasterFileFilter_(QString & fileFilters)
 | 
			
		||||
{
 | 
			
		||||
  // first get the GDAL driver manager
 | 
			
		||||
 | 
			
		||||
  GDALDriverManager *driverManager = GetGDALDriverManager();
 | 
			
		||||
 | 
			
		||||
  if (!driverManager)
 | 
			
		||||
    {
 | 
			
		||||
      std::cerr << "unable to get GDALDriverManager\n";
 | 
			
		||||
      return;                   // XXX good place to throw exception if we 
 | 
			
		||||
    }                           // XXX decide to do exceptions
 | 
			
		||||
 | 
			
		||||
  // then iterate through all of the supported drivers, adding the
 | 
			
		||||
  // corresponding file filter
 | 
			
		||||
 | 
			
		||||
  GDALDriver *driver;           // current driver
 | 
			
		||||
 | 
			
		||||
  char **driverMetadata;        // driver metadata strings
 | 
			
		||||
 | 
			
		||||
  QString driverLongName("");   // long name for the given driver
 | 
			
		||||
  QString driverExtension("");  // file name extension for given driver
 | 
			
		||||
  QString driverDescription;    // QString wrapper of GDAL driver description
 | 
			
		||||
 | 
			
		||||
  QStringList metadataTokens;   // essentially the metadata string delimited by '='
 | 
			
		||||
 | 
			
		||||
  QString catchallFilter;       // for Any file(*.*), but also for those
 | 
			
		||||
  // drivers with no specific file
 | 
			
		||||
  // filter
 | 
			
		||||
 | 
			
		||||
  // Grind through all the drivers and their respective metadata.
 | 
			
		||||
  // We'll add a file filter for those drivers that have a file
 | 
			
		||||
  // extension defined for them; the others, welll, even though
 | 
			
		||||
  // theoreticaly we can open those files because there exists a
 | 
			
		||||
  // driver for them, the user will have to use the "All Files" to
 | 
			
		||||
  // open datasets with no explicitly defined file name extension.
 | 
			
		||||
  // Note that file name extension strings are of the form
 | 
			
		||||
  // "DMD_EXTENSION=.*".  We'll also store the long name of the
 | 
			
		||||
  // driver, which will be found in DMD_LONGNAME, which will have the
 | 
			
		||||
  // same form.
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < driverManager->GetDriverCount(); ++i)
 | 
			
		||||
    {
 | 
			
		||||
      driver = driverManager->GetDriver(i);
 | 
			
		||||
 | 
			
		||||
      Q_CHECK_PTR(driver);
 | 
			
		||||
 | 
			
		||||
      if (!driver)
 | 
			
		||||
        {
 | 
			
		||||
          qWarning("unable to get driver %d", i);
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
      // now we need to see if the driver is for something currently
 | 
			
		||||
      // supported; if not, we give it a miss for the next driver
 | 
			
		||||
 | 
			
		||||
      driverDescription = driver->GetDescription();
 | 
			
		||||
 | 
			
		||||
      if (!isSupportedRasterDriver_(driverDescription))
 | 
			
		||||
        {
 | 
			
		||||
          // not supported, therefore skip
 | 
			
		||||
#ifdef QGISDEBUG
 | 
			
		||||
          qWarning("skipping unsupported driver %s", driver->GetDescription());
 | 
			
		||||
#endif
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
      // std::cerr << "got driver string " << driver->GetDescription() << "\n";
 | 
			
		||||
 | 
			
		||||
      driverMetadata = driver->GetMetadata();
 | 
			
		||||
 | 
			
		||||
      // presumably we know we've run out of metadta if either the
 | 
			
		||||
      // address is 0, or the first character is null
 | 
			
		||||
      while (driverMetadata && '\0' != driverMetadata[0])
 | 
			
		||||
        {
 | 
			
		||||
          metadataTokens = QStringList::split("=", *driverMetadata);
 | 
			
		||||
          // std::cerr << "\t" << *driverMetadata << "\n";
 | 
			
		||||
 | 
			
		||||
          // XXX add check for malformed metadataTokens
 | 
			
		||||
 | 
			
		||||
          // Note that it's oddly possible for there to be a
 | 
			
		||||
          // DMD_EXTENSION with no corresponding defined extension
 | 
			
		||||
          // string; so we check that there're more than two tokens.
 | 
			
		||||
 | 
			
		||||
          if (metadataTokens.count() > 1)
 | 
			
		||||
            {
 | 
			
		||||
              if ("DMD_EXTENSION" == metadataTokens[0])
 | 
			
		||||
                {
 | 
			
		||||
                  driverExtension = metadataTokens[1];
 | 
			
		||||
 | 
			
		||||
              } else if ("DMD_LONGNAME" == metadataTokens[0])
 | 
			
		||||
                {
 | 
			
		||||
                  driverLongName = metadataTokens[1];
 | 
			
		||||
 | 
			
		||||
                  // remove any superfluous (.*) strings at the end as
 | 
			
		||||
                  // they'll confuse QFileDialog::getOpenFileNames()
 | 
			
		||||
 | 
			
		||||
                  driverLongName.remove(QRegExp("\\(.*\\)$"));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          // if we have both the file name extension and the long name,
 | 
			
		||||
          // then we've all the information we need for the current
 | 
			
		||||
          // driver; therefore emit a file filter string and move to
 | 
			
		||||
          // the next driver
 | 
			
		||||
          if (!(driverExtension.isEmpty() || driverLongName.isEmpty()))
 | 
			
		||||
            {
 | 
			
		||||
              // XXX add check for SDTS; in that case we want (*CATD.DDF)
 | 
			
		||||
              fileFilters += createFileFilter_(driverLongName, "*." + driverExtension);
 | 
			
		||||
 | 
			
		||||
              break;            // ... to next driver, if any.
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          ++driverMetadata;
 | 
			
		||||
 | 
			
		||||
        }                       // each metadata item
 | 
			
		||||
 | 
			
		||||
      if (driverExtension.isEmpty() && !driverLongName.isEmpty())
 | 
			
		||||
        {
 | 
			
		||||
          // Then what we have here is a driver with no corresponding
 | 
			
		||||
          // file extension; e.g., GRASS.  In which case we append the
 | 
			
		||||
          // string to the "catch-all" which will match all file types.
 | 
			
		||||
          // (I.e., "*.*") We use the driver description intead of the
 | 
			
		||||
          // long time to prevent the catch-all line from getting too
 | 
			
		||||
          // large.
 | 
			
		||||
 | 
			
		||||
          // ... OTOH, there are some drivers with missing
 | 
			
		||||
          // DMD_EXTENSION; so let's check for them here and handle
 | 
			
		||||
          // them appropriately
 | 
			
		||||
 | 
			
		||||
          // USGS DEMs use "*.dem"
 | 
			
		||||
          if (driverDescription.startsWith("USGSDEM"))
 | 
			
		||||
            {
 | 
			
		||||
              fileFilters += createFileFilter_(driverLongName, "*.dem");
 | 
			
		||||
            } else if (driverDescription.startsWith("DTED"))
 | 
			
		||||
            {
 | 
			
		||||
              // DTED use "*.dt0"
 | 
			
		||||
              fileFilters += createFileFilter_(driverLongName, "*.dt0");
 | 
			
		||||
            } else
 | 
			
		||||
            {
 | 
			
		||||
              catchallFilter += QString(driver->GetDescription()) + " ";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      driverExtension = driverLongName = "";  // reset for next driver
 | 
			
		||||
 | 
			
		||||
    }                           // each loaded GDAL driver
 | 
			
		||||
 | 
			
		||||
  // can't forget the default case
 | 
			
		||||
  fileFilters += catchallFilter + "All other files (*)";
 | 
			
		||||
 | 
			
		||||
}                               // buildSupportedRasterFileFilter_()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** @todo XXX I'd *really* like to return, ya know, _false_.
 | 
			
		||||
 */
 | 
			
		||||
void QgisApp::addRasterLayer()
 | 
			
		||||
{
 | 
			
		||||
  mMapCanvas->freeze();
 | 
			
		||||
  QString fileFilters;
 | 
			
		||||
 | 
			
		||||
  // build the file filters based on the loaded GDAL drivers
 | 
			
		||||
  buildSupportedRasterFileFilter_(fileFilters);
 | 
			
		||||
 | 
			
		||||
  QStringList selectedFiles;
 | 
			
		||||
 | 
			
		||||
  openFilesRememberingFilter_("lastRasterFileFilter", fileFilters, selectedFiles);
 | 
			
		||||
 | 
			
		||||
  if (selectedFiles.isEmpty())
 | 
			
		||||
    {
 | 
			
		||||
      // no files were selected, so just bail		
 | 
			
		||||
       return;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
   addRasterLayer(selectedFiles);
 | 
			
		||||
}// QgisApp::addRasterLayer()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool QgisApp::addRasterLayer(QFileInfo const & rasterFile)
 | 
			
		||||
{	
 | 
			
		||||
   // let the user know we're going to possibly be taking a while
 | 
			
		||||
   QApplication::setOverrideCursor(Qt::WaitCursor);
 | 
			
		||||
 | 
			
		||||
   mMapCanvas->freeze();         // XXX why do we do this?
 | 
			
		||||
 | 
			
		||||
   // XXX ya know QgsRasterLayer can snip out the basename on its own;
 | 
			
		||||
   // XXX why do we have to pass it in for it?
 | 
			
		||||
   QgsRasterLayer *layer = 
 | 
			
		||||
      new QgsRasterLayer(rasterFile.filePath(), rasterFile.baseName());
 | 
			
		||||
 | 
			
		||||
   Q_CHECK_PTR( layer );
 | 
			
		||||
 | 
			
		||||
   if ( ! layer )
 | 
			
		||||
   {
 | 
			
		||||
      mMapCanvas->freeze(false);
 | 
			
		||||
      QApplication::restoreOverrideCursor();
 | 
			
		||||
 | 
			
		||||
      // XXX insert meaningful whine to the user here; although be
 | 
			
		||||
      // XXX mindful that a null layer may mean exhausted memory resources
 | 
			
		||||
      return false; 
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (layer->isValid())
 | 
			
		||||
   {
 | 
			
		||||
     // register this layer with the central layers registry
 | 
			
		||||
     mMapLayerRegistry->addMapLayer(layer);
 | 
			
		||||
     // XXX doesn't the mMapCanvas->addLayer() do this?
 | 
			
		||||
     QObject::connect(layer, 
 | 
			
		||||
             SIGNAL(repaintRequested()), 
 | 
			
		||||
             mMapCanvas, 
 | 
			
		||||
             SLOT(refresh()));
 | 
			
		||||
 | 
			
		||||
     // connect up any request the raster may make to update the app progress
 | 
			
		||||
     QObject::connect(layer, 
 | 
			
		||||
             SIGNAL(setProgress(int,int)), 
 | 
			
		||||
             this, 
 | 
			
		||||
             SLOT(showProgress(int,int)));  
 | 
			
		||||
     // connect up any request the raster may make to update the statusbar message
 | 
			
		||||
     QObject::connect(layer, 
 | 
			
		||||
             SIGNAL(setStatus(QString)), 
 | 
			
		||||
             this, 
 | 
			
		||||
             SLOT(showStatusMessage(QString)));            
 | 
			
		||||
     // add it to the mapcanvas collection
 | 
			
		||||
     mMapCanvas->addLayer(layer);
 | 
			
		||||
     
 | 
			
		||||
     //connect up a request from the raster layer to show in overview map
 | 
			
		||||
     QObject::connect(layer, 
 | 
			
		||||
             SIGNAL(showInOverview(QString,bool)), 
 | 
			
		||||
             this, 
 | 
			
		||||
             SLOT(setLayerOverviewStatus(QString,bool)));           
 | 
			
		||||
         
 | 
			
		||||
     mProjectIsDirtyFlag = true;
 | 
			
		||||
 | 
			
		||||
     // init the context menu so it can connect to slots in main app
 | 
			
		||||
     layer->initContextMenu(this);
 | 
			
		||||
   } else
 | 
			
		||||
   {
 | 
			
		||||
      QString msg(rasterFile.baseName() + " is not a valid or recognized raster data source");
 | 
			
		||||
      QMessageBox::critical(this, "Invalid Data Source", msg);
 | 
			
		||||
 | 
			
		||||
      delete layer;
 | 
			
		||||
 | 
			
		||||
      mMapCanvas->freeze(false);
 | 
			
		||||
      QApplication::restoreOverrideCursor();
 | 
			
		||||
 | 
			
		||||
      return false;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   // mMapLegend->update(); NOW UPDATED VIA SIGNAL/SLOTS
 | 
			
		||||
  qApp->processEvents();
 | 
			
		||||
  mMapCanvas->freeze(false);
 | 
			
		||||
  mMapCanvas->render();
 | 
			
		||||
  QApplication::restoreOverrideCursor();
 | 
			
		||||
  statusBar()->message(mMapCanvas->extent().stringRep(2));
 | 
			
		||||
 | 
			
		||||
   return true;
 | 
			
		||||
   
 | 
			
		||||
} // QgisApp::addRasterLayer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   @todo XXX ya know, this could be changed to iteratively call the above
 | 
			
		||||
*/
 | 
			
		||||
bool QgisApp::addRasterLayer(QStringList const &theFileNameQStringList)
 | 
			
		||||
{
 | 
			
		||||
  if (theFileNameQStringList.empty())
 | 
			
		||||
  {
 | 
			
		||||
    // no files selected so bail out, but
 | 
			
		||||
    // allow mMapCanvas to handle events
 | 
			
		||||
    // first
 | 
			
		||||
    mMapCanvas->freeze(false);
 | 
			
		||||
    return false;
 | 
			
		||||
  } else
 | 
			
		||||
  {
 | 
			
		||||
    mMapCanvas->freeze();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QApplication::setOverrideCursor(Qt::WaitCursor);
 | 
			
		||||
  // this is messy since some files in the list may be rasters and others may
 | 
			
		||||
  // be ogr layers. We'll set returnValue to false if one or more layers fail
 | 
			
		||||
  // to load.
 | 
			
		||||
  bool returnValue = true;
 | 
			
		||||
  for (QStringList::ConstIterator myIterator = theFileNameQStringList.begin(); 
 | 
			
		||||
          myIterator != theFileNameQStringList.end();
 | 
			
		||||
          ++myIterator)
 | 
			
		||||
  {
 | 
			
		||||
    if (isValidRasterFileName(*myIterator))
 | 
			
		||||
    {
 | 
			
		||||
      QFileInfo myFileInfo(*myIterator);
 | 
			
		||||
      // get the directory the .adf file was in
 | 
			
		||||
      QString myDirNameQString = myFileInfo.dirPath();
 | 
			
		||||
      QString myBaseNameQString = myFileInfo.baseName();
 | 
			
		||||
      //only allow one copy of a ai grid file to be loaded at a
 | 
			
		||||
      //time to prevent the user selecting all adfs in 1 dir which
 | 
			
		||||
      //actually represent 1 coverate,
 | 
			
		||||
 | 
			
		||||
      // create the layer
 | 
			
		||||
      QgsRasterLayer *layer = new QgsRasterLayer(*myIterator, myBaseNameQString);
 | 
			
		||||
      Q_CHECK_PTR( layer );
 | 
			
		||||
 | 
			
		||||
      if ( ! layer )
 | 
			
		||||
      {
 | 
			
		||||
        mMapCanvas->freeze(false);
 | 
			
		||||
        QApplication::restoreOverrideCursor();
 | 
			
		||||
 | 
			
		||||
        // XXX insert meaningful whine to the user here
 | 
			
		||||
        return false; 
 | 
			
		||||
      }
 | 
			
		||||
      if (layer->isValid())
 | 
			
		||||
      {
 | 
			
		||||
        // register this layer with the central layers registry
 | 
			
		||||
        mMapLayerRegistry->addMapLayer(layer);
 | 
			
		||||
      
 | 
			
		||||
        QObject::connect(layer, 
 | 
			
		||||
                SIGNAL(repaintRequested()), 
 | 
			
		||||
                mMapCanvas, 
 | 
			
		||||
                SLOT(refresh()));
 | 
			
		||||
        // connect up any request the raster may make to update the app statusbar
 | 
			
		||||
        QObject::connect(layer, 
 | 
			
		||||
                SIGNAL(setProgress(int,int)), 
 | 
			
		||||
                this, 
 | 
			
		||||
                SLOT(showProgress(int,int))); 
 | 
			
		||||
        // connect up any request the raster may make to update the statusbar message
 | 
			
		||||
        QObject::connect(layer, 
 | 
			
		||||
                SIGNAL(setStatus(QString)), 
 | 
			
		||||
                this, 
 | 
			
		||||
                SLOT(showStatusMessage(QString)));                
 | 
			
		||||
        // add it to the mapcanvas collection
 | 
			
		||||
        mMapCanvas->addLayer(layer);
 | 
			
		||||
     //connect up a request from the raster layer to show in overview map
 | 
			
		||||
     QObject::connect(layer, 
 | 
			
		||||
             SIGNAL(showInOverview(QString,bool)), 
 | 
			
		||||
             this, 
 | 
			
		||||
             SLOT(setLayerOverviewStatus(QString,bool)));           
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        mProjectIsDirtyFlag = true;
 | 
			
		||||
        // init the context menu so it can connect to slots in main app
 | 
			
		||||
        // XXX Yes, but what if the layer is invalid?  Should we still be doing this?
 | 
			
		||||
        layer->initContextMenu(this);
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
        QString msg(*myIterator + " is not a valid or recognized raster data source");
 | 
			
		||||
        QMessageBox::critical(this, "Invalid Data Source", msg);
 | 
			
		||||
 | 
			
		||||
        delete layer;
 | 
			
		||||
 | 
			
		||||
        // XXX should we return false here, or just grind through
 | 
			
		||||
        // XXX the remaining arguments?
 | 
			
		||||
        returnValue = false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      //only allow one copy of a ai grid file to be loaded at a
 | 
			
		||||
      //time to prevent the user selecting all adfs in 1 dir which
 | 
			
		||||
      //actually represent 1 coverate,
 | 
			
		||||
 | 
			
		||||
      if (myBaseNameQString.lower().endsWith(".adf"))
 | 
			
		||||
      {
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }else
 | 
			
		||||
    {
 | 
			
		||||
      QString msg(*myIterator + " is not a supported raster data source");
 | 
			
		||||
      QMessageBox::critical(this, "Unsupported Data Source", msg);
 | 
			
		||||
      returnValue = false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // mMapLegend->update(); NOW UPDATED VIA SIGNAL/SLOTS
 | 
			
		||||
 | 
			
		||||
  qApp->processEvents();
 | 
			
		||||
 | 
			
		||||
  mMapCanvas->freeze(false);
 | 
			
		||||
 | 
			
		||||
  mMapCanvas->render();
 | 
			
		||||
 | 
			
		||||
  QApplication::restoreOverrideCursor();
 | 
			
		||||
 | 
			
		||||
  statusBar()->message(mMapCanvas->extent().stringRep(2));
 | 
			
		||||
 | 
			
		||||
  return returnValue;
 | 
			
		||||
 | 
			
		||||
}                               // QgisApp::addRasterLayer()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** This helper checks to see whether the filename appears to be a valid raster file name */
 | 
			
		||||
bool QgisApp::isValidRasterFileName(QString theFileNameQString)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  GDALDatasetH myDataset;
 | 
			
		||||
  GDALAllRegister();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  myDataset = GDALOpen( theFileNameQString, GA_ReadOnly );
 | 
			
		||||
 | 
			
		||||
  if( myDataset == NULL )
 | 
			
		||||
  {
 | 
			
		||||
    
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    GDALClose(myDataset);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * This way is no longer a good idea because it does not
 | 
			
		||||
   * cater for filetypes such as grass rasters that dont
 | 
			
		||||
   * have a predictable file extension.
 | 
			
		||||
   * 
 | 
			
		||||
   QString name = theFileNameQString.lower();
 | 
			
		||||
   return (name.endsWith(".adf") ||
 | 
			
		||||
   name.endsWith(".asc") ||
 | 
			
		||||
   name.endsWith(".grd") ||
 | 
			
		||||
   name.endsWith(".img") ||
 | 
			
		||||
   name.endsWith(".tif") || 
 | 
			
		||||
   name.endsWith(".png") || 
 | 
			
		||||
   name.endsWith(".jpg") || 
 | 
			
		||||
   name.endsWith(".dem") || 
 | 
			
		||||
   name.endsWith(".ddf")) ||
 | 
			
		||||
   name.endsWith(".dt0");
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Overloaded of the above function provided for convenience that takes a qstring pointer */
 | 
			
		||||
bool QgisApp::isValidRasterFileName(QString * theFileNameQString)
 | 
			
		||||
{
 | 
			
		||||
  //dereference and delegate
 | 
			
		||||
  return isValidRasterFileName(*theFileNameQString);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** This helper checks to see whether the filename appears to be a valid vector file name */
 | 
			
		||||
bool QgisApp::isValidVectorFileName(QString theFileNameQString)
 | 
			
		||||
{
 | 
			
		||||
@ -3225,3 +2708,224 @@ void QgisApp::showCapturePointCoordinate(QgsPoint & theQgsPoint)
 | 
			
		||||
  QString myMessage = "Clipboard contents set to: ";
 | 
			
		||||
  statusBar()->message(myMessage + myClipboard->text());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
// Only functions relating to raster layer management in this
 | 
			
		||||
// section (look for a similar comment block to this to find
 | 
			
		||||
// the end of this section). I am hoping to move many of the
 | 
			
		||||
// raster layer loading fn's below into QgsRasterLayer
 | 
			
		||||
// Only ones that require a gui or are particularly wired in
 | 
			
		||||
// to the mapCanvas instance etc will remain here.
 | 
			
		||||
//
 | 
			
		||||
// Tim Sutton
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
/////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** @todo XXX I'd *really* like to return, ya know, _false_.
 | 
			
		||||
 */
 | 
			
		||||
void QgisApp::addRasterLayer()
 | 
			
		||||
{
 | 
			
		||||
  mMapCanvas->freeze();
 | 
			
		||||
  QString fileFilters;
 | 
			
		||||
 | 
			
		||||
  // build the file filters based on the loaded GDAL drivers
 | 
			
		||||
  QgsRasterLayer::buildSupportedRasterFileFilter(fileFilters);
 | 
			
		||||
 | 
			
		||||
  QStringList selectedFiles;
 | 
			
		||||
 | 
			
		||||
  openFilesRememberingFilter_("lastRasterFileFilter", fileFilters, selectedFiles);
 | 
			
		||||
 | 
			
		||||
  if (selectedFiles.isEmpty())
 | 
			
		||||
    {
 | 
			
		||||
      // no files were selected, so just bail		
 | 
			
		||||
       return;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
   addRasterLayer(selectedFiles);
 | 
			
		||||
}// QgisApp::addRasterLayer()
 | 
			
		||||
 | 
			
		||||
bool QgisApp::addRasterLayer(QgsRasterLayer * theRasterLayer)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  Q_CHECK_PTR( theRasterLayer );
 | 
			
		||||
 | 
			
		||||
  if ( ! theRasterLayer )
 | 
			
		||||
  {
 | 
			
		||||
    mMapCanvas->freeze(false);
 | 
			
		||||
    QApplication::restoreOverrideCursor();
 | 
			
		||||
 | 
			
		||||
    // XXX insert meaningful whine to the user here; although be
 | 
			
		||||
    // XXX mindful that a null layer may mean exhausted memory resources
 | 
			
		||||
    return false; 
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (theRasterLayer->isValid())
 | 
			
		||||
  {
 | 
			
		||||
    // register this layer with the central layers registry
 | 
			
		||||
    mMapLayerRegistry->addMapLayer(theRasterLayer);
 | 
			
		||||
    // XXX doesn't the mMapCanvas->addLayer() do this?
 | 
			
		||||
    QObject::connect(theRasterLayer, 
 | 
			
		||||
            SIGNAL(repaintRequested()), 
 | 
			
		||||
            mMapCanvas, 
 | 
			
		||||
            SLOT(refresh()));
 | 
			
		||||
 | 
			
		||||
    // connect up any request the raster may make to update the app progress
 | 
			
		||||
    QObject::connect(theRasterLayer, 
 | 
			
		||||
            SIGNAL(setProgress(int,int)), 
 | 
			
		||||
            this, 
 | 
			
		||||
            SLOT(showProgress(int,int)));  
 | 
			
		||||
    // connect up any request the raster may make to update the statusbar message
 | 
			
		||||
    QObject::connect(theRasterLayer, 
 | 
			
		||||
            SIGNAL(setStatus(QString)), 
 | 
			
		||||
            this, 
 | 
			
		||||
            SLOT(showStatusMessage(QString)));            
 | 
			
		||||
    // add it to the mapcanvas collection
 | 
			
		||||
    mMapCanvas->addLayer(theRasterLayer);
 | 
			
		||||
 | 
			
		||||
    //connect up a request from the raster layer to show in overview map
 | 
			
		||||
    QObject::connect(theRasterLayer, 
 | 
			
		||||
            SIGNAL(showInOverview(QString,bool)), 
 | 
			
		||||
            this, 
 | 
			
		||||
            SLOT(setLayerOverviewStatus(QString,bool)));           
 | 
			
		||||
 | 
			
		||||
    mProjectIsDirtyFlag = true;
 | 
			
		||||
 | 
			
		||||
    // init the context menu so it can connect to slots in main app
 | 
			
		||||
    theRasterLayer->initContextMenu(this);
 | 
			
		||||
  } 
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
 | 
			
		||||
    delete theRasterLayer;
 | 
			
		||||
 | 
			
		||||
    mMapCanvas->freeze(false);
 | 
			
		||||
    QApplication::restoreOverrideCursor();
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // mMapLegend->update(); NOW UPDATED VIA SIGNAL/SLOTS
 | 
			
		||||
  qApp->processEvents();
 | 
			
		||||
  mMapCanvas->freeze(false);
 | 
			
		||||
  mMapCanvas->render();
 | 
			
		||||
  QApplication::restoreOverrideCursor();
 | 
			
		||||
  statusBar()->message(mMapCanvas->extent().stringRep(2));
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgisApp::addRasterLayer(QFileInfo const & rasterFile)
 | 
			
		||||
{
 | 
			
		||||
  // let the user know we're going to possibly be taking a while
 | 
			
		||||
  QApplication::setOverrideCursor(Qt::WaitCursor);
 | 
			
		||||
 | 
			
		||||
  mMapCanvas->freeze();         // XXX why do we do this?
 | 
			
		||||
 | 
			
		||||
  // XXX ya know QgsRasterLayer can snip out the basename on its own;
 | 
			
		||||
  // XXX why do we have to pass it in for it?
 | 
			
		||||
  QgsRasterLayer *layer = 
 | 
			
		||||
      new QgsRasterLayer(rasterFile.filePath(), rasterFile.baseName());
 | 
			
		||||
  
 | 
			
		||||
  if (!addRasterLayer(layer))
 | 
			
		||||
  {
 | 
			
		||||
    QString msg(rasterFile.baseName() + " is not a valid or recognized raster data source");
 | 
			
		||||
    QMessageBox::critical(this, "Invalid Data Source", msg);
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
} // QgisApp::addRasterLayer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool QgisApp::addRasterLayer(QStringList const &theFileNameQStringList)
 | 
			
		||||
{
 | 
			
		||||
  if (theFileNameQStringList.empty())
 | 
			
		||||
  {
 | 
			
		||||
    // no files selected so bail out, but
 | 
			
		||||
    // allow mMapCanvas to handle events
 | 
			
		||||
    // first
 | 
			
		||||
    mMapCanvas->freeze(false);
 | 
			
		||||
    return false;
 | 
			
		||||
  } 
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    mMapCanvas->freeze();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QApplication::setOverrideCursor(Qt::WaitCursor);
 | 
			
		||||
  // this is messy since some files in the list may be rasters and others may
 | 
			
		||||
  // be ogr layers. We'll set returnValue to false if one or more layers fail
 | 
			
		||||
  // to load.
 | 
			
		||||
  bool returnValue = true;
 | 
			
		||||
  for (QStringList::ConstIterator myIterator = theFileNameQStringList.begin(); 
 | 
			
		||||
          myIterator != theFileNameQStringList.end();
 | 
			
		||||
          ++myIterator)
 | 
			
		||||
  {
 | 
			
		||||
    if (QgsRasterLayer::isValidRasterFileName(*myIterator))
 | 
			
		||||
    {
 | 
			
		||||
      QFileInfo myFileInfo(*myIterator);
 | 
			
		||||
      // get the directory the .adf file was in
 | 
			
		||||
      QString myDirNameQString = myFileInfo.dirPath();
 | 
			
		||||
      QString myBaseNameQString = myFileInfo.baseName();
 | 
			
		||||
      //only allow one copy of a ai grid file to be loaded at a
 | 
			
		||||
      //time to prevent the user selecting all adfs in 1 dir which
 | 
			
		||||
      //actually represent 1 coverate,
 | 
			
		||||
 | 
			
		||||
      // create the layer
 | 
			
		||||
      QgsRasterLayer *layer = new QgsRasterLayer(*myIterator, myBaseNameQString);
 | 
			
		||||
 | 
			
		||||
      addRasterLayer(layer);
 | 
			
		||||
 | 
			
		||||
      //only allow one copy of a ai grid file to be loaded at a
 | 
			
		||||
      //time to prevent the user selecting all adfs in 1 dir which
 | 
			
		||||
      //actually represent 1 coverate,
 | 
			
		||||
 | 
			
		||||
      if (myBaseNameQString.lower().endsWith(".adf"))
 | 
			
		||||
      {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }else
 | 
			
		||||
    {
 | 
			
		||||
      QApplication::restoreOverrideCursor();
 | 
			
		||||
      QString msg(*myIterator + " is not a supported raster data source");
 | 
			
		||||
      QMessageBox::critical(this, "Unsupported Data Source", msg);
 | 
			
		||||
      returnValue = false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // mMapLegend->update(); NOW UPDATED VIA SIGNAL/SLOTS
 | 
			
		||||
 | 
			
		||||
  return returnValue;
 | 
			
		||||
 | 
			
		||||
}                               // QgisApp::addRasterLayer()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//    RASTER ONLY RELATED FUNCTIONS BLOCK ENDS....
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
///////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,7 @@ class QgsProviderRegistry;
 | 
			
		||||
class QgsHelpViewer;
 | 
			
		||||
class QgsMapCanvas;
 | 
			
		||||
class QgsMapLayerRegistry;
 | 
			
		||||
class QgsRasterLayer;
 | 
			
		||||
#ifdef WIN32
 | 
			
		||||
#include "qgisappbase.h"
 | 
			
		||||
#else
 | 
			
		||||
@ -141,12 +142,11 @@ private:
 | 
			
		||||
 | 
			
		||||
    //! Add a vector layer to the map
 | 
			
		||||
    void addLayer();
 | 
			
		||||
    //! Add a raster layer to the map
 | 
			
		||||
    //! Add a raster layer to the map (will prompt user for filename using dlg
 | 
			
		||||
    void addRasterLayer();
 | 
			
		||||
    /** This helper checks to see whether the filename appears to be a valid raster file name */
 | 
			
		||||
    bool isValidRasterFileName (QString theFileNameQString);
 | 
			
		||||
    /** Overloaded version of the above function provided for convenience that takes a qstring pointer */
 | 
			
		||||
    bool isValidRasterFileName (QString * theFileNameQString);
 | 
			
		||||
    //! Add a raster layer to the map (passed in as a ptr)
 | 
			
		||||
    bool addRasterLayer(QgsRasterLayer * theRasterLayer);
 | 
			
		||||
    //@todo We should move these next two into vector layer class
 | 
			
		||||
    /** This helper checks to see whether the filename appears to be a valid vector file name */
 | 
			
		||||
    bool isValidVectorFileName (QString theFileNameQString);
 | 
			
		||||
    /** Overloaded version of the above function provided for convenience that takes a qstring pointer */
 | 
			
		||||
 | 
			
		||||
@ -83,6 +83,288 @@ email                : tim at linfiniti.com
 | 
			
		||||
#include "gdal_priv.h"
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// Static Methods and members first....
 | 
			
		||||
//
 | 
			
		||||
/////////////////////////////////////////////////////////
 | 
			
		||||
/**
 | 
			
		||||
  Static member variable storing the subset of GDAL formats 
 | 
			
		||||
  that we currently support.
 | 
			
		||||
 | 
			
		||||
  @note
 | 
			
		||||
 | 
			
		||||
  Some day this won't be necessary as there'll be a time when
 | 
			
		||||
  theoretically we'll support everything that GDAL can throw at us.
 | 
			
		||||
 | 
			
		||||
  These are GDAL driver description strings.
 | 
			
		||||
  */
 | 
			
		||||
static const char *const mSupportedRasterFormats[] = {
 | 
			
		||||
  "SDTS",
 | 
			
		||||
  "AIG",
 | 
			
		||||
  "AAIGrid",
 | 
			
		||||
  "GTiff",
 | 
			
		||||
  "USGSDEM",
 | 
			
		||||
  "HFA",
 | 
			
		||||
  "GRASS",
 | 
			
		||||
  "DTED",
 | 
			
		||||
  ""   // used to indicate end of list
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
  Builds the list of file filter strings to later be used by
 | 
			
		||||
  QgisApp::addRasterLayer()
 | 
			
		||||
 | 
			
		||||
  We query GDAL for a list of supported raster formats; we then build
 | 
			
		||||
  a list of file filter strings from that list.  We return a string
 | 
			
		||||
  that contains this list that is suitable for use in a a
 | 
			
		||||
  QFileDialog::getOpenFileNames() call.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
void QgsRasterLayer::buildSupportedRasterFileFilter(QString & theFileFiltersString)
 | 
			
		||||
{
 | 
			
		||||
  // first get the GDAL driver manager
 | 
			
		||||
  GDALAllRegister();
 | 
			
		||||
  GDALDriverManager *myGdalDriverManager = GetGDALDriverManager();
 | 
			
		||||
 | 
			
		||||
  if (!myGdalDriverManager)
 | 
			
		||||
  {
 | 
			
		||||
    std::cerr << "unable to get GDALDriverManager\n";
 | 
			
		||||
    return;                   // XXX good place to throw exception if we 
 | 
			
		||||
  }                           // XXX decide to do exceptions
 | 
			
		||||
 | 
			
		||||
  // then iterate through all of the supported drivers, adding the
 | 
			
		||||
  // corresponding file filter
 | 
			
		||||
 | 
			
		||||
  GDALDriver *myGdalDriver;           // current driver
 | 
			
		||||
 | 
			
		||||
  char **myGdalDriverMetadata;        // driver metadata strings
 | 
			
		||||
 | 
			
		||||
  QString myGdalDriverLongName("");   // long name for the given driver
 | 
			
		||||
  QString myGdalDriverExtension("");  // file name extension for given driver
 | 
			
		||||
  QString myGdalDriverDescription;    // QString wrapper of GDAL driver description
 | 
			
		||||
 | 
			
		||||
  QStringList metadataTokens;   // essentially the metadata string delimited by '='
 | 
			
		||||
 | 
			
		||||
  QString catchallFilter;       // for Any file(*.*), but also for those
 | 
			
		||||
  // drivers with no specific file
 | 
			
		||||
  // filter
 | 
			
		||||
 | 
			
		||||
  // Grind through all the drivers and their respective metadata.
 | 
			
		||||
  // We'll add a file filter for those drivers that have a file
 | 
			
		||||
  // extension defined for them; the others, welll, even though
 | 
			
		||||
  // theoreticaly we can open those files because there exists a
 | 
			
		||||
  // driver for them, the user will have to use the "All Files" to
 | 
			
		||||
  // open datasets with no explicitly defined file name extension.
 | 
			
		||||
  // Note that file name extension strings are of the form
 | 
			
		||||
  // "DMD_EXTENSION=.*".  We'll also store the long name of the
 | 
			
		||||
  // driver, which will be found in DMD_LONGNAME, which will have the
 | 
			
		||||
  // same form.
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < myGdalDriverManager->GetDriverCount(); ++i)
 | 
			
		||||
  {
 | 
			
		||||
    myGdalDriver = myGdalDriverManager->GetDriver(i);
 | 
			
		||||
 | 
			
		||||
    Q_CHECK_PTR(myGdalDriver);
 | 
			
		||||
 | 
			
		||||
    if (!myGdalDriver)
 | 
			
		||||
    {
 | 
			
		||||
      qWarning("unable to get driver %d", i);
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    // now we need to see if the driver is for something currently
 | 
			
		||||
    // supported; if not, we give it a miss for the next driver
 | 
			
		||||
 | 
			
		||||
    myGdalDriverDescription = myGdalDriver->GetDescription();
 | 
			
		||||
 | 
			
		||||
    if (!isSupportedRasterDriver(myGdalDriverDescription))
 | 
			
		||||
    {
 | 
			
		||||
      // not supported, therefore skip
 | 
			
		||||
#ifdef QGISDEBUG
 | 
			
		||||
      qWarning("skipping unsupported driver %s", myGdalDriver->GetDescription());
 | 
			
		||||
#endif
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    // std::cerr << "got driver string " << myGdalDriver->GetDescription() << "\n";
 | 
			
		||||
 | 
			
		||||
    myGdalDriverMetadata = myGdalDriver->GetMetadata();
 | 
			
		||||
 | 
			
		||||
    // presumably we know we've run out of metadta if either the
 | 
			
		||||
    // address is 0, or the first character is null
 | 
			
		||||
    while (myGdalDriverMetadata && '\0' != myGdalDriverMetadata[0])
 | 
			
		||||
    {
 | 
			
		||||
      metadataTokens = QStringList::split("=", *myGdalDriverMetadata);
 | 
			
		||||
      // std::cerr << "\t" << *myGdalDriverMetadata << "\n";
 | 
			
		||||
 | 
			
		||||
      // XXX add check for malformed metadataTokens
 | 
			
		||||
 | 
			
		||||
      // Note that it's oddly possible for there to be a
 | 
			
		||||
      // DMD_EXTENSION with no corresponding defined extension
 | 
			
		||||
      // string; so we check that there're more than two tokens.
 | 
			
		||||
 | 
			
		||||
      if (metadataTokens.count() > 1)
 | 
			
		||||
      {
 | 
			
		||||
        if ("DMD_EXTENSION" == metadataTokens[0])
 | 
			
		||||
        {
 | 
			
		||||
          myGdalDriverExtension = metadataTokens[1];
 | 
			
		||||
 | 
			
		||||
        } 
 | 
			
		||||
        else if ("DMD_LONGNAME" == metadataTokens[0])
 | 
			
		||||
        {
 | 
			
		||||
          myGdalDriverLongName = metadataTokens[1];
 | 
			
		||||
 | 
			
		||||
          // remove any superfluous (.*) strings at the end as
 | 
			
		||||
          // they'll confuse QFileDialog::getOpenFileNames()
 | 
			
		||||
 | 
			
		||||
          myGdalDriverLongName.remove(QRegExp("\\(.*\\)$"));
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      // if we have both the file name extension and the long name,
 | 
			
		||||
      // then we've all the information we need for the current
 | 
			
		||||
      // driver; therefore emit a file filter string and move to
 | 
			
		||||
      // the next driver
 | 
			
		||||
      if (!(myGdalDriverExtension.isEmpty() || myGdalDriverLongName.isEmpty()))
 | 
			
		||||
      {
 | 
			
		||||
        // XXX add check for SDTS; in that case we want (*CATD.DDF)
 | 
			
		||||
        QString glob = "*." + myGdalDriverExtension; 
 | 
			
		||||
        theFileFiltersString += myGdalDriverLongName + " (" + glob.lower() + " " + glob.upper() + ");;";
 | 
			
		||||
 | 
			
		||||
        break;            // ... to next driver, if any.
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      ++myGdalDriverMetadata;
 | 
			
		||||
 | 
			
		||||
    }                       // each metadata item
 | 
			
		||||
 | 
			
		||||
    if (myGdalDriverExtension.isEmpty() && !myGdalDriverLongName.isEmpty())
 | 
			
		||||
    {
 | 
			
		||||
      // Then what we have here is a driver with no corresponding
 | 
			
		||||
      // file extension; e.g., GRASS.  In which case we append the
 | 
			
		||||
      // string to the "catch-all" which will match all file types.
 | 
			
		||||
      // (I.e., "*.*") We use the driver description intead of the
 | 
			
		||||
      // long time to prevent the catch-all line from getting too
 | 
			
		||||
      // large.
 | 
			
		||||
 | 
			
		||||
      // ... OTOH, there are some drivers with missing
 | 
			
		||||
      // DMD_EXTENSION; so let's check for them here and handle
 | 
			
		||||
      // them appropriately
 | 
			
		||||
 | 
			
		||||
      // USGS DEMs use "*.dem"
 | 
			
		||||
      if (myGdalDriverDescription.startsWith("USGSDEM"))
 | 
			
		||||
      {
 | 
			
		||||
        QString glob = "*.dem"; 
 | 
			
		||||
        theFileFiltersString += myGdalDriverLongName + " (" + glob.lower() + " " + glob.upper() + ");;";
 | 
			
		||||
      }
 | 
			
		||||
      else if (myGdalDriverDescription.startsWith("DTED"))
 | 
			
		||||
      {
 | 
			
		||||
        // DTED use "*.dt0"
 | 
			
		||||
        QString glob = "*.dt0"; 
 | 
			
		||||
        theFileFiltersString += myGdalDriverLongName + " (" + glob.lower() + " " + glob.upper() + ");;";
 | 
			
		||||
      } 
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
        catchallFilter += QString(myGdalDriver->GetDescription()) + " ";
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    myGdalDriverExtension = myGdalDriverLongName = "";  // reset for next driver
 | 
			
		||||
 | 
			
		||||
  }                           // each loaded GDAL driver
 | 
			
		||||
 | 
			
		||||
  // can't forget the default case
 | 
			
		||||
  theFileFiltersString += catchallFilter + "All other files (*)";
 | 
			
		||||
#ifdef QGISDEBUG
 | 
			
		||||
  std::cout << "Raster filter list built: " << theFileFiltersString << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
}                               // buildSupportedRasterFileFilter_()
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  returns true if the given raster driver name is one currently
 | 
			
		||||
  supported, otherwise it returns false
 | 
			
		||||
 | 
			
		||||
  @param theDriverName GDAL driver description string
 | 
			
		||||
  */
 | 
			
		||||
bool QgsRasterLayer::isSupportedRasterDriver(QString const &theDriverName)
 | 
			
		||||
{
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
 | 
			
		||||
  while (mSupportedRasterFormats[i][0]) // while not end of string list
 | 
			
		||||
  {
 | 
			
		||||
    // If we've got a case-insensitive match for a GDAL aware driver
 | 
			
		||||
    // description, then we've got a match.  Why case-insensitive?
 | 
			
		||||
    // I'm just being paranoid in that I can envision a situation
 | 
			
		||||
    // whereby GDAL slightly changes driver description string case,
 | 
			
		||||
    // in which case we'd catch it here.  Not that that would likely
 | 
			
		||||
    // happen, but if it does, we'll already compensate.
 | 
			
		||||
    // GS - At Qt 3.1.2, the case sensitive argument. So we change the
 | 
			
		||||
    // driverName to lower case before testing
 | 
			
		||||
    QString format = mSupportedRasterFormats[i];
 | 
			
		||||
    if (theDriverName.lower().startsWith(format.lower()))
 | 
			
		||||
    {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    i++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}   // isSupportedRasterDriver
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** This helper checks to see whether the filename appears to be a valid raster file name */
 | 
			
		||||
bool QgsRasterLayer::isValidRasterFileName(QString theFileNameQString)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  GDALDatasetH myDataset;
 | 
			
		||||
  GDALAllRegister();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  myDataset = GDALOpen( theFileNameQString, GA_ReadOnly );
 | 
			
		||||
 | 
			
		||||
  if( myDataset == NULL )
 | 
			
		||||
  {
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    GDALClose(myDataset);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * This way is no longer a good idea because it does not
 | 
			
		||||
   * cater for filetypes such as grass rasters that dont
 | 
			
		||||
   * have a predictable file extension.
 | 
			
		||||
   * 
 | 
			
		||||
   QString name = theFileNameQString.lower();
 | 
			
		||||
   return (name.endsWith(".adf") ||
 | 
			
		||||
   name.endsWith(".asc") ||
 | 
			
		||||
   name.endsWith(".grd") ||
 | 
			
		||||
   name.endsWith(".img") ||
 | 
			
		||||
   name.endsWith(".tif") || 
 | 
			
		||||
   name.endsWith(".png") || 
 | 
			
		||||
   name.endsWith(".jpg") || 
 | 
			
		||||
   name.endsWith(".dem") || 
 | 
			
		||||
   name.endsWith(".ddf")) ||
 | 
			
		||||
   name.endsWith(".dt0");
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Overloaded of the above function provided for convenience that takes a qstring pointer */
 | 
			
		||||
bool QgsRasterLayer::isValidRasterFileName(QString * theFileNameQString)
 | 
			
		||||
{
 | 
			
		||||
  //dereference and delegate
 | 
			
		||||
  return isValidRasterFileName(*theFileNameQString);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// Non Static methods now....
 | 
			
		||||
//
 | 
			
		||||
/////////////////////////////////////////////////////////
 | 
			
		||||
QgsRasterLayer::QgsRasterLayer(QString path, QString baseName):QgsMapLayer(RASTER, baseName, path)
 | 
			
		||||
{
 | 
			
		||||
  //we need to do the tr() stuff outside of the loop becauses tr() is a
 | 
			
		||||
@ -395,13 +677,13 @@ QPixmap QgsRasterLayer::getPaletteAsPixmap()
 | 
			
		||||
  if (hasBand("Palette")) //dont tr() this its a gdal word!
 | 
			
		||||
  {
 | 
			
		||||
#ifdef QGISDEBUG
 | 
			
		||||
  std::cout << "....found paletted image" << std::endl;
 | 
			
		||||
    std::cout << "....found paletted image" << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
    GDALRasterBandH myGdalBand = gdalDataset->GetRasterBand(1);
 | 
			
		||||
    if( GDALGetRasterColorInterpretation(myGdalBand) == GCI_PaletteIndex )
 | 
			
		||||
    {
 | 
			
		||||
#ifdef QGISDEBUG
 | 
			
		||||
  std::cout << "....found GCI_PaletteIndex" << std::endl;
 | 
			
		||||
      std::cout << "....found GCI_PaletteIndex" << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
      GDALColorTableH myTable;
 | 
			
		||||
      myTable = GDALGetRasterColorTable( myGdalBand );
 | 
			
		||||
@ -437,7 +719,7 @@ QPixmap QgsRasterLayer::getPaletteAsPixmap()
 | 
			
		||||
        GDALColorEntry myEntry;
 | 
			
		||||
        GDALGetColorEntryAsRGB( myTable, myIteratorInt, &myEntry );
 | 
			
		||||
        myQImage.setPixel(myIteratorInt % myWidth,(int)(myIteratorInt/myWidth)
 | 
			
		||||
                          ,qRgba(myEntry.c1, myEntry.c2, myEntry.c3, myEntry.c4));
 | 
			
		||||
                ,qRgba(myEntry.c1, myEntry.c2, myEntry.c3, myEntry.c4));
 | 
			
		||||
      }
 | 
			
		||||
      myQPainter.drawImage(0,0,myQImage);
 | 
			
		||||
      return myPalettePixmap; 
 | 
			
		||||
@ -487,7 +769,7 @@ void QgsRasterLayer::draw(QPainter * theQPainter, QgsRect * theViewExtent, QgsCo
 | 
			
		||||
  myRasterViewPort->rectYOffsetInt = static_cast < int >((layerExtent.yMax() - theViewExtent->yMax()) / fabs(adfGeoTransform[5]));
 | 
			
		||||
  if (myRasterViewPort->rectYOffsetInt < 0)
 | 
			
		||||
  {
 | 
			
		||||
     myRasterViewPort->rectYOffsetInt = 0;
 | 
			
		||||
    myRasterViewPort->rectYOffsetInt = 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //std::cout << "Nodata value for band " << i << " is " << noDataDouble << "\n" << std::endl;
 | 
			
		||||
@ -508,7 +790,7 @@ void QgsRasterLayer::draw(QPainter * theQPainter, QgsRect * theViewExtent, QgsCo
 | 
			
		||||
  // make sure we don't exceed size of raster
 | 
			
		||||
  if (myRasterViewPort->clippedWidthInt > rasterXDimInt)
 | 
			
		||||
  {
 | 
			
		||||
     myRasterViewPort->clippedWidthInt = rasterXDimInt;
 | 
			
		||||
    myRasterViewPort->clippedWidthInt = rasterXDimInt;
 | 
			
		||||
  }
 | 
			
		||||
  if (myRasterViewPort->clippedHeightInt > rasterYDimInt) 
 | 
			
		||||
  {
 | 
			
		||||
@ -1570,51 +1852,51 @@ const bool QgsRasterLayer::hasStats(int theBandNoInt)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
/** Private method to calculate statistics for a band. Populates rasterStatsMemArray.
 | 
			
		||||
    Note that this is a cpu intensive /slow task!*/
 | 
			
		||||
  Note that this is a cpu intensive /slow task!*/
 | 
			
		||||
const RasterBandStats QgsRasterLayer::getRasterBandStats(int theBandNoInt)
 | 
			
		||||
{
 | 
			
		||||
emit setStatus(QString("Calculating stats for ")+layerName);
 | 
			
		||||
//reset the main app progress bar
 | 
			
		||||
emit setProgress(0,0);
 | 
			
		||||
  emit setStatus(QString("Calculating stats for ")+layerName);
 | 
			
		||||
  //reset the main app progress bar
 | 
			
		||||
  emit setProgress(0,0);
 | 
			
		||||
#ifdef QGISDEBUG
 | 
			
		||||
    std::cout << "QgsRasterLayer::calculate stats for band " << theBandNoInt << std::endl;
 | 
			
		||||
  std::cout << "QgsRasterLayer::calculate stats for band " << theBandNoInt << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
    //check if we have received a valid band number
 | 
			
		||||
    if ((gdalDataset->GetRasterCount() < theBandNoInt) && rasterLayerType != PALETTE)
 | 
			
		||||
    {
 | 
			
		||||
        //invalid band id, return nothing
 | 
			
		||||
        RasterBandStats myNullReturnStats;
 | 
			
		||||
        return myNullReturnStats;
 | 
			
		||||
    }
 | 
			
		||||
    if (rasterLayerType == PALETTE && (theBandNoInt > 3))
 | 
			
		||||
    {
 | 
			
		||||
        //invalid band id, return nothing
 | 
			
		||||
        RasterBandStats myNullReturnStats;
 | 
			
		||||
        return myNullReturnStats;
 | 
			
		||||
    }
 | 
			
		||||
    //check if we have previously gathered stats for this band...
 | 
			
		||||
  //check if we have received a valid band number
 | 
			
		||||
  if ((gdalDataset->GetRasterCount() < theBandNoInt) && rasterLayerType != PALETTE)
 | 
			
		||||
  {
 | 
			
		||||
    //invalid band id, return nothing
 | 
			
		||||
    RasterBandStats myNullReturnStats;
 | 
			
		||||
    return myNullReturnStats;
 | 
			
		||||
  }
 | 
			
		||||
  if (rasterLayerType == PALETTE && (theBandNoInt > 3))
 | 
			
		||||
  {
 | 
			
		||||
    //invalid band id, return nothing
 | 
			
		||||
    RasterBandStats myNullReturnStats;
 | 
			
		||||
    return myNullReturnStats;
 | 
			
		||||
  }
 | 
			
		||||
  //check if we have previously gathered stats for this band...
 | 
			
		||||
 | 
			
		||||
    RasterBandStats myRasterBandStats = rasterStatsVector[theBandNoInt - 1];
 | 
			
		||||
    myRasterBandStats.bandNoInt = theBandNoInt;
 | 
			
		||||
    //dont bother with this if we already have stats
 | 
			
		||||
    if (myRasterBandStats.statsGatheredFlag)
 | 
			
		||||
    {
 | 
			
		||||
        return myRasterBandStats;
 | 
			
		||||
    }
 | 
			
		||||
    GDALRasterBand *myGdalBand = gdalDataset->GetRasterBand(theBandNoInt);
 | 
			
		||||
    QString myColorInterpretation = GDALGetColorInterpretationName(myGdalBand->GetColorInterpretation());
 | 
			
		||||
  RasterBandStats myRasterBandStats = rasterStatsVector[theBandNoInt - 1];
 | 
			
		||||
  myRasterBandStats.bandNoInt = theBandNoInt;
 | 
			
		||||
  //dont bother with this if we already have stats
 | 
			
		||||
  if (myRasterBandStats.statsGatheredFlag)
 | 
			
		||||
  {
 | 
			
		||||
    return myRasterBandStats;
 | 
			
		||||
  }
 | 
			
		||||
  GDALRasterBand *myGdalBand = gdalDataset->GetRasterBand(theBandNoInt);
 | 
			
		||||
  QString myColorInterpretation = GDALGetColorInterpretationName(myGdalBand->GetColorInterpretation());
 | 
			
		||||
 | 
			
		||||
    //declare a colorTable to hold a palette - will only be used if the layer color interp is palette
 | 
			
		||||
    GDALColorTable *colorTable;
 | 
			
		||||
    if (rasterLayerType == PALETTE)
 | 
			
		||||
  //declare a colorTable to hold a palette - will only be used if the layer color interp is palette
 | 
			
		||||
  GDALColorTable *colorTable;
 | 
			
		||||
  if (rasterLayerType == PALETTE)
 | 
			
		||||
  {
 | 
			
		||||
    //get the palette colour table
 | 
			
		||||
    colorTable = myGdalBand->GetColorTable();
 | 
			
		||||
    //override the band name - palette images are really only one band
 | 
			
		||||
    //so we are faking three band behaviour
 | 
			
		||||
    switch (theBandNoInt)
 | 
			
		||||
    {
 | 
			
		||||
        //get the palette colour table
 | 
			
		||||
        colorTable = myGdalBand->GetColorTable();
 | 
			
		||||
        //override the band name - palette images are really only one band
 | 
			
		||||
        //so we are faking three band behaviour
 | 
			
		||||
        switch (theBandNoInt)
 | 
			
		||||
        {
 | 
			
		||||
            // a "Red" layer
 | 
			
		||||
      // a "Red" layer
 | 
			
		||||
        case 1:
 | 
			
		||||
            myRasterBandStats.bandName = redTranslatedQString;
 | 
			
		||||
            break;
 | 
			
		||||
@ -1629,151 +1911,151 @@ emit setProgress(0,0);
 | 
			
		||||
            RasterBandStats myNullReturnStats;
 | 
			
		||||
            return myNullReturnStats;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else if (rasterLayerType==GRAY_OR_UNDEFINED)
 | 
			
		||||
  {
 | 
			
		||||
    myRasterBandStats.bandName = myColorInterpretation;
 | 
			
		||||
  }
 | 
			
		||||
  else //rasterLayerType is MULTIBAND
 | 
			
		||||
  {
 | 
			
		||||
    //do nothing
 | 
			
		||||
  }
 | 
			
		||||
  myRasterBandStats.elementCountInt = rasterXDimInt * rasterYDimInt;
 | 
			
		||||
 | 
			
		||||
  //allocate a buffer to hold one row of ints
 | 
			
		||||
  int myAllocationSizeInt = sizeof(uint) * rasterXDimInt;
 | 
			
		||||
  uint *myScanlineAllocInt = (uint *) CPLMalloc(myAllocationSizeInt);
 | 
			
		||||
  bool myFirstIterationFlag = true;
 | 
			
		||||
  //unfortunately we need to make two passes through the data to calculate stddev
 | 
			
		||||
  for (int myCurrentRowInt = 0; myCurrentRowInt < rasterYDimInt; myCurrentRowInt++)
 | 
			
		||||
  {
 | 
			
		||||
    //we loop through the dataset twice for stats so ydim is doubled!
 | 
			
		||||
    emit setProgress(myCurrentRowInt,rasterYDimInt*2);
 | 
			
		||||
    CPLErr myResult =
 | 
			
		||||
        myGdalBand->RasterIO(GF_Read, 0, myCurrentRowInt, rasterXDimInt, 1, myScanlineAllocInt, rasterXDimInt, 1, GDT_UInt32, 0, 0);
 | 
			
		||||
    for (int myCurrentColInt = 0; myCurrentColInt < rasterXDimInt; myCurrentColInt++)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
      double myDouble = 0;
 | 
			
		||||
      //get the nth element from the current row
 | 
			
		||||
      if (myColorInterpretation != "Palette") //dont translate this its a gdal string
 | 
			
		||||
      {
 | 
			
		||||
        myDouble = myScanlineAllocInt[myCurrentColInt];
 | 
			
		||||
      } else
 | 
			
		||||
      {
 | 
			
		||||
        //this is a palette layer so red / green / blue 'layers are 'virtual'
 | 
			
		||||
        //in that we need to obtain the palette entry and then get the r,g or g
 | 
			
		||||
        //component from that palette entry
 | 
			
		||||
        const GDALColorEntry *myColorEntry = GDALGetColorEntry(colorTable, myScanlineAllocInt[myCurrentColInt]);
 | 
			
		||||
        //check colorEntry is valid
 | 
			
		||||
        if (myColorEntry != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          //check for alternate color mappings
 | 
			
		||||
          if (theBandNoInt == 1)  //"Red"
 | 
			
		||||
          {
 | 
			
		||||
            myDouble = static_cast < double >(myColorEntry->c1);
 | 
			
		||||
          }
 | 
			
		||||
          if (theBandNoInt == 2)  //"Green"
 | 
			
		||||
          {
 | 
			
		||||
            myDouble = static_cast < double >(myColorEntry->c2);
 | 
			
		||||
          }
 | 
			
		||||
          if (theBandNoInt == 3)  //"Blue"
 | 
			
		||||
          {
 | 
			
		||||
            myDouble = static_cast < double >(myColorEntry->c3);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if (rasterLayerType==GRAY_OR_UNDEFINED)
 | 
			
		||||
    {
 | 
			
		||||
        myRasterBandStats.bandName = myColorInterpretation;
 | 
			
		||||
    }
 | 
			
		||||
    else //rasterLayerType is MULTIBAND
 | 
			
		||||
    {
 | 
			
		||||
        //do nothing
 | 
			
		||||
    }
 | 
			
		||||
    myRasterBandStats.elementCountInt = rasterXDimInt * rasterYDimInt;
 | 
			
		||||
 | 
			
		||||
    //allocate a buffer to hold one row of ints
 | 
			
		||||
    int myAllocationSizeInt = sizeof(uint) * rasterXDimInt;
 | 
			
		||||
    uint *myScanlineAllocInt = (uint *) CPLMalloc(myAllocationSizeInt);
 | 
			
		||||
    bool myFirstIterationFlag = true;
 | 
			
		||||
    //unfortunately we need to make two passes through the data to calculate stddev
 | 
			
		||||
    for (int myCurrentRowInt = 0; myCurrentRowInt < rasterYDimInt; myCurrentRowInt++)
 | 
			
		||||
    {
 | 
			
		||||
       //we loop through the dataset twice for stats so ydim is doubled!
 | 
			
		||||
       emit setProgress(myCurrentRowInt,rasterYDimInt*2);
 | 
			
		||||
        CPLErr myResult =
 | 
			
		||||
            myGdalBand->RasterIO(GF_Read, 0, myCurrentRowInt, rasterXDimInt, 1, myScanlineAllocInt, rasterXDimInt, 1, GDT_UInt32, 0, 0);
 | 
			
		||||
        for (int myCurrentColInt = 0; myCurrentColInt < rasterXDimInt; myCurrentColInt++)
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      //only use this element if we have a non null element
 | 
			
		||||
      if (myDouble != noDataValueDouble)
 | 
			
		||||
      {
 | 
			
		||||
        if (myFirstIterationFlag)
 | 
			
		||||
        {
 | 
			
		||||
	
 | 
			
		||||
            double myDouble = 0;
 | 
			
		||||
            //get the nth element from the current row
 | 
			
		||||
            if (myColorInterpretation != "Palette") //dont translate this its a gdal string
 | 
			
		||||
            {
 | 
			
		||||
                myDouble = myScanlineAllocInt[myCurrentColInt];
 | 
			
		||||
            } else
 | 
			
		||||
            {
 | 
			
		||||
                //this is a palette layer so red / green / blue 'layers are 'virtual'
 | 
			
		||||
                //in that we need to obtain the palette entry and then get the r,g or g
 | 
			
		||||
                //component from that palette entry
 | 
			
		||||
                const GDALColorEntry *myColorEntry = GDALGetColorEntry(colorTable, myScanlineAllocInt[myCurrentColInt]);
 | 
			
		||||
                //check colorEntry is valid
 | 
			
		||||
                if (myColorEntry != NULL)
 | 
			
		||||
                {
 | 
			
		||||
                    //check for alternate color mappings
 | 
			
		||||
                    if (theBandNoInt == 1)  //"Red"
 | 
			
		||||
                    {
 | 
			
		||||
                        myDouble = static_cast < double >(myColorEntry->c1);
 | 
			
		||||
                    }
 | 
			
		||||
                    if (theBandNoInt == 2)  //"Green"
 | 
			
		||||
                    {
 | 
			
		||||
                        myDouble = static_cast < double >(myColorEntry->c2);
 | 
			
		||||
                    }
 | 
			
		||||
                    if (theBandNoInt == 3)  //"Blue"
 | 
			
		||||
                    {
 | 
			
		||||
                        myDouble = static_cast < double >(myColorEntry->c3);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            //only use this element if we have a non null element
 | 
			
		||||
            if (myDouble != noDataValueDouble)
 | 
			
		||||
            {
 | 
			
		||||
                if (myFirstIterationFlag)
 | 
			
		||||
                {
 | 
			
		||||
                    //this is the first iteration so initialise vars
 | 
			
		||||
                    myFirstIterationFlag = false;
 | 
			
		||||
                    myRasterBandStats.minValDouble = myDouble;
 | 
			
		||||
                    myRasterBandStats.maxValDouble = myDouble;
 | 
			
		||||
                }               //end of true part for first iteration check
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    //this is done for all subsequent iterations
 | 
			
		||||
                    if (myDouble < myRasterBandStats.minValDouble)
 | 
			
		||||
                    {
 | 
			
		||||
                        myRasterBandStats.minValDouble = myDouble;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (myDouble > myRasterBandStats.maxValDouble)
 | 
			
		||||
                    {
 | 
			
		||||
                        myRasterBandStats.maxValDouble = myDouble;
 | 
			
		||||
                    }
 | 
			
		||||
                    //only increment the running total if it is not a nodata value
 | 
			
		||||
                    if (myDouble != noDataValueDouble)
 | 
			
		||||
                    {
 | 
			
		||||
                        myRasterBandStats.sumDouble += myDouble;
 | 
			
		||||
                        ++myRasterBandStats.elementCountInt;
 | 
			
		||||
                    }
 | 
			
		||||
                }               //end of false part for first iteration check
 | 
			
		||||
            }                   //end of nodata chec
 | 
			
		||||
        }                       //end of column wise loop
 | 
			
		||||
    }                           //end of row wise loop
 | 
			
		||||
    //
 | 
			
		||||
    //end of first pass through data now calculate the range
 | 
			
		||||
    myRasterBandStats.rangeDouble = myRasterBandStats.maxValDouble - myRasterBandStats.minValDouble;
 | 
			
		||||
    //calculate the mean
 | 
			
		||||
    myRasterBandStats.meanDouble = myRasterBandStats.sumDouble / myRasterBandStats.elementCountInt;
 | 
			
		||||
    //for the second pass we will get the sum of the squares / mean
 | 
			
		||||
    for (int myCurrentRowInt = 0; myCurrentRowInt < rasterYDimInt; myCurrentRowInt++)
 | 
			
		||||
    {
 | 
			
		||||
        //we loop through the dataset twice for stats so ydim is doubled (this is loop2)!
 | 
			
		||||
        emit setProgress(myCurrentRowInt+rasterYDimInt,rasterYDimInt*2);
 | 
			
		||||
        CPLErr myResult =
 | 
			
		||||
            myGdalBand->RasterIO(GF_Read, 0, myCurrentRowInt, rasterXDimInt, 1, myScanlineAllocInt, rasterXDimInt, 1, GDT_UInt32, 0, 0);
 | 
			
		||||
        for (int myCurrentColInt = 0; myCurrentColInt < rasterXDimInt; myCurrentColInt++)
 | 
			
		||||
          //this is the first iteration so initialise vars
 | 
			
		||||
          myFirstIterationFlag = false;
 | 
			
		||||
          myRasterBandStats.minValDouble = myDouble;
 | 
			
		||||
          myRasterBandStats.maxValDouble = myDouble;
 | 
			
		||||
        }               //end of true part for first iteration check
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            double myDouble = 0;
 | 
			
		||||
            //get the nth element from the current row
 | 
			
		||||
            if (myColorInterpretation != "Palette") //dont translate this its a gdal string
 | 
			
		||||
            {
 | 
			
		||||
                myDouble = myScanlineAllocInt[myCurrentColInt];
 | 
			
		||||
            } else
 | 
			
		||||
            {
 | 
			
		||||
                //this is a palette layer so red / green / blue 'layers are 'virtual'
 | 
			
		||||
                //in that we need to obtain the palette entry and then get the r,g or g
 | 
			
		||||
                //component from that palette entry
 | 
			
		||||
                const GDALColorEntry *myColorEntry = GDALGetColorEntry(colorTable, myScanlineAllocInt[myCurrentColInt]);
 | 
			
		||||
                //check colorEntry is valid
 | 
			
		||||
                if (myColorEntry != NULL)
 | 
			
		||||
                {
 | 
			
		||||
                    //check for alternate color mappings
 | 
			
		||||
                    if (theBandNoInt == 1)  //red
 | 
			
		||||
                    {
 | 
			
		||||
                        myDouble = myColorEntry->c1;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (theBandNoInt == 1)  //green
 | 
			
		||||
                    {
 | 
			
		||||
                        myDouble = myColorEntry->c2;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (theBandNoInt == 3)  //blue
 | 
			
		||||
                    {
 | 
			
		||||
                        myDouble = myColorEntry->c3;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
          //this is done for all subsequent iterations
 | 
			
		||||
          if (myDouble < myRasterBandStats.minValDouble)
 | 
			
		||||
          {
 | 
			
		||||
            myRasterBandStats.minValDouble = myDouble;
 | 
			
		||||
          }
 | 
			
		||||
          if (myDouble > myRasterBandStats.maxValDouble)
 | 
			
		||||
          {
 | 
			
		||||
            myRasterBandStats.maxValDouble = myDouble;
 | 
			
		||||
          }
 | 
			
		||||
          //only increment the running total if it is not a nodata value
 | 
			
		||||
          if (myDouble != noDataValueDouble)
 | 
			
		||||
          {
 | 
			
		||||
            myRasterBandStats.sumDouble += myDouble;
 | 
			
		||||
            ++myRasterBandStats.elementCountInt;
 | 
			
		||||
          }
 | 
			
		||||
        }               //end of false part for first iteration check
 | 
			
		||||
      }                   //end of nodata chec
 | 
			
		||||
    }                       //end of column wise loop
 | 
			
		||||
  }                           //end of row wise loop
 | 
			
		||||
  //
 | 
			
		||||
  //end of first pass through data now calculate the range
 | 
			
		||||
  myRasterBandStats.rangeDouble = myRasterBandStats.maxValDouble - myRasterBandStats.minValDouble;
 | 
			
		||||
  //calculate the mean
 | 
			
		||||
  myRasterBandStats.meanDouble = myRasterBandStats.sumDouble / myRasterBandStats.elementCountInt;
 | 
			
		||||
  //for the second pass we will get the sum of the squares / mean
 | 
			
		||||
  for (int myCurrentRowInt = 0; myCurrentRowInt < rasterYDimInt; myCurrentRowInt++)
 | 
			
		||||
  {
 | 
			
		||||
    //we loop through the dataset twice for stats so ydim is doubled (this is loop2)!
 | 
			
		||||
    emit setProgress(myCurrentRowInt+rasterYDimInt,rasterYDimInt*2);
 | 
			
		||||
    CPLErr myResult =
 | 
			
		||||
        myGdalBand->RasterIO(GF_Read, 0, myCurrentRowInt, rasterXDimInt, 1, myScanlineAllocInt, rasterXDimInt, 1, GDT_UInt32, 0, 0);
 | 
			
		||||
    for (int myCurrentColInt = 0; myCurrentColInt < rasterXDimInt; myCurrentColInt++)
 | 
			
		||||
    {
 | 
			
		||||
      double myDouble = 0;
 | 
			
		||||
      //get the nth element from the current row
 | 
			
		||||
      if (myColorInterpretation != "Palette") //dont translate this its a gdal string
 | 
			
		||||
      {
 | 
			
		||||
        myDouble = myScanlineAllocInt[myCurrentColInt];
 | 
			
		||||
      } else
 | 
			
		||||
      {
 | 
			
		||||
        //this is a palette layer so red / green / blue 'layers are 'virtual'
 | 
			
		||||
        //in that we need to obtain the palette entry and then get the r,g or g
 | 
			
		||||
        //component from that palette entry
 | 
			
		||||
        const GDALColorEntry *myColorEntry = GDALGetColorEntry(colorTable, myScanlineAllocInt[myCurrentColInt]);
 | 
			
		||||
        //check colorEntry is valid
 | 
			
		||||
        if (myColorEntry != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          //check for alternate color mappings
 | 
			
		||||
          if (theBandNoInt == 1)  //red
 | 
			
		||||
          {
 | 
			
		||||
            myDouble = myColorEntry->c1;
 | 
			
		||||
          }
 | 
			
		||||
          if (theBandNoInt == 1)  //green
 | 
			
		||||
          {
 | 
			
		||||
            myDouble = myColorEntry->c2;
 | 
			
		||||
          }
 | 
			
		||||
          if (theBandNoInt == 3)  //blue
 | 
			
		||||
          {
 | 
			
		||||
            myDouble = myColorEntry->c3;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            myRasterBandStats.sumSqrDevDouble += static_cast < double >(pow(myDouble - myRasterBandStats.meanDouble, 2));
 | 
			
		||||
        }                       //end of column wise loop
 | 
			
		||||
    }                           //end of row wise loop
 | 
			
		||||
    //divide result by sample size - 1 and get square root to get stdev
 | 
			
		||||
    myRasterBandStats.stdDevDouble = static_cast < double >(sqrt(myRasterBandStats.sumSqrDevDouble /
 | 
			
		||||
                                     (myRasterBandStats.elementCountInt - 1)));
 | 
			
		||||
    CPLFree(myScanlineAllocInt);
 | 
			
		||||
    myRasterBandStats.statsGatheredFlag = true;
 | 
			
		||||
    //add this band to the class stats map
 | 
			
		||||
    rasterStatsVector[theBandNoInt - 1] = myRasterBandStats;
 | 
			
		||||
    emit setProgress(rasterYDimInt, rasterYDimInt); //reset progress
 | 
			
		||||
    return myRasterBandStats;
 | 
			
		||||
      }
 | 
			
		||||
      myRasterBandStats.sumSqrDevDouble += static_cast < double >(pow(myDouble - myRasterBandStats.meanDouble, 2));
 | 
			
		||||
    }                       //end of column wise loop
 | 
			
		||||
  }                           //end of row wise loop
 | 
			
		||||
  //divide result by sample size - 1 and get square root to get stdev
 | 
			
		||||
  myRasterBandStats.stdDevDouble = static_cast < double >(sqrt(myRasterBandStats.sumSqrDevDouble /
 | 
			
		||||
              (myRasterBandStats.elementCountInt - 1)));
 | 
			
		||||
  CPLFree(myScanlineAllocInt);
 | 
			
		||||
  myRasterBandStats.statsGatheredFlag = true;
 | 
			
		||||
  //add this band to the class stats map
 | 
			
		||||
  rasterStatsVector[theBandNoInt - 1] = myRasterBandStats;
 | 
			
		||||
  emit setProgress(rasterYDimInt, rasterYDimInt); //reset progress
 | 
			
		||||
  return myRasterBandStats;
 | 
			
		||||
}                               //end of getRasterBandStats
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2230,7 +2512,7 @@ void QgsRasterLayer::setTransparency(int theInt)
 | 
			
		||||
#endif
 | 
			
		||||
  mTransparencySlider->setValue(255-theInt);
 | 
			
		||||
  //delegate rest to transparency slider
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
unsigned int QgsRasterLayer::getTransparency()
 | 
			
		||||
{
 | 
			
		||||
@ -2257,10 +2539,10 @@ QString QgsRasterLayer::getMetadata()
 | 
			
		||||
  myMetadataQString += tr("X: ") + QString::number(gdalDataset->GetRasterXSize()) +
 | 
			
		||||
      tr(" Y: ") + QString::number(gdalDataset->GetRasterYSize()) + tr(" Bands: ") + QString::number(gdalDataset->GetRasterCount());
 | 
			
		||||
  myMetadataQString += "</td></tr>";
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  //just use the first band
 | 
			
		||||
  GDALRasterBand *myGdalBand = gdalDataset->GetRasterBand(1);
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  myMetadataQString += "<tr><td bgcolor=\"gray\">";
 | 
			
		||||
  myMetadataQString += tr("Data Type:");
 | 
			
		||||
  myMetadataQString += "</td></tr>";
 | 
			
		||||
@ -2304,7 +2586,7 @@ QString QgsRasterLayer::getMetadata()
 | 
			
		||||
          myMetadataQString += tr("Could not determine raster data type.");
 | 
			
		||||
  }
 | 
			
		||||
  myMetadataQString += "</td></tr>";
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  myMetadataQString += "<tr><td bgcolor=\"gray\">";
 | 
			
		||||
  myMetadataQString += tr("Pyramid overviews:");
 | 
			
		||||
  myMetadataQString += "</td></tr>";
 | 
			
		||||
 | 
			
		||||
@ -314,6 +314,21 @@ class QgsRasterLayer : public QgsMapLayer
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
    //
 | 
			
		||||
    // Static methods:
 | 
			
		||||
    //
 | 
			
		||||
        
 | 
			
		||||
    static void buildSupportedRasterFileFilter(QString & fileFilters);
 | 
			
		||||
    static bool isSupportedRasterDriver(QString const &driverName);
 | 
			
		||||
    /** This helper checks to see whether the filename appears to be a valid raster file name */
 | 
			
		||||
    static bool isValidRasterFileName(QString theFileNameQString);
 | 
			
		||||
    /** Overloaded version of the above function provided for convenience that takes a qstring pointer */
 | 
			
		||||
    static bool isValidRasterFileName(QString * theFileNameQString);
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // Non Static methods:
 | 
			
		||||
    //
 | 
			
		||||
        
 | 
			
		||||
    /** \brief This is the constructor for the RasterLayer class.
 | 
			
		||||
     *
 | 
			
		||||
     * The main tasks carried out by the constructor are:
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user