Skip to content

Commit

Permalink
Enabled delimitedtext provider again
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Oct 20, 2012
1 parent 999df64 commit 7ed9308
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 221 deletions.
2 changes: 1 addition & 1 deletion src/providers/CMakeLists.txt
Expand Up @@ -5,7 +5,7 @@ SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/${QGIS_PLUGIN_SUBDI
ADD_SUBDIRECTORY(memory)
ADD_SUBDIRECTORY(ogr)
ADD_SUBDIRECTORY(wms)
#ADD_SUBDIRECTORY(delimitedtext) # TODO: enable when migrated to new api
ADD_SUBDIRECTORY(delimitedtext)
#ADD_SUBDIRECTORY(osm) # TODO: enable when migrated to new api
#ADD_SUBDIRECTORY(sqlanywhere) # TODO: enable when migrated to new api
ADD_SUBDIRECTORY(gdal)
Expand Down
1 change: 1 addition & 0 deletions src/providers/delimitedtext/CMakeLists.txt
Expand Up @@ -3,6 +3,7 @@
# Files

SET (DTEXT_SRCS
qgsdelimitedtextfeatureiterator.cpp
qgsdelimitedtextprovider.cpp
qgsdelimitedtextsourceselect.cpp
)
Expand Down
236 changes: 236 additions & 0 deletions src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
@@ -0,0 +1,236 @@
#include "qgsdelimitedtextfeatureiterator.h"

#include "qgsdelimitedtextprovider.h"

#include "qgsgeometry.h"

#include <QTextStream>

QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTextProvider* p, const QgsFeatureRequest& request )
: QgsAbstractFeatureIterator( request ), P( p )
{
rewind();
}

QgsDelimitedTextFeatureIterator::~QgsDelimitedTextFeatureIterator()
{
close();
}

bool QgsDelimitedTextFeatureIterator::nextFeature( QgsFeature& feature )
{
// before we do anything else, assume that there's something wrong with
// the feature
feature.setValid( false );

if ( mClosed )
return false;

while ( !P->mStream->atEnd() )
{
QString line = P->readLine( P->mStream ); // Default local 8 bit encoding
if ( line.isEmpty() )
continue;

// lex the tokens from the current data line
QStringList tokens = P->splitLine( line );

while ( tokens.size() < P->mFieldCount )
tokens.append( QString::null );

QgsGeometry *geom = 0;

if ( P->mWktFieldIndex >= 0 )
{
geom = loadGeometryWkt( tokens );
}
else if ( P->mXFieldIndex >= 0 && P->mYFieldIndex >= 0 )
{
geom = loadGeometryXY( tokens );
}

if ( !geom && P->mWkbType != QGis::WKBNoGeometry )
{
P->mInvalidLines << line;
continue;
}

mFid++;

// At this point the current feature values are valid

feature.setValid( true );
feature.setFields( &P->attributeFields ); // allow name-based attribute lookups
feature.setFeatureId( mFid );
feature.initAttributes( P->attributeFields.count() );

if ( geom )
feature.setGeometry( geom );

if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
{
const QgsAttributeList& attrs = mRequest.subsetOfAttributes();
for ( QgsAttributeList::const_iterator i = attrs.begin(); i != attrs.end(); ++i )
{
int fieldIdx = *i;
if ( fieldIdx < 0 || fieldIdx >= P->attributeColumns.count() )
continue; // ignore non-existant fields
fetchAttribute( feature, fieldIdx, tokens );
}
}
else
{
for ( int idx = 0; idx < P->attributeFields.count(); ++idx )
fetchAttribute( feature, idx, tokens );
}

// We have a good line, so return
return true;

} // !mStream->atEnd()

// End of the file. If there are any lines that couldn't be
// loaded, display them now.
P->handleInvalidLines();

return false;
}

bool QgsDelimitedTextFeatureIterator::rewind()
{
if ( mClosed )
return false;

// Reset feature id to 0
mFid = 0;
// Skip to first data record
P->mStream->seek( 0 );
int n = P->mFirstDataLine - 1;
while ( n-- > 0 )
P->readLine( P->mStream );

return true;
}

bool QgsDelimitedTextFeatureIterator::close()
{
if ( mClosed )
return false;

mClosed = true;
return true;
}


QgsGeometry* QgsDelimitedTextFeatureIterator::loadGeometryWkt(const QStringList& tokens)
{
QgsGeometry* geom = 0;
try
{
QString sWkt = tokens[P->mWktFieldIndex];
// Remove Z and M coordinates if present, as currently fromWkt doesn't
// support these.
if ( P->mWktHasZM )
{
sWkt.remove( P->mWktZMRegexp ).replace( P->mWktCrdRegexp, "\\1" );
}

geom = QgsGeometry::fromWkt( sWkt );
}
catch ( ... )
{
geom = 0;
}

if ( geom && geom->wkbType() != P->mWkbType )
{
delete geom;
geom = 0;
}
if ( geom && !boundsCheck( geom ) )
{
delete geom;
geom = 0;
}
return geom;
}


QgsGeometry* QgsDelimitedTextFeatureIterator::loadGeometryXY( const QStringList& tokens )
{
QString sX = tokens[P->mXFieldIndex];
QString sY = tokens[P->mYFieldIndex];

if ( !P->mDecimalPoint.isEmpty() )
{
sX.replace( P->mDecimalPoint, "." );
sY.replace( P->mDecimalPoint, "." );
}

bool xOk, yOk;
double x = sX.toDouble( &xOk );
double y = sY.toDouble( &yOk );
if ( xOk && yOk )
{
if ( boundsCheck( x, y ) )
{
return QgsGeometry::fromPoint( QgsPoint( x, y ) );
}
}
return 0;
}



/**
* Check to see if the point is within the selection rectangle
*/
bool QgsDelimitedTextFeatureIterator::boundsCheck( double x, double y )
{
// no selection rectangle or geometry => always in the bounds
if ( mRequest.filterType() != QgsFeatureRequest::FilterRect || (mRequest.flags() & QgsFeatureRequest::NoGeometry) )
return true;

return mRequest.filterRect().contains( QgsPoint( x, y ) );
}

/**
* Check to see if the geometry is within the selection rectangle
*/
bool QgsDelimitedTextFeatureIterator::boundsCheck( QgsGeometry *geom )
{
// no selection rectangle or geometry => always in the bounds
if ( mRequest.filterType() != QgsFeatureRequest::FilterRect || (mRequest.flags() & QgsFeatureRequest::NoGeometry) )
return true;

if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
return geom->intersects( mRequest.filterRect() );
else
return geom->boundingBox().intersects( mRequest.filterRect() );
}


void QgsDelimitedTextFeatureIterator::fetchAttribute( QgsFeature& feature, int fieldIdx, const QStringList& tokens )
{
const QString &value = tokens[P->attributeColumns[fieldIdx]];
QVariant val;
switch ( P->attributeFields[fieldIdx].type() )
{
case QVariant::Int:
if ( !value.isEmpty() )
val = QVariant( value );
else
val = QVariant( P->attributeFields[fieldIdx].type() );
break;
case QVariant::Double:
if ( !value.isEmpty() )
val = QVariant( value.toDouble() );
else
val = QVariant( P->attributeFields[fieldIdx].type() );
break;
default:
val = QVariant( value );
break;
}
feature.setAttribute( fieldIdx, val );
}
40 changes: 40 additions & 0 deletions src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.h
@@ -0,0 +1,40 @@
#ifndef QGSDELIMITEDTEXTFEATUREITERATOR_H
#define QGSDELIMITEDTEXTFEATUREITERATOR_H

#include "qgsfeatureiterator.h"

class QgsDelimitedTextProvider;

class QgsDelimitedTextFeatureIterator : public QgsAbstractFeatureIterator
{
public:
QgsDelimitedTextFeatureIterator( QgsDelimitedTextProvider* p, const QgsFeatureRequest& request );

~QgsDelimitedTextFeatureIterator();

//! fetch next feature, return true on success
virtual bool nextFeature( QgsFeature& feature );

//! reset the iterator to the starting position
virtual bool rewind();

//! end of iterating: free the resources / lock
virtual bool close();

protected:
QgsDelimitedTextProvider* P;

//! Feature id
long mFid;

QgsGeometry* loadGeometryWkt( const QStringList& tokens );
QgsGeometry* loadGeometryXY( const QStringList& tokens );

bool boundsCheck( double x, double y );
bool boundsCheck( QgsGeometry *geom );

void fetchAttribute( QgsFeature& feature, int fieldIdx, const QStringList& tokens );
};


#endif // QGSDELIMITEDTEXTFEATUREITERATOR_H

0 comments on commit 7ed9308

Please sign in to comment.