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 );
82 if ( !userName.isNull() || !password.isNull() )
84 request.setRawHeader(
"Authorization",
"Basic " + QString(
"%1:%2" ).arg( userName ).arg( password ).toAscii().toBase64() );
88 connect( reply, SIGNAL( finished() ),
this, SLOT(
setFinished() ) );
89 connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ),
this, SLOT(
handleProgressEvent( qint64, qint64 ) ) );
92 QProgressDialog* progressDialog = 0;
93 QWidget* mainWindow = 0;
94 QWidgetList topLevelWidgets = qApp->topLevelWidgets();
95 for ( QWidgetList::iterator it = topLevelWidgets.begin(); it != topLevelWidgets.end(); ++it )
97 if (( *it )->objectName() ==
"QgisApp" )
105 progressDialog =
new QProgressDialog(
tr(
"Loading GML data\n%1" ).arg(
mTypeName ),
tr(
"Abort" ), 0, 0, mainWindow );
106 progressDialog->setWindowModality( Qt::ApplicationModal );
107 connect(
this, SIGNAL(
dataReadProgress(
int ) ), progressDialog, SLOT( setValue(
int ) ) );
108 connect(
this, SIGNAL(
totalStepsUpdate(
int ) ), progressDialog, SLOT( setMaximum(
int ) ) );
109 connect( progressDialog, SIGNAL( canceled() ),
this, SLOT(
setFinished() ) );
110 progressDialog->show();
120 QByteArray readData = reply->readAll();
121 if ( readData.size() > 0 )
123 if ( XML_Parse( p, readData.constData(), readData.size(), atEnd ) == 0 )
125 XML_Error errorCode = XML_GetErrorCode( p );
126 QString errorString =
tr(
"Error: %1 on line %2, column %3" )
127 .arg( XML_ErrorString( errorCode ) )
128 .arg( XML_GetCurrentLineNumber( p ) )
129 .arg( XML_GetCurrentColumnNumber( p ) );
133 QCoreApplication::processEvents();
136 QNetworkReply::NetworkError replyError = reply->error();
137 QString replyErrorString = reply->errorString();
140 delete progressDialog;
145 tr(
"GML Getfeature network request failed with error: %1" ).arg( replyErrorString ),
174 XML_Parser p = XML_ParserCreateNS( NULL,
NS_SEPARATOR );
175 XML_SetUserData( p,
this );
179 XML_Parse( p, data.constData(), data.size(), atEnd );
194 if ( totalSteps < 0 )
206 QString elementName( QString::fromUtf8( el ) );
208 QStringList splitName = elementName.split(
NS_SEPARATOR );
209 QString localName = splitName.last();
210 QString ns = splitName.size() > 1 ? splitName.first() :
"";
237 if ( dimension.isEmpty() || !ok )
301 else if ( theParseMode ==
feature
302 && localName.compare(
"attribute", Qt::CaseInsensitive ) == 0 )
312 if (
mEpsg == 0 && ( localName ==
"Point" || localName ==
"MultiPoint" ||
313 localName ==
"LineString" || localName ==
"MultiLineString" ||
314 localName ==
"Polygon" || localName ==
"MultiPolygon" ) )
329 QString elementName( QString::fromUtf8( el ) );
331 QStringList splitName = elementName.split(
NS_SEPARATOR );
332 QString localName = splitName.last();
333 QString ns = splitName.size() > 1 ? splitName.first() :
"";
336 || ( theParseMode ==
posList && (
390 QList<QgsPoint> pointList;
396 if ( pointList.count() == 0 )
414 unsigned char* wkb = 0;
416 QList<unsigned char*> wkbList;
417 QList<int> wkbSizeList;
418 if (
getPointWKB( &wkb, &wkbSize, *( pointList.begin() ) ) != 0 )
437 QList<QgsPoint> pointList;
456 unsigned char* wkb = 0;
458 QList<unsigned char*> wkbList;
459 QList<int> wkbSizeList;
460 if (
getLineWKB( &wkb, &wkbSize, pointList ) != 0 )
477 QList<QgsPoint> pointList;
482 unsigned char* wkb = 0;
484 if (
getRingWKB( &wkb, &wkbSize, pointList ) != 0 )
541 mStringCash.append( QString::fromUtf8( chars, len ) );
548 QMap<QString, QPair<int, QgsField> >::const_iterator att_it =
mThematicAttributes.find( name );
552 switch ( att_it.value().second.type() )
554 case QVariant::Double:
555 var = QVariant( value.toDouble() );
558 var = QVariant( value.toInt() );
560 case QVariant::LongLong:
561 var = QVariant( value.toLongLong() );
564 var = QVariant( value );
575 while ( attr[i] != NULL )
577 if ( strcmp( attr[i],
"srsName" ) == 0 )
579 QString epsgString( attr[i+1] );
580 QString epsgNrString;
581 if ( epsgString.startsWith(
"http" ) )
583 epsgNrString = epsgString.section(
"#", 1, 1 );
587 epsgNrString = epsgString.section(
":", 1, 1 );
590 int eNr = epsgNrString.toInt( &conversionOk );
606 while ( attr[i] != NULL )
608 if ( attributeName.compare( attr[i] ) == 0 )
610 return QString( attr[i+1] );
619 QList<QgsPoint> points;
625 if ( points.size() < 2 )
630 r.
set( points[0], points[1] );
638 QStringList tuples = coordString.split(
mTupleSeparator, QString::SkipEmptyParts );
639 QStringList tuples_coordinates;
641 bool conversionSuccess;
643 QStringList::const_iterator tupleIterator;
644 for ( tupleIterator = tuples.constBegin(); tupleIterator != tuples.constEnd(); ++tupleIterator )
647 if ( tuples_coordinates.size() < 2 )
651 x = tuples_coordinates.at( 0 ).toDouble( &conversionSuccess );
652 if ( !conversionSuccess )
656 y = tuples_coordinates.at( 1 ).toDouble( &conversionSuccess );
657 if ( !conversionSuccess )
661 points.push_back(
QgsPoint( x, y ) );
669 QStringList coordinates = coordString.split(
" ", QString::SkipEmptyParts );
671 if ( coordinates.size() % dimension != 0 )
676 int ncoor = coordinates.size() / dimension;
677 for (
int i = 0; i < ncoor; i++ )
679 bool conversionSuccess;
680 double x = coordinates.value( i * dimension ).toDouble( &conversionSuccess );
681 if ( !conversionSuccess )
685 double y = coordinates.value( i * dimension + 1 ).toDouble( &conversionSuccess );
686 if ( !conversionSuccess )
710 int wkbSize = 1 +
sizeof( int ) + 2 *
sizeof(
double );
712 *wkb =
new unsigned char[wkbSize];
714 double x = point.
x();
715 double y = point.
y();
718 memcpy( &( *wkb )[wkbPosition], &
mEndian, 1 );
720 memcpy( &( *wkb )[wkbPosition], &type,
sizeof(
int ) );
721 wkbPosition +=
sizeof( int );
722 memcpy( &( *wkb )[wkbPosition], &x,
sizeof(
double ) );
723 wkbPosition +=
sizeof( double );
724 memcpy( &( *wkb )[wkbPosition], &y,
sizeof(
double ) );
730 int wkbSize = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
732 *wkb =
new unsigned char[wkbSize];
736 int nPoints = lineCoordinates.size();
739 memcpy( &( *wkb )[wkbPosition], &
mEndian, 1 );
741 memcpy( &( *wkb )[wkbPosition], &type,
sizeof(
int ) );
742 wkbPosition +=
sizeof( int );
743 memcpy( &( *wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
744 wkbPosition +=
sizeof( int );
746 QList<QgsPoint>::const_iterator iter;
747 for ( iter = lineCoordinates.begin(); iter != lineCoordinates.end(); ++iter )
751 memcpy( &( *wkb )[wkbPosition], &x,
sizeof(
double ) );
752 wkbPosition +=
sizeof( double );
753 memcpy( &( *wkb )[wkbPosition], &y,
sizeof(
double ) );
754 wkbPosition +=
sizeof( double );
761 int wkbSize =
sizeof( int ) + ringCoordinates.size() * 2 *
sizeof( double );
763 *wkb =
new unsigned char[wkbSize];
766 int nPoints = ringCoordinates.size();
767 memcpy( &( *wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
768 wkbPosition +=
sizeof( int );
770 QList<QgsPoint>::const_iterator iter;
771 for ( iter = ringCoordinates.begin(); iter != ringCoordinates.end(); ++iter )
775 memcpy( &( *wkb )[wkbPosition], &x,
sizeof(
double ) );
776 wkbPosition +=
sizeof( double );
777 memcpy( &( *wkb )[wkbPosition], &y,
sizeof(
double ) );
778 wkbPosition +=
sizeof( double );
796 memcpy( &(
mCurrentWKB[pos] ), &type,
sizeof(
int ) );
797 pos +=
sizeof( int );
798 memcpy( &(
mCurrentWKB[pos] ), &numLines,
sizeof(
int ) );
799 pos +=
sizeof( int );
830 memcpy( &(
mCurrentWKB[pos] ), &type,
sizeof(
int ) );
831 pos +=
sizeof( int );
832 memcpy( &(
mCurrentWKB[pos] ), &numPoints,
sizeof(
int ) );
833 pos +=
sizeof( int );
864 memcpy( &(
mCurrentWKB[pos] ), &type,
sizeof(
int ) );
865 pos +=
sizeof( int );
866 memcpy( &(
mCurrentWKB[pos] ), &numRings,
sizeof(
int ) );
867 pos +=
sizeof( int );
899 memcpy( &(
mCurrentWKB[pos] ), &type,
sizeof(
int ) );
900 pos +=
sizeof( int );
901 memcpy( &(
mCurrentWKB[pos] ), &numPolys,
sizeof(
int ) );
902 pos +=
sizeof( int );
905 QList< QList<unsigned char*> >::iterator outerWkbIt;
906 QList< QList<int> >::iterator outerSizeIt;
907 QList< unsigned char* >::iterator innerWkbIt;
908 QList< int >::iterator innerSizeIt;
918 memcpy( &(
mCurrentWKB[pos] ), &polygonType,
sizeof(
int ) );
919 pos +=
sizeof( int );
920 numRings = outerWkbIt->size();
921 memcpy( &(
mCurrentWKB[pos] ), &numRings,
sizeof(
int ) );
922 pos +=
sizeof( int );
924 innerWkbIt = outerWkbIt->begin();
925 innerSizeIt = outerSizeIt->begin();
926 for ( ; innerWkbIt != outerWkbIt->end(); ++innerWkbIt, ++innerSizeIt )
928 memcpy( &(
mCurrentWKB[pos] ), *innerWkbIt, *innerSizeIt );
930 delete[] *innerWkbIt;
945 foreach (
int i, list )
962 bool bboxInitialised =
false;
964 for (
int i = 0; i <
mFeatures.size(); ++i )
967 if ( !currentFeature )
971 currentGeometry = currentFeature->
geometry();
972 if ( currentGeometry )
974 if ( !bboxInitialised )
977 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)
QgsFeature * mCurrentFeature
void setAttribute(const QString &name, const QString &value)
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'.
int getFeatures(const QString &uri, QGis::WkbType *wkbType, QgsRectangle *extent=0, const QString &userName=QString(), const QString &password=QString())
Does the Http GET request to the wfs server Supports only UTF-8, UTF-16, ISO-8859-1, ISO-8859-1 XML encodings.
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.