43
43
#include < QUrl>
44
44
#include < QWidget>
45
45
#include < QPair>
46
+ #include < QTimer>
47
+
46
48
#include < cfloat>
47
49
48
50
static const QString TEXT_PROVIDER_KEY = " WFS" ;
@@ -62,9 +64,12 @@ QgsWFSProvider::QgsWFSProvider( const QString& uri )
62
64
, mSourceCRS( 0 )
63
65
, mFeatureCount( 0 )
64
66
, mValid( true )
67
+ , mPendingRetrieval( false )
68
+ #if 0
65
69
, mLayer( 0 )
66
70
, mGetRenderedOnly( false )
67
71
, mInitGro( false )
72
+ #endif
68
73
{
69
74
mSpatialIndex = 0 ;
70
75
if ( uri.isEmpty () )
@@ -115,7 +120,8 @@ QgsWFSProvider::QgsWFSProvider( const QString& uri )
115
120
setDataSourceUri ( bkUri );
116
121
}
117
122
118
- if ( ! uri.contains ( " BBOX=" ) )
123
+ mCached = !uri.contains ( " BBOX=" );
124
+ if ( mCached )
119
125
{ // "Cache Features" option; get all features in layer immediately
120
126
reloadData ();
121
127
} // otherwise, defer feature retrieval until layer is first rendered
@@ -124,6 +130,8 @@ QgsWFSProvider::QgsWFSProvider( const QString& uri )
124
130
{
125
131
getLayerCapabilities ();
126
132
}
133
+
134
+ qRegisterMetaType<QgsRectangle>( " QgsRectangle" );
127
135
}
128
136
129
137
QgsWFSProvider::~QgsWFSProvider ()
@@ -134,15 +142,22 @@ QgsWFSProvider::~QgsWFSProvider()
134
142
135
143
QgsAbstractFeatureSource* QgsWFSProvider::featureSource () const
136
144
{
137
- return new QgsWFSFeatureSource ( this );
145
+ QgsWFSFeatureSource *fs = new QgsWFSFeatureSource ( this );
146
+ connect ( fs, SIGNAL ( extentRequested ( const QgsRectangle & ) ),
147
+ this , SLOT ( extendExtent ( const QgsRectangle & ) ) );
148
+ return fs;
138
149
}
139
150
140
151
void QgsWFSProvider::reloadData ()
141
152
{
153
+ mPendingRetrieval = false ;
142
154
deleteData ();
143
155
delete mSpatialIndex ;
144
156
mSpatialIndex = new QgsSpatialIndex ();
145
157
mValid = !getFeature ( dataSourceUri () );
158
+
159
+ if ( !mCached )
160
+ emit dataChanged ();
146
161
}
147
162
148
163
void QgsWFSProvider::deleteData ()
@@ -193,6 +208,7 @@ bool QgsWFSProvider::isValid()
193
208
194
209
QgsFeatureIterator QgsWFSProvider::getFeatures ( const QgsFeatureRequest& request )
195
210
{
211
+ #if 0
196
212
if ( !( request.flags() & QgsFeatureRequest::NoGeometry ) )
197
213
{
198
214
QgsRectangle rect = request.filterRect();
@@ -261,7 +277,8 @@ QgsFeatureIterator QgsWFSProvider::getFeatures( const QgsFeatureRequest& request
261
277
}
262
278
263
279
}
264
- return QgsFeatureIterator ( new QgsWFSFeatureIterator ( new QgsWFSFeatureSource ( this ), true , request ) );
280
+ #endif
281
+ return new QgsWFSFeatureIterator ( new QgsWFSFeatureSource ( this ), true , request );
265
282
}
266
283
267
284
int QgsWFSProvider::getFeature ( const QString& uri )
@@ -658,7 +675,7 @@ int QgsWFSProvider::getFeatureGET( const QString& uri, const QString& geometryAt
658
675
QString typeName = parameterFromUrl ( " typename" );
659
676
QgsGml dataReader ( typeName, geometryAttribute, mFields );
660
677
661
- QObject:: connect ( &dataReader, SIGNAL ( dataProgressAndSteps ( int , int ) ), this , SLOT ( handleWFSProgressMessage ( int , int ) ) );
678
+ connect ( &dataReader, SIGNAL ( dataProgressAndSteps ( int , int ) ), this , SLOT ( handleWFSProgressMessage ( int , int ) ) );
662
679
663
680
// also connect to statusChanged signal of qgisapp (if it exists)
664
681
QWidget* mainWindow = 0 ;
@@ -675,14 +692,15 @@ int QgsWFSProvider::getFeatureGET( const QString& uri, const QString& geometryAt
675
692
676
693
if ( mainWindow )
677
694
{
678
- QObject:: connect ( this , SIGNAL ( dataReadProgressMessage ( QString ) ), mainWindow, SLOT ( showStatusMessage ( QString ) ) );
695
+ connect ( this , SIGNAL ( dataReadProgressMessage ( QString ) ), mainWindow, SLOT ( showStatusMessage ( QString ) ) );
679
696
}
680
697
681
698
// if ( dataReader.getWFSData() != 0 )
682
699
QUrl getFeatureUrl ( uri );
683
700
getFeatureUrl.removeQueryItem ( " username" );
684
701
getFeatureUrl.removeQueryItem ( " password" );
685
- if ( dataReader.getFeatures ( getFeatureUrl.toString (), &mWKBType , &mExtent , mAuth .mUserName , mAuth .mPassword ) != 0 )
702
+ QgsRectangle extent;
703
+ if ( dataReader.getFeatures ( getFeatureUrl.toString (), &mWKBType , mCached ? &mExtent : &extent, mAuth .mUserName , mAuth .mPassword ) != 0 )
686
704
{
687
705
QgsDebugMsg ( " getWFSData returned with error" );
688
706
return 1 ;
@@ -691,7 +709,6 @@ int QgsWFSProvider::getFeatureGET( const QString& uri, const QString& geometryAt
691
709
mIdMap = dataReader.idsMap ();
692
710
693
711
QgsDebugMsg ( QString ( " feature count after request is: %1" ).arg ( mFeatures .size () ) );
694
- QgsDebugMsg ( QString ( " mExtent after request is: %1" ).arg ( mExtent .toString () ) );
695
712
696
713
if ( mWKBType != QGis::WKBNoGeometry )
697
714
{
@@ -726,7 +743,8 @@ int QgsWFSProvider::getFeatureFILE( const QString& uri, const QString& geometryA
726
743
727
744
QDomElement featureCollectionElement = gmlDoc.documentElement ();
728
745
// get and set Extent
729
- if ( mWKBType != QGis::WKBNoGeometry && getExtentFromGML2 ( &mExtent , featureCollectionElement ) != 0 )
746
+ QgsRectangle extent;
747
+ if ( mWKBType != QGis::WKBNoGeometry && getExtentFromGML2 ( mCached ? &mExtent : &extent, featureCollectionElement ) != 0 )
730
748
{
731
749
return 3 ;
732
750
}
@@ -1102,7 +1120,6 @@ int QgsWFSProvider::getExtentFromGML2( QgsRectangle* extent, const QDomElement&
1102
1120
1103
1121
int QgsWFSProvider::setCRSFromGML2 ( const QDomElement& wfsCollectionElement )
1104
1122
{
1105
- QgsDebugMsg ( " entering." );
1106
1123
// search <gml:boundedBy>
1107
1124
QDomNodeList boundedByList = wfsCollectionElement.elementsByTagNameNS ( GML_NAMESPACE, " boundedBy" );
1108
1125
if ( boundedByList.size () < 1 )
@@ -1523,6 +1540,26 @@ void QgsWFSProvider::getLayerCapabilities()
1523
1540
QString name = featureTypeList.at ( i ).firstChildElement ( " Name" ).text ();
1524
1541
if ( name == thisLayerName )
1525
1542
{
1543
+ if ( !mCached && mExtent .isEmpty () )
1544
+ {
1545
+ QDomElement e = featureTypeList.at ( i ).firstChildElement ( " LatLongBoundingBox" );
1546
+ if ( !e.isNull () )
1547
+ {
1548
+ QgsRectangle r ( e.attribute ( " minx" ).toDouble (), e.attribute ( " miny" ).toDouble (),
1549
+ e.attribute ( " maxx" ).toDouble (), e.attribute ( " maxy" ).toDouble () );
1550
+ QgsCoordinateReferenceSystem src;
1551
+ src.createFromOgcWmsCrs ( " CRS:84" );
1552
+ QgsCoordinateTransform ct ( src, mSourceCRS );
1553
+
1554
+ QgsDebugMsg ( " latlon ext:" + r.toString () );
1555
+ QgsDebugMsg ( " src:" + src.authid () );
1556
+ QgsDebugMsg ( " dst:" + mSourceCRS .authid () );
1557
+
1558
+ mExtent = ct.transformBoundingBox ( r, QgsCoordinateTransform::ForwardTransform );
1559
+
1560
+ QgsDebugMsg ( " layer ext:" + mExtent .toString () );
1561
+ }
1562
+ }
1526
1563
appendSupportedOperations ( featureTypeList.at ( i ).firstChildElement ( " Operations" ), capabilities );
1527
1564
break ;
1528
1565
}
@@ -1558,6 +1595,7 @@ void QgsWFSProvider::appendSupportedOperations( const QDomElement& operationsEle
1558
1595
}
1559
1596
}
1560
1597
1598
+ #if 0
1561
1599
//initialization for getRenderedOnly option
1562
1600
//(formerly "Only request features overlapping the current view extent")
1563
1601
bool QgsWFSProvider::initGetRenderedOnly( const QgsRectangle &rect )
@@ -1585,6 +1623,7 @@ bool QgsWFSProvider::initGetRenderedOnly( const QgsRectangle &rect )
1585
1623
}
1586
1624
return true;
1587
1625
}
1626
+ #endif
1588
1627
1589
1628
QGis::WkbType QgsWFSProvider::geomTypeFromPropertyType ( QString attName, QString propType )
1590
1629
{
@@ -1617,33 +1656,73 @@ void QgsWFSProvider::handleException( const QDomDocument& serverResponse )
1617
1656
QDomElement exceptionElem = serverResponse.documentElement ();
1618
1657
if ( exceptionElem.isNull () )
1619
1658
{
1620
- pushError ( QObject:: tr ( " empty response" ) );
1659
+ pushError ( tr ( " empty response" ) );
1621
1660
return ;
1622
1661
}
1623
1662
1624
1663
if ( exceptionElem.tagName () == " ServiceExceptionReport" )
1625
1664
{
1626
- pushError ( QObject:: tr ( " WFS service exception:%1" ).arg ( exceptionElem.firstChildElement ( " ServiceException" ).text () ) );
1665
+ pushError ( tr ( " WFS service exception:%1" ).arg ( exceptionElem.firstChildElement ( " ServiceException" ).text () ) );
1627
1666
return ;
1628
1667
}
1629
1668
1630
1669
if ( exceptionElem.tagName () == " WFS_TransactionResponse" )
1631
1670
{
1632
- pushError ( QObject:: tr ( " unsuccessful service response: %1" ).arg ( exceptionElem.firstChildElement ( " TransactionResult" ).firstChildElement ( " Message" ).text () ) );
1671
+ pushError ( tr ( " unsuccessful service response: %1" ).arg ( exceptionElem.firstChildElement ( " TransactionResult" ).firstChildElement ( " Message" ).text () ) );
1633
1672
return ;
1634
1673
}
1635
1674
1636
1675
if ( exceptionElem.tagName () == " ExceptionReport" )
1637
1676
{
1638
1677
QDomElement exception = exceptionElem.firstChildElement ( " Exception" );
1639
- pushError ( QObject:: tr ( " WFS exception report (code=%1 text=%2)" )
1640
- .arg ( exception .attribute ( " exceptionCode" , QObject:: tr ( " missing" ) ) )
1678
+ pushError ( tr ( " WFS exception report (code=%1 text=%2)" )
1679
+ .arg ( exception .attribute ( " exceptionCode" , tr ( " missing" ) ) )
1641
1680
.arg ( exception .firstChildElement ( " ExceptionText" ).text () )
1642
1681
);
1643
1682
return ;
1644
1683
}
1645
1684
1646
- pushError ( QObject::tr ( " unhandled response: %1" ).arg ( exceptionElem.tagName () ) );
1685
+ pushError ( tr ( " unhandled response: %1" ).arg ( exceptionElem.tagName () ) );
1686
+ }
1687
+
1688
+ void QgsWFSProvider::extendExtent ( const QgsRectangle &extent )
1689
+ {
1690
+ if ( mCached )
1691
+ return ;
1692
+
1693
+ QgsRectangle r ( mExtent .intersect ( &extent ) );
1694
+
1695
+ if ( mGetExtent .contains ( r ) )
1696
+ return ;
1697
+
1698
+ if ( mGetExtent .isEmpty () )
1699
+ {
1700
+ mGetExtent = r;
1701
+ }
1702
+ else if ( qgsDoubleNear ( mGetExtent .xMinimum (), r.xMinimum () ) &&
1703
+ qgsDoubleNear ( mGetExtent .yMinimum (), r.yMinimum () ) &&
1704
+ qgsDoubleNear ( mGetExtent .xMaximum (), r.xMaximum () ) &&
1705
+ qgsDoubleNear ( mGetExtent .yMaximum (), r.yMaximum () ) )
1706
+ {
1707
+ return ;
1708
+ }
1709
+ else
1710
+ {
1711
+ mGetExtent .combineExtentWith ( &r );
1712
+ }
1713
+
1714
+ setDataSourceUri ( dataSourceUri ().replace ( QRegExp ( " BBOX=[^&]*" ),
1715
+ QString ( " BBOX=%1,%2,%3,%4" )
1716
+ .arg ( qgsDoubleToString ( mGetExtent .xMinimum () ) )
1717
+ .arg ( qgsDoubleToString ( mGetExtent .yMinimum () ) )
1718
+ .arg ( qgsDoubleToString ( mGetExtent .xMaximum () ) )
1719
+ .arg ( qgsDoubleToString ( mGetExtent .yMaximum () ) ) ) );
1720
+
1721
+ if ( !mPendingRetrieval )
1722
+ {
1723
+ mPendingRetrieval = true ;
1724
+ QTimer::singleShot ( 100 , this , SLOT ( reloadData () ) );
1725
+ }
1647
1726
}
1648
1727
1649
1728
QGISEXTERN QgsWFSProvider* classFactory ( const QString *uri )
0 commit comments