Quantum GIS API Documentation
1.8
|
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 }