QVector<QgsDataItem *> QgsOgrDataCollectionItem::createChildren() { QVector<QgsDataItem *> children; QStringList skippedLayerNames; char **papszOptions = nullptr; papszOptions = CSLSetNameValue( papszOptions, "@LIST_ALL_TABLES", "YES" ); gdal::dataset_unique_ptr hDataSource( GDALOpenEx( mPath.toUtf8().constData(), GDAL_OF_VECTOR, nullptr, papszOptions, nullptr ) ); CSLDestroy( papszOptions ); GDALDriverH hDriver = GDALGetDatasetDriver( hDataSource.get() ); QString driverName = QString::fromUtf8( GDALGetDriverShortName( hDriver ) ); if ( driverName == QStringLiteral( "SQLite" ) ) { skippedLayerNames = QgsSqliteUtils::systemTables(); } if ( !hDataSource ) return children; int numLayers = GDALDatasetGetLayerCount( hDataSource.get() ); // Check if layer names are unique, so we can use |layername= in URI QMap< QString, int > mapLayerNameToCount; QList< int > skippedLayers; bool uniqueNames = true; for ( int i = 0; i < numLayers; ++i ) { OGRLayerH hLayer = GDALDatasetGetLayer( hDataSource.get(), i ); OGRFeatureDefnH hDef = OGR_L_GetLayerDefn( hLayer ); QString layerName = QString::fromUtf8( OGR_FD_GetName( hDef ) ); ++mapLayerNameToCount[layerName]; if ( mapLayerNameToCount[layerName] > 1 ) { uniqueNames = false; break; } if ( ( driverName == QStringLiteral( "SQLite" ) && layerName.contains( QRegularExpression( QStringLiteral( "idx_.*_geometry($|_.*)" ) ) ) ) || skippedLayerNames.contains( layerName ) ) { skippedLayers << i; } } children.reserve( numLayers ); for ( int i = 0; i < numLayers; ++i ) { if ( !skippedLayers.contains( i ) ) { QgsOgrLayerItem *item = dataItemForLayer( this, QString(), mPath, hDataSource.get(), i, true, uniqueNames ); children.append( item ); } } return children; }
QVector<QgsDataItem *> QgsOgrDataCollectionItem::createChildren() { QVector<QgsDataItem *> children; gdal::dataset_unique_ptr hDataSource( GDALOpenEx( mPath.toUtf8().constData(), GDAL_OF_VECTOR, nullptr, nullptr, nullptr ) ); if ( !hDataSource ) return children; int numLayers = GDALDatasetGetLayerCount( hDataSource.get() ); children.reserve( numLayers ); for ( int i = 0; i < numLayers; ++i ) { QgsOgrLayerItem *item = dataItemForLayer( this, QString(), mPath, hDataSource.get(), i, true ); children.append( item ); } return children; }
GDALDatasetH GDALRasterize( const char *pszDest, GDALDatasetH hDstDS, GDALDatasetH hSrcDataset, const GDALRasterizeOptions *psOptionsIn, int *pbUsageError ) { if( pszDest == NULL && hDstDS == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "pszDest == NULL && hDstDS == NULL"); if(pbUsageError) *pbUsageError = TRUE; return NULL; } if( hSrcDataset == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "hSrcDataset== NULL"); if(pbUsageError) *pbUsageError = TRUE; return NULL; } if( hDstDS != NULL && psOptionsIn && psOptionsIn->bCreateOutput ) { CPLError( CE_Failure, CPLE_AppDefined, "hDstDS != NULL but options that imply creating a new dataset have been set."); if(pbUsageError) *pbUsageError = TRUE; return NULL; } GDALRasterizeOptions* psOptionsToFree = NULL; const GDALRasterizeOptions* psOptions; if( psOptionsIn ) psOptions = psOptionsIn; else { psOptionsToFree = GDALRasterizeOptionsNew(NULL, NULL); psOptions = psOptionsToFree; } int bCloseOutDSOnError = (hDstDS == NULL); if( pszDest == NULL ) pszDest = GDALGetDescription(hDstDS); if( psOptions->pszSQL == NULL && psOptions->papszLayers == NULL && GDALDatasetGetLayerCount(hSrcDataset) != 1 ) { CPLError(CE_Failure, CPLE_NotSupported, "Neither -sql nor -l are specified, but the source dataset has not one single layer."); if( pbUsageError ) *pbUsageError = TRUE; GDALRasterizeOptionsFree(psOptionsToFree); return NULL; } /* -------------------------------------------------------------------- */ /* Open target raster file. Eventually we will add optional */ /* creation. */ /* -------------------------------------------------------------------- */ int bCreateOutput = psOptions->bCreateOutput; if( hDstDS == NULL ) bCreateOutput = TRUE; GDALDriverH hDriver = NULL; if (psOptions->bCreateOutput) { /* -------------------------------------------------------------------- */ /* Find the output driver. */ /* -------------------------------------------------------------------- */ hDriver = GDALGetDriverByName( psOptions->pszFormat ); if( hDriver == NULL || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL ) { int iDr; CPLError( CE_Failure, CPLE_NotSupported, "Output driver `%s' not recognised or does not support " " direct output file creation.", psOptions->pszFormat); fprintf(stderr, "The following format drivers are configured\n" "and support direct output:\n" ); for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ ) { hDriver = GDALGetDriver(iDr); if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL ) { fprintf(stderr, " %s: %s\n", GDALGetDriverShortName( hDriver ), GDALGetDriverLongName( hDriver ) ); } } fprintf(stderr, "\n" ); GDALRasterizeOptionsFree(psOptionsToFree); return NULL; } } /* -------------------------------------------------------------------- */ /* Process SQL request. */ /* -------------------------------------------------------------------- */ CPLErr eErr = CE_Failure; if( psOptions->pszSQL != NULL ) { OGRLayerH hLayer; hLayer = GDALDatasetExecuteSQL( hSrcDataset, psOptions->pszSQL, NULL, psOptions->pszDialect ); if( hLayer != NULL ) { if (bCreateOutput) { std::vector<OGRLayerH> ahLayers; ahLayers.push_back(hLayer); hDstDS = CreateOutputDataset(ahLayers, psOptions->hSRS, psOptions->bGotBounds, psOptions->sEnvelop, hDriver, pszDest, psOptions->nXSize, psOptions->nYSize, psOptions->dfXRes, psOptions->dfYRes, psOptions->bTargetAlignedPixels, static_cast<int>(psOptions->anBandList.size()), psOptions->eOutputType, psOptions->papszCreationOptions, psOptions->adfInitVals, psOptions->bNoDataSet, psOptions->dfNoData); if( hDstDS == NULL ) { GDALDatasetReleaseResultSet( hSrcDataset, hLayer ); GDALRasterizeOptionsFree(psOptionsToFree); return NULL; } } eErr = ProcessLayer( hLayer, psOptions->hSRS != NULL, hDstDS, psOptions->anBandList, psOptions->adfBurnValues, psOptions->b3D, psOptions->bInverse, psOptions->pszBurnAttribute, psOptions->papszRasterizeOptions, psOptions->pfnProgress, psOptions->pProgressData ); GDALDatasetReleaseResultSet( hSrcDataset, hLayer ); } } /* -------------------------------------------------------------------- */ /* Create output file if necessary. */ /* -------------------------------------------------------------------- */ int nLayerCount = (psOptions->pszSQL == NULL && psOptions->papszLayers == NULL) ? 1 : CSLCount(psOptions->papszLayers); if (psOptions->bCreateOutput && hDstDS == NULL) { std::vector<OGRLayerH> ahLayers; for( int i = 0; i < nLayerCount; i++ ) { OGRLayerH hLayer; if( psOptions->papszLayers ) hLayer = GDALDatasetGetLayerByName( hSrcDataset, psOptions->papszLayers[i] ); else hLayer = GDALDatasetGetLayer(hSrcDataset, 0); if( hLayer == NULL ) { continue; } ahLayers.push_back(hLayer); } hDstDS = CreateOutputDataset(ahLayers, psOptions->hSRS, psOptions->bGotBounds, psOptions->sEnvelop, hDriver, pszDest, psOptions->nXSize, psOptions->nYSize, psOptions->dfXRes, psOptions->dfYRes, psOptions->bTargetAlignedPixels, static_cast<int>(psOptions->anBandList.size()), psOptions->eOutputType, psOptions->papszCreationOptions, psOptions->adfInitVals, psOptions->bNoDataSet, psOptions->dfNoData); if( hDstDS == NULL ) { GDALRasterizeOptionsFree(psOptionsToFree); return NULL; } } /* -------------------------------------------------------------------- */ /* Process each layer. */ /* -------------------------------------------------------------------- */ for( int i = 0; i < nLayerCount; i++ ) { OGRLayerH hLayer; if( psOptions->papszLayers ) hLayer = GDALDatasetGetLayerByName( hSrcDataset, psOptions->papszLayers[i] ); else hLayer = GDALDatasetGetLayer(hSrcDataset, 0); if( hLayer == NULL ) { CPLError(CE_Failure, CPLE_AppDefined, "Unable to find layer \"%s\", skipping.", psOptions->papszLayers ? psOptions->papszLayers[i] : "0" ); continue; } if( psOptions->pszWHERE ) { if( OGR_L_SetAttributeFilter( hLayer, psOptions->pszWHERE ) != OGRERR_NONE ) break; } void *pScaledProgress; pScaledProgress = GDALCreateScaledProgress( 0.0, 1.0 * (i + 1) / nLayerCount, psOptions->pfnProgress, psOptions->pProgressData ); eErr = ProcessLayer( hLayer, psOptions->hSRS != NULL, hDstDS, psOptions->anBandList, psOptions->adfBurnValues, psOptions->b3D, psOptions->bInverse, psOptions->pszBurnAttribute, psOptions->papszRasterizeOptions, GDALScaledProgress, pScaledProgress ); GDALDestroyScaledProgress( pScaledProgress ); if( eErr != CE_None ) break; } GDALRasterizeOptionsFree(psOptionsToFree); if( eErr != CE_None ) { if( bCloseOutDSOnError ) GDALClose(hDstDS); return NULL; } return hDstDS; }
MAIN_START(argc, argv) { // Check that we are running against at least GDAL 1.4. // Note to developers: if we use newer API, please change the requirement. if( atoi(GDALVersionInfo("VERSION_NUM")) < 1400 ) { fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, " "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME); exit(1); } GDALAllRegister(); OGRRegisterAll(); argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 ); if( argc < 1 ) exit( -argc ); /* -------------------------------------------------------------------- */ /* Get commandline arguments other than the GDAL raster filenames. */ /* -------------------------------------------------------------------- */ const char* pszIndexLayerName = nullptr; const char *index_filename = nullptr; const char *tile_index = "location"; const char* pszDriverName = nullptr; size_t nMaxFieldSize = 254; bool write_absolute_path = false; char* current_path = nullptr; bool skip_different_projection = false; const char *pszTargetSRS = ""; bool bSetTargetSRS = false; const char* pszSrcSRSName = nullptr; int i_SrcSRSName = -1; bool bSrcSRSFormatSpecified = false; SrcSRSFormat eSrcSRSFormat = FORMAT_AUTO; int iArg = 1; // Used after for. for( ; iArg < argc; iArg++ ) { if( EQUAL(argv[iArg], "--utility_version") ) { printf("%s was compiled against GDAL %s and is running against " "GDAL %s\n", argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME")); CSLDestroy( argv ); return 0; } else if( EQUAL(argv[iArg],"--help") ) Usage(nullptr); else if( (strcmp(argv[iArg],"-f") == 0 || strcmp(argv[iArg],"-of") == 0) ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszDriverName = argv[++iArg]; } else if( strcmp(argv[iArg],"-lyr_name") == 0 ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszIndexLayerName = argv[++iArg]; } else if( strcmp(argv[iArg],"-tileindex") == 0 ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); tile_index = argv[++iArg]; } else if( strcmp(argv[iArg],"-t_srs") == 0 ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszTargetSRS = argv[++iArg]; bSetTargetSRS = true; } else if ( strcmp(argv[iArg],"-write_absolute_path") == 0 ) { write_absolute_path = true; } else if ( strcmp(argv[iArg],"-skip_different_projection") == 0 ) { skip_different_projection = true; } else if( strcmp(argv[iArg], "-src_srs_name") == 0 ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszSrcSRSName = argv[++iArg]; } else if( strcmp(argv[iArg], "-src_srs_format") == 0 ) { const char* pszFormat; bSrcSRSFormatSpecified = true; CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszFormat = argv[++iArg]; if( EQUAL(pszFormat, "AUTO") ) eSrcSRSFormat = FORMAT_AUTO; else if( EQUAL(pszFormat, "WKT") ) eSrcSRSFormat = FORMAT_WKT; else if( EQUAL(pszFormat, "EPSG") ) eSrcSRSFormat = FORMAT_EPSG; else if( EQUAL(pszFormat, "PROJ") ) eSrcSRSFormat = FORMAT_PROJ; } else if( argv[iArg][0] == '-' ) Usage(CPLSPrintf("Unknown option name '%s'", argv[iArg])); else if( index_filename == nullptr ) { index_filename = argv[iArg]; iArg++; break; } } if( index_filename == nullptr ) Usage("No index filename specified."); if( iArg == argc ) Usage("No file to index specified."); if( bSrcSRSFormatSpecified && pszSrcSRSName == nullptr ) Usage("-src_srs_name must be specified when -src_srs_format is " "specified."); /* -------------------------------------------------------------------- */ /* Create and validate target SRS if given. */ /* -------------------------------------------------------------------- */ OGRSpatialReferenceH hTargetSRS = nullptr; if( bSetTargetSRS ) { if( skip_different_projection ) { fprintf( stderr, "Warning : -skip_different_projection does not apply " "when -t_srs is requested.\n" ); } hTargetSRS = OSRNewSpatialReference(""); OSRSetAxisMappingStrategy(hTargetSRS, OAMS_TRADITIONAL_GIS_ORDER); // coverity[tainted_data] if( OSRSetFromUserInput( hTargetSRS, pszTargetSRS ) != CE_None ) { OSRDestroySpatialReference( hTargetSRS ); fprintf( stderr, "Invalid target SRS `%s'.\n", pszTargetSRS ); exit(1); } } /* -------------------------------------------------------------------- */ /* Open or create the target datasource */ /* -------------------------------------------------------------------- */ GDALDatasetH hTileIndexDS = GDALOpenEx( index_filename, GDAL_OF_VECTOR | GDAL_OF_UPDATE, nullptr, nullptr, nullptr ); OGRLayerH hLayer = nullptr; CPLString osFormat; if( hTileIndexDS != nullptr ) { GDALDriverH hDriver = GDALGetDatasetDriver(hTileIndexDS); if( hDriver ) osFormat = GDALGetDriverShortName(hDriver); if( GDALDatasetGetLayerCount(hTileIndexDS) == 1 ) { hLayer = GDALDatasetGetLayer(hTileIndexDS, 0); } else { if( pszIndexLayerName == nullptr ) { printf( "-lyr_name must be specified.\n" ); exit( 1 ); } CPLPushErrorHandler(CPLQuietErrorHandler); hLayer = GDALDatasetGetLayerByName(hTileIndexDS, pszIndexLayerName); CPLPopErrorHandler(); } } else { printf( "Creating new index file...\n" ); if( pszDriverName == nullptr ) { std::vector<CPLString> aoDrivers = GetOutputDriversFor(index_filename, GDAL_OF_VECTOR); if( aoDrivers.empty() ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot guess driver for %s", index_filename); exit( 10 ); } else { if( aoDrivers.size() > 1 ) { CPLError( CE_Warning, CPLE_AppDefined, "Several drivers matching %s extension. Using %s", CPLGetExtension(index_filename), aoDrivers[0].c_str() ); } osFormat = aoDrivers[0]; } } else { osFormat = pszDriverName; } if( !EQUAL(osFormat, "ESRI Shapefile") ) nMaxFieldSize = 0; GDALDriverH hDriver = GDALGetDriverByName( osFormat.c_str() ); if( hDriver == nullptr ) { printf( "%s driver not available.\n", osFormat.c_str() ); exit( 1 ); } hTileIndexDS = GDALCreate( hDriver, index_filename, 0, 0, 0, GDT_Unknown, nullptr ); } if( hTileIndexDS != nullptr && hLayer == nullptr ) { OGRSpatialReferenceH hSpatialRef = nullptr; char* pszLayerName = nullptr; if( pszIndexLayerName == nullptr ) { VSIStatBuf sStat; if( EQUAL(osFormat, "ESRI Shapefile") || VSIStat(index_filename, &sStat) == 0 ) { pszLayerName = CPLStrdup(CPLGetBasename(index_filename)); } else { printf( "-lyr_name must be specified.\n" ); exit( 1 ); } } else { pszLayerName = CPLStrdup(pszIndexLayerName); } /* get spatial reference for output file from target SRS (if set) */ /* or from first input file */ if( bSetTargetSRS ) { hSpatialRef = OSRClone( hTargetSRS ); } else { GDALDatasetH hDS = GDALOpen( argv[iArg], GA_ReadOnly ); if( hDS ) { const char* pszWKT = GDALGetProjectionRef(hDS); if (pszWKT != nullptr && pszWKT[0] != '\0') { hSpatialRef = OSRNewSpatialReference(pszWKT); OSRSetAxisMappingStrategy(hSpatialRef, OAMS_TRADITIONAL_GIS_ORDER); } GDALClose(hDS); } } hLayer = GDALDatasetCreateLayer( hTileIndexDS, pszLayerName, hSpatialRef, wkbPolygon, nullptr ); CPLFree(pszLayerName); if( hSpatialRef ) OSRRelease(hSpatialRef); if( hLayer ) { OGRFieldDefnH hFieldDefn = OGR_Fld_Create( tile_index, OFTString ); if( nMaxFieldSize ) OGR_Fld_SetWidth( hFieldDefn, static_cast<int>(nMaxFieldSize)); OGR_L_CreateField( hLayer, hFieldDefn, TRUE ); OGR_Fld_Destroy(hFieldDefn); if( pszSrcSRSName != nullptr ) { hFieldDefn = OGR_Fld_Create( pszSrcSRSName, OFTString ); if( nMaxFieldSize ) OGR_Fld_SetWidth(hFieldDefn, static_cast<int>(nMaxFieldSize)); OGR_L_CreateField( hLayer, hFieldDefn, TRUE ); OGR_Fld_Destroy(hFieldDefn); } } } if( hTileIndexDS == nullptr || hLayer == nullptr ) { fprintf( stderr, "Unable to open/create shapefile `%s'.\n", index_filename ); exit(2); } OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hLayer); const int ti_field = OGR_FD_GetFieldIndex( hFDefn, tile_index ); if( ti_field < 0 ) { fprintf( stderr, "Unable to find field `%s' in file `%s'.\n", tile_index, index_filename ); exit(2); } if( pszSrcSRSName != nullptr ) i_SrcSRSName = OGR_FD_GetFieldIndex( hFDefn, pszSrcSRSName ); // Load in memory existing file names in SHP. int nExistingFiles = static_cast<int>(OGR_L_GetFeatureCount(hLayer, FALSE)); if( nExistingFiles < 0) nExistingFiles = 0; char** existingFilesTab = nullptr; bool alreadyExistingProjectionRefValid = false; char* alreadyExistingProjectionRef = nullptr; if( nExistingFiles > 0 ) { OGRFeatureH hFeature = nullptr; existingFilesTab = static_cast<char **>( CPLMalloc(nExistingFiles * sizeof(char*))); for( int i = 0; i < nExistingFiles; i++ ) { hFeature = OGR_L_GetNextFeature(hLayer); existingFilesTab[i] = CPLStrdup(OGR_F_GetFieldAsString( hFeature, ti_field )); if( i == 0 ) { GDALDatasetH hDS = GDALOpen(existingFilesTab[i], GA_ReadOnly ); if( hDS ) { alreadyExistingProjectionRefValid = true; alreadyExistingProjectionRef = CPLStrdup(GDALGetProjectionRef(hDS)); GDALClose(hDS); } } OGR_F_Destroy( hFeature ); } } if( write_absolute_path ) { current_path = CPLGetCurrentDir(); if (current_path == nullptr) { fprintf( stderr, "This system does not support the CPLGetCurrentDir call. " "The option -write_absolute_path will have no effect\n" ); write_absolute_path = FALSE; } } /* -------------------------------------------------------------------- */ /* loop over GDAL files, processing. */ /* -------------------------------------------------------------------- */ for( ; iArg < argc; iArg++ ) { char *fileNameToWrite = nullptr; VSIStatBuf sStatBuf; // Make sure it is a file before building absolute path name. if( write_absolute_path && CPLIsFilenameRelative( argv[iArg] ) && VSIStat( argv[iArg], &sStatBuf ) == 0 ) { fileNameToWrite = CPLStrdup(CPLProjectRelativeFilename(current_path, argv[iArg])); } else { fileNameToWrite = CPLStrdup(argv[iArg]); } // Checks that file is not already in tileindex. { int i = 0; // Used after for. for( ; i < nExistingFiles; i++ ) { if (EQUAL(fileNameToWrite, existingFilesTab[i])) { fprintf(stderr, "File %s is already in tileindex. Skipping it.\n", fileNameToWrite); break; } } if (i != nExistingFiles) { CPLFree(fileNameToWrite); continue; } } GDALDatasetH hDS = GDALOpen( argv[iArg], GA_ReadOnly ); if( hDS == nullptr ) { fprintf( stderr, "Unable to open %s, skipping.\n", argv[iArg] ); CPLFree(fileNameToWrite); continue; } double adfGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; GDALGetGeoTransform( hDS, adfGeoTransform ); if( adfGeoTransform[0] == 0.0 && adfGeoTransform[1] == 1.0 && adfGeoTransform[3] == 0.0 && std::abs(adfGeoTransform[5]) == 1.0 ) { fprintf( stderr, "It appears no georeferencing is available for\n" "`%s', skipping.\n", argv[iArg] ); GDALClose( hDS ); CPLFree(fileNameToWrite); continue; } const char *projectionRef = GDALGetProjectionRef(hDS); // If not set target srs, test that the current file uses same // projection as others. if( !bSetTargetSRS ) { if( alreadyExistingProjectionRefValid ) { int projectionRefNotNull, alreadyExistingProjectionRefNotNull; projectionRefNotNull = projectionRef && projectionRef[0]; alreadyExistingProjectionRefNotNull = alreadyExistingProjectionRef && alreadyExistingProjectionRef[0]; if ((projectionRefNotNull && alreadyExistingProjectionRefNotNull && EQUAL(projectionRef, alreadyExistingProjectionRef) == 0) || (projectionRefNotNull != alreadyExistingProjectionRefNotNull)) { fprintf( stderr, "Warning : %s is not using the same projection system " "as other files in the tileindex.\n" "This may cause problems when using it in MapServer " "for example.\n" "Use -t_srs option to set target projection system " "(not supported by MapServer).\n" "%s\n", argv[iArg], skip_different_projection ? "Skipping this file." : ""); if( skip_different_projection ) { CPLFree(fileNameToWrite); GDALClose( hDS ); continue; } } } else { alreadyExistingProjectionRefValid = true; alreadyExistingProjectionRef = CPLStrdup(projectionRef); } } const int nXSize = GDALGetRasterXSize( hDS ); const int nYSize = GDALGetRasterYSize( hDS ); double adfX[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 }; double adfY[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 }; adfX[0] = adfGeoTransform[0] + 0 * adfGeoTransform[1] + 0 * adfGeoTransform[2]; adfY[0] = adfGeoTransform[3] + 0 * adfGeoTransform[4] + 0 * adfGeoTransform[5]; adfX[1] = adfGeoTransform[0] + nXSize * adfGeoTransform[1] + 0 * adfGeoTransform[2]; adfY[1] = adfGeoTransform[3] + nXSize * adfGeoTransform[4] + 0 * adfGeoTransform[5]; adfX[2] = adfGeoTransform[0] + nXSize * adfGeoTransform[1] + nYSize * adfGeoTransform[2]; adfY[2] = adfGeoTransform[3] + nXSize * adfGeoTransform[4] + nYSize * adfGeoTransform[5]; adfX[3] = adfGeoTransform[0] + 0 * adfGeoTransform[1] + nYSize * adfGeoTransform[2]; adfY[3] = adfGeoTransform[3] + 0 * adfGeoTransform[4] + nYSize * adfGeoTransform[5]; adfX[4] = adfGeoTransform[0] + 0 * adfGeoTransform[1] + 0 * adfGeoTransform[2]; adfY[4] = adfGeoTransform[3] + 0 * adfGeoTransform[4] + 0 * adfGeoTransform[5]; OGRSpatialReferenceH hSourceSRS = nullptr; if( (bSetTargetSRS || i_SrcSRSName >= 0) && projectionRef != nullptr && projectionRef[0] != '\0' ) { hSourceSRS = OSRNewSpatialReference( projectionRef ); OSRSetAxisMappingStrategy(hSourceSRS, OAMS_TRADITIONAL_GIS_ORDER); } // If set target srs, do the forward transformation of all points. if( bSetTargetSRS && projectionRef != nullptr && projectionRef[0] != '\0' ) { OGRCoordinateTransformationH hCT = nullptr; if( hSourceSRS && !OSRIsSame( hSourceSRS, hTargetSRS ) ) { hCT = OCTNewCoordinateTransformation( hSourceSRS, hTargetSRS ); if( hCT == nullptr || !OCTTransform( hCT, 5, adfX, adfY, nullptr ) ) { fprintf( stderr, "Warning : unable to transform points from source " "SRS `%s' to target SRS `%s'\n" "for file `%s' - file skipped\n", projectionRef, pszTargetSRS, fileNameToWrite ); if( hCT ) OCTDestroyCoordinateTransformation( hCT ); if( hSourceSRS ) OSRDestroySpatialReference( hSourceSRS ); continue; } if( hCT ) OCTDestroyCoordinateTransformation( hCT ); } } OGRFeatureH hFeature = OGR_F_Create( OGR_L_GetLayerDefn( hLayer ) ); OGR_F_SetFieldString( hFeature, ti_field, fileNameToWrite ); if( i_SrcSRSName >= 0 && hSourceSRS != nullptr ) { const char* pszAuthorityCode = OSRGetAuthorityCode(hSourceSRS, nullptr); const char* pszAuthorityName = OSRGetAuthorityName(hSourceSRS, nullptr); if( eSrcSRSFormat == FORMAT_AUTO ) { if( pszAuthorityName != nullptr && pszAuthorityCode != nullptr ) { OGR_F_SetFieldString( hFeature, i_SrcSRSName, CPLSPrintf("%s:%s", pszAuthorityName, pszAuthorityCode) ); } else if( nMaxFieldSize == 0 || strlen(projectionRef) <= nMaxFieldSize ) { OGR_F_SetFieldString(hFeature, i_SrcSRSName, projectionRef); } else { char* pszProj4 = nullptr; if( OSRExportToProj4(hSourceSRS, &pszProj4) == OGRERR_NONE ) { OGR_F_SetFieldString( hFeature, i_SrcSRSName, pszProj4 ); CPLFree(pszProj4); } else { OGR_F_SetFieldString( hFeature, i_SrcSRSName, projectionRef ); } } } else if( eSrcSRSFormat == FORMAT_WKT ) { if( nMaxFieldSize == 0 || strlen(projectionRef) <= nMaxFieldSize ) { OGR_F_SetFieldString( hFeature, i_SrcSRSName, projectionRef ); } else { fprintf(stderr, "Cannot write WKT for file %s as it is too long!\n", fileNameToWrite); } } else if( eSrcSRSFormat == FORMAT_PROJ ) { char* pszProj4 = nullptr; if( OSRExportToProj4(hSourceSRS, &pszProj4) == OGRERR_NONE ) { OGR_F_SetFieldString( hFeature, i_SrcSRSName, pszProj4 ); CPLFree(pszProj4); } } else if( eSrcSRSFormat == FORMAT_EPSG ) { if( pszAuthorityName != nullptr && pszAuthorityCode != nullptr ) OGR_F_SetFieldString( hFeature, i_SrcSRSName, CPLSPrintf("%s:%s", pszAuthorityName, pszAuthorityCode) ); } } if( hSourceSRS ) OSRDestroySpatialReference( hSourceSRS ); OGRGeometryH hPoly = OGR_G_CreateGeometry(wkbPolygon); OGRGeometryH hRing = OGR_G_CreateGeometry(wkbLinearRing); for( int k = 0; k < 5; k++ ) OGR_G_SetPoint_2D(hRing, k, adfX[k], adfY[k]); OGR_G_AddGeometryDirectly( hPoly, hRing ); OGR_F_SetGeometryDirectly( hFeature, hPoly ); if( OGR_L_CreateFeature( hLayer, hFeature ) != OGRERR_NONE ) { printf( "Failed to create feature in shapefile.\n" ); break; } OGR_F_Destroy( hFeature ); CPLFree(fileNameToWrite); GDALClose( hDS ); } CPLFree(current_path); if (nExistingFiles) { for( int i = 0; i < nExistingFiles; i++ ) { CPLFree(existingFilesTab[i]); } CPLFree(existingFilesTab); } CPLFree(alreadyExistingProjectionRef); if ( hTargetSRS ) OSRDestroySpatialReference( hTargetSRS ); GDALClose( hTileIndexDS ); GDALDestroyDriverManager(); OGRCleanupAll(); CSLDestroy(argv); exit( 0 ); }
QgsDataItem *QgsOgrDataItemProvider::createDataItem( const QString &pathIn, QgsDataItem *parentItem ) { QString path( pathIn ); if ( path.isEmpty() ) return nullptr; QgsDebugMsgLevel( "thePath: " + path, 2 ); // zip settings + info QgsSettings settings; QString scanZipSetting = settings.value( QStringLiteral( "qgis/scanZipInBrowser2" ), "basic" ).toString(); QString vsiPrefix = QgsZipItem::vsiPrefix( path ); bool is_vsizip = ( vsiPrefix == QLatin1String( "/vsizip/" ) ); bool is_vsigzip = ( vsiPrefix == QLatin1String( "/vsigzip/" ) ); bool is_vsitar = ( vsiPrefix == QLatin1String( "/vsitar/" ) ); // should we check ext. only? // check if scanItemsInBrowser2 == extension or parent dir in scanItemsFastScanUris // TODO - do this in dir item, but this requires a way to inform which extensions are supported by provider // maybe a callback function or in the provider registry? bool scanExtSetting = false; if ( ( settings.value( QStringLiteral( "qgis/scanItemsInBrowser2" ), "extension" ).toString() == QLatin1String( "extension" ) ) || ( parentItem && settings.value( QStringLiteral( "qgis/scanItemsFastScanUris" ), QStringList() ).toStringList().contains( parentItem->path() ) ) || ( ( is_vsizip || is_vsitar ) && parentItem && parentItem->parent() && settings.value( QStringLiteral( "qgis/scanItemsFastScanUris" ), QStringList() ).toStringList().contains( parentItem->parent()->path() ) ) ) { scanExtSetting = true; } // get suffix, removing .gz if present QString tmpPath = path; //path used for testing, not for layer creation if ( is_vsigzip ) tmpPath.chop( 3 ); QFileInfo info( tmpPath ); QString suffix = info.suffix().toLower(); // extract basename with extension info.setFile( path ); QString name = info.fileName(); // If a .tab exists, then the corresponding .map/.dat is very likely a // side-car file of the .tab if ( suffix == QLatin1String( "map" ) || suffix == QLatin1String( "dat" ) ) { if ( QFileInfo( QDir( info.path() ), info.baseName() + ".tab" ).exists() ) return nullptr; } QgsDebugMsgLevel( "thePath= " + path + " tmpPath= " + tmpPath + " name= " + name + " suffix= " + suffix + " vsiPrefix= " + vsiPrefix, 3 ); QStringList myExtensions = fileExtensions(); QStringList dirExtensions = directoryExtensions(); // allow only normal files, supported directories, or VSIFILE items to continue bool isOgrSupportedDirectory = info.isDir() && dirExtensions.contains( suffix ); if ( !isOgrSupportedDirectory && !info.isFile() && vsiPrefix.isEmpty() ) return nullptr; // skip *.aux.xml files (GDAL auxiliary metadata files), // *.shp.xml files (ESRI metadata) and *.tif.xml files (TIFF metadata) // unless that extension is in the list (*.xml might be though) if ( path.endsWith( QLatin1String( ".aux.xml" ), Qt::CaseInsensitive ) && !myExtensions.contains( QStringLiteral( "aux.xml" ) ) ) return nullptr; if ( path.endsWith( QLatin1String( ".shp.xml" ), Qt::CaseInsensitive ) && !myExtensions.contains( QStringLiteral( "shp.xml" ) ) ) return nullptr; if ( path.endsWith( QLatin1String( ".tif.xml" ), Qt::CaseInsensitive ) && !myExtensions.contains( QStringLiteral( "tif.xml" ) ) ) return nullptr; // skip QGIS style xml files if ( path.endsWith( QLatin1String( ".xml" ), Qt::CaseInsensitive ) && QgsStyle::isXmlStyleFile( path ) ) return nullptr; // We have to filter by extensions, otherwise e.g. all Shapefile files are displayed // because OGR drive can open also .dbf, .shx. if ( myExtensions.indexOf( suffix ) < 0 && !dirExtensions.contains( suffix ) ) { bool matches = false; const auto constWildcards = wildcards(); for ( const QString &wildcard : constWildcards ) { QRegExp rx( wildcard, Qt::CaseInsensitive, QRegExp::Wildcard ); if ( rx.exactMatch( info.fileName() ) ) { matches = true; break; } } if ( !matches ) return nullptr; } // .dbf should probably appear if .shp is not present if ( suffix == QLatin1String( "dbf" ) ) { QString pathShp = path.left( path.count() - 4 ) + ".shp"; if ( QFileInfo::exists( pathShp ) ) return nullptr; } // fix vsifile path and name if ( !vsiPrefix.isEmpty() ) { // add vsiPrefix to path if needed if ( !path.startsWith( vsiPrefix ) ) path = vsiPrefix + path; // if this is a /vsigzip/path_to_zip.zip/file_inside_zip remove the full path from the name // no need to change the name I believe #if 0 if ( ( is_vsizip || is_vsitar ) && ( path != vsiPrefix + parentItem->path() ) ) { name = path; name = name.replace( vsiPrefix + parentItem->path() + '/', "" ); } #endif } // Filters out the OGR/GDAL supported formats that can contain multiple layers // and should be treated like a DB: GeoPackage and SQLite // NOTE: this formats are scanned for rasters too and they must // be skipped by "gdal" provider or the rasters will be listed // twice. ogrSupportedDbLayersExtensions must be kept in sync // with the companion variable (same name) in the gdal provider // class // TODO: add more OGR supported multiple layers formats here! static QStringList sOgrSupportedDbLayersExtensions { QStringLiteral( "gpkg" ), QStringLiteral( "sqlite" ), QStringLiteral( "db" ), QStringLiteral( "gdb" ), QStringLiteral( "kml" ) }; static QStringList sOgrSupportedDbDriverNames { QStringLiteral( "GPKG" ), QStringLiteral( "db" ), QStringLiteral( "gdb" ) }; // these extensions are trivial to read, so there's no need to rely on // the extension only scan here -- avoiding it always gives us the correct data type // and sublayer visiblity static QStringList sSkipFastTrackExtensions { QStringLiteral( "xlsx" ), QStringLiteral( "ods" ), QStringLiteral( "csv" ), QStringLiteral( "nc" ) }; // Fast track: return item without testing if: // scanExtSetting or zipfile and scan zip == "Basic scan" // netCDF files can be both raster or vector, so fallback to opening if ( ( scanExtSetting || ( ( is_vsizip || is_vsitar ) && scanZipSetting == QLatin1String( "basic" ) ) ) && !sSkipFastTrackExtensions.contains( suffix ) ) { // if this is a VRT file make sure it is vector VRT to avoid duplicates if ( suffix == QLatin1String( "vrt" ) ) { CPLPushErrorHandler( CPLQuietErrorHandler ); CPLErrorReset(); GDALDriverH hDriver = GDALIdentifyDriver( path.toUtf8().constData(), nullptr ); CPLPopErrorHandler(); if ( !hDriver || GDALGetDriverShortName( hDriver ) == QLatin1String( "VRT" ) ) { QgsDebugMsgLevel( QStringLiteral( "Skipping VRT file because root is not a OGR VRT" ), 2 ); return nullptr; } } // Handle collections // Check if the layer has sublayers by comparing the extension QgsDataItem *item = nullptr; if ( ! sOgrSupportedDbLayersExtensions.contains( suffix ) ) { item = new QgsOgrLayerItem( parentItem, name, path, path, QgsLayerItem::Vector ); } else if ( suffix.compare( QLatin1String( "gpkg" ), Qt::CaseInsensitive ) == 0 ) { item = new QgsGeoPackageCollectionItem( parentItem, name, path ); } else { item = new QgsOgrDataCollectionItem( parentItem, name, path ); } if ( item ) return item; } // Slow track: scan file contents QgsDataItem *item = nullptr; // test that file is valid with OGR if ( OGRGetDriverCount() == 0 ) { OGRRegisterAll(); } // do not print errors, but write to debug CPLPushErrorHandler( CPLQuietErrorHandler ); CPLErrorReset(); gdal::dataset_unique_ptr hDS( GDALOpenEx( path.toUtf8().constData(), GDAL_OF_VECTOR, nullptr, nullptr, nullptr ) ); CPLPopErrorHandler(); if ( ! hDS ) { QgsDebugMsg( QStringLiteral( "GDALOpen error # %1 : %2 on %3" ).arg( CPLGetLastErrorNo() ).arg( CPLGetLastErrorMsg() ).arg( path ) ); return nullptr; } GDALDriverH hDriver = GDALGetDatasetDriver( hDS.get() ); QString driverName = GDALGetDriverShortName( hDriver ); QgsDebugMsgLevel( QStringLiteral( "GDAL Driver : %1" ).arg( driverName ), 2 ); int numLayers = GDALDatasetGetLayerCount( hDS.get() ); // GeoPackage needs a specialized data item, mainly because of raster deletion not // yet implemented in GDAL (2.2.1) if ( driverName == QLatin1String( "GPKG" ) ) { item = new QgsGeoPackageCollectionItem( parentItem, name, path ); } else if ( numLayers > 1 || sOgrSupportedDbDriverNames.contains( driverName ) ) { item = new QgsOgrDataCollectionItem( parentItem, name, path ); } else { item = dataItemForLayer( parentItem, name, path, hDS.get(), 0, false, true ); } return item; }