diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp
index 6b56f2a..abceeb3 100644
--- a/src/app/qgisapp.cpp
+++ b/src/app/qgisapp.cpp
@@ -2437,7 +2437,6 @@ void QgisApp::addWfsLayer()
     return;
   }
 
-  // Fudge for now
   QgsDebugMsg( "about to addWfsLayer" );
 
   // TODO: QDialog for now, switch to QWidget in future
@@ -2450,7 +2449,12 @@ void QgisApp::addWfsLayer()
   connect( wfss , SIGNAL( addWfsLayer( QString, QString ) ),
            this , SLOT( addWfsLayer( QString, QString ) ) );
 
-  wfss->setProperty( "MapExtent", mMapCanvas->extent().toString() ); //hack to reenable wfs with extent setting
+  //reenable wfs with extent setting: pass canvas info to source select
+  wfss->setProperty( "MapExtent", mMapCanvas->extent().toString() );
+  if ( mMapCanvas->mapRenderer()->hasCrsTransformEnabled() )
+  { //if "on the fly" reprojection is active, pass canvas CRS
+    wfss->setProperty( "MapCRS", mMapCanvas->mapRenderer()->destinationCrs().authid() );
+  }
 
   bool bkRenderFlag = mMapCanvas->renderFlag();
   mMapCanvas->setRenderFlag( false );
diff --git a/src/providers/wfs/qgswfsdata.cpp b/src/providers/wfs/qgswfsdata.cpp
index 9a196ac..d334818 100644
--- a/src/providers/wfs/qgswfsdata.cpp
+++ b/src/providers/wfs/qgswfsdata.cpp
@@ -101,7 +101,7 @@ int QgsWFSData::getWFSData()
 
   if ( mainWindow )
   {
-    progressDialog = new QProgressDialog( tr( "Loading WFS data" ), tr( "Abort" ), 0, 0, mainWindow );
+    progressDialog = new QProgressDialog( tr( "Loading WFS data\n%1" ).arg( mTypeName ), tr( "Abort" ), 0, 0, mainWindow );
     progressDialog->setWindowModality( Qt::ApplicationModal );
     connect( this, SIGNAL( dataReadProgress( int ) ), progressDialog, SLOT( setValue( int ) ) );
     connect( this, SIGNAL( totalStepsUpdate( int ) ), progressDialog, SLOT( setMaximum( int ) ) );
diff --git a/src/providers/wfs/qgswfsprovider.cpp b/src/providers/wfs/qgswfsprovider.cpp
index f40220b..b1c16df 100644
--- a/src/providers/wfs/qgswfsprovider.cpp
+++ b/src/providers/wfs/qgswfsprovider.cpp
@@ -17,7 +17,9 @@
 
 #define WFS_THRESHOLD 200
 
+#include "qgis.h"
 #include "qgsapplication.h"
+#include "qgsmaplayerregistry.h"
 #include "qgsfeature.h"
 #include "qgsfield.h"
 #include "qgsgeometry.h"
@@ -47,11 +49,17 @@ static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
 QgsWFSProvider::QgsWFSProvider( const QString& uri )
     : QgsVectorDataProvider( uri ),
     mNetworkRequestFinished( true ),
+    mGeometryAttribute( 0 ),
     mEncoding( QgsWFSProvider::GET ),
     mUseIntersect( false ),
+    mWKBType( QGis::WKBUnknown ),
     mSourceCRS( 0 ),
     mFeatureCount( 0 ),
-    mValid( true )
+    mValid( true ),
+    mLayer( 0 ),
+    mGetRenderedOnly( false ),
+    mInitGro( false ),
+    mGetExtent()
 {
   mSpatialIndex = 0;
   if ( uri.isEmpty() )
@@ -60,7 +68,39 @@ QgsWFSProvider::QgsWFSProvider( const QString& uri )
     return;
   }
 
-  reloadData();
+  //Local url or HTTP?  [WBC 111221] refactored from getFeature()
+  if ( uri.startsWith( "http" ) )
+  {
+    mEncoding = QgsWFSProvider::GET;
+  }
+  else
+  {
+    mEncoding = QgsWFSProvider::FILE;
+  }
+
+  //create mSourceCRS from url if possible [WBC 111221] refactored from GetFeatureGET()
+  QString srsname = parameterFromUrl( "SRSNAME" );
+  if ( !srsname.isEmpty() )
+  {
+    mSourceCRS.createFromOgcWmsCrs( srsname );
+  }
+
+  //fetch attributes of layer and type of its geometry attribute
+  //WBC 111221: extracting geometry type here instead of getFeature allows successful
+  //layer creation even when no features are retrieved (due to, e.g., BBOX or FILTER)
+  if ( describeFeatureType( uri, mGeometryAttribute, mFields, mWKBType ) )
+  {
+    mValid = false;
+    QgsDebugMsg( QString( "describeFeatureType failed, URI=%1" ).arg( uri ) );
+    QMessageBox( QMessageBox::Warning, "DescribeFeatureType failed!",
+                 QString( "Layer cannot be created from\n%1" ).arg( uri ) );
+    return;
+  }
+
+  if ( ! uri.contains("BBOX") )
+  { //"Cache Features" option; get all features in layer immediately
+    reloadData();
+  } //otherwise, defer feature retrieval until layer is first rendered
 
   if ( mValid )
   {
@@ -231,30 +271,76 @@ void QgsWFSProvider::select( QgsAttributeList fetchAttributes,
   mAttributesToFetch = fetchAttributes;
   mFetchGeom = fetchGeometry;
 
-  QString dsURI = dataSourceUri();
-  if ( dsURI.contains( "BBOX" ) )
-  {
-    QUrl url( dsURI );
-    url.removeQueryItem( "BBOX" );
-    url.addQueryItem( "BBOX", QString::number( rect.xMinimum() ) + "," + QString::number( rect.yMinimum() ) + ","
-                      + QString::number( rect.xMaximum() ) + "," + QString::number( rect.yMaximum() ) );
-    setDataSourceUri( url.toString() );
-    reloadData();
+  if ( rect.isEmpty() )
+  { //select all features
+    mSpatialFilter = mExtent;
     mSelectedFeatures = mFeatures.keys();
-    mSpatialFilter = rect;
   }
   else
-  {
-    if ( rect.isEmpty() )
-    {
-      mSpatialFilter = mExtent;
-      mSelectedFeatures = mFeatures.keys();
-    }
-    else
-    {
-      mSpatialFilter = rect;
-      mSelectedFeatures = mSpatialIndex->intersects( mSpatialFilter );
+  { //select features intersecting caller's extent
+    QString dsURI = dataSourceUri();
+    //first time through, initialize GetRenderedOnly args
+    //ctor cannot initialize because layer object not available then
+    if ( ! mInitGro )
+    { //did user check "Cache Features" in WFS layer source selection?
+      if ( dsURI.contains( "BBOX" ) )
+      { //no: initialize incremental getFeature
+        if ( initGetRenderedOnly( rect ) )
+        {
+          mGetRenderedOnly = true;
+        }
+        else
+        { //initialization failed;
+          QgsDebugMsg( QString( "GetRenderedOnly initialization failed; incorrect operation may occur\n%1" )
+                                .arg( dataSourceUri() ) );
+          QMessageBox( QMessageBox::Warning, "Non-Cached layer initialization failed!",
+                       QString( "Incorrect operation may occur:\n%1" ).arg( dataSourceUri() ) );
+        }
+      }
+      mInitGro = true;
+    }
+
+    if ( mGetRenderedOnly )
+    { //"Cache Features" was not selected for this layer
+      //has rendered extent expanded beyond last-retrieved WFS extent?
+      //NB: "intersect" instead of "contains" tolerates rounding errors;
+      //    avoids unnecessary second fetch on zoom-in/zoom-out sequences
+      QgsRectangle olap( rect );
+      olap = olap.intersect( &mGetExtent );
+      if ( doubleNear( rect.width(), olap.width() ) && doubleNear ( rect.height(), olap.height() ) )
+      { //difference between canvas and layer extents is within rounding error: do not re-fetch
+        QgsDebugMsg( QString( "Layer %1 GetRenderedOnly: no fetch required" ).arg( mLayer->name() ) );
+      }
+      else
+      { //combined old and new extents might speed up local panning & zooming
+        mGetExtent.combineExtentWith( &rect );
+        //but see if the combination is useless or too big
+        double pArea = mGetExtent.width() * mGetExtent.height();
+        double cArea = rect.width() * rect.height();
+        if ( olap.isEmpty() || pArea > ( cArea * 4.0 ) )
+        { //new canvas extent does not overlap or combining old and new extents would
+          //fetch > 4 times the area to be rendered; get only what will be rendered
+          mGetExtent = rect;
+        }
+        QgsDebugMsg( QString( "Layer %1 GetRenderedOnly: fetching extent %2" )
+                   .arg( mLayer->name(), mGetExtent.asWktCoordinates() ) );
+        dsURI = dsURI.replace( QRegExp( "BBOX=[^&]*" ),
+                               QString( "BBOX=%1,%2,%3,%4" )
+                               .arg( mGetExtent.xMinimum(), 0, 'f' )
+                               .arg( mGetExtent.yMinimum(), 0, 'f' )
+                               .arg( mGetExtent.xMaximum(), 0, 'f' )
+                               .arg( mGetExtent.yMaximum(), 0, 'f' ) );
+        //TODO: BBOX may not be combined with FILTER. WFS spec v. 1.1.0, sec. 14.7.3 ff.
+        //      if a FILTER is present, the BBOX must be merged into it, capabilities permitting.
+        //      Else one criterion must be abandoned and the user warned.  [WBC 111221]
+        setDataSourceUri( dsURI );
+        reloadData();
+        mLayer->updateExtents();
+      }
     }
+
+    mSpatialFilter = rect;
+    mSelectedFeatures = mSpatialIndex->intersects( mSpatialFilter );
   }
 
   mFeatureIterator = mSelectedFeatures.begin();
@@ -262,41 +348,11 @@ void QgsWFSProvider::select( QgsAttributeList fetchAttributes,
 
 int QgsWFSProvider::getFeature( const QString& uri )
 {
-  QString geometryAttribute;
-
-  //Local url or HTTP?
-  if ( uri.startsWith( "http" ) )
-  {
-    mEncoding = QgsWFSProvider::GET;
-  }
-  else
-  {
-    mEncoding = QgsWFSProvider::FILE;
-  }
-
-  if ( mEncoding == QgsWFSProvider::FILE )
-  {
-    //guess geometry attribute and other attributes from schema or from .gml file
-    if ( describeFeatureTypeFile( uri, mGeometryAttribute, mFields ) != 0 )
-    {
-      return 1;
-    }
-  }
-  else //take schema with describeFeatureType request
-  {
-    QString describeFeatureUri = uri;
-    describeFeatureUri.replace( QString( "GetFeature" ), QString( "DescribeFeatureType" ) );
-    if ( describeFeatureType( describeFeatureUri, mGeometryAttribute, mFields ) != 0 )
-    {
-      return 1;
-    }
-  }
-
   if ( mEncoding == QgsWFSProvider::GET )
   {
     return getFeatureGET( uri, mGeometryAttribute );
   }
-  else//local file
+  else  //local file
   {
     return getFeatureFILE( uri, mGeometryAttribute ); //read the features from disk
   }
@@ -658,16 +714,27 @@ bool QgsWFSProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_
   }
 }
 
-int QgsWFSProvider::describeFeatureType( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields )
+int QgsWFSProvider::describeFeatureType( const QString& uri, QString& geometryAttribute,
+                                         QgsFieldMap& fields, QGis::WkbType& geomType )
+//NB: also called from QgsWFSSourceSelect::on_treeWidget_itemDoubleClicked() to build filters.
+//    a temporary provider object is constructed with a null URI, which bypasses much provider
+//    instantiation logic: refresh(), getFeature(), etc.  therefore, many provider class members
+//    are only default values or uninitialized when running under the source select dialog!
 {
   fields.clear();
-  switch ( mEncoding )
-  {
-    case QgsWFSProvider::GET:
-      return describeFeatureTypeGET( uri, geometryAttribute, fields );
-    case QgsWFSProvider::FILE:
-      return describeFeatureTypeFile( uri, geometryAttribute, fields );
-  }
+  //Local url or HTTP?  WBC111221 refactored here from getFeature()
+  switch( mEncoding )
+  {
+     case QgsWFSProvider::GET:
+     {
+       return describeFeatureTypeGET( uri, geometryAttribute, fields, geomType );
+     }
+     case QgsWFSProvider::FILE:
+     {
+       return describeFeatureTypeFile( uri, geometryAttribute, fields, geomType );
+     }
+  }
+  QgsDebugMsg( "SHOULD NOT OCCUR: mEncoding undefined" );
   return 1;
 }
 
@@ -682,13 +749,6 @@ int QgsWFSProvider::getFeatureGET( const QString& uri, const QString& geometryAt
     thematicAttributes.insert( it.value().name(), qMakePair( it.key(), it.value() ) );
   }
 
-  //create mSourceCRS from url if possible
-  QString srsname = parameterFromUrl( "SRSNAME" );
-  if ( !srsname.isEmpty() )
-  {
-    mSourceCRS.createFromOgcWmsCrs( srsname );
-  }
-
   QgsWFSData dataReader( uri, &mExtent, mFeatures, mIdMap, geometryAttribute, thematicAttributes, &mWKBType );
   QObject::connect( &dataReader, SIGNAL( dataProgressAndSteps( int , int ) ), this, SLOT( handleWFSProgressMessage( int, int ) ) );
 
@@ -765,7 +825,7 @@ int QgsWFSProvider::getFeatureFILE( const QString& uri, const QString& geometryA
   return 0;
 }
 
-int QgsWFSProvider::describeFeatureTypeGET( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields )
+int QgsWFSProvider::describeFeatureTypeGET( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields, QGis::WkbType& geomType )
 {
   if ( !mNetworkRequestFinished )
   {
@@ -774,7 +834,9 @@ int QgsWFSProvider::describeFeatureTypeGET( const QString& uri, QString& geometr
 
   mNetworkRequestFinished = false;
 
-  QNetworkRequest request( uri );
+  QString describeFeatureUri = uri;
+  describeFeatureUri.replace( QString( "GetFeature" ), QString( "DescribeFeatureType" ) );
+  QNetworkRequest request( describeFeatureUri );
   QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );
   connect( reply, SIGNAL( finished() ), this, SLOT( networkRequestFinished() ) );
   while ( !mNetworkRequestFinished )
@@ -792,8 +854,10 @@ int QgsWFSProvider::describeFeatureTypeGET( const QString& uri, QString& geometr
     return 2;
   }
 
-  if ( readAttributesFromSchema( describeFeatureDocument, geometryAttribute, fields ) != 0 )
+  if ( readAttributesFromSchema( describeFeatureDocument,
+                                 geometryAttribute, fields, geomType ) != 0 )
   {
+    QgsDebugMsg( QString( "FAILED: readAttributesFromSchema" ) );
     return 3;
   }
 
@@ -805,7 +869,7 @@ void QgsWFSProvider::networkRequestFinished()
   mNetworkRequestFinished = true;
 }
 
-int QgsWFSProvider::describeFeatureTypeFile( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields )
+int QgsWFSProvider::describeFeatureTypeFile( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields, QGis::WkbType& geomType)
 {
   //first look in the schema file
   QString noExtension = uri;
@@ -821,7 +885,7 @@ int QgsWFSProvider::describeFeatureTypeFile( const QString& uri, QString& geomet
       return 1; //xml file not readable or not valid
     }
 
-    if ( readAttributesFromSchema( schemaDoc, geometryAttribute, fields ) != 0 )
+    if ( readAttributesFromSchema( schemaDoc, geometryAttribute, fields, geomType ) != 0 )
     {
       return 2;
     }
@@ -846,7 +910,7 @@ int QgsWFSProvider::describeFeatureTypeFile( const QString& uri, QString& geomet
   return 0;
 }
 
-int QgsWFSProvider::readAttributesFromSchema( QDomDocument& schemaDoc, QString& geometryAttribute, QgsFieldMap& fields )
+int QgsWFSProvider::readAttributesFromSchema( QDomDocument& schemaDoc, QString& geometryAttribute, QgsFieldMap& fields, QGis::WkbType& geomType )
 {
   //get the <schema> root element
   QDomNodeList schemaNodeList = schemaDoc.elementsByTagNameNS( "http://www.w3.org/2001/XMLSchema", "schema" );
@@ -921,9 +985,11 @@ int QgsWFSProvider::readAttributesFromSchema( QDomDocument& schemaDoc, QString&
 
     //is it a geometry attribute?
     //MH 090428: sometimes the <element> tags for geometry attributes have only attribute ref="gml:polygonProperty" and no name
-    if (( type.startsWith( "gml:" ) && type.endsWith( "PropertyType" ) ) || name.isEmpty() )
+    QRegExp gmlPT( "gml:(.*)PropertyType" );
+    if ( type.indexOf( gmlPT ) == 0 || name.isEmpty() )
     {
       geometryAttribute = name;
+      geomType = geomTypeFromPropertyType(geometryAttribute, gmlPT.cap(1) );
     }
     else //todo: distinguish between numerical and non-numerical types
     {
@@ -2288,6 +2354,54 @@ void QgsWFSProvider::appendSupportedOperations( const QDomElement& operationsEle
   }
 }
 
+//initialization for getRenderedOnly option
+//(formerly "Only request features overlapping the current view extent")
+bool QgsWFSProvider::initGetRenderedOnly( const QgsRectangle rect )
+{ //find our layer
+  QMap<QString, QgsMapLayer*> layers = QgsMapLayerRegistry::instance()->mapLayers();
+  QMap<QString, QgsMapLayer*>::const_iterator layersIt = layers.begin();
+  for ( ; layersIt != layers.end() ; ++layersIt )
+  {
+    if ( ( mLayer = dynamic_cast<QgsVectorLayer*>( layersIt.value() ) ) )
+    {
+      if ( mLayer->dataProvider() == this )
+      {
+        QgsDebugMsg( QString( "found layer %1" ).arg( mLayer->name() ) );
+        break;
+      }
+    }
+  }
+  if ( layersIt == layers.end() )
+  {
+    QgsDebugMsg( "SHOULD NOT OCCUR: initialize() did not find layer." );
+    return false;
+  }
+  return true;
+}
+
+QGis::WkbType QgsWFSProvider::geomTypeFromPropertyType( QString attName, QString propType )
+{
+  const QStringList geomTypes = ( QStringList ()
+    //all GML v.2.1.3 _geometryProperty group members, except MultiGeometryPropertyType
+    //sequence must exactly match enum Qgis::WkbType
+    << ""  // unknown geometry, enum 0
+    << "Point"
+    << "LineString"
+    << "Polygon"
+    << "MultiPoint"
+    << "MultiLineString"
+    << "MultiPolygon" );
+
+  QgsDebugMsg( QString( "DescribeFeatureType geometry attribute \"%1\" type is \"%2\"" )
+                       .arg( attName, propType ) );
+  int i = geomTypes.indexOf( propType );
+  if ( i <= 0 )
+  { // feature type missing or unknown
+    i = (int) QGis::WKBUnknown;
+  }
+  return (QGis::WkbType) i;
+}
+
 void QgsWFSProvider::handleException( const QDomDocument& serverResponse ) const
 {
   QDomElement exceptionElem = serverResponse.documentElement();
diff --git a/src/providers/wfs/qgswfsprovider.h b/src/providers/wfs/qgswfsprovider.h
index bf5c124..ac2d9e7 100644
--- a/src/providers/wfs/qgswfsprovider.h
+++ b/src/providers/wfs/qgswfsprovider.h
@@ -23,6 +23,8 @@
 #include "qgsrectangle.h"
 #include "qgscoordinatereferencesystem.h"
 #include "qgsvectordataprovider.h"
+#include "qgsmaplayer.h"
+#include "qgsvectorlayer.h"
 
 class QgsRectangle;
 class QgsSpatialIndex;
@@ -140,8 +142,9 @@ class QgsWFSProvider: public QgsVectorDataProvider
       synchronize with changes in the data source*/
     virtual void reloadData();
 
-    /**Collects information about the field types. Is called internally from QgsWFSProvider::getFeature. The method delegates the work to request specific ones and gives back the name of the geometry attribute and the thematic attributes with their types*/
-    int describeFeatureType( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );
+    /**Collects information about the field types. Is called internally from QgsWFSProvider ctor. The method delegates the work to request specific ones and gives back the name of the geometry attribute and the thematic attributes with their types*/
+    int describeFeatureType( const QString& uri, QString& geometryAttribute,
+                             QgsFieldMap& fields, QGis::WkbType& geomType );
 
   signals:
     void dataReadProgressMessage( QString message );
@@ -191,6 +194,14 @@ class QgsWFSProvider: public QgsVectorDataProvider
     QString mWfsNamespace;
     /**Server capabilities for this layer (generated from capabilities document)*/
     int mCapabilities;
+    /**GetRenderedOnly: layer asociated with this provider*/
+    QgsVectorLayer *mLayer;
+    /**GetRenderedOnly: fetch only features within canvas extent to be rendered*/
+    bool mGetRenderedOnly;
+    /**GetRenderedOnly initializaiton flat*/
+    bool mInitGro;
+    /**if GetRenderedOnly, extent specified in WFS getFeatures; else empty (no constraint)*/
+    QgsRectangle mGetExtent;
 
     //encoding specific methods of getFeature
     int getFeatureGET( const QString& uri, const QString& geometryAttribute );
@@ -198,13 +209,13 @@ class QgsWFSProvider: public QgsVectorDataProvider
     int getFeatureSOAP( const QString& uri, const QString& geometryAttribute );
     int getFeatureFILE( const QString& uri, const QString& geometryAttribute );
     //encoding specific methods of describeFeatureType
-    int describeFeatureTypeGET( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );
+    int describeFeatureTypeGET( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields, QGis::WkbType& geomType );
     int describeFeatureTypePOST( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );
     int describeFeatureTypeSOAP( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );
-    int describeFeatureTypeFile( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );
+    int describeFeatureTypeFile( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields, QGis::WkbType& geomType );
 
     /**Reads the name of the geometry attribute, the thematic attributes and their types from a dom document. Returns 0 in case of success*/
-    int readAttributesFromSchema( QDomDocument& schemaDoc, QString& geometryAttribute, QgsFieldMap& fields );
+    int readAttributesFromSchema( QDomDocument& schemaDoc, QString& geometryAttribute, QgsFieldMap& fields, QGis::WkbType& geomType );
     /**This method tries to guess the geometry attribute and the other attribute names from the .gml file if no schema is present. Returns 0 in case of success*/
     int guessAttributesFromFile( const QString& uri, QString& geometryAttribute, std::list<QString>& thematicAttributes ) const;
 
@@ -284,6 +295,10 @@ class QgsWFSProvider: public QgsVectorDataProvider
     void appendSupportedOperations( const QDomElement& operationsElem, int& capabilities ) const;
     /**Shows a message box with the exception string (or does nothing if the xml document is not an exception)*/
     void handleException( const QDomDocument& serverResponse ) const;
+    /**Initializes "Cache Features" inactive processing*/
+    bool initGetRenderedOnly( QgsRectangle );
+    /**Converts DescribeFeatureType schema geometry property type to WKBType*/
+    QGis::WkbType geomTypeFromPropertyType( QString attName, QString propType );
 
     void deleteData();
 };
diff --git a/src/providers/wfs/qgswfssourceselect.cpp b/src/providers/wfs/qgswfssourceselect.cpp
index 02c7884..63aa4a6 100644
--- a/src/providers/wfs/qgswfssourceselect.cpp
+++ b/src/providers/wfs/qgswfssourceselect.cpp
@@ -15,7 +15,6 @@
  *                                                                         *
  ***************************************************************************/
 
-#include "qgisinterface.h"
 #include "qgswfssourceselect.h"
 #include "qgswfsconnection.h"
 #include "qgswfsprovider.h"
@@ -25,6 +24,7 @@
 #include "qgscontexthelp.h"
 #include "qgsproject.h"
 #include "qgscoordinatereferencesystem.h"
+#include "qgscoordinatetransform.h"
 #include "qgslogger.h"
 #include "qgsmapcanvas.h" //for current view extent
 #include "qgsmanageconnectionsdialog.h"
@@ -263,22 +263,57 @@ void QgsWFSSourceSelect::addLayer()
 
   QList<QTreeWidgetItem*> selectedItems = treeWidget->selectedItems();
   QList<QTreeWidgetItem*>::const_iterator sIt = selectedItems.constBegin();
-  for ( ; sIt != selectedItems.constEnd(); ++sIt )
+  QgsWFSConnection conn( cmbConnections->currentText() );
+  QString pCrsString( labelCoordRefSys->text() );
+  QgsCoordinateReferenceSystem pCrs( pCrsString );
+  //prepare canvas extent info for layers with "cache features" option not set
+  QgsRectangle extent;
+  QVariant extentVariant = property( "MapExtent" );
+  if ( extentVariant.isValid() )
   {
-    QString typeName = ( *sIt )->text( 1 );
-    QString crs = labelCoordRefSys->text();
-    QString filter = ( *sIt )->text( 4 );
-
-    QgsRectangle currentRectangle;
-    if (( *sIt )->checkState( 3 ) == Qt::Unchecked )
+    QString crs;
+    QgsCoordinateTransform xform;
+    QString extentString = extentVariant.toString();
+    QStringList minMaxSplit = extentString.split( ":" );
+    if ( minMaxSplit.size() > 1 )
     {
-      currentRectangle = mExtent;
+      QStringList xyMinSplit = minMaxSplit[0].split( "," );
+      QStringList xyMaxSplit = minMaxSplit[1].split( "," );
+      if ( xyMinSplit.size() > 1 && xyMaxSplit.size() > 1 )
+      {
+        extent.set( xyMinSplit[0].toDouble(), xyMinSplit[1].toDouble(),
+                    xyMaxSplit[0].toDouble(), xyMaxSplit[1].toDouble() );
+      }
+    }
+    //does canvas have "on the fly" reprojection set?
+    QVariant crsVariant = property( "MapCRS" );
+    if ( crsVariant.isValid() )
+    { //transform between provider CRS set in source select dialog and canvas CRS
+      QgsCoordinateReferenceSystem cCrs( crsVariant.toString() );
+      if ( pCrs.isValid() && cCrs.isValid() )
+      {
+        QgsCoordinateTransform xform( pCrs, cCrs );
+        extent = xform.transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
+        QgsDebugMsg( QString("canvas transform: Canvas CRS=%1, Provider CRS=%2, BBOX=%3")
+                             .arg(cCrs.authid(), pCrs.authid(), extent.asWktCoordinates() ) );
+      }
     }
-
-    //add a wfs layer to the map
-    QgsWFSConnection conn( cmbConnections->currentText() );
-    QString uri = conn.uriGetFeature( typeName, crs, filter, currentRectangle );
-    emit addWfsLayer( uri, typeName );
+  }
+  //create layers that user selected from this WFS source
+  for ( ; sIt != selectedItems.constEnd(); ++sIt )
+  { //add a wfs layer to the map
+    QString typeName = ( *sIt )->text( 1 );  //WFS repository's name for layer
+    QString filter = ( *sIt )->text( 4 );    //optional filter specified by user
+    //is "cache features" checked?
+    if ( ( *sIt )->checkState( 3 ) == Qt::Checked )
+    { //yes: entire WFS layer will be retrieved and cached
+      mUri = conn.uriGetFeature( typeName, pCrsString, filter );
+    }
+    else
+    { //no: include BBOX of current canvas extent in URI
+      mUri = conn.uriGetFeature( typeName, pCrsString, filter, extent );
+    }
+    emit addWfsLayer( mUri, typeName );
   }
   accept();
 }
@@ -365,18 +400,18 @@ void QgsWFSSourceSelect::on_treeWidget_itemDoubleClicked( QTreeWidgetItem* item,
   if ( item && column == 4 )
   {
     //get available fields for wfs layer
-    QgsWFSProvider p( "" );
+    QgsWFSProvider p( "" );  //bypasses most provider instantiation logic
     QgsWFSConnection conn( cmbConnections->currentText() );
     QString uri = conn.uriDescribeFeatureType( item->text( 1 ) );
 
     QgsFieldMap fields;
     QString geometryAttribute;
-    if ( p.describeFeatureType( uri, geometryAttribute, fields ) != 0 )
+    QGis::WkbType geomType;
+    if ( p.describeFeatureType( uri, geometryAttribute, fields, geomType ) != 0 )
     {
       return;
     }
 
-
     //show expression builder
     QgsExpressionBuilderDialog d( 0, item->text( 3 ) );
 
@@ -399,24 +434,3 @@ void QgsWFSSourceSelect::on_treeWidget_itemDoubleClicked( QTreeWidgetItem* item,
     }
   }
 }
-
-void QgsWFSSourceSelect::showEvent( QShowEvent* event )
-{
-  Q_UNUSED( event );
-  QVariant extentVariant = property( "MapExtent" );
-  if ( extentVariant.isValid() )
-  {
-    QString extentString = extentVariant.toString();
-    QStringList minMaxSplit = extentString.split( ":" );
-    if ( minMaxSplit.size() > 1 )
-    {
-      QStringList xyMinSplit = minMaxSplit[0].split( "," );
-      QStringList xyMaxSplit = minMaxSplit[1].split( "," );
-      if ( xyMinSplit.size() > 1 && xyMaxSplit.size() > 1 )
-      {
-        mExtent.set( xyMinSplit[0].toDouble(), xyMinSplit[1].toDouble(), xyMaxSplit[0].toDouble(), xyMaxSplit[1].toDouble() );
-        return;
-      }
-    }
-  }
-}
diff --git a/src/providers/wfs/qgswfssourceselect.h b/src/providers/wfs/qgswfssourceselect.h
index 52643d9..8342f3d 100644
--- a/src/providers/wfs/qgswfssourceselect.h
+++ b/src/providers/wfs/qgswfssourceselect.h
@@ -20,7 +20,6 @@
 
 #include "ui_qgswfssourceselectbase.h"
 #include "qgscontexthelp.h"
-#include "qgsrectangle.h"
 
 class QgsGenericProjectionSelector;
 class QgsWFSConnection;
@@ -47,7 +46,7 @@ class QgsWFSSourceSelect: public QDialog, private Ui::QgsWFSSourceSelectBase
     std::map<QString, std::list<QString> > mAvailableCRS;
     QAbstractButton* btnAdd;
     QgsWFSConnection* mConn;
-    QgsRectangle mExtent;
+    QString mUri;            // data source URI
 
     void populateConnectionList();
 
@@ -74,8 +73,6 @@ class QgsWFSSourceSelect: public QDialog, private Ui::QgsWFSSourceSelectBase
 
     void on_buttonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
 
-  protected:
-    void showEvent( QShowEvent* event );
 };
 
 #endif
diff --git a/src/ui/qgswfssourceselectbase.ui b/src/ui/qgswfssourceselectbase.ui
index 14a21f1..e23dd64 100644
--- a/src/ui/qgswfssourceselectbase.ui
+++ b/src/ui/qgswfssourceselectbase.ui
@@ -6,7 +6,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>552</width>
+    <width>592</width>
     <height>439</height>
    </rect>
   </property>
@@ -114,6 +114,12 @@
      <property name="columnCount">
       <number>5</number>
      </property>
+     <attribute name="headerMinimumSectionSize">
+      <number>27</number>
+     </attribute>
+     <attribute name="headerMinimumSectionSize">
+      <number>27</number>
+     </attribute>
      <column>
       <property name="text">
        <string>Title</string>
@@ -131,7 +137,11 @@
      </column>
      <column>
       <property name="text">
-       <string>cache features</string>
+       <string>Cache
+Features</string>
+      </property>
+      <property name="textAlignment">
+       <set>AlignHCenter|AlignVCenter|AlignCenter</set>
       </property>
      </column>
      <column>
