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..de3df68 100644
--- a/src/providers/wfs/qgswfsprovider.cpp
+++ b/src/providers/wfs/qgswfsprovider.cpp
@@ -18,6 +18,7 @@
 #define WFS_THRESHOLD 200
 
 #include "qgsapplication.h"
+#include "qgsmaplayerregistry.h"
 #include "qgsfeature.h"
 #include "qgsfield.h"
 #include "qgsgeometry.h"
@@ -51,7 +52,10 @@ QgsWFSProvider::QgsWFSProvider( const QString& uri )
     mUseIntersect( false ),
     mSourceCRS( 0 ),
     mFeatureCount( 0 ),
-    mValid( true )
+    mValid( true ),
+    mLayer( 0 ),
+    mGetRenderedOnly( false ),
+    mInitGro( false )
 {
   mSpatialIndex = 0;
   if ( uri.isEmpty() )
@@ -231,30 +235,64 @@ 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() )
+        {
+          mGetRenderedOnly = true;
+        }
+        else
+        { //initialization failed;
+          QgsDebugMsg( QString( "GetRenderOnly aborted; \"Cache Features\" in effect" ) );
+        }
+      }
+      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" to evade small rounding errors; avoids
+      //    unnecessary double fetch on initial rendering or zoom-in/zoom-out sequences
+      QgsRectangle olap( rect );
+      olap = olap.intersect( &mGetExtent );
+      double carea = rect.width() * rect.height();
+      double oarea = olap.width() * olap.height();
+      if ( .9999 < oarea/carea )
+      { //do not re-fetch if previous get extent covers at least 99.99% of canvas extent
+        QgsDebugMsg( QString( "Layer %1 GetRenderedOnly: no fetch required" ).arg( mLayer->name() ) );
+      }
+      else
+      {
+        mGetExtent.combineExtentWith( &rect );
+        QgsDebugMsg( QString( "Layer %1 GetRenderedOnly: fetching extent %2" )
+                   .arg( mLayer->name(), mGetExtent.asWktCoordinates() ) );
+        dsURI = dsURI.replace( QRegExp( "BBOX=[.,0-9]*" ),
+                               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' ) );
+        setDataSourceUri( dsURI );
+        reloadData();
+        mLayer->updateExtents();
+      }
     }
+
+    mSpatialFilter = rect;
+    mSelectedFeatures = mSpatialIndex->intersects( mSpatialFilter );
   }
 
   mFeatureIterator = mSelectedFeatures.begin();
@@ -2288,6 +2326,55 @@ void QgsWFSProvider::appendSupportedOperations( const QDomElement& operationsEle
   }
 }
 
+//initialization for getRenderedOnly option
+//(formerly "Only request features overlapping the current view extent")
+bool QgsWFSProvider::initGetRenderedOnly( )
+{ //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;
+  }
+  //set initial getFeatures extent from URI BBOX
+  double m[4];
+  bool ok = false;  //toDouble failure flag
+  QRegExp rebbox( "BBOX=(([0-9.]+,?){4})" );
+  QString dsURI = dataSourceUri();
+  if ( dsURI.indexOf( rebbox ) >! 0 )
+  {
+    QStringList mlist = rebbox.cap( 1 ).split( "," );
+    QStringList::const_iterator mlistIt = mlist.begin();
+    ok = true;
+    for (int i = 0 ; mlistIt != mlist.end() && ok ; ++mlistIt )
+    {
+      m[ i++ ] = ( *mlistIt ).toDouble( &ok );
+    }
+  }
+  if ( ok )
+  { //initial getFeatures extent
+    mGetExtent = QgsRectangle( m[0], m[1], m[2], m[3] );
+  }
+  else
+  {
+    QgsDebugMsg( QString( "SHOULD NOT OCCUR: missing or malformed URI BBOX args \"%1\"" ).arg( dataSourceUri() ) );
+    return false;
+  }
+  return true;
+}
+
 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..643fc66 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;
@@ -191,6 +193,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 );
@@ -284,6 +294,8 @@ 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();
 
     void deleteData();
 };
diff --git a/src/providers/wfs/qgswfssourceselect.cpp b/src/providers/wfs/qgswfssourceselect.cpp
index 02c7884..f12a8b5 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() );
+      }
     }
-
-    //add a wfs layer to the map
-    QgsWFSConnection conn( cmbConnections->currentText() );
-    QString uri = conn.uriGetFeature( typeName, crs, filter, currentRectangle );
-    emit addWfsLayer( uri, typeName );
+    //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() ) );
+      }
+    }
+  }
+  //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();
 }
@@ -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>
