24 #include <QNetworkRequest>
25 #include <QNetworkReply>
26 #include <QProgressDialog>
37 const QString& typeName,
38 const QString& geometryAttribute,
41 , mTypeName( typeName )
42 , mGeometryAttribute( geometryAttribute )
44 , mCurrentFeature( 0 )
46 , mCurrentWKBSize( 0 )
50 for (
int i = 0; i < fields.
size(); i++ )
58 if ( index != -1 && index <
mTypeName.length() )
74 XML_SetUserData( p,
this );
81 QNetworkRequest request(
mUri );
84 connect( reply, SIGNAL( finished() ),
this, SLOT(
setFinished() ) );
85 connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ),
this, SLOT(
handleProgressEvent( qint64, qint64 ) ) );
88 QProgressDialog* progressDialog = 0;
89 QWidget* mainWindow = 0;
90 QWidgetList topLevelWidgets = qApp->topLevelWidgets();
91 for ( QWidgetList::iterator it = topLevelWidgets.begin(); it != topLevelWidgets.end(); ++it )
93 if (( *it )->objectName() ==
"QgisApp" )
101 progressDialog =
new QProgressDialog(
tr(
"Loading GML data\n%1" ).arg(
mTypeName ),
tr(
"Abort" ), 0, 0, mainWindow );
102 progressDialog->setWindowModality( Qt::ApplicationModal );
103 connect(
this, SIGNAL(
dataReadProgress(
int ) ), progressDialog, SLOT( setValue(
int ) ) );
104 connect(
this, SIGNAL(
totalStepsUpdate(
int ) ), progressDialog, SLOT( setMaximum(
int ) ) );
105 connect( progressDialog, SIGNAL( canceled() ),
this, SLOT(
setFinished() ) );
106 progressDialog->show();
116 QByteArray readData = reply->readAll();
117 if ( readData.size() > 0 )
119 if ( XML_Parse( p, readData.constData(), readData.size(), atEnd ) == 0 )
121 XML_Error errorCode = XML_GetErrorCode( p );
122 QString errorString =
tr(
"Error: %1 on line %2, column %3" )
123 .arg( XML_ErrorString( errorCode ) )
124 .arg( XML_GetCurrentLineNumber( p ) )
125 .arg( XML_GetCurrentColumnNumber( p ) );
129 QCoreApplication::processEvents();
132 QNetworkReply::NetworkError replyError = reply->error();
133 QString replyErrorString = reply->errorString();
136 delete progressDialog;
141 tr(
"GML Getfeature network request failed with error: %1" ).arg( replyErrorString ),
170 XML_Parser p = XML_ParserCreateNS( NULL,
NS_SEPARATOR );
171 XML_SetUserData( p,
this );
175 XML_Parse( p, data.constData(), data.size(), atEnd );
190 if ( totalSteps < 0 )
202 QString elementName( QString::fromUtf8( el ) );
204 QStringList splitName = elementName.split(
NS_SEPARATOR );
205 QString localName = splitName.last();
206 QString ns = splitName.size() > 1 ? splitName.first() :
"";
233 if ( dimension.isEmpty() || !ok )
297 if (
mEpsg == 0 && ( localName ==
"Point" || localName ==
"MultiPoint" ||
298 localName ==
"LineString" || localName ==
"MultiLineString" ||
299 localName ==
"Polygon" || localName ==
"MultiPolygon" ) )
314 QString elementName( QString::fromUtf8( el ) );
316 QStringList splitName = elementName.split(
NS_SEPARATOR );
317 QString localName = splitName.last();
318 QString ns = splitName.size() > 1 ? splitName.first() :
"";
321 || ( theParseMode ==
posList && (
336 switch ( att_it.value().second.type() )
338 case QVariant::Double:
344 case QVariant::LongLong:
397 QList<QgsPoint> pointList;
418 unsigned char* wkb = 0;
420 QList<unsigned char*> wkbList;
421 QList<int> wkbSizeList;
422 if (
getPointWKB( &wkb, &wkbSize, *( pointList.begin() ) ) != 0 )
441 QList<QgsPoint> pointList;
460 unsigned char* wkb = 0;
462 QList<unsigned char*> wkbList;
463 QList<int> wkbSizeList;
464 if (
getLineWKB( &wkb, &wkbSize, pointList ) != 0 )
481 QList<QgsPoint> pointList;
486 unsigned char* wkb = 0;
488 if (
getRingWKB( &wkb, &wkbSize, pointList ) != 0 )
545 mStringCash.append( QString::fromUtf8( chars, len ) );
552 while ( attr[i] != NULL )
554 if ( strcmp( attr[i],
"srsName" ) == 0 )
556 QString epsgString( attr[i+1] );
557 QString epsgNrString;
558 if ( epsgString.startsWith(
"http" ) )
560 epsgNrString = epsgString.section(
"#", 1, 1 );
564 epsgNrString = epsgString.section(
":", 1, 1 );
567 int eNr = epsgNrString.toInt( &conversionOk );
583 while ( attr[i] != NULL )
585 if ( attributeName.compare( attr[i] ) == 0 )
587 return QString( attr[i+1] );
596 QList<QgsPoint> points;
602 if ( points.size() < 2 )
607 r.
set( points[0], points[1] );
615 QStringList tuples = coordString.split(
mTupleSeparator, QString::SkipEmptyParts );
616 QStringList tuples_coordinates;
618 bool conversionSuccess;
620 QStringList::const_iterator tupleIterator;
621 for ( tupleIterator = tuples.constBegin(); tupleIterator != tuples.constEnd(); ++tupleIterator )
624 if ( tuples_coordinates.size() < 2 )
628 x = tuples_coordinates.at( 0 ).toDouble( &conversionSuccess );
629 if ( !conversionSuccess )
633 y = tuples_coordinates.at( 1 ).toDouble( &conversionSuccess );
634 if ( !conversionSuccess )
638 points.push_back(
QgsPoint( x, y ) );
646 QStringList coordinates = coordString.split(
" ", QString::SkipEmptyParts );
648 if ( coordinates.size() % dimension != 0 )
653 int ncoor = coordinates.size() / dimension;
654 for (
int i = 0; i < ncoor; i++ )
656 bool conversionSuccess;
657 double x = coordinates.value( i * dimension ).toDouble( &conversionSuccess );
658 if ( !conversionSuccess )
662 double y = coordinates.value( i * dimension + 1 ).toDouble( &conversionSuccess );
663 if ( !conversionSuccess )
687 int wkbSize = 1 +
sizeof( int ) + 2 *
sizeof(
double );
689 *wkb =
new unsigned char[wkbSize];
691 double x = point.
x();
692 double y = point.
y();
695 memcpy( &( *wkb )[wkbPosition], &
mEndian, 1 );
697 memcpy( &( *wkb )[wkbPosition], &type,
sizeof(
int ) );
698 wkbPosition +=
sizeof( int );
699 memcpy( &( *wkb )[wkbPosition], &x,
sizeof(
double ) );
700 wkbPosition +=
sizeof( double );
701 memcpy( &( *wkb )[wkbPosition], &y,
sizeof(
double ) );
707 int wkbSize = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
709 *wkb =
new unsigned char[wkbSize];
713 int nPoints = lineCoordinates.size();
716 memcpy( &( *wkb )[wkbPosition], &
mEndian, 1 );
718 memcpy( &( *wkb )[wkbPosition], &type,
sizeof(
int ) );
719 wkbPosition +=
sizeof( int );
720 memcpy( &( *wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
721 wkbPosition +=
sizeof( int );
723 QList<QgsPoint>::const_iterator iter;
724 for ( iter = lineCoordinates.begin(); iter != lineCoordinates.end(); ++iter )
728 memcpy( &( *wkb )[wkbPosition], &x,
sizeof(
double ) );
729 wkbPosition +=
sizeof( double );
730 memcpy( &( *wkb )[wkbPosition], &y,
sizeof(
double ) );
731 wkbPosition +=
sizeof( double );
738 int wkbSize =
sizeof( int ) + ringCoordinates.size() * 2 *
sizeof( double );
740 *wkb =
new unsigned char[wkbSize];
743 int nPoints = ringCoordinates.size();
744 memcpy( &( *wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
745 wkbPosition +=
sizeof( int );
747 QList<QgsPoint>::const_iterator iter;
748 for ( iter = ringCoordinates.begin(); iter != ringCoordinates.end(); ++iter )
752 memcpy( &( *wkb )[wkbPosition], &x,
sizeof(
double ) );
753 wkbPosition +=
sizeof( double );
754 memcpy( &( *wkb )[wkbPosition], &y,
sizeof(
double ) );
755 wkbPosition +=
sizeof( double );
773 memcpy( &(
mCurrentWKB[pos] ), &type,
sizeof(
int ) );
774 pos +=
sizeof( int );
775 memcpy( &(
mCurrentWKB[pos] ), &numLines,
sizeof(
int ) );
776 pos +=
sizeof( int );
807 memcpy( &(
mCurrentWKB[pos] ), &type,
sizeof(
int ) );
808 pos +=
sizeof( int );
809 memcpy( &(
mCurrentWKB[pos] ), &numPoints,
sizeof(
int ) );
810 pos +=
sizeof( int );
841 memcpy( &(
mCurrentWKB[pos] ), &type,
sizeof(
int ) );
842 pos +=
sizeof( int );
843 memcpy( &(
mCurrentWKB[pos] ), &numRings,
sizeof(
int ) );
844 pos +=
sizeof( int );
876 memcpy( &(
mCurrentWKB[pos] ), &type,
sizeof(
int ) );
877 pos +=
sizeof( int );
878 memcpy( &(
mCurrentWKB[pos] ), &numPolys,
sizeof(
int ) );
879 pos +=
sizeof( int );
882 QList< QList<unsigned char*> >::iterator outerWkbIt;
883 QList< QList<int> >::iterator outerSizeIt;
884 QList< unsigned char* >::iterator innerWkbIt;
885 QList< int >::iterator innerSizeIt;
895 memcpy( &(
mCurrentWKB[pos] ), &polygonType,
sizeof(
int ) );
896 pos +=
sizeof( int );
897 numRings = outerWkbIt->size();
898 memcpy( &(
mCurrentWKB[pos] ), &numRings,
sizeof(
int ) );
899 pos +=
sizeof( int );
901 innerWkbIt = outerWkbIt->begin();
902 innerSizeIt = outerSizeIt->begin();
903 for ( ; innerWkbIt != outerWkbIt->end(); ++innerWkbIt, ++innerSizeIt )
905 memcpy( &(
mCurrentWKB[pos] ), *innerWkbIt, *innerSizeIt );
907 delete[] *innerWkbIt;
922 foreach (
int i, list )
939 bool bboxInitialised =
false;
941 for (
int i = 0; i <
mFeatures.size(); ++i )
944 if ( !currentFeature )
948 currentGeometry = currentFeature->
geometry();
949 if ( currentGeometry )
951 if ( !bboxInitialised )
954 bboxInitialised =
true;
QgsFeatureId id() const
Get the feature id for this feature.
void unionRect(const QgsRectangle &rect)
updates rectangle to include passed argument
QgsRectangle mCurrentExtent
A rectangle specified with double values.
int createMultiLineFromFragments()
Creates a multiline from the information in mCurrentWKBFragments and mCurrentWKBFragmentSizes.
bool isEmpty() const
test if rectangle is empty
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
QgsApplication::endian_t mEndian
QString mGeometryAttribute
Name of geometry attribute.
int pointsFromPosListString(QList< QgsPoint > &points, const QString &coordString, int dimension) const
Creates a set of points from a gml:posList or gml:pos coordinate string.
int createMultiPolygonFromFragments()
int pointsFromString(QList< QgsPoint > &points, const QString &coordString) const
static void start(void *data, const XML_Char *el, const XML_Char **attr)
int getFeatures(const QString &uri, QGis::WkbType *wkbType, QgsRectangle *extent=0)
Does the Http GET request to the wfs server Supports only UTF-8, UTF-16, ISO-8859-1, ISO-8859-1 XML encodings.
QgsFeature * mCurrentFeature
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
void characters(const XML_Char *chars, int len)
Container of fields for a vector layer.
void setAttributes(const QgsAttributes &attrs)
bool setAttribute(int field, const QVariant &attr)
Set an attribute by id.
WkbType
Used for symbology operations.
void dataReadProgress(int progress)
int getLineWKB(unsigned char **wkb, int *size, const QList< QgsPoint > &lineCoordinates) const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
static endian_t endian()
Returns whether this machine uses big or little endian.
void endElement(const XML_Char *el)
QString mCurrentFeatureId
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
void totalStepsUpdate(int totalSteps)
QString mCoordinateSeparator
Coordinate separator for coordinate strings.
void set(const QgsPoint &p1, const QgsPoint &p2)
Set the rectangle from two QgsPoints.
bool createFromOgcWmsCrs(QString theCrs)
Set up this CRS from the given OGC CRS.
void setGeometry(const QgsGeometry &geom)
Set this feature's geometry from another QgsGeometry object (deep copy)
void dataProgressAndSteps(int progress, int totalSteps)
QgsGml(const QString &typeName, const QString &geometryAttribute, const QgsFields &fields)
unsigned char * mCurrentWKB
The total WKB for a feature.
static void chars(void *data, const XML_Char *chars, int len)
QString mTupleSeparator
Tuple separator for coordinate strings.
int createPolygonFromFragments()
int getRingWKB(unsigned char **wkb, int *size, const QList< QgsPoint > &ringCoordinates) const
A class to represent a point geometry.
int totalWKBFragmentSize() const
Adds all the integers contained in mCurrentWKBFragmentSizes.
static void end(void *data, const XML_Char *el)
QStack< ParseMode > mParseModeStack
Keep track about the most important nested elements.
int createBBoxFromCoordinateString(QgsRectangle &bb, const QString &coordString) const
Creates a rectangle from a coordinate string.
const QString GML_NAMESPACE
void setValid(bool validity)
Set the validity of the feature.
QgsRectangle boundingBox()
Returns the bounding box of this feature.
ParseMode mCoorMode
Coordinates mode, coordinate or posList.
int createMultiPointFromFragments()
static QgsNetworkAccessManager * instance()
returns a pointer to the single instance
QMap< QgsFeatureId, QgsFeature * > mFeatures
The features of the layer, map of feature maps for each feature type.
QVector< QVariant > QgsAttributes
void startElement(const XML_Char *el, const XML_Char **attr)
XML handler methods.
void handleProgressEvent(qint64 progress, qint64 totalSteps)
Takes progress value and total steps and emit signals 'dataReadProgress' and 'totalStepUpdate'.
Class for storing a coordinate reference system (CRS)
QString readAttribute(const QString &attributeName, const XML_Char **attr) const
Reads attribute as string.
int size() const
Return number of items.
static QgsGeometry * fromRect(const QgsRectangle &rect)
construct geometry from a rectangle
bool mFinished
True if the request is finished.
QList< QList< unsigned char * > > mCurrentWKBFragments
WKB intermediate storage during parsing.
int mEpsg
EPSG of parsed features geometries.
int getPointWKB(unsigned char **wkb, int *size, const QgsPoint &) const
QgsRectangle mExtent
Bounding box of the layer.
int readEpsgFromAttribute(int &epsgNr, const XML_Char **attr) const
Reads attribute srsName="EpsgCrsId:...".
QList< QList< int > > mCurrentWKBFragmentSizes
Similar to mCurrentWKB, but only the size.
int mDimension
Number of dimensions in pos or posList.
int pointsFromCoordinateString(QList< QgsPoint > &points, const QString &coordString) const
Creates a set of points from a coordinate string.
QMap< QString, QPair< int, QgsField > > mThematicAttributes
int mCurrentWKBSize
The total WKB size for a feature.
QMap< QgsFeatureId, QString > mIdMap
Stores the relation between provider ids and WFS server ids.
QgsCoordinateReferenceSystem crs() const
Returns features spatial reference system.
QString mStringCash
This contains the character data if an important element has been encountered.
void setGeometryAndOwnership(unsigned char *geom, size_t length)
Set this feature's geometry from WKB.
void calculateExtentFromFeatures()
This function evaluates the layer bounding box from the features and sets it to mExtent.