Quantum GIS API Documentation  1.8
src/core/qgsvectorlayerimport.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           qgsvectorlayerimport.cpp
00003                           vector layer importer
00004                              -------------------
00005     begin                : Thu Aug 25 2011
00006     copyright            : (C) 2011 by Giuseppe Sucameli
00007     email                : brush.tyler at gmail.com
00008  ***************************************************************************/
00009 
00010 /***************************************************************************
00011  *                                                                         *
00012  *   This program is free software; you can redistribute it and/or modify  *
00013  *   it under the terms of the GNU General Public License as published by  *
00014  *   the Free Software Foundation; either version 2 of the License, or     *
00015  *   (at your option) any later version.                                   *
00016  *                                                                         *
00017  ***************************************************************************/
00018 
00019 #include "qgsfield.h"
00020 #include "qgsfeature.h"
00021 #include "qgsgeometry.h"
00022 #include "qgslogger.h"
00023 #include "qgsmessagelog.h"
00024 #include "qgscoordinatereferencesystem.h"
00025 #include "qgsvectorlayerimport.h"
00026 #include "qgsproviderregistry.h"
00027 
00028 #define FEATURE_BUFFER_SIZE 200
00029 
00030 typedef QgsVectorLayerImport::ImportError createEmptyLayer_t(
00031   const QString &uri,
00032   const QgsFieldMap &fields,
00033   QGis::WkbType geometryType,
00034   const QgsCoordinateReferenceSystem *destCRS,
00035   bool overwrite,
00036   QMap<int, int> *oldToNewAttrIdx,
00037   QString *errorMessage,
00038   const QMap<QString, QVariant> *options
00039 );
00040 
00041 
00042 QgsVectorLayerImport::QgsVectorLayerImport( const QString &uri,
00043     const QString &providerKey,
00044     const QgsFieldMap& fields,
00045     QGis::WkbType geometryType,
00046     const QgsCoordinateReferenceSystem* crs,
00047     bool overwrite,
00048     const QMap<QString, QVariant> *options )
00049     : mErrorCount( 0 )
00050 {
00051   mProvider = NULL;
00052 
00053   QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
00054 
00055   QLibrary *myLib = pReg->providerLibrary( providerKey );
00056   if ( !myLib )
00057   {
00058     mError = ErrInvalidProvider;
00059     mErrorMessage = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
00060     return;
00061   }
00062 
00063   createEmptyLayer_t * pCreateEmpty = ( createEmptyLayer_t * ) cast_to_fptr( myLib->resolve( "createEmptyLayer" ) );
00064   if ( !pCreateEmpty )
00065   {
00066     delete myLib;
00067     mError = ErrProviderUnsupportedFeature;
00068     mErrorMessage = QObject::tr( "Provider %1 has no createEmptyLayer method" ).arg( providerKey );
00069     return;
00070   }
00071 
00072   delete myLib;
00073 
00074   // create an empty layer
00075   QString errMsg;
00076   mError = pCreateEmpty( uri, fields, geometryType, crs, overwrite, &mOldToNewAttrIdx, &errMsg, options );
00077   if ( hasError() )
00078   {
00079     mErrorMessage = errMsg;
00080     return;
00081   }
00082 
00083   QgsDebugMsg( "Created empty layer" );
00084 
00085   QgsVectorDataProvider *vectorProvider = ( QgsVectorDataProvider* ) pReg->provider( providerKey, uri );
00086   if ( !vectorProvider || !vectorProvider->isValid() )
00087   {
00088     mError = ErrInvalidLayer;
00089     mErrorMessage = QObject::tr( "Loading of layer failed" );
00090 
00091     if ( vectorProvider )
00092       delete vectorProvider;
00093 
00094     return;
00095   }
00096 
00097   mProvider = vectorProvider;
00098   mError = NoError;
00099 }
00100 
00101 QgsVectorLayerImport::~QgsVectorLayerImport()
00102 {
00103   flushBuffer();
00104 
00105   if ( mProvider )
00106     delete mProvider;
00107 }
00108 
00109 QgsVectorLayerImport::ImportError QgsVectorLayerImport::hasError()
00110 {
00111   return mError;
00112 }
00113 
00114 QString QgsVectorLayerImport::errorMessage()
00115 {
00116   return mErrorMessage;
00117 }
00118 
00119 bool QgsVectorLayerImport::addFeature( QgsFeature& feat )
00120 {
00121   const QgsAttributeMap &attrs = feat.attributeMap();
00122 
00123   QgsAttributeMap newAttrs;
00124   for ( QgsAttributeMap::const_iterator it = attrs.begin(); it != attrs.end(); it++ )
00125   {
00126     if ( mOldToNewAttrIdx.contains( it.key() ) )
00127     {
00128       QgsDebugMsgLevel( QString( "moving field from pos %1 to %2" ).arg( it.key() ).arg( mOldToNewAttrIdx.value( it.key() ) ), 3 );
00129       newAttrs.insert( mOldToNewAttrIdx.value( it.key() ), *it );
00130     }
00131     else
00132     {
00133       QgsDebugMsgLevel( QString( "added attr pos %1" ).arg( it.key() ), 3 );
00134       newAttrs.insert( it.key(), *it );
00135     }
00136   }
00137   feat.setAttributeMap( newAttrs );
00138 
00139   mFeatureBuffer.append( feat );
00140 
00141   if ( mFeatureBuffer.count() >= FEATURE_BUFFER_SIZE )
00142   {
00143     return flushBuffer();
00144   }
00145 
00146   return true;
00147 }
00148 
00149 bool QgsVectorLayerImport::flushBuffer()
00150 {
00151   if ( mFeatureBuffer.count() <= 0 )
00152     return true;
00153 
00154   if ( !mProvider->addFeatures( mFeatureBuffer ) )
00155   {
00156     QStringList errors = mProvider->errors();
00157     mProvider->clearErrors();
00158 
00159     mErrorMessage = QObject::tr( "Creation error for features from #%1 to #%2. Provider errors was: \n%3" )
00160                     .arg( mFeatureBuffer.first().id() )
00161                     .arg( mFeatureBuffer.last().id() )
00162                     .arg( errors.join( "\n" ) );
00163 
00164     mError = ErrFeatureWriteFailed;
00165     mErrorCount += mFeatureBuffer.count();
00166 
00167     mFeatureBuffer.clear();
00168     QgsDebugMsg( mErrorMessage );
00169     return false;
00170   }
00171 
00172   mFeatureBuffer.clear();
00173   return true;
00174 }
00175 
00176 
00177 QgsVectorLayerImport::ImportError
00178 QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
00179                                    const QString& uri,
00180                                    const QString& providerKey,
00181                                    const QgsCoordinateReferenceSystem *destCRS,
00182                                    bool onlySelected,
00183                                    QString *errorMessage,
00184                                    bool skipAttributeCreation,
00185                                    QMap<QString, QVariant> *options )
00186 {
00187   const QgsCoordinateReferenceSystem* outputCRS;
00188   QgsCoordinateTransform* ct = 0;
00189   int shallTransform = false;
00190 
00191   if ( layer == NULL )
00192   {
00193     return ErrInvalidLayer;
00194   }
00195 
00196   if ( destCRS && destCRS->isValid() )
00197   {
00198     // This means we should transform
00199     outputCRS = destCRS;
00200     shallTransform = true;
00201   }
00202   else
00203   {
00204     // This means we shouldn't transform, use source CRS as output (if defined)
00205     outputCRS = &layer->crs();
00206   }
00207 
00208   QgsFieldMap fields = skipAttributeCreation ? QgsFieldMap() : layer->pendingFields();
00209   if ( layer->providerType() == "ogr" && layer->storageType() == "ESRI Shapefile" )
00210   {
00211     // convert field names to lowercase
00212     for ( QgsFieldMap::iterator fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
00213     {
00214       fldIt.value().setName( fldIt.value().name().toLower() );
00215     }
00216   }
00217 
00218   bool overwrite = false;
00219   if ( options )
00220   {
00221     overwrite = options->take( "overwrite" ).toBool();
00222   }
00223 
00224   QgsVectorLayerImport * writer =
00225     new QgsVectorLayerImport( uri, providerKey, fields, layer->wkbType(), outputCRS, overwrite, options );
00226 
00227   // check whether file creation was successful
00228   ImportError err = writer->hasError();
00229   if ( err != NoError )
00230   {
00231     if ( errorMessage )
00232       *errorMessage = writer->errorMessage();
00233     delete writer;
00234     return err;
00235   }
00236 
00237   if ( errorMessage )
00238   {
00239     errorMessage->clear();
00240   }
00241 
00242   QgsAttributeList allAttr = skipAttributeCreation ? QgsAttributeList() : layer->pendingAllAttributesList();
00243   QgsFeature fet;
00244 
00245   layer->select( allAttr, QgsRectangle(), layer->wkbType() != QGis::WKBNoGeometry );
00246 
00247   const QgsFeatureIds& ids = layer->selectedFeaturesIds();
00248 
00249   // Create our transform
00250   if ( destCRS )
00251   {
00252     ct = new QgsCoordinateTransform( layer->crs(), *destCRS );
00253   }
00254 
00255   // Check for failure
00256   if ( ct == NULL )
00257   {
00258     shallTransform = false;
00259   }
00260 
00261   int n = 0;
00262 
00263   if ( errorMessage )
00264   {
00265     *errorMessage = QObject::tr( "Feature write errors:" );
00266   }
00267 
00268   // write all features
00269   while ( layer->nextFeature( fet ) )
00270   {
00271     if ( writer->errorCount() > 1000 )
00272     {
00273       if ( errorMessage )
00274       {
00275         *errorMessage += "\n" + QObject::tr( "Stopping after %1 errors" ).arg( writer->errorCount() );
00276       }
00277       break;
00278     }
00279 
00280     if ( onlySelected && !ids.contains( fet.id() ) )
00281       continue;
00282 
00283     if ( shallTransform )
00284     {
00285       try
00286       {
00287         if ( fet.geometry() )
00288         {
00289           fet.geometry()->transform( *ct );
00290         }
00291       }
00292       catch ( QgsCsException &e )
00293       {
00294         delete ct;
00295         delete writer;
00296 
00297         QString msg = QObject::tr( "Failed to transform a point while drawing a feature of type '%1'. Writing stopped. (Exception: %2)" )
00298                       .arg( fet.typeName() ).arg( e.what() );
00299         QgsMessageLog::logMessage( msg, QObject::tr( "Vector import" ) );
00300         if ( errorMessage )
00301           *errorMessage += "\n" + msg;
00302 
00303         return ErrProjection;
00304       }
00305     }
00306     if ( skipAttributeCreation )
00307     {
00308       fet.clearAttributeMap();
00309     }
00310     if ( !writer->addFeature( fet ) )
00311     {
00312       if ( writer->hasError() && errorMessage )
00313       {
00314         *errorMessage += "\n" + writer->errorMessage();
00315       }
00316     }
00317     n++;
00318   }
00319 
00320   // flush the buffer to be sure that all features are written
00321   if ( !writer->flushBuffer() )
00322   {
00323     if ( writer->hasError() && errorMessage )
00324     {
00325       *errorMessage += "\n" + writer->errorMessage();
00326     }
00327   }
00328   int errors = writer->errorCount();
00329 
00330   delete writer;
00331 
00332   if ( shallTransform )
00333   {
00334     delete ct;
00335   }
00336 
00337   if ( errorMessage )
00338   {
00339     if ( errors > 0 )
00340     {
00341       *errorMessage += "\n" + QObject::tr( "Only %1 of %2 features written." ).arg( n - errors ).arg( n );
00342     }
00343     else
00344     {
00345       errorMessage->clear();
00346     }
00347   }
00348 
00349   return errors == 0 ? NoError : ErrFeatureWriteFailed;
00350 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines