[QGIS Commit] r13072 - in trunk/qgis: python/core src/app/legend src/core

svn_qgis at osgeo.org svn_qgis at osgeo.org
Thu Mar 18 18:24:19 EDT 2010


Author: mhugent
Date: 2010-03-18 18:24:18 -0400 (Thu, 18 Mar 2010)
New Revision: 13072

Modified:
   trunk/qgis/python/core/qgsvectorfilewriter.sip
   trunk/qgis/src/app/legend/qgslegendlayer.cpp
   trunk/qgis/src/app/legend/qgslegendlayer.h
   trunk/qgis/src/core/qgsvectorfilewriter.cpp
   trunk/qgis/src/core/qgsvectorfilewriter.h
Log:
Apply patch #2452 (save as vector)

Modified: trunk/qgis/python/core/qgsvectorfilewriter.sip
===================================================================
--- trunk/qgis/python/core/qgsvectorfilewriter.sip	2010-03-18 18:12:04 UTC (rev 13071)
+++ trunk/qgis/python/core/qgsvectorfilewriter.sip	2010-03-18 22:24:18 UTC (rev 13072)
@@ -31,13 +31,32 @@
                                         const QgsCoordinateReferenceSystem*,
                                         bool onlySelected = FALSE);
 
+    /** Write contents of vector layer to an (OGR supported) vector formt
+        @note: this method was added in version 1.5*/
+    static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
+                                            const QString& fileName,
+                                            const QString& fileEncoding,
+                                            const QgsCoordinateReferenceSystem *destCRS,
+                                            const QString& driverName = "ESRI Shapefile",
+                                            bool onlySelected = FALSE,
+                                            QString *errorMessage = 0 );
+
     /** create shapefile and initialize it */
-    QgsVectorFileWriter(const QString& shapefileName,
+    QgsVectorFileWriter(const QString& vectorFileName,
                         const QString& fileEncoding,
                         const QMap<int, QgsField>& fields,
                         QGis::WkbType geometryType,
                         const QgsCoordinateReferenceSystem* srs,
 			const QString& driverName = "ESRI Shapefile" );
+
+    /**Returns map with format filter string as key and OGR format key as value*/
+    static QMap< QString, QString> supportedFiltersAndFormats();
+
+    /**Returns filter string that can be used for dialogs*/
+    static QString fileFilterString();
+
+    /**Creates a filter for an OGR driver key*/
+    static QString filterForDriver( const QString& driverName );
     
     /** checks whether there were any errors in constructor */
     WriterError hasError();

Modified: trunk/qgis/src/app/legend/qgslegendlayer.cpp
===================================================================
--- trunk/qgis/src/app/legend/qgslegendlayer.cpp	2010-03-18 18:12:04 UTC (rev 13071)
+++ trunk/qgis/src/app/legend/qgslegendlayer.cpp	2010-03-18 22:24:18 UTC (rev 13072)
@@ -423,14 +423,14 @@
       }
     }
 
-    // save as shapefile
-    theMenu.addAction( tr( "Save as shapefile..." ), this, SLOT( saveAsShapefile() ) );
+    // save as vector file
+    theMenu.addAction( tr( "Save as..." ), this, SLOT( saveAsVectorFile() ) );
 
-    // save selection as shapefile
-    QAction* saveSelectionAction = theMenu.addAction( tr( "Save selection as shapefile..." ), this, SLOT( saveSelectionAsShapefile() ) );
+    // save selection as vector file
+    QAction* saveSelectionAsAction = theMenu.addAction( tr( "Save selection as..." ), this, SLOT( saveSelectionAsVectorFile() ) );
     if ( vlayer->selectedFeatureCount() == 0 )
     {
-      saveSelectionAction->setEnabled( false );
+      saveSelectionAsAction->setEnabled( false );
     }
 
     theMenu.addSeparator();
@@ -460,6 +460,16 @@
   saveAsShapefileGeneral( TRUE );
 }
 
+void QgsLegendLayer::saveAsVectorFile()
+{
+  saveAsVectorFileGeneral( false );
+}
+
+void QgsLegendLayer::saveSelectionAsVectorFile()
+{
+  saveAsVectorFileGeneral( true );
+}
+
 //////////
 
 void QgsLegendLayer::setVisible( bool visible )
@@ -492,9 +502,83 @@
   legend()->updateOverview();
 }
 
+void QgsLegendLayer::saveAsVectorFileGeneral( bool saveOnlySelection )
+{
+  if ( mLyr.layer()->type() != QgsMapLayer::VectorLayer )
+    return;
 
+  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( mLyr.layer() );
 
+  //get output name and format
+  QSettings settings;
+  QString filter =  QString( "Shapefiles (*.shp)" );
+  QString dirName = settings.value( "/UI/lastVectorfileDir", "." ).toString();
+  QString filterString = QgsVectorFileWriter::fileFilterString();
+  QString selectedFilter = settings.value( "/UI/lastVectorFilter", "[OGR] ESRI Shapefiles (*.shp *.SHP)" ).toString();
+  QString outputFile = QFileDialog::getSaveFileName( 0, tr( "Save layer as..." ), dirName, filterString, &selectedFilter );
+  if ( outputFile.isNull() )
+  {
+    return; //cancelled
+  }
 
+  settings.setValue( "/UI/lastVectorfileDir", QFileInfo( outputFile ).absolutePath() );
+  settings.setValue( "/UI/lastVectorFilter", selectedFilter );
+
+  QMap< QString, QString> filterDriverMap = QgsVectorFileWriter::supportedFiltersAndFormats();
+  QMap< QString, QString>::const_iterator it = filterDriverMap.find( selectedFilter + ";;" );
+  if ( it == filterDriverMap.constEnd() )
+  {
+    return; //unknown format
+  }
+
+  QString driverKey = *it;
+
+  //output CRS
+  QgsCoordinateReferenceSystem destCRS = vlayer->srs();
+  // Find out if we have projections enabled or not
+  if ( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() )
+  {
+    destCRS = QgisApp::instance()->mapCanvas()->mapRenderer()->destinationSrs();
+  }
+
+  QgsGenericProjectionSelector * mySelector = new QgsGenericProjectionSelector();
+  mySelector->setSelectedCrsId( destCRS.srsid() );
+  mySelector->setMessage( tr( "Select the coordinate reference system for the saved shapefile. "
+                              "The data points will be transformed from the layer coordinate reference system." ) );
+
+  if ( mySelector->exec() )
+  {
+    QgsCoordinateReferenceSystem srs( mySelector->selectedCrsId(), QgsCoordinateReferenceSystem::InternalCrsId );
+    destCRS = srs;
+    //   destCRS->createFromId(mySelector->selectedCrsId(), QgsCoordinateReferenceSystem::InternalCrsId)
+  }
+  else
+  {
+    // Aborted CS selection, don't save.
+    delete mySelector;
+    return;
+  }
+  delete mySelector;
+
+  // overwrite the file - user will already have been prompted
+  // to verify they want to overwrite by the file dialog above
+  // might not even exists in the given case.
+  if ( driverKey == "ESRI Shapefile" )
+  {
+    // add the extension if not present
+    if ( !outputFile.endsWith( ".shp", Qt::CaseInsensitive ) )
+    {
+      outputFile += ".shp";
+    }
+    QgsVectorFileWriter::deleteShapeFile( outputFile );
+  }
+
+  QString errorMessage;
+  QgsVectorFileWriter::WriterError error;
+  error = QgsVectorFileWriter::writeAsVectorFormat( vlayer, outputFile, "utf-8", &destCRS, driverKey, saveOnlySelection, &errorMessage );
+}
+
+
 void QgsLegendLayer::saveAsShapefileGeneral( bool saveOnlySelection )
 {
   QgsCoordinateReferenceSystem destCRS;

Modified: trunk/qgis/src/app/legend/qgslegendlayer.h
===================================================================
--- trunk/qgis/src/app/legend/qgslegendlayer.h	2010-03-18 18:12:04 UTC (rev 13071)
+++ trunk/qgis/src/app/legend/qgslegendlayer.h	2010-03-18 22:24:18 UTC (rev 13072)
@@ -87,6 +87,9 @@
     void saveAsShapefile();
     void saveSelectionAsShapefile();
 
+    void saveAsVectorFile();
+    void saveSelectionAsVectorFile();
+
     /**update the layer's icon to show whether is in editing mode or in overview */
     void updateIcon();
 
@@ -111,6 +114,8 @@
     /**Save as shapefile (called from saveAsShapefile and saveSelectionAsShapefile)*/
     void saveAsShapefileGeneral( bool saveOnlySelection );
 
+    void saveAsVectorFileGeneral( bool saveOnlySelection );
+
   private:
     /** Helper method to make the font bold from all ctors.
      *  Not to be confused with setFont() which is inherited

Modified: trunk/qgis/src/core/qgsvectorfilewriter.cpp
===================================================================
--- trunk/qgis/src/core/qgsvectorfilewriter.cpp	2010-03-18 18:12:04 UTC (rev 13071)
+++ trunk/qgis/src/core/qgsvectorfilewriter.cpp	2010-03-18 22:24:18 UTC (rev 13072)
@@ -41,7 +41,7 @@
 #include <cpl_error.h>
 
 
-QgsVectorFileWriter::QgsVectorFileWriter( const QString& shapefileName,
+QgsVectorFileWriter::QgsVectorFileWriter( const QString& vectorFileName,
     const QString& fileEncoding,
     const QgsFieldMap& fields,
     QGis::WkbType geometryType,
@@ -85,7 +85,7 @@
   }
 
   // create the data source
-  mDS = OGR_Dr_CreateDataSource( poDriver, shapefileName.toLocal8Bit().data(), NULL );
+  mDS = OGR_Dr_CreateDataSource( poDriver, vectorFileName.toLocal8Bit().data(), NULL );
   if ( mDS == NULL )
   {
     mError = ErrCreateDataSource;
@@ -121,7 +121,7 @@
   }
 
   // datasource created, now create the output layer
-  QString layerName = shapefileName.left( shapefileName.indexOf( ".shp", Qt::CaseInsensitive ) );
+  QString layerName = QFileInfo( vectorFileName ).baseName();
   OGRwkbGeometryType wkbType = static_cast<OGRwkbGeometryType>( geometryType );
   mLayer = OGR_DS_CreateLayer( mDS, QFile::encodeName( layerName ).data(), ogrRef, wkbType, NULL );
 
@@ -386,7 +386,8 @@
                                        bool onlySelected,
                                        QString *errorMessage )
 {
-
+  return writeAsVectorFormat( layer, shapefileName, fileEncoding, destCRS, "ESRI Shapefile", onlySelected, errorMessage );
+#if 0
   const QgsCoordinateReferenceSystem* outputCRS;
   QgsCoordinateTransform* ct = 0;
   int shallTransform = false;
@@ -471,9 +472,105 @@
   }
 
   return NoError;
+#endif //0
 }
 
+QgsVectorFileWriter::WriterError
+QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
+    const QString& fileName,
+    const QString& fileEncoding,
+    const QgsCoordinateReferenceSystem *destCRS,
+    const QString& driverName,
+    bool onlySelected,
+    QString *errorMessage )
+{
+  const QgsCoordinateReferenceSystem* outputCRS;
+  QgsCoordinateTransform* ct = 0;
+  int shallTransform = false;
 
+  if ( destCRS && destCRS->isValid() )
+  {
+    // This means we should transform
+    outputCRS = destCRS;
+    shallTransform = true;
+  }
+  else
+  {
+    // This means we shouldn't transform, use source CRS as output (if defined)
+    outputCRS = &layer->srs();
+  }
+  QgsVectorFileWriter* writer =
+    new QgsVectorFileWriter( fileName, fileEncoding, layer->pendingFields(), layer->wkbType(), outputCRS, driverName );
+
+  // check whether file creation was successful
+  WriterError err = writer->hasError();
+  if ( err != NoError )
+  {
+    if ( errorMessage )
+      *errorMessage = writer->errorMessage();
+    delete writer;
+    return err;
+  }
+
+  QgsAttributeList allAttr = layer->pendingAllAttributesList();
+  QgsFeature fet;
+
+  layer->select( allAttr, QgsRectangle(), true );
+
+  const QgsFeatureIds& ids = layer->selectedFeaturesIds();
+
+  // Create our transform
+  if ( destCRS )
+  {
+    ct = new QgsCoordinateTransform( layer->srs(), *destCRS );
+  }
+
+  // Check for failure
+  if ( ct == NULL )
+  {
+    shallTransform = false;
+  }
+
+  // write all features
+  while ( layer->nextFeature( fet ) )
+  {
+    if ( onlySelected && !ids.contains( fet.id() ) )
+      continue;
+
+    if ( shallTransform )
+    {
+      try
+      {
+        fet.geometry()->transform( *ct );
+      }
+      catch ( QgsCsException &e )
+      {
+        delete ct;
+        delete writer;
+
+        QString msg = QObject::tr( "Failed to transform a point while drawing a feature of type '%1'. Writing stopped. (Exception: %2)" )
+                      .arg( fet.typeName() ).arg( e.what() );
+        QgsLogger::warning( msg );
+        if ( errorMessage )
+          *errorMessage = msg;
+
+        return ErrProjection;
+      }
+    }
+    writer->addFeature( fet );
+  }
+
+  delete writer;
+
+  if ( shallTransform )
+  {
+    delete ct;
+  }
+
+  return NoError;
+}
+
+
 bool QgsVectorFileWriter::deleteShapeFile( QString theFileName )
 {
   QFileInfo fi( theFileName );
@@ -498,3 +595,157 @@
 
   return ok;
 }
+
+QMap< QString, QString> QgsVectorFileWriter::supportedFiltersAndFormats()
+{
+  QMap<QString, QString> resultMap;
+
+  QgsApplication::registerOgrDrivers();
+  int const drvCount = OGRGetDriverCount();
+
+  QString drvName;
+  QString filterString;
+  for ( int i = 0; i < drvCount; ++i )
+  {
+    OGRSFDriverH drv = OGRGetDriver( i );
+    if ( drv )
+    {
+      drvName = OGR_Dr_GetName( drv );
+      if ( OGR_Dr_TestCapability( drv, ODrCCreateDataSource ) != 0 )
+      {
+        //add driver name and filter to map
+        filterString = QgsVectorFileWriter::filterForDriver( drvName );
+        if ( !filterString.isEmpty() )
+        {
+          resultMap.insert( filterString, drvName );
+        }
+      }
+    }
+  }
+
+  return resultMap;
+}
+
+QString QgsVectorFileWriter::fileFilterString()
+{
+  QString filterString;
+  QMap< QString, QString> driverFormatMap = QgsVectorFileWriter::supportedFiltersAndFormats();
+  QMap< QString, QString>::const_iterator it = driverFormatMap.constBegin();
+  for ( ; it != driverFormatMap.constEnd(); ++it )
+  {
+    filterString += it.key();
+  }
+  return filterString;
+}
+
+QString QgsVectorFileWriter::filterForDriver( const QString& driverName )
+{
+  QString longName;
+  QString glob;
+
+  if ( driverName.startsWith( "AVCE00" ) )
+  {
+    longName = "Arc/Info ASCII Coverage";
+    glob = "*.e00";
+  }
+  else if ( driverName.startsWith( "BNA" ) )
+  {
+    longName = "Atlas BNA";
+    glob = "*.bna";
+  }
+  else if ( driverName.startsWith( "CSV" ) )
+  {
+    longName = "Comma Separated Value";
+    glob = "*.csv";
+  }
+  else if ( driverName.startsWith( "ESRI" ) )
+  {
+    longName = "ESRI Shapefiles";
+    glob = "*.shp";
+  }
+  else if ( driverName.startsWith( "FMEObjects Gateway" ) )
+  {
+    longName = "FMEObjects Gateway";
+    glob = "*.fdd";
+  }
+  else if ( driverName.startsWith( "GeoJSON" ) )
+  {
+    longName = "GeoJSON";
+    glob = "*.geojson";
+  }
+  else if ( driverName.startsWith( "GeoRSS" ) )
+  {
+    longName = "GeoRSS";
+    glob = "*.xml";
+  }
+  else if ( driverName.startsWith( "GML" ) )
+  {
+    longName = "Geography Markup Language";
+    glob = "*.gml";
+  }
+  else if ( driverName.startsWith( "GMT" ) )
+  {
+    longName = "GMT";
+    glob = "*.gmt";
+  }
+  else if ( driverName.startsWith( "GPX" ) )
+  {
+    longName = "GPX";
+    glob = "*.gpx";
+  }
+  else if ( driverName.startsWith( "Interlis 1" ) )
+  {
+    longName = "INTERLIS 1";
+    glob = "*.itf *.xml *.ili";
+  }
+  else if ( driverName.startsWith( "Interlis 2" ) )
+  {
+    longName = "INTERLIS 2";
+    glob = "*.itf *.xml *.ili";
+  }
+  else if ( driverName.startsWith( "KML" ) )
+  {
+    longName = "KML";
+    glob = "*.kml" ;
+  }
+  else if ( driverName.startsWith( "MapInfo File" ) )
+  {
+    longName = "Mapinfo File";
+    glob = "*.mif *.tab";
+  }
+  else if ( driverName.startsWith( "DGN" ) )
+  {
+    longName = "Microstation DGN";
+    glob = "*.dgn";
+  }
+  else if ( driverName.startsWith( "S57" ) )
+  {
+    longName = "S-57 Base file";
+    glob = "*.000";
+  }
+  else if ( driverName.startsWith( "SDTS" ) )
+  {
+    longName = "Spatial Data Transfer Standard";
+    glob = "*catd.ddf";
+  }
+  else if ( driverName.startsWith( "SQLite" ) )
+  {
+    longName = "SQLite";
+    glob = "*.sqlite";
+  }
+  else if ( driverName.startsWith( "VRT" ) )
+  {
+    longName = "VRT - Virtual Datasource ";
+    glob = "*.vrt";
+  }
+  else if ( driverName.startsWith( "XPlane" ) )
+  {
+    longName = "X-Plane/Flighgear";
+    glob = "apt.dat nav.dat fix.dat awy.dat";
+  }
+  else
+  {
+    return QString();
+  }
+  return "[OGR] " + longName + " (" + glob.toLower() + " " + glob.toUpper() + ");;";
+}

Modified: trunk/qgis/src/core/qgsvectorfilewriter.h
===================================================================
--- trunk/qgis/src/core/qgsvectorfilewriter.h	2010-03-18 18:12:04 UTC (rev 13071)
+++ trunk/qgis/src/core/qgsvectorfilewriter.h	2010-03-18 22:24:18 UTC (rev 13072)
@@ -53,7 +53,8 @@
       ErrProjection // added in 1.5
     };
 
-    /** Write contents of vector layer to a shapefile */
+    /** Write contents of vector layer to a shapefile
+        @note: deprecated. Use writeAsVectorFormat instead*/
     static WriterError writeAsShapefile( QgsVectorLayer* layer,
                                          const QString& shapefileName,
                                          const QString& fileEncoding,
@@ -61,14 +62,33 @@
                                          bool onlySelected = FALSE,
                                          QString *errorMessage = 0 );
 
+    /** Write contents of vector layer to an (OGR supported) vector formt
+        @note: this method was added in version 1.5*/
+    static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
+                                            const QString& fileName,
+                                            const QString& fileEncoding,
+                                            const QgsCoordinateReferenceSystem *destCRS,
+                                            const QString& driverName = "ESRI Shapefile",
+                                            bool onlySelected = FALSE,
+                                            QString *errorMessage = 0 );
+
     /** create shapefile and initialize it */
-    QgsVectorFileWriter( const QString& shapefileName,
+    QgsVectorFileWriter( const QString& vectorFileName,
                          const QString& fileEncoding,
                          const QgsFieldMap& fields,
                          QGis::WkbType geometryType,
                          const QgsCoordinateReferenceSystem* srs,
                          const QString& driverName = "ESRI Shapefile" );
 
+    /**Returns map with format filter string as key and OGR format key as value*/
+    static QMap< QString, QString> supportedFiltersAndFormats();
+
+    /**Returns filter string that can be used for dialogs*/
+    static QString fileFilterString();
+
+    /**Creates a filter for an OGR driver key*/
+    static QString filterForDriver( const QString& driverName );
+
     /** checks whether there were any errors in constructor */
     WriterError hasError();
 



More information about the QGIS-commit mailing list