24 #include <QNetworkRequest>
25 #include <QNetworkReply>
26 #include <QProgressDialog>
37 const QString& typeName,
38 const QString& geometryAttribute,
41 , mTypeName( typeName )
42 , mGeometryAttribute( geometryAttribute )
45 , mCurrentFeature( 0 )
48 , mCurrentWKBSize( 0 )
50 , mCoorMode(
QgsGml::coordinate )
53 mThematicAttributes.clear();
54 for (
int i = 0; i < fields.
size(); i++ )
56 mThematicAttributes.insert( fields[i].name(), qMakePair( i, fields[i] ) );
61 int index = mTypeName.indexOf(
":" );
62 if ( index != -1 && index < mTypeName.length() )
64 mTypeName = mTypeName.mid( index + 1 );
78 XML_SetUserData( p,
this );
79 XML_SetElementHandler( p, QgsGml::start, QgsGml::end );
80 XML_SetCharacterDataHandler( p, QgsGml::chars );
85 QNetworkRequest request( mUri );
86 if ( !userName.isNull() || !password.isNull() )
88 request.setRawHeader(
"Authorization",
"Basic " + QString(
"%1:%2" ).arg( userName ).arg( password ).toAscii().toBase64() );
92 connect( reply, SIGNAL( finished() ),
this, SLOT( setFinished() ) );
93 connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ),
this, SLOT( handleProgressEvent( qint64, qint64 ) ) );
96 QProgressDialog* progressDialog = 0;
97 QWidget* mainWindow = 0;
98 QWidgetList topLevelWidgets = qApp->topLevelWidgets();
99 for ( QWidgetList::iterator it = topLevelWidgets.begin(); it != topLevelWidgets.end(); ++it )
101 if (( *it )->objectName() ==
"QgisApp" )
109 progressDialog =
new QProgressDialog(
tr(
"Loading GML data\n%1" ).arg( mTypeName ),
tr(
"Abort" ), 0, 0, mainWindow );
110 progressDialog->setWindowModality( Qt::ApplicationModal );
111 connect(
this, SIGNAL(
dataReadProgress(
int ) ), progressDialog, SLOT( setValue(
int ) ) );
112 connect(
this, SIGNAL(
totalStepsUpdate(
int ) ), progressDialog, SLOT( setMaximum(
int ) ) );
113 connect( progressDialog, SIGNAL( canceled() ),
this, SLOT( setFinished() ) );
114 progressDialog->show();
124 QByteArray readData = reply->readAll();
125 if ( readData.size() > 0 )
127 if ( XML_Parse( p, readData.constData(), readData.size(), atEnd ) == 0 )
129 XML_Error errorCode = XML_GetErrorCode( p );
130 QString errorString =
tr(
"Error: %1 on line %2, column %3" )
131 .arg( XML_ErrorString( errorCode ) )
132 .arg( XML_GetCurrentLineNumber( p ) )
133 .arg( XML_GetCurrentColumnNumber( p ) );
137 QCoreApplication::processEvents();
140 QNetworkReply::NetworkError replyError = reply->error();
141 QString replyErrorString = reply->errorString();
144 delete progressDialog;
149 tr(
"GML Getfeature network request failed with error: %1" ).arg( replyErrorString ),
161 calculateExtentFromFeatures();
178 XML_Parser p = XML_ParserCreateNS( NULL,
NS_SEPARATOR );
179 XML_SetUserData( p,
this );
180 XML_SetElementHandler( p, QgsGml::start, QgsGml::end );
181 XML_SetCharacterDataHandler( p, QgsGml::chars );
183 XML_Parse( p, data.constData(), data.size(), atEnd );
191 void QgsGml::setFinished()
196 void QgsGml::handleProgressEvent( qint64 progress, qint64 totalSteps )
198 if ( totalSteps < 0 )
208 void QgsGml::startElement(
const XML_Char* el,
const XML_Char** attr )
210 QString elementName( QString::fromUtf8( el ) );
211 ParseMode theParseMode( mParseModeStack.isEmpty() ? none : mParseModeStack.top() );
212 QStringList splitName = elementName.split(
NS_SEPARATOR );
213 QString localName = splitName.last();
214 QString ns = splitName.size() > 1 ? splitName.first() :
"";
218 mParseModeStack.push( QgsGml::coordinate );
219 mCoorMode = QgsGml::coordinate;
221 mCoordinateSeparator = readAttribute(
"cs", attr );
222 if ( mCoordinateSeparator.isEmpty() )
224 mCoordinateSeparator =
",";
226 mTupleSeparator = readAttribute(
"ts", attr );
227 if ( mTupleSeparator.isEmpty() )
229 mTupleSeparator =
" ";
235 mParseModeStack.push( QgsGml::posList );
236 mCoorMode = QgsGml::posList;
238 QString dimension = readAttribute(
"srsDimension", attr );
240 mDimension = dimension.toInt( &ok );
241 if ( dimension.isEmpty() || !ok )
246 else if ( localName == mGeometryAttribute )
248 mParseModeStack.push( QgsGml::geometry );
253 mParseModeStack.push( QgsGml::boundingBox );
255 else if ( theParseMode == none && localName == mTypeName )
257 Q_ASSERT( !mCurrentFeature );
258 mCurrentFeature =
new QgsFeature( mFeatureCount );
261 mParseModeStack.push( QgsGml::feature );
262 mCurrentFeatureId = readAttribute(
"fid", attr );
269 if ( readEpsgFromAttribute( epsgNr, attr ) != 0 )
276 mCurrentWKBFragments.push_back( QList<unsigned char*>() );
277 mCurrentWKBFragmentSizes.push_back( QList<int>() );
281 mParseModeStack.push( QgsGml::multiPoint );
283 mCurrentWKBFragments.push_back( QList<unsigned char*>() );
284 mCurrentWKBFragmentSizes.push_back( QList<int>() );
288 mParseModeStack.push( QgsGml::multiLine );
290 mCurrentWKBFragments.push_back( QList<unsigned char*>() );
291 mCurrentWKBFragmentSizes.push_back( QList<int>() );
295 mParseModeStack.push( QgsGml::multiPolygon );
297 else if ( theParseMode == feature && mThematicAttributes.contains( localName ) )
299 mParseModeStack.push( QgsGml::attribute );
300 mAttributeName = localName;
305 else if ( theParseMode == feature
306 && localName.compare(
"attribute", Qt::CaseInsensitive ) == 0 )
308 QString name = readAttribute(
"name", attr );
309 if ( mThematicAttributes.contains( name ) )
311 QString value = readAttribute(
"value", attr );
312 setAttribute( name, value );
316 if ( mEpsg == 0 && ( localName ==
"Point" || localName ==
"MultiPoint" ||
317 localName ==
"LineString" || localName ==
"MultiLineString" ||
318 localName ==
"Polygon" || localName ==
"MultiPolygon" ) )
320 if ( readEpsgFromAttribute( mEpsg, attr ) != 0 )
326 QgsDebugMsg( QString(
"mEpsg = %1" ).arg( mEpsg ) );
331 void QgsGml::endElement(
const XML_Char* el )
333 QString elementName( QString::fromUtf8( el ) );
334 ParseMode theParseMode( mParseModeStack.isEmpty() ? none : mParseModeStack.top() );
335 QStringList splitName = elementName.split(
NS_SEPARATOR );
336 QString localName = splitName.last();
337 QString ns = splitName.size() > 1 ? splitName.first() :
"";
340 || ( theParseMode == posList && (
344 mParseModeStack.pop();
346 else if ( theParseMode == attribute && localName == mAttributeName )
348 mParseModeStack.pop();
350 setAttribute( mAttributeName, mStringCash );
352 else if ( theParseMode == geometry && localName == mGeometryAttribute )
354 mParseModeStack.pop();
359 if ( createBBoxFromCoordinateString( mCurrentExtent, mStringCash ) != 0 )
364 mParseModeStack.pop();
366 else if ( theParseMode == feature && localName == mTypeName )
368 Q_ASSERT( mCurrentFeature );
369 if ( mCurrentWKBSize > 0 )
373 else if ( !mCurrentExtent.
isEmpty() )
383 mFeatures.insert( mCurrentFeature->
id(), mCurrentFeature );
384 if ( !mCurrentFeatureId.isEmpty() )
386 mIdMap.insert( mCurrentFeature->
id(), mCurrentFeatureId );
390 mParseModeStack.pop();
394 QList<QgsPoint> pointList;
395 if ( pointsFromString( pointList, mStringCash ) != 0 )
400 if ( pointList.count() == 0 )
403 if ( theParseMode == QgsGml::geometry )
406 if ( getPointWKB( &mCurrentWKB, &mCurrentWKBSize, *( pointList.begin() ) ) != 0 )
418 unsigned char* wkb = 0;
420 QList<unsigned char*> wkbList;
421 QList<int> wkbSizeList;
422 if ( getPointWKB( &wkb, &wkbSize, *( pointList.begin() ) ) != 0 )
426 if ( !mCurrentWKBFragments.isEmpty() )
428 mCurrentWKBFragments.last().push_back( wkb );
429 mCurrentWKBFragmentSizes.last().push_back( wkbSize );
442 QList<QgsPoint> pointList;
443 if ( pointsFromString( pointList, mStringCash ) != 0 )
447 if ( theParseMode == QgsGml::geometry )
449 if ( getLineWKB( &mCurrentWKB, &mCurrentWKBSize, pointList ) != 0 )
461 unsigned char* wkb = 0;
463 QList<unsigned char*> wkbList;
464 QList<int> wkbSizeList;
465 if ( getLineWKB( &wkb, &wkbSize, pointList ) != 0 )
469 if ( !mCurrentWKBFragments.isEmpty() )
471 mCurrentWKBFragments.last().push_back( wkb );
472 mCurrentWKBFragmentSizes.last().push_back( wkbSize );
481 else if (( theParseMode == geometry || theParseMode == multiPolygon ) && elementName ==
GML_NAMESPACE +
NS_SEPARATOR +
"LinearRing" )
483 QList<QgsPoint> pointList;
484 if ( pointsFromString( pointList, mStringCash ) != 0 )
488 unsigned char* wkb = 0;
490 if ( getRingWKB( &wkb, &wkbSize, pointList ) != 0 )
494 if ( !mCurrentWKBFragments.isEmpty() )
496 mCurrentWKBFragments.last().push_back( wkb );
497 mCurrentWKBFragmentSizes.last().push_back( wkbSize );
505 else if (( theParseMode == geometry || theParseMode == multiPolygon ) && elementName ==
GML_NAMESPACE +
NS_SEPARATOR +
"Polygon" )
512 if ( theParseMode == geometry )
514 createPolygonFromFragments();
520 mParseModeStack.pop();
521 createMultiPointFromFragments();
526 mParseModeStack.pop();
527 createMultiLineFromFragments();
532 mParseModeStack.pop();
533 createMultiPolygonFromFragments();
537 void QgsGml::characters(
const XML_Char* chars,
int len )
540 if ( mParseModeStack.size() == 0 )
545 QgsGml::ParseMode theParseMode = mParseModeStack.top();
546 if ( theParseMode == QgsGml::attribute || theParseMode == QgsGml::coordinate || theParseMode == QgsGml::posList )
548 mStringCash.append( QString::fromUtf8( chars, len ) );
552 void QgsGml::setAttribute(
const QString& name,
const QString& value )
555 QMap<QString, QPair<int, QgsField> >::const_iterator att_it = mThematicAttributes.find( name );
556 if ( att_it != mThematicAttributes.constEnd() )
559 switch ( att_it.value().second.type() )
561 case QVariant::Double:
562 var = QVariant( value.toDouble() );
565 var = QVariant( value.toInt() );
567 case QVariant::LongLong:
568 var = QVariant( value.toLongLong() );
571 var = QVariant( value );
574 Q_ASSERT( mCurrentFeature );
575 mCurrentFeature->
setAttribute( att_it.value().first, var );
579 int QgsGml::readEpsgFromAttribute(
int& epsgNr,
const XML_Char** attr )
const
582 while ( attr[i] != NULL )
584 if ( strcmp( attr[i],
"srsName" ) == 0 )
586 QString epsgString( attr[i+1] );
587 QString epsgNrString;
588 if ( epsgString.startsWith(
"http" ) )
590 epsgNrString = epsgString.section(
"#", 1, 1 );
594 epsgNrString = epsgString.section(
":", 1, 1 );
597 int eNr = epsgNrString.toInt( &conversionOk );
610 QString QgsGml::readAttribute(
const QString& attributeName,
const XML_Char** attr )
const
613 while ( attr[i] != NULL )
615 if ( attributeName.compare( attr[i] ) == 0 )
617 return QString::fromUtf8( attr[i+1] );
624 int QgsGml::createBBoxFromCoordinateString(
QgsRectangle &r,
const QString& coordString )
const
626 QList<QgsPoint> points;
627 if ( pointsFromCoordinateString( points, coordString ) != 0 )
632 if ( points.size() < 2 )
637 r.
set( points[0], points[1] );
642 int QgsGml::pointsFromCoordinateString( QList<QgsPoint>& points,
const QString& coordString )
const
645 QStringList tuples = coordString.split( mTupleSeparator, QString::SkipEmptyParts );
646 QStringList tuples_coordinates;
648 bool conversionSuccess;
650 QStringList::const_iterator tupleIterator;
651 for ( tupleIterator = tuples.constBegin(); tupleIterator != tuples.constEnd(); ++tupleIterator )
653 tuples_coordinates = tupleIterator->split( mCoordinateSeparator, QString::SkipEmptyParts );
654 if ( tuples_coordinates.size() < 2 )
658 x = tuples_coordinates.at( 0 ).toDouble( &conversionSuccess );
659 if ( !conversionSuccess )
663 y = tuples_coordinates.at( 1 ).toDouble( &conversionSuccess );
664 if ( !conversionSuccess )
668 points.push_back(
QgsPoint( x, y ) );
673 int QgsGml::pointsFromPosListString( QList<QgsPoint>& points,
const QString& coordString,
int dimension )
const
676 QStringList coordinates = coordString.split(
" ", QString::SkipEmptyParts );
678 if ( coordinates.size() % dimension != 0 )
683 int ncoor = coordinates.size() / dimension;
684 for (
int i = 0; i < ncoor; i++ )
686 bool conversionSuccess;
687 double x = coordinates.value( i * dimension ).toDouble( &conversionSuccess );
688 if ( !conversionSuccess )
692 double y = coordinates.value( i * dimension + 1 ).toDouble( &conversionSuccess );
693 if ( !conversionSuccess )
702 int QgsGml::pointsFromString( QList<QgsPoint>& points,
const QString& coordString )
const
704 if ( mCoorMode == QgsGml::coordinate )
706 return pointsFromCoordinateString( points, coordString );
708 else if ( mCoorMode == QgsGml::posList )
710 return pointsFromPosListString( points, coordString, mDimension );
715 int QgsGml::getPointWKB(
unsigned char** wkb,
int*
size,
const QgsPoint& point )
const
717 int wkbSize = 1 +
sizeof( int ) + 2 *
sizeof(
double );
719 *wkb =
new unsigned char[wkbSize];
721 double x = point.
x();
722 double y = point.
y();
725 memcpy( &( *wkb )[wkbPosition], &mEndian, 1 );
727 memcpy( &( *wkb )[wkbPosition], &type,
sizeof(
int ) );
728 wkbPosition +=
sizeof( int );
729 memcpy( &( *wkb )[wkbPosition], &x,
sizeof(
double ) );
730 wkbPosition +=
sizeof( double );
731 memcpy( &( *wkb )[wkbPosition], &y,
sizeof(
double ) );
735 int QgsGml::getLineWKB(
unsigned char** wkb,
int* size,
const QList<QgsPoint>& lineCoordinates )
const
737 int wkbSize = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
739 *wkb =
new unsigned char[wkbSize];
743 int nPoints = lineCoordinates.size();
746 memcpy( &( *wkb )[wkbPosition], &mEndian, 1 );
748 memcpy( &( *wkb )[wkbPosition], &type,
sizeof(
int ) );
749 wkbPosition +=
sizeof( int );
750 memcpy( &( *wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
751 wkbPosition +=
sizeof( int );
753 QList<QgsPoint>::const_iterator iter;
754 for ( iter = lineCoordinates.begin(); iter != lineCoordinates.end(); ++iter )
758 memcpy( &( *wkb )[wkbPosition], &x,
sizeof(
double ) );
759 wkbPosition +=
sizeof( double );
760 memcpy( &( *wkb )[wkbPosition], &y,
sizeof(
double ) );
761 wkbPosition +=
sizeof( double );
766 int QgsGml::getRingWKB(
unsigned char** wkb,
int* size,
const QList<QgsPoint>& ringCoordinates )
const
768 int wkbSize =
sizeof( int ) + ringCoordinates.size() * 2 *
sizeof( double );
770 *wkb =
new unsigned char[wkbSize];
773 int nPoints = ringCoordinates.size();
774 memcpy( &( *wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
775 wkbPosition +=
sizeof( int );
777 QList<QgsPoint>::const_iterator iter;
778 for ( iter = ringCoordinates.begin(); iter != ringCoordinates.end(); ++iter )
782 memcpy( &( *wkb )[wkbPosition], &x,
sizeof(
double ) );
783 wkbPosition +=
sizeof( double );
784 memcpy( &( *wkb )[wkbPosition], &y,
sizeof(
double ) );
785 wkbPosition +=
sizeof( double );
790 int QgsGml::createMultiLineFromFragments()
793 mCurrentWKBSize += 1 + 2 *
sizeof( int );
794 mCurrentWKBSize += totalWKBFragmentSize();
796 mCurrentWKB =
new unsigned char[mCurrentWKBSize];
799 int numLines = mCurrentWKBFragments.begin()->size();
801 memcpy( &( mCurrentWKB[pos] ), &mEndian, 1 );
803 memcpy( &( mCurrentWKB[pos] ), &type,
sizeof(
int ) );
804 pos +=
sizeof( int );
805 memcpy( &( mCurrentWKB[pos] ), &numLines,
sizeof(
int ) );
806 pos +=
sizeof( int );
807 QList<unsigned char*>::iterator wkbIt = mCurrentWKBFragments.begin()->begin();
808 QList<int>::iterator sizeIt = mCurrentWKBFragmentSizes.begin()->begin();
811 for ( ; wkbIt != mCurrentWKBFragments.begin()->end(); ++wkbIt, ++sizeIt )
813 memcpy( &( mCurrentWKB[pos] ), *wkbIt, *sizeIt );
818 mCurrentWKBFragments.clear();
819 mCurrentWKBFragmentSizes.clear();
824 int QgsGml::createMultiPointFromFragments()
827 mCurrentWKBSize += 1 + 2 *
sizeof( int );
828 mCurrentWKBSize += totalWKBFragmentSize();
829 mCurrentWKB =
new unsigned char[mCurrentWKBSize];
833 int numPoints = mCurrentWKBFragments.begin()->size();
835 memcpy( &( mCurrentWKB[pos] ), &mEndian, 1 );
837 memcpy( &( mCurrentWKB[pos] ), &type,
sizeof(
int ) );
838 pos +=
sizeof( int );
839 memcpy( &( mCurrentWKB[pos] ), &numPoints,
sizeof(
int ) );
840 pos +=
sizeof( int );
842 QList<unsigned char*>::iterator wkbIt = mCurrentWKBFragments.begin()->begin();
843 QList<int>::iterator sizeIt = mCurrentWKBFragmentSizes.begin()->begin();
845 for ( ; wkbIt != mCurrentWKBFragments.begin()->end(); ++wkbIt, ++sizeIt )
847 memcpy( &( mCurrentWKB[pos] ), *wkbIt, *sizeIt );
852 mCurrentWKBFragments.clear();
853 mCurrentWKBFragmentSizes.clear();
859 int QgsGml::createPolygonFromFragments()
862 mCurrentWKBSize += 1 + 2 *
sizeof( int );
863 mCurrentWKBSize += totalWKBFragmentSize();
865 mCurrentWKB =
new unsigned char[mCurrentWKBSize];
868 int numRings = mCurrentWKBFragments.begin()->size();
869 memcpy( &( mCurrentWKB[pos] ), &mEndian, 1 );
871 memcpy( &( mCurrentWKB[pos] ), &type,
sizeof(
int ) );
872 pos +=
sizeof( int );
873 memcpy( &( mCurrentWKB[pos] ), &numRings,
sizeof(
int ) );
874 pos +=
sizeof( int );
876 QList<unsigned char*>::iterator wkbIt = mCurrentWKBFragments.begin()->begin();
877 QList<int>::iterator sizeIt = mCurrentWKBFragmentSizes.begin()->begin();
878 for ( ; wkbIt != mCurrentWKBFragments.begin()->end(); ++wkbIt, ++sizeIt )
880 memcpy( &( mCurrentWKB[pos] ), *wkbIt, *sizeIt );
885 mCurrentWKBFragments.clear();
886 mCurrentWKBFragmentSizes.clear();
891 int QgsGml::createMultiPolygonFromFragments()
894 mCurrentWKBSize += 1 + 2 *
sizeof( int );
895 mCurrentWKBSize += totalWKBFragmentSize();
896 mCurrentWKBSize += mCurrentWKBFragments.size() * ( 1 + 2 *
sizeof( int ) );
898 mCurrentWKB =
new unsigned char[mCurrentWKBSize];
902 int numPolys = mCurrentWKBFragments.size();
904 memcpy( &( mCurrentWKB[pos] ), &mEndian, 1 );
906 memcpy( &( mCurrentWKB[pos] ), &type,
sizeof(
int ) );
907 pos +=
sizeof( int );
908 memcpy( &( mCurrentWKB[pos] ), &numPolys,
sizeof(
int ) );
909 pos +=
sizeof( int );
912 QList< QList<unsigned char*> >::iterator outerWkbIt;
913 QList< QList<int> >::iterator outerSizeIt;
914 QList< unsigned char* >::iterator innerWkbIt;
915 QList< int >::iterator innerSizeIt;
917 outerWkbIt = mCurrentWKBFragments.begin();
918 outerSizeIt = mCurrentWKBFragmentSizes.begin();
920 for ( ; outerWkbIt != mCurrentWKBFragments.end(); ++outerWkbIt, ++outerSizeIt )
923 memcpy( &( mCurrentWKB[pos] ), &mEndian, 1 );
925 memcpy( &( mCurrentWKB[pos] ), &polygonType,
sizeof(
int ) );
926 pos +=
sizeof( int );
927 numRings = outerWkbIt->size();
928 memcpy( &( mCurrentWKB[pos] ), &numRings,
sizeof(
int ) );
929 pos +=
sizeof( int );
931 innerWkbIt = outerWkbIt->begin();
932 innerSizeIt = outerSizeIt->begin();
933 for ( ; innerWkbIt != outerWkbIt->end(); ++innerWkbIt, ++innerSizeIt )
935 memcpy( &( mCurrentWKB[pos] ), *innerWkbIt, *innerSizeIt );
937 delete[] *innerWkbIt;
941 mCurrentWKBFragments.clear();
942 mCurrentWKBFragmentSizes.clear();
947 int QgsGml::totalWKBFragmentSize()
const
950 foreach (
const QList<int> &list, mCurrentWKBFragmentSizes )
952 foreach (
int i, list )
960 void QgsGml::calculateExtentFromFeatures()
962 if ( mFeatures.size() < 1 )
969 bool bboxInitialised =
false;
971 for (
int i = 0; i < mFeatures.size(); ++i )
973 currentFeature = mFeatures[i];
974 if ( !currentFeature )
978 currentGeometry = currentFeature->
geometry();
979 if ( currentGeometry )
981 if ( !bboxInitialised )
984 bboxInitialised =
true;