[qgis] 01/05: Imported Upstream version 2.14.6+dfsg

Bas Couwenberg sebastic at debian.org
Fri Aug 26 14:25:58 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository qgis.

commit fda1341724ab30b1bc8deaa0c797fb1b830c41cf
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Aug 26 14:08:49 2016 +0200

    Imported Upstream version 2.14.6+dfsg
---
 .gitignore                                         |   2 +
 .travis.yml                                        |   2 +
 CMakeLists.txt                                     |   2 +-
 ChangeLog                                          | 235 +++++++++++++++++++++
 debian/changelog                                   |  10 +-
 debian/control.in                                  |   3 +-
 i18n/qgis_de.ts                                    |   2 +-
 python/core/qgsvectorlayer.sip                     |  26 ++-
 python/plugins/fTools/tools/doPointsInPolygon.py   |  10 +-
 .../processing/algs/gdal/ogr2ogronesidebuffer.py   |  26 ++-
 .../plugins/processing/algs/qgis/AddTableField.py  |   5 +-
 .../processing/algs/qgis/AutoincrementalField.py   |   5 +-
 python/plugins/processing/algs/qgis/Centroids.py   |   2 +-
 .../plugins/processing/algs/qgis/CheckValidity.py  |   9 +-
 python/plugins/processing/algs/qgis/ConcaveHull.py |   2 +-
 python/plugins/processing/algs/qgis/ConvexHull.py  |   2 +-
 .../processing/algs/qgis/DensifyGeometries.py      |   5 +-
 python/plugins/processing/algs/qgis/Difference.py  |   4 +-
 python/plugins/processing/algs/qgis/Dissolve.py    |   5 +-
 python/plugins/processing/algs/qgis/Eliminate.py   |   9 +-
 .../processing/algs/qgis/EquivalentNumField.py     |   5 +-
 python/plugins/processing/algs/qgis/Explode.py     |   3 +-
 .../processing/algs/qgis/ExportGeometryInfo.py     |   2 +-
 .../processing/algs/qgis/ExtractByLocation.py      |   2 +-
 .../plugins/processing/algs/qgis/FieldPyculator.py |   7 +-
 .../processing/algs/qgis/FieldsCalculator.py       |   5 +-
 .../plugins/processing/algs/qgis/FieldsMapper.py   |   3 +-
 .../plugins/processing/algs/qgis/Intersection.py   |   5 +-
 .../plugins/processing/algs/qgis/JoinAttributes.py |   3 +-
 python/plugins/processing/algs/qgis/Merge.py       |  10 +-
 .../processing/algs/qgis/MultipartToSingleparts.py |  20 +-
 .../algs/qgis/OrientedMinimumBoundingBox.py        |   5 +-
 .../processing/algs/qgis/PointsDisplacement.py     |   5 +-
 .../processing/algs/qgis/PointsInPolygon.py        |   7 +-
 .../processing/algs/qgis/PointsInPolygonUnique.py  |   5 +-
 .../algs/qgis/PointsInPolygonWeighted.py           |   7 +-
 .../processing/algs/qgis/PointsLayerFromTable.py   |   3 +-
 .../plugins/processing/algs/qgis/PointsToPaths.py  |   2 +-
 python/plugins/processing/algs/qgis/Polygonize.py  |   3 +-
 .../processing/algs/qgis/RandomPointsAlongLines.py |   2 +-
 .../processing/algs/qgis/RandomPointsLayer.py      |   2 +-
 .../algs/qgis/RandomPointsPolygonsFixed.py         |   2 +-
 .../algs/qgis/RandomPointsPolygonsVariable.py      |   2 +-
 .../processing/algs/qgis/ReverseLineDirection.py   |   3 +-
 .../processing/algs/qgis/SaveSelectedFeatures.py   |   5 +-
 .../algs/qgis/SinglePartsToMultiparts.py           |   2 +-
 python/plugins/processing/algs/qgis/Smooth.py      |   3 +-
 python/plugins/processing/algs/qgis/SpatialJoin.py |   9 +-
 python/plugins/processing/algs/qgis/SumLines.py    |   6 +-
 .../processing/algs/qgis/SymmetricalDifference.py  |  13 +-
 python/plugins/processing/algs/qgis/Union.py       |   6 +-
 python/plugins/processing/algs/qgis/VectorSplit.py |   2 +-
 .../processing/algs/qgis/ZonalStatistics.py        |   2 +-
 .../plugins/processing/gui/AlgorithmDialogBase.py  |   3 +
 python/plugins/processing/gui/SilentProgress.py    |   8 +-
 python/testing/__init__.py                         |   5 +-
 src/app/pluginmanager/qgspluginmanager.cpp         |   2 +-
 src/app/qgisapp.cpp                                |   4 +-
 src/app/qgsdxfexportdialog.cpp                     |   8 +-
 src/core/pal/feature.cpp                           |  80 ++++---
 src/core/pal/feature.h                             |   6 +-
 src/core/pal/geomfunction.cpp                      |  53 +++++
 src/core/pal/geomfunction.h                        |  12 ++
 src/core/pal/layer.cpp                             |   2 +-
 src/core/pal/layer.h                               |  16 --
 src/core/pal/pointset.cpp                          |  45 +---
 src/core/qgsgml.cpp                                |  14 ++
 src/core/qgslabelfeature.cpp                       |  24 +++
 src/core/qgslabelfeature.h                         |  34 +++
 src/core/qgslabelingenginev2.cpp                   |   3 -
 src/core/qgslabelingenginev2.h                     |   1 -
 src/core/qgsnetworkaccessmanager.cpp               |  17 +-
 src/core/qgspallabeling.cpp                        |  15 ++
 src/core/qgsrulebasedlabeling.cpp                  |   2 -
 src/core/qgsvectorlayer.cpp                        |  77 ++++++-
 src/core/qgsvectorlayer.h                          |  26 ++-
 src/core/qgsvectorlayerlabelprovider.cpp           |   1 -
 src/gui/CMakeLists.txt                             |  19 ++
 src/gui/attributetable/qgsfeaturelistview.cpp      |   3 +-
 src/providers/ogr/qgsogrfeatureiterator.cpp        |  49 +++--
 src/providers/ogr/qgsogrfeatureiterator.h          |   8 +-
 src/providers/spatialite/qgsspatialiteprovider.cpp |  49 ++---
 src/providers/wcs/qgswcscapabilities.cpp           |  35 +++
 src/providers/wcs/qgswcscapabilities.h             |   3 +
 src/providers/wcs/qgswcsprovider.cpp               |  27 +++
 src/providers/wcs/qgswcsprovider.h                 |  10 +
 src/providers/wfs/qgswfscapabilities.cpp           |  31 +++
 src/providers/wfs/qgswfscapabilities.h             |   3 +
 src/providers/wfs/qgswfsprovider.cpp               |  23 ++
 src/providers/wfs/qgswfsprovider.h                 |  10 +
 src/providers/wms/qgswmscapabilities.cpp           |  22 +-
 src/providers/wms/qgswmscapabilities.h             |   9 +
 src/providers/wms/qgswmsprovider.cpp               |   2 +
 src/server/qgsserver.cpp                           |   4 +-
 src/server/qgswfsserver.cpp                        |  27 ++-
 src/server/qgswmsserver.cpp                        |   4 +
 tests/src/python/providertestbase.py               |  26 +++
 tests/src/python/test_qgsfeatureiterator.py        |   9 +-
 tests/src/python/test_qgspallabeling_placement.py  |   1 +
 tests/src/python/test_qgsserver.py                 |  93 ++++++--
 ...eature_nobbox.txt => wfs_getfeature_limit2.txt} |  19 +-
 .../testdata/qgis_server/wfs_getfeature_nobbox.txt |   2 +-
 ...index2.txt => wfs_getfeature_start1_limit1.txt} |  14 +-
 .../qgis_server/wfs_getfeature_startindex2.txt     |   2 +-
 104 files changed, 1119 insertions(+), 370 deletions(-)

diff --git a/.gitignore b/.gitignore
index 6ce059c..e91eddc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,4 +61,6 @@ tests/testdata/raster/band1_float32_noct_epsg4326.tif.aux.xml
 tests/testdata/raster/band1_int16_noct_epsg4326.tif.aux.xml
 tests/testdata/raster/band3_float32_noct_epsg4326.tif.aux.xml
 tests/testdata/raster/band3_int16_noct_epsg4326.tif.aux.xml
+python/plugins/processing/tests/testdata/custom/grass7/float_raster.tif.aux.xml
+python/plugins/processing/tests/testdata/custom/grass7/raster_1class.tif.aux.xml
 Thumb.db
diff --git a/.travis.yml b/.travis.yml
index c85a552..1d6e070 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,7 @@
 matrix:
   fast_finish: true
+  allow_failures:
+    - os: osx
   include:
     # QT4 based build with Python 2.7 // using container based builds and prebuild binary dependencies in osgeo4travis
     - os: linux
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9af0765..f945b1a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 SET(CPACK_PACKAGE_VERSION_MAJOR "2")
 SET(CPACK_PACKAGE_VERSION_MINOR "14")
-SET(CPACK_PACKAGE_VERSION_PATCH "5")
+SET(CPACK_PACKAGE_VERSION_PATCH "6")
 SET(COMPLETE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
 SET(RELEASE_NAME "Essen")
 IF (POLICY CMP0048) # in CMake 3.0.0+
diff --git a/ChangeLog b/ChangeLog
index eca3ffd..6d0f335 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,238 @@
+rldhont <rldhont at gmail.com>	2016-08-25
+
+    fix typo 1369794 @alexbruy [processing] add missed error() method
+
+Juergen E. Fischer <jef at norbit.de>	2016-08-23
+
+    fix switching of projects within unicode folders
+
+    (cherry picked from commit 3951f15b6481a85b551e2f33f26c2aeb6687a24a)
+
+rldhont <rldhont at gmail.com>	2016-08-23
+
+    Fix indentation after cherry-picking
+
+Alessandro Pasotti <apasottis at boundlessgeo.com>	2016-05-19
+
+    [server][bugfix] FILTER GetFeatureInfo working again
+
+    Fixes #8656
+
+Stéphane Brunner <stephane.brunner at camptocamp.com>	2016-05-26
+
+    Add and fix WFS server MAXFEATURES test
+
+    It was not working when we do a POST with an XML
+
+elpaso <elpaso at itopen.it>	2016-04-01
+
+    [SERVER] Fix encoding of query string for bindings
+
+    Fix an error when passing utf-8 chars in the query string
+    from python bindings
+
+    Adds a test for GetLegendGraphics
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-08-23
+
+    [processing] add missed error() method
+
+Matthias Kuhn <matthias at opengis.ch>	2016-08-18
+
+    [travis] Allow failing mac osx builds
+
+    Seems to be a (temporary?) problem with sip in homebrew
+
+Juergen E. Fischer <jef at norbit.de>	2016-08-18
+
+    dxf export: avoid symbology scale 0 (fixes #14138)
+
+    (cherry picked from commit 0a07fee15297e18a73b63f194f5aeecffd76800c)
+
+Juergen E. Fischer <jef at norbit.de>	2016-08-18
+
+    debian packaging update
+
+    (cherry picked from commit 127fb683b226908c4f34a78a8fa1e43965a51dfa)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-08-17
+
+    fix repeated labels on curved lines when label width > repeat distance
+
+    (cherry-picked from fb346ecf4fda53ccac7ef939bc6ec84a361a9d58)
+    o
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-08-17
+
+    Make QgsVectorLayer uniqueValues/min/maxValue consider edits
+
+    Previously these methods would inconsistently handle the
+    edit buffer, eg uniqueValues would consider changed attributes
+    but not added features. Now uniqueValues, minimumValue and
+    maximumValue all consider both added features and changed
+    attribute values when performing their calculation.
+
+    The most noticable effect of this fix is that the unique
+    values widget now correctly shows values for features which
+    have been added but not yet committed to the provider.
+
+    (cherry-picked from 50c35929d86ab01b22c29cd129fd7019a1bf624a)
+
+Merge: 47421b2 5480a80
+Larry Shaffer <dakcarto at users.noreply.github.com>	2016-08-12
+
+    Merge pull request #3378 from dakcarto/release-2_14-auth-reply-ows
+
+    [auth] Reinstate auth system reply expansions for OWS providers
+
+Anita Graser <anitagraser at gmx.at>	2016-08-10
+
+    fixed failure to insert only one point
+
+    Previously, if pointsNumber was 1, it wouldn't insert a new point in the middle.
+    (cherry picked from commit 754ccefabc5c5fb9ba4472b182f1f05cd2a0ebb2)
+
+Alessandro Pasotti <apasotti at boundlessgeo.com>	2016-08-12
+
+    Stop the timer when the reply finish
+
+    This should fix a few reported and unreported issues
+    with false positive timeout errors.
+
+    Fixes: #12243
+
+     (cherry-picked from ace9d2b0f661849106f0448189cb233710754f12)
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-05-28
+
+    [pluginmanager] limit plugin icon maximum size to prevent breaking description page layout
+
+    (cherry picked from commit e60ed0511fcf52cc81821067f41e8023db0d1dfa)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-22
+
+    Remove cryptic assert (was failing regularly; fixes #15418)
+
+    (cherry picked from commit b1b439f5cc4f709db9839d0ab8209346defe4bb7)
+
+Larry Shaffer <lshaffer at boundlessgeo.com>	2016-08-10
+
+    [auth] Reinstate auth system reply expansions for OWS providers
+
+    - Apparently this was lost during a git squash of commits for 2.12 PR
+
+    (Needs forward-ported to 2.16, master_2 and master)
+
+Larry Shaffer <lshaffer at boundlessgeo.com>	2016-08-10
+
+    [auth] Add missing auth system ui headers for external C++ apps
+
+    (cherry-picked from f3e90f1d5a87b2a7c6c693aa8ba3eaad64161b1d)
+
+Matthias Kuhn <matthias at opengis.ch>	2016-08-10
+
+    Fix crash when clicking in empty relation editor
+
+Matthias Kuhn <matthias at opengis.ch>	2016-08-10
+
+    Fix translation
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-08-10
+
+    Reset layers for each pal placement test, avoids all tests failing
+    because of one
+
+    (cherry-picked from 95ecdaf4383a0337710fd98fe34c93323be8e0ad)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-08-10
+
+    Fix "label only inside polygon" mode when used with perimeter placement
+
+    The option was not working with perimeter placements as perimeter placements alter
+    the label feature geometry to be a boundary linestring - hence no labels where
+    ever inside this boundary.
+
+    Accordingly this refactors how the force label inside polygon option functions.
+    Now QgsLabelFeatures can have a permissible zone geometry set, such that any
+    label candidates outside of this permissible zone are discarded.
+
+    This approach is more flexible as it could also be used for more labeling options
+    in future, eg discarding label candidates which are too far from a centroid or
+    something.
+
+    Sponsored by Andreas Neumann
+
+    (cherry-picked from c234d80e1e6c07813140df416b26ad5665b9ab99)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-08-09
+
+    Make test layer comparison handle different order of features
+
+    (cherry-picked from f449bf236198ced18bbd7078144f12a9aab77cd0)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-08-09
+
+    [processing] Fix multipart to singlepart handling of null geometry
+
+    (cherry-picked from 0455b6600d2ab443ea8d691e3c007ee481a30910)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-08-09
+
+    Add processing test .aux.xml to .gitignore
+
+    (cherry-picked from 0939dbf9df5d0cb6867a4d0b3ea6a543eea77366)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-08-09
+
+    [processing] Use layer crs/fields instead of provider crs/fields
+
+    Since the layer has more complete knowledge of the crs (ie, when
+    provider could not determine crs and user has selected it from
+    the list), and also better knowledge of layer fields (virtual
+    fields, joined fields) we should use these rather than the
+    provider methods.
+
+    (cherry-picked from 06c4b07222f9410e1669387a6497897c61748a16)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-08-09
+
+    Implement provider side FilterFids iterators for OGR provider
+
+    Makes some operations with OGR sources magnitudes faster, ie
+    zoom to 20 selected features in a 4 million point dataset:
+
+    before: 14 seconds of blocked gui
+    after: instant
+
+    (cherry-picked from 1f02fd491d62b2a79ee1bd98000f48cb4db1b442)
+
+Juergen E. Fischer <jef at norbit.de>	2016-08-04
+
+    debian packaging update
+
+    (cherry picked from commit aef87037254729583590102e86a59ea51262cf78)
+
+Sandro Mani <manisandro at gmail.com>	2016-07-27
+
+    [Spatialite] Remove t_table_catalog WHERE clause when searcing for layer styles in db
+
+    This sanity check is unnecessary and breaks styling if the sqlite file is moved or renamed.
+    The t_table_catalog column is kept for backwards compatibility.
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-08-01
+
+    [processing] don't apply additional parameter if offset curve operation is used (fix #15342)
+
+    (cherry picked from commit 1d2b0b4ca7658ed57c4663d9f064ca4bbc55381e)
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-08-01
+
+    [ftools] add support for int64 fields (fix #15367)
+
+Juergen E. Fischer <jef at norbit.de>	2016-07-29
+
+    Release of 2.14.5
+
 Nyall Dawson <nyall.dawson at gmail.com>	2016-07-27
 
     Fix indentation:
diff --git a/debian/changelog b/debian/changelog
index b85a92f..4941a01 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,14 @@
-qgis (2.14.5) UNRELEASED; urgency=medium
+qgis (2.14.6) UNRELEASED; urgency=medium
+
+  * Release of 2.14.6
+
+ -- Jürgen E. Fischer <jef at norbit.de>  Fri, 26 Aug 2016 13:57:14 +0200
+
+qgis (2.14.5) unstable; urgency=medium
 
   * Release of 2.14.5
 
- -- Jürgen E. Fischer <jef at norbit.de>  Fri, 29 Jul 2016 14:03:54 +0200
+ -- Jürgen E. Fischer <jef at norbit.de>  Fri, 26 Aug 2016 13:57:14 +0200
 
 qgis (2.14.4) unstable; urgency=medium
 
diff --git a/debian/control.in b/debian/control.in
index a5ca8b4..25492b2 100644
--- a/debian/control.in
+++ b/debian/control.in
@@ -406,7 +406,8 @@ Depends:
  gdal-bin,
  python-gdal,
  python-matplotlib,
- libqgis-customwidgets,
+ python-shapely,
+ libqgis-customwidgets (>= ${source:Version}),
  ${misc:Depends}
 XB-Python-Version: ${python:Versions}
 Description: Python bindings to QGIS - architecture-independent files
diff --git a/i18n/qgis_de.ts b/i18n/qgis_de.ts
index ee7caa3..7255a98 100644
--- a/i18n/qgis_de.ts
+++ b/i18n/qgis_de.ts
@@ -64684,7 +64684,7 @@ Immer Netzwerk: immer aus dem Netzwerk laden und nicht prüfen, ob im Cache ein
     <message>
         <location filename="../src/ui/qgsoptionsbase.ui" line="1674"/>
         <source>Create transaction groups automatically whenever possible (Experimental)</source>
-        <translation>Ausdrücke auf PostgreSQL serverseitig ausführen, wenn möglich (Experimentell)</translation>
+        <translation>Wenn möglich automatisch Transaktionsgruppen erstellen (Experimentell)</translation>
     </message>
     <message>
         <location filename="../src/ui/qgsoptionsbase.ui" line="1690"/>
diff --git a/python/core/qgsvectorlayer.sip b/python/core/qgsvectorlayer.sip
index 92f8046..ffbdbc3 100644
--- a/python/core/qgsvectorlayer.sip
+++ b/python/core/qgsvectorlayer.sip
@@ -1477,17 +1477,35 @@ class QgsVectorLayer : QgsMapLayer
     /** Caches joined attributes if required (and not already done) */
     void createJoinCaches();
 
-    /** Returns unique values for column
+    /** Calculates a list of unique values contained within an attribute in the layer. Note that
+     * in some circumstances when unsaved changes are present for the layer then the returned list
+     * may contain outdated values (for instance when the attribute value in a saved feature has
+     * been changed inside the edit buffer then the previous saved value will be included in the
+     * returned list).
      * @param index column index for attribute
      * @param uniqueValues out: result list
-     * @param limit maximum number of values to return (-1 if unlimited)
+     * @param limit maximum number of values to return (or -1 if unlimited)
+     * @see minimumValue()
+     * @see maximumValue()
      */
     void uniqueValues( int index, QList<QVariant> &uniqueValues /Out/, int limit = -1 );
 
-    /** Returns minimum value for an attribute column or invalid variant in case of error */
+    /** Returns the minimum value for an attribute column or an invalid variant in case of error.
+     * Note that in some circumstances when unsaved changes are present for the layer then the
+     * returned value may be outdated (for instance when the attribute value in a saved feature has
+     * been changed inside the edit buffer then the previous saved value may be returned as the minimum).
+     * @see maximumValue()
+     * @see uniqueValues()
+     */
     QVariant minimumValue( int index );
 
-    /** Returns maximum value for an attribute column or invalid variant in case of error */
+    /** Returns the maximum value for an attribute column or an invalid variant in case of error.
+     * Note that in some circumstances when unsaved changes are present for the layer then the
+     * returned value may be outdated (for instance when the attribute value in a saved feature has
+     * been changed inside the edit buffer then the previous saved value may be returned as the maximum).
+     * @see minimumValue()
+     * @see uniqueValues()
+     */
     QVariant maximumValue( int index );
 
     /** Fetches all values from a specified field name or expression.
diff --git a/python/plugins/fTools/tools/doPointsInPolygon.py b/python/plugins/fTools/tools/doPointsInPolygon.py
index 84bf373..338e93b 100644
--- a/python/plugins/fTools/tools/doPointsInPolygon.py
+++ b/python/plugins/fTools/tools/doPointsInPolygon.py
@@ -79,13 +79,13 @@ class Dialog(QDialog, Ui_Dialog):
 
             self.attributeList.clear()
             for field in pointFieldList:
-                if field.type() == QVariant.Int or field.type() == QVariant.Double:
-                    if field.type() == QVariant.Int:
-                        global typeInt
-                        item = QListWidgetItem(unicode(field.name()), None, typeInt)
-                    else:
+                if field.type() in [QVariant.Int, QVariant.Double, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]:
+                    if field.type() == QVariant.Double:
                         global typeDouble
                         item = QListWidgetItem(unicode(field.name()), None, typeDouble)
+                    else:
+                        global typeInt
+                        item = QListWidgetItem(unicode(field.name()), None, typeInt)
                     item.setToolTip("Attribute <%s> of type %s" % (field.name(), field.typeName()))
                     self.attributeList.addItem(item)
 
diff --git a/python/plugins/processing/algs/gdal/ogr2ogronesidebuffer.py b/python/plugins/processing/algs/gdal/ogr2ogronesidebuffer.py
index 03e3b61..191855a 100644
--- a/python/plugins/processing/algs/gdal/ogr2ogronesidebuffer.py
+++ b/python/plugins/processing/algs/gdal/ogr2ogronesidebuffer.py
@@ -86,7 +86,7 @@ class Ogr2OgrOneSideBuffer(GdalAlgorithm):
         inLayer = self.getParameterValue(self.INPUT_LAYER)
         ogrLayer = ogrConnectionString(inLayer)[1:-1]
         layername = "'" + ogrLayerName(inLayer) + "'"
-        operation = self.OPERATIONLIST[self.getParameterValue(self.OPERATION)]
+        operation = self.getParameterValue(self.OPERATION)
         geometry = unicode(self.getParameterValue(self.GEOMETRY))
         distance = unicode(self.getParameterValue(self.RADIUS))
         leftright = self.LEFTRIGHTLIST[self.getParameterValue(self.LEFTRIGHT)]
@@ -105,12 +105,12 @@ class Ogr2OgrOneSideBuffer(GdalAlgorithm):
         arguments.append(ogrLayer)
         arguments.append(ogrLayerName(inLayer))
         if dissolveall or field != 'None':
-            if operation == 'Single Side Buffer':
+            if operation == 0:
                 arguments.append('-dialect sqlite -sql "SELECT ST_Union(ST_SingleSidedBuffer(')
             else:
                 arguments.append('-dialect sqlite -sql "SELECT ST_Union(ST_OffsetCurve(')
         else:
-            if operation == 'Single Side Buffer':
+            if operation == 0:
                 arguments.append('-dialect sqlite -sql "SELECT ST_SingleSidedBuffer(')
             else:
                 arguments.append('-dialect sqlite -sql "SELECT ST_OffsetCurve(')
@@ -119,14 +119,26 @@ class Ogr2OgrOneSideBuffer(GdalAlgorithm):
         arguments.append(distance)
         if dissolveall or field != 'None':
             if leftright == 'Left':
-                arguments.append(',0)),*')
+                if operation == 0:
+                    arguments.append(',0)),*')
+                else:
+                    arguments.append(')),*')
             else:
-                arguments.append(',1)),*')
+                if operation == 0:
+                    arguments.append(',1)),*')
+                else:
+                    arguments.append(')),*')
         else:
             if leftright == 'Left':
-                arguments.append(',0),*')
+                if operation == 0:
+                    arguments.append(',0),*')
+                else:
+                    arguments.append('),*')
             else:
-                arguments.append(',1),*')
+                if operation == 0:
+                    arguments.append(',1),*')
+                else:
+                    arguments.append('),*')
         arguments.append('FROM')
         arguments.append(layername)
         if field != 'None':
diff --git a/python/plugins/processing/algs/qgis/AddTableField.py b/python/plugins/processing/algs/qgis/AddTableField.py
index c2d7565..a210036 100644
--- a/python/plugins/processing/algs/qgis/AddTableField.py
+++ b/python/plugins/processing/algs/qgis/AddTableField.py
@@ -78,11 +78,10 @@ class AddTableField(GeoAlgorithm):
         layer = dataobjects.getObjectFromUri(
             self.getParameterValue(self.INPUT_LAYER))
 
-        provider = layer.dataProvider()
-        fields = provider.fields()
+        fields = layer.fields()
         fields.append(QgsField(fieldName, self.TYPES[fieldType], '',
                                fieldLength, fieldPrecision))
-        writer = output.getVectorWriter(fields, provider.geometryType(),
+        writer = output.getVectorWriter(fields, layer.wkbType(),
                                         layer.crs())
         outFeat = QgsFeature()
         features = vector.features(layer)
diff --git a/python/plugins/processing/algs/qgis/AutoincrementalField.py b/python/plugins/processing/algs/qgis/AutoincrementalField.py
index df7db61..161571f 100644
--- a/python/plugins/processing/algs/qgis/AutoincrementalField.py
+++ b/python/plugins/processing/algs/qgis/AutoincrementalField.py
@@ -49,10 +49,9 @@ class AutoincrementalField(GeoAlgorithm):
         output = self.getOutputFromName(self.OUTPUT)
         vlayer = \
             dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
-        vprovider = vlayer.dataProvider()
-        fields = vprovider.fields()
+        fields = vlayer.fields()
         fields.append(QgsField('AUTO', QVariant.Int))
-        writer = output.getVectorWriter(fields, vprovider.geometryType(),
+        writer = output.getVectorWriter(fields, vlayer.wkbType(),
                                         vlayer.crs())
         outFeat = QgsFeature()
         features = vector.features(vlayer)
diff --git a/python/plugins/processing/algs/qgis/Centroids.py b/python/plugins/processing/algs/qgis/Centroids.py
index 4571dd3..9538b8d 100644
--- a/python/plugins/processing/algs/qgis/Centroids.py
+++ b/python/plugins/processing/algs/qgis/Centroids.py
@@ -53,7 +53,7 @@ class Centroids(GeoAlgorithm):
 
         writer = self.getOutputFromName(
             self.OUTPUT_LAYER).getVectorWriter(
-                layer.pendingFields().toList(),
+                layer.fields(),
                 QGis.WKBPoint,
                 layer.crs())
 
diff --git a/python/plugins/processing/algs/qgis/CheckValidity.py b/python/plugins/processing/algs/qgis/CheckValidity.py
index 2c9a93e..c9417f4 100644
--- a/python/plugins/processing/algs/qgis/CheckValidity.py
+++ b/python/plugins/processing/algs/qgis/CheckValidity.py
@@ -89,27 +89,26 @@ class CheckValidity(GeoAlgorithm):
     def doCheck(self, progress):
         layer = dataobjects.getObjectFromUri(
             self.getParameterValue(self.INPUT_LAYER))
-        provider = layer.dataProvider()
 
         settings = QtCore.QSettings()
         method = int(settings.value(settings_method_key, 1))
 
         valid_ouput = self.getOutputFromName(self.VALID_OUTPUT)
-        valid_fields = layer.pendingFields().toList()
+        valid_fields = layer.fields()
         valid_writer = valid_ouput.getVectorWriter(
             valid_fields,
-            provider.geometryType(),
+            layer.wkbType(),
             layer.crs())
         valid_count = 0
 
         invalid_ouput = self.getOutputFromName(self.INVALID_OUTPUT)
-        invalid_fields = layer.pendingFields().toList() + [
+        invalid_fields = layer.fields().toList() + [
             QgsField(name='_errors',
                      type=QtCore.QVariant.String,
                      len=255)]
         invalid_writer = invalid_ouput.getVectorWriter(
             invalid_fields,
-            provider.geometryType(),
+            layer.wkbType(),
             layer.crs())
         invalid_count = 0
 
diff --git a/python/plugins/processing/algs/qgis/ConcaveHull.py b/python/plugins/processing/algs/qgis/ConcaveHull.py
index 5279ac1..36df1eb 100644
--- a/python/plugins/processing/algs/qgis/ConcaveHull.py
+++ b/python/plugins/processing/algs/qgis/ConcaveHull.py
@@ -111,7 +111,7 @@ class ConcaveHull(GeoAlgorithm):
         feat = QgsFeature()
         dissolved_layer.getFeatures(QgsFeatureRequest().setFilterFid(0)).nextFeature(feat)
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            layer.pendingFields().toList(), QGis.WKBPolygon, layer.crs())
+            layer.fields().toList(), QGis.WKBPolygon, layer.crs())
         geom = feat.geometry()
         if no_multigeom and geom.isMultipart():
             # Only singlepart geometries are allowed
diff --git a/python/plugins/processing/algs/qgis/ConvexHull.py b/python/plugins/processing/algs/qgis/ConvexHull.py
index 5ade572..dfa535c 100644
--- a/python/plugins/processing/algs/qgis/ConvexHull.py
+++ b/python/plugins/processing/algs/qgis/ConvexHull.py
@@ -88,7 +88,7 @@ class ConvexHull(GeoAlgorithm):
                   ]
 
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields, QGis.WKBPolygon, layer.dataProvider().crs())
+            fields, QGis.WKBPolygon, layer.crs())
 
         outFeat = QgsFeature()
         inGeom = QgsGeometry()
diff --git a/python/plugins/processing/algs/qgis/DensifyGeometries.py b/python/plugins/processing/algs/qgis/DensifyGeometries.py
index ad70dcf..ca485a5 100644
--- a/python/plugins/processing/algs/qgis/DensifyGeometries.py
+++ b/python/plugins/processing/algs/qgis/DensifyGeometries.py
@@ -108,10 +108,7 @@ class DensifyGeometries(GeoAlgorithm):
 
     def densify(self, polyline, pointsNumber):
         output = []
-        if pointsNumber != 1:
-            multiplier = 1.0 / float(pointsNumber + 1)
-        else:
-            multiplier = 1
+        multiplier = 1.0 / float(pointsNumber + 1)
         for i in xrange(len(polyline) - 1):
             p1 = polyline[i]
             p2 = polyline[i + 1]
diff --git a/python/plugins/processing/algs/qgis/Difference.py b/python/plugins/processing/algs/qgis/Difference.py
index fafd79c..95930d1 100644
--- a/python/plugins/processing/algs/qgis/Difference.py
+++ b/python/plugins/processing/algs/qgis/Difference.py
@@ -64,11 +64,11 @@ class Difference(GeoAlgorithm):
             self.getParameterValue(Difference.OVERLAY))
         ignoreInvalid = self.getParameterValue(Difference.IGNORE_INVALID)
 
-        geomType = layerA.dataProvider().geometryType()
+        geomType = layerA.wkbType()
         writer = self.getOutputFromName(
             Difference.OUTPUT).getVectorWriter(layerA.pendingFields(),
                                                geomType,
-                                               layerA.dataProvider().crs())
+                                               layerA.crs())
 
         outFeat = QgsFeature()
         index = vector.spatialindex(layerB)
diff --git a/python/plugins/processing/algs/qgis/Dissolve.py b/python/plugins/processing/algs/qgis/Dissolve.py
index 80af1fc..d950b91 100644
--- a/python/plugins/processing/algs/qgis/Dissolve.py
+++ b/python/plugins/processing/algs/qgis/Dissolve.py
@@ -64,12 +64,11 @@ class Dissolve(GeoAlgorithm):
         fieldname = self.getParameterValue(Dissolve.FIELD)
         vlayerA = dataobjects.getObjectFromUri(
             self.getParameterValue(Dissolve.INPUT))
-        vproviderA = vlayerA.dataProvider()
         fields = vlayerA.fields()
         writer = self.getOutputFromName(
             Dissolve.OUTPUT).getVectorWriter(fields,
-                                             vproviderA.geometryType(),
-                                             vproviderA.crs())
+                                             vlayerA.wkbType(),
+                                             vlayerA.crs())
         outFeat = QgsFeature()
         features = vector.features(vlayerA)
         total = 100.0 / len(features)
diff --git a/python/plugins/processing/algs/qgis/Eliminate.py b/python/plugins/processing/algs/qgis/Eliminate.py
index 6c596c3..b544085 100644
--- a/python/plugins/processing/algs/qgis/Eliminate.py
+++ b/python/plugins/processing/algs/qgis/Eliminate.py
@@ -98,8 +98,8 @@ class Eliminate(GeoAlgorithm):
             comparison = self.comparisons[self.getParameterValue(self.COMPARISON)]
             comparisonvalue = self.getParameterValue(self.COMPARISONVALUE)
 
-            selectindex = inLayer.dataProvider().fieldNameIndex(attribute)
-            selectType = inLayer.dataProvider().fields()[selectindex].type()
+            selectindex = inLayer.fieldNameIndex(attribute)
+            selectType = inLayer.fields()[selectindex].type()
             selectionError = False
 
             if selectType == 2:
@@ -304,10 +304,9 @@ class Eliminate(GeoAlgorithm):
         # End while
 
         # Create output
-        provider = inLayer.dataProvider()
         output = self.getOutputFromName(self.OUTPUT)
-        writer = output.getVectorWriter(provider.fields(),
-                                        provider.geometryType(), inLayer.crs())
+        writer = output.getVectorWriter(inLayer.fields(),
+                                        inLayer.wkbType(), inLayer.crs())
 
         # Write all features that are left over to output layer
         iterator = inLayer.getFeatures()
diff --git a/python/plugins/processing/algs/qgis/EquivalentNumField.py b/python/plugins/processing/algs/qgis/EquivalentNumField.py
index 357ce4a..6c16b78 100644
--- a/python/plugins/processing/algs/qgis/EquivalentNumField.py
+++ b/python/plugins/processing/algs/qgis/EquivalentNumField.py
@@ -54,11 +54,10 @@ class EquivalentNumField(GeoAlgorithm):
         output = self.getOutputFromName(self.OUTPUT)
         vlayer = dataobjects.getObjectFromUri(
             self.getParameterValue(self.INPUT))
-        vprovider = vlayer.dataProvider()
         fieldindex = vlayer.fieldNameIndex(fieldname)
-        fields = vprovider.fields()
+        fields = vlayer.fields()
         fields.append(QgsField('NUM_FIELD', QVariant.Int))
-        writer = output.getVectorWriter(fields, vprovider.geometryType(),
+        writer = output.getVectorWriter(fields, vlayer.wkbType(),
                                         vlayer.crs())
         outFeat = QgsFeature()
         classes = {}
diff --git a/python/plugins/processing/algs/qgis/Explode.py b/python/plugins/processing/algs/qgis/Explode.py
index a541971..daa35ba 100644
--- a/python/plugins/processing/algs/qgis/Explode.py
+++ b/python/plugins/processing/algs/qgis/Explode.py
@@ -48,8 +48,7 @@ class Explode(GeoAlgorithm):
         vlayer = dataobjects.getObjectFromUri(
             self.getParameterValue(self.INPUT))
         output = self.getOutputFromName(self.OUTPUT)
-        vprovider = vlayer.dataProvider()
-        fields = vprovider.fields()
+        fields = vlayer.fields()
         writer = output.getVectorWriter(fields, QGis.WKBLineString,
                                         vlayer.crs())
         outFeat = QgsFeature()
diff --git a/python/plugins/processing/algs/qgis/ExportGeometryInfo.py b/python/plugins/processing/algs/qgis/ExportGeometryInfo.py
index 1b0f556..19f7ffe 100644
--- a/python/plugins/processing/algs/qgis/ExportGeometryInfo.py
+++ b/python/plugins/processing/algs/qgis/ExportGeometryInfo.py
@@ -79,7 +79,7 @@ class ExportGeometryInfo(GeoAlgorithm):
             fields.append(QgsField(yName, QVariant.Double))
 
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields.toList(), layer.dataProvider().geometryType(), layer.crs())
+            fields.toList(), layer.wkbType(), layer.crs())
 
         ellips = None
         crs = None
diff --git a/python/plugins/processing/algs/qgis/ExtractByLocation.py b/python/plugins/processing/algs/qgis/ExtractByLocation.py
index f255ec0..ac389ca 100644
--- a/python/plugins/processing/algs/qgis/ExtractByLocation.py
+++ b/python/plugins/processing/algs/qgis/ExtractByLocation.py
@@ -71,7 +71,7 @@ class ExtractByLocation(GeoAlgorithm):
 
         output = self.getOutputFromName(self.OUTPUT)
         writer = output.getVectorWriter(layer.pendingFields(),
-                                        layer.dataProvider().geometryType(), layer.crs())
+                                        layer.wkbType(), layer.crs())
 
         if 'disjoint' in predicates:
             disjoinSet = []
diff --git a/python/plugins/processing/algs/qgis/FieldPyculator.py b/python/plugins/processing/algs/qgis/FieldPyculator.py
index 9ce54eb..4eeacbf 100644
--- a/python/plugins/processing/algs/qgis/FieldPyculator.py
+++ b/python/plugins/processing/algs/qgis/FieldPyculator.py
@@ -88,11 +88,10 @@ class FieldsPyculator(GeoAlgorithm):
 
         layer = dataobjects.getObjectFromUri(
             self.getParameterValue(self.INPUT_LAYER))
-        provider = layer.dataProvider()
-        fields = provider.fields()
+        fields = layer.fields()
         fields.append(QgsField(fieldName, self.TYPES[fieldType], '',
                                fieldLength, fieldPrecision))
-        writer = output.getVectorWriter(fields, provider.geometryType(),
+        writer = output.getVectorWriter(fields, layer.wkbType(),
                                         layer.crs())
         outFeat = QgsFeature()
         new_ns = {}
@@ -107,7 +106,7 @@ class FieldsPyculator(GeoAlgorithm):
                     self.tr("FieldPyculator code execute error.Global code block can't be executed!\n%s\n%s" % (unicode(sys.exc_info()[0].__name__), unicode(sys.exc_info()[1]))))
 
         # Replace all fields tags
-        fields = provider.fields()
+        fields = layer.fields()
         num = 0
         for field in fields:
             field_name = unicode(field.name())
diff --git a/python/plugins/processing/algs/qgis/FieldsCalculator.py b/python/plugins/processing/algs/qgis/FieldsCalculator.py
index 95e1fac..987e4d2 100644
--- a/python/plugins/processing/algs/qgis/FieldsCalculator.py
+++ b/python/plugins/processing/algs/qgis/FieldsCalculator.py
@@ -94,12 +94,11 @@ class FieldsCalculator(GeoAlgorithm):
             output.value = system.getTempFilenameInTempFolder(
                 output.name + '.' + ext)
 
-        provider = layer.dataProvider()
-        fields = layer.pendingFields()
+        fields = layer.fields()
         if newField:
             fields.append(QgsField(fieldName, fieldType, '', width, precision))
 
-        writer = output.getVectorWriter(fields, provider.geometryType(),
+        writer = output.getVectorWriter(fields, layer.wkbType(),
                                         layer.crs())
 
         exp = QgsExpression(formula)
diff --git a/python/plugins/processing/algs/qgis/FieldsMapper.py b/python/plugins/processing/algs/qgis/FieldsMapper.py
index 7c8c742..4b50e98 100644
--- a/python/plugins/processing/algs/qgis/FieldsMapper.py
+++ b/python/plugins/processing/algs/qgis/FieldsMapper.py
@@ -66,7 +66,6 @@ class FieldsMapper(GeoAlgorithm):
         output = self.getOutputFromName(self.OUTPUT_LAYER)
 
         layer = dataobjects.getObjectFromUri(layer)
-        provider = layer.dataProvider()
         fields = []
         expressions = []
 
@@ -107,7 +106,7 @@ class FieldsMapper(GeoAlgorithm):
             expressions.append(expression)
 
         writer = output.getVectorWriter(fields,
-                                        provider.geometryType(),
+                                        layer.wkbType(),
                                         layer.crs())
 
         # Create output vector layer with new attributes
diff --git a/python/plugins/processing/algs/qgis/Intersection.py b/python/plugins/processing/algs/qgis/Intersection.py
index b71da9a..dc182e0 100644
--- a/python/plugins/processing/algs/qgis/Intersection.py
+++ b/python/plugins/processing/algs/qgis/Intersection.py
@@ -64,12 +64,11 @@ class Intersection(GeoAlgorithm):
             self.getParameterValue(self.INPUT))
         vlayerB = dataobjects.getObjectFromUri(
             self.getParameterValue(self.INPUT2))
-        vproviderA = vlayerA.dataProvider()
 
-        geomType = vproviderA.geometryType()
+        geomType = vlayerA.wkbType()
         fields = vector.combineVectorFields(vlayerA, vlayerB)
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields,
-                                                                     geomType, vproviderA.crs())
+                                                                     geomType, vlayerA.crs())
         outFeat = QgsFeature()
         index = vector.spatialindex(vlayerB)
         selectionA = vector.features(vlayerA)
diff --git a/python/plugins/processing/algs/qgis/JoinAttributes.py b/python/plugins/processing/algs/qgis/JoinAttributes.py
index 3f5cf13..e7cd418 100644
--- a/python/plugins/processing/algs/qgis/JoinAttributes.py
+++ b/python/plugins/processing/algs/qgis/JoinAttributes.py
@@ -65,14 +65,13 @@ class JoinAttributes(GeoAlgorithm):
         field2 = self.getParameterValue(self.TABLE_FIELD_2)
 
         layer = dataobjects.getObjectFromUri(input)
-        provider = layer.dataProvider()
         joinField1Index = layer.fieldNameIndex(field)
 
         layer2 = dataobjects.getObjectFromUri(input2)
         joinField2Index = layer2.fieldNameIndex(field2)
 
         outFields = vector.combineVectorFields(layer, layer2)
-        writer = output.getVectorWriter(outFields, provider.geometryType(),
+        writer = output.getVectorWriter(outFields, layer.wkbType(),
                                         layer.crs())
 
         # Cache attributes of Layer 2
diff --git a/python/plugins/processing/algs/qgis/Merge.py b/python/plugins/processing/algs/qgis/Merge.py
index 0c9f750..5df01b6 100644
--- a/python/plugins/processing/algs/qgis/Merge.py
+++ b/python/plugins/processing/algs/qgis/Merge.py
@@ -61,14 +61,14 @@ class Merge(GeoAlgorithm):
             layer = QgsVectorLayer(paths[x], unicode(x), 'ogr')
 
             if (len(layers) > 0):
-                if (layer.dataProvider().geometryType() != layers[0].dataProvider().geometryType()):
+                if (layer.wkbType() != layers[0].wkbType()):
                     raise GeoAlgorithmExecutionException(
                         self.tr('All layers must have same geometry type!'))
 
             layers.append(layer)
             totalFeatureCount += layer.featureCount()
 
-            for sindex, sfield in enumerate(layer.dataProvider().fields()):
+            for sindex, sfield in enumerate(layer.fields()):
                 found = None
                 for dfield in fields:
                     if (dfield.name().upper() == sfield.name().upper()):
@@ -83,12 +83,12 @@ class Merge(GeoAlgorithm):
 
         total = 100.0 / totalFeatureCount
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields.toList(), layers[0].dataProvider().geometryType(),
+            fields.toList(), layers[0].wkbType(),
             layers[0].crs())
 
         featureCount = 0
         for layer in layers:
-            for feature in layer.dataProvider().getFeatures():
+            for feature in layer.getFeatures():
                 sattributes = feature.attributes()
                 dattributes = []
                 for dindex, dfield in enumerate(fields):
@@ -99,7 +99,7 @@ class Merge(GeoAlgorithm):
                     else:
                         dattribute = ''
 
-                    for sindex, sfield in enumerate(layer.dataProvider().fields()):
+                    for sindex, sfield in enumerate(layer.fields()):
                         if (sfield.name().upper() == dfield.name().upper()):
                             if (sfield.type() != dfield.type()):
                                 raise GeoAlgorithmExecutionException(
diff --git a/python/plugins/processing/algs/qgis/MultipartToSingleparts.py b/python/plugins/processing/algs/qgis/MultipartToSingleparts.py
index c59b349..4a27fcf 100644
--- a/python/plugins/processing/algs/qgis/MultipartToSingleparts.py
+++ b/python/plugins/processing/algs/qgis/MultipartToSingleparts.py
@@ -53,25 +53,27 @@ class MultipartToSingleparts(GeoAlgorithm):
     def processAlgorithm(self, progress):
         layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
 
-        geomType = self.multiToSingleGeom(layer.dataProvider().geometryType())
+        geomType = self.multiToSingleGeom(layer.wkbType())
 
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
             layer.pendingFields().toList(), geomType, layer.crs())
 
-        outFeat = QgsFeature()
-        inGeom = QgsGeometry()
-
         features = vector.features(layer)
         total = 100.0 / len(features)
         for current, f in enumerate(features):
-            inGeom = f.geometry()
+            outFeat = QgsFeature()
             attrs = f.attributes()
-
-            geometries = self.extractAsSingle(inGeom)
             outFeat.setAttributes(attrs)
 
-            for g in geometries:
-                outFeat.setGeometry(g)
+            if f.constGeometry():
+                inGeom = QgsGeometry(f.constGeometry())
+                geometries = self.extractAsSingle(inGeom)
+
+                for g in geometries:
+                    outFeat.setGeometry(g)
+                    writer.addFeature(outFeat)
+            else:
+                #input feature with null geometry
                 writer.addFeature(outFeat)
 
             progress.setPercentage(int(current * total))
diff --git a/python/plugins/processing/algs/qgis/OrientedMinimumBoundingBox.py b/python/plugins/processing/algs/qgis/OrientedMinimumBoundingBox.py
index b0e9618..339a59d 100644
--- a/python/plugins/processing/algs/qgis/OrientedMinimumBoundingBox.py
+++ b/python/plugins/processing/algs/qgis/OrientedMinimumBoundingBox.py
@@ -82,11 +82,10 @@ class OrientedMinimumBoundingBox(GeoAlgorithm):
 
     def layerOmmb(self, layer, writer, progress):
         current = 0
-        vprovider = layer.dataProvider()
 
-        fit = vprovider.getFeatures()
+        fit = layer.getFeatures()
         inFeat = QgsFeature()
-        total = 100.0 / vprovider.featureCount()
+        total = 100.0 / layer.featureCount()
         newgeometry = QgsGeometry()
         first = True
         while fit.nextFeature(inFeat):
diff --git a/python/plugins/processing/algs/qgis/PointsDisplacement.py b/python/plugins/processing/algs/qgis/PointsDisplacement.py
index bae5822..c61d480 100644
--- a/python/plugins/processing/algs/qgis/PointsDisplacement.py
+++ b/python/plugins/processing/algs/qgis/PointsDisplacement.py
@@ -62,9 +62,8 @@ class PointsDisplacement(GeoAlgorithm):
 
         layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_LAYER))
 
-        provider = layer.dataProvider()
-        writer = output.getVectorWriter(provider.fields(),
-                                        provider.geometryType(), provider.crs())
+        writer = output.getVectorWriter(layer.fields(),
+                                        layer.wkbType(), layer.crs())
 
         features = vector.features(layer)
 
diff --git a/python/plugins/processing/algs/qgis/PointsInPolygon.py b/python/plugins/processing/algs/qgis/PointsInPolygon.py
index df3a969..c88ba92 100644
--- a/python/plugins/processing/algs/qgis/PointsInPolygon.py
+++ b/python/plugins/processing/algs/qgis/PointsInPolygon.py
@@ -58,15 +58,14 @@ class PointsInPolygon(GeoAlgorithm):
         pointLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.POINTS))
         fieldName = self.getParameterValue(self.FIELD)
 
-        polyProvider = polyLayer.dataProvider()
-        fields = polyProvider.fields()
+        fields = polyLayer.fields()
         fields.append(QgsField(fieldName, QVariant.Int))
 
         (idxCount, fieldList) = vector.findOrCreateField(polyLayer,
-                                                         polyLayer.pendingFields(), fieldName)
+                                                         polyLayer.fields(), fieldName)
 
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields.toList(), polyProvider.geometryType(), polyProvider.crs())
+            fields.toList(), polyLayer.wkbType(), polyLayer.crs())
 
         spatialIndex = vector.spatialindex(pointLayer)
 
diff --git a/python/plugins/processing/algs/qgis/PointsInPolygonUnique.py b/python/plugins/processing/algs/qgis/PointsInPolygonUnique.py
index e290369..869e082 100644
--- a/python/plugins/processing/algs/qgis/PointsInPolygonUnique.py
+++ b/python/plugins/processing/algs/qgis/PointsInPolygonUnique.py
@@ -62,8 +62,7 @@ class PointsInPolygonUnique(GeoAlgorithm):
         fieldName = self.getParameterValue(self.FIELD)
         classFieldName = self.getParameterValue(self.CLASSFIELD)
 
-        polyProvider = polyLayer.dataProvider()
-        fields = polyProvider.fields()
+        fields = polyLayer.fields()
         fields.append(QgsField(fieldName, QVariant.Int))
 
         classFieldIndex = pointLayer.fieldNameIndex(classFieldName)
@@ -71,7 +70,7 @@ class PointsInPolygonUnique(GeoAlgorithm):
                                                          polyLayer.pendingFields(), fieldName)
 
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields.toList(), polyProvider.geometryType(), polyProvider.crs())
+            fields.toList(), polyLayer.wkbType(), polyLayer.crs())
 
         spatialIndex = vector.spatialindex(pointLayer)
 
diff --git a/python/plugins/processing/algs/qgis/PointsInPolygonWeighted.py b/python/plugins/processing/algs/qgis/PointsInPolygonWeighted.py
index ab63df6..2ea1142 100644
--- a/python/plugins/processing/algs/qgis/PointsInPolygonWeighted.py
+++ b/python/plugins/processing/algs/qgis/PointsInPolygonWeighted.py
@@ -69,15 +69,14 @@ class PointsInPolygonWeighted(GeoAlgorithm):
         fieldName = self.getParameterValue(self.FIELD)
         fieldIdx = pointLayer.fieldNameIndex(self.getParameterValue(self.WEIGHT))
 
-        polyProvider = polyLayer.dataProvider()
-        fields = polyProvider.fields()
+        fields = polyLayer.fields()
         fields.append(QgsField(fieldName, QVariant.Int))
 
         (idxCount, fieldList) = vector.findOrCreateField(polyLayer,
-                                                         polyLayer.pendingFields(), fieldName)
+                                                         polyLayer.fields(), fieldName)
 
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields.toList(), polyProvider.geometryType(), polyProvider.crs())
+            fields.toList(), polyLayer.wkbType(), polyLayer.crs())
 
         spatialIndex = vector.spatialindex(pointLayer)
 
diff --git a/python/plugins/processing/algs/qgis/PointsLayerFromTable.py b/python/plugins/processing/algs/qgis/PointsLayerFromTable.py
index 32abc69..50a6ea9 100644
--- a/python/plugins/processing/algs/qgis/PointsLayerFromTable.py
+++ b/python/plugins/processing/algs/qgis/PointsLayerFromTable.py
@@ -59,8 +59,7 @@ class PointsLayerFromTable(GeoAlgorithm):
         source = self.getParameterValue(self.INPUT)
         vlayer = dataobjects.getObjectFromUri(source)
         output = self.getOutputFromName(self.OUTPUT)
-        vprovider = vlayer.dataProvider()
-        fields = vprovider.fields()
+        fields = vlayer.fields()
         writer = output.getVectorWriter(fields, QGis.WKBPoint, self.crs)
         xfieldindex = vlayer.fieldNameIndex(self.getParameterValue(self.XFIELD))
         yfieldindex = vlayer.fieldNameIndex(self.getParameterValue(self.YFIELD))
diff --git a/python/plugins/processing/algs/qgis/PointsToPaths.py b/python/plugins/processing/algs/qgis/PointsToPaths.py
index 2a1bac5..995bbc1 100644
--- a/python/plugins/processing/algs/qgis/PointsToPaths.py
+++ b/python/plugins/processing/algs/qgis/PointsToPaths.py
@@ -81,7 +81,7 @@ class PointsToPaths(GeoAlgorithm):
         fields.append(QgsField('begin', QVariant.String, '', 254, 0))
         fields.append(QgsField('end', QVariant.String, '', 254, 0))
         writer = self.getOutputFromName(self.OUTPUT_LINES).getVectorWriter(
-            fields, QGis.WKBLineString, layer.dataProvider().crs())
+            fields, QGis.WKBLineString, layer.crs())
 
         points = dict()
         features = vector.features(layer)
diff --git a/python/plugins/processing/algs/qgis/Polygonize.py b/python/plugins/processing/algs/qgis/Polygonize.py
index 124a3ae..3db2829 100644
--- a/python/plugins/processing/algs/qgis/Polygonize.py
+++ b/python/plugins/processing/algs/qgis/Polygonize.py
@@ -60,9 +60,8 @@ class Polygonize(GeoAlgorithm):
     def processAlgorithm(self, progress):
         vlayer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
         output = self.getOutputFromName(self.OUTPUT)
-        vprovider = vlayer.dataProvider()
         if self.getParameterValue(self.FIELDS):
-            fields = vprovider.fields()
+            fields = vlayer.fields()
         else:
             fields = QgsFields()
         if self.getParameterValue(self.GEOMETRY):
diff --git a/python/plugins/processing/algs/qgis/RandomPointsAlongLines.py b/python/plugins/processing/algs/qgis/RandomPointsAlongLines.py
index 37c4911..31ca327 100644
--- a/python/plugins/processing/algs/qgis/RandomPointsAlongLines.py
+++ b/python/plugins/processing/algs/qgis/RandomPointsAlongLines.py
@@ -68,7 +68,7 @@ class RandomPointsAlongLines(GeoAlgorithm):
         fields = QgsFields()
         fields.append(QgsField('id', QVariant.Int, '', 10, 0))
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields, QGis.WKBPoint, layer.dataProvider().crs())
+            fields, QGis.WKBPoint, layer.crs())
 
         nPoints = 0
         nIterations = 0
diff --git a/python/plugins/processing/algs/qgis/RandomPointsLayer.py b/python/plugins/processing/algs/qgis/RandomPointsLayer.py
index 694a1c0..fe91ed4 100644
--- a/python/plugins/processing/algs/qgis/RandomPointsLayer.py
+++ b/python/plugins/processing/algs/qgis/RandomPointsLayer.py
@@ -70,7 +70,7 @@ class RandomPointsLayer(GeoAlgorithm):
         fields = QgsFields()
         fields.append(QgsField('id', QVariant.Int, '', 10, 0))
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields, QGis.WKBPoint, layer.dataProvider().crs())
+            fields, QGis.WKBPoint, layer.crs())
 
         nPoints = 0
         nIterations = 0
diff --git a/python/plugins/processing/algs/qgis/RandomPointsPolygonsFixed.py b/python/plugins/processing/algs/qgis/RandomPointsPolygonsFixed.py
index e955ccf..2b012ec 100644
--- a/python/plugins/processing/algs/qgis/RandomPointsPolygonsFixed.py
+++ b/python/plugins/processing/algs/qgis/RandomPointsPolygonsFixed.py
@@ -76,7 +76,7 @@ class RandomPointsPolygonsFixed(GeoAlgorithm):
         fields = QgsFields()
         fields.append(QgsField('id', QVariant.Int, '', 10, 0))
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields, QGis.WKBPoint, layer.dataProvider().crs())
+            fields, QGis.WKBPoint, layer.crs())
 
         da = QgsDistanceArea()
 
diff --git a/python/plugins/processing/algs/qgis/RandomPointsPolygonsVariable.py b/python/plugins/processing/algs/qgis/RandomPointsPolygonsVariable.py
index 139b91f..2952a80 100644
--- a/python/plugins/processing/algs/qgis/RandomPointsPolygonsVariable.py
+++ b/python/plugins/processing/algs/qgis/RandomPointsPolygonsVariable.py
@@ -77,7 +77,7 @@ class RandomPointsPolygonsVariable(GeoAlgorithm):
         fields = QgsFields()
         fields.append(QgsField('id', QVariant.Int, '', 10, 0))
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields, QGis.WKBPoint, layer.dataProvider().crs())
+            fields, QGis.WKBPoint, layer.crs())
 
         da = QgsDistanceArea()
 
diff --git a/python/plugins/processing/algs/qgis/ReverseLineDirection.py b/python/plugins/processing/algs/qgis/ReverseLineDirection.py
index d4d9269..00267fc 100644
--- a/python/plugins/processing/algs/qgis/ReverseLineDirection.py
+++ b/python/plugins/processing/algs/qgis/ReverseLineDirection.py
@@ -49,12 +49,11 @@ class ReverseLineDirection(GeoAlgorithm):
     def processAlgorithm(self, progress):
         layer = dataobjects.getObjectFromUri(
             self.getParameterValue(self.INPUT_LAYER))
-        provider = layer.dataProvider()
 
         writer = self.getOutputFromName(
             self.OUTPUT_LAYER).getVectorWriter(
                 layer.fields().toList(),
-                provider.geometryType(),
+                layer.wkbType(),
                 layer.crs())
 
         outFeat = QgsFeature()
diff --git a/python/plugins/processing/algs/qgis/SaveSelectedFeatures.py b/python/plugins/processing/algs/qgis/SaveSelectedFeatures.py
index 756e870..77a8a58 100644
--- a/python/plugins/processing/algs/qgis/SaveSelectedFeatures.py
+++ b/python/plugins/processing/algs/qgis/SaveSelectedFeatures.py
@@ -52,9 +52,8 @@ class SaveSelectedFeatures(GeoAlgorithm):
 
         vectorLayer = dataobjects.getObjectFromUri(inputFilename)
 
-        provider = vectorLayer.dataProvider()
-        writer = output.getVectorWriter(provider.fields(),
-                                        provider.geometryType(), vectorLayer.crs())
+        writer = output.getVectorWriter(vectorLayer.fields(),
+                                        vectorLayer.wkbType(), vectorLayer.crs())
 
         features = vector.features(vectorLayer)
         total = 100.0 / len(features)
diff --git a/python/plugins/processing/algs/qgis/SinglePartsToMultiparts.py b/python/plugins/processing/algs/qgis/SinglePartsToMultiparts.py
index a2c97b4..355b138 100644
--- a/python/plugins/processing/algs/qgis/SinglePartsToMultiparts.py
+++ b/python/plugins/processing/algs/qgis/SinglePartsToMultiparts.py
@@ -54,7 +54,7 @@ class SinglePartsToMultiparts(GeoAlgorithm):
         layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
         fieldName = self.getParameterValue(self.FIELD)
 
-        geomType = self.singleToMultiGeom(layer.dataProvider().geometryType())
+        geomType = self.singleToMultiGeom(layer.wkbType())
 
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
             layer.pendingFields().toList(), geomType, layer.crs())
diff --git a/python/plugins/processing/algs/qgis/Smooth.py b/python/plugins/processing/algs/qgis/Smooth.py
index f82d274..3bf67fd 100644
--- a/python/plugins/processing/algs/qgis/Smooth.py
+++ b/python/plugins/processing/algs/qgis/Smooth.py
@@ -55,14 +55,13 @@ class Smooth(GeoAlgorithm):
     def processAlgorithm(self, progress):
         layer = dataobjects.getObjectFromUri(
             self.getParameterValue(self.INPUT_LAYER))
-        provider = layer.dataProvider()
         iterations = self.getParameterValue(self.ITERATIONS)
         offset = self.getParameterValue(self.OFFSET)
 
         writer = self.getOutputFromName(
             self.OUTPUT_LAYER).getVectorWriter(
                 layer.fields().toList(),
-                provider.geometryType(),
+                layer.wkbType(),
                 layer.crs())
 
         outFeat = QgsFeature()
diff --git a/python/plugins/processing/algs/qgis/SpatialJoin.py b/python/plugins/processing/algs/qgis/SpatialJoin.py
index 6fb5adc..5221c93 100644
--- a/python/plugins/processing/algs/qgis/SpatialJoin.py
+++ b/python/plugins/processing/algs/qgis/SpatialJoin.py
@@ -97,11 +97,8 @@ class SpatialJoin(GeoAlgorithm):
 
         sumList = self.getParameterValue(self.STATS).lower().split(',')
 
-        targetProvider = target.dataProvider()
-        joinProvider = join.dataProvider()
-
-        targetFields = targetProvider.fields()
-        joinFields = joinProvider.fields()
+        targetFields = target.fields()
+        joinFields = join.fields()
 
         fieldList = QgsFields()
 
@@ -130,7 +127,7 @@ class SpatialJoin(GeoAlgorithm):
             fields.append(f)
 
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields, targetProvider.geometryType(), targetProvider.crs())
+            fields, target.wkbType(), target.crs())
 
         outFeat = QgsFeature()
         inFeatB = QgsFeature()
diff --git a/python/plugins/processing/algs/qgis/SumLines.py b/python/plugins/processing/algs/qgis/SumLines.py
index 02a1da0..837c24a 100644
--- a/python/plugins/processing/algs/qgis/SumLines.py
+++ b/python/plugins/processing/algs/qgis/SumLines.py
@@ -62,15 +62,13 @@ class SumLines(GeoAlgorithm):
         lengthFieldName = self.getParameterValue(self.LEN_FIELD)
         countFieldName = self.getParameterValue(self.COUNT_FIELD)
 
-        polyProvider = polyLayer.dataProvider()
-
         (idxLength, fieldList) = vector.findOrCreateField(polyLayer,
-                                                          polyLayer.pendingFields(), lengthFieldName)
+                                                          polyLayer.fields(), lengthFieldName)
         (idxCount, fieldList) = vector.findOrCreateField(polyLayer, fieldList,
                                                          countFieldName)
 
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fieldList.toList(), polyProvider.geometryType(), polyProvider.crs())
+            fieldList.toList(), polyLayer.wkbType(), polyLayer.crs())
 
         spatialIndex = vector.spatialindex(lineLayer)
 
diff --git a/python/plugins/processing/algs/qgis/SymmetricalDifference.py b/python/plugins/processing/algs/qgis/SymmetricalDifference.py
index 5392da2..2318631 100644
--- a/python/plugins/processing/algs/qgis/SymmetricalDifference.py
+++ b/python/plugins/processing/algs/qgis/SymmetricalDifference.py
@@ -56,13 +56,10 @@ class SymmetricalDifference(GeoAlgorithm):
         layerB = dataobjects.getObjectFromUri(
             self.getParameterValue(self.OVERLAY))
 
-        providerA = layerA.dataProvider()
-        providerB = layerB.dataProvider()
-
-        geomType = providerA.geometryType()
+        geomType = layerA.wkbType()
         fields = vector.combineVectorFields(layerA, layerB)
         writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
-            fields, geomType, providerA.crs())
+            fields, geomType, layerA.crs())
 
         featB = QgsFeature()
         outFeat = QgsFeature()
@@ -83,7 +80,7 @@ class SymmetricalDifference(GeoAlgorithm):
             attrs = featA.attributes()
             intersects = indexA.intersects(geom.boundingBox())
             for i in intersects:
-                providerB.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
+                layerB.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
                 tmpGeom = QgsGeometry(featB.geometry())
                 if diffGeom.intersects(tmpGeom):
                     diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
@@ -108,7 +105,7 @@ class SymmetricalDifference(GeoAlgorithm):
             count += 1
             progress.setPercentage(int(count * total))
 
-        length = len(providerA.fields())
+        length = len(layerA.fields())
 
         for featA in featuresB:
             add = True
@@ -118,7 +115,7 @@ class SymmetricalDifference(GeoAlgorithm):
             attrs = [NULL] * length + attrs
             intersects = indexB.intersects(geom.boundingBox())
             for i in intersects:
-                providerA.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
+                layerA.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
                 tmpGeom = QgsGeometry(featB.geometry())
                 if diffGeom.intersects(tmpGeom):
                     diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
diff --git a/python/plugins/processing/algs/qgis/Union.py b/python/plugins/processing/algs/qgis/Union.py
index f64c1ca..a292622 100644
--- a/python/plugins/processing/algs/qgis/Union.py
+++ b/python/plugins/processing/algs/qgis/Union.py
@@ -62,9 +62,7 @@ class Union(GeoAlgorithm):
         vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT))
         vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2))
 
-        vproviderA = vlayerA.dataProvider()
-
-        geomType = vproviderA.geometryType()
+        geomType = vlayerA.wkbType()
         fields = vector.combineVectorFields(vlayerA, vlayerB)
         writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields,
                                                                       geomType, vproviderA.crs())
@@ -165,7 +163,7 @@ class Union(GeoAlgorithm):
                     ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                            self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
 
-        length = len(vproviderA.fields())
+        length = len(vlayerA.fields())
         atMapA = [None] * length
 
         featuresA = vector.features(vlayerB)
diff --git a/python/plugins/processing/algs/qgis/VectorSplit.py b/python/plugins/processing/algs/qgis/VectorSplit.py
index fe43f54..f4ef0f6 100644
--- a/python/plugins/processing/algs/qgis/VectorSplit.py
+++ b/python/plugins/processing/algs/qgis/VectorSplit.py
@@ -64,7 +64,7 @@ class VectorSplit(GeoAlgorithm):
         baseName = os.path.join(directory, '{0}_{1}'.format(layer.name(), fieldName))
 
         fields = layer.pendingFields()
-        crs = layer.dataProvider().crs()
+        crs = layer.crs()
         geomType = layer.wkbType()
 
         total = 100.0 / len(uniqueValues)
diff --git a/python/plugins/processing/algs/qgis/ZonalStatistics.py b/python/plugins/processing/algs/qgis/ZonalStatistics.py
index 4d09e4c..510bae2 100644
--- a/python/plugins/processing/algs/qgis/ZonalStatistics.py
+++ b/python/plugins/processing/algs/qgis/ZonalStatistics.py
@@ -158,7 +158,7 @@ class ZonalStatistics(GeoAlgorithm):
                                                          columnPrefix + 'mode', 21, 6)
 
         writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(
-            fields.toList(), layer.dataProvider().geometryType(), layer.crs())
+            fields.toList(), layer.wkbType(), layer.crs())
 
         outFeat = QgsFeature()
 
diff --git a/python/plugins/processing/gui/AlgorithmDialogBase.py b/python/plugins/processing/gui/AlgorithmDialogBase.py
index 4dd1ad5..69c282d 100644
--- a/python/plugins/processing/gui/AlgorithmDialogBase.py
+++ b/python/plugins/processing/gui/AlgorithmDialogBase.py
@@ -172,6 +172,9 @@ class AlgorithmDialogBase(BASE, WIDGET):
         self.setInfo(text, False)
         QCoreApplication.processEvents()
 
+    def error(self, msg):
+        self.setInfo(msg, error=True)
+
     def setParamValues(self):
         pass
 
diff --git a/python/plugins/processing/gui/SilentProgress.py b/python/plugins/processing/gui/SilentProgress.py
index cff916f..06e5605 100644
--- a/python/plugins/processing/gui/SilentProgress.py
+++ b/python/plugins/processing/gui/SilentProgress.py
@@ -37,16 +37,16 @@ class SilentProgress(object):
     def setPercentage(self, i):
         pass
 
-    def setInfo(self, _):
+    def setInfo(self, msg):
         pass
 
-    def setCommand(self, _):
+    def setCommand(self, msg):
         pass
 
-    def setDebugInfo(self, _):
+    def setDebugInfo(self, msg):
         pass
 
-    def setConsoleInfo(self, _):
+    def setConsoleInfo(self, msg):
         pass
 
     def close(self):
diff --git a/python/testing/__init__.py b/python/testing/__init__.py
index dba5068..f916cd6 100644
--- a/python/testing/__init__.py
+++ b/python/testing/__init__.py
@@ -72,7 +72,10 @@ class TestCase(_TestCase):
         except KeyError:
             precision = 17
 
-        for feats in zip(layer_expected.getFeatures(request), layer_result.getFeatures(request)):
+        expected_features = sorted(layer_expected.getFeatures(request), key=lambda f: f.id())
+        result_features = sorted(layer_expected.getFeatures(request), key=lambda f: f.id())
+
+        for feats in zip(expected_features, result_features):
             if feats[0].geometry() is not None:
                 geom0 = feats[0].geometry().geometry().asWkt(precision)
             else:
diff --git a/src/app/pluginmanager/qgspluginmanager.cpp b/src/app/pluginmanager/qgspluginmanager.cpp
index 3f6eab8..c42c162 100644
--- a/src/app/pluginmanager/qgspluginmanager.cpp
+++ b/src/app/pluginmanager/qgspluginmanager.cpp
@@ -744,7 +744,7 @@ void QgsPluginManager::showPluginDetails( QStandardItem * item )
     {
       iconPath = "file://" + iconPath;
     }
-    html += QString( "<img src=\"%1\" style=\"float:right;\">" ).arg( iconPath );
+    html += QString( "<img src=\"%1\" style=\"float:right;max-width:64px;max-height:64px;\">" ).arg( iconPath );
   }
 
   html += QString( "<h1>%1</h1>" ).arg( metadata->value( "name" ) );
diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp
index cc174fa..581b4d1 100644
--- a/src/app/qgisapp.cpp
+++ b/src/app/qgisapp.cpp
@@ -10739,13 +10739,13 @@ void QgisApp::projectChanged( const QDomDocument &doc )
   if ( !prevProjectDir.isNull() )
   {
     QString prev = prevProjectDir;
-    expr = QString( "sys.path.remove('%1'); " ).arg( prev.replace( '\'', "\\'" ) );
+    expr = QString( "sys.path.remove(u'%1'); " ).arg( prev.replace( '\'', "\\'" ) );
   }
 
   prevProjectDir = fi.canonicalPath();
 
   QString prev = prevProjectDir;
-  expr += QString( "sys.path.append('%1')" ).arg( prev.replace( '\'', "\\'" ) );
+  expr += QString( "sys.path.append(u'%1')" ).arg( prev.replace( '\'', "\\'" ) );
 
   QgsPythonRunner::run( expr );
 }
diff --git a/src/app/qgsdxfexportdialog.cpp b/src/app/qgsdxfexportdialog.cpp
index b425a94..28f4fa7 100644
--- a/src/app/qgsdxfexportdialog.cpp
+++ b/src/app/qgsdxfexportdialog.cpp
@@ -526,11 +526,13 @@ QList< QPair<QgsVectorLayer *, int> > QgsDxfExportDialog::layers() const
 
 double QgsDxfExportDialog::symbologyScale() const
 {
-  double scale = 1 / mScaleWidget->scale();
+  if ( qgsDoubleNear( mScaleWidget->scale(), 0.0 ) )
+    return 1.0;
+
+  double scale = 1.0 / mScaleWidget->scale();
   if ( qgsDoubleNear( scale, 0.0 ) )
-  {
     return 1.0;
-  }
+
   return scale;
 }
 
diff --git a/src/core/pal/feature.cpp b/src/core/pal/feature.cpp
index b2cdcaa..30ae3e2 100644
--- a/src/core/pal/feature.cpp
+++ b/src/core/pal/feature.cpp
@@ -227,7 +227,7 @@ LabelPosition::Quadrant FeaturePart::quadrantFromOffset() const
   }
 }
 
-int FeaturePart::createCandidatesOverPoint( double x, double y, QList< LabelPosition*>& lPos, double angle, PointSet *mapShape )
+int FeaturePart::createCandidatesOverPoint( double x, double y, QList< LabelPosition*>& lPos, double angle )
 {
   int nbp = 1;
 
@@ -294,9 +294,9 @@ int FeaturePart::createCandidatesOverPoint( double x, double y, QList< LabelPosi
   double lx = x + xdiff;
   double ly = y + ydiff;
 
-  if ( mapShape && type == GEOS_POLYGON && mLF->layer()->fitInPolygonOnly() )
+  if ( mLF->permissibleZonePrepared() )
   {
-    if ( !mapShape->containsLabelCandidate( lx, ly, labelW, labelH, angle ) )
+    if ( !GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), lx, ly, labelW, labelH, angle ) )
     {
       return 0;
     }
@@ -419,10 +419,12 @@ int FeaturePart::createCandidatesAtOrderedPositionsOverPoint( double x, double y
     double labelX = referenceX + deltaX;
     double labelY = referenceY + deltaY;
 
-    lPos << new LabelPosition( i, labelX, labelY, labelWidth, labelHeight, angle, cost, this, false, quadrant );
-
-    //TODO - tweak
-    cost += 0.001;
+    if ( ! mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), labelX, labelY, labelWidth, labelHeight, angle ) )
+    {
+      lPos << new LabelPosition( i, labelX, labelY, labelWidth, labelHeight, angle, cost, this, false, quadrant );
+      //TODO - tweak
+      cost += 0.001;
+    }
 
     ++i;
   }
@@ -430,7 +432,7 @@ int FeaturePart::createCandidatesAtOrderedPositionsOverPoint( double x, double y
   return lPos.count();
 }
 
-int FeaturePart::createCandidatesAroundPoint( double x, double y, QList< LabelPosition* >& lPos, double angle, PointSet *mapShape )
+int FeaturePart::createCandidatesAroundPoint( double x, double y, QList< LabelPosition* >& lPos, double angle )
 {
   double labelWidth = getLabelWidth();
   double labelHeight = getLabelHeight();
@@ -547,9 +549,9 @@ int FeaturePart::createCandidatesAroundPoint( double x, double y, QList< LabelPo
       cost = 0.0001 + 0.0020 * double( icost ) / double( numberCandidates - 1 );
 
 
-    if ( mapShape && type == GEOS_POLYGON && mLF->layer()->fitInPolygonOnly() )
+    if ( mLF->permissibleZonePrepared() )
     {
-      if ( !mapShape->containsLabelCandidate( labelX, labelY, labelWidth, labelHeight, angle ) )
+      if ( !GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), labelX, labelY, labelWidth, labelHeight, angle ) )
       {
         continue;
       }
@@ -698,17 +700,17 @@ int FeaturePart::createCandidatesAlongLine( QList< LabelPosition* >& lPos, Point
 
       if ( aboveLine )
       {
-        if ( !mLF->layer()->fitInPolygonOnly() || mapShape->containsLabelCandidate( bx + cos( beta ) *distlabel, by + sin( beta ) *distlabel, xrm, yrm, alpha ) )
+        if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), bx + cos( beta ) *distlabel, by + sin( beta ) *distlabel, xrm, yrm, alpha ) )
           positions.append( new LabelPosition( i, bx + cos( beta ) *distlabel, by + sin( beta ) *distlabel, xrm, yrm, alpha, cost, this, isRightToLeft ) ); // Line
       }
       if ( belowLine )
       {
-        if ( !mLF->layer()->fitInPolygonOnly() || mapShape->containsLabelCandidate( bx - cos( beta ) *( distlabel + yrm ), by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha ) )
+        if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), bx - cos( beta ) *( distlabel + yrm ), by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha ) )
           positions.append( new LabelPosition( i, bx - cos( beta ) *( distlabel + yrm ), by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha, cost, this, isRightToLeft ) );   // Line
       }
       if ( flags & FLAG_ON_LINE )
       {
-        if ( !mLF->layer()->fitInPolygonOnly() || mapShape->containsLabelCandidate( bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha ) )
+        if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha ) )
           positions.append( new LabelPosition( i, bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha, cost, this, isRightToLeft ) ); // Line
       }
     }
@@ -879,6 +881,7 @@ LabelPosition* FeaturePart::curvedPlacementAtOffset( PointSet* path_positions, d
       delete slp;
       return nullptr;
     }
+
     // Shift the character downwards since the draw position is specified at the baseline
     // and we're calculating the mean line here
     double dist = 0.9 * li->label_height / 2;
@@ -1047,14 +1050,36 @@ int FeaturePart::createCurvedCandidatesAlongLine( QList< LabelPosition* >& lPos,
 
       // average angle is calculated with respect to periodicity of angles
       double angle_avg = atan2( sin_avg / li->char_num, cos_avg / li->char_num );
-      // displacement
-      if (( !reversed && ( flags & FLAG_ABOVE_LINE ) ) || ( reversed && ( flags & FLAG_BELOW_LINE ) ) )
-        positions.append( _createCurvedCandidate( slp, angle_avg, mLF->distLabel() + li->label_height / 2 ) );
-      if ( flags & FLAG_ON_LINE )
-        positions.append( _createCurvedCandidate( slp, angle_avg, 0 ) );
-      if (( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) ) )
-        positions.append( _createCurvedCandidate( slp, angle_avg, -li->label_height / 2 - mLF->distLabel() ) );
+      // displacement - we loop through 3 times, generating above, online then below line placements successively
+      for ( int i = 0; i <= 2; ++i )
+      {
+        LabelPosition* p = nullptr;
+        if ( i == 0 && (( !reversed && ( flags & FLAG_ABOVE_LINE ) ) || ( reversed && ( flags & FLAG_BELOW_LINE ) ) ) )
+          p = _createCurvedCandidate( slp, angle_avg, mLF->distLabel() + li->label_height / 2 );
+        if ( i == 1 && flags & FLAG_ON_LINE )
+          p = _createCurvedCandidate( slp, angle_avg, 0 );
+        if ( i == 2 && (( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) ) ) )
+          p = _createCurvedCandidate( slp, angle_avg, -li->label_height / 2 - mLF->distLabel() );
+
+        if ( p && mLF->permissibleZonePrepared() )
+        {
+          bool within = true;
+          LabelPosition* currentPos = p;
+          while ( within && currentPos )
+          {
+            within = GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), currentPos->getX(), currentPos->getY(), currentPos->getWidth(), currentPos->getHeight(), currentPos->getAlpha() );
+            currentPos = currentPos->getNextPart();
+          }
+          if ( !within )
+          {
+            delete p;
+            p = nullptr;
+          }
+        }
 
+        if ( p )
+          positions.append( p );
+      }
       // delete original candidate
       delete slp;
     }
@@ -1144,7 +1169,7 @@ int FeaturePart::createCandidatesForPolygon( QList< LabelPosition*>& lPos, Point
 
     //fit in polygon only mode slows down calculation a lot, so if it's enabled
     //then use a smaller limit for number of iterations
-    int maxTry = mLF->layer()->fitInPolygonOnly() ? 7 : 10;
+    int maxTry = mLF->permissibleZonePrepared() ? 7 : 10;
 
     do
     {
@@ -1158,10 +1183,11 @@ int FeaturePart::createCandidatesForPolygon( QList< LabelPosition*>& lPos, Point
           continue;
         }
 
-        if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Horizontal && mLF->layer()->fitInPolygonOnly() )
+        if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Horizontal && mLF->permissibleZonePrepared() )
         {
           //check width/height of bbox is sufficient for label
-          if ( box->length < labelWidth || box->width < labelHeight )
+          if ( mLF->permissibleZone().boundingBox().width() < labelWidth ||
+               mLF->permissibleZone().boundingBox().height() < labelHeight )
           {
             //no way label can fit in this box, skip it
             continue;
@@ -1249,8 +1275,8 @@ int FeaturePart::createCandidatesForPolygon( QList< LabelPosition*>& lPos, Point
             rx += box->x[0];
             ry += box->y[0];
 
-            bool candidateAcceptable = ( mLF->layer()->fitInPolygonOnly()
-                                         ? mapShape->containsLabelCandidate( rx - dlx, ry - dly, labelWidth, labelHeight, alpha )
+            bool candidateAcceptable = ( mLF->permissibleZonePrepared()
+                                         ? GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), rx - dlx, ry - dly, labelWidth, labelHeight, alpha )
                                          : mapShape->containsPoint( rx, ry ) );
             if ( candidateAcceptable )
             {
@@ -1337,9 +1363,9 @@ int FeaturePart::createCandidates( QList< LabelPosition*>& lPos,
             double cx, cy;
             mapShape->getCentroid( cx, cy, mLF->layer()->centroidInside() );
             if ( mLF->layer()->arrangement() == QgsPalLayerSettings::OverPoint )
-              createCandidatesOverPoint( cx, cy, lPos, angle, mapShape );
+              createCandidatesOverPoint( cx, cy, lPos, angle );
             else
-              createCandidatesAroundPoint( cx, cy, lPos, angle, mapShape );
+              createCandidatesAroundPoint( cx, cy, lPos, angle );
             break;
           case QgsPalLayerSettings::Line:
             createCandidatesAlongLine( lPos, mapShape );
diff --git a/src/core/pal/feature.h b/src/core/pal/feature.h
index 408c13d..01c1956 100644
--- a/src/core/pal/feature.h
+++ b/src/core/pal/feature.h
@@ -131,20 +131,18 @@ namespace pal
        * @param y y coordinate of the point
        * @param lPos pointer to an array of candidates, will be filled by generated candidates
        * @param angle orientation of the label
-       * @param mapShape optional geometry of source polygon
        * @returns the number of generated candidates
        */
-      int createCandidatesAroundPoint( double x, double y, QList<LabelPosition *> &lPos, double angle, PointSet *mapShape = nullptr );
+      int createCandidatesAroundPoint( double x, double y, QList<LabelPosition *> &lPos, double angle );
 
       /** Generate one candidate over or offset the specified point.
        * @param x x coordinate of the point
        * @param y y coordinate of the point
        * @param lPos pointer to an array of candidates, will be filled by generated candidate
        * @param angle orientation of the label
-       * @param mapShape optional geometry of source polygon
        * @returns the number of generated candidates (always 1)
        */
-      int createCandidatesOverPoint( double x, double y, QList<LabelPosition *> &lPos, double angle, PointSet *mapShape = nullptr );
+      int createCandidatesOverPoint( double x, double y, QList<LabelPosition *> &lPos, double angle );
 
       /** Generates candidates following a prioritised list of predefined positions around a point.
        * @param x x coordinate of the point
diff --git a/src/core/pal/geomfunction.cpp b/src/core/pal/geomfunction.cpp
index bdf8c40..623e539 100644
--- a/src/core/pal/geomfunction.cpp
+++ b/src/core/pal/geomfunction.cpp
@@ -31,6 +31,8 @@
 #include "feature.h"
 #include "util.h"
 #include "qgis.h"
+#include "pal.h"
+#include "qgsmessagelog.h"
 
 using namespace pal;
 
@@ -315,6 +317,57 @@ int GeomFunction::reorderPolygon( int nbPoints, double *x, double *y )
   return 0;
 }
 
+bool GeomFunction::containsCandidate( const GEOSPreparedGeometry *geom, double x, double y, double width, double height, double alpha )
+{
+  if ( !geom )
+    return false;
+
+  GEOSContextHandle_t geosctxt = geosContext();
+  GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 5, 2 );
+
+  GEOSCoordSeq_setX_r( geosctxt, coord, 0, x );
+  GEOSCoordSeq_setY_r( geosctxt, coord, 0, y );
+  if ( !qgsDoubleNear( alpha, 0.0 ) )
+  {
+    double beta = alpha + ( M_PI / 2 );
+    double dx1 = cos( alpha ) * width;
+    double dy1 = sin( alpha ) * width;
+    double dx2 = cos( beta ) * height;
+    double dy2 = sin( beta ) * height;
+    GEOSCoordSeq_setX_r( geosctxt, coord, 1, x  + dx1 );
+    GEOSCoordSeq_setY_r( geosctxt, coord, 1, y + dy1 );
+    GEOSCoordSeq_setX_r( geosctxt, coord, 2, x + dx1 + dx2 );
+    GEOSCoordSeq_setY_r( geosctxt, coord, 2, y + dy1 + dy2 );
+    GEOSCoordSeq_setX_r( geosctxt, coord, 3, x + dx2 );
+    GEOSCoordSeq_setY_r( geosctxt, coord, 3, y + dy2 );
+  }
+  else
+  {
+    GEOSCoordSeq_setX_r( geosctxt, coord, 1, x + width );
+    GEOSCoordSeq_setY_r( geosctxt, coord, 1, y );
+    GEOSCoordSeq_setX_r( geosctxt, coord, 2, x + width );
+    GEOSCoordSeq_setY_r( geosctxt, coord, 2, y + height );
+    GEOSCoordSeq_setX_r( geosctxt, coord, 3, x );
+    GEOSCoordSeq_setY_r( geosctxt, coord, 3, y + height );
+  }
+  //close ring
+  GEOSCoordSeq_setX_r( geosctxt, coord, 4, x );
+  GEOSCoordSeq_setY_r( geosctxt, coord, 4, y );
+
+  try
+  {
+    GEOSGeometry* bboxGeos = GEOSGeom_createLinearRing_r( geosctxt, coord );
+    bool result = ( GEOSPreparedContainsProperly_r( geosctxt, geom, bboxGeos ) == 1 );
+    GEOSGeom_destroy_r( geosctxt, bboxGeos );
+    return result;
+  }
+  catch ( GEOSException &e )
+  {
+    QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
+    return false;
+  }
+}
+
 void GeomFunction::findLineCircleIntersection( double cx, double cy, double radius,
     double x1, double y1, double x2, double y2,
     double& xRes, double& yRes )
diff --git a/src/core/pal/geomfunction.h b/src/core/pal/geomfunction.h
index 617a6fc..a76f31b 100644
--- a/src/core/pal/geomfunction.h
+++ b/src/core/pal/geomfunction.h
@@ -31,6 +31,7 @@
 #define PAL_GEOM_FUNCTION
 
 #include "util.h"
+#include "qgsgeos.h"
 
 namespace pal
 {
@@ -98,6 +99,17 @@ namespace pal
       //! Reorder points to have cross prod ((x,y)[i], (x,y)[i+1), point) > 0 when point is outside
       static int reorderPolygon( int nbPoints, double *x, double *y );
 
+      /** Returns true if a GEOS prepared geometry totally contains a label candidate.
+       * @param geom GEOS prepared geometry
+       * @param x candidate x
+       * @param y candidate y
+       * @param width candidate width
+       * @param height candidate height
+       * @param alpha candidate angle
+       * @returns true if candidate is totally contained
+       */
+      static bool containsCandidate( const GEOSPreparedGeometry* geom, double x, double y, double width, double height, double alpha );
+
   };
 } //namespace
 
diff --git a/src/core/pal/layer.cpp b/src/core/pal/layer.cpp
index 604d2d1..e00b438 100644
--- a/src/core/pal/layer.cpp
+++ b/src/core/pal/layer.cpp
@@ -49,7 +49,6 @@ Layer::Layer( QgsAbstractLabelProvider* provider, const QString& name, QgsPalLay
     , mLabelLayer( toLabel )
     , mDisplayAll( displayAll )
     , mCentroidInside( false )
-    , mFitInPolygon( false )
     , mArrangement( arrangement )
     , mArrangementFlags( nullptr )
     , mMode( LabelPerFeature )
@@ -427,6 +426,7 @@ void Layer::chopFeaturesAtRepeatDistance()
     double chopInterval = fpart->repeatDistance();
     if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
     {
+      chopInterval *= ceil( fpart->getLabelWidth() / fpart->repeatDistance() );
 
       double bmin[2], bmax[2];
       fpart->getBoundingBox( bmin, bmax );
diff --git a/src/core/pal/layer.h b/src/core/pal/layer.h
index 1a32b6c..f8346e6 100644
--- a/src/core/pal/layer.h
+++ b/src/core/pal/layer.h
@@ -210,21 +210,6 @@ namespace pal
        */
       bool centroidInside() const { return mCentroidInside; }
 
-      /** Sets whether labels which do not fit completely within a polygon feature
-       * are discarded.
-       * @param fitInPolygon set to true to discard labels which do not fit within
-       * polygon features. Set to false to allow labels which partially fall outside
-       * the polygon.
-       * @see fitInPolygonOnly
-       */
-      void setFitInPolygonOnly( bool fitInPolygon ) { mFitInPolygon = fitInPolygon; }
-
-      /** Returns whether labels which do not fit completely within a polygon feature
-       * are discarded.
-       * @see setFitInPolygonOnly
-       */
-      bool fitInPolygonOnly() const { return mFitInPolygon; }
-
       /** Register a feature in the layer.
        *
        * Does not take ownership of the label feature (it is owned by its provider).
@@ -266,7 +251,6 @@ namespace pal
       bool mLabelLayer;
       bool mDisplayAll;
       bool mCentroidInside;
-      bool mFitInPolygon;
 
       /** Optional flags used for some placement methods */
       QgsPalLayerSettings::Placement mArrangement;
diff --git a/src/core/pal/pointset.cpp b/src/core/pal/pointset.cpp
index 2626c3d..a996d77 100644
--- a/src/core/pal/pointset.cpp
+++ b/src/core/pal/pointset.cpp
@@ -289,50 +289,7 @@ bool PointSet::containsPoint( double x, double y ) const
 
 bool PointSet::containsLabelCandidate( double x, double y, double width, double height, double alpha ) const
 {
-  GEOSContextHandle_t geosctxt = geosContext();
-  GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 5, 2 );
-
-  GEOSCoordSeq_setX_r( geosctxt, coord, 0, x );
-  GEOSCoordSeq_setY_r( geosctxt, coord, 0, y );
-  if ( !qgsDoubleNear( alpha, 0.0 ) )
-  {
-    double beta = alpha + ( M_PI / 2 );
-    double dx1 = cos( alpha ) * width;
-    double dy1 = sin( alpha ) * width;
-    double dx2 = cos( beta ) * height;
-    double dy2 = sin( beta ) * height;
-    GEOSCoordSeq_setX_r( geosctxt, coord, 1, x  + dx1 );
-    GEOSCoordSeq_setY_r( geosctxt, coord, 1, y + dy1 );
-    GEOSCoordSeq_setX_r( geosctxt, coord, 2, x + dx1 + dx2 );
-    GEOSCoordSeq_setY_r( geosctxt, coord, 2, y + dy1 + dy2 );
-    GEOSCoordSeq_setX_r( geosctxt, coord, 3, x + dx2 );
-    GEOSCoordSeq_setY_r( geosctxt, coord, 3, y + dy2 );
-  }
-  else
-  {
-    GEOSCoordSeq_setX_r( geosctxt, coord, 1, x + width );
-    GEOSCoordSeq_setY_r( geosctxt, coord, 1, y );
-    GEOSCoordSeq_setX_r( geosctxt, coord, 2, x + width );
-    GEOSCoordSeq_setY_r( geosctxt, coord, 2, y + height );
-    GEOSCoordSeq_setX_r( geosctxt, coord, 3, x );
-    GEOSCoordSeq_setY_r( geosctxt, coord, 3, y + height );
-  }
-  //close ring
-  GEOSCoordSeq_setX_r( geosctxt, coord, 4, x );
-  GEOSCoordSeq_setY_r( geosctxt, coord, 4, y );
-
-  try
-  {
-    GEOSGeometry* bboxGeos = GEOSGeom_createLinearRing_r( geosctxt, coord );
-    bool result = ( GEOSPreparedContainsProperly_r( geosctxt, preparedGeom(), bboxGeos ) == 1 );
-    GEOSGeom_destroy_r( geosctxt, bboxGeos );
-    return result;
-  }
-  catch ( GEOSException &e )
-  {
-    QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
-    return false;
-  }
+  return GeomFunction::containsCandidate( preparedGeom(), x, y, width, height, alpha );
 }
 
 void PointSet::splitPolygons( QLinkedList<PointSet*> &shapes_toProcess,
diff --git a/src/core/qgsgml.cpp b/src/core/qgsgml.cpp
index f77e313..c225efc 100644
--- a/src/core/qgsgml.cpp
+++ b/src/core/qgsgml.cpp
@@ -103,6 +103,20 @@ int QgsGml::getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangl
   }
   QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );
 
+  if ( !authcfg.isEmpty() )
+  {
+    if ( !QgsAuthManager::instance()->updateNetworkReply( reply, authcfg ) )
+    {
+      reply->deleteLater();
+      QgsMessageLog::logMessage(
+        tr( "GML Getfeature network reply update failed for authcfg %1" ).arg( authcfg ),
+        tr( "Network" ),
+        QgsMessageLog::CRITICAL
+      );
+      return 1;
+    }
+  }
+
   connect( reply, SIGNAL( finished() ), this, SLOT( setFinished() ) );
   connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( handleProgressEvent( qint64, qint64 ) ) );
 
diff --git a/src/core/qgslabelfeature.cpp b/src/core/qgslabelfeature.cpp
index 4ed75b7..d371b31 100644
--- a/src/core/qgslabelfeature.cpp
+++ b/src/core/qgslabelfeature.cpp
@@ -35,6 +35,7 @@ QgsLabelFeature::QgsLabelFeature( QgsFeatureId id, GEOSGeometry* geometry, QSize
     , mIsObstacle( false )
     , mObstacleFactor( 1 )
     , mInfo( nullptr )
+    , mPermissibleZoneGeosPrepared( nullptr )
 {
 }
 
@@ -46,6 +47,9 @@ QgsLabelFeature::~QgsLabelFeature()
   if ( mObstacleGeometry )
     GEOSGeom_destroy_r( QgsGeometry::getGEOSHandler(), mObstacleGeometry );
 
+  if ( mPermissibleZoneGeosPrepared )
+    GEOSPreparedGeom_destroy_r( QgsGeometry::getGEOSHandler(), mPermissibleZoneGeosPrepared );
+
   delete mInfo;
 }
 
@@ -56,3 +60,23 @@ void QgsLabelFeature::setObstacleGeometry( GEOSGeometry* obstacleGeom )
 
   mObstacleGeometry = obstacleGeom;
 }
+
+void QgsLabelFeature::setPermissibleZone( const QgsGeometry &geometry )
+{
+  mPermissibleZone = geometry;
+
+  if ( mPermissibleZoneGeosPrepared )
+  {
+    GEOSPreparedGeom_destroy_r( QgsGeometry::getGEOSHandler(), mPermissibleZoneGeosPrepared );
+    mPermissibleZoneGeosPrepared = nullptr;
+  }
+
+  if ( mPermissibleZone.isEmpty() )
+    return;
+
+  const GEOSGeometry* zoneGeos = mPermissibleZone.asGeos();
+  if ( !zoneGeos )
+    return;
+
+  mPermissibleZoneGeosPrepared = GEOSPrepare_r( QgsGeometry::getGEOSHandler(), zoneGeos );
+}
diff --git a/src/core/qgslabelfeature.h b/src/core/qgslabelfeature.h
index 8c4f30d..02ff838 100644
--- a/src/core/qgslabelfeature.h
+++ b/src/core/qgslabelfeature.h
@@ -107,6 +107,32 @@ class CORE_EXPORT QgsLabelFeature
      */
     GEOSGeometry* obstacleGeometry() const { return mObstacleGeometry; }
 
+    /** Sets the label's permissible zone geometry. If set, the feature's label MUST be fully contained
+     * within this zone, and the feature will not be labeled if no candidates can be generated which
+     * are not contained within the zone.
+     * @param geometry permissible zone geometry. If an invalid QgsGeometry is passed then no zone limit
+     * will be applied to the label candidates (this is the default behaviour).
+     * @note added in QGIS 3.0
+     * @see permissibleZone()
+     */
+    void setPermissibleZone( const QgsGeometry& geometry );
+
+    /** Returns the label's permissible zone geometry. If a valid geometry is returned, the feature's label
+     * MUST be fully contained within this zone, and the feature will not be labeled if no candidates can be
+     * generated which are not contained within the zone.
+     * @note added in QGIS 3.0
+     * @see setPermissibleZone()
+     * @see permissibleZonePrepared()
+     */
+    QgsGeometry permissibleZone() const { return mPermissibleZone; }
+
+    /** Returns a GEOS prepared geometry representing the label's permissibleZone().
+     * @see permissibleZone()
+     * @note added in QGIS 3.0
+     */
+    //TODO - remove when QgsGeometry caches GEOS preparedness
+    const GEOSPreparedGeometry* permissibleZonePrepared() const { return mPermissibleZoneGeosPrepared; }
+
     //! Size of the label (in map units)
     QSizeF size() const { return mSize; }
 
@@ -316,6 +342,8 @@ class CORE_EXPORT QgsLabelFeature
     GEOSGeometry* mGeometry;
     //! Optional geometry to use for label obstacles, if different to mGeometry
     GEOSGeometry* mObstacleGeometry;
+    //! Optional geometry to use for label's permissible zone
+    QgsGeometry mPermissibleZone;
     //! Width and height of the label
     QSizeF mSize;
     //! Visual margin of label contents
@@ -358,6 +386,12 @@ class CORE_EXPORT QgsLabelFeature
     QString mLabelText;
     //! extra information for curved labels (may be null)
     pal::LabelInfo* mInfo;
+
+  private:
+
+    // TODO - not required when QgsGeometry caches geos preparedness
+    const GEOSPreparedGeometry* mPermissibleZoneGeosPrepared;
+
 };
 
 #endif // QGSLABELFEATURE_H
diff --git a/src/core/qgslabelingenginev2.cpp b/src/core/qgslabelingenginev2.cpp
index cfc9881..0539f2f 100644
--- a/src/core/qgslabelingenginev2.cpp
+++ b/src/core/qgslabelingenginev2.cpp
@@ -126,9 +126,6 @@ void QgsLabelingEngineV2::processProvider( QgsAbstractLabelProvider* provider, Q
   // set whether location of centroid must be inside of polygons
   l->setCentroidInside( flags.testFlag( QgsAbstractLabelProvider::CentroidMustBeInside ) );
 
-  // set whether labels must fall completely within the polygon
-  l->setFitInPolygonOnly( flags.testFlag( QgsAbstractLabelProvider::FitInPolygonOnly ) );
-
   // set how to show upside-down labels
   pal::Layer::UpsideDownLabels upsdnlabels;
   switch ( provider->upsidedownLabels() )
diff --git a/src/core/qgslabelingenginev2.h b/src/core/qgslabelingenginev2.h
index 73e6c20..7dda77b 100644
--- a/src/core/qgslabelingenginev2.h
+++ b/src/core/qgslabelingenginev2.h
@@ -57,7 +57,6 @@ class CORE_EXPORT QgsAbstractLabelProvider
       DrawAllLabels           = 1 << 2,  //!< whether all features will be labelled even though overlaps occur
       MergeConnectedLines     = 1 << 3,  //!< whether adjacent lines (with the same label text) should be merged
       CentroidMustBeInside    = 1 << 4,  //!< whether location of centroid must be inside of polygons
-      FitInPolygonOnly        = 1 << 5,  //!< whether labels must fall completely within the polygon
       LabelPerFeaturePart     = 1 << 6,  //!< whether to label each part of multi-part features separately
     };
     Q_DECLARE_FLAGS( Flags, Flag )
diff --git a/src/core/qgsnetworkaccessmanager.cpp b/src/core/qgsnetworkaccessmanager.cpp
index aa9aba8..72f939b 100644
--- a/src/core/qgsnetworkaccessmanager.cpp
+++ b/src/core/qgsnetworkaccessmanager.cpp
@@ -212,7 +212,9 @@ QNetworkReply *QgsNetworkAccessManager::createRequest( QNetworkAccessManager::Op
 
   emit requestCreated( reply );
 
-  // abort request, when network timeout happens
+  // The timer will call abortRequest slot to abort the connection if needed.
+  // The timer is stopped by the finished signal and is restarted on downloadProgress and
+  // uploadProgress.
   QTimer *timer = new QTimer( reply );
   timer->setObjectName( "timeoutTimer" );
   connect( timer, SIGNAL( timeout() ), this, SLOT( abortRequest() ) );
@@ -221,6 +223,8 @@ QNetworkReply *QgsNetworkAccessManager::createRequest( QNetworkAccessManager::Op
 
   connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ), timer, SLOT( start() ) );
   connect( reply, SIGNAL( uploadProgress( qint64, qint64 ) ), timer, SLOT( start() ) );
+  connect( reply, SIGNAL( finished( ) ), timer, SLOT( stop( ) ) );
+  QgsDebugMsgLevel( QString( "Created [reply:%1]" ).arg(( qint64 ) reply, 0, 16 ), 3 );
 
   return reply;
 }
@@ -233,16 +237,15 @@ void QgsNetworkAccessManager::abortRequest()
   QNetworkReply *reply = qobject_cast<QNetworkReply *>( timer->parent() );
   Q_ASSERT( reply );
 
-  QgsDebugMsg( QString( "Abort [reply:%1]" ).arg(( qint64 ) reply, 0, 16 ) );
-
+  reply->abort();
+  QgsDebugMsgLevel( QString( "Abort [reply:%1] %2" ).arg(( qint64 ) reply, 0, 16 ).arg( reply->url().toString() ), 3 );
   QgsMessageLog::logMessage( tr( "Network request %1 timed out" ).arg( reply->url().toString() ), tr( "Network" ) );
-
-  if ( reply->isRunning() )
-    reply->close();
-
+  // Notify the application
   emit requestTimedOut( reply );
+
 }
 
+
 QString QgsNetworkAccessManager::cacheLoadControlName( QNetworkRequest::CacheLoadControl theControl )
 {
   switch ( theControl )
diff --git a/src/core/qgspallabeling.cpp b/src/core/qgspallabeling.cpp
index fb7c994..92df90c 100644
--- a/src/core/qgspallabeling.cpp
+++ b/src/core/qgspallabeling.cpp
@@ -2436,6 +2436,20 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
     doClip = true;
   }
 
+  // if using fitInPolygonOnly option, generate the permissible zone (must happen before geometry is modified - eg
+  // as a result of using perimeter based labeling and the geometry is converted to a boundary)
+  QgsGeometry permissibleZone;
+  if ( geom->type() == QGis::Polygon && fitInPolygonOnly )
+  {
+    permissibleZone = *geom;
+    if ( QgsPalLabeling::geometryRequiresPreparation( &permissibleZone, context, ct, doClip ? extentGeom : nullptr ) )
+    {
+      QgsGeometry* preparedZone = QgsPalLabeling::prepareGeometry( &permissibleZone, context, ct, doClip ? extentGeom : nullptr );
+      permissibleZone = *preparedZone;
+      delete preparedZone;
+    }
+  }
+
   const GEOSGeometry* geos_geom = nullptr;
   const QgsGeometry* preparedGeom = geom;
   QScopedPointer<QgsGeometry> scopedPreparedGeom;
@@ -2834,6 +2848,7 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
   ( *labelFeature )->setAlwaysShow( alwaysShow );
   ( *labelFeature )->setRepeatDistance( repeatDist );
   ( *labelFeature )->setLabelText( labelText );
+  ( *labelFeature )->setPermissibleZone( permissibleZone );
   if ( geosObstacleGeomClone )
   {
     ( *labelFeature )->setObstacleGeometry( geosObstacleGeomClone );
diff --git a/src/core/qgsrulebasedlabeling.cpp b/src/core/qgsrulebasedlabeling.cpp
index 4f89475..5f635ba 100644
--- a/src/core/qgsrulebasedlabeling.cpp
+++ b/src/core/qgsrulebasedlabeling.cpp
@@ -266,8 +266,6 @@ QgsRuleBasedLabeling::Rule::RegisterResult QgsRuleBasedLabeling::Rule::registerF
 
   bool registered = false;
 
-  Q_ASSERT( !mSettings == subProviders.contains( this ) );
-
   // do we have active subprovider for the rule?
   if ( subProviders.contains( this ) && mIsActive )
   {
diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp
index c8d4d71..ec50d7c 100644
--- a/src/core/qgsvectorlayer.cpp
+++ b/src/core/qgsvectorlayer.cpp
@@ -2955,6 +2955,23 @@ void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int
           vals << v.toString();
         }
 
+        QgsFeatureMap added = mEditBuffer->addedFeatures();
+        QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
+        while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
+        {
+          addedIt.next();
+          QVariant v = addedIt.value().attribute( index );
+          if ( v.isValid() )
+          {
+            QString vs = v.toString();
+            if ( !vals.contains( vs ) )
+            {
+              vals << vs;
+              uniqueValues << v;
+            }
+          }
+        }
+
         QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
         while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
         {
@@ -3033,7 +3050,35 @@ QVariant QgsVectorLayer::minimumValue( int index )
       return QVariant();
 
     case QgsFields::OriginProvider: //a provider field
-      return mDataProvider->minimumValue( index );
+    {
+      QVariant min = mDataProvider->minimumValue( index );
+      if ( mEditBuffer )
+      {
+        QgsFeatureMap added = mEditBuffer->addedFeatures();
+        QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
+        while ( addedIt.hasNext() )
+        {
+          addedIt.next();
+          QVariant v = addedIt.value().attribute( index );
+          if ( v.isValid() && qgsVariantLessThan( v, min ) )
+          {
+            min = v;
+          }
+        }
+
+        QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
+        while ( it.hasNext() )
+        {
+          it.next();
+          QVariant v = it.value().value( index );
+          if ( v.isValid() && qgsVariantLessThan( v, min ) )
+          {
+            min = v;
+          }
+        }
+      }
+      return min;
+    }
 
     case QgsFields::OriginEdit:
     {
@@ -3092,7 +3137,35 @@ QVariant QgsVectorLayer::maximumValue( int index )
       return QVariant();
 
     case QgsFields::OriginProvider: //a provider field
-      return mDataProvider->maximumValue( index );
+    {
+      QVariant min = mDataProvider->maximumValue( index );
+      if ( mEditBuffer )
+      {
+        QgsFeatureMap added = mEditBuffer->addedFeatures();
+        QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
+        while ( addedIt.hasNext() )
+        {
+          addedIt.next();
+          QVariant v = addedIt.value().attribute( index );
+          if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
+          {
+            min = v;
+          }
+        }
+
+        QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
+        while ( it.hasNext() )
+        {
+          it.next();
+          QVariant v = it.value().value( index );
+          if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
+          {
+            min = v;
+          }
+        }
+      }
+      return min;
+    }
 
     case QgsFields::OriginEdit:
       // the layer is editable, but in certain cases it can still be avoided going through all features
diff --git a/src/core/qgsvectorlayer.h b/src/core/qgsvectorlayer.h
index 59f1718..4f54ddf 100644
--- a/src/core/qgsvectorlayer.h
+++ b/src/core/qgsvectorlayer.h
@@ -1590,17 +1590,35 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
     /** Caches joined attributes if required (and not already done) */
     void createJoinCaches();
 
-    /** Returns unique values for column
+    /** Calculates a list of unique values contained within an attribute in the layer. Note that
+     * in some circumstances when unsaved changes are present for the layer then the returned list
+     * may contain outdated values (for instance when the attribute value in a saved feature has
+     * been changed inside the edit buffer then the previous saved value will be included in the
+     * returned list).
      * @param index column index for attribute
      * @param uniqueValues out: result list
-     * @param limit maximum number of values to return (-1 if unlimited)
+     * @param limit maximum number of values to return (or -1 if unlimited)
+     * @see minimumValue()
+     * @see maximumValue()
      */
     void uniqueValues( int index, QList<QVariant> &uniqueValues, int limit = -1 );
 
-    /** Returns minimum value for an attribute column or invalid variant in case of error */
+    /** Returns the minimum value for an attribute column or an invalid variant in case of error.
+     * Note that in some circumstances when unsaved changes are present for the layer then the
+     * returned value may be outdated (for instance when the attribute value in a saved feature has
+     * been changed inside the edit buffer then the previous saved value may be returned as the minimum).
+     * @see maximumValue()
+     * @see uniqueValues()
+     */
     QVariant minimumValue( int index );
 
-    /** Returns maximum value for an attribute column or invalid variant in case of error */
+    /** Returns the maximum value for an attribute column or an invalid variant in case of error.
+     * Note that in some circumstances when unsaved changes are present for the layer then the
+     * returned value may be outdated (for instance when the attribute value in a saved feature has
+     * been changed inside the edit buffer then the previous saved value may be returned as the maximum).
+     * @see minimumValue()
+     * @see uniqueValues()
+     */
     QVariant maximumValue( int index );
 
     /** Fetches all values from a specified field name or expression.
diff --git a/src/core/qgsvectorlayerlabelprovider.cpp b/src/core/qgsvectorlayerlabelprovider.cpp
index 9780a60..ccdece2 100644
--- a/src/core/qgsvectorlayerlabelprovider.cpp
+++ b/src/core/qgsvectorlayerlabelprovider.cpp
@@ -101,7 +101,6 @@ void QgsVectorLayerLabelProvider::init()
   if ( mSettings.displayAll ) mFlags |= DrawAllLabels;
   if ( mSettings.mergeLines ) mFlags |= MergeConnectedLines;
   if ( mSettings.centroidInside ) mFlags |= CentroidMustBeInside;
-  if ( mSettings.fitInPolygonOnly ) mFlags |= FitInPolygonOnly;
   if ( mSettings.labelPerPart ) mFlags |= LabelPerFeaturePart;
   mPriority = 1 - mSettings.priority / 10.0; // convert 0..10 --> 1..0
 
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 2a3f283..151da0e 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -640,6 +640,25 @@ IF (WITH_TOUCH)
 ENDIF (WITH_TOUCH)
 
 SET(QGIS_GUI_UI_HDRS
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthauthoritieseditor.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthcertificateinfo.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthcertificatemanager.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthconfigedit.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthconfigeditor.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthconfigidedit.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthconfigselect.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthconfiguriedit.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsautheditorwidgets.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthidentitieseditor.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthimportcertdialog.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthimportidentitydialog.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthmethodplugins.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthserverseditor.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthsslconfigwidget.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthsslerrorsdialog.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthsslimportdialog.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthsslimporterrors.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthtrustedcasdialog.h
   ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgscredentialdialog.h
   ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsdetaileditemwidgetbase.h
   ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsexpressionbuilderdialogbase.h
diff --git a/src/gui/attributetable/qgsfeaturelistview.cpp b/src/gui/attributetable/qgsfeaturelistview.cpp
index 1bc73a4..38c0c0e 100644
--- a/src/gui/attributetable/qgsfeaturelistview.cpp
+++ b/src/gui/attributetable/qgsfeaturelistview.cpp
@@ -257,7 +257,8 @@ void QgsFeatureListView::mouseReleaseEvent( QMouseEvent *event )
   }
   else
   {
-    mFeatureSelectionModel->enableSync( true );
+    if ( mFeatureSelectionModel )
+      mFeatureSelectionModel->enableSync( true );
   }
 }
 
diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp
index 426c117..6b37691 100644
--- a/src/providers/ogr/qgsogrfeatureiterator.cpp
+++ b/src/providers/ogr/qgsogrfeatureiterator.cpp
@@ -43,6 +43,8 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrFeatureSource* source, bool
     , mFetchGeometry( false )
     , mGeometrySimplifier( nullptr )
     , mExpressionCompiled( false )
+    , mFilterFids( mRequest.filterFids() )
+    , mFilterFidsIt( mFilterFids.constBegin() )
 {
   mConn = QgsOgrConnPool::instance()->acquireConnection( mSource->mProvider->dataSourceUri() );
   if ( !mConn->ds )
@@ -213,6 +215,22 @@ bool QgsOgrFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType m
   return false;
 }
 
+bool QgsOgrFeatureIterator::fetchFeatureWithId( QgsFeatureId id, QgsFeature& feature ) const
+{
+  feature.setValid( false );
+  OGRFeatureH fet = OGR_L_GetFeature( ogrLayer, FID_TO_NUMBER( id ) );
+  if ( !fet )
+  {
+    return false;
+  }
+
+  if ( readFeature( fet, feature ) )
+    OGR_F_Destroy( fet );
+
+  feature.setValid( true );
+  return true;
+}
+
 bool QgsOgrFeatureIterator::fetchFeature( QgsFeature& feature )
 {
   feature.setValid( false );
@@ -222,19 +240,22 @@ bool QgsOgrFeatureIterator::fetchFeature( QgsFeature& feature )
 
   if ( mRequest.filterType() == QgsFeatureRequest::FilterFid )
   {
-    OGRFeatureH fet = OGR_L_GetFeature( ogrLayer, FID_TO_NUMBER( mRequest.filterFid() ) );
-    if ( !fet )
+    bool result = fetchFeatureWithId( mRequest.filterFid(), feature );
+    close(); // the feature has been read or was not found: we have finished here
+    return result;
+  }
+  else if ( mRequest.filterType() == QgsFeatureRequest::FilterFids )
+  {
+    while ( mFilterFidsIt != mFilterFids.constEnd() )
     {
-      close();
-      return false;
-    }
-
-    if ( readFeature( fet, feature ) )
-      OGR_F_Destroy( fet );
+      QgsFeatureId nextId = *mFilterFidsIt;
+      mFilterFidsIt++;
 
-    feature.setValid( true );
-    close(); // the feature has been read: we have finished here
-    return true;
+      if ( fetchFeatureWithId( nextId, feature ) )
+        return true;
+    }
+    close();
+    return false;
   }
 
   OGRFeatureH fet;
@@ -267,6 +288,8 @@ bool QgsOgrFeatureIterator::rewind()
 
   OGR_L_ResetReading( ogrLayer );
 
+  mFilterFidsIt = mFilterFids.constBegin();
+
   return true;
 }
 
@@ -293,7 +316,7 @@ bool QgsOgrFeatureIterator::close()
 }
 
 
-void QgsOgrFeatureIterator::getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex )
+void QgsOgrFeatureIterator::getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex ) const
 {
   OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attindex );
 
@@ -351,7 +374,7 @@ void QgsOgrFeatureIterator::getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature
 }
 
 
-bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )
+bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) const
 {
   feature.setFeatureId( OGR_F_GetFID( fet ) );
   feature.initAttributes( mSource->mFields.count() );
diff --git a/src/providers/ogr/qgsogrfeatureiterator.h b/src/providers/ogr/qgsogrfeatureiterator.h
index 57b2a82..9bc0814 100644
--- a/src/providers/ogr/qgsogrfeatureiterator.h
+++ b/src/providers/ogr/qgsogrfeatureiterator.h
@@ -70,10 +70,10 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsOgr
     //! fetch next feature filter expression
     bool nextFeatureFilterExpression( QgsFeature& f ) override;
 
-    bool readFeature( OGRFeatureH fet, QgsFeature& feature );
+    bool readFeature( OGRFeatureH fet, QgsFeature& feature ) const;
 
     //! Get an attribute associated with a feature
-    void getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex );
+    void getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex ) const;
 
     bool mFeatureFetched;
 
@@ -90,6 +90,10 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsOgr
     QgsOgrAbstractGeometrySimplifier* mGeometrySimplifier;
 
     bool mExpressionCompiled;
+    QgsFeatureIds mFilterFids;
+    QgsFeatureIds::const_iterator mFilterFidsIt;
+
+    bool fetchFeatureWithId( QgsFeatureId id, QgsFeature& feature ) const;
 
     //! returns whether the iterator supports simplify geometries on provider side
     virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const override;
diff --git a/src/providers/spatialite/qgsspatialiteprovider.cpp b/src/providers/spatialite/qgsspatialiteprovider.cpp
index 5156225..63468b3 100644
--- a/src/providers/spatialite/qgsspatialiteprovider.cpp
+++ b/src/providers/spatialite/qgsspatialiteprovider.cpp
@@ -5330,7 +5330,7 @@ QGISEXTERN bool saveStyle( const QString& uri, const QString& qmlStyle, const QS
                          ") VALUES ("
                          "%1,%2,%3,%4,%5,%6,%7,%8,%9,%10%12"
                          ")" )
-                .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.database() ) )
+                .arg( QgsSpatiaLiteProvider::quotedValue( QString() ) )
                 .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.schema() ) )
                 .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
                 .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) )
@@ -5345,12 +5345,10 @@ QGISEXTERN bool saveStyle( const QString& uri, const QString& qmlStyle, const QS
 
   QString checkQuery = QString( "SELECT styleName"
                                 " FROM layer_styles"
-                                " WHERE f_table_catalog=%1"
-                                " AND f_table_schema=%2"
-                                " AND f_table_name=%3"
-                                " AND f_geometry_column=%4"
-                                " AND styleName=%5" )
-                       .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.database() ) )
+                                " WHERE f_table_schema=%1"
+                                " AND f_table_name=%2"
+                                " AND f_geometry_column=%3"
+                                " AND styleName=%4" )
                        .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.schema() ) )
                        .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
                        .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) )
@@ -5384,17 +5382,15 @@ QGISEXTERN bool saveStyle( const QString& uri, const QString& qmlStyle, const QS
                    ",styleSLD=%3"
                    ",description=%4"
                    ",owner=%5"
-                   " WHERE f_table_catalog=%6"
-                   " AND f_table_schema=%7"
-                   " AND f_table_name=%8"
-                   " AND f_geometry_column=%9"
-                   " AND styleName=%10" )
+                   " WHERE f_table_schema=%6"
+                   " AND f_table_name=%7"
+                   " AND f_geometry_column=%8"
+                   " AND styleName=%9" )
           .arg( useAsDefault ? "1" : "0" )
           .arg( QgsSpatiaLiteProvider::quotedValue( qmlStyle ) )
           .arg( QgsSpatiaLiteProvider::quotedValue( sldStyle ) )
           .arg( QgsSpatiaLiteProvider::quotedValue( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ) )
           .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.username() ) )
-          .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.database() ) )
           .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.schema() ) )
           .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
           .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) )
@@ -5405,11 +5401,9 @@ QGISEXTERN bool saveStyle( const QString& uri, const QString& qmlStyle, const QS
   {
     QString removeDefaultSql = QString( "UPDATE layer_styles"
                                         " SET useAsDefault=0"
-                                        " WHERE f_table_catalog=%1"
-                                        " AND f_table_schema=%2"
-                                        " AND f_table_name=%3"
-                                        " AND f_geometry_column=%4" )
-                               .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.database() ) )
+                                        " WHERE f_table_schema=%1"
+                                        " AND f_table_name=%2"
+                                        " AND f_geometry_column=%3" )
                                .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.schema() ) )
                                .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
                                .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) );
@@ -5460,13 +5454,11 @@ QGISEXTERN QString loadStyle( const QString& uri, QString& errCause )
 
   QString selectQmlQuery = QString( "SELECT styleQML"
                                     " FROM layer_styles"
-                                    " WHERE f_table_catalog=%1"
-                                    " AND f_table_schema=%2"
-                                    " AND f_table_name=%3"
-                                    " AND f_geometry_column=%4"
+                                    " WHERE f_table_schema=%1"
+                                    " AND f_table_name=%2"
+                                    " AND f_geometry_column=%3"
                                     " ORDER BY CASE WHEN useAsDefault THEN 1 ELSE 2 END"
                                     ",update_time DESC LIMIT 1" )
-                           .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.database() ) )
                            .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.schema() ) )
                            .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
                            .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) );
@@ -5543,11 +5535,9 @@ QGISEXTERN int listStyles( const QString &uri, QStringList &ids, QStringList &na
   // get them
   QString selectRelatedQuery = QString( "SELECT id,styleName,description"
                                         " FROM layer_styles"
-                                        " WHERE f_table_catalog=%1"
-                                        " AND f_table_schema=%2"
-                                        " AND f_table_name=%3"
-                                        " AND f_geometry_column=%4" )
-                               .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.database() ) )
+                                        " WHERE f_table_schema=%1"
+                                        " AND f_table_name=%2"
+                                        " AND f_geometry_column=%3" )
                                .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.schema() ) )
                                .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
                                .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) );
@@ -5572,9 +5562,8 @@ QGISEXTERN int listStyles( const QString &uri, QStringList &ids, QStringList &na
 
   QString selectOthersQuery = QString( "SELECT id,styleName,description"
                                        " FROM layer_styles"
-                                       " WHERE NOT (f_table_catalog=%1 AND f_table_schema=%2 AND f_table_name=%3 AND f_geometry_column=%4)"
+                                       " WHERE NOT (f_table_schema=%1 AND f_table_name=%2 AND f_geometry_column=%3)"
                                        " ORDER BY update_time DESC" )
-                              .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.database() ) )
                               .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.schema() ) )
                               .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
                               .arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) );
diff --git a/src/providers/wcs/qgswcscapabilities.cpp b/src/providers/wcs/qgswcscapabilities.cpp
index f98af95..111a6e9 100644
--- a/src/providers/wcs/qgswcscapabilities.cpp
+++ b/src/providers/wcs/qgswcscapabilities.cpp
@@ -157,6 +157,14 @@ bool QgsWcsCapabilities::sendRequest( QString const & url )
 
   QgsDebugMsg( QString( "getcapabilities: %1" ).arg( url ) );
   mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+  if ( !setAuthorizationReply( mCapabilitiesReply ) )
+  {
+    mCapabilitiesReply->deleteLater();
+    mCapabilitiesReply = nullptr;
+    mError = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+    QgsMessageLog::logMessage( mError, tr( "WCS" ) );
+    return false;
+  }
 
   connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
   connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
@@ -368,6 +376,15 @@ void QgsWcsCapabilities::capabilitiesReplyFinished()
       mCapabilitiesReply->deleteLater();
       QgsDebugMsg( QString( "redirected getcapabilities: %1" ).arg( redirect.toString() ) );
       mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+      if ( !setAuthorizationReply( mCapabilitiesReply ) )
+      {
+        mCapabilitiesResponse.clear();
+        mCapabilitiesReply->deleteLater();
+        mCapabilitiesReply = nullptr;
+        mError = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+        QgsMessageLog::logMessage( mError, tr( "WCS" ) );
+        return;
+      }
 
       connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
       connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
@@ -394,6 +411,15 @@ void QgsWcsCapabilities::capabilitiesReplyFinished()
       mCapabilitiesReply->deleteLater();
 
       mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+      if ( !setAuthorizationReply( mCapabilitiesReply ) )
+      {
+        mCapabilitiesResponse.clear();
+        mCapabilitiesReply->deleteLater();
+        mCapabilitiesReply = nullptr;
+        mError = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+        QgsMessageLog::logMessage( mError, tr( "WCS" ) );
+        return;
+      }
       connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
       connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
       return;
@@ -1181,6 +1207,15 @@ bool QgsWcsCapabilities::setAuthorization( QNetworkRequest &request ) const
   return true;
 }
 
+bool QgsWcsCapabilities::setAuthorizationReply( QNetworkReply *reply ) const
+{
+  if ( mUri.hasParam( "authcfg" ) && !mUri.param( "authcfg" ).isEmpty() )
+  {
+    return QgsAuthManager::instance()->updateNetworkReply( reply, mUri.param( "authcfg" ) );
+  }
+  return true;
+}
+
 void QgsWcsCapabilities::showMessageBox( const QString& title, const QString& text )
 {
   QgsMessageOutput *message = QgsMessageOutput::createMessageOutput();
diff --git a/src/providers/wcs/qgswcscapabilities.h b/src/providers/wcs/qgswcscapabilities.h
index c13687e..fee4025 100644
--- a/src/providers/wcs/qgswcscapabilities.h
+++ b/src/providers/wcs/qgswcscapabilities.h
@@ -155,6 +155,9 @@ class QgsWcsCapabilities : public QObject
     //! set authorization header
     bool setAuthorization( QNetworkRequest &request ) const;
 
+    //! set authorization reply
+    bool setAuthorizationReply( QNetworkReply * reply ) const;
+
     QString version() const { return mCapabilities.version; }
 
     /**
diff --git a/src/providers/wcs/qgswcsprovider.cpp b/src/providers/wcs/qgswcsprovider.cpp
index 9c78f81..7f79733 100644
--- a/src/providers/wcs/qgswcsprovider.cpp
+++ b/src/providers/wcs/qgswcsprovider.cpp
@@ -1684,6 +1684,15 @@ QgsWcsDownloadHandler::QgsWcsDownloadHandler( const QUrl& url, QgsWcsAuthorizati
   request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, cacheLoadControl );
 
   mCacheReply = QgsNetworkAccessManager::instance()->get( request );
+  if ( !mAuth.setAuthorizationReply( mCacheReply ) )
+  {
+    mCacheReply->deleteLater();
+    mCacheReply = nullptr;
+    QgsMessageLog::logMessage( tr( "Network reply update failed for authentication config" ),
+                               tr( "WCS" ) );
+    finish();
+    return;
+  }
   connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ) );
   connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ) );
 }
@@ -1719,6 +1728,15 @@ void QgsWcsDownloadHandler::cacheReplyFinished()
         return;
       }
       mCacheReply = QgsNetworkAccessManager::instance()->get( request );
+      if ( !mAuth.setAuthorizationReply( mCacheReply ) )
+      {
+        mCacheReply->deleteLater();
+        mCacheReply = nullptr;
+        QgsMessageLog::logMessage( tr( "Network reply update failed for authentication config" ),
+                                   tr( "WCS" ) );
+        finish();
+        return;
+      }
       connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ) );
       connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ) );
 
@@ -1883,6 +1901,15 @@ void QgsWcsDownloadHandler::cacheReplyFinished()
       mCacheReply->deleteLater();
 
       mCacheReply = QgsNetworkAccessManager::instance()->get( request );
+      if ( !mAuth.setAuthorizationReply( mCacheReply ) )
+      {
+        mCacheReply->deleteLater();
+        mCacheReply = nullptr;
+        QgsMessageLog::logMessage( tr( "Network reply update failed for authentication config" ),
+                                   tr( "WCS" ) );
+        finish();
+        return;
+      }
       connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ), Qt::DirectConnection );
       connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );
 
diff --git a/src/providers/wcs/qgswcsprovider.h b/src/providers/wcs/qgswcsprovider.h
index 8d84cbd..b866d3f 100644
--- a/src/providers/wcs/qgswcsprovider.h
+++ b/src/providers/wcs/qgswcsprovider.h
@@ -71,6 +71,16 @@ struct QgsWcsAuthorization
     return true;
   }
 
+  //! set authorization reply
+  bool setAuthorizationReply( QNetworkReply * reply ) const
+  {
+    if ( !mAuthCfg.isEmpty() )
+    {
+      return QgsAuthManager::instance()->updateNetworkReply( reply, mAuthCfg );
+    }
+    return true;
+  }
+
   //! Username for basic http authentication
   QString mUserName;
 
diff --git a/src/providers/wfs/qgswfscapabilities.cpp b/src/providers/wfs/qgswfscapabilities.cpp
index a3a248f..adbabe9 100644
--- a/src/providers/wfs/qgswfscapabilities.cpp
+++ b/src/providers/wfs/qgswfscapabilities.cpp
@@ -165,6 +165,15 @@ bool QgsWFSCapabilities::setAuthorization( QNetworkRequest &request ) const
   return true;
 }
 
+bool QgsWFSCapabilities::setAuthorizationReply( QNetworkReply *reply ) const
+{
+  if ( mUri.hasParam( "authcfg" ) && !mUri.param( "authcfg" ).isEmpty() )
+  {
+    return QgsAuthManager::instance()->updateNetworkReply( reply, mUri.param( "authcfg" ) );
+  }
+  return true;
+}
+
 void QgsWFSCapabilities::requestCapabilities()
 {
   mErrorCode = QgsWFSCapabilities::NoError;
@@ -182,6 +191,17 @@ void QgsWFSCapabilities::requestCapabilities()
 
   request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
   mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+  if ( !setAuthorizationReply( mCapabilitiesReply ) )
+  {
+    mCapabilitiesReply->deleteLater();
+    mCapabilitiesReply = nullptr;
+    mErrorCode = QgsWFSCapabilities::NetworkError;
+    mErrorMessage = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+    QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
+    emit gotCapabilities();
+    return;
+  }
+
   connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
 }
 
@@ -220,6 +240,17 @@ void QgsWFSCapabilities::capabilitiesReplyFinished()
     request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
 
     mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+    if ( !setAuthorizationReply( mCapabilitiesReply ) )
+    {
+      mCaps.clear();
+      mCapabilitiesReply->deleteLater();
+      mCapabilitiesReply = nullptr;
+      mErrorCode = QgsWFSCapabilities::NetworkError;
+      mErrorMessage = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+      QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
+      emit gotCapabilities();
+      return;
+    }
 
     connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
     return;
diff --git a/src/providers/wfs/qgswfscapabilities.h b/src/providers/wfs/qgswfscapabilities.h
index 0632d81..09a612c 100644
--- a/src/providers/wfs/qgswfscapabilities.h
+++ b/src/providers/wfs/qgswfscapabilities.h
@@ -76,6 +76,9 @@ class QgsWFSCapabilities : public QObject
     //! set authorization header
     bool setAuthorization( QNetworkRequest &request ) const;
 
+    //! set authorization reply
+    bool setAuthorizationReply( QNetworkReply * reply ) const;
+
   signals:
     void gotCapabilities();
 
diff --git a/src/providers/wfs/qgswfsprovider.cpp b/src/providers/wfs/qgswfsprovider.cpp
index 33f3c92..c1e842c 100644
--- a/src/providers/wfs/qgswfsprovider.cpp
+++ b/src/providers/wfs/qgswfsprovider.cpp
@@ -743,6 +743,13 @@ int QgsWFSProvider::describeFeatureTypeGET( const QString& uri, QString& geometr
     return 1;
   }
   QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );
+  if ( !mAuth.setAuthorizationReply( reply ) )
+  {
+    reply->deleteLater();
+    QgsMessageLog::logMessage( tr( "Network reply update failed for authentication config" ),
+                               tr( "WFS" ) );
+    return 1;
+  }
 
   connect( reply, SIGNAL( finished() ), this, SLOT( networkRequestFinished() ) );
   while ( !mNetworkRequestFinished )
@@ -1341,6 +1348,14 @@ bool QgsWFSProvider::sendTransactionDocument( const QDomDocument& doc, QDomDocum
 
   request.setHeader( QNetworkRequest::ContentTypeHeader, "text/xml" );
   QNetworkReply* reply = QgsNetworkAccessManager::instance()->post( request, doc.toByteArray( -1 ) );
+  if ( !mAuth.setAuthorizationReply( reply ) )
+  {
+    reply->deleteLater();
+    QgsMessageLog::logMessage( tr( "Network reply update failed for authentication config" ),
+                               tr( "WFS" ) );
+    return false;
+  }
+  
   QgsDebugMsg( "WFS transaction: " + doc.toByteArray( ) );
 
   connect( reply, SIGNAL( finished() ), this, SLOT( networkRequestFinished() ) );
@@ -1479,6 +1494,14 @@ void QgsWFSProvider::getLayerCapabilities()
     return;
   }
   QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );
+  if ( !mAuth.setAuthorizationReply( reply ) )
+  {
+    reply->deleteLater();
+    mCapabilities = 0;
+    QgsMessageLog::logMessage( tr( "Network reply update failed for authentication config" ),
+                               tr( "WFS" ) );
+    return;
+  }
 
   connect( reply, SIGNAL( finished() ), this, SLOT( networkRequestFinished() ) );
   while ( !mNetworkRequestFinished )
diff --git a/src/providers/wfs/qgswfsprovider.h b/src/providers/wfs/qgswfsprovider.h
index 9cda437..ca1353d 100644
--- a/src/providers/wfs/qgswfsprovider.h
+++ b/src/providers/wfs/qgswfsprovider.h
@@ -56,6 +56,16 @@ struct QgsWFSAuthorization
     return true;
   }
 
+  //! set authorization reply
+  bool setAuthorizationReply( QNetworkReply * reply ) const
+  {
+    if ( !mAuthCfg.isEmpty() )
+    {
+      return QgsAuthManager::instance()->updateNetworkReply( reply, mAuthCfg );
+    }
+    return true;
+  }
+
   //! Username for basic http authentication
   QString mUserName;
 
diff --git a/src/providers/wms/qgswmscapabilities.cpp b/src/providers/wms/qgswmscapabilities.cpp
index 5ce19bf..2ae3ab9 100644
--- a/src/providers/wms/qgswmscapabilities.cpp
+++ b/src/providers/wms/qgswmscapabilities.cpp
@@ -1934,6 +1934,14 @@ bool QgsWmsCapabilitiesDownload::downloadCapabilities()
   request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
 
   mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+  if ( !mAuth.setAuthorizationReply( mCapabilitiesReply ) )
+  {
+    mCapabilitiesReply->deleteLater();
+    mCapabilitiesReply = nullptr;
+    mError = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+    QgsMessageLog::logMessage( mError, tr( "WMS" ) );
+    return false;
+  }
   connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ), Qt::DirectConnection );
   connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );
 
@@ -2002,7 +2010,19 @@ void QgsWmsCapabilitiesDownload::capabilitiesReplyFinished()
 
           QgsDebugMsg( QString( "redirected getcapabilities: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ) );
           mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
-          connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ), Qt::DirectConnection );
+          
+		  if ( !mAuth.setAuthorizationReply( mCapabilitiesReply ) )
+          {
+            mHttpCapabilitiesResponse.clear();
+            mCapabilitiesReply->deleteLater();
+            mCapabilitiesReply = nullptr;
+            mError = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+            QgsMessageLog::logMessage( mError, tr( "WMS" ) );
+            emit downloadFinished();
+            return;
+          }
+		  
+		  connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ), Qt::DirectConnection );
           connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );
           return;
         }
diff --git a/src/providers/wms/qgswmscapabilities.h b/src/providers/wms/qgswmscapabilities.h
index c0273a9..60eda8f 100644
--- a/src/providers/wms/qgswmscapabilities.h
+++ b/src/providers/wms/qgswmscapabilities.h
@@ -455,6 +455,15 @@ struct QgsWmsAuthorization
     }
     return true;
   }
+  //! set authorization reply
+  bool setAuthorizationReply( QNetworkReply * reply ) const
+  {
+    if ( !mAuthCfg.isEmpty() )
+    {
+      return QgsAuthManager::instance()->updateNetworkReply( reply, mAuthCfg );
+    }
+    return true;
+  }
 
   //! Username for basic http authentication
   QString mUserName;
diff --git a/src/providers/wms/qgswmsprovider.cpp b/src/providers/wms/qgswmsprovider.cpp
index d6d22bf..9a72362 100644
--- a/src/providers/wms/qgswmsprovider.cpp
+++ b/src/providers/wms/qgswmsprovider.cpp
@@ -2805,6 +2805,7 @@ void QgsWmsProvider::identifyReplyFinished()
 
       QgsDebugMsg( QString( "redirected getfeatureinfo: %1" ).arg( redirect.toString() ) );
       mIdentifyReply = QgsNetworkAccessManager::instance()->get( QNetworkRequest( redirect.toUrl() ) );
+      mSettings.authorization().setAuthorizationReply( mIdentifyReply );
       mIdentifyReply->setProperty( "eventLoop", QVariant::fromValue( qobject_cast<QObject *>( loop ) ) );
       connect( mIdentifyReply, SIGNAL( finished() ), this, SLOT( identifyReplyFinished() ) );
       return;
@@ -3733,6 +3734,7 @@ QgsWmsLegendDownloadHandler::startUrl( const QUrl& url )
   request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
 
   mReply = mNetworkAccessManager.get( request );
+  mSettings.authorization().setAuthorizationReply( mReply );
   connect( mReply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( errored( QNetworkReply::NetworkError ) ) );
   connect( mReply, SIGNAL( finished() ), this, SLOT( finished() ) );
   connect( mReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( progressed( qint64, qint64 ) ) );
diff --git a/src/server/qgsserver.cpp b/src/server/qgsserver.cpp
index 22600f8..3366f7a 100644
--- a/src/server/qgsserver.cpp
+++ b/src/server/qgsserver.cpp
@@ -441,9 +441,9 @@ bool QgsServer::init( int & argc, char ** argv )
 void QgsServer::putenv( const QString &var, const QString &val )
 {
 #ifdef _MSC_VER
-  _putenv_s( var.toUtf8().data(), val.toUtf8().data() );
+  _putenv_s( var.toStdString().c_str(), val.toStdString().c_str() );
 #else
-  setenv( var.toUtf8().data(), val.toUtf8().data(), 1 );
+  setenv( var.toStdString().c_str(), val.toStdString().c_str(), 1 );
 #endif
 }
 
diff --git a/src/server/qgswfsserver.cpp b/src/server/qgswfsserver.cpp
index 51115ba..c598f53 100644
--- a/src/server/qgswfsserver.cpp
+++ b/src/server/qgswfsserver.cpp
@@ -409,8 +409,8 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
   mErrors = QStringList();
   mTypeNames = QStringList();
 
-  long maxFeat = 0;
-  long maxFeatures = -1;
+  long maxFeatures = 0;
+  bool hasFeatureLimit = false;
   long startIndex = 0;
   long featureCounter = 0;
   int layerPrec = 8;
@@ -431,9 +431,14 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
   {
     QDomElement docElem = doc.documentElement();
     if ( docElem.hasAttribute( "maxFeatures" ) )
+    {
+      hasFeatureLimit = true;
       maxFeatures = docElem.attribute( "maxFeatures" ).toLong();
+    }
     if ( docElem.hasAttribute( "startIndex" ) )
+    {
       startIndex = docElem.attribute( "startIndex" ).toLong();
+    }
 
     QDomNodeList queryNodes = docElem.elementsByTagName( "Query" );
     QDomElement queryElem;
@@ -629,7 +634,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
             req.setSubsetOfAttributes( attrIndexes );
 
             QgsFeatureIterator fit = layer->getFeatures( req );
-            while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
+            while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
             {
               if ( featureCounter == startIndex )
                 startGetFeature( request, format, layerPrec, layerCrs, &searchRect );
@@ -651,7 +656,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
               {
                 throw QgsMapServiceException( "RequestNotWellFormed", filter->parserErrorString() );
               }
-              while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
+              while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
               {
                 expressionContext.setFeature( feature );
 
@@ -678,7 +683,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
         }
         else
         {
-          while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
+          while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
           {
             if ( featureCounter == startIndex )
               startGetFeature( request, format, layerPrec, layerCrs, &searchRect );
@@ -818,8 +823,8 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
   {
     QString mfString = mfIt.value();
     bool mfOk;
+    hasFeatureLimit = true;
     maxFeatures = mfString.toLong( &mfOk, 10 );
-    maxFeat = mfString.toLong( &mfOk, 10 );
   }
 
   //read STARTINDEX
@@ -982,7 +987,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
           {
             throw QgsMapServiceException( "RequestNotWellFormed", QString( "Expression filter error message: %1." ).arg( filter->parserErrorString() ) );
           }
-          while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
+          while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
           {
             expressionContext.setFeature( feature );
             QVariant res = filter->evaluate( &expressionContext );
@@ -1066,7 +1071,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
           req.setSubsetOfAttributes( attrIndexes );
 
           QgsFeatureIterator fit = layer->getFeatures( req );
-          while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
+          while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
           {
             if ( featureCounter == startIndex )
               startGetFeature( request, format, layerPrec, layerCrs, &searchRect );
@@ -1107,7 +1112,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
             }
             req.setSubsetOfAttributes( attrIndexes );
             QgsFeatureIterator fit = layer->getFeatures( req );
-            while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
+            while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
             {
               expressionContext.setFeature( feature );
               QVariant res = filter->evaluate( &expressionContext );
@@ -1153,7 +1158,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
         }
         req.setSubsetOfAttributes( attrIndexes );
         QgsFeatureIterator fit = layer->getFeatures( req );
-        while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
+        while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
         {
           mErrors << QString( "The feature %2 of layer for the TypeName '%1'" ).arg( tnStr ).arg( featureCounter );
           if ( featureCounter == startIndex )
@@ -1374,7 +1379,7 @@ void QgsWFSServer::endGetFeature( QgsRequestHandler& request, const QString& for
   }
   else
   {
-    fcString = "</wfs:FeatureCollection>";
+    fcString = "</wfs:FeatureCollection>\n";
     result = fcString.toUtf8();
     request.endGetFeatureResponse( &result );
     fcString = "";
diff --git a/src/server/qgswmsserver.cpp b/src/server/qgswmsserver.cpp
index 28f30ab..cfcc29f 100644
--- a/src/server/qgswmsserver.cpp
+++ b/src/server/qgswmsserver.cpp
@@ -2194,6 +2194,10 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
   {
     fReq.setFilterRect( searchRect );
   }
+  else
+  {
+    fReq.setFlags( fReq.flags() & ~ QgsFeatureRequest::ExactIntersect );
+  }
 
 #ifdef HAVE_SERVER_PYTHON_PLUGINS
   mAccessControl->filterFeatures( layer, fReq );
diff --git a/tests/src/python/providertestbase.py b/tests/src/python/providertestbase.py
index df76136..2e33446 100644
--- a/tests/src/python/providertestbase.py
+++ b/tests/src/python/providertestbase.py
@@ -352,10 +352,36 @@ class ProviderTestCase(object):
         expected = set([fids[1], fids[3], fids[4]])
         assert result == expected, 'Expected {} and got {} when testing for feature IDs filter'.format(expected, result)
 
+        #providers should ignore non-existant fids
+        result = set([f.id() for f in self.provider.getFeatures(QgsFeatureRequest().setFilterFids([-101, fids[1], -102, fids[3], -103, fids[4], -104]))])
+        expected = set([fids[1], fids[3], fids[4]])
+        assert result == expected, 'Expected {} and got {} when testing for feature IDs filter'.format(expected, result)
+
         result = set([f.id() for f in self.provider.getFeatures(QgsFeatureRequest().setFilterFids([]))])
         expected = set([])
         assert result == expected, 'Expected {} and got {} when testing for feature IDs filter'.format(expected, result)
 
+        # Rewind mid-way
+        request = QgsFeatureRequest().setFilterFids([fids[1], fids[3], fids[4]])
+        feature_it = self.provider.getFeatures(request)
+        feature = QgsFeature()
+        feature.setValid(True)
+        self.assertTrue(feature_it.nextFeature(feature))
+        self.assertIn(feature.id(), [fids[1], fids[3], fids[4]])
+        first_feature = feature
+        self.assertTrue(feature.isValid())
+        # rewind
+        self.assertTrue(feature_it.rewind())
+        self.assertTrue(feature_it.nextFeature(feature))
+        self.assertEqual(feature.id(), first_feature.id())
+        self.assertTrue(feature.isValid())
+        # grab all features
+        self.assertTrue(feature_it.nextFeature(feature))
+        self.assertTrue(feature_it.nextFeature(feature))
+        # none left
+        self.assertFalse(feature_it.nextFeature(feature))
+        self.assertFalse(feature.isValid())
+
     def testGetFeaturesFilterRectTests(self):
         extent = QgsRectangle(-70, 67, -60, 80)
         request = QgsFeatureRequest().setFilterRect(extent)
diff --git a/tests/src/python/test_qgsfeatureiterator.py b/tests/src/python/test_qgsfeatureiterator.py
index 526157b..19f25c1 100644
--- a/tests/src/python/test_qgsfeatureiterator.py
+++ b/tests/src/python/test_qgsfeatureiterator.py
@@ -81,23 +81,20 @@ class TestQgsFeatureIterator(unittest.TestCase):
 
         ids = [feat.id() for feat in pointLayer.getFeatures(QgsFeatureRequest().setFilterFids([7, 8, 12, 30]))]
         expectedIds = [7, 8, 12]
-        myMessage = '\nExpected: {0} features\nGot: {1} features'.format(repr(expectedIds), repr(ids))
-        assert ids == expectedIds, myMessage
+        self.assertEquals(set(ids), set(expectedIds))
 
         pointLayer.startEditing()
         self.addFeatures(pointLayer)
 
         ids = [feat.id() for feat in pointLayer.getFeatures(QgsFeatureRequest().setFilterFids([-4, 7, 8, 12, 30]))]
         expectedIds = [-4, 7, 8, 12]
-        myMessage = '\nExpected: {0} features\nGot: {1} features'.format(repr(expectedIds), repr(ids))
-        assert ids == expectedIds, myMessage
+        self.assertEquals(set(ids), set(expectedIds))
 
         pointLayer.rollBack()
 
         ids = [feat.id() for feat in pointLayer.getFeatures(QgsFeatureRequest().setFilterFids([-2, 7, 8, 12, 30]))]
         expectedIds = [7, 8, 12]
-        myMessage = '\nExpected: {0} features\nGot: {1} features'.format(repr(expectedIds), repr(ids))
-        assert ids == expectedIds, myMessage
+        self.assertEquals(set(ids), set(expectedIds))
 
     def addFeatures(self, vl):
         feat = QgsFeature()
diff --git a/tests/src/python/test_qgspallabeling_placement.py b/tests/src/python/test_qgspallabeling_placement.py
index 26a6619..7c23df2 100644
--- a/tests/src/python/test_qgspallabeling_placement.py
+++ b/tests/src/python/test_qgspallabeling_placement.py
@@ -54,6 +54,7 @@ class TestPlacementBase(TestQgsPalLabeling):
     def setUp(self):
         """Run before each test."""
         super(TestPlacementBase, self).setUp()
+        self.removeAllLayers()
         self.configTest('pal_placement', 'sp')
         self._TestImage = ''
         # ensure per test map settings stay encapsulated
diff --git a/tests/src/python/test_qgsserver.py b/tests/src/python/test_qgsserver.py
index d41c8da..a810372 100644
--- a/tests/src/python/test_qgsserver.py
+++ b/tests/src/python/test_qgsserver.py
@@ -41,6 +41,13 @@ class TestQgsServer(unittest.TestCase):
                 pass
         self.server = QgsServer()
 
+    def assert_headers(self, header, body):
+        headers = Message(StringIO(header))
+        if 'content-length' in headers:
+            content_length = int(headers['content-length'])
+            body_length = len(body)
+            self.assertEqual(content_length, body_length, msg="Header reported content-length: %d Actual body length was: %d" % (content_length, body_length))
+
     def test_destructor_segfaults(self):
         """Segfault on destructor?"""
         server = QgsServer()
@@ -264,9 +271,19 @@ class TestQgsServer(unittest.TestCase):
 
         query_string = 'MAP=%s&SERVICE=WFS&VERSION=1.0.0&REQUEST=%s' % (urllib.quote(project), request)
         header, body = [str(_v) for _v in self.server.handleRequest(query_string)]
+        self.result_compare(
+            'wfs_getfeature_' + requestid + '.txt',
+            u"request %s failed.\n Query: %s" % (
+                query_string,
+                request,
+            ),
+            header, body
+        )
+
+    def result_compare(self, file_name, error_msg_header, header, body):
         self.assert_headers(header, body)
         response = header + body
-        f = open(self.testdata_path + 'wfs_getfeature_' + requestid + '.txt')
+        f = open(self.testdata_path + file_name)
         expected = f.read()
         f.close()
         # Store the output for debug or to regenerate the reference documents:
@@ -280,9 +297,8 @@ class TestQgsServer(unittest.TestCase):
         """
         response = re.sub(RE_STRIP_PATH, '', response)
         expected = re.sub(RE_STRIP_PATH, '', expected)
-        self.assertEqual(response, expected, msg=u"request %s failed.\n Query: %s\n Expected:\n%s\n\n Response:\n%s"
-                                                 % (query_string,
-                                                    request,
+        self.assertEqual(response, expected, msg=u"%s\n Expected:\n%s\n\n Response:\n%s"
+                                                 % (error_msg_header,
                                                     unicode(expected, errors='replace'),
                                                     unicode(response, errors='replace')))
 
@@ -290,16 +306,71 @@ class TestQgsServer(unittest.TestCase):
         tests = []
         tests.append(('nobbox', u'GetFeature&TYPENAME=testlayer'))
         tests.append(('startindex2', u'GetFeature&TYPENAME=testlayer&STARTINDEX=2'))
+        tests.append(('limit2', u'GetFeature&TYPENAME=testlayer&MAXFEATURES=2'))
+        tests.append(('start1_limit1', u'GetFeature&TYPENAME=testlayer&MAXFEATURES=1&STARTINDEX=1'))
 
         for id, req in tests:
             self.wfs_getfeature_compare(id, req)
 
-    def assert_headers(self, header, body):
-        headers = Message(StringIO(header))
-        if 'content-length' in headers:
-            content_length = int(headers['content-length'])
-            body_length = len(body)
-            self.assertEqual(content_length, body_length, msg="Header reported content-length: %d Actual body length was: %d" % (content_length, body_length))
+    def wfs_getfeature_post_compare(self, requestid, request):
+        project = self.testdata_path + "test+project_wfs.qgs"
+        assert os.path.exists(project), "Project file not found: " + project
+
+        query_string = 'MAP={}'.format(urllib.quote(project))
+        self.server.putenv("REQUEST_METHOD", "POST")
+        self.server.putenv("REQUEST_BODY", request)
+        header, body = self.server.handleRequest(query_string)
+        self.server.putenv("REQUEST_METHOD", '')
+        self.server.putenv("REQUEST_BODY", '')
+
+        self.result_compare(
+            'wfs_getfeature_{}.txt'.format(requestid),
+            "GetFeature in POST for '{}' failed.".format(requestid),
+            header, body,
+        )
+
+    def test_getfeature_post(self):
+        template = """<?xml version="1.0" encoding="UTF-8"?>
+<wfs:GetFeature service="WFS" version="1.0.0" {} xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
+  <wfs:Query typeName="testlayer" xmlns:feature="http://www.qgis.org/gml">
+    <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
+      <ogc:BBOX>
+        <ogc:PropertyName>geometry</ogc:PropertyName>
+        <gml:Envelope xmlns:gml="http://www.opengis.net/gml">
+          <gml:lowerCorner>8 44</gml:lowerCorner>
+          <gml:upperCorner>9 45</gml:upperCorner>
+        </gml:Envelope>
+      </ogc:BBOX>
+    </ogc:Filter>
+  </wfs:Query>
+</wfs:GetFeature>
+"""
+
+        tests = []
+        tests.append(('nobbox', template.format("")))
+        tests.append(('startindex2', template.format('startIndex="2"')))
+        tests.append(('limit2', template.format('maxFeatures="2"')))
+        tests.append(('start1_limit1', template.format('startIndex="1" maxFeatures="1"')))
+
+        for id, req in tests:
+            self.wfs_getfeature_post_compare(id, req)
+
+    def test_getLegendGraphics(self):
+        """Test that does not return an exception but an image"""
+        parms = {
+            'MAP': self.testdata_path + "test%2Bproject.qgs",
+            'SERVICE': 'WMS',
+            'VERSIONE': '1.0.0',
+            'REQUEST': 'GetLegendGraphic',
+            'FORMAT': 'image/png',
+            #'WIDTH': '20', # optional
+            #'HEIGHT': '20', # optional
+            'LAYER': u'testlayer+èé',
+        }
+        qs = '&'.join([u"%s=%s" % (k, v) for k, v in parms.iteritems()])
+        h, r = self.server.handleRequest(qs)
+        self.assertEquals(-1, h.find('Content-Type: text/xml; charset=utf-8'), "Header: %s\nResponse:\n%s" % (h, r))
+        self.assertNotEquals(-1, h.find('Content-Type: image/png'), "Header: %s\nResponse:\n%s" % (h, r))
 
     # The following code was used to test type conversion in python bindings
     # def test_qpair(self):
@@ -307,7 +378,5 @@ class TestQgsServer(unittest.TestCase):
     #    f, s = self.server.testQPair(('First', 'Second'))
     #    self.assertEqual(f, 'First')
     #    self.assertEqual(s, 'Second')
-
-
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/testdata/qgis_server/wfs_getfeature_nobbox.txt b/tests/testdata/qgis_server/wfs_getfeature_limit2.txt
similarity index 76%
copy from tests/testdata/qgis_server/wfs_getfeature_nobbox.txt
copy to tests/testdata/qgis_server/wfs_getfeature_limit2.txt
index 4e0ea08..bcb35f5 100644
--- a/tests/testdata/qgis_server/wfs_getfeature_nobbox.txt
+++ b/tests/testdata/qgis_server/wfs_getfeature_limit2.txt
@@ -39,21 +39,4 @@ Content-Type: text/xml; charset=utf-8
   <qgs:utf8nameè>two àò</qgs:utf8nameè>
  </qgs:testlayer>
 </gml:featureMember>
-<gml:featureMember>
- <qgs:testlayer fid="testlayer.2">
-  <gml:boundedBy>
-   <gml:Box srsName="EPSG:4326">
-    <gml:coordinates cs="," ts=" ">8.20345931,44.90139484 8.20345931,44.90139484</gml:coordinates>
-   </gml:Box>
-  </gml:boundedBy>
-  <qgs:geometry>
-   <gml:Point srsName="EPSG:4326">
-    <gml:coordinates cs="," ts=" ">8.20345931,44.90139484</gml:coordinates>
-   </gml:Point>
-  </qgs:geometry>
-  <qgs:id>3</qgs:id>
-  <qgs:name>three</qgs:name>
-  <qgs:utf8nameè>three èé↓</qgs:utf8nameè>
- </qgs:testlayer>
-</gml:featureMember>
-</wfs:FeatureCollection>
\ No newline at end of file
+</wfs:FeatureCollection>
diff --git a/tests/testdata/qgis_server/wfs_getfeature_nobbox.txt b/tests/testdata/qgis_server/wfs_getfeature_nobbox.txt
index 4e0ea08..d13aefc 100644
--- a/tests/testdata/qgis_server/wfs_getfeature_nobbox.txt
+++ b/tests/testdata/qgis_server/wfs_getfeature_nobbox.txt
@@ -56,4 +56,4 @@ Content-Type: text/xml; charset=utf-8
   <qgs:utf8nameè>three èé↓</qgs:utf8nameè>
  </qgs:testlayer>
 </gml:featureMember>
-</wfs:FeatureCollection>
\ No newline at end of file
+</wfs:FeatureCollection>
diff --git a/tests/testdata/qgis_server/wfs_getfeature_startindex2.txt b/tests/testdata/qgis_server/wfs_getfeature_start1_limit1.txt
similarity index 75%
copy from tests/testdata/qgis_server/wfs_getfeature_startindex2.txt
copy to tests/testdata/qgis_server/wfs_getfeature_start1_limit1.txt
index 59b3a7c..9408334 100644
--- a/tests/testdata/qgis_server/wfs_getfeature_startindex2.txt
+++ b/tests/testdata/qgis_server/wfs_getfeature_start1_limit1.txt
@@ -6,20 +6,20 @@ Content-Type: text/xml; charset=utf-8
  </gml:Box>
 </gml:boundedBy>
 <gml:featureMember>
- <qgs:testlayer fid="testlayer.2">
+ <qgs:testlayer fid="testlayer.1">
   <gml:boundedBy>
    <gml:Box srsName="EPSG:4326">
-    <gml:coordinates cs="," ts=" ">8.20345931,44.90139484 8.20345931,44.90139484</gml:coordinates>
+    <gml:coordinates cs="," ts=" ">8.20354699,44.90143568 8.20354699,44.90143568</gml:coordinates>
    </gml:Box>
   </gml:boundedBy>
   <qgs:geometry>
    <gml:Point srsName="EPSG:4326">
-    <gml:coordinates cs="," ts=" ">8.20345931,44.90139484</gml:coordinates>
+    <gml:coordinates cs="," ts=" ">8.20354699,44.90143568</gml:coordinates>
    </gml:Point>
   </qgs:geometry>
-  <qgs:id>3</qgs:id>
-  <qgs:name>three</qgs:name>
-  <qgs:utf8nameè>three èé↓</qgs:utf8nameè>
+  <qgs:id>2</qgs:id>
+  <qgs:name>two</qgs:name>
+  <qgs:utf8nameè>two àò</qgs:utf8nameè>
  </qgs:testlayer>
 </gml:featureMember>
-</wfs:FeatureCollection>
\ No newline at end of file
+</wfs:FeatureCollection>
diff --git a/tests/testdata/qgis_server/wfs_getfeature_startindex2.txt b/tests/testdata/qgis_server/wfs_getfeature_startindex2.txt
index 59b3a7c..534f7a1 100644
--- a/tests/testdata/qgis_server/wfs_getfeature_startindex2.txt
+++ b/tests/testdata/qgis_server/wfs_getfeature_startindex2.txt
@@ -22,4 +22,4 @@ Content-Type: text/xml; charset=utf-8
   <qgs:utf8nameè>three èé↓</qgs:utf8nameè>
  </qgs:testlayer>
 </gml:featureMember>
-</wfs:FeatureCollection>
\ No newline at end of file
+</wfs:FeatureCollection>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/qgis.git



More information about the Pkg-grass-devel mailing list