Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Enabled delimitedtext provider again
- Loading branch information
Showing
6 changed files
with
291 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
236 changes: 236 additions & 0 deletions
236
src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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
40
src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.