/*************************************************************************** qgsshapefile.cpp - description ------------------- begin : Fri Dec 19 2003 copyright : (C) 2003 by Denis Antipov email : ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* $Id$ */ #include #include #include #include #include #include #include #include "qgsdbfbase.h" #include "cpl_error.h" #include "qgsshapefile.h" #include "qgsscangeometries.h" #include "../../src/qgis.h" QgsShapeFile::QgsShapeFile(QString name){ filename = name; features = 0; OGRRegisterAll(); ogrDataSource = OGRSFDriverRegistrar::Open((const char *) filename); if (ogrDataSource != NULL){ valid = true; ogrLayer = ogrDataSource->GetLayer(0); features = ogrLayer->GetFeatureCount(); } else valid = false; setDefaultTable(); // init the geometry types geometries << "NULL" << "POINT" << "LINESTRING" << "POLYGON" << "MULTPOINT" << "MULTILINESTRING" << "MULTIPOLYGON" << "GEOMETRYCOLLECTION"; } QgsShapeFile::~QgsShapeFile(){ delete ogrLayer; delete ogrDataSource; delete filename; delete geom_type; } int QgsShapeFile::getFeatureCount(){ return features; } bool QgsShapeFile::scanGeometries() { int progressThreshold = 5; int progressCount = 0; QgsScanGeometries *sg = new QgsScanGeometries(); sg->setFileInfo("Scanning " + filename); sg->show(); qApp->processEvents(); OGRFeature *feat; int currentType = 0; bool multi = false; while((feat = ogrLayer->GetNextFeature())) { // update the progress counter // if(++progressCount == progressThreshold) // { // progressCount = 0; // sg->setStatus(0); qApp->processEvents(); // } // feat->DumpReadable(NULL); OGRGeometry *geom = feat->GetGeometryRef(); if(geom) { QString gml = geom->exportToGML(); // std::cerr << gml << std::endl; if(gml.find("gml:Multi") > -1) { // std::cerr << "MULTI Part Feature detected" << std::endl; multi = true; } OGRFeatureDefn *fDef = feat->GetDefnRef(); OGRwkbGeometryType gType = fDef->GetGeomType(); // std::cerr << fDef->GetGeomType() << std::endl; if(gType > currentType) { currentType = gType; } if(gType < currentType) { std::cerr << "Encountered inconsistent geometry type " << gType << std::endl; } } } ogrLayer->ResetReading(); geom_type = geometries[currentType]; if(multi && (geom_type.find("MULTI") == -1)) { geom_type = "MULTI" + geom_type; } delete sg; // std::cerr << "Geometry type is " << currentType << " (" << geometries[currentType] << ")" << std::endl; return multi; } QString QgsShapeFile::getFeatureClass(){ // scan the whole layer to try to determine the geometry // type. qApp->processEvents(); isMulti = scanGeometries(); OGRFeature *feat = ogrLayer->GetNextFeature(); if(feat){ OGRGeometry *geom = feat->GetGeometryRef(); if(geom){ /* OGR doesn't appear to report geometry type properly * for a layer containing both polygon and multipolygon * entities * // get the feature type from the layer OGRFeatureDefn * gDef = ogrLayer->GetLayerDefn(); OGRwkbGeometryType gType = gDef->GetGeomType(); geom_type = QGis::qgisFeatureTypes[gType]; */ //geom_type = QString(geom->getGeometryName()); //geom_type = "GEOMETRY"; std::cerr << "Preparing to escape " << geom_type << std::endl; char * esc_str = new char[geom_type.length()*2+1]; PQescapeString(esc_str, (const char *)geom_type, geom_type.length()); geom_type = QString(esc_str); std::cerr << "After escaping, geom_type is : " << geom_type << std::endl; delete[] esc_str; QString file(filename); file.replace(file.length()-3, 3, "dbf"); // open the dbf file std::ifstream dbf((const char*)file, std::ios::in | std::ios::binary); // read header DbaseHeader dbh; dbf.read((char *)&dbh, sizeof(dbh)); Fda fda; QString str_type = "varchar("; for(int field_count = 0, bytes_read = sizeof(dbh); bytes_read < dbh.size_hdr-1; field_count++, bytes_read +=sizeof(fda)){ dbf.read((char *)&fda, sizeof(fda)); switch(fda.field_type){ case 'N': if((int)fda.field_decimal>0) column_types.push_back("float"); else column_types.push_back("int"); break; case 'F': column_types.push_back("float"); break; case 'D': column_types.push_back("date"); break; case 'C': str_type= QString("varchar(%1)").arg(fda.field_length); column_types.push_back(str_type); break; case 'L': column_types.push_back("boolean"); break; default: column_types.push_back("varchar(256)"); break; } } dbf.close(); int numFields = feat->GetFieldCount(); for(int n=0; nGetFieldDefnRef(n)->GetNameRef()); }else valid = false; delete feat; }else valid = false; ogrLayer->ResetReading(); return valid?geom_type:QString::null; } bool QgsShapeFile::is_valid(){ return valid; } QString QgsShapeFile::getName(){ return filename; } QString QgsShapeFile::getTable(){ return table_name; } void QgsShapeFile::setTable(QString new_table){ new_table.replace("\'","\\'"); new_table.replace("\\","\\\\"); table_name = new_table; } void QgsShapeFile::setDefaultTable(){ QString name(filename); name = name.section('/', -1); table_name = name.section('.', 0, 0); } void QgsShapeFile::setColumnNames(QStringList columns) { column_names.clear(); for (QStringList::Iterator it = columns.begin(); it != columns.end(); ++it) { column_names.push_back(*it); } } bool QgsShapeFile::insertLayer(QString dbname, QString schema, QString geom_col, QString srid, PGconn * conn, QProgressDialog * pro, bool &fin){ connect(pro, SIGNAL(cancelled()), this, SLOT(cancelImport())); import_cancelled = false; bool result = true; QString query = "CREATE TABLE "+schema+"."+table_name+"(gid int4 PRIMARY KEY, "; for(int n=0; nGetNextFeature(); if(feat){ OGRGeometry *geom = feat->GetGeometryRef(); if(geom){ query = "INSERT INTO "+schema+"."+table_name+QString(" VALUES( %1, ").arg(m); int num = geom->WkbSize(); char * geo_temp = new char[num*3]; geom->exportToWkt(&geo_temp); QString geometry(geo_temp); QString quotes; for(int n=0; nGetFieldAsString(n); char * esc_str = new char[val.length()*2+1]; PQescapeString(esc_str, (const char *)val.lower(), val.length()); // add escaped value to the query query += esc_str; query += QString(quotes + ", "); delete[] esc_str; } query += QString("GeometryFromText(\'")+geometry+QString("\', ")+srid+QString("))"); // std::cerr << query << std::endl; if(result) res = PQexec(conn, (const char *)query); if(PQresultStatus(res)!=PGRES_COMMAND_OK){ // flag error and send query and error message to stdout on debug result = false; qWarning(PQresultErrorMessage(res)); } else { PQclear(res); } pro->setProgress(pro->progress()+1); qApp->processEvents(); delete[] geo_temp; } delete feat; } } // create the GIST index if the the load was successful if(result) { // prompt user to see if they want to build the index and warn // them about the potential time-cost } ogrLayer->ResetReading(); return result; } void QgsShapeFile::cancelImport(){ import_cancelled = true; }