QGIS API Documentation
qgsgml.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgml.cpp
3  ---------------------
4  begin : February 2013
5  copyright : (C) 2013 by Radim Blazek
6  email : radim dot blazek at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 #include "qgsgml.h"
16 #include "qgsauthmanager.h"
17 #include "qgsrectangle.h"
19 #include "qgsgeometry.h"
20 #include "qgslogger.h"
21 #include "qgsmessagelog.h"
23 #include "qgswkbptr.h"
24 
25 #include <QBuffer>
26 #include <QList>
27 #include <QNetworkRequest>
28 #include <QNetworkReply>
29 #include <QProgressDialog>
30 #include <QSet>
31 #include <QSettings>
32 #include <QUrl>
33 
34 #include <limits>
35 
36 static const char NS_SEPARATOR = '?';
37 static const char* GML_NAMESPACE = "http://www.opengis.net/gml";
38 static const char* GML32_NAMESPACE = "http://www.opengis.net/gml/3.2";
39 
41  const QString& typeName,
42  const QString& geometryAttribute,
43  const QgsFields & fields )
44  : QObject()
45  , mParser( typeName, geometryAttribute, fields )
46  , mTypeName( typeName )
47  , mFinished( false )
48 {
49  int index = mTypeName.indexOf( ':' );
50  if ( index != -1 && index < mTypeName.length() )
51  {
52  mTypeName = mTypeName.mid( index + 1 );
53  }
54 }
55 
57 {
58 }
59 
60 int QgsGml::getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangle* extent, const QString& userName, const QString& password , const QString& authcfg )
61 {
62  //start with empty extent
63  mExtent.setMinimal();
64 
65  QNetworkRequest request( uri );
66  if ( !authcfg.isEmpty() )
67  {
68  if ( !QgsAuthManager::instance()->updateNetworkRequest( request, authcfg ) )
69  {
71  tr( "GML Getfeature network request update failed for authcfg %1" ).arg( authcfg ),
72  tr( "Network" ),
74  );
75  return 1;
76  }
77  }
78  else if ( !userName.isNull() || !password.isNull() )
79  {
80  request.setRawHeader( "Authorization", "Basic " + QString( "%1:%2" ).arg( userName, password ).toAscii().toBase64() );
81  }
83 
84  connect( reply, SIGNAL( finished() ), this, SLOT( setFinished() ) );
85  connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( handleProgressEvent( qint64, qint64 ) ) );
86 
87  //find out if there is a QGIS main window. If yes, display a progress dialog
88  QProgressDialog* progressDialog = nullptr;
89  QWidget* mainWindow = nullptr;
90  QWidgetList topLevelWidgets = qApp->topLevelWidgets();
91  for ( QWidgetList::const_iterator it = topLevelWidgets.constBegin(); it != topLevelWidgets.constEnd(); ++it )
92  {
93  if (( *it )->objectName() == "QgisApp" )
94  {
95  mainWindow = *it;
96  break;
97  }
98  }
99  if ( mainWindow )
100  {
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();
107  }
108 
109  int atEnd = 0;
110  while ( !atEnd )
111  {
112  if ( mFinished )
113  {
114  atEnd = 1;
115  }
116  QByteArray readData = reply->readAll();
117  if ( !readData.isEmpty() )
118  {
119  mParser.processData( readData, atEnd );
120  }
122  }
123 
124  fillMapsFromParser();
125 
126  QNetworkReply::NetworkError replyError = reply->error();
127  QString replyErrorString = reply->errorString();
128 
129  delete reply;
130  delete progressDialog;
131 
132  if ( replyError )
133  {
135  tr( "GML Getfeature network request failed with error: %1" ).arg( replyErrorString ),
136  tr( "Network" ),
138  );
139  return 1;
140  }
141 
142  *wkbType = mParser.wkbType();
143 
144  if ( *wkbType != QGis::WKBNoGeometry )
145  {
146  if ( mExtent.isEmpty() )
147  {
148  //reading of bbox from the server failed, so we calculate it less efficiently by evaluating the features
149  calculateExtentFromFeatures();
150  }
151  }
152 
153  if ( extent )
154  *extent = mExtent;
155 
156  return 0;
157 }
158 
159 int QgsGml::getFeatures( const QByteArray &data, QGis::WkbType* wkbType, QgsRectangle* extent )
160 {
161  mExtent.setMinimal();
162 
163  mParser.processData( data, true /* atEnd */ );
164 
165  fillMapsFromParser();
166 
167  *wkbType = mParser.wkbType();
168 
169  if ( extent )
170  *extent = mExtent;
171 
172  return 0;
173 }
174 
175 void QgsGml::fillMapsFromParser()
176 {
178  Q_FOREACH ( QgsGmlStreamingParser::QgsGmlFeaturePtrGmlIdPair featPair, features )
179  {
180  QgsFeature* feat = featPair.first;
181  const QString& gmlId = featPair.second;
182  mFeatures.insert( feat->id(), feat );
183  if ( !gmlId.isEmpty() )
184  {
185  mIdMap.insert( feat->id(), gmlId );
186  }
187  }
188 }
189 
190 void QgsGml::setFinished()
191 {
192  mFinished = true;
193 }
194 
195 void QgsGml::handleProgressEvent( qint64 progress, qint64 totalSteps )
196 {
197  if ( totalSteps < 0 )
198  {
199  totalSteps = 0;
200  progress = 0;
201  }
202  emit totalStepsUpdate( totalSteps );
203  emit dataReadProgress( progress );
204  emit dataProgressAndSteps( progress, totalSteps );
205 }
206 
207 void QgsGml::calculateExtentFromFeatures()
208 {
209  if ( mFeatures.size() < 1 )
210  {
211  return;
212  }
213 
214  QgsFeature* currentFeature = nullptr;
215  const QgsGeometry* currentGeometry = nullptr;
216  bool bboxInitialised = false; //gets true once bbox has been set to the first geometry
217 
218  for ( int i = 0; i < mFeatures.size(); ++i )
219  {
220  currentFeature = mFeatures[i];
221  if ( !currentFeature )
222  {
223  continue;
224  }
225  currentGeometry = currentFeature->constGeometry();
226  if ( currentGeometry )
227  {
228  if ( !bboxInitialised )
229  {
230  mExtent = currentGeometry->boundingBox();
231  bboxInitialised = true;
232  }
233  else
234  {
235  mExtent.unionRect( currentGeometry->boundingBox() );
236  }
237  }
238  }
239 }
240 
242 {
244  if ( mParser.getEPSGCode() != 0 )
245  {
246  crs.createFromOgcWmsCrs( QString( "EPSG:%1" ).arg( mParser.getEPSGCode() ) );
247  }
248  return crs;
249 }
250 
251 
252 
253 
254 
256  const QString& geometryAttribute,
257  const QgsFields & fields,
258  AxisOrientationLogic axisOrientationLogic,
259  bool invertAxisOrientation )
260  : mTypeName( typeName )
261  , mTypeNameBA( mTypeName.toUtf8() )
262  , mTypeNamePtr( mTypeNameBA.constData() )
263  , mWkbType( QGis::WKBUnknown )
264  , mGeometryAttribute( geometryAttribute )
265  , mGeometryAttributeBA( geometryAttribute.toUtf8() )
266  , mGeometryAttributePtr( mGeometryAttributeBA.constData() )
267  , mFields( fields )
268  , mIsException( false )
269  , mParseDepth( 0 )
270  , mCurrentFeature( nullptr )
271  , mFeatureCount( 0 )
272  , mCurrentWKB( nullptr, 0 )
273  , mBoundedByNullFound( false )
274  , mDimension( 2 )
275  , mCoorMode( coordinate )
276  , mEpsg( 0 )
277  , mGMLNameSpaceURIPtr( nullptr )
278  , mAxisOrientationLogic( axisOrientationLogic )
279  , mInvertAxisOrientationRequest( invertAxisOrientation )
280  , mInvertAxisOrientation( invertAxisOrientation )
281  , mNumberReturned( -1 )
282  , mNumberMatched( -1 )
283 {
284  mThematicAttributes.clear();
285  for ( int i = 0; i < fields.size(); i++ )
286  {
287  mThematicAttributes.insert( fields[i].name(), qMakePair( i, fields[i] ) );
288  }
289 
290  mEndian = QgsApplication::endian();
291 
292  int index = mTypeName.indexOf( ':' );
293  if ( index != -1 && index < mTypeName.length() )
294  {
295  mTypeName = mTypeName.mid( index + 1 );
296  mTypeNameBA = mTypeName.toUtf8();
297  mTypeNamePtr = mTypeNameBA.constData();
298  }
299 
300  mParser = XML_ParserCreateNS( nullptr, NS_SEPARATOR );
301  XML_SetUserData( mParser, this );
302  XML_SetElementHandler( mParser, QgsGmlStreamingParser::start, QgsGmlStreamingParser::end );
303  XML_SetCharacterDataHandler( mParser, QgsGmlStreamingParser::chars );
304 }
305 
307 {
308  XML_ParserFree( mParser );
309 
310  // Normally a sane user of this class should have consumed everything...
311  Q_FOREACH ( QgsGmlFeaturePtrGmlIdPair featPair, mFeatureList )
312  {
313  delete featPair.first;
314  }
315 }
316 
317 bool QgsGmlStreamingParser::processData( const QByteArray& data, bool atEnd )
318 {
319  if ( XML_Parse( mParser, data.data(), data.size(), atEnd ) == 0 )
320  {
321  XML_Error errorCode = XML_GetErrorCode( mParser );
322  QString errorString = QObject::tr( "Error: %1 on line %2, column %3" )
323  .arg( XML_ErrorString( errorCode ) )
324  .arg( XML_GetCurrentLineNumber( mParser ) )
325  .arg( XML_GetCurrentColumnNumber( mParser ) );
326  QgsMessageLog::logMessage( errorString, QObject::tr( "WFS" ) );
327 
328  return false;
329  }
330 
331  return true;
332 }
333 
335 {
336  QVector<QgsGmlFeaturePtrGmlIdPair> ret = mFeatureList;
337  mFeatureList.clear();
338  return ret;
339 }
340 
341 #define LOCALNAME_EQUALS(string_constant) \
342  ( localNameLen == strlen( string_constant ) && memcmp(pszLocalName, string_constant, localNameLen) == 0 )
343 
344 void QgsGmlStreamingParser::startElement( const XML_Char* el, const XML_Char** attr )
345 {
346  const int elLen = ( int )strlen( el );
347  const char* pszSep = strchr( el, NS_SEPARATOR );
348  const char* pszLocalName = ( pszSep ) ? pszSep + 1 : el;
349  const int nsLen = ( pszSep ) ? ( int )( pszSep - el ) : 0;
350  const int localNameLen = ( pszSep ) ? ( int )( elLen - nsLen ) - 1 : elLen;
351  ParseMode theParseMode( mParseModeStack.isEmpty() ? none : mParseModeStack.top() );
352 
353  // Figure out if the GML namespace is GML_NAMESPACE or GML32_NAMESPACE
354  if ( mGMLNameSpaceURIPtr == nullptr && pszSep != nullptr )
355  {
356  if ( nsLen == ( int )strlen( GML_NAMESPACE ) && memcmp( el, GML_NAMESPACE, nsLen ) == 0 )
357  {
358  mGMLNameSpaceURI = GML_NAMESPACE;
359  mGMLNameSpaceURIPtr = GML_NAMESPACE;
360  }
361  else if ( nsLen == ( int )strlen( GML32_NAMESPACE ) && memcmp( el, GML32_NAMESPACE, nsLen ) == 0 )
362  {
363  mGMLNameSpaceURI = GML32_NAMESPACE;
364  mGMLNameSpaceURIPtr = GML32_NAMESPACE;
365  }
366  }
367 
368  const bool isGMLNS = ( nsLen == mGMLNameSpaceURI.size() && memcmp( el, mGMLNameSpaceURIPtr, nsLen ) == 0 );
369  bool isGeom = false;
370  if ( isGMLNS && LOCALNAME_EQUALS( "coordinates" ) )
371  {
372  mParseModeStack.push( coordinate );
373  mCoorMode = QgsGmlStreamingParser::coordinate;
374  mStringCash.clear();
375  mCoordinateSeparator = readAttribute( "cs", attr );
376  if ( mCoordinateSeparator.isEmpty() )
377  {
378  mCoordinateSeparator = ',';
379  }
380  mTupleSeparator = readAttribute( "ts", attr );
381  if ( mTupleSeparator.isEmpty() )
382  {
383  mTupleSeparator = ' ';
384  }
385  }
386  else if ( isGMLNS &&
387  ( LOCALNAME_EQUALS( "pos" ) || LOCALNAME_EQUALS( "posList" ) ) )
388  {
389  mParseModeStack.push( QgsGmlStreamingParser::posList );
390  mCoorMode = QgsGmlStreamingParser::posList;
391  mStringCash.clear();
392  QString dimension = readAttribute( "srsDimension", attr );
393  bool ok;
394  mDimension = dimension.toInt( &ok );
395  if ( dimension.isEmpty() || !ok )
396  {
397  mDimension = 2;
398  }
399  }
400  else if ( localNameLen == mGeometryAttribute.size() &&
401  memcmp( pszLocalName, mGeometryAttributePtr, localNameLen ) == 0 )
402  {
403  mParseModeStack.push( QgsGmlStreamingParser::geometry );
404  }
405  //else if ( mParseModeStack.size() == 0 && elementName == mGMLNameSpaceURI + NS_SEPARATOR + "boundedBy" )
406  else if ( isGMLNS && LOCALNAME_EQUALS( "boundedBy" ) )
407  {
408  mParseModeStack.push( QgsGmlStreamingParser::boundingBox );
409  mCurrentExtent = QgsRectangle();
410  mBoundedByNullFound = false;
411  }
412  else if ( theParseMode == boundingBox &&
413  isGMLNS && LOCALNAME_EQUALS( "null" ) )
414  {
415  mParseModeStack.push( QgsGmlStreamingParser::null );
416  mBoundedByNullFound = true;
417  }
418  else if ( theParseMode == boundingBox &&
419  isGMLNS && LOCALNAME_EQUALS( "Envelope" ) )
420  {
421  isGeom = true;
422  mParseModeStack.push( QgsGmlStreamingParser::envelope );
423  }
424  else if ( theParseMode == envelope &&
425  isGMLNS && LOCALNAME_EQUALS( "lowerCorner" ) )
426  {
427  mParseModeStack.push( QgsGmlStreamingParser::lowerCorner );
428  mStringCash.clear();
429  }
430  else if ( theParseMode == envelope &&
431  isGMLNS && LOCALNAME_EQUALS( "upperCorner" ) )
432  {
433  mParseModeStack.push( QgsGmlStreamingParser::upperCorner );
434  mStringCash.clear();
435  }
436  else if ( theParseMode == none &&
437  localNameLen == mTypeName.size() && memcmp( pszLocalName, mTypeNamePtr, mTypeName.size() ) == 0 )
438  {
439  Q_ASSERT( !mCurrentFeature );
440  mCurrentFeature = new QgsFeature( mFeatureCount );
441  mCurrentFeature->setFields( mFields ); // allow name-based attribute lookups
442  QgsAttributes attributes( mThematicAttributes.size() ); //add empty attributes
443  mCurrentFeature->setAttributes( attributes );
444  mParseModeStack.push( QgsGmlStreamingParser::feature );
445  mCurrentFeatureId = readAttribute( "fid", attr );
446  if ( mCurrentFeatureId.isEmpty() )
447  {
448  // Figure out if the GML namespace is GML_NAMESPACE or GML32_NAMESPACE
449  // (should happen only for the first features if there's no gml: element
450  // encountered before
451  if ( mGMLNameSpaceURI.isEmpty() )
452  {
453  mCurrentFeatureId = readAttribute( QString( GML_NAMESPACE ) + NS_SEPARATOR + "id", attr );
454  if ( !mCurrentFeatureId.isEmpty() )
455  {
456  mGMLNameSpaceURI = GML_NAMESPACE;
457  mGMLNameSpaceURIPtr = GML_NAMESPACE;
458  }
459  else
460  {
461  mCurrentFeatureId = readAttribute( QString( GML32_NAMESPACE ) + NS_SEPARATOR + "id", attr );
462  if ( !mCurrentFeatureId.isEmpty() )
463  {
464  mGMLNameSpaceURI = GML32_NAMESPACE;
465  mGMLNameSpaceURIPtr = GML32_NAMESPACE;
466  }
467  }
468  }
469  else
470  mCurrentFeatureId = readAttribute( mGMLNameSpaceURI + NS_SEPARATOR + "id", attr );
471  }
472  }
473 
474  else if ( theParseMode == boundingBox && isGMLNS && LOCALNAME_EQUALS( "Box" ) )
475  {
476  isGeom = true;
477  }
478  else if ( isGMLNS && LOCALNAME_EQUALS( "Point" ) )
479  {
480  isGeom = true;
481  }
482  else if ( isGMLNS && LOCALNAME_EQUALS( "LineString" ) )
483  {
484  isGeom = true;
485  }
486  else if ( isGMLNS &&
487  localNameLen == strlen( "Polygon" ) && memcmp( pszLocalName, "Polygon", localNameLen ) == 0 )
488  {
489  isGeom = true;
490  mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
491  }
492  else if ( isGMLNS && LOCALNAME_EQUALS( "MultiPoint" ) )
493  {
494  isGeom = true;
495  mParseModeStack.push( QgsGmlStreamingParser::multiPoint );
496  //we need one nested list for intermediate WKB
497  mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
498  }
499  else if ( isGMLNS && ( LOCALNAME_EQUALS( "MultiLineString" ) || LOCALNAME_EQUALS( "MultiCurve" ) ) )
500  {
501  isGeom = true;
502  mParseModeStack.push( QgsGmlStreamingParser::multiLine );
503  //we need one nested list for intermediate WKB
504  mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
505  }
506  else if ( isGMLNS && ( LOCALNAME_EQUALS( "MultiPolygon" ) || LOCALNAME_EQUALS( "MultiSurface" ) ) )
507  {
508  isGeom = true;
509  mParseModeStack.push( QgsGmlStreamingParser::multiPolygon );
510  }
511  else if ( theParseMode == feature )
512  {
513  QString localName( QString::fromUtf8( pszLocalName, localNameLen ) );
514  if ( mThematicAttributes.contains( localName ) )
515  {
516  mParseModeStack.push( QgsGmlStreamingParser::attribute );
517  mAttributeName = localName;
518  mStringCash.clear();
519  }
520  else
521  {
522  // QGIS server (2.2) is using:
523  // <Attribute value="My description" name="desc"/>
524  if ( localName.compare( "attribute", Qt::CaseInsensitive ) == 0 )
525  {
526  QString name = readAttribute( "name", attr );
527  if ( mThematicAttributes.contains( name ) )
528  {
529  QString value = readAttribute( "value", attr );
530  setAttribute( name, value );
531  }
532  }
533  }
534  }
535  else if ( mParseDepth == 0 && LOCALNAME_EQUALS( "FeatureCollection" ) )
536  {
537  QString numberReturned = readAttribute( "numberReturned", attr ); // WFS 2.0
538  if ( numberReturned.isEmpty() )
539  numberReturned = readAttribute( "numberOfFeatures", attr ); // WFS 1.1
540  bool conversionOk;
541  mNumberReturned = numberReturned.toInt( &conversionOk );
542  if ( !conversionOk )
543  mNumberReturned = -1;
544 
545  QString numberMatched = readAttribute( "numberMatched", attr ); // WFS 2.0
546  mNumberMatched = numberMatched.toInt( &conversionOk );
547  if ( !conversionOk ) // likely since numberMatched="unknown" is legal
548  mNumberMatched = -1;
549  }
550  else if ( mParseDepth == 0 && LOCALNAME_EQUALS( "ExceptionReport" ) )
551  {
552  mIsException = true;
553  mParseModeStack.push( QgsGmlStreamingParser::ExceptionReport );
554  }
555  else if ( mIsException && LOCALNAME_EQUALS( "ExceptionText" ) )
556  {
557  mStringCash.clear();
558  mParseModeStack.push( QgsGmlStreamingParser::ExceptionText );
559  }
560 
561  if ( mEpsg == 0 && isGeom )
562  {
563  if ( readEpsgFromAttribute( mEpsg, attr ) != 0 )
564  {
565  QgsDebugMsg( "error, could not get epsg id" );
566  }
567  else
568  {
569  QgsDebugMsg( QString( "mEpsg = %1" ).arg( mEpsg ) );
570  }
571  }
572 
573  mParseDepth ++;
574 }
575 
576 void QgsGmlStreamingParser::endElement( const XML_Char* el )
577 {
578  mParseDepth --;
579 
580  const int elLen = ( int )strlen( el );
581  const char* pszSep = strchr( el, NS_SEPARATOR );
582  const char* pszLocalName = ( pszSep ) ? pszSep + 1 : el;
583  const int nsLen = ( pszSep ) ? ( int )( pszSep - el ) : 0;
584  const int localNameLen = ( pszSep ) ? ( int )( elLen - nsLen ) - 1 : elLen;
585  ParseMode theParseMode( mParseModeStack.isEmpty() ? none : mParseModeStack.top() );
586 
587  const bool isGMLNS = ( nsLen == mGMLNameSpaceURI.size() && memcmp( el, mGMLNameSpaceURIPtr, nsLen ) == 0 );
588 
589  if ( theParseMode == coordinate && isGMLNS && LOCALNAME_EQUALS( "coordinates" ) )
590  {
591  mParseModeStack.pop();
592  }
593  else if ( theParseMode == posList && isGMLNS &&
594  ( LOCALNAME_EQUALS( "pos" ) || LOCALNAME_EQUALS( "posList" ) ) )
595  {
596  mParseModeStack.pop();
597  }
598  else if ( theParseMode == attribute && QString::fromUtf8( pszLocalName, localNameLen ) == mAttributeName ) //add a thematic attribute to the feature
599  {
600  mParseModeStack.pop();
601 
602  setAttribute( mAttributeName, mStringCash );
603  }
604  else if ( theParseMode == geometry && localNameLen == mGeometryAttribute.size() &&
605  memcmp( pszLocalName, mGeometryAttributePtr, localNameLen ) == 0 )
606  {
607  mParseModeStack.pop();
608  }
609  else if ( theParseMode == boundingBox && isGMLNS && LOCALNAME_EQUALS( "boundedBy" ) )
610  {
611  //create bounding box from mStringCash
612  if ( mCurrentExtent.isNull() &&
613  !mBoundedByNullFound &&
614  createBBoxFromCoordinateString( mCurrentExtent, mStringCash ) != 0 )
615  {
616  QgsDebugMsg( "creation of bounding box failed" );
617  }
618 
619  mParseModeStack.pop();
620  }
621  else if ( theParseMode == null && isGMLNS && LOCALNAME_EQUALS( "null" ) )
622  {
623  mParseModeStack.pop();
624  }
625  else if ( theParseMode == envelope && isGMLNS && LOCALNAME_EQUALS( "Envelope" ) )
626  {
627  mParseModeStack.pop();
628  }
629  else if ( theParseMode == lowerCorner && isGMLNS && LOCALNAME_EQUALS( "lowerCorner" ) )
630  {
631  QList<QgsPoint> points;
632  pointsFromPosListString( points, mStringCash, 2 );
633  if ( points.size() == 1 )
634  {
635  mCurrentExtent.setXMinimum( points[0].x() );
636  mCurrentExtent.setYMinimum( points[0].y() );
637  }
638  mParseModeStack.pop();
639  }
640  else if ( theParseMode == upperCorner && isGMLNS && LOCALNAME_EQUALS( "upperCorner" ) )
641  {
642  QList<QgsPoint> points;
643  pointsFromPosListString( points, mStringCash, 2 );
644  if ( points.size() == 1 )
645  {
646  mCurrentExtent.setXMaximum( points[0].x() );
647  mCurrentExtent.setYMaximum( points[0].y() );
648  }
649  mParseModeStack.pop();
650  }
651  else if ( theParseMode == feature && localNameLen == mTypeName.size() &&
652  memcmp( pszLocalName, mTypeNamePtr, mTypeName.size() ) == 0 )
653  {
654  Q_ASSERT( mCurrentFeature );
655  if ( mCurrentWKB.size() > 0 )
656  {
657  QgsGeometry *g = new QgsGeometry();
658  g->fromWkb( mCurrentWKB, mCurrentWKB.size() );
659  mCurrentFeature->setGeometry( g );
660  mCurrentWKB = QgsWkbPtr( nullptr, 0 );
661  }
662  else if ( !mCurrentExtent.isEmpty() )
663  {
664  mCurrentFeature->setGeometry( QgsGeometry::fromRect( mCurrentExtent ) );
665  }
666  else
667  {
668  mCurrentFeature->setGeometry( nullptr );
669  }
670  mCurrentFeature->setValid( true );
671 
672  mFeatureList.push_back( QgsGmlFeaturePtrGmlIdPair( mCurrentFeature, mCurrentFeatureId ) );
673 
674  mCurrentFeature = nullptr;
675  ++mFeatureCount;
676  mParseModeStack.pop();
677  }
678  else if ( isGMLNS && LOCALNAME_EQUALS( "Point" ) )
679  {
680  QList<QgsPoint> pointList;
681  if ( pointsFromString( pointList, mStringCash ) != 0 )
682  {
683  //error
684  }
685 
686  if ( pointList.isEmpty() )
687  return; // error
688 
689  if ( theParseMode == QgsGmlStreamingParser::geometry )
690  {
691  //directly add WKB point to the feature
692  if ( getPointWKB( mCurrentWKB, *( pointList.constBegin() ) ) != 0 )
693  {
694  //error
695  }
696 
697  if ( mWkbType != QGis::WKBMultiPoint ) //keep multitype in case of geometry type mix
698  {
699  mWkbType = QGis::WKBPoint;
700  }
701  }
702  else //multipoint, add WKB as fragment
703  {
704  QgsWkbPtr wkbPtr( nullptr, 0 );
705  if ( getPointWKB( wkbPtr, *( pointList.constBegin() ) ) != 0 )
706  {
707  //error
708  }
709  if ( !mCurrentWKBFragments.isEmpty() )
710  {
711  mCurrentWKBFragments.last().push_back( wkbPtr );
712  }
713  else
714  {
715  QgsDebugMsg( "No wkb fragments" );
716  delete [] wkbPtr;
717  }
718  }
719  }
720  else if ( isGMLNS && ( LOCALNAME_EQUALS( "LineString" ) || LOCALNAME_EQUALS( "LineStringSegment" ) ) )
721  {
722  //add WKB point to the feature
723 
724  QList<QgsPoint> pointList;
725  if ( pointsFromString( pointList, mStringCash ) != 0 )
726  {
727  //error
728  }
729  if ( theParseMode == QgsGmlStreamingParser::geometry )
730  {
731  if ( getLineWKB( mCurrentWKB, pointList ) != 0 )
732  {
733  //error
734  }
735 
736  if ( mWkbType != QGis::WKBMultiLineString )//keep multitype in case of geometry type mix
737  {
738  mWkbType = QGis::WKBLineString;
739  }
740  }
741  else //multiline, add WKB as fragment
742  {
743  QgsWkbPtr wkbPtr( nullptr, 0 );
744  if ( getLineWKB( wkbPtr, pointList ) != 0 )
745  {
746  //error
747  }
748  if ( !mCurrentWKBFragments.isEmpty() )
749  {
750  mCurrentWKBFragments.last().push_back( wkbPtr );
751  }
752  else
753  {
754  QgsDebugMsg( "no wkb fragments" );
755  delete [] wkbPtr;
756  }
757  }
758  }
759  else if (( theParseMode == geometry || theParseMode == multiPolygon ) &&
760  isGMLNS && LOCALNAME_EQUALS( "LinearRing" ) )
761  {
762  QList<QgsPoint> pointList;
763  if ( pointsFromString( pointList, mStringCash ) != 0 )
764  {
765  //error
766  }
767 
768  QgsWkbPtr wkbPtr( nullptr, 0 );
769  if ( getRingWKB( wkbPtr, pointList ) != 0 )
770  {
771  //error
772  }
773 
774  if ( !mCurrentWKBFragments.isEmpty() )
775  {
776  mCurrentWKBFragments.last().push_back( wkbPtr );
777  }
778  else
779  {
780  delete[] wkbPtr;
781  QgsDebugMsg( "no wkb fragments" );
782  }
783  }
784  else if (( theParseMode == geometry || theParseMode == multiPolygon ) && isGMLNS &&
785  LOCALNAME_EQUALS( "Polygon" ) )
786  {
787  if ( mWkbType != QGis::WKBMultiPolygon )//keep multitype in case of geometry type mix
788  {
789  mWkbType = QGis::WKBPolygon;
790  }
791 
792  if ( theParseMode == geometry )
793  {
794  createPolygonFromFragments();
795  }
796  }
797  else if ( theParseMode == multiPoint && isGMLNS &&
798  LOCALNAME_EQUALS( "MultiPoint" ) )
799  {
800  mWkbType = QGis::WKBMultiPoint;
801  mParseModeStack.pop();
802  createMultiPointFromFragments();
803  }
804  else if ( theParseMode == multiLine && isGMLNS &&
805  ( LOCALNAME_EQUALS( "MultiLineString" ) || LOCALNAME_EQUALS( "MultiCurve" ) ) )
806  {
807  mWkbType = QGis::WKBMultiLineString;
808  mParseModeStack.pop();
809  createMultiLineFromFragments();
810  }
811  else if ( theParseMode == multiPolygon && isGMLNS &&
812  ( LOCALNAME_EQUALS( "MultiPolygon" ) || LOCALNAME_EQUALS( "MultiSurface" ) ) )
813  {
814  mWkbType = QGis::WKBMultiPolygon;
815  mParseModeStack.pop();
816  createMultiPolygonFromFragments();
817  }
818  else if ( mParseDepth == 0 && LOCALNAME_EQUALS( "ExceptionReport" ) )
819  {
820  mParseModeStack.pop();
821  }
822  else if ( theParseMode == ExceptionText && LOCALNAME_EQUALS( "ExceptionText" ) )
823  {
824  mExceptionText = mStringCash;
825  mParseModeStack.pop();
826  }
827 }
828 
829 void QgsGmlStreamingParser::characters( const XML_Char* chars, int len )
830 {
831  //save chars in mStringCash attribute mode or coordinate mode
832  if ( mParseModeStack.isEmpty() )
833  {
834  return;
835  }
836 
837  QgsGmlStreamingParser::ParseMode theParseMode = mParseModeStack.top();
838  if ( theParseMode == QgsGmlStreamingParser::attribute ||
839  theParseMode == QgsGmlStreamingParser::coordinate ||
840  theParseMode == QgsGmlStreamingParser::posList ||
841  theParseMode == QgsGmlStreamingParser::lowerCorner ||
842  theParseMode == QgsGmlStreamingParser::upperCorner ||
843  theParseMode == QgsGmlStreamingParser::ExceptionText )
844  {
845  mStringCash.append( QString::fromUtf8( chars, len ) );
846  }
847 }
848 
849 void QgsGmlStreamingParser::setAttribute( const QString& name, const QString& value )
850 {
851  //find index with attribute name
852  QMap<QString, QPair<int, QgsField> >::const_iterator att_it = mThematicAttributes.constFind( name );
853  if ( att_it != mThematicAttributes.constEnd() )
854  {
855  QVariant var;
856  switch ( att_it.value().second.type() )
857  {
858  case QVariant::Double:
859  var = QVariant( value.toDouble() );
860  break;
861  case QVariant::Int:
862  var = QVariant( value.toInt() );
863  break;
864  case QVariant::LongLong:
865  var = QVariant( value.toLongLong() );
866  break;
867  default: //string type is default
868  var = QVariant( value );
869  break;
870  }
871  Q_ASSERT( mCurrentFeature );
872  mCurrentFeature->setAttribute( att_it.value().first, var );
873  }
874 }
875 
876 int QgsGmlStreamingParser::readEpsgFromAttribute( int& epsgNr, const XML_Char** attr )
877 {
878  int i = 0;
879  while ( attr[i] )
880  {
881  if ( strcmp( attr[i], "srsName" ) == 0 )
882  {
883  QString epsgString( attr[i+1] );
884  QString epsgNrString;
885  bool bIsUrn = false;
886  if ( epsgString.startsWith( "http" ) ) //e.g. geoserver: "http://www.opengis.net/gml/srs/epsg.xml#4326"
887  {
888  epsgNrString = epsgString.section( '#', 1, 1 );
889  }
890  // WFS >= 1.1
891  else if ( epsgString.startsWith( "urn:ogc:def:crs:EPSG:" ) ||
892  epsgString.startsWith( "urn:x-ogc:def:crs:EPSG:" ) )
893  {
894  bIsUrn = true;
895  epsgNrString = epsgString.split( ':' ).last();
896  }
897  else //e.g. umn mapserver: "EPSG:4326">
898  {
899  epsgNrString = epsgString.section( ':', 1, 1 );
900  }
901  bool conversionOk;
902  int eNr = epsgNrString.toInt( &conversionOk );
903  if ( !conversionOk )
904  {
905  return 1;
906  }
907  epsgNr = eNr;
908 
910  if ( crs.createFromOgcWmsCrs( QString( "EPSG:%1" ).arg( epsgNr ) ) )
911  {
912  if ((( mAxisOrientationLogic == Honour_EPSG_if_urn && bIsUrn ) ||
913  mAxisOrientationLogic == Honour_EPSG ) && crs.axisInverted() )
914  {
915  mInvertAxisOrientation = !mInvertAxisOrientationRequest;
916  }
917  }
918 
919  return 0;
920  }
921  ++i;
922  }
923  return 2;
924 }
925 
926 QString QgsGmlStreamingParser::readAttribute( const QString& attributeName, const XML_Char** attr ) const
927 {
928  int i = 0;
929  while ( attr[i] )
930  {
931  if ( attributeName.compare( attr[i] ) == 0 )
932  {
933  return QString::fromUtf8( attr[i+1] );
934  }
935  i += 2;
936  }
937  return QString();
938 }
939 
940 int QgsGmlStreamingParser::createBBoxFromCoordinateString( QgsRectangle &r, const QString& coordString ) const
941 {
942  QList<QgsPoint> points;
943  if ( pointsFromCoordinateString( points, coordString ) != 0 )
944  {
945  return 2;
946  }
947 
948  if ( points.size() < 2 )
949  {
950  return 3;
951  }
952 
953  r.set( points[0], points[1] );
954 
955  return 0;
956 }
957 
958 int QgsGmlStreamingParser::pointsFromCoordinateString( QList<QgsPoint>& points, const QString& coordString ) const
959 {
960  //tuples are separated by space, x/y by ','
961  QStringList tuples = coordString.split( mTupleSeparator, QString::SkipEmptyParts );
962  QStringList tuples_coordinates;
963  double x, y;
964  bool conversionSuccess;
965 
966  QStringList::const_iterator tupleIterator;
967  for ( tupleIterator = tuples.constBegin(); tupleIterator != tuples.constEnd(); ++tupleIterator )
968  {
969  tuples_coordinates = tupleIterator->split( mCoordinateSeparator, QString::SkipEmptyParts );
970  if ( tuples_coordinates.size() < 2 )
971  {
972  continue;
973  }
974  x = tuples_coordinates.at( 0 ).toDouble( &conversionSuccess );
975  if ( !conversionSuccess )
976  {
977  continue;
978  }
979  y = tuples_coordinates.at( 1 ).toDouble( &conversionSuccess );
980  if ( !conversionSuccess )
981  {
982  continue;
983  }
984  points.push_back(( mInvertAxisOrientation ) ? QgsPoint( y, x ) : QgsPoint( x, y ) );
985  }
986  return 0;
987 }
988 
989 int QgsGmlStreamingParser::pointsFromPosListString( QList<QgsPoint>& points, const QString& coordString, int dimension ) const
990 {
991  // coordinates separated by spaces
992  QStringList coordinates = coordString.split( ' ', QString::SkipEmptyParts );
993 
994  if ( coordinates.size() % dimension != 0 )
995  {
996  QgsDebugMsg( "Wrong number of coordinates" );
997  }
998 
999  int ncoor = coordinates.size() / dimension;
1000  for ( int i = 0; i < ncoor; i++ )
1001  {
1002  bool conversionSuccess;
1003  double x = coordinates.value( i * dimension ).toDouble( &conversionSuccess );
1004  if ( !conversionSuccess )
1005  {
1006  continue;
1007  }
1008  double y = coordinates.value( i * dimension + 1 ).toDouble( &conversionSuccess );
1009  if ( !conversionSuccess )
1010  {
1011  continue;
1012  }
1013  points.append(( mInvertAxisOrientation ) ? QgsPoint( y, x ) : QgsPoint( x, y ) );
1014  }
1015  return 0;
1016 }
1017 
1018 int QgsGmlStreamingParser::pointsFromString( QList<QgsPoint>& points, const QString& coordString ) const
1019 {
1020  if ( mCoorMode == QgsGmlStreamingParser::coordinate )
1021  {
1022  return pointsFromCoordinateString( points, coordString );
1023  }
1024  else if ( mCoorMode == QgsGmlStreamingParser::posList )
1025  {
1026  return pointsFromPosListString( points, coordString, mDimension );
1027  }
1028  return 1;
1029 }
1030 
1031 int QgsGmlStreamingParser::getPointWKB( QgsWkbPtr &wkbPtr, const QgsPoint& point ) const
1032 {
1033  int wkbSize = 1 + sizeof( int ) + 2 * sizeof( double );
1034  wkbPtr = QgsWkbPtr( new unsigned char[wkbSize], wkbSize );
1035 
1036  QgsWkbPtr fillPtr( wkbPtr );
1037  fillPtr << mEndian << QGis::WKBPoint << point.x() << point.y();
1038 
1039  return 0;
1040 }
1041 
1042 int QgsGmlStreamingParser::getLineWKB( QgsWkbPtr &wkbPtr, const QList<QgsPoint>& lineCoordinates ) const
1043 {
1044  int wkbSize = 1 + 2 * sizeof( int ) + lineCoordinates.size() * 2 * sizeof( double );
1045  wkbPtr = QgsWkbPtr( new unsigned char[wkbSize], wkbSize );
1046 
1047  QgsWkbPtr fillPtr( wkbPtr );
1048 
1049  fillPtr << mEndian << QGis::WKBLineString << lineCoordinates.size();
1050 
1052  for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
1053  {
1054  fillPtr << iter->x() << iter->y();
1055  }
1056 
1057  return 0;
1058 }
1059 
1060 int QgsGmlStreamingParser::getRingWKB( QgsWkbPtr &wkbPtr, const QList<QgsPoint>& ringCoordinates ) const
1061 {
1062  int wkbSize = sizeof( int ) + ringCoordinates.size() * 2 * sizeof( double );
1063  wkbPtr = QgsWkbPtr( new unsigned char[wkbSize], wkbSize );
1064 
1065  QgsWkbPtr fillPtr( wkbPtr );
1066 
1067  fillPtr << ringCoordinates.size();
1068 
1070  for ( iter = ringCoordinates.constBegin(); iter != ringCoordinates.constEnd(); ++iter )
1071  {
1072  fillPtr << iter->x() << iter->y();
1073  }
1074 
1075  return 0;
1076 }
1077 
1078 int QgsGmlStreamingParser::createMultiLineFromFragments()
1079 {
1080  int size = 1 + 2 * sizeof( int ) + totalWKBFragmentSize();
1081  mCurrentWKB = QgsWkbPtr( new unsigned char[size], size );
1082 
1083  QgsWkbPtr wkbPtr( mCurrentWKB );
1084 
1085  wkbPtr << mEndian << QGis::WKBMultiLineString << mCurrentWKBFragments.constBegin()->size();
1086 
1087  //copy (and delete) all the wkb fragments
1088  QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
1089  for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
1090  {
1091  memcpy( wkbPtr, *wkbIt, wkbIt->size() );
1092  wkbPtr += wkbIt->size();
1093  delete[] *wkbIt;
1094  }
1095 
1096  mCurrentWKBFragments.clear();
1097  mWkbType = QGis::WKBMultiLineString;
1098  return 0;
1099 }
1100 
1101 int QgsGmlStreamingParser::createMultiPointFromFragments()
1102 {
1103  int size = 1 + 2 * sizeof( int ) + totalWKBFragmentSize();
1104  mCurrentWKB = QgsWkbPtr( new unsigned char[size], size );
1105 
1106  QgsWkbPtr wkbPtr( mCurrentWKB );
1107  wkbPtr << mEndian << QGis::WKBMultiPoint << mCurrentWKBFragments.constBegin()->size();
1108 
1109  QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
1110  for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
1111  {
1112  memcpy( wkbPtr, *wkbIt, wkbIt->size() );
1113  wkbPtr += wkbIt->size();
1114  delete[] *wkbIt;
1115  }
1116 
1117  mCurrentWKBFragments.clear();
1118  mWkbType = QGis::WKBMultiPoint;
1119  return 0;
1120 }
1121 
1122 
1123 int QgsGmlStreamingParser::createPolygonFromFragments()
1124 {
1125  int size = 1 + 2 * sizeof( int ) + totalWKBFragmentSize();
1126  mCurrentWKB = QgsWkbPtr( new unsigned char[size], size );
1127 
1128  QgsWkbPtr wkbPtr( mCurrentWKB );
1129  wkbPtr << mEndian << QGis::WKBPolygon << mCurrentWKBFragments.constBegin()->size();
1130 
1131  QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
1132  for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
1133  {
1134  memcpy( wkbPtr, *wkbIt, wkbIt->size() );
1135  wkbPtr += wkbIt->size();
1136  delete[] *wkbIt;
1137  }
1138 
1139  mCurrentWKBFragments.clear();
1140  mWkbType = QGis::WKBPolygon;
1141  return 0;
1142 }
1143 
1144 int QgsGmlStreamingParser::createMultiPolygonFromFragments()
1145 {
1146  int size = 0;
1147  size += 1 + 2 * sizeof( int );
1148  size += totalWKBFragmentSize();
1149  size += mCurrentWKBFragments.size() * ( 1 + 2 * sizeof( int ) ); //fragments are just the rings
1150 
1151  mCurrentWKB = QgsWkbPtr( new unsigned char[size], size );
1152 
1153  QgsWkbPtr wkbPtr( mCurrentWKB );
1154  wkbPtr << ( char ) mEndian << QGis::WKBMultiPolygon << mCurrentWKBFragments.size();
1155 
1156  //have outer and inner iterators
1157  QList< QList<QgsWkbPtr> >::const_iterator outerWkbIt = mCurrentWKBFragments.constBegin();
1158 
1159  for ( ; outerWkbIt != mCurrentWKBFragments.constEnd(); ++outerWkbIt )
1160  {
1161  //new polygon
1162  wkbPtr << ( char ) mEndian << QGis::WKBPolygon << outerWkbIt->size();
1163 
1164  QList<QgsWkbPtr>::const_iterator innerWkbIt = outerWkbIt->constBegin();
1165  for ( ; innerWkbIt != outerWkbIt->constEnd(); ++innerWkbIt )
1166  {
1167  memcpy( wkbPtr, *innerWkbIt, innerWkbIt->size() );
1168  wkbPtr += innerWkbIt->size();
1169  delete[] *innerWkbIt;
1170  }
1171  }
1172 
1173  mCurrentWKBFragments.clear();
1174  mWkbType = QGis::WKBMultiPolygon;
1175  return 0;
1176 }
1177 
1178 int QgsGmlStreamingParser::totalWKBFragmentSize() const
1179 {
1180  int result = 0;
1181  Q_FOREACH ( const QList<QgsWkbPtr> &list, mCurrentWKBFragments )
1182  {
1183  Q_FOREACH ( const QgsWkbPtr &i, list )
1184  {
1185  result += i.size();
1186  }
1187  }
1188  return result;
1189 }
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
void clear()
void unionRect(const QgsRectangle &rect)
Updates rectangle to include passed argument.
int getEPSGCode() const
Return the EPSG code, or 0 if unknown.
Definition: qgsgml.h:79
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
static unsigned index
A rectangle specified with double values.
Definition: qgsrectangle.h:35
QString & append(QChar ch)
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.
bool contains(const Key &key) const
static QgsAuthManager * instance()
Enforce singleton pattern.
AxisOrientationLogic
Axis orientation logic.
Definition: qgsgml.h:50
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:172
void push_back(const T &value)
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer&#39;s length...
void setWindowModality(Qt::WindowModality windowModality)
QString errorString() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
void push(const T &t)
const T & at(int i) const
int size() const
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
bool isEmpty() const
int numberMatched() const
Return WFS 2.0 "numberMatched" attribute, or -1 if invalid/not found.
Definition: qgsgml.h:85
Container of fields for a vector layer.
Definition: qgsfield.h:187
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:115
bool setAttribute(int field, const QVariant &attr)
Set an attribute&#39;s value by field index.
Definition: qgsfeature.cpp:222
WkbType
Used for symbology operations.
Definition: qgis.h:57
static const char * GML32_NAMESPACE
Definition: qgsgml.cpp:38
void dataReadProgress(int progress)
const_iterator constFind(const Key &key) const
The QGis class provides global constants for use throughout the application.
Definition: qgis.h:36
bool axisInverted() const
Returns whether axis is inverted (eg.
int numberReturned() const
Return WFS 2.0 "numberReturned" or WFS 1.1 "numberOfFeatures" attribute, or -1 if invalid/not found...
Definition: qgsgml.h:88
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
void clear()
double toDouble(bool *ok) const
static endian_t endian()
Returns whether this machine uses big or little endian.
QString tr(const char *sourceText, const char *disambiguation, int n)
#define LOCALNAME_EQUALS(string_constant)
Definition: qgsgml.cpp:341
double x() const
Get the x value of the point.
Definition: qgspoint.h:185
int size() const
bool isNull() const
void totalStepsUpdate(int totalSteps)
T value(int i) const
void set(const QgsPoint &p1, const QgsPoint &p2)
Set the rectangle from two QgsPoints.
void clear()
bool createFromOgcWmsCrs(QString theCrs)
Set up this CRS from the given OGC CRS.
void setGeometry(const QgsGeometry &geom)
Set this feature&#39;s geometry from another QgsGeometry object.
Definition: qgsfeature.cpp:124
Honour EPSG axis order.
Definition: qgsgml.h:55
void processEvents(QFlags< QEventLoop::ProcessEventsFlag > flags)
void append(const T &value)
QString fromUtf8(const char *str, int size)
int getFeatures(const QString &uri, QGis::WkbType *wkbType, QgsRectangle *extent=nullptr, const QString &userName=QString(), const QString &password=QString(), const QString &authcfg=QString())
Does the Http GET request to the wfs server Supports only UTF-8, UTF-16, ISO-8859-1, ISO-8859-1 XML encodings.
Definition: qgsgml.cpp:60
void dataProgressAndSteps(int progress, int totalSteps)
QgsGml(const QString &typeName, const QString &geometryAttribute, const QgsFields &fields)
Definition: qgsgml.cpp:40
int toInt(bool *ok, int base) const
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:177
bool isEmpty() const
bool isEmpty() const
const_iterator constEnd() const
const char * constData() const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QByteArray readAll()
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
int size() const
Definition: qgswkbptr.h:81
Honour EPSG axis order only if srsName is of the form urn:ogc:def:crs:EPSG:
Definition: qgsgml.h:53
QVector< QgsGmlFeaturePtrGmlIdPair > getAndStealReadyFeatures()
Returns the list of features that have been completely parsed.
Definition: qgsgml.cpp:334
QPair< QgsFeature *, QString > QgsGmlFeaturePtrGmlIdPair
Definition: qgsgml.h:47
A class to represent a point.
Definition: qgspoint.h:117
Q_DECL_DEPRECATED void setFields(const QgsFields *fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:173
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:204
QString mid(int position, int n) const
bool updateNetworkRequest(QNetworkRequest &request, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkRequest with an authentication config.
static QgsNetworkAccessManager * instance()
returns a pointer to the single instance
void setRawHeader(const QByteArray &headerName, const QByteArray &headerValue)
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:182
T & last()
Class for storing a coordinate reference system (CRS)
bool processData(const QByteArray &data, bool atEnd)
Process a new chunk of data.
Definition: qgsgml.cpp:317
int size() const
Return number of items.
Definition: qgsfield.cpp:370
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
int length() const
static QgsGeometry * fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
QgsGmlStreamingParser(const QString &typeName, const QString &geometryAttribute, const QgsFields &fields, AxisOrientationLogic axisOrientationLogic=Honour_EPSG_if_urn, bool invertAxisOrientation=false)
Constructor.
Definition: qgsgml.cpp:255
static const char * GML_NAMESPACE
Definition: qgsgml.cpp:37
char * data()
QString section(QChar sep, int start, int end, QFlags< QString::SectionFlag > flags) const
NetworkError error() const
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
iterator insert(const Key &key, const T &value)
void show()
static const char NS_SEPARATOR
Definition: qgsgml.cpp:36
QNetworkReply * get(const QNetworkRequest &request)
const_iterator constEnd() const
const_iterator constBegin() const
QGis::WkbType wkbType() const
Return the geometry type.
Definition: qgsgml.h:82
int size() const
A vector of attributes.
Definition: qgsfeature.h:115
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int compare(const QString &other) const
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
~QgsGml()
Definition: qgsgml.cpp:56
qlonglong toLongLong(bool *ok, int base) const
QgsCoordinateReferenceSystem crs() const
Returns features spatial reference system.
Definition: qgsgml.cpp:241
int size() const
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:167
const T value(const Key &key) const
T & top()
QByteArray toUtf8() const