[qgis] 01/08: Imported Upstream version 2.14.2+dfsg

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Fri Apr 29 20:22:43 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 435e2ec755250b710d9f784a5bfc6a87313ceff1
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Apr 29 15:54:42 2016 +0200

    Imported Upstream version 2.14.2+dfsg
---
 .travis.yml                                        |  20 +-
 CMakeLists.txt                                     |   2 +-
 ChangeLog                                          | 512 ++++++++++++++++++++-
 debian/changelog                                   |  10 +-
 debian/control.in                                  |   2 +-
 debian/python-qgis.install.in                      |   1 +
 debian/rules                                       |   4 +
 ms-windows/osgeo4w/browser.bat.tmpl                |   1 +
 python/core/composer/qgscomposertablev2.sip        |   5 +-
 python/core/conversions.sip                        |  29 --
 python/core/qgis.sip                               |  11 +
 python/core/qgsdataprovider.sip                    |   5 +
 python/core/qgsnetworkaccessmanager.sip            |  20 +
 python/core/qgstracer.sip                          |   5 +
 python/core/symbology-ng/qgssymbolv2.sip           |  75 ++-
 .../db_manager/db_plugins/postgis/connector.py     |  10 +-
 .../plugins/processing/algs/gdal/ClipByExtent.py   |  14 +-
 python/plugins/processing/algs/gdal/ClipByMask.py  |  14 +-
 .../plugins/processing/algs/gdal/GdalAlgorithm.py  |  13 +-
 .../algs/gdal/GdalOgrAlgorithmProvider.py          |   2 +-
 python/plugins/processing/algs/gdal/contour.py     |   6 +-
 python/plugins/processing/algs/gdal/gdalcalc.py    |  14 +-
 python/plugins/processing/algs/gdal/rasterize.py   |  14 +-
 python/plugins/processing/algs/gdal/translate.py   |  14 +-
 python/plugins/processing/algs/gdal/warp.py        |  14 +-
 .../processing/algs/grass/GrassAlgorithm.py        |   2 +-
 .../algs/grass/GrassAlgorithmProvider.py           |   2 +-
 python/plugins/processing/algs/grass/GrassUtils.py |   8 +-
 .../processing/algs/grass7/Grass7Algorithm.py      |   2 +-
 .../algs/grass7/Grass7AlgorithmProvider.py         |   7 +-
 .../plugins/processing/algs/grass7/Grass7Utils.py  |  17 +-
 .../processing/algs/otb/OTBSpecific_XMLLoading.py  |   3 +-
 python/plugins/processing/algs/otb/OTBUtils.py     |  15 +-
 python/plugins/processing/algs/qgis/Buffer.py      |   4 +-
 python/plugins/processing/algs/qgis/Dissolve.py    |  17 +-
 .../plugins/processing/algs/qgis/JoinAttributes.py |   2 +-
 .../processing/algs/qgis/QGISAlgorithmProvider.py  |   2 +-
 .../processing/algs/qgis/ZonalStatistics.py        |  24 +-
 python/plugins/processing/algs/r/RAlgorithm.py     |   2 +-
 .../processing/algs/r/RAlgorithmProvider.py        |   2 +-
 python/plugins/processing/algs/r/RUtils.py         |  13 +-
 .../processing/algs/taudem/TauDEMAlgorithm.py      |   2 +-
 .../algs/taudem/TauDEMAlgorithmProvider.py         |   2 +-
 .../plugins/processing/algs/taudem/dinfdistdown.py |   2 +-
 .../processing/algs/taudem/dinfdistdown_multi.py   |   2 +-
 .../plugins/processing/algs/taudem/dinfdistup.py   |   2 +-
 .../processing/algs/taudem/dinfdistup_multi.py     |   2 +-
 .../processing/algs/taudem/dinftranslimaccum.py    |   2 +-
 .../processing/algs/taudem/dinftranslimaccum2.py   |   2 +-
 .../algs/taudem/dinftranslimaccum2_multi.py        |   2 +-
 .../algs/taudem/dinftranslimaccum_multi.py         |   2 +-
 .../plugins/processing/algs/taudem/dropanalysis.py |   2 +-
 .../processing/algs/taudem/dropanalysis_multi.py   |   2 +-
 python/plugins/processing/algs/taudem/gridnet.py   |   2 +-
 .../processing/algs/taudem/gridnet_multi.py        |   2 +-
 .../plugins/processing/algs/taudem/lengtharea.py   |   2 +-
 .../processing/algs/taudem/lengtharea_multi.py     |   2 +-
 .../processing/algs/taudem/peukerdouglas.py        |   2 +-
 .../processing/algs/taudem/peukerdouglas_multi.py  |   2 +-
 python/plugins/processing/algs/taudem/slopearea.py |   2 +-
 .../processing/algs/taudem/slopearea_multi.py      |   2 +-
 python/plugins/processing/core/GeoAlgorithm.py     |   3 +-
 .../processing/gui/CreateNewScriptAction.py        |   2 +-
 .../plugins/processing/gui/GetScriptsAndModels.py  |   4 +-
 python/plugins/processing/gui/ProcessingToolbox.py |   2 -
 python/plugins/processing/images/CMakeLists.txt    |   2 +-
 python/plugins/processing/images/gdal.png          | Bin 734 -> 0 bytes
 python/plugins/processing/images/gdal.svg          | 126 +++++
 python/plugins/processing/images/grass.png         | Bin 750 -> 0 bytes
 python/plugins/processing/images/grass.svg         | 271 +++++++++++
 python/plugins/processing/images/qgis.png          | Bin 785 -> 0 bytes
 python/plugins/processing/images/qgis.svg          | 286 ++++++++++++
 python/plugins/processing/images/r.png             | Bin 829 -> 0 bytes
 python/plugins/processing/images/r.svg             |  14 +
 python/plugins/processing/images/taudem.png        | Bin 1030 -> 0 bytes
 python/plugins/processing/images/taudem.svg        | 196 ++++++++
 .../plugins/processing/modeler/ModelerAlgorithm.py |   9 +-
 .../processing/modeler/ModelerParametersDialog.py  |   8 +-
 python/testing/CMakeLists.txt                      |   2 +-
 src/app/qgisapp.cpp                                |   5 +-
 src/app/qgsattributetabledialog.cpp                |   4 +-
 src/app/qgsrasterlayerproperties.cpp               |  19 +-
 src/app/qgsrasterlayerproperties.h                 |   7 +
 src/app/qgsstatisticalsummarydockwidget.cpp        |   2 +-
 src/app/qgsvectorlayerproperties.cpp               |  14 +-
 src/app/qgsvectorlayerproperties.h                 |   5 +
 src/core/composer/qgsatlascomposition.cpp          |  19 +-
 src/core/composer/qgscomposerattributetable.cpp    |  56 +--
 src/core/composer/qgscomposerattributetablev2.cpp  |  56 +--
 src/core/composer/qgscomposermap.cpp               |   8 +
 src/core/composer/qgscomposertablev2.cpp           |  18 +-
 src/core/composer/qgscomposertablev2.h             |   3 +-
 src/core/geometry/qgsgeometry.cpp                  |   6 +-
 src/core/layertree/qgslayertreemodellegendnode.cpp |   4 +-
 src/core/qgis.cpp                                  |  41 ++
 src/core/qgis.h                                    |  14 +-
 src/core/qgsdataprovider.h                         |   5 +
 src/core/qgsexpression.cpp                         |   8 +
 src/core/qgsexpressioncontext.cpp                  |   3 +
 src/core/qgsmaplayer.cpp                           |  40 +-
 src/core/qgsnetworkaccessmanager.cpp               |  18 +
 src/core/qgsnetworkaccessmanager.h                 |  19 +
 src/core/qgsofflineediting.cpp                     |  88 ++--
 src/core/qgspallabeling.cpp                        | 330 +++++++++----
 src/core/qgstracer.cpp                             |  36 +-
 src/core/qgstracer.h                               |   8 +
 src/core/qgsvectordataprovider.cpp                 |  14 +
 src/core/qgsvectorlayer.cpp                        |  69 ++-
 src/core/qgsvectorlayerlabelprovider.cpp           |   4 +-
 src/core/symbology-ng/qgsellipsesymbollayerv2.cpp  |  26 +-
 src/core/symbology-ng/qgssymbollayerv2utils.cpp    |  34 --
 src/core/symbology-ng/qgssymbolv2.cpp              |  70 ++-
 src/core/symbology-ng/qgssymbolv2.h                |  76 ++-
 .../qgsattributetablefiltermodel.cpp               |  36 +-
 .../editorwidgets/qgsrelationreferencewidget.cpp   |  22 +-
 .../qgsvaluerelationwidgetwrapper.cpp              |  15 +-
 src/gui/qgsfieldexpressionwidget.cpp               |   6 +-
 src/gui/qgsmapcanvastracer.cpp                     |   5 +
 src/gui/qgsnewnamedialog.cpp                       |   3 +
 src/plugins/CMakeLists.txt                         |   1 +
 src/plugins/globe/CMakeLists.txt                   |   3 +
 src/plugins/globe/globe_plugin.cpp                 |  17 +-
 .../qgsdelimitedtextfeatureiterator.cpp            |  22 +-
 .../delimitedtext/qgsdelimitedtextprovider.cpp     |   3 +-
 src/providers/memory/qgsmemoryfeatureiterator.cpp  |   6 +-
 src/providers/memory/qgsmemoryprovider.cpp         |   1 +
 src/providers/mssql/qgsmssqlfeatureiterator.cpp    |  23 +-
 src/providers/ogr/qgsogrfeatureiterator.cpp        |  12 +
 src/providers/oracle/qgsoraclefeatureiterator.cpp  | 174 +++++--
 src/providers/oracle/qgsoraclefeatureiterator.h    |   1 +
 .../postgres/qgspostgresfeatureiterator.cpp        |  13 +
 .../spatialite/qgsspatialitefeatureiterator.cpp    |  13 +
 src/providers/spatialite/qgsspatialiteprovider.cpp |   5 +-
 src/providers/spatialite/qgsspatialiteprovider.h   |   2 +
 .../virtual/qgsvirtuallayerfeatureiterator.cpp     |  16 +-
 src/providers/virtual/qgsvirtuallayerprovider.cpp  |   1 +
 src/providers/wfs/qgswfsprovider.cpp               |  89 +---
 src/server/qgsconfigparserutils.cpp                |  16 +-
 src/server/qgsserverprojectparser.cpp              |   2 +-
 src/server/qgswfsserver.cpp                        |  12 +
 src/ui/composer/qgscomposerlegendwidgetbase.ui     |  10 +-
 tests/src/core/testqgis.cpp                        |  68 +++
 tests/src/core/testqgslegendrenderer.cpp           |  37 ++
 tests/src/core/testqgssimplemarker.cpp             |  54 +++
 tests/src/gui/testqgsfieldexpressionwidget.cpp     |  57 +++
 tests/src/python/providertestbase.py               |  70 +++
 tests/src/python/test_provider_memory.py           |   2 +-
 .../python/test_qgsdelimitedtextprovider_wanted.py |  54 +++
 .../expected_legend_mapunits.png                   | Bin 0 -> 11060 bytes
 .../expected_legend_mapunits_mask.png              | Bin 0 -> 2192 bytes
 .../expected_simplemarker_boundsoffset.png         | Bin 0 -> 11019 bytes
 .../expected_simplemarker_boundsoffset_mask.png    | Bin 0 -> 5329 bytes
 .../expected_simplemarker_boundsrotation.png       | Bin 0 -> 19177 bytes
 .../expected_simplemarker_boundsrotation_mask.png  | Bin 0 -> 6115 bytes
 .../expected_simplemarker_boundsrotationoffset.png | Bin 0 -> 11845 bytes
 ...cted_simplemarker_boundsrotationoffset_mask.png | Bin 0 -> 3576 bytes
 tests/testdata/delimitedtext/test14666.csv         |   7 +
 157 files changed, 3157 insertions(+), 754 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 1ee4517..6136abe 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,15 +1,17 @@
 language: cpp
 
-sudo: required
-dist: precise
-group: legacy
+matrix:
+  allow_failures:
+    - os: osx
+  include:
+    - os: linux
+      sudo: required
+      dist: precise
+      group: legacy
+      compiler: clang
+    - os: osx
+      compiler: clang
 
-os:
-  - linux
-  - osx
-
-compiler:
-  - clang
 
 git:
   depth: 30
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 27eca56..21fdbc4 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 "1")
+SET(CPACK_PACKAGE_VERSION_PATCH "2")
 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 f3442dd..73312a3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,513 @@
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-29
+
+    Fix calculation of point symbol bounds using data defined rotation or offset
+
+    (cherry-picked from a67853f825c096f66c5525584b70c19f68209375)
+
+Martin Dobias <wonder.sk at gmail.com>	2016-04-27
+
+    Gracefully handle topology errors when tracing (fixes #14447)
+
+    (cherry picked from commit 11e7140d37b88264490928114665967df4f6cfa5)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-29
+
+    Fix delete ring tool not updating rendered feature (fix #14741)
+
+    (cherry-picked from 6c9bc938125376a2670ecf9047eff5ca853bf3ba)
+
+Juergen E. Fischer <jef at norbit.de>	2016-04-28
+
+    oracle provider: cleaner geometry retrieval and fix case issue with
+    feature request alias and sdo_relate
+
+rldhont <rldhont at gmail.com>	2016-04-27
+
+    [Processing][Modeler] Use default value instead of None
+
+    In Modeler algorithm, when a algorithm's parameter was not defined it's value was set to None.
+    Before the possibility to defined optional parameters, None value is equal to set value to default one.
+    Now, it's important to use default value instead of None.
+
+Denis Rouzaud <denis.rouzaud at gmail.com>	2016-04-27
+
+    debian: install qgis testing
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-04-26
+
+    [processing] don't write NaN's to attribute table (fix #14639)
+
+    (cherry picked from commit 77d95b0d655022ab5c9f1927fa0a8ddb492b44df)
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-04-26
+
+    fix formatting
+
+rldhont <rldhont at gmail.com>	2016-04-26
+
+    [Processing][GDAL] Well manage optional parameters
+
+    Because EXTRA and NO_DATA parameters are optional, the value can be `None` which is the same as `''`.
+
+    (cherry picked from commit 793b712eb9dbd5d6d7589e7490c63d50d0038a69)
+
+    Conflicts:
+python/plugins/processing/algs/gdal/rasterize.py
+python/plugins/processing/algs/gdal/warp.py
+
+volaya <volayaf at gmail.com>	2016-04-26
+
+    [processing] fixed wrong call to addToLog
+
+    (cherry picked from commit 5cc2dcd2a469da07ad95733a4832e21d01ba466c)
+
+Giovanni Manghi <giovanni.manghi at faunalia.pt>	2016-04-25
+
+    more GDAL a_nodata fixes, for sake of uniformity
+
+Giovanni Manghi <giovanni.manghi at faunalia.pt>	2016-04-25
+
+    set nodata parameter as optional in GDAL clip by extent
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-04-11
+
+    [processing] fix path handling (fix #14432)
+
+    (cherry picked from commit e873540d14cb102ffe9318063b32c323c56e5bfb)
+
+    Conflicts:
+python/plugins/processing/algs/otb/OTBUtils.py
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-26
+
+    Consolidate all qvariant sort methods to use qgsVariantLessThan,
+    make sure qgsVariantLessThan incorporates all functionality from
+    other duplicate implementations, and add tests
+
+    (fixes #14671)
+
+    (cherry-picked from 647f32)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-26
+
+    Fix map unit scale parameters were not always saved for labeling
+
+    Refs #14698 - all settings are now saved but the size range in mm
+    is not yet respected during rendering
+
+    (cherry-picked from 3322bc)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-26
+
+    Fix crash in relation reference widget (fix #14732)
+
+    (cherry-picked from eed4ee)
+
+Juergen E. Fischer <jef at norbit.de>	2016-04-25
+
+    osgeo4w: add qt plugin directories to browser
+
+    (cherry picked from commit b758a8c1b4fb5386ba5830092eb893d8f42ae033)
+
+Matthias Kuhn <matthias at opengis.ch>	2016-04-22
+
+    Reduce test matrix
+
+Alessandro Pasotti <apasotti at boundlessgeo.com>	2016-04-21
+
+    [bugfix] offline editing converting offline twice
+
+    Fixes #10537: Converting offline twice within the same
+    instance causing unusable offline state.
+
+    The problem was due to spatialite connection not being
+    invalidated.  When the new offline layer is re-created
+    the provider connection doesn't pick the latest commits.
+
+    Funded by Boundless
+
+    (cherry-picked from f045492)
+
+Even Rouault <even.rouault at spatialys.com>	2016-03-27
+
+    Add QgsDataProvider::invalidateConnections() and implement in Spatialite provider
+
+    This invalidates all cached connections to the given database name.
+    This will be used by the WFS provider to cleanup any cached connections before
+    removing its temporary Spatialite DB
+
+    (cherry-picked from 62bd406, necessary for offline plugin fix)
+
+Alessandro Pasotti <apasotti at boundlessgeo.com>	2016-04-15
+
+    Prevents a crash when online features are gone
+
+    Fixes an unreported segfault when converting an online layer
+    to offline if features cannot be (completely) fetched.
+
+    Funded by Boundless
+
+    (cherry-picked from 79442b6)
+
+Alessandro Pasotti <apasotti at boundlessgeo.com>	2016-04-13
+
+    Avoid crash when WFS converted to offline
+
+    Fixes #14010 Converting to Offline Editing of WFS-T layer causes minidump
+
+    Funded by Boundless
+
+    (cherry-picked from eeb9bdd)
+
+Matthias Kuhn <matthias at opengis.ch>	2016-04-22
+
+    allow failures on osx
+
+    currently building osx version fails due to deprecated sip directives in PyQt4.
+
+Matthias Kuhn <matthias at opengis.ch>	2016-04-22
+
+    Revert "[travis] OSX: Force sip version 4.17 due to build problems"
+
+    This reverts commit c88789973b6fb9ee25fc22e25a8fb4389738e74d.
+
+rldhont <rldhont at gmail.com>	2016-04-21
+
+    [BUGFIX] The way layer's shortname is write in QGIS project and used in QGIS Server
+
+Denis Rouzaud <denis.rouzaud at gmail.com>	2016-04-21
+
+    fix python testing install directory
+
+rldhont <rldhont at gmail.com>	2016-04-20
+
+    [BUGFIX] QGIS Server segfault if layer extent is null
+
+rldhont <rldhont at gmail.com>	2016-04-20
+
+    Remove set mShortName in QgsMapLayer constructor
+
+rldhont <rldhont at gmail.com>	2016-04-20
+
+    [Processing] Fix when iface is None
+
+Matthias Kuhn <matthias at opengis.ch>	2016-04-15
+
+    [travis] OSX: Force sip version 4.17 due to build problems
+
+Larry Shaffer <lshaffer at boundlessgeo.com>	2016-04-15
+
+    Remove conversions.sip conditionals meant for 4.12 but actually 4.18
+
+    - The hex version of 4.12 was not 0x041200 (current 4.18) but 0x040c00.
+      Code was always skipped and has worked with recent sip versions.
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-12
+
+    Fix effects not working for ellipse symbol layers (fix #14661)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-16
+
+    Fix missing map settings expression variables in composer maps
+
+    Missing map extent related variables were causing stacking order
+    issues with the 25d renderer (fix #14604)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-16
+
+    Fix other feature's geometries are shown instead of null geometry
+    in delimited text provider (fix #14666)
+
+    Add tests, also fix virtual layer, mssql and db2 providers which
+    suffered the same bug
+
+    (cherry-picked from 02e0e3f95925356c4da8ed5effa4634e92fd44f8)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-16
+
+    QgsSymbolV2: only pop expression scope if it was really added
+
+    (cherry-picked from ef77e19fe342e6734487ba3608a8c12ee72b0bf7)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-16
+
+    Fix some providers did not respect layer's subset when calculating
+    min/max/uniqueValues
+
+    Providers included delimited text, memory, virtual layer, and WFS
+
+    Add unit test to provider test
+
+    (cherry-picked from 16d8da3886c03ccc1acc5c9f1ca945cb49d454f2)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-16
+
+    Fix huge legend item size when symbol uses map unit sizes (fix #13979)
+
+    Add unit test
+
+    (cherry-picked from 0c5fa81126cec652d9e9932861f031c1ab3700db)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-16
+
+    Add methods for retrieving and setting size units for QgsMarkerSymbolV2
+
+    (cherry-picked from e21de0394d051de1eea7ce36d587cc933c474bae)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-16
+
+    Initially set focus to text in new name dialog
+
+    (cherry-picked from 846c6183cafe4cb535547f1e13a7f9c48d751a61)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-16
+
+    [composer] Fix crash setting table columns from python
+
+    (cherry-picked from 39d0ba5781c8b759faaaf333b54e886c01a2d910)
+
+Juergen E. Fischer <jef at norbit.de>	2016-04-15
+
+    Bring back QgsNetworkManager slots and signals removed in 2eb8243 as deprecated
+
+    (cherry picked from commit 78725feda46a534fbe419b61b85f13741950997a)
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-04-13
+
+    fix build
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-04-07
+
+    don't apply loaded style when layer properties dialog is cancelled
+
+    (cherry picked from commit 25a162c05a2fd95f8e685499a0e403a85edf2646)
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-04-10
+
+    [processing] fix missed quotes in OTB provider (fix #14557)
+
+    (cherry picked from commit 8eb79dbb91d55f9975d903a4f2cc1d650a68b038)
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-04-10
+
+    [processing] fix GRASS icon
+
+    (cherry picked from commit badea8ceb256fcfe12323b64f200b7ea18f316d8)
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-04-07
+
+    [processing] don't ask for MSYS folder for GRASS7 (fix #14431)
+
+    (cherry picked from commit 525194dc0b0db98ece343539f3cd5b7540f2a020)
+
+Alessandro Pasotti <apasottis at boundlessgeo.com>	2016-04-12
+
+    [dbmanager] PG ignore env if service file is used
+
+    Cherry-picked from master
+
+    Fixes #14436
+
+    Funded by Boundless
+
+volaya <volayaf at gmail.com>	2016-04-07
+
+    [processing] make gdal algorithms honor selection
+
+    fixes #14622
+
+    (cherry picked from commit cc50157ab8053637f24c6f18e35a2bea7feafc78)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-10
+
+    [processing] Use unary union in dissolve (much faster for many
+    complex geometry inputs)
+
+Even Rouault <even.rouault at spatialys.com>	2016-04-08
+
+    Fix thread-unsafe initialization of QgsExpression::Functions()
+
+    The method initializes the gmFunctions static member, without any mutex protection.
+    This turned out to cause random crashes in the tests of the WFS provider since the downloader
+    thread may evaluate an expression, in parallel of the main thread, which does the same.
+    This was mainly seen on Mac Travis (2 crashes + 1 failures, over 50 iterations), when
+    parallelizing tests so as to get particular scheduling :
+    https://travis-ci.org/rouault/Quantum-GIS/builds/121720556.
+    But I could finally reproduce it systematically on my Linux box when inserting the following sleep.
+
+    diff --git a/src/providers/wfs/qgswfsshareddata.cpp b/src/providers/wfs/qgswfsshareddata.cpp
+    index adc7042..e9e4577 100644
+    --- a/src/providers/wfs/qgswfsshareddata.cpp
+    +++ b/src/providers/wfs/qgswfsshareddata.cpp
+    @@ -426,6 +426,7 @@ int QgsWFSSharedData::registerToCache( QgsWFSFeatureIterator* iterator, QgsRecta
+         connect( mDownloader, SIGNAL( ready() ), &loop, SLOT( quit() ) );
+         mDownloader->start();
+         loop.exec( QEventLoop::ExcludeUserInputEvents );
+    +    usleep( 100 * 1000 );
+       }
+       if ( mDownloadFinished )
+         return -1;
+
+    After applying this commit, the Mac builder is fine:
+    https://travis-ci.org/rouault/Quantum-GIS/builds/121756158
+
+Juergen E. Fischer <jef at norbit.de>	2016-04-03
+
+    oracle provider: handle NULL geometry in case of multiple geometry columns
+
+    (cherry picked from commit c93187d78c49cada9bd6d554d171d640a53f72a8)
+
+Juergen E. Fischer <jef at norbit.de>	2016-04-08
+
+    oracle provider: handle empty geometries (fixes #14631)
+
+    (cherry picked from commit d07bc18353c2a11092fbd7e8c3483e9cca9b8822)
+
+rldhont <rldhont at gmail.com>	2016-04-08
+
+    [BUGFIX] QGIS Server segfault when features does not have the same fields as the layer.
+
+    In some WFS GetFeature request, with Filter or FeatureId, all the fields are not well loaded in the feature.
+
+    To fix it, we just verifying that the attribute index is lesser than the feature fields count.
+
+    Fixes #14619
+
+volaya <volayaf at gmail.com>	2016-04-04
+
+    [processing] extra checks to avoid issues with previous versions values
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-04-04
+
+    [processing] fix looping over features in Join Attributes alg (fix #14428)
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-04-01
+
+    [processing] more HiDPI fixes (refs #14474)
+
+Septen <gammerxpower at gmail.com>	2016-03-25
+
+    [processing]Fixed UI bug with invalid button width.
+
+volaya <volayaf at gmail.com>	2016-03-18
+
+    [processing] do not search text in short help when filtering in toolbox
+
+    This should fix problems with slow and unresponsive filtering
+
+Juergen E. Fischer <jef at norbit.de>	2016-04-04
+
+    don't crash when reply is destroyed while it's waiting for credentials to be entered
+
+    (cherry picked from commit 10a26e6acd8aa3a91e603730c752e398700e4451)
+
+Juergen E. Fischer <jef at norbit.de>	2016-03-31
+
+    globe plugin: fix crash on exit
+
+    (cherry picked from commit bde512646caffc48f3158ec42b56016aeaae77fd)
+
+Juergen E. Fischer <jef at norbit.de>	2016-04-05
+
+    debian packaging: no need for downgraded cmake on xenial anymore (backport dccd731)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-04
+
+    Fix field calc bar error when setting to field name with spaces
+
+    (cherry-picked from a4ed8e03e649e79c1e43c338426eca40c3d429a1)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-04
+
+    Fix stats dock not working with field names with spaces (fix #14541)
+
+    (cherry-picked from 53b493c6e6b49ba725d45e272c0690479c61a301)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-04
+
+    Fix QgsFieldExpressionWidget reporting field names with spaces as
+    invalid, add tests
+
+    (cherry-picked from af8c1667dfd6f945414b4080c95ee731125f44cc)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-04
+
+    Fix crash in memory provider (fix #14559)
+
+    (cherry-picked from 59d4b85c73aff475429005f321d6009ade9fc8c6)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-04
+
+    Fix layer extent was not invalidated for certain geometry editing
+    operations (eg move feature, add/delete/move vertex) (fix #14573)
+
+    (cherry-picked from 4ece916728da95b7fd98e8f46564df3cc0826fcb)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-04-04
+
+    Fix missing features when combining FilterExpression requests with
+    subsets of attributes and the filter expression requires fields
+    which are not included in the attribute subset
+
+    Note: I've only fixed the providers which implement the vector
+    provider conformance unit tests. Other providers (eg GRASS) should
+    also implement a similar fix.
+
+    (cherry-picked from 402ee9d4cf6d026574a77cc503d8e26918daa78b)
+
+elpaso <elpaso at itopen.it>	2016-03-30
+
+    Fix for simple geometries insert error in WFS-T
+
+    Fixes #14139 Error inserting feature in WFS-T server
+
+    (cherry-picked from commit 768416340fdf233f8f5ce8945636d8df8b2e4f48)
+
+    Signed-off-by: Larry Shaffer <lshaffer at boundlessgeo.com>
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-03-25
+
+    [processing] replace some raster icons with SVG to improve HiDPI support (refs #14474)
+
+Even Rouault <even.rouault at spatialys.com>	2016-03-25
+
+    Make QgsVectorDataProvider::fillMinMaxCache() handle LongLong
+
+    The code currently fallbacks to dealing with LongLong fields as
+    strings, which breaks the ProviderTestCase testMinValue() and
+    testMaxValue() tests, if we change the definition of the tests
+    of the memory provider to use a int8 field for the cnt field.
+
+    ======================================================================
+    FAIL: testMaxValue (__main__.TestPyQgsMemoryProviderIndexed)
+    ----------------------------------------------------------------------
+    Traceback (most recent call last):
+      File "/home/even/qgis-git/Quantum-GIS.clean/tests/src/python/providertestbase.py", line 349, in testMaxValue
+        self.assertEqual(self.provider.maximumValue(1), 400)
+    AssertionError: u'400' != 400
+
+    ======================================================================
+    FAIL: testMinValue (__main__.TestPyQgsMemoryProviderIndexed)
+    ----------------------------------------------------------------------
+    Traceback (most recent call last):
+      File "/home/even/qgis-git/Quantum-GIS.clean/tests/src/python/providertestbase.py", line 345, in testMinValue
+        self.assertEqual(self.provider.minimumValue(1), -200)
+    AssertionError: u'-200' != -200
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-03-01
+
+    Increase minimum size of composer legend list widget
+
+    (cherry picked from commit e695fbb9f11f9c0e08b59db7ecf8ad25d28d484f)
+
+Juergen E. Fischer <jef at norbit.de>	2016-03-26
+
+    disable symbol visiblity flags for globe plugin on release builds on trusty
+
+Juergen E. Fischer <jef at norbit.de>	2016-03-25
+
+    Release of 2.14.1
+
 Juergen E. Fischer <jef at norbit.de>	2016-03-25
 
     german translation update
@@ -755,7 +1265,7 @@ elpaso <elpaso at itopen.it>	2016-02-24
 
     [bugfix][server] Fixes #13291
 
-Merge: 395bae6 d266582
+Merge: 395bae6 d2665826
 Alessandro Pasotti <elpaso at itopen.it>	2016-02-24
 
     Merge pull request #2829 from elpaso/server-static-initializers-construct-on-firts-use
diff --git a/debian/changelog b/debian/changelog
index 40e473c..2c0290e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,14 @@
-qgis (2.14.1) UNRELEASED; urgency=medium
+qgis (2.14.2) UNRELEASED; urgency=medium
+
+  * Release of 2.14.2
+
+ -- Jürgen E. Fischer <jef at norbit.de>  Fri, 29 Apr 2016 14:00:28 +0200
+
+qgis (2.14.1) unstable; urgency=medium
 
   * Release of 2.14.1
 
- -- Jürgen E. Fischer <jef at norbit.de>  Fri, 25 Mar 2016 13:17:00 +0100
+ -- Jürgen E. Fischer <jef at norbit.de>  Fri, 29 Apr 2016 14:00:28 +0200
 
 qgis (2.14.0) unstable; urgency=medium
 
diff --git a/debian/control.in b/debian/control.in
index a4e4de8..9964b4a 100644
--- a/debian/control.in
+++ b/debian/control.in
@@ -6,7 +6,7 @@ Priority: optional
 Build-Depends:
  bison,
  cmake (>= 2.8),
-#wily xenial# cmake (<< 3.3.2),
+#wily# cmake (<< 3.3.2),
 #sid stretch jessie wheezy saucy trusty utopic vivid wily xenial# debhelper (>= 9),
 #sid stretch jessie trusty vivid wily xenial# dh-python,
 #precise# debhelper (>= 7),
diff --git a/debian/python-qgis.install.in b/debian/python-qgis.install.in
index 382a751..34a677a 100644
--- a/debian/python-qgis.install.in
+++ b/debian/python-qgis.install.in
@@ -5,5 +5,6 @@ usr/lib/python*/*-packages/qgis/gui/*
 usr/lib/python*/*-packages/qgis/analysis/*
 usr/lib/python*/*-packages/qgis/networkanalysis/*
 usr/lib/python*/*-packages/qgis/server/*
+usr/lib/python*/*-packages/qgis/testing/*
 #wheezy precise#usr/lib/python*/*-packages/pyspatialite/*.py
 #wheezy precise#usr/lib/python*/*-packages/pyspatialite/*.so
diff --git a/debian/rules b/debian/rules
index d3e1c3f..f44c81f 100755
--- a/debian/rules
+++ b/debian/rules
@@ -135,6 +135,10 @@ endif
 
 ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
 	CMAKE_OPTS += -DCMAKE_BUILD_TYPE=Debug
+else
+ifneq (,$(findstring $(DISTRIBUTION),"trusty"))
+	CMAKE_OPTS += -DKEEP_GLOBE_CXX_FLAGS=TRUE
+endif
 endif
 
 ifneq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
diff --git a/ms-windows/osgeo4w/browser.bat.tmpl b/ms-windows/osgeo4w/browser.bat.tmpl
index 267cfe6..2c95904 100644
--- a/ms-windows/osgeo4w/browser.bat.tmpl
+++ b/ms-windows/osgeo4w/browser.bat.tmpl
@@ -3,4 +3,5 @@ call "%~dp0\o4w_env.bat"
 @echo off
 path %OSGEO4W_ROOT%\apps\@package@\bin;%PATH%
 set QGIS_PREFIX_PATH=%OSGEO4W_ROOT:\=/%/apps/@package@
+set QT_PLUGIN_PATH=%OSGEO4W_ROOT%\apps\@package@\qtplugins;%OSGEO4W_ROOT%\apps\qt4\plugins
 start "QGIS Browser" /B "%OSGEO4W_ROOT%"\bin\@package at -browser-bin.exe %*
diff --git a/python/core/composer/qgscomposertablev2.sip b/python/core/composer/qgscomposertablev2.sip
index 825bc2c..e1e66c0 100644
--- a/python/core/composer/qgscomposertablev2.sip
+++ b/python/core/composer/qgscomposertablev2.sip
@@ -347,10 +347,11 @@ class QgsComposerTableV2: QgsComposerMultiFrame
     QgsComposerTableColumns* columns();
 
     /** Replaces the columns in the table with a specified list of QgsComposerTableColumns.
-     * @param columns list of QgsComposerTableColumns to show in table
+     * @param columns list of QgsComposerTableColumns to show in table. Ownership of columns
+     * is transferred to the table.
      * @see columns
      */
-    void setColumns( const QgsComposerTableColumns& columns );
+    void setColumns( const QgsComposerTableColumns& columns /Transfer/ );
 
     /** Sets the cell style for a cell group.
      * @param group group to set style for
diff --git a/python/core/conversions.sip b/python/core/conversions.sip
index 8fcf789..d64171f 100644
--- a/python/core/conversions.sip
+++ b/python/core/conversions.sip
@@ -680,11 +680,6 @@ template<TYPE>
   PyObject *kobj, *tobj, *kobj2, *tobj2;
   Py_ssize_t i = 0;
 
-  //TODO: it works using SIP
-#if (SIP_VERSION >= 0x041200)
-  const sipMappedType* qmap2 = sipFindMappedType("QMap<int, TYPE>");
-#endif
-
   // Check the type if that is all that is required.
   if (sipIsErr == NULL)
   {
@@ -696,17 +691,12 @@ template<TYPE>
       if (!PyDict_Check(tobj))
         return 0;
 
-#if (SIP_VERSION >= 0x041200)
-      if (!sipCanConvertToMappedType(tobj, qmap2, SIP_NOT_NONE))
-        return 0;
-#else
       Py_ssize_t j = 0;
       while (PyDict_Next(tobj, &j, &kobj2, &tobj2))
       {
         if (!sipCanConvertToType(tobj2, sipType_TYPE, SIP_NOT_NONE))
           return 0;
       }
-#endif
     }
     return 1;
   }
@@ -717,24 +707,6 @@ template<TYPE>
   {
     qint64 k = PyLong_AsLongLong(kobj);
 
-#if (SIP_VERSION >= 0x041200)
-    // TODO: search for the minimum SIP version this code works on, it works
-    // on SIP 4.13.3 (GS). See #else to know why the version check is needed.
-
-    int state;
-
-    TYPE* t = reinterpret_cast<TYPE*>(sipConvertToMappedType(tobj, qmap2, sipTransferObj,SIP_NOT_NONE,&state,sipIsErr));
-
-    if (*sipIsErr)
-    {
-      sipReleaseMappedType(t, qmap2, state);
-      delete qm;
-      return 0;
-    }
-
-    qm.insert(k, *t);
-    sipReleaseMappedType(t, qmap2, state);
-#else
     // using sipConvertToMappedType to convert directly to QMap<int, TYPE> doesn't work
     // and ends with a segfault
 
@@ -759,7 +731,6 @@ template<TYPE>
       sipReleaseType(t2, sipType_TYPE, state);
     }
     qm->insert(k, qm2);
-#endif
   }
 
   *sipCppPtr = qm;
diff --git a/python/core/qgis.sip b/python/core/qgis.sip
index 197e427..2dc6dd3 100644
--- a/python/core/qgis.sip
+++ b/python/core/qgis.sip
@@ -233,6 +233,17 @@ class QGis
     static double DEFAULT_HIGHLIGHT_MIN_WIDTH_MM;
 };
 
+//! Compares two QVariant values and returns whether the first is less than the second.
+//! Useful for sorting lists of variants, correctly handling sorting of the various
+//! QVariant data types (such as strings, numeric values, dates and times)
+//! @see qgsVariantGreaterThan()
+bool qgsVariantLessThan( const QVariant& lhs, const QVariant& rhs );
+
+//! Compares two QVariant values and returns whether the first is greater than the second.
+//! Useful for sorting lists of variants, correctly handling sorting of the various
+//! QVariant data types (such as strings, numeric values, dates and times)
+//! @see qgsVariantLessThan()
+bool qgsVariantGreaterThan( const QVariant& lhs, const QVariant& rhs );
 
 /** Wkt string that represents a geographic coord sys
  * @note added to replace GEOWkt
diff --git a/python/core/qgsdataprovider.sip b/python/core/qgsdataprovider.sip
index c003d90..7ea28ec 100644
--- a/python/core/qgsdataprovider.sip
+++ b/python/core/qgsdataprovider.sip
@@ -218,6 +218,11 @@ class QgsDataProvider : QObject
      */
     virtual QgsError error() const;
 
+    /** Invalidate connections corresponding to specified name
+     * @note added in QGIS 2.16
+     */
+    virtual void invalidateConnections( const QString& connection );
+
   signals:
 
     /**
diff --git a/python/core/qgsnetworkaccessmanager.sip b/python/core/qgsnetworkaccessmanager.sip
index b4e1e83..9a15075 100644
--- a/python/core/qgsnetworkaccessmanager.sip
+++ b/python/core/qgsnetworkaccessmanager.sip
@@ -60,12 +60,32 @@ class QgsNetworkAccessManager : QNetworkAccessManager
     //! Setup the NAM according to the user's settings
     void setupDefaultProxyAndCache();
 
+    //! return whether the system proxy should be used
     bool useSystemProxy();
 
+  public slots:
+    /** Send GET request, calls get().
+     * Emits requestSent().
+     * @param request request to be sent
+     * @deprecated use get() directly
+     */
+    void sendGet( const QNetworkRequest & request ) /Deprecated/;
+    /** Abort and delete reply.
+     * @param reply reply to be aborted.
+     * @deprecated use abort() and deleteLayer() on the reply directly
+     */
+    void deleteReply( QNetworkReply * reply ) /Deprecated/;
+
   signals:
     void requestAboutToBeCreated( QNetworkAccessManager::Operation, const QNetworkRequest &, QIODevice * );
     void requestCreated( QNetworkReply * );
     void requestTimedOut( QNetworkReply * );
+    /** Emitted when request was sent by request()
+     * @param reply request reply
+     * @param sender the object which called request() slot.
+     * @deprecated only emitted from deprecated sendGet
+     */
+    void requestSent( QNetworkReply * reply, QObject *sender );
 
   protected:
     virtual QNetworkReply *createRequest( QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *outgoingData = 0 );
diff --git a/python/core/qgstracer.sip b/python/core/qgstracer.sip
index a7dff3a..0dfb904 100644
--- a/python/core/qgstracer.sip
+++ b/python/core/qgstracer.sip
@@ -49,6 +49,11 @@ class QgsTracer : QObject
     //! Whether the internal data structures have been initialized
     bool isInitialized() const;
 
+    //! Whether there was an error during graph creation due to noding exception,
+    //! indicating some input data topology problems
+    //! @note added in QGIS 2.14.2
+    bool hasTopologyProblem() const;
+
     //! Possible errors that may happen when calling findShortestPath()
     enum PathError
     {
diff --git a/python/core/symbology-ng/qgssymbolv2.sip b/python/core/symbology-ng/qgssymbolv2.sip
index 808eebe..c3feb72 100644
--- a/python/core/symbology-ng/qgssymbolv2.sip
+++ b/python/core/symbology-ng/qgssymbolv2.sip
@@ -363,7 +363,19 @@ class QgsMarkerSymbolV2 : QgsSymbolV2
 
     QgsMarkerSymbolV2( const QgsSymbolLayerV2List& layers /Transfer/ = QgsSymbolLayerV2List() );
 
+    /** Sets the angle for the whole symbol. Individual symbol layer sizes
+     * will be rotated to maintain their current relative angle to the whole symbol angle.
+     * @param angle new symbol angle
+     * @see angle()
+     */
     void setAngle( double angle );
+
+    /** Returns the marker angle for the whole symbol. Note that for symbols with
+     * multiple symbol layers, this will correspond just to the angle of
+     * the first symbol layer.
+     * @note added in QGIS 2.16
+     * @see setAngle()
+     */
     double angle() const;
 
     /** Set data defined angle for whole symbol (including all symbol layers).
@@ -389,9 +401,60 @@ class QgsMarkerSymbolV2 : QgsSymbolV2
      */
     void setLineAngle( double lineAngle );
 
+    /** Sets the size for the whole symbol. Individual symbol layer sizes
+     * will be scaled to maintain their current relative size to the whole symbol size.
+     * @param size new symbol size
+     * @see size()
+     * @see setSizeUnit()
+     * @see setSizeMapUnitScale()
+     */
     void setSize( double size );
+
+    /** Returns the size for the whole symbol, which is the maximum size of
+     * all marker symbol layers in the symbol.
+     * @see setSize()
+     * @see sizeUnit()
+     * @see sizeMapUnitScale()
+     */
     double size() const;
 
+    /** Sets the size units for the whole symbol (including all symbol layers).
+     * @param unit size units
+     * @note added in QGIS 2.16
+     * @see sizeUnit()
+     * @see setSizeMapUnitScale()
+     * @see setSize()
+     */
+    void setSizeUnit( OutputUnit unit );
+
+    /** Returns the size units for the whole symbol (including all symbol layers).
+     * @returns size units, or mixed units if symbol layers have different units
+     * @note added in QGIS 2.16
+     * @see setSizeUnit()
+     * @see sizeMapUnitScale()
+     * @see size()
+     */
+    OutputUnit sizeUnit() const;
+
+    /** Sets the size map unit scale for the whole symbol (including all symbol layers).
+     * @param scale map unit scale
+     * @note added in QGIS 2.16
+     * @see sizeMapUnitScale()
+     * @see setSizeUnit()
+     * @see setSize()
+     */
+    void setSizeMapUnitScale( const QgsMapUnitScale& scale );
+
+    /** Returns the size map unit scale for the whole symbol. Note that for symbols with
+     * multiple symbol layers, this will correspond just to the map unit scale
+     * for the first symbol layer.
+     * @note added in QGIS 2.16
+     * @see setSizeMapUnitScale()
+     * @see sizeUnit()
+     * @see size()
+     */
+    QgsMapUnitScale sizeMapUnitScale() const;
+
     /** Set data defined size for whole symbol (including all symbol layers).
      * @param dd data defined size
      * @note added in QGIS 2.9
@@ -413,10 +476,16 @@ class QgsMarkerSymbolV2 : QgsSymbolV2
     void renderPoint( QPointF point, const QgsFeature* f, QgsRenderContext& context, int layer = -1, bool selected = false );
 
     /** Returns the approximate bounding box of the marker symbol, which includes the bounding box
-     * of all symbol layers for the symbol.
+     * of all symbol layers for the symbol. It is recommended to use this method only between startRender()
+     * and stopRender() calls, or data defined rotation and offset will not be correctly calculated.
+     * @param point location of rendered point in painter units
+     * @param context render context
+     * @param feature feature being rendered at point (optional). If not specified, the bounds calculation will not
+     * include data defined parameters such as offset and rotation
      * @returns approximate symbol bounds, in painter units
-     * @note added in QGIS 2.14     */
-    QRectF bounds( QPointF point, QgsRenderContext& context ) const;
+     * @note added in QGIS 2.14
+    */
+    QRectF bounds(QPointF point, QgsRenderContext& context, const QgsFeature &feature = QgsFeature() ) const;
 
     virtual QgsMarkerSymbolV2* clone() const /Factory/;
 };
diff --git a/python/plugins/db_manager/db_plugins/postgis/connector.py b/python/plugins/db_manager/db_plugins/postgis/connector.py
index 3eeb89a..ec23ade 100644
--- a/python/plugins/db_manager/db_plugins/postgis/connector.py
+++ b/python/plugins/db_manager/db_plugins/postgis/connector.py
@@ -48,11 +48,15 @@ class PostGisDBConnector(DBConnector):
         self.host = uri.host() or os.environ.get('PGHOST')
         self.port = uri.port() or os.environ.get('PGPORT')
 
-        username = uri.username() or os.environ.get('PGUSER') or os.environ.get('USER')
+        username = uri.username() or os.environ.get('PGUSER')
         password = uri.password() or os.environ.get('PGPASSWORD')
 
-        self.dbname = uri.database() or os.environ.get('PGDATABASE') or username
-        uri.setDatabase(self.dbname)
+        # Do not get db and user names from the env if service is used
+        if uri.service() is None:
+            if username is None:
+                username = os.environ.get('USER')
+            self.dbname = uri.database() or os.environ.get('PGDATABASE') or username
+            uri.setDatabase(self.dbname)
 
         expandedConnInfo = self._connectionInfo()
         try:
diff --git a/python/plugins/processing/algs/gdal/ClipByExtent.py b/python/plugins/processing/algs/gdal/ClipByExtent.py
index fcabbd9..3271190 100644
--- a/python/plugins/processing/algs/gdal/ClipByExtent.py
+++ b/python/plugins/processing/algs/gdal/ClipByExtent.py
@@ -64,7 +64,7 @@ class ClipByExtent(GdalAlgorithm):
             self.INPUT, self.tr('Input layer'), False))
         self.addParameter(ParameterString(self.NO_DATA,
                                           self.tr("Nodata value, leave blank to take the nodata value from input"),
-                                          ''))
+                                          '', optional=True))
         self.addParameter(ParameterExtent(self.PROJWIN, self.tr('Clipping extent')))
 
         params = []
@@ -98,9 +98,13 @@ class ClipByExtent(GdalAlgorithm):
 
     def getConsoleCommands(self):
         out = self.getOutputValue(self.OUTPUT)
-        noData = unicode(self.getParameterValue(self.NO_DATA))
+        noData = self.getParameterValue(self.NO_DATA)
+        if noData is not None:
+            noData = unicode(noData)
         projwin = unicode(self.getParameterValue(self.PROJWIN))
-        extra = unicode(self.getParameterValue(self.EXTRA))
+        extra = self.getParameterValue(self.EXTRA)
+        if extra is not None:
+            extra = unicode(extra)
         jpegcompression = unicode(self.getParameterValue(self.JPEGCOMPRESSION))
         predictor = unicode(self.getParameterValue(self.PREDICTOR))
         zlevel = unicode(self.getParameterValue(self.ZLEVEL))
@@ -114,7 +118,7 @@ class ClipByExtent(GdalAlgorithm):
         arguments.append(GdalUtils.getFormatShortNameFromFilename(out))
         arguments.append('-ot')
         arguments.append(self.TYPE[self.getParameterValue(self.RTYPE)])
-        if len(noData) > 0:
+        if noData and len(noData) > 0:
             arguments.append('-a_nodata')
             arguments.append(noData)
 
@@ -125,7 +129,7 @@ class ClipByExtent(GdalAlgorithm):
         arguments.append(regionCoords[1])
         arguments.append(regionCoords[2])
 
-        if len(extra) > 0:
+        if extra and len(extra) > 0:
             arguments.append(extra)
         if GdalUtils.getFormatShortNameFromFilename(out) == "GTiff":
             arguments.append("-co COMPRESS=" + compress)
diff --git a/python/plugins/processing/algs/gdal/ClipByMask.py b/python/plugins/processing/algs/gdal/ClipByMask.py
index 6a37191..8e4d7af 100644
--- a/python/plugins/processing/algs/gdal/ClipByMask.py
+++ b/python/plugins/processing/algs/gdal/ClipByMask.py
@@ -73,7 +73,7 @@ class ClipByMask(GdalAlgorithm):
                                           [ParameterVector.VECTOR_TYPE_POLYGON]))
         self.addParameter(ParameterString(self.NO_DATA,
                                           self.tr("Nodata value, leave blank to take the nodata value from input"),
-                                          '-9999'))
+                                          '', optional=True))
         self.addParameter(ParameterBoolean(self.ALPHA_BAND,
                                            self.tr('Create and output alpha band'), False))
         self.addParameter(ParameterBoolean(self.CROP_TO_CUTLINE,
@@ -116,11 +116,15 @@ class ClipByMask(GdalAlgorithm):
         maskLayer = dataobjects.getObjectFromUri(
             self.getParameterValue(self.MASK))
         ogrMask = ogrConnectionString(mask)[1:-1]
-        noData = unicode(self.getParameterValue(self.NO_DATA))
+        noData = self.getParameterValue(self.NO_DATA)
+        if noData is not None:
+            noData = unicode(noData)
         addAlphaBand = self.getParameterValue(self.ALPHA_BAND)
         cropToCutline = self.getParameterValue(self.CROP_TO_CUTLINE)
         keepResolution = self.getParameterValue(self.KEEP_RESOLUTION)
-        extra = unicode(self.getParameterValue(self.EXTRA))
+        extra = self.getParameterValue(self.EXTRA)
+        if extra is not None:
+            extra = unicode(extra)
         jpegcompression = unicode(self.getParameterValue(self.JPEGCOMPRESSION))
         predictor = unicode(self.getParameterValue(self.PREDICTOR))
         zlevel = unicode(self.getParameterValue(self.ZLEVEL))
@@ -135,7 +139,7 @@ class ClipByMask(GdalAlgorithm):
         arguments.append('-q')
         arguments.append('-of')
         arguments.append(GdalUtils.getFormatShortNameFromFilename(out))
-        if len(noData) > 0:
+        if noData and len(noData) > 0:
             arguments.append('-dstnodata')
             arguments.append(noData)
 
@@ -160,7 +164,7 @@ class ClipByMask(GdalAlgorithm):
         if addAlphaBand:
             arguments.append('-dstalpha')
 
-        if len(extra) > 0:
+        if extra and len(extra) > 0:
             arguments.append(extra)
         if GdalUtils.getFormatShortNameFromFilename(out) == "GTiff":
             arguments.append("-co COMPRESS=" + compress)
diff --git a/python/plugins/processing/algs/gdal/GdalAlgorithm.py b/python/plugins/processing/algs/gdal/GdalAlgorithm.py
index 500b56b..e50a348 100644
--- a/python/plugins/processing/algs/gdal/GdalAlgorithm.py
+++ b/python/plugins/processing/algs/gdal/GdalAlgorithm.py
@@ -16,6 +16,7 @@
 *                                                                         *
 ***************************************************************************
 """
+from processing.tools import dataobjects
 
 
 __author__ = 'Victor Olaya'
@@ -41,13 +42,21 @@ pluginPath = os.path.normpath(os.path.join(
 class GdalAlgorithm(GeoAlgorithm):
 
     def getIcon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'gdal.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'gdal.svg'))
 
     def getCustomParametersDialog(self):
         return GdalAlgorithmDialog(self)
 
     def processAlgorithm(self, progress):
-        GdalUtils.runGdal(self.getConsoleCommands(), progress)
+        commands = self.getConsoleCommands()
+        layers = dataobjects.getVectorLayers()
+        for i, c in enumerate(commands):
+            for layer in layers:
+                if layer.source() in c:
+                    c = c.replace(layer.source(), dataobjects.exportVectorLayer(layer))
+
+            commands[i] = c
+        GdalUtils.runGdal(commands, progress)
 
     def shortHelp(self):
         return self._formatHelp('''This algorithm is based on the GDAL %s module.
diff --git a/python/plugins/processing/algs/gdal/GdalOgrAlgorithmProvider.py b/python/plugins/processing/algs/gdal/GdalOgrAlgorithmProvider.py
index 60768ae..9934ff6 100644
--- a/python/plugins/processing/algs/gdal/GdalOgrAlgorithmProvider.py
+++ b/python/plugins/processing/algs/gdal/GdalOgrAlgorithmProvider.py
@@ -108,7 +108,7 @@ class GdalOgrAlgorithmProvider(AlgorithmProvider):
         return 'gdalogr'
 
     def getIcon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'gdal.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'gdal.svg'))
 
     def _loadAlgorithms(self):
         self.algs = self.preloadedAlgs
diff --git a/python/plugins/processing/algs/gdal/contour.py b/python/plugins/processing/algs/gdal/contour.py
index 0082f46..eeefa6c 100644
--- a/python/plugins/processing/algs/gdal/contour.py
+++ b/python/plugins/processing/algs/gdal/contour.py
@@ -64,7 +64,9 @@ class contour(GdalAlgorithm):
     def getConsoleCommands(self):
         interval = unicode(self.getParameterValue(self.INTERVAL))
         fieldName = unicode(self.getParameterValue(self.FIELD_NAME))
-        extra = unicode(self.getParameterValue(self.EXTRA))
+        extra = self.getParameterValue(self.EXTRA)
+        if extra is not None:
+            extra = unicode(extra)
 
         arguments = []
         if len(fieldName) > 0:
@@ -73,7 +75,7 @@ class contour(GdalAlgorithm):
         arguments.append('-i')
         arguments.append(interval)
 
-        if len(extra) > 0:
+        if extra and len(extra) > 0:
             arguments.append(extra)
 
         arguments.append(self.getParameterValue(self.INPUT_RASTER))
diff --git a/python/plugins/processing/algs/gdal/gdalcalc.py b/python/plugins/processing/algs/gdal/gdalcalc.py
index 7c42eaf..74818f7 100644
--- a/python/plugins/processing/algs/gdal/gdalcalc.py
+++ b/python/plugins/processing/algs/gdal/gdalcalc.py
@@ -92,7 +92,7 @@ class gdalcalc(GdalAlgorithm):
         self.addParameter(ParameterString(self.FORMULA,
                                           self.tr('Calculation in gdalnumeric syntax using +-/* or any numpy array functions (i.e. logical_and())'), 'A*2', optional=False))
         self.addParameter(ParameterString(self.NO_DATA,
-                                          self.tr('Set output nodata value'), '-9999'))
+                                          self.tr('Set output nodata value'), '', optional=True))
         self.addParameter(ParameterSelection(self.RTYPE,
                                              self.tr('Output raster type'), self.TYPE, 5))
         #self.addParameter(ParameterBoolean(
@@ -103,10 +103,14 @@ class gdalcalc(GdalAlgorithm):
 
     def getConsoleCommands(self):
         out = self.getOutputValue(self.OUTPUT)
-        extra = unicode(self.getParameterValue(self.EXTRA))
+        extra = self.getParameterValue(self.EXTRA)
+        if extra is not None:
+            extra = unicode(extra)
         #debug = self.getParameterValue(self.DEBUG)
         formula = self.getParameterValue(self.FORMULA)
-        noData = unicode(self.getParameterValue(self.NO_DATA))
+        noData = self.getParameterValue(self.NO_DATA)
+        if noData is not None:
+            noData = unicode(noData)
 
         arguments = []
         arguments.append('--calc')
@@ -115,10 +119,10 @@ class gdalcalc(GdalAlgorithm):
         arguments.append(GdalUtils.getFormatShortNameFromFilename(out))
         arguments.append('--type')
         arguments.append(self.TYPE[self.getParameterValue(self.RTYPE)])
-        if len(noData) > 0:
+        if noData and len(noData) > 0:
             arguments.append('--NoDataValue')
             arguments.append(noData)
-        if len(extra) > 0:
+        if extra and len(extra) > 0:
             arguments.append(extra)
         #if debug:
         #    arguments.append('--debug')
diff --git a/python/plugins/processing/algs/gdal/rasterize.py b/python/plugins/processing/algs/gdal/rasterize.py
index 1aeb02e..b7c34d5 100644
--- a/python/plugins/processing/algs/gdal/rasterize.py
+++ b/python/plugins/processing/algs/gdal/rasterize.py
@@ -85,7 +85,7 @@ class rasterize(GdalAlgorithm):
                                          self.TYPE, 5))
         params.append(ParameterString(self.NO_DATA,
                                       self.tr("Nodata value"),
-                                      '-9999'))
+                                      '', optional=True))
         params.append(ParameterSelection(self.COMPRESS,
                                          self.tr('GeoTIFF options. Compression type:'), self.COMPRESSTYPE, 4))
         params.append(ParameterNumber(self.JPEGCOMPRESSION,
@@ -116,7 +116,9 @@ class rasterize(GdalAlgorithm):
     def getConsoleCommands(self):
         inLayer = self.getParameterValue(self.INPUT)
         ogrLayer = ogrConnectionString(inLayer)[1:-1]
-        noData = unicode(self.getParameterValue(self.NO_DATA))
+        noData = self.getParameterValue(self.NO_DATA)
+        if noData is not None:
+            noData = unicode(noData)
         jpegcompression = unicode(self.getParameterValue(self.JPEGCOMPRESSION))
         predictor = unicode(self.getParameterValue(self.PREDICTOR))
         zlevel = unicode(self.getParameterValue(self.ZLEVEL))
@@ -125,7 +127,9 @@ class rasterize(GdalAlgorithm):
         bigtiff = self.BIGTIFFTYPE[self.getParameterValue(self.BIGTIFF)]
         tfw = unicode(self.getParameterValue(self.TFW))
         out = self.getOutputValue(self.OUTPUT)
-        extra = unicode(self.getParameterValue(self.EXTRA))
+        extra = self.getParameterValue(self.EXTRA)
+        if extra is not None:
+            extra = unicode(extra)
 
         arguments = []
         arguments.append('-a')
@@ -147,7 +151,7 @@ class rasterize(GdalAlgorithm):
             arguments.append(unicode(self.getParameterValue(self.WIDTH)))
             arguments.append(unicode(self.getParameterValue(self.HEIGHT)))
 
-        if len(noData) > 0:
+        if noData and len(noData) > 0:
             arguments.append('-a_nodata')
             arguments.append(noData)
 
@@ -165,7 +169,7 @@ class rasterize(GdalAlgorithm):
                 arguments.append("-co TFW=YES")
             if len(bigtiff) > 0:
                 arguments.append("-co BIGTIFF=" + bigtiff)
-        if len(extra) > 0:
+        if extra and len(extra) > 0:
             arguments.append(extra)
         arguments.append('-l')
 
diff --git a/python/plugins/processing/algs/gdal/translate.py b/python/plugins/processing/algs/gdal/translate.py
index 13d3c76..996064a 100644
--- a/python/plugins/processing/algs/gdal/translate.py
+++ b/python/plugins/processing/algs/gdal/translate.py
@@ -76,7 +76,7 @@ class translate(GdalAlgorithm):
                                            self.tr('Output size is a percentage of input size'), True))
         self.addParameter(ParameterString(self.NO_DATA,
                                           self.tr("Nodata value, leave blank to take the nodata value from input"),
-                                          ''))
+                                          '', optional=True))
         self.addParameter(ParameterSelection(self.EXPAND,
                                              self.tr('Expand'), ['none', 'gray', 'rgb', 'rgba']))
         self.addParameter(ParameterCrs(self.SRS,
@@ -120,13 +120,17 @@ class translate(GdalAlgorithm):
         out = self.getOutputValue(translate.OUTPUT)
         outsize = unicode(self.getParameterValue(self.OUTSIZE))
         outsizePerc = unicode(self.getParameterValue(self.OUTSIZE_PERC))
-        noData = unicode(self.getParameterValue(self.NO_DATA))
+        noData = self.getParameterValue(self.NO_DATA)
+        if noData is not None:
+            noData = unicode(noData)
         expand = unicode(self.getParameterFromName(
             self.EXPAND).options[self.getParameterValue(self.EXPAND)])
         projwin = unicode(self.getParameterValue(self.PROJWIN))
         crsId = self.getParameterValue(self.SRS)
         sds = self.getParameterValue(self.SDS)
-        extra = unicode(self.getParameterValue(self.EXTRA))
+        extra = self.getParameterValue(self.EXTRA)
+        if extra is not None:
+            extra = unicode(extra)
         jpegcompression = unicode(self.getParameterValue(self.JPEGCOMPRESSION))
         predictor = unicode(self.getParameterValue(self.PREDICTOR))
         zlevel = unicode(self.getParameterValue(self.ZLEVEL))
@@ -148,7 +152,7 @@ class translate(GdalAlgorithm):
             arguments.append('-outsize')
             arguments.append(outsize)
             arguments.append(outsize)
-        if len(noData) > 0:
+        if noData and len(noData) > 0:
             arguments.append('-a_nodata')
             arguments.append(noData)
         if expand != 'none':
@@ -171,7 +175,7 @@ class translate(GdalAlgorithm):
             arguments.append(unicode(crsId))
         if sds:
             arguments.append('-sds')
-        if len(extra) > 0:
+        if extra and len(extra) > 0:
             arguments.append(extra)
         if GdalUtils.getFormatShortNameFromFilename(out) == "GTiff":
             arguments.append("-co COMPRESS=" + compress)
diff --git a/python/plugins/processing/algs/gdal/warp.py b/python/plugins/processing/algs/gdal/warp.py
index 15170e7..3ca5d3d 100644
--- a/python/plugins/processing/algs/gdal/warp.py
+++ b/python/plugins/processing/algs/gdal/warp.py
@@ -69,7 +69,7 @@ class warp(GdalAlgorithm):
                                        self.tr('Destination SRS'), ''))
         self.addParameter(ParameterString(self.NO_DATA,
                                           self.tr("Nodata value, leave blank to take the nodata value from input"),
-                                          '-9999'))
+                                          '', optional=True))
         self.addParameter(ParameterNumber(self.TR,
                                           self.tr('Output file resolution in target georeferenced units (leave 0 for no change)'),
                                           0.0, None, 0.0))
@@ -106,7 +106,9 @@ class warp(GdalAlgorithm):
         self.addOutput(OutputRaster(self.OUTPUT, self.tr('Reprojected')))
 
     def getConsoleCommands(self):
-        noData = unicode(self.getParameterValue(self.NO_DATA))
+        noData = self.getParameterValue(self.NO_DATA)
+        if noData is not None:
+            noData = unicode(noData)
         srccrs = self.getParameterValue(self.SOURCE_SRS)
         dstcrs = self.getParameterValue(self.DEST_SRS)
         jpegcompression = unicode(self.getParameterValue(self.JPEGCOMPRESSION))
@@ -126,7 +128,7 @@ class warp(GdalAlgorithm):
         if len(dstcrs) > 0:
             arguments.append('-t_srs')
             arguments.append(dstcrs)
-        if len(noData) > 0:
+        if noData and len(noData) > 0:
             arguments.append('-dstnodata')
             arguments.append(noData)
         arguments.append('-r')
@@ -139,8 +141,10 @@ class warp(GdalAlgorithm):
             arguments.append('-tr')
             arguments.append(unicode(self.getParameterValue(self.TR)))
             arguments.append(unicode(self.getParameterValue(self.TR)))
-        extra = unicode(self.getParameterValue(self.EXTRA))
-        if len(extra) > 0:
+        extra = self.getParameterValue(self.EXTRA)
+        if extra is not None:
+            extra = unicode(extra)
+        if extra and len(extra) > 0:
             arguments.append(extra)
         if GdalUtils.getFormatShortNameFromFilename(out) == "GTiff":
             arguments.append("-co COMPRESS=" + compress)
diff --git a/python/plugins/processing/algs/grass/GrassAlgorithm.py b/python/plugins/processing/algs/grass/GrassAlgorithm.py
index 60333e2..481084d 100644
--- a/python/plugins/processing/algs/grass/GrassAlgorithm.py
+++ b/python/plugins/processing/algs/grass/GrassAlgorithm.py
@@ -77,7 +77,7 @@ class GrassAlgorithm(GeoAlgorithm):
         return newone
 
     def getIcon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'grass.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'grass.svg'))
 
     def help(self):
         return False, 'http://grass.osgeo.org/grass64/manuals/' + self.grassName + '.html'
diff --git a/python/plugins/processing/algs/grass/GrassAlgorithmProvider.py b/python/plugins/processing/algs/grass/GrassAlgorithmProvider.py
index 45fc2d9..fe062cd 100644
--- a/python/plugins/processing/algs/grass/GrassAlgorithmProvider.py
+++ b/python/plugins/processing/algs/grass/GrassAlgorithmProvider.py
@@ -98,7 +98,7 @@ class GrassAlgorithmProvider(AlgorithmProvider):
         return 'grass'
 
     def getIcon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'grass.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'grass.svg'))
 
     def getSupportedOutputVectorLayerExtensions(self):
         return ['shp']
diff --git a/python/plugins/processing/algs/grass/GrassUtils.py b/python/plugins/processing/algs/grass/GrassUtils.py
index 76e7441..2d6c99e 100644
--- a/python/plugins/processing/algs/grass/GrassUtils.py
+++ b/python/plugins/processing/algs/grass/GrassUtils.py
@@ -86,7 +86,9 @@ class GrassUtils:
         if not isWindows() and not isMac():
             return ''
 
-        folder = ProcessingConfig.getSetting(GrassUtils.GRASS_FOLDER)
+        folder = ProcessingConfig.getSetting(GrassUtils.GRASS_FOLDER) or ''
+        if not os.path.exists(folder):
+            folder = None
         if folder is None:
             if isWindows():
                 testfolder = os.path.dirname(QgsApplication.prefixPath())
@@ -105,7 +107,9 @@ class GrassUtils:
 
     @staticmethod
     def grassWinShell():
-        folder = ProcessingConfig.getSetting(GrassUtils.GRASS_WIN_SHELL)
+        folder = ProcessingConfig.getSetting(GrassUtils.GRASS_WIN_SHELL) or ''
+        if not os.path.exists(folder):
+            folder = None
         if folder is None:
             folder = os.path.dirname(unicode(QgsApplication.prefixPath()))
             folder = os.path.join(folder, 'msys')
diff --git a/python/plugins/processing/algs/grass7/Grass7Algorithm.py b/python/plugins/processing/algs/grass7/Grass7Algorithm.py
index 3bea7f9..0843cb0 100644
--- a/python/plugins/processing/algs/grass7/Grass7Algorithm.py
+++ b/python/plugins/processing/algs/grass7/Grass7Algorithm.py
@@ -84,7 +84,7 @@ class Grass7Algorithm(GeoAlgorithm):
         return newone
 
     def getIcon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'grass.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'grass.svg'))
 
     def help(self):
         localDoc = None
diff --git a/python/plugins/processing/algs/grass7/Grass7AlgorithmProvider.py b/python/plugins/processing/algs/grass7/Grass7AlgorithmProvider.py
index c918247..32da9eb 100644
--- a/python/plugins/processing/algs/grass7/Grass7AlgorithmProvider.py
+++ b/python/plugins/processing/algs/grass7/Grass7AlgorithmProvider.py
@@ -52,10 +52,6 @@ class Grass7AlgorithmProvider(AlgorithmProvider):
                 self.getDescription(),
                 Grass7Utils.GRASS_FOLDER, self.tr('GRASS7 folder'),
                 Grass7Utils.grassPath(), valuetype=Setting.FOLDER))
-            ProcessingConfig.addSetting(Setting(
-                self.getDescription(),
-                Grass7Utils.GRASS_WIN_SHELL, self.tr('Msys folder'),
-                Grass7Utils.grassWinShell(), valuetype=Setting.FOLDER))
         ProcessingConfig.addSetting(Setting(
             self.getDescription(),
             Grass7Utils.GRASS_LOG_COMMANDS,
@@ -69,7 +65,6 @@ class Grass7AlgorithmProvider(AlgorithmProvider):
         AlgorithmProvider.unload(self)
         if isWindows() or isMac():
             ProcessingConfig.removeSetting(Grass7Utils.GRASS_FOLDER)
-            ProcessingConfig.removeSetting(Grass7Utils.GRASS_WIN_SHELL)
         ProcessingConfig.removeSetting(Grass7Utils.GRASS_LOG_COMMANDS)
         ProcessingConfig.removeSetting(Grass7Utils.GRASS_LOG_CONSOLE)
 
@@ -102,7 +97,7 @@ class Grass7AlgorithmProvider(AlgorithmProvider):
         return 'grass70'
 
     def getIcon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'grass.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'grass.svg'))
 
     def getSupportedOutputVectorLayerExtensions(self):
         return ['shp']
diff --git a/python/plugins/processing/algs/grass7/Grass7Utils.py b/python/plugins/processing/algs/grass7/Grass7Utils.py
index 8bf8ad8..79ac28d 100644
--- a/python/plugins/processing/algs/grass7/Grass7Utils.py
+++ b/python/plugins/processing/algs/grass7/Grass7Utils.py
@@ -45,7 +45,6 @@ class Grass7Utils:
     GRASS_REGION_YMAX = 'GRASS7_REGION_YMAX'
     GRASS_REGION_CELLSIZE = 'GRASS7_REGION_CELLSIZE'
     GRASS_FOLDER = 'GRASS7_FOLDER'
-    GRASS_WIN_SHELL = 'GRASS7_WIN_SHELL'
     GRASS_LOG_COMMANDS = 'GRASS7_LOG_COMMANDS'
     GRASS_LOG_CONSOLE = 'GRASS7_LOG_CONSOLE'
 
@@ -84,7 +83,9 @@ class Grass7Utils:
         if not isWindows() and not isMac():
             return ''
 
-        folder = ProcessingConfig.getSetting(Grass7Utils.GRASS_FOLDER)
+        folder = ProcessingConfig.getSetting(Grass7Utils.GRASS_FOLDER) or ''
+        if not os.path.exists(folder):
+            folder = None
         if folder is None:
             if isWindows():
                 testfolder = os.path.dirname(unicode(QgsApplication.prefixPath()))
@@ -102,21 +103,12 @@ class Grass7Utils:
         return folder
 
     @staticmethod
-    def grassWinShell():
-        folder = ProcessingConfig.getSetting(Grass7Utils.GRASS_WIN_SHELL)
-        if folder is None:
-            folder = os.path.dirname(unicode(QgsApplication.prefixPath()))
-            folder = os.path.join(folder, 'msys')
-        return folder
-
-    @staticmethod
     def grassDescriptionPath():
         return os.path.join(os.path.dirname(__file__), 'description')
 
     @staticmethod
     def createGrass7Script(commands):
         folder = Grass7Utils.grassPath()
-        shell = Grass7Utils.grassWinShell()
 
         script = Grass7Utils.grassScriptFilename()
         gisrc = userFolder() + os.sep + 'processing.gisrc7'  # FIXME: use temporary file
@@ -135,9 +127,6 @@ class Grass7Utils:
         output = open(script, 'w')
         output.write('set HOME=' + os.path.expanduser('~') + '\n')
         output.write('set GISRC=' + gisrc + '\n')
-        output.write('set GRASS_SH=' + shell + '\\bin\\sh.exe\n')
-        output.write('set PATH=' + shell + os.sep + 'bin;' + shell + os.sep
-                     + 'lib;' + '%PATH%\n')
         output.write('set WINGISBASE=' + folder + '\n')
         output.write('set GISBASE=' + folder + '\n')
         output.write('set GRASS_PROJSHARE=' + folder + os.sep + 'share'
diff --git a/python/plugins/processing/algs/otb/OTBSpecific_XMLLoading.py b/python/plugins/processing/algs/otb/OTBSpecific_XMLLoading.py
index 290b124..793246f 100644
--- a/python/plugins/processing/algs/otb/OTBSpecific_XMLLoading.py
+++ b/python/plugins/processing/algs/otb/OTBSpecific_XMLLoading.py
@@ -171,7 +171,7 @@ def adaptColorMapping(commands_list):
     The output of this algorithm must be in uint8.
     """
     indexInput = commands_list.index("-out")
-    commands_list[indexInput + 1] = commands_list[indexInput + 1] + " uint8"
+    commands_list[indexInput + 1] = commands_list[indexInput + 1] + '" "uint8"'
     return commands_list
 
 
@@ -188,7 +188,6 @@ def adaptStereoFramework(commands_list):
             argumentToRemove = commands_list2[index - 1]
             commands_list2.remove(item)
             commands_list2.remove(argumentToRemove)
-        #commands_list2.append(item)
     return commands_list2
 
 
diff --git a/python/plugins/processing/algs/otb/OTBUtils.py b/python/plugins/processing/algs/otb/OTBUtils.py
index cbba252..adc75e6 100644
--- a/python/plugins/processing/algs/otb/OTBUtils.py
+++ b/python/plugins/processing/algs/otb/OTBUtils.py
@@ -101,24 +101,15 @@ def findOtbLibPath():
 
 
 def otbLibPath():
-    folder = findOtbLibPath()
-    if folder is None:
-        folder = ProcessingConfig.getSetting(OTB_LIB_FOLDER)
-    return folder
+    return ProcessingConfig.getSetting(OTB_LIB_FOLDER) or ''
 
 
 def otbSRTMPath():
-    folder = ProcessingConfig.getSetting(OTB_SRTM_FOLDER)
-    if folder is None:
-        folder = ""
-    return folder
+    return ProcessingConfig.getSetting(OTB_SRTM_FOLDER) or ''
 
 
 def otbGeoidPath():
-    filepath = ProcessingConfig.getSetting(OTB_GEOID_FILE)
-    if filepath is None:
-        filepath = ""
-    return filepath
+    return ProcessingConfig.getSetting(OTB_GEOID_FILE) or ''
 
 
 def otbDescriptionPath():
diff --git a/python/plugins/processing/algs/qgis/Buffer.py b/python/plugins/processing/algs/qgis/Buffer.py
index 00fdb2b..db55b0d 100644
--- a/python/plugins/processing/algs/qgis/Buffer.py
+++ b/python/plugins/processing/algs/qgis/Buffer.py
@@ -58,7 +58,7 @@ def buffering(progress, writer, distance, field, useField, layer, dissolve,
 
             inGeom = QgsGeometry(inFeat.geometry())
             if inGeom.isGeosEmpty() or not inGeom.isGeosValid():
-                ProcessingLog.addToLog('Feature {} has empty or invalid geometry. Skipping...'.format(inFeat.id()), ProcessingLog.LOG_WARNING)
+                ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Feature {} has empty or invalid geometry. Skipping...'.format(inFeat.id()))
                 continue
             outGeom = inGeom.buffer(float(value), segments)
             if first:
@@ -83,7 +83,7 @@ def buffering(progress, writer, distance, field, useField, layer, dissolve,
                 value = distance
             inGeom = QgsGeometry(inFeat.geometry())
             if inGeom.isGeosEmpty() or not inGeom.isGeosValid():
-                ProcessingLog.addToLog('Feature {} has empty or invalid geometry. Skipping...'.format(inFeat.id()), ProcessingLog.LOG_WARNING)
+                ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Feature {} has empty or invalid geometry. Skipping...'.format(inFeat.id()))
                 continue
 
             outGeom = inGeom.buffer(float(value), segments)
diff --git a/python/plugins/processing/algs/qgis/Dissolve.py b/python/plugins/processing/algs/qgis/Dissolve.py
index 6c49490..b063416 100644
--- a/python/plugins/processing/algs/qgis/Dissolve.py
+++ b/python/plugins/processing/algs/qgis/Dissolve.py
@@ -128,18 +128,11 @@ class Dissolve(GeoAlgorithm):
             for key, value in myDict.items():
                 nElement += 1
                 progress.setPercentage(int(nElement * 100 / nFeat))
-                for i in range(len(value)):
-                    tmpInGeom = value[i]
-
-                    if i == 0:
-                        tmpOutGeom = tmpInGeom
-                    else:
-                        try:
-                            tmpOutGeom = QgsGeometry(
-                                tmpOutGeom.combine(tmpInGeom))
-                        except:
-                            raise GeoAlgorithmExecutionException(
-                                self.tr('Geometry exception while dissolving'))
+                try:
+                    tmpOutGeom = QgsGeometry.unaryUnion(value)
+                except:
+                    raise GeoAlgorithmExecutionException(
+                        self.tr('Geometry exception while dissolving'))
                 outFeat.setGeometry(tmpOutGeom)
                 outFeat.setAttributes(attrDict[key])
                 writer.addFeature(outFeat)
diff --git a/python/plugins/processing/algs/qgis/JoinAttributes.py b/python/plugins/processing/algs/qgis/JoinAttributes.py
index a03f118..3f5cf13 100644
--- a/python/plugins/processing/algs/qgis/JoinAttributes.py
+++ b/python/plugins/processing/algs/qgis/JoinAttributes.py
@@ -79,7 +79,7 @@ class JoinAttributes(GeoAlgorithm):
         cache = {}
         features = vector.features(layer2)
         total = 100.0 / len(features)
-        for current, feat in features:
+        for current, feat in enumerate(features):
             attrs = feat.attributes()
             joinValue2 = unicode(attrs[joinField2Index])
             if joinValue2 not in cache:
diff --git a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
index 25d211e..d2e1825 100644
--- a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
+++ b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
@@ -149,7 +149,7 @@ class QGISAlgorithmProvider(AlgorithmProvider):
 
     def __init__(self):
         AlgorithmProvider.__init__(self)
-        self._icon = QIcon(os.path.join(pluginPath, 'images', 'qgis.png'))
+        self._icon = QIcon(os.path.join(pluginPath, 'images', 'qgis.svg'))
 
         self.alglist = [SumLines(), PointsInPolygon(),
                         PointsInPolygonWeighted(), PointsInPolygonUnique(),
diff --git a/python/plugins/processing/algs/qgis/ZonalStatistics.py b/python/plugins/processing/algs/qgis/ZonalStatistics.py
index c2d35e5..4d09e4c 100644
--- a/python/plugins/processing/algs/qgis/ZonalStatistics.py
+++ b/python/plugins/processing/algs/qgis/ZonalStatistics.py
@@ -227,16 +227,24 @@ class ZonalStatistics(GeoAlgorithm):
             outFeat.setGeometry(geom)
 
             attrs = f.attributes()
-            attrs.insert(idxMin, float(masked.min()))
-            attrs.insert(idxMax, float(masked.max()))
-            attrs.insert(idxSum, float(masked.sum()))
+            v = float(masked.min())
+            attrs.insert(idxMin, None if numpy.isnan(v) else v)
+            v = float(masked.max())
+            attrs.insert(idxMax, None if numpy.isnan(v) else v)
+            v = float(masked.sum())
+            attrs.insert(idxSum, None if numpy.isnan(v) else v)
             attrs.insert(idxCount, int(masked.count()))
-            attrs.insert(idxMean, float(masked.mean()))
-            attrs.insert(idxStd, float(masked.std()))
+            v = float(masked.mean())
+            attrs.insert(idxMean, None if numpy.isnan(v) else v)
+            v = float(masked.std())
+            attrs.insert(idxStd, None if numpy.isnan(v) else v)
             attrs.insert(idxUnique, numpy.unique(masked.compressed()).size)
-            attrs.insert(idxRange, float(masked.max()) - float(masked.min()))
-            attrs.insert(idxVar, float(masked.var()))
-            attrs.insert(idxMedian, float(numpy.ma.median(masked)))
+            v = float(masked.max()) - float(masked.min())
+            attrs.insert(idxRange, None if numpy.isnan(v) else v)
+            v = float(masked.var())
+            attrs.insert(idxVar, None if numpy.isnan(v) else v)
+            v = float(numpy.ma.median(masked))
+            attrs.insert(idxMedian, None if numpy.isnan(v) else v)
             if hasSciPy:
                 attrs.insert(idxMode, float(mode(masked, axis=None)[0][0]))
 
diff --git a/python/plugins/processing/algs/r/RAlgorithm.py b/python/plugins/processing/algs/r/RAlgorithm.py
index 41ba75f..051db38 100644
--- a/python/plugins/processing/algs/r/RAlgorithm.py
+++ b/python/plugins/processing/algs/r/RAlgorithm.py
@@ -74,7 +74,7 @@ class RAlgorithm(GeoAlgorithm):
             self.defineCharacteristicsFromFile()
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/r.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/r.svg')
 
     def defineCharacteristicsFromScript(self):
         lines = self.script.split('\n')
diff --git a/python/plugins/processing/algs/r/RAlgorithmProvider.py b/python/plugins/processing/algs/r/RAlgorithmProvider.py
index dc25186..df6a30a 100644
--- a/python/plugins/processing/algs/r/RAlgorithmProvider.py
+++ b/python/plugins/processing/algs/r/RAlgorithmProvider.py
@@ -86,7 +86,7 @@ class RAlgorithmProvider(AlgorithmProvider):
             ProcessingConfig.removeSetting(RUtils.R_USE64)
 
     def getIcon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'r.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'r.svg'))
 
     def getDescription(self):
         return 'R scripts'
diff --git a/python/plugins/processing/algs/r/RUtils.py b/python/plugins/processing/algs/r/RUtils.py
index 999cfa2..60f791c 100644
--- a/python/plugins/processing/algs/r/RUtils.py
+++ b/python/plugins/processing/algs/r/RUtils.py
@@ -56,8 +56,11 @@ class RUtils:
         folder = ProcessingConfig.getSetting(RUtils.R_LIBS_USER)
         if folder is None:
             folder = unicode(os.path.join(userFolder(), 'rlibs'))
-        mkdir(folder)
-
+        try:
+            mkdir(folder)
+        except:
+            folder = unicode(os.path.join(userFolder(), 'rlibs'))
+            mkdir(folder)
         return os.path.abspath(unicode(folder))
 
     @staticmethod
@@ -65,7 +68,11 @@ class RUtils:
         folder = ProcessingConfig.getSetting(RUtils.RSCRIPTS_FOLDER)
         if folder is None:
             folder = unicode(os.path.join(userFolder(), 'rscripts'))
-        mkdir(folder)
+        try:
+            mkdir(folder)
+        except:
+            folder = unicode(os.path.join(userFolder(), 'rscripts'))
+            mkdir(folder)
 
         return os.path.abspath(folder)
 
diff --git a/python/plugins/processing/algs/taudem/TauDEMAlgorithm.py b/python/plugins/processing/algs/taudem/TauDEMAlgorithm.py
index de84551..a4a8d4b 100644
--- a/python/plugins/processing/algs/taudem/TauDEMAlgorithm.py
+++ b/python/plugins/processing/algs/taudem/TauDEMAlgorithm.py
@@ -59,7 +59,7 @@ class TauDEMAlgorithm(GeoAlgorithm):
         return newone
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristicsFromFile(self):
         lines = open(self.descriptionFile)
diff --git a/python/plugins/processing/algs/taudem/TauDEMAlgorithmProvider.py b/python/plugins/processing/algs/taudem/TauDEMAlgorithmProvider.py
index 62cd783..00f891a 100644
--- a/python/plugins/processing/algs/taudem/TauDEMAlgorithmProvider.py
+++ b/python/plugins/processing/algs/taudem/TauDEMAlgorithmProvider.py
@@ -71,7 +71,7 @@ class TauDEMAlgorithmProvider(AlgorithmProvider):
         return 'taudem'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def initializeSettings(self):
         AlgorithmProvider.initializeSettings(self)
diff --git a/python/plugins/processing/algs/taudem/dinfdistdown.py b/python/plugins/processing/algs/taudem/dinfdistdown.py
index bebc6de..8840a2b 100644
--- a/python/plugins/processing/algs/taudem/dinfdistdown.py
+++ b/python/plugins/processing/algs/taudem/dinfdistdown.py
@@ -65,7 +65,7 @@ class DinfDistDown(GeoAlgorithm):
     }
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('D-Infinity Distance Down')
diff --git a/python/plugins/processing/algs/taudem/dinfdistdown_multi.py b/python/plugins/processing/algs/taudem/dinfdistdown_multi.py
index 827092a..1f7b046 100644
--- a/python/plugins/processing/algs/taudem/dinfdistdown_multi.py
+++ b/python/plugins/processing/algs/taudem/dinfdistdown_multi.py
@@ -66,7 +66,7 @@ class DinfDistDownMulti(GeoAlgorithm):
     }
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('D-Infinity Distance Down (multifile)')
diff --git a/python/plugins/processing/algs/taudem/dinfdistup.py b/python/plugins/processing/algs/taudem/dinfdistup.py
index f8dad92..65896c7 100644
--- a/python/plugins/processing/algs/taudem/dinfdistup.py
+++ b/python/plugins/processing/algs/taudem/dinfdistup.py
@@ -66,7 +66,7 @@ class DinfDistUp(GeoAlgorithm):
     }
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('D-Infinity Distance Up')
diff --git a/python/plugins/processing/algs/taudem/dinfdistup_multi.py b/python/plugins/processing/algs/taudem/dinfdistup_multi.py
index 5e7f9b9..c548a65 100644
--- a/python/plugins/processing/algs/taudem/dinfdistup_multi.py
+++ b/python/plugins/processing/algs/taudem/dinfdistup_multi.py
@@ -67,7 +67,7 @@ class DinfDistUpMulti(GeoAlgorithm):
     }
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('D-Infinity Distance Up (multifile)')
diff --git a/python/plugins/processing/algs/taudem/dinftranslimaccum.py b/python/plugins/processing/algs/taudem/dinftranslimaccum.py
index 9fef119..9e87a34 100644
--- a/python/plugins/processing/algs/taudem/dinftranslimaccum.py
+++ b/python/plugins/processing/algs/taudem/dinftranslimaccum.py
@@ -56,7 +56,7 @@ class DinfTransLimAccum(GeoAlgorithm):
     OUT_CONCENTR_GRID = 'OUT_CONCENTR_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('D-Infinity Transport Limited Accumulation')
diff --git a/python/plugins/processing/algs/taudem/dinftranslimaccum2.py b/python/plugins/processing/algs/taudem/dinftranslimaccum2.py
index e5418fd..820d7e7 100644
--- a/python/plugins/processing/algs/taudem/dinftranslimaccum2.py
+++ b/python/plugins/processing/algs/taudem/dinftranslimaccum2.py
@@ -56,7 +56,7 @@ class DinfTransLimAccum2(GeoAlgorithm):
     OUT_CONCENTR_GRID = 'OUT_CONCENTR_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('D-Infinity Transport Limited Accumulation - 2')
diff --git a/python/plugins/processing/algs/taudem/dinftranslimaccum2_multi.py b/python/plugins/processing/algs/taudem/dinftranslimaccum2_multi.py
index 77f1b65..e15eafe 100644
--- a/python/plugins/processing/algs/taudem/dinftranslimaccum2_multi.py
+++ b/python/plugins/processing/algs/taudem/dinftranslimaccum2_multi.py
@@ -56,7 +56,7 @@ class DinfTransLimAccum2Multi(GeoAlgorithm):
     OUT_CONCENTR_GRID = 'OUT_CONCENTR_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('D-Infinity Transport Limited Accumulation - 2 (multifile)')
diff --git a/python/plugins/processing/algs/taudem/dinftranslimaccum_multi.py b/python/plugins/processing/algs/taudem/dinftranslimaccum_multi.py
index ea07957..8e9fa79 100644
--- a/python/plugins/processing/algs/taudem/dinftranslimaccum_multi.py
+++ b/python/plugins/processing/algs/taudem/dinftranslimaccum_multi.py
@@ -56,7 +56,7 @@ class DinfTransLimAccumMulti(GeoAlgorithm):
     OUT_CONCENTR_GRID = 'OUT_CONCENTR_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('D-Infinity Transport Limited Accumulation (multifile)')
diff --git a/python/plugins/processing/algs/taudem/dropanalysis.py b/python/plugins/processing/algs/taudem/dropanalysis.py
index 569bc56..89a7d2f 100644
--- a/python/plugins/processing/algs/taudem/dropanalysis.py
+++ b/python/plugins/processing/algs/taudem/dropanalysis.py
@@ -60,7 +60,7 @@ class DropAnalysis(GeoAlgorithm):
     STEPS = ['Logarithmic', 'Linear']
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('Stream Drop Analysis')
diff --git a/python/plugins/processing/algs/taudem/dropanalysis_multi.py b/python/plugins/processing/algs/taudem/dropanalysis_multi.py
index b947bf7..4f4138a 100644
--- a/python/plugins/processing/algs/taudem/dropanalysis_multi.py
+++ b/python/plugins/processing/algs/taudem/dropanalysis_multi.py
@@ -60,7 +60,7 @@ class DropAnalysisMulti(GeoAlgorithm):
     STEPS = ['Logarithmic', 'Linear']
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('Stream Drop Analysis (multifile)')
diff --git a/python/plugins/processing/algs/taudem/gridnet.py b/python/plugins/processing/algs/taudem/gridnet.py
index 23c3d5c..f704391 100644
--- a/python/plugins/processing/algs/taudem/gridnet.py
+++ b/python/plugins/processing/algs/taudem/gridnet.py
@@ -54,7 +54,7 @@ class GridNet(GeoAlgorithm):
     STRAHLER_GRID = 'STRAHLER_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('Grid Network')
diff --git a/python/plugins/processing/algs/taudem/gridnet_multi.py b/python/plugins/processing/algs/taudem/gridnet_multi.py
index 5d305ea..74cd3e2 100644
--- a/python/plugins/processing/algs/taudem/gridnet_multi.py
+++ b/python/plugins/processing/algs/taudem/gridnet_multi.py
@@ -54,7 +54,7 @@ class GridNetMulti(GeoAlgorithm):
     STRAHLER_GRID = 'STRAHLER_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('Grid Network (multifile)')
diff --git a/python/plugins/processing/algs/taudem/lengtharea.py b/python/plugins/processing/algs/taudem/lengtharea.py
index a520865..b0fd4ab 100644
--- a/python/plugins/processing/algs/taudem/lengtharea.py
+++ b/python/plugins/processing/algs/taudem/lengtharea.py
@@ -51,7 +51,7 @@ class LengthArea(GeoAlgorithm):
     STREAM_SOURCE_GRID = 'STREAM_SOURCE_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('Length Area Stream Source')
diff --git a/python/plugins/processing/algs/taudem/lengtharea_multi.py b/python/plugins/processing/algs/taudem/lengtharea_multi.py
index 60bf829..3ebff9c 100644
--- a/python/plugins/processing/algs/taudem/lengtharea_multi.py
+++ b/python/plugins/processing/algs/taudem/lengtharea_multi.py
@@ -51,7 +51,7 @@ class LengthAreaMulti(GeoAlgorithm):
     STREAM_SOURCE_GRID = 'STREAM_SOURCE_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('Length Area Stream Source (multifile)')
diff --git a/python/plugins/processing/algs/taudem/peukerdouglas.py b/python/plugins/processing/algs/taudem/peukerdouglas.py
index 239cc8a..145f78b 100644
--- a/python/plugins/processing/algs/taudem/peukerdouglas.py
+++ b/python/plugins/processing/algs/taudem/peukerdouglas.py
@@ -48,7 +48,7 @@ class PeukerDouglas(GeoAlgorithm):
     STREAM_SOURCE_GRID = 'STREAM_SOURCE_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('Peuker Douglas')
diff --git a/python/plugins/processing/algs/taudem/peukerdouglas_multi.py b/python/plugins/processing/algs/taudem/peukerdouglas_multi.py
index a95ccfb..6c97deb 100644
--- a/python/plugins/processing/algs/taudem/peukerdouglas_multi.py
+++ b/python/plugins/processing/algs/taudem/peukerdouglas_multi.py
@@ -50,7 +50,7 @@ class PeukerDouglasMulti(GeoAlgorithm):
     STREAM_SOURCE_GRID = 'STREAM_SOURCE_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('Peuker Douglas (multifile)')
diff --git a/python/plugins/processing/algs/taudem/slopearea.py b/python/plugins/processing/algs/taudem/slopearea.py
index 9feb652..b5fc7a9 100644
--- a/python/plugins/processing/algs/taudem/slopearea.py
+++ b/python/plugins/processing/algs/taudem/slopearea.py
@@ -51,7 +51,7 @@ class SlopeArea(GeoAlgorithm):
     SLOPE_AREA_GRID = 'SLOPE_AREA_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('Slope Area Combination')
diff --git a/python/plugins/processing/algs/taudem/slopearea_multi.py b/python/plugins/processing/algs/taudem/slopearea_multi.py
index 22a8a15..f0a0599 100644
--- a/python/plugins/processing/algs/taudem/slopearea_multi.py
+++ b/python/plugins/processing/algs/taudem/slopearea_multi.py
@@ -51,7 +51,7 @@ class SlopeAreaMulti(GeoAlgorithm):
     SLOPE_AREA_GRID = 'SLOPE_AREA_GRID'
 
     def getIcon(self):
-        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
+        return QIcon(os.path.dirname(__file__) + '/../../images/taudem.svg')
 
     def defineCharacteristics(self):
         self.name, self.i18n_name = self.trAlgorithm('Slope Area Combination (multifile)')
diff --git a/python/plugins/processing/core/GeoAlgorithm.py b/python/plugins/processing/core/GeoAlgorithm.py
index 0911859..597db29 100644
--- a/python/plugins/processing/core/GeoAlgorithm.py
+++ b/python/plugins/processing/core/GeoAlgorithm.py
@@ -385,7 +385,8 @@ class GeoAlgorithm:
                             return
         try:
             from qgis.utils import iface
-            self.crs = iface.mapCanvas().mapSettings().destinationCrs()
+            if iface is not None:
+                self.crs = iface.mapCanvas().mapSettings().destinationCrs()
         except:
             pass
 
diff --git a/python/plugins/processing/gui/CreateNewScriptAction.py b/python/plugins/processing/gui/CreateNewScriptAction.py
index 525e904..b0539f2 100644
--- a/python/plugins/processing/gui/CreateNewScriptAction.py
+++ b/python/plugins/processing/gui/CreateNewScriptAction.py
@@ -49,7 +49,7 @@ class CreateNewScriptAction(ToolboxAction):
         if self.scriptType == self.SCRIPT_PYTHON:
             return QIcon(os.path.join(pluginPath, 'images', 'script.png'))
         elif self.scriptType == self.SCRIPT_R:
-            return QIcon(os.path.join(pluginPath, 'images', 'r.png'))
+            return QIcon(os.path.join(pluginPath, 'images', 'r.svg'))
 
     def execute(self):
         dlg = None
diff --git a/python/plugins/processing/gui/GetScriptsAndModels.py b/python/plugins/processing/gui/GetScriptsAndModels.py
index 9bb98d9..d928f9d 100644
--- a/python/plugins/processing/gui/GetScriptsAndModels.py
+++ b/python/plugins/processing/gui/GetScriptsAndModels.py
@@ -74,7 +74,7 @@ class GetRScriptsAction(ToolboxAction):
         self.group = self.tr('Tools', 'GetRScriptsAction')
 
     def getIcon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'r.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'r.svg'))
 
     def execute(self):
         dlg = GetScriptsAndModelsDialog(GetScriptsAndModelsDialog.RSCRIPTS)
@@ -137,7 +137,7 @@ class GetScriptsAndModelsDialog(BASE, WIDGET):
         else:
             self.folder = RUtils.RScriptsFolder()
             self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/rscripts/'
-            self.icon = QIcon(os.path.join(pluginPath, 'images', 'r.png'))
+            self.icon = QIcon(os.path.join(pluginPath, 'images', 'r.svg'))
 
         self.lastSelectedItem = None
         self.updateToolbox = False
diff --git a/python/plugins/processing/gui/ProcessingToolbox.py b/python/plugins/processing/gui/ProcessingToolbox.py
index adc4e2d..2fc7c87 100644
--- a/python/plugins/processing/gui/ProcessingToolbox.py
+++ b/python/plugins/processing/gui/ProcessingToolbox.py
@@ -134,8 +134,6 @@ class ProcessingToolbox(BASE, WIDGET):
             hide = bool(text) and (text not in item.text(0).lower())
             if isinstance(item, TreeAlgorithmItem):
                 hide = hide and (text not in item.alg.commandLineName())
-                if item.alg.shortHelp() is not None:
-                    hide = hide and (text not in item.alg.shortHelp())
             item.setHidden(hide)
             return not hide
         else:
diff --git a/python/plugins/processing/images/CMakeLists.txt b/python/plugins/processing/images/CMakeLists.txt
index b480e3b..b54cb5f 100644
--- a/python/plugins/processing/images/CMakeLists.txt
+++ b/python/plugins/processing/images/CMakeLists.txt
@@ -1,3 +1,3 @@
-FILE(GLOB IMAGE_FILES *.png *.gif)
+FILE(GLOB IMAGE_FILES *.png *.gif *.svg)
 
 PLUGIN_INSTALL(processing ./images ${IMAGE_FILES})
diff --git a/python/plugins/processing/images/gdal.png b/python/plugins/processing/images/gdal.png
deleted file mode 100644
index 89a3f3b..0000000
Binary files a/python/plugins/processing/images/gdal.png and /dev/null differ
diff --git a/python/plugins/processing/images/gdal.svg b/python/plugins/processing/images/gdal.svg
new file mode 100644
index 0000000..f876aff
--- /dev/null
+++ b/python/plugins/processing/images/gdal.svg
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+]>
+<svg  version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="571.5" height="632.057" viewBox="0 0 571.5 632.057"
+	 overflow="visible" enable-background="new 0 0 571.5 632.057" xml:space="preserve">
+<g id="Layer_5">
+</g>
+<g id="Layer_6">
+	<ellipse fill="#71C9F1" cx="346.517" cy="406.618" rx="224.981" ry="225.439"/>
+	<path fill="#359946" d="M501.978,457.39c-7.509-0.713-16.236,0.223-23.391-2.537c-8.306-3.204-4.547-10.3-9.413-16.078
+		c-3.78-4.487-11.079-5.93-16.188-8.536c-6.96-3.549-13.698-7.636-21.302-9.71c-7.862-2.143-17.271,0.333-24.15,4.177
+		c-2.157,1.205-7.1,5.316-9.661,3.283c-2.681-2.127,2.007-10.977-4.186-8.791c-5.667,2-8.333,10.666-13,10
+		c-5.563-0.797-10.045-2.484-15.7-2.025c-4.935,0.4-9.862,1.645-13.318-2.984c-3.655-4.897-0.294-11.042-2.59-16.06
+		c-3.943-8.621-14.11-0.312-20.288-4.171c4.428-3.34,8.556-9.208,8.812-14.902c0.24-5.296-3.365-9.285-8.459-5.876
+		c-2.794,1.87-2.717,5.298-4.786,7.61c-3.579,3.998-22.032,5.008-23.392-2.131c-1.274-6.693-3.8-19.088-0.613-25.461
+		c2.46-4.92,5.587-10.722,11.14-12.62c5.662-1.937,13.416,0.266,19.726-1.347c5.419-1.385,11.471-3.187,16.794-0.577
+		c5.431,2.663,6.361,8.669,8.675,13.876c1.333,3,6.333,7,4.998-1.009c-1.043-6.257-6.906-13.907-3.835-20.018
+		c2.753-5.469,9.375-7.259,12.905-11.957c3.462-4.605,0.965-10.548,3.581-15.406c2.607-4.842,8.754-6.369,11.152-11.427
+		c1.169-2.466,6.492-16.992,11.812-12.393c2.256,1.95,0.915,4.433,4.449,1.971c1.443-1.005,6.797-4.77,3.601-6.54
+		c-2.938-1.626-8,0.977-9.614-3.112c-2.782-7.047,10.244-10.657,11.95-15.776c1-3,0.999-4-6.667-7
+		c-5.263-2.06-10.834-13.366-16.136-13.021c-2.959,0.193-2.355,3.443-4.236,3.981c-4.458,1.275-6.904-5.511-9.975-7.852
+		c-2.22-1.691-10.525-5.292-13.255-3.211c-6.569,5.007,11.048,30.222-1.377,34.982c-3.051,1.169-9.481-11.799-13.748-13.541
+		c-6.876-2.808-18.555-1.837-18.288-12.673c0.259-10.54,13.503-7.468,16.641-14.656c2.782-6.372-7.008-16.185-12.755-14.704
+		c-0.313,1.593,0.765,5.348-0.234,6.547c-3.135,3.749-22.685,0.086-26.976-1.256c-7.398-2.314-15.241-3.933-22.041-7.793
+		c-5.896-3.347-9.099-9.623-16.62-6.803c-5.333,2-8.581,4.748-13.247,6.749c-4.513,1.935-9.57,2.161-14.054,4.299
+		c-4.543,2.167-1.849,10.273-5.445,14.193c-4.375,4.767-11.717,4.507-17.641,5.074c-1.479,0.142-11.102,0.365-11.364,1.94
+		c-0.377,2.465,24.337-0.224,26.059-0.717c3.962-1.134,6.864-4.043,10.679-5.509c4.563-1.753,10.064-2.544,12.391,2.452
+		c2.72,5.866,0.49,11.602-1.584,17.235c-2.341,6.359-1.505,7.897,0.193,14.208c1.063,3.951,0.289,6.358-1.373,10.062
+		c-4.133,9.214-15.476,25.558-11.28,36.347c3.218,8.275,10.404,15.299,16.03,21.95c3.825,4.522,3.212,8.959,5.922,14.176
+		c2.562,4.931,6.369,9.652,9.468,14.285c4.448,6.649,5.391,15.301,10.732,21.386c4.689,5.344,18.895,14.808,26.259,15.046
+		c2.229,0.071,4.227-2.034,6.38-1.789c6.695,0.77,10.746,7.212,16.557,9.839c5.312,2.401,12.593,0.383,17.068,4.591
+		c5.602,5.266,6.109,13.242,14.608,15.555c4.236,1.151,9.679-0.793,13.622,1.16c11.421,5.661,3.7,18.943,0.003,26.387
+		c-3.837,7.723-7.906,16.742-6.265,25.596c1.417,7.646,7.29,12.614,11.329,18.841c3.502,5.398,4.498,12.508,10.363,16.07
+		c4.594,2.789,13.605,2.979,16.249,8.182c2.943,5.793-3.647,14.68-5.068,20.259c-1.802,7.076-3.995,14.092-6.196,21.056
+		c-2.197,6.953-5.879,11.785-8.91,18.124c-2.504,5.236-9.558,25.709,1.111,24.759c15.161-1.355,20.782-21.278,33.737-26.138
+		c2.666-1,25-17.666,29-21c4-3.332,14-7.332,15.333-11.332s6.333-7,8-14.001c1.917-8.052,14.624-10.232,20.124-15.672
+		c7.525-7.445,11.274-18.378,15.207-27.991c3.35-8.187,10.577-14.424,12.632-23.294C521.237,461.064,512.516,458.392,501.978,457.39
+		z"/>
+	<path fill="#359946" d="M381.378,381.335c-1.71-0.46-3.672-0.411-5.432-0.978c-2.658-0.856-4.965-2.606-7.574-3.604
+		c-2.751-1.053-5.575-1.834-8.521-2.048c-1.604-0.117-3.228-0.049-4.813,0.229c-1.477,0.259-3.017,0.697-4.387,1.315
+		c-0.578,0.261-1.629,0.807-1.259,1.641c0.655,1.472,4.881,0.516,6.075,0.517c4.407,0.004,9.582-0.109,13.225,2.781
+		c0.947,0.752,1.812,1.611,2.563,2.56c0.613,0.771,1.158,1.651,2.077,2.095c0.902,0.436,1.856-0.061,2.698-0.418
+		c1.194-0.506,2.403-0.981,3.641-1.37c1.015-0.318,2.294-0.438,3.014-1.312C383.285,382.015,382.271,381.576,381.378,381.335z"/>
+	<path fill="#359946" d="M401.687,385.114c-2.328-0.596-4.999,2.082-8.334,0.75c-3.021-1.209-3.718-2.699-5.646-3.062
+		c-1.204-0.227-3.259,0.418-1.688,1.812c2.719,2.412,4.67,4.588,8,6.084c2.071,0.93,7.254,0.213,9.25-0.918
+		C406.687,387.846,405.27,386.03,401.687,385.114z"/>
+	<path fill="#359946" d="M417.418,273.486c-0.908-0.569-4.107-7.395-6.731-1.956c-3.417,7.083,9.064,8.755,10.345,7.231
+		S417.771,273.707,417.418,273.486z"/>
+	<path fill="#359946" d="M360.747,219.091c-1.993-0.813-19.86-8.049-20.452-2.425c-0.387,3.669,6.869,4.285,9.104,4.869
+		c3.51,0.918,9.196,3.659,10.155,7.568c0.661,2.702-3.062,6.094,2.133,6.094c2.333,0,7.333,1.333,7.333,1.333s2.331,1.332,4.33,1
+		c5.634-0.933-3.676-9.816-5.043-11.32C365.747,223.395,364.427,220.593,360.747,219.091z"/>
+	<path fill="#359946" d="M309.146,212.979c-1.678-0.62-5.983-1.21-6.354-1.005c-3.8,2.109-3.879,3.164,0.234,5.171
+		c3.782,1.846,7.568,3.359,11.677,4.333c2.281,0.541,6.878,0.554,4.704-3.035C317.571,215.415,312.246,214.124,309.146,212.979z"/>
+	<path fill="#359946" d="M348.823,199.695c-1.944-1.491-4.894,0.116-6.754,0.966c-4.292,1.959-8.718,0.723-13.063,2.073
+		c-1.127,0.35-2.913,1.235-3.002,2.619c-0.118,1.815,2.478,2.298,3.74,2.786c1.955,0.756,3.552,2.407,5.803,1.95
+		c1.804-0.366,3.223-1.749,5.056-2.105c2.112-0.41,4.178-0.647,5.794-2.204C347.59,204.631,350.832,201.245,348.823,199.695z"/>
+	<path fill="#359946" d="M409.354,226.53c-0.277-1.943,0.044-3.902-0.289-5.833c-1.829-10.604-14.968-16.208-23.786-19.79
+		c-3.56-1.446-7.52-2.477-11.37-2.703c-5.047-0.295-11.717-0.849-16.163,2.083c-1.566,1.033-2.45,2.509-2.168,4.596
+		c0.491,3.619,7.262,2.939,9.767,3.551c7.157,1.748,13.058,5.072,18.678,9.865c8.422,7.184,15.936,13.401,26.332,17.563
+		c1.666,0.667,4.991,1.393,4.261-1.401C413.585,230.525,410.021,231.197,409.354,226.53z"/>
+	<path fill="#359946" d="M526.982,282.734c0.352,6.433,1.142,12.889,3.198,19.021c0.987,2.942,2.672,5.6,3.723,8.518
+		c2.473,6.87,1.067,14.3,2.423,21.351c1.335,6.941,5.996,12.545,8.022,19.24c1.876,6.197,0.695,13.385,3.337,19.332
+		c1.507,3.391,4.328,5.977,6.224,9.145c2.399,4.01,5.111,14.822,10.22,16.139c3.615,0.932,3.283-7.537,3.784-9.68
+		c0.519-2.219,1.267-4.58,1.886-6.961c-4.898-39.934-20.21-76.639-43.142-107.295C526.64,271.893,526.795,279.295,526.982,282.734z"
+		/>
+	<path fill="#359946" d="M476.633,224.922c0.477,2.124,1.054,4.656-0.107,5.572c-2.11,1.665-5.297-1.39-6.854-2.635
+		c-1.262-1.009-3.767-3.708-5.544-2.832c-3.024,1.491,7.355,8.955,8.257,9.812c1.441,1.37,2.495,3.188,4.04,4.431
+		c3.075,2.472,3.656-0.448,5.861-1.96c3.364-2.308,6.416,1.998,8.007,4.324c2.456,3.59,4.026,7.599,6.747,11.036
+		c3.116,3.936,6.173,7.852,8.763,12.208c2.714,4.562,5.375,9.192,8.843,13.237c2.25,2.625,6.559,4.244,7.52,3.403
+		c1.647-1.44-0.844-4.196-1.373-5.637c-1.469-4-4.137-7.383-6.099-11.132c-1.967-3.76-4.444-12.495-4.486-12.773
+		c-10.307-10.95-21.691-20.868-33.99-29.577C476.203,223.003,476.406,223.917,476.633,224.922z"/>
+	<path fill="#359946" d="M419.521,197.116c4.331,3.715,9.838,5.95,15.165,8.081c3.333,1.333,4.333,3,8.333,5
+		c4.945,2.473,9.567,5.014,14.826,6.81c1.517,0.518,5.319,2.592,6.841,1.523c0.674-0.474,0.79-1.88,0.596-3.397
+		c-15.574-9.72-32.418-17.584-50.229-23.287C415.21,192.163,417.981,195.796,419.521,197.116z"/>
+	<path fill="#CCCCCC" d="M56.772,483.438h65.061v106.465c-27.313,12.211-64.063,15.461-91.063-5.039
+		C7.581,567.256-5.479,522.768,2.21,481.368s31.643-63.137,56.78-70.381c25.137-7.246,53.529,0.877,61.512,6.357l-10.055,47.908
+		c-11.178-6.139-20.737-9.535-32.974-7.246c-29.954,5.607-24.806,69.16-17.152,82.807c6.198,11.051,11.09,10.201,11.09,10.201
+		l0.148-20.848l-14.787-0.148V483.438z"/>
+	<path fill="#CCCCCC" d="M225.77,420.364c-22.75-15.25-65.25-14.25-89.5-6.25l0.25,182c23.75,3.75,65.75,6.5,88.75-10.25
+		c24.713-17.998,33.25-48.25,33-84.5C258.013,464.114,248.52,435.614,225.77,420.364z M204.27,503.614c-0.5,44-15,47.75-15,47.75
+		v-96C189.27,455.364,205.27,458.614,204.27,503.614z"/>
+	<polygon fill="#CCCCCC" points="291.02,409.364 250.27,597.864 302.27,597.864 310.02,559.614 323.77,559.614 331.02,597.864
+		383.27,597.614 346.52,409.614 	"/>
+	<polygon fill="#CCCCCC" points="389.52,409.364 389.52,597.614 485.52,597.614 485.52,550.114 442.52,550.114 442.52,409.364 	"/>
+	<g>
+		<path d="M112.02,583.364c-7.25,3-22.75,6-35,6c-19.25,0-33.75-5.5-45-16.75c-14.5-14-22.25-39-21.75-68
+			c0.75-61.25,35.75-86.75,71.5-86.75c12.75,0,22.25,2.5,27.5,5l-5.75,28.25c-4.75-2.25-11-3.75-19.25-3.75
+			c-22.25,0-40,15.25-40,59.25c0,40.5,15.75,55,31,55c3,0,5.25-0.25,6.5-0.75v-40.75h-15v-26.75h45.25V583.364z"/>
+		<path d="M146.516,421.864c8.25-2,20.25-3.25,33.25-3.25c21.25,0,36,5,46.75,15c14.5,13,22,35.25,22,68c0,34-8.75,58.25-23.5,71.25
+			c-11.25,11-28,16.25-51.5,16.25c-10.25,0-20.5-1-27-1.75V421.864z M179.266,561.864c1.5,0.5,4,0.5,5.75,0.5
+			c15.75,0,29.5-15.5,29.5-62c0-34.5-9-55.5-28.75-55.5c-2.25,0-4.5,0-6.5,0.75V561.864z"/>
+		<path d="M302.018,549.364l-7.5,38.5h-31.75l36.5-168.5h39.25l32.75,168.5h-31.75l-7.25-38.5H302.018z M329.268,523.864l-5.5-35.25
+			c-1.75-10.25-4-27-5.5-38.25h-0.75c-1.75,11.25-4.25,28.75-6,38.5l-6.25,35H329.268z"/>
+		<path d="M399.766,419.364h32.75v140.75h43.25v27.75h-76V419.364z"/>
+	</g>
+</g>
+<g id="Layer_3">
+	<path fill="#ED1E3A" d="M182.65,173.129l-2.333,6.184l186.476,68.695c0.404-2.107,1.5-4.08,2.162-6.247L182.65,173.129z"/>
+	<path fill="#ED1E3A" d="M180.528,179.824l-33.894,195.825c2.202,1.482,4.432,2.82,6.716,4.102l34.414-198.825L180.528,179.824z"/>
+	<path fill="#ED1E3A" d="M244.787,288.181c-66.626,41.209-91.718,80.856-96.071,88.376c1.7,1.018,3.417,1.962,5.158,2.872
+		c10.307-16.118,37.901-52.546,94.204-86.861c51.214-31.214,96.002-40.895,117.844-43.891c0.354-1.78,1.219-3.4,2.071-5.071
+		C353.696,245.325,300.475,253.737,244.787,288.181z"/>
+	<polygon fill="#666667" points="263.86,51.352 183.091,103.005 168.93,51.652 249.699,0 	"/>
+	<path d="M175.983,114.397c0,0-12.522,3.461-23.303,9.845c-10.781,6.384-19.823,15.693-19.823,15.693l-34.207-57.5
+		c0,0,6.653-12.348,17.642-18.854c10.565-6.257,25.482-6.683,25.482-6.683L175.983,114.397z"/>
+	<path fill="#666667" d="M152.493,136.525c19.72-12.891,41.243-20.098,49.737-16.902c-5.473-2.507-27.143-10.826-50.188,2.244
+		c-23.858,13.531-26.183,34.557-26.165,42.379C126.953,157.471,136.976,146.669,152.493,136.525z"/>
+	<path fill="#989898" d="M205.773,125.483c0.139-0.985,0.084-1.885-0.177-2.681c-0.111-0.342-0.26-0.665-0.448-0.967
+		c-0.125-0.201-0.267-0.394-0.427-0.578c-0.318-0.367-0.707-0.697-1.167-0.988c-1.379-0.871-3.304-1.323-5.658-1.393
+		c-0.392-0.012-0.796-0.012-1.212-0.003c-0.831,0.018-1.708,0.08-2.626,0.18c-0.459,0.051-0.929,0.112-1.408,0.182
+		c-0.24,0.035-0.481,0.073-0.727,0.114c-0.488,0.081-0.987,0.171-1.494,0.271c-0.254,0.051-0.51,0.102-0.769,0.157
+		c-0.516,0.109-1.041,0.229-1.574,0.358c-10.13,2.447-23.218,8.3-35.594,16.39c-12.051,7.876-20.788,16.152-24.596,22.63
+		c-0.205,0.349-0.397,0.694-0.573,1.034c-0.177,0.339-0.339,0.673-0.486,1.001c-0.146,0.328-0.278,0.65-0.396,0.965
+		c-0.41,1.104-0.634,2.131-0.66,3.066c-0.008,0.268,0.001,0.527,0.026,0.78c0.147,1.511,0.884,2.74,2.263,3.611
+		c7.357,4.647,30.218-2.63,51.062-16.256c0.651-0.426,1.293-0.853,1.924-1.28C195.589,142.238,204.864,131.969,205.773,125.483z"/>
+	<rect x="141.008" y="160.14" transform="matrix(0.7021 0.7121 -0.7121 0.7021 164.3516 -70.1016)" width="49.895" height="2.455"/>
+
+		<rect x="155.701" y="153.297" transform="matrix(-0.2491 -0.9685 0.9685 -0.2491 75.9908 367.9678)" width="49.894" height="2.454"/>
+	<path d="M182.736,172.197l-22.197-40.319c-0.891,0.273-1.691,0.455-2.214,1.07l22.261,40.433L182.736,172.197z"/>
+	<circle cx="184.314" cy="176.851" r="6.662"/>
+	<polygon fill="#666667" points="110.624,151.075 26.927,204.696 13.282,152.997 96.979,99.375 	"/>
+	<path d="M97.479,128.201l2.529,3.574l23.545-15.261c-0.268-0.568-2.182-3.293-2.52-3.79L97.479,128.201z"/>
+	<path d="M157.986,89.501l2.529,3.574l23.546-15.261c-0.269-0.569-2.182-3.294-2.521-3.791L157.986,89.501z"/>
+</g>
+</svg>
diff --git a/python/plugins/processing/images/grass.png b/python/plugins/processing/images/grass.png
deleted file mode 100644
index ec8135c..0000000
Binary files a/python/plugins/processing/images/grass.png and /dev/null differ
diff --git a/python/plugins/processing/images/grass.svg b/python/plugins/processing/images/grass.svg
new file mode 100644
index 0000000..b4f71f9
--- /dev/null
+++ b/python/plugins/processing/images/grass.svg
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="70"
+   height="79.006187"
+   id="svg4088"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="grass.svg"
+   inkscape:export-filename="/home/vincent/Documents/developpement/grass/grass_splash/logo/logo_variant_bw_bg.png"
+   inkscape:export-xdpi="600"
+   inkscape:export-ydpi="600">
+  <defs
+     id="defs4090" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.39754282"
+     inkscape:cx="-279.82761"
+     inkscape:cy="37.538143"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1362"
+     inkscape:window-height="745"
+     inkscape:window-x="2"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
+  <metadata
+     id="metadata4093">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="logo"
+     inkscape:groupmode="layer"
+     id="layer1"
+     style="display:inline"
+     transform="translate(-337.04735,-464.78448)">
+    <g
+       transform="matrix(0.37476995,0,0,0.37476995,232.61522,307.09071)"
+       id="g5376"
+       inkscape:export-filename="/home/vincent/Documents/developpement/grass/grass_splash/logo/logo_variant_bg.png"
+       inkscape:export-xdpi="600"
+       inkscape:export-ydpi="600">
+      <g
+         inkscape:label="color"
+         id="g5378"
+         style="display:inline">
+        <path
+           id="path5380"
+           d="m 367.81011,602.52854 4.21781,4.2809 1.43857,-1.54392 -2.57138,-19.15924 0.21875,-3.09375 1.3125,-4.625 1.375,-4.25 1.5,-3.34375 4.875,8.1875 4.75,8.65625 1.05469,5.08007 6.62885,-6.5039 3.34766,-25.16992 7.03125,-34.0625 4.53125,-23.12499 9.1875,-18.21875 1.375,-3.78125 0.5,-2.21875 0.1875,-3.59375 -0.5625,-2.875 -1.3125,-2.59375 -2.40625,-2.40625 0.125,0.65625 1.1875,1.21875 1.09375,2.5625 0.125,2.0625 -1.5,4.125 -1.9375,4.4375 -4.15625,7.46875 2.3125,-17.25 0.65625,-9.06 [...]
+           style="fill:#009000;stroke:none;display:inline"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.82688445;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           d="m 297.50037,539.11859 -3,3 22.53125,22.53125 -2.96875,2.96875 22.5,22.5 -3,3 38.46875,38.46875 38.5,-38.46875 -3,-3 22.5,-22.5 -2.96875,-2.96875 22.53125,-22.53125 -3,-3 -74.5625,74.53125 -74.53125,-74.53125 z"
+           id="path5382" />
+        <path
+           inkscape:connector-curvature="0"
+           style="color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           d="m 372.03162,420.77484 -93.375,93.40625 93.375,93.40625 93.40625,-93.40625 -93.40625,-93.40625 z m 0,1.65625 91.75,91.75 -91.75,91.75 -91.75,-91.75 91.75,-91.75 z"
+           id="path5384" />
+        <g
+           style="display:inline"
+           id="g5386"
+           transform="translate(268.5353,413.93109)">
+          <path
+             inkscape:connector-curvature="0"
+             id="path5388"
+             d="m 30.875,210.40625 0,1.25 60.3125,0 0,-1.25 -60.3125,0 z"
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-backgro [...]
+          <path
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-backgro [...]
+             d="m 115.83638,210.40625 0,1.25 60.3125,0 0,-1.25 -60.3125,0 z"
+             id="path5390"
+             inkscape:connector-curvature="0" />
+        </g>
+      </g>
+      <g
+         id="g5392"
+         inkscape:label="grayscale_opaque"
+         style="display:none">
+        <path
+           sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+           inkscape:connector-curvature="0"
+           style="fill:#909090;fill-opacity:1;stroke:none;display:inline"
+           d="m 367.81011,602.52854 4.21781,4.2809 1.43857,-1.54392 -2.57138,-19.15924 0.21875,-3.09375 1.3125,-4.625 1.375,-4.25 1.5,-3.34375 4.875,8.1875 4.75,8.65625 1.05469,5.08007 6.62885,-6.5039 3.34766,-25.16992 7.03125,-34.0625 4.53125,-23.12499 9.1875,-18.21875 1.375,-3.78125 0.5,-2.21875 0.1875,-3.59375 -0.5625,-2.875 -1.3125,-2.59375 -2.40625,-2.40625 0.125,0.65625 1.1875,1.21875 1.09375,2.5625 0.125,2.0625 -1.5,4.125 -1.9375,4.4375 -4.15625,7.46875 2.3125,-17.25 0.65625,-9.06 [...]
+           id="path5394" />
+        <path
+           id="path5396"
+           d="m 297.50037,539.11859 -3,3 22.53125,22.53125 -2.96875,2.96875 22.5,22.5 -3,3 38.46875,38.46875 38.5,-38.46875 -3,-3 22.5,-22.5 -2.96875,-2.96875 22.53125,-22.53125 -3,-3 -74.5625,74.53125 -74.53125,-74.53125 z"
+           style="color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.82688445;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           inkscape:connector-curvature="0" />
+        <path
+           id="path5398"
+           d="m 372.03162,420.77484 -93.375,93.40625 93.375,93.40625 93.40625,-93.40625 -93.40625,-93.40625 z m 0,1.65625 91.75,91.75 -91.75,91.75 -91.75,-91.75 91.75,-91.75 z"
+           style="color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           inkscape:connector-curvature="0" />
+        <g
+           transform="translate(268.5353,413.93109)"
+           id="g5400"
+           style="display:inline">
+          <path
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-backgro [...]
+             d="m 30.875,210.40625 0,1.25 60.3125,0 0,-1.25 -60.3125,0 z"
+             id="path5402"
+             inkscape:connector-curvature="0" />
+          <path
+             inkscape:connector-curvature="0"
+             id="path5404"
+             d="m 115.83638,210.40625 0,1.25 60.3125,0 0,-1.25 -60.3125,0 z"
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-backgro [...]
+        </g>
+      </g>
+      <g
+         style="display:none"
+         inkscape:label="grayscale_transparent"
+         id="g5406">
+        <path
+           id="path5408"
+           d="m 367.81011,602.52854 4.21781,4.2809 1.43857,-1.54392 -2.57138,-19.15924 0.21875,-3.09375 1.3125,-4.625 1.375,-4.25 1.5,-3.34375 4.875,8.1875 4.75,8.65625 1.05469,5.08007 6.62885,-6.5039 3.34766,-25.16992 7.03125,-34.0625 4.53125,-23.12499 9.1875,-18.21875 1.375,-3.78125 0.5,-2.21875 0.1875,-3.59375 -0.5625,-2.875 -1.3125,-2.59375 -2.40625,-2.40625 0.125,0.65625 1.1875,1.21875 1.09375,2.5625 0.125,2.0625 -1.5,4.125 -1.9375,4.4375 -4.15625,7.46875 2.3125,-17.25 0.65625,-9.06 [...]
+           style="fill:#000000;fill-opacity:0.44075832;stroke:none;display:inline"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.82688445;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           d="m 297.50037,539.11859 -3,3 22.53125,22.53125 -2.96875,2.96875 22.5,22.5 -3,3 38.46875,38.46875 38.5,-38.46875 -3,-3 22.5,-22.5 -2.96875,-2.96875 22.53125,-22.53125 -3,-3 -74.5625,74.53125 -74.53125,-74.53125 z"
+           id="path5410" />
+        <path
+           inkscape:connector-curvature="0"
+           style="color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           d="m 372.03162,420.77484 -93.375,93.40625 93.375,93.40625 93.40625,-93.40625 -93.40625,-93.40625 z m 0,1.65625 91.75,91.75 -91.75,91.75 -91.75,-91.75 91.75,-91.75 z"
+           id="path5412" />
+        <g
+           style="display:inline"
+           id="g5414"
+           transform="translate(268.5353,413.93109)">
+          <path
+             inkscape:connector-curvature="0"
+             id="path5416"
+             d="m 30.875,210.40625 0,1.25 60.3125,0 0,-1.25 -60.3125,0 z"
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-backgro [...]
+          <path
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-backgro [...]
+             d="m 115.83638,210.40625 0,1.25 60.3125,0 0,-1.25 -60.3125,0 z"
+             id="path5418"
+             inkscape:connector-curvature="0" />
+        </g>
+      </g>
+      <g
+         style="display:none"
+         inkscape:label="white_transparent"
+         id="g5420">
+        <rect
+           sodipodi:insensitive="true"
+           ry="15.09564"
+           rx="15.09564"
+           y="307.29431"
+           x="32.395325"
+           height="437.77356"
+           width="679.30383"
+           id="rect5422"
+           style="color:#000000;fill:#c6c6c6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.125;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+        <path
+           id="path5424"
+           d="m 367.81011,602.52854 4.21781,4.2809 1.43857,-1.54392 -2.57138,-19.15924 0.21875,-3.09375 1.3125,-4.625 1.375,-4.25 1.5,-3.34375 4.875,8.1875 4.75,8.65625 1.05469,5.08007 6.62885,-6.5039 3.34766,-25.16992 7.03125,-34.0625 4.53125,-23.12499 9.1875,-18.21875 1.375,-3.78125 0.5,-2.21875 0.1875,-3.59375 -0.5625,-2.875 -1.3125,-2.59375 -2.40625,-2.40625 0.125,0.65625 1.1875,1.21875 1.09375,2.5625 0.125,2.0625 -1.5,4.125 -1.9375,4.4375 -4.15625,7.46875 2.3125,-17.25 0.65625,-9.06 [...]
+           style="fill:#ffffff;fill-opacity:0.43668123;stroke:none;display:inline"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.82688445;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           d="m 297.50037,539.11859 -3,3 22.53125,22.53125 -2.96875,2.96875 22.5,22.5 -3,3 38.46875,38.46875 38.5,-38.46875 -3,-3 22.5,-22.5 -2.96875,-2.96875 22.53125,-22.53125 -3,-3 -74.5625,74.53125 -74.53125,-74.53125 z"
+           id="path5426" />
+        <path
+           inkscape:connector-curvature="0"
+           style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           d="m 372.03162,420.77484 -93.375,93.40625 93.375,93.40625 93.40625,-93.40625 -93.40625,-93.40625 z m 0,1.65625 91.75,91.75 -91.75,91.75 -91.75,-91.75 91.75,-91.75 z"
+           id="path5428" />
+        <g
+           style="fill:#ffffff;fill-opacity:1;display:inline"
+           id="g5430"
+           transform="translate(268.5353,413.93109)">
+          <path
+             inkscape:connector-curvature="0"
+             id="path5432"
+             d="m 30.875,210.40625 0,1.25 60.3125,0 0,-1.25 -60.3125,0 z"
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-backgro [...]
+          <path
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-backgro [...]
+             d="m 115.83638,210.40625 0,1.25 60.3125,0 0,-1.25 -60.3125,0 z"
+             id="path5434"
+             inkscape:connector-curvature="0" />
+        </g>
+      </g>
+      <g
+         id="g5436"
+         inkscape:label="white_opaque"
+         style="display:none">
+        <rect
+           style="color:#000000;fill:#c6c6c6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.125;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="rect5438"
+           width="679.30383"
+           height="437.77356"
+           x="32.395325"
+           y="307.29431"
+           rx="15.09564"
+           ry="15.09564"
+           sodipodi:insensitive="true" />
+        <path
+           sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+           inkscape:connector-curvature="0"
+           style="fill:#ffffff;fill-opacity:1;stroke:none;display:inline"
+           d="m 367.81011,602.52854 4.21781,4.2809 1.43857,-1.54392 -2.57138,-19.15924 0.21875,-3.09375 1.3125,-4.625 1.375,-4.25 1.5,-3.34375 4.875,8.1875 4.75,8.65625 1.05469,5.08007 6.62885,-6.5039 3.34766,-25.16992 7.03125,-34.0625 4.53125,-23.12499 9.1875,-18.21875 1.375,-3.78125 0.5,-2.21875 0.1875,-3.59375 -0.5625,-2.875 -1.3125,-2.59375 -2.40625,-2.40625 0.125,0.65625 1.1875,1.21875 1.09375,2.5625 0.125,2.0625 -1.5,4.125 -1.9375,4.4375 -4.15625,7.46875 2.3125,-17.25 0.65625,-9.06 [...]
+           id="path5440" />
+        <path
+           id="path5442"
+           d="m 297.50037,539.11859 -3,3 22.53125,22.53125 -2.96875,2.96875 22.5,22.5 -3,3 38.46875,38.46875 38.5,-38.46875 -3,-3 22.5,-22.5 -2.96875,-2.96875 22.53125,-22.53125 -3,-3 -74.5625,74.53125 -74.53125,-74.53125 z"
+           style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.82688445;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           inkscape:connector-curvature="0" />
+        <path
+           id="path5444"
+           d="m 372.03162,420.77484 -93.375,93.40625 93.375,93.40625 93.40625,-93.40625 -93.40625,-93.40625 z m 0,1.65625 91.75,91.75 -91.75,91.75 -91.75,-91.75 91.75,-91.75 z"
+           style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           inkscape:connector-curvature="0" />
+        <g
+           transform="translate(268.5353,413.93109)"
+           id="g5446"
+           style="fill:#ffffff;fill-opacity:1;display:inline">
+          <path
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-backgro [...]
+             d="m 30.875,210.40625 0,1.25 60.3125,0 0,-1.25 -60.3125,0 z"
+             id="path5448"
+             inkscape:connector-curvature="0" />
+          <path
+             inkscape:connector-curvature="0"
+             id="path5450"
+             d="m 115.83638,210.40625 0,1.25 60.3125,0 0,-1.25 -60.3125,0 z"
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-backgro [...]
+        </g>
+      </g>
+    </g>
+  </g>
+</svg>
diff --git a/python/plugins/processing/images/qgis.png b/python/plugins/processing/images/qgis.png
deleted file mode 100644
index a35e7e7..0000000
Binary files a/python/plugins/processing/images/qgis.png and /dev/null differ
diff --git a/python/plugins/processing/images/qgis.svg b/python/plugins/processing/images/qgis.svg
new file mode 100644
index 0000000..e9becc4
--- /dev/null
+++ b/python/plugins/processing/images/qgis.svg
@@ -0,0 +1,286 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="59.266239"
+   height="65.359184"
+   id="svg4907"
+   version="1.1"
+   inkscape:version="0.48+devel r11668"
+   sodipodi:docname="logo-proposal.svg">
+  <defs
+     id="defs4909">
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4144">
+      <rect
+         style="fill:#000000;stroke:none"
+         id="rect4146"
+         width="42.875"
+         height="39.625"
+         x="565.16125"
+         y="646.18127"
+         transform="matrix(0.99990096,-0.01407388,0.01407388,0.99990096,0,0)" />
+    </clipPath>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5342-4-9-7"
+       id="linearGradient3970-6"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(156.08765,208.94407)"
+       x1="413.40717"
+       y1="477.57877"
+       x2="423.64282"
+       y2="463.79016" />
+    <linearGradient
+       id="linearGradient5342-4-9-7">
+      <stop
+         style="stop-color:#0d4100;stop-opacity:1;"
+         offset="0"
+         id="stop5344-0-0-6" />
+      <stop
+         style="stop-color:#129300;stop-opacity:1;"
+         offset="1"
+         id="stop5346-85-9-0" />
+    </linearGradient>
+    <linearGradient
+       y2="463.79016"
+       x2="423.64282"
+       y1="477.57877"
+       x1="413.40717"
+       gradientTransform="matrix(-0.28268074,-0.95921406,-0.95921406,0.28268074,1144.7424,948.30227)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4111"
+       xlink:href="#linearGradient5342-4-0-4"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient5342-4-0-4">
+      <stop
+         style="stop-color:#0d1d00;stop-opacity:1;"
+         offset="0"
+         id="stop5344-0-9-7" />
+      <stop
+         style="stop-color:#0d7200;stop-opacity:1;"
+         offset="1"
+         id="stop5346-85-5-3" />
+    </linearGradient>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4825-8">
+      <path
+         style="fill:#e4f363;fill-opacity:1;stroke:none"
+         d="m 485.06341,446.7935 c -9.77401,0.51743 -17.5625,8.97625 -17.5625,19.3125 0,10.66968 8.28361,19.3125 18.5,19.3125 1.1046,0 2.16736,-0.11879 3.21875,-0.3125 l 0,3.09375 c 0.085,1.31607 1.67268,4.12266 6.65625,4.15625 5.76986,0.0389 8.44866,-3.49777 8.9375,-4.5625 0.90942,-2.43008 0.73396,-3.98858 0.6875,-4.96875 -0.019,0.58818 -1.99576,4.1014 -5.09375,4.21875 -4.98011,0.18864 -4.4375,-0.71244 -4.4375,-2.03125 l 0,-2.625 c 5.12836,-3.43242 8.53125,-9.44688 8.53125,-16.28125 0,- [...]
+         id="path4827-5"
+         inkscape:connector-curvature="0"
+         inkscape:export-filename="/home/webmaster/Desktop/path3895-6-6-7-4-4-0_2.png"
+         inkscape:export-xdpi="300"
+         inkscape:export-ydpi="300" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter4776-5"
+       x="-0.33183911"
+       width="1.6636782"
+       y="-0.39338365"
+       height="1.7867672"
+       style="color-interpolation-filters:sRGB">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.65194979"
+         id="feGaussianBlur4778-0" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4947-8-4"
+       style="color-interpolation-filters:sRGB">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.0155639"
+         id="feGaussianBlur4949-0-5" />
+    </filter>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5342-4-9"
+       id="linearGradient3970"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(156.08765,208.94407)"
+       x1="413.40717"
+       y1="477.57877"
+       x2="423.64282"
+       y2="463.79016" />
+    <linearGradient
+       id="linearGradient5342-4-9">
+      <stop
+         style="stop-color:#0d4100;stop-opacity:1;"
+         offset="0"
+         id="stop5344-0-0" />
+      <stop
+         style="stop-color:#129300;stop-opacity:1;"
+         offset="1"
+         id="stop5346-85-9" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5342-4-0-4"
+       id="linearGradient3972"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.28268074,-0.95921406,-0.95921406,0.28268074,1144.7424,948.30227)"
+       x1="413.40717"
+       y1="477.57877"
+       x2="423.64282"
+       y2="463.79016" />
+    <linearGradient
+       id="linearGradient4887">
+      <stop
+         style="stop-color:#0d1d00;stop-opacity:1;"
+         offset="0"
+         id="stop4889" />
+      <stop
+         style="stop-color:#0d7200;stop-opacity:1;"
+         offset="1"
+         id="stop4891" />
+    </linearGradient>
+    <filter
+       inkscape:collect="always"
+       id="filter5427-2-5"
+       style="color-interpolation-filters:sRGB">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.48785405"
+         id="feGaussianBlur5429-2-8" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2.8"
+     inkscape:cx="31.572364"
+     inkscape:cy="28.045706"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     width="0px"
+     height="0px"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1920"
+     inkscape:window-height="1018"
+     inkscape:window-x="-8"
+     inkscape:window-y="-8"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata4912">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-293.22402,-451.11116)">
+    <path
+       style="opacity:0.30041151;fill:#000000;fill-opacity:1;stroke:#060000;stroke-width:0.60000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter5427-2-5)"
+       d="m 445.49832,443.64178 -13.43694,5.46836 3.53559,2.34117 c 0,0 -21.73596,25.20136 -26.72117,31.08815 l -9.37732,3.36622 7.94737,1.95465 2.1582,7.35242 2.83885,-9.42158 26.7609,-31.21072 2.97047,3.27344 L 445.49832,443.64178 Z"
+       id="path3895-6-6-7-4-6-2-7-5"
+       inkscape:connector-curvature="0"
+       inkscape:export-xdpi="300"
+       inkscape:export-ydpi="300"
+       inkscape:export-filename="/home/webmaster/Desktop/path3895-6-6-7-4-4-0_2.png"
+       transform="matrix(0.99958439,-0.02882794,0.02882794,0.99958439,-112.94886,26.451722)" />
+    <g
+       id="g3966"
+       transform="matrix(0.99990096,0.01407388,-0.01407388,0.99990096,-245.10157,-201.70028)">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3895-6-6-7-4-6-8-4"
+         d="m 597.71136,649.10637 -12.9375,6.3125 3.6875,2.09375 c 0,0 -19.96054,26.62963 -24.53125,32.84375 l -9.125,4 8.03125,1.40625 L 597.71136,649.10637 Z"
+         style="fill:url(#linearGradient3970);fill-opacity:1;stroke:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3895-6-6-7-4-6-8-4-5"
+         d="m 597.69396,649.11595 -2.39786,14.19425 -3.05074,-2.94525 c 0,0 -19.90106,26.67412 -24.56967,32.81503 l -1.25739,9.88354 -3.61917,-7.30616 L 597.69396,649.11595 Z"
+         style="fill:url(#linearGradient3972);fill-opacity:1;stroke:none" />
+    </g>
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter4947-8-4)"
+       d="m 322.14652,464.00363 c -9.77401,0.51743 -17.5625,8.97625 -17.5625,19.3125 0,10.66968 8.28361,19.3125 18.5,19.3125 1.1046,0 2.16736,-0.11879 3.21875,-0.3125 l 0,3.09375 c 0.085,1.31607 1.67268,4.12266 6.65625,4.15625 5.76986,0.0389 8.44866,-3.49777 8.9375,-4.5625 0.90942,-2.43008 0.73396,-3.98858 0.6875,-4.96875 -0.019,0.58818 -1.99576,4.1014 -5.09375,4.21875 -4.98011,0.18864 -4.4375,-0.71244 -4.4375,-2.03125 l 0,-2.625 c 5.12836,-3.43242 8.53125,-9.44688 8.53125,-16.28125 0,-1 [...]
+       id="path3050-3-9-3-4-2-4"
+       inkscape:export-filename="/home/webmaster/Desktop/path3895-6-6-7-4-4-0_2.png"
+       inkscape:export-xdpi="300"
+       inkscape:export-ydpi="300" />
+    <path
+       style="fill:#e4f363;fill-opacity:1;stroke:none"
+       d="m 321.61618,463.47329 c -9.77401,0.51743 -17.5625,8.97625 -17.5625,19.3125 0,10.66968 8.28361,19.3125 18.5,19.3125 1.1046,0 2.16736,-0.11879 3.21875,-0.3125 l 0,3.09375 c 0.085,1.31607 1.67268,4.12266 6.65625,4.15625 5.76986,0.0389 8.44866,-3.49777 8.9375,-4.5625 0.90942,-2.43008 0.73396,-3.98858 0.6875,-4.96875 -0.019,0.58818 -1.99576,4.1014 -5.09375,4.21875 -4.98011,0.18864 -4.4375,-0.71244 -4.4375,-2.03125 l 0,-2.625 c 5.12836,-3.43242 8.53125,-9.44688 8.53125,-16.28125 0,-1 [...]
+       id="path3050-3-9-3-2-3"
+       inkscape:connector-curvature="0"
+       inkscape:export-filename="/home/webmaster/Desktop/path3895-6-6-7-4-4-0_2.png"
+       inkscape:export-xdpi="300"
+       inkscape:export-ydpi="300" />
+    <path
+       id="path4738-5"
+       style="opacity:0.38271604;fill:#ffffff;stroke:none;filter:url(#filter4776-5)"
+       d="m 488.43401,448.93493 c 0,0 3.0052,0.53033 4.15425,1.23744 1.14905,0.70711 0.17678,2.65165 0.17678,2.65165 L 490.64372,452.91242 Z M 479.5,472.11218 c 0,0 2.375,-1.25 4,-1.4375 1.625,-0.1875 4.4375,-0.25 5.5625,0.0625 1.125,0.3125 3.3125,0.9375 3.5,1.25 0.1875,0.3125 1,3.25 1,3.25 l -2.5625,0.25 -1.8125,-2.0625 c 0,0 -2.6875,-1.625 -3.0625,-1.625 -0.375,0 -2.5625,-0.25 -3.375,-0.125 C 481.9375,471.79968 479.1875,471.98718 479.1875,471.98718 z m -10.50551,-11.04186 c -0.0152,-0. [...]
+       clip-path="url(#clipPath4825-8)"
+       mask="none"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="csccccssscccsscccscscccccccssccccscccssssssccsscsc"
+       transform="translate(-163.44724,16.679802)" />
+    <path
+       style="fill:none;stroke:none"
+       d="m 327.55368,480.31704 10.25,-13.75 3.1875,3.0625 2.34375,-14.40625 -13.03125,6.375 3.6875,2.09375 c 0,0 -4.79404,6.41727 -10,13.375"
+       id="path3895-6-6-7-4-4-0-2-0"
+       inkscape:connector-curvature="0"
+       inkscape:export-xdpi="300"
+       inkscape:export-ydpi="300"
+       sodipodi:nodetypes="ccccccc" />
+    <rect
+       style="opacity:0.39506172;fill:none;stroke:none"
+       id="rect5465-5-8"
+       width="57.375"
+       height="57.375"
+       x="295.11526"
+       y="454.49084"
+       inkscape:export-xdpi="94.117645"
+       inkscape:export-ydpi="94.117645"
+       inkscape:export-filename="/home/webmaster/Desktop/new_doc_128.png" />
+    <g
+       id="g3966-2"
+       transform="matrix(0.99990096,0.01407388,-0.01407388,0.99990096,-245.10157,-201.70028)"
+       clip-path="url(#clipPath4144)">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3895-6-6-7-4-6-8-4-4"
+         d="m 597.71136,649.10637 -12.9375,6.3125 3.6875,2.09375 c 0,0 -19.96054,26.62963 -24.53125,32.84375 l -9.125,4 8.03125,1.40625 L 597.71136,649.10637 Z"
+         style="fill:url(#linearGradient3970-6);fill-opacity:1;stroke:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3895-6-6-7-4-6-8-4-5-8"
+         d="m 597.69396,649.11595 -2.39786,14.19425 -3.05074,-2.94525 c 0,0 -19.90106,26.67412 -24.56967,32.81503 l -1.25739,9.88354 -3.61917,-7.30616 L 597.69396,649.11595 Z"
+         style="fill:url(#linearGradient4111);fill-opacity:1;stroke:none" />
+    </g>
+  </g>
+</svg>
diff --git a/python/plugins/processing/images/r.png b/python/plugins/processing/images/r.png
deleted file mode 100644
index e4af3fa..0000000
Binary files a/python/plugins/processing/images/r.png and /dev/null differ
diff --git a/python/plugins/processing/images/r.svg b/python/plugins/processing/images/r.svg
new file mode 100644
index 0000000..097e83e
--- /dev/null
+++ b/python/plugins/processing/images/r.svg
@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid" width="724" height="561" viewBox="0 0 724 561">
+  <defs>
+    <linearGradient id="gradientFill-1" x1="0" x2="1" y1="0" y2="1" gradientUnits="objectBoundingBox" spreadMethod="pad">
+      <stop offset="0" stop-color="rgb(203,206,208)" stop-opacity="1"/>
+      <stop offset="1" stop-color="rgb(132,131,139)" stop-opacity="1"/>
+    </linearGradient>
+    <linearGradient id="gradientFill-2" x1="0" x2="1" y1="0" y2="1" gradientUnits="objectBoundingBox" spreadMethod="pad">
+      <stop offset="0" stop-color="rgb(39,109,195)" stop-opacity="1"/>
+      <stop offset="1" stop-color="rgb(22,92,170)" stop-opacity="1"/>
+    </linearGradient>
+  </defs>
+  <path d="M361.453,485.937 C162.329,485.937 0.906,377.828 0.906,244.469 C0.906,111.109 162.329,3.000 361.453,3.000 C560.578,3.000 722.000,111.109 722.000,244.469 C722.000,377.828 560.578,485.937 361.453,485.937 ZM416.641,97.406 C265.289,97.406 142.594,171.314 142.594,262.484 C142.594,353.654 265.289,427.562 416.641,427.562 C567.992,427.562 679.687,377.033 679.687,262.484 C679.687,147.971 567.992,97.406 416.641,97.406 Z" fill="url(#gradientFill-1)" fill-rule="evenodd"/>
+  <path d="M550.000,377.000 C550.000,377.000 571.822,383.585 584.500,390.000 C588.899,392.226 596.510,396.668 602.000,402.500 C607.378,408.212 610.000,414.000 610.000,414.000 L696.000,559.000 L557.000,559.062 L492.000,437.000 C492.000,437.000 478.690,414.131 470.500,407.500 C463.668,401.969 460.755,400.000 454.000,400.000 C449.298,400.000 420.974,400.000 420.974,400.000 L421.000,558.974 L298.000,559.026 L298.000,152.938 L545.000,152.938 C545.000,152.938 657.500,154.967 657.500,262.000 C6 [...]
+</svg>
\ No newline at end of file
diff --git a/python/plugins/processing/images/taudem.png b/python/plugins/processing/images/taudem.png
deleted file mode 100644
index 4860ca8..0000000
Binary files a/python/plugins/processing/images/taudem.png and /dev/null differ
diff --git a/python/plugins/processing/images/taudem.svg b/python/plugins/processing/images/taudem.svg
new file mode 100644
index 0000000..0a045c0
--- /dev/null
+++ b/python/plugins/processing/images/taudem.svg
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg3399"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   width="25.4mm"
+   height="25.4mm"
+   viewBox="0 0 89.999998 89.999999"
+   sodipodi:docname="taudem.svg">
+  <metadata
+     id="metadata3405">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs3403">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5605">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop5607" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop5610" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5613">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop5615" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop5617" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5607"
+       osb:paint="solid">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop5609" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5589"
+       osb:paint="solid">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop5591" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4138">
+      <stop
+         style="stop-color:#990000;stop-opacity:1;"
+         offset="0"
+         id="stop4140" />
+      <stop
+         style="stop-color:#6e0000;stop-opacity:1"
+         offset="1"
+         id="stop4142" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4138"
+       id="linearGradient4144"
+       x1="0.33333334"
+       y1="700.4278"
+       x2="90"
+       y2="699.9278"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(0,-654.09448)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5589"
+       id="linearGradient5593"
+       x1="54.945377"
+       y1="51.502598"
+       x2="85.780338"
+       y2="51.502598"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5613"
+       id="linearGradient5619"
+       x1="54.445377"
+       y1="51.502598"
+       x2="86.280338"
+       y2="51.502598"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5605"
+       id="radialGradient5612"
+       cx="71.826358"
+       cy="50.677773"
+       fx="71.826358"
+       fy="50.677773"
+       r="15.378681"
+       gradientTransform="matrix(1,0,0,0.317652,0,34.579877)"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1366"
+     inkscape:window-height="714"
+     id="namedview3401"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     units="mm"
+     inkscape:zoom="2.1213203"
+     inkscape:cx="-78.093983"
+     inkscape:cy="46.505347"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="layer1" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="back">
+    <rect
+       style="fill:url(#linearGradient4144);fill-opacity:1;stroke:none;image-rendering:optimizeQuality"
+       id="rect3417"
+       width="90"
+       height="90"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="tau">
+    <g
+       transform="matrix(1.0471214,0,0,0.95499911,-4.424218e-7,-654.09448)"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:152.20530701px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       id="text3409">
+      <path
+         d="m 50.072425,707.8088 -2.155251,21.32955 q -0.520233,5.57392 -0.520233,11.14785 0,10.62761 2.452527,12.9315 2.526846,2.22957 5.722562,2.22957 7.134624,0 8.472366,-8.9926 l 2.749803,0 q -2.452527,20.66069 -16.424498,20.66069 -14.640843,0 -14.640843,-16.7961 0,-8.47236 1.635018,-21.10659 l 2.749803,-21.40387 -7.357581,0 q -6.094158,0 -9.512831,2.08093 -3.344355,2.00661 -6.242796,8.17509 l -2.675484,0 q 2.378208,-8.17509 5.648244,-12.93151 3.270036,-4.83073 6.242795,-6.46575 2.97 [...]
+         id="path3336"
+         inkscape:connector-curvature="0" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="dem">
+    <text
+       xml:space="preserve"
+       style="font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:12.07694149px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans Bold Italic';letter-spacing:0px;word-spacing:0px;opacity:0.766;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.966;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;"
+       x="56.677109"
+       y="55.079842"
+       id="text4139"
+       sodipodi:linespacing="125%"
+       transform="scale(0.97457262,1.0260908)"><tspan
+         sodipodi:role="line"
+         id="tspan4141"
+         x="56.677109"
+         y="55.079842"
+         style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.966;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-linejoin:round;stroke-linecap:round;">DEM</tspan></text>
+  </g>
+</svg>
diff --git a/python/plugins/processing/modeler/ModelerAlgorithm.py b/python/plugins/processing/modeler/ModelerAlgorithm.py
index 2e7a743..10a43dc 100644
--- a/python/plugins/processing/modeler/ModelerAlgorithm.py
+++ b/python/plugins/processing/modeler/ModelerAlgorithm.py
@@ -375,10 +375,11 @@ class ModelerAlgorithm(GeoAlgorithm):
                 if param.name in alg.params:
                     value = self.resolveValue(alg.params[param.name])
                 else:
-                    iface.messageBar().pushMessage(self.tr("Warning"),
-                                                   self.tr("Parameter %s in algorithm %s in the model is run with default value! Edit the model to make sure that this is correct." % (param.name, alg.name)),
-                                                   QgsMessageBar.WARNING, 4)
-                    value = None
+                    if iface is not None:
+                        iface.messageBar().pushMessage(self.tr("Warning"),
+                                                       self.tr("Parameter %s in algorithm %s in the model is run with default value! Edit the model to make sure that this is correct.") % (param.name, alg.name),
+                                                       QgsMessageBar.WARNING, 4)
+                    value = param.default
                 if value is None and isinstance(param, ParameterExtent):
                     value = self.getMinCoveringExtent()
                 # We allow unexistent filepaths, since that allows
diff --git a/python/plugins/processing/modeler/ModelerParametersDialog.py b/python/plugins/processing/modeler/ModelerParametersDialog.py
index a669261..499ed58 100644
--- a/python/plugins/processing/modeler/ModelerParametersDialog.py
+++ b/python/plugins/processing/modeler/ModelerParametersDialog.py
@@ -99,10 +99,12 @@ class ModelerParametersDialog(QDialog):
             if param.isAdvanced:
                 self.advancedButton = QPushButton()
                 self.advancedButton.setText(self.tr('Show advanced parameters'))
-                self.advancedButton.setMaximumWidth(150)
                 self.advancedButton.clicked.connect(
                     self.showAdvancedParametersClicked)
-                self.verticalLayout.addWidget(self.advancedButton)
+                advancedButtonHLayout = QHBoxLayout()
+                advancedButtonHLayout.addWidget(self.advancedButton)
+                advancedButtonHLayout.addStretch()
+                self.verticalLayout.addLayout(advancedButtonHLayout)
                 break
         for param in self._alg.parameters:
             if param.hidden:
@@ -417,7 +419,7 @@ class ModelerParametersDialog(QDialog):
                 if param.name in alg.params:
                     value = alg.params[param.name]
                 else:
-                    value = None
+                    value = param.default
                 if isinstance(param, (
                         ParameterRaster,
                         ParameterVector,
diff --git a/python/testing/CMakeLists.txt b/python/testing/CMakeLists.txt
index 8a5d1b4..a44bdec 100644
--- a/python/testing/CMakeLists.txt
+++ b/python/testing/CMakeLists.txt
@@ -1,6 +1,6 @@
 # See ../CMakeLists.txt for info on staged-plugins* and clean-staged-plugins targets
 
-SET (QGIS_PYTHON_DIR ${QGIS_DATA_DIR}/python)
+SET(QGIS_PYTHON_DIR ${PYTHON_SITE_PACKAGES_DIR}/qgis)
 SET (PYTHON_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/python)
 
 SET(PY_FILES
diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp
index 8059bbc..928d3cb 100644
--- a/src/app/qgisapp.cpp
+++ b/src/app/qgisapp.cpp
@@ -10875,8 +10875,9 @@ void QgisApp::namSetup()
 #endif
 }
 
-void QgisApp::namAuthenticationRequired( QNetworkReply *reply, QAuthenticator *auth )
+void QgisApp::namAuthenticationRequired( QNetworkReply *inReply, QAuthenticator *auth )
 {
+  QPointer<QNetworkReply> reply( inReply );
   Q_ASSERT( qApp->thread() == QThread::currentThread() );
 
   QString username = auth->user();
@@ -10911,7 +10912,7 @@ void QgisApp::namAuthenticationRequired( QNetworkReply *reply, QAuthenticator *a
     if ( !ok )
       return;
 
-    if ( reply->isFinished() )
+    if ( reply.isNull() || reply->isFinished() )
       return;
 
     if ( auth->user() != username || ( password != auth->password() && !password.isNull() ) )
diff --git a/src/app/qgsattributetabledialog.cpp b/src/app/qgsattributetabledialog.cpp
index 33ae17b..63bad96 100644
--- a/src/app/qgsattributetabledialog.cpp
+++ b/src/app/qgsattributetabledialog.cpp
@@ -343,13 +343,13 @@ void QgsAttributeTableDialog::updateFieldFromExpression()
 {
   bool filtered = mMainView->filterMode() != QgsAttributeTableFilterModel::ShowAll;
   QgsFeatureIds filteredIds = filtered ? mMainView->filteredFeatures() : QgsFeatureIds();
-  runFieldCalculation( mLayer, mFieldCombo->currentText(), mUpdateExpressionText->currentField(), filteredIds );
+  runFieldCalculation( mLayer, mFieldCombo->currentText(), mUpdateExpressionText->asExpression(), filteredIds );
 }
 
 void QgsAttributeTableDialog::updateFieldFromExpressionSelected()
 {
   QgsFeatureIds filteredIds = mLayer->selectedFeaturesIds();
-  runFieldCalculation( mLayer, mFieldCombo->currentText(), mUpdateExpressionText->currentField(), filteredIds );
+  runFieldCalculation( mLayer, mFieldCombo->currentText(), mUpdateExpressionText->asExpression(), filteredIds );
 }
 
 void QgsAttributeTableDialog::runFieldCalculation( QgsVectorLayer* layer, const QString& fieldName, const QString& expression, const QgsFeatureIds& filteredIds )
diff --git a/src/app/qgsrasterlayerproperties.cpp b/src/app/qgsrasterlayerproperties.cpp
index 29b4971..7caaac2 100644
--- a/src/app/qgsrasterlayerproperties.cpp
+++ b/src/app/qgsrasterlayerproperties.cpp
@@ -30,7 +30,6 @@
 #include "qgsmapcanvas.h"
 #include "qgsmaplayerregistry.h"
 #include "qgsmaplayerstyleguiutils.h"
-#include "qgsmaplayerstylemanager.h"
 #include "qgsmaprenderer.h"
 #include "qgsmaptoolemitpoint.h"
 #include "qgsmaptopixel.h"
@@ -106,6 +105,8 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer* lyr, QgsMapCanv
   connect( lyr->styleManager(), SIGNAL( currentStyleChanged( QString ) ), this, SLOT( syncToLayer() ) );
 
   connect( this, SIGNAL( accepted() ), this, SLOT( apply() ) );
+  connect( this, SIGNAL( rejected() ), this, SLOT( onCancel() ) );
+
   connect( buttonBox->button( QDialogButtonBox::Apply ), SIGNAL( clicked() ), this, SLOT( apply() ) );
 
   connect( mOptionsStackedWidget, SIGNAL( currentChanged( int ) ), this, SLOT( mOptionsStackedWidget_CurrentChanged( int ) ) );
@@ -1707,6 +1708,8 @@ void QgsRasterLayerProperties::loadStyle_clicked()
   if ( !fileName.endsWith( ".qml", Qt::CaseInsensitive ) )
     fileName += ".qml";
 
+  mOldStyle = mRasterLayer->styleManager()->style( mRasterLayer->styleManager()->currentStyle() );
+
   bool defaultLoadedFlag = false;
   QString message = mRasterLayer->loadNamedStyle( fileName, defaultLoadedFlag );
   if ( defaultLoadedFlag )
@@ -1776,4 +1779,16 @@ bool QgsRasterLayerProperties::rasterIsMultiBandColor()
   return mRasterLayer && nullptr != dynamic_cast<QgsMultiBandColorRenderer*>( mRasterLayer->renderer() );
 }
 
-
+void QgsRasterLayerProperties::onCancel()
+{
+  if ( mOldStyle.xmlData() != mRasterLayer->styleManager()->style( mRasterLayer->styleManager()->currentStyle() ).xmlData() )
+  {
+    // need to reset style to previous - style applied directly to the layer (not in apply())
+    QString myMessage;
+    QDomDocument doc( "qgis" );
+    int errorLine, errorColumn;
+    doc.setContent( mOldStyle.xmlData(), false, &myMessage, &errorLine, &errorColumn );
+    mRasterLayer->importNamedStyle( doc, myMessage );
+    syncToLayer();
+  }
+}
diff --git a/src/app/qgsrasterlayerproperties.h b/src/app/qgsrasterlayerproperties.h
index 0dd9b74..cacb0dc 100644
--- a/src/app/qgsrasterlayerproperties.h
+++ b/src/app/qgsrasterlayerproperties.h
@@ -25,6 +25,7 @@
 #include "qgsmaptool.h"
 #include "qgscolorrampshader.h"
 #include "qgscontexthelp.h"
+#include "qgsmaplayerstylemanager.h"
 
 class QgsMapLayer;
 class QgsMapCanvas;
@@ -57,6 +58,8 @@ class APP_EXPORT QgsRasterLayerProperties : public QgsOptionsDialogBase, private
     //TODO: Verify that these all need to be public
     /** \brief Applies the settings made in the dialog without closing the box */
     void apply();
+    /** Called when cancel button is pressed */
+    void onCancel();
     /** \brief Slot to update layer display name as original is edited. */
     void on_mLayerOrigNameLineEd_textEdited( const QString& text );
     /** \brief this slot asks the rasterlayer to construct pyramids */
@@ -186,5 +189,9 @@ class APP_EXPORT QgsRasterLayerProperties : public QgsOptionsDialogBase, private
     QgsRasterHistogramWidget* mHistogramWidget;
 
     QVector<bool> mTransparencyToEdited;
+
+    /** Previous layer style. Used to reset style to previous state if new style
+     * was loaded but dialog is cancelled */
+    QgsMapLayerStyle mOldStyle;
 };
 #endif
diff --git a/src/app/qgsstatisticalsummarydockwidget.cpp b/src/app/qgsstatisticalsummarydockwidget.cpp
index e2c7e97..b5e93ca 100644
--- a/src/app/qgsstatisticalsummarydockwidget.cpp
+++ b/src/app/qgsstatisticalsummarydockwidget.cpp
@@ -107,7 +107,7 @@ QgsStatisticalSummaryDockWidget::~QgsStatisticalSummaryDockWidget()
 
 void QgsStatisticalSummaryDockWidget::refreshStatistics()
 {
-  if ( !mLayer || !mFieldExpressionWidget->isValidExpression() )
+  if ( !mLayer || ( mFieldExpressionWidget->isExpression() && !mFieldExpressionWidget->isValidExpression() ) )
   {
     mStatisticsTable->setRowCount( 0 );
     return;
diff --git a/src/app/qgsvectorlayerproperties.cpp b/src/app/qgsvectorlayerproperties.cpp
index 1b8ddb6..b3a260e 100644
--- a/src/app/qgsvectorlayerproperties.cpp
+++ b/src/app/qgsvectorlayerproperties.cpp
@@ -37,7 +37,6 @@
 #include "qgslogger.h"
 #include "qgsmaplayerregistry.h"
 #include "qgsmaplayerstyleguiutils.h"
-#include "qgsmaplayerstylemanager.h"
 #include "qgspluginmetadata.h"
 #include "qgspluginregistry.h"
 #include "qgsproject.h"
@@ -660,6 +659,17 @@ void QgsVectorLayerProperties::onCancel()
 
     layer->setSubsetString( mOriginalSubsetSQL );
   }
+
+  if ( mOldStyle.xmlData() != layer->styleManager()->style( layer->styleManager()->currentStyle() ).xmlData() )
+  {
+    // need to reset style to previous - style applied directly to the layer (not in apply())
+    QString myMessage;
+    QDomDocument doc( "qgis" );
+    int errorLine, errorColumn;
+    doc.setContent( mOldStyle.xmlData(), false, &myMessage, &errorLine, &errorColumn );
+    layer->importNamedStyle( doc, myMessage );
+    syncToLayer();
+  }
 }
 
 void QgsVectorLayerProperties::on_pbnQueryBuilder_clicked()
@@ -826,6 +836,8 @@ void QgsVectorLayerProperties::loadStyle_clicked()
     return;
   }
 
+  mOldStyle = layer->styleManager()->style( layer->styleManager()->currentStyle() );
+
   QString myMessage;
   bool defaultLoadedFlag = false;
 
diff --git a/src/app/qgsvectorlayerproperties.h b/src/app/qgsvectorlayerproperties.h
index ff144e3..67ae134 100644
--- a/src/app/qgsvectorlayerproperties.h
+++ b/src/app/qgsvectorlayerproperties.h
@@ -30,6 +30,7 @@
 #include "qgsmapcanvas.h"
 #include "qgscontexthelp.h"
 #include "qgsexpressionbuilderdialog.h"
+#include "qgsmaplayerstylemanager.h"
 
 class QgsMapLayer;
 
@@ -187,6 +188,10 @@ class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private
     //! List of joins of a layer at the time of creation of the dialog. Used to return joins to previous state if dialog is cancelled
     QList< QgsVectorJoinInfo > mOldJoins;
 
+    /** Previous layer style. Used to reset style to previous state if new style
+     * was loaded but dialog is cancelled */
+    QgsMapLayerStyle mOldStyle;
+
     void initDiagramTab();
 
     /** Buffer pixmap which takes the picture of renderers before they are assigned to the vector layer*/
diff --git a/src/core/composer/qgsatlascomposition.cpp b/src/core/composer/qgsatlascomposition.cpp
index 97be7cf..fbdfeea 100644
--- a/src/core/composer/qgsatlascomposition.cpp
+++ b/src/core/composer/qgsatlascomposition.cpp
@@ -166,23 +166,10 @@ class FieldSorter
 
     bool operator()( const QPair< QgsFeatureId, QString > & id1, const QPair< QgsFeatureId, QString >& id2 )
     {
-      bool result = true;
-
-      if ( mKeys[ id1.first ].type() == QVariant::Int )
-      {
-        result = mKeys[ id1.first ].toInt() < mKeys[ id2.first ].toInt();
-      }
-      else if ( mKeys[ id1.first ].type() == QVariant::Double )
-      {
-        result = mKeys[ id1.first ].toDouble() < mKeys[ id2.first ].toDouble();
-      }
-      else if ( mKeys[ id1.first ].type() == QVariant::String )
-      {
-        result = ( QString::localeAwareCompare( mKeys[ id1.first ].toString(), mKeys[ id2.first ].toString() ) < 0 );
-      }
-
-      return mAscending ? result : !result;
+      return mAscending ? qgsVariantLessThan( mKeys.value( id1.first ), mKeys.value( id2.first ) )
+             : qgsVariantGreaterThan( mKeys.value( id1.first ), mKeys.value( id2.first ) );
     }
+
   private:
     QgsAtlasComposition::SorterKeys& mKeys;
     bool mAscending;
diff --git a/src/core/composer/qgscomposerattributetable.cpp b/src/core/composer/qgscomposerattributetable.cpp
index b0403a2..b1d9e69 100644
--- a/src/core/composer/qgscomposerattributetable.cpp
+++ b/src/core/composer/qgscomposerattributetable.cpp
@@ -32,60 +32,8 @@ QgsComposerAttributeTableCompare::QgsComposerAttributeTableCompare()
 
 bool QgsComposerAttributeTableCompare::operator()( const QgsAttributeMap& m1, const QgsAttributeMap& m2 )
 {
-  QVariant v1 = m1[mCurrentSortColumn];
-  QVariant v2 = m2[mCurrentSortColumn];
-
-  bool less = false;
-
-  //sort null values first
-  if ( v1.isNull() && v2.isNull() )
-  {
-    less = false;
-  }
-  else if ( v1.isNull() )
-  {
-    less = true;
-  }
-  else if ( v2.isNull() )
-  {
-    less = false;
-  }
-  else
-  {
-    //otherwise sort by converting to corresponding type and comparing
-    switch ( v1.type() )
-    {
-      case QVariant::Int:
-      case QVariant::UInt:
-      case QVariant::LongLong:
-      case QVariant::ULongLong:
-        less = v1.toLongLong() < v2.toLongLong();
-        break;
-
-      case QVariant::Double:
-        less = v1.toDouble() < v2.toDouble();
-        break;
-
-      case QVariant::Date:
-        less = v1.toDate() < v2.toDate();
-        break;
-
-      case QVariant::DateTime:
-        less = v1.toDateTime() < v2.toDateTime();
-        break;
-
-      case QVariant::Time:
-        less = v1.toTime() < v2.toTime();
-        break;
-
-      default:
-        //use locale aware compare for strings
-        less = v1.toString().localeAwareCompare( v2.toString() ) < 0;
-        break;
-    }
-  }
-
-  return ( mAscending ? less : !less );
+  return ( mAscending ? qgsVariantLessThan( m1[mCurrentSortColumn], m2[mCurrentSortColumn] )
+           : qgsVariantGreaterThan( m1[mCurrentSortColumn], m2[mCurrentSortColumn] ) );
 }
 
 
diff --git a/src/core/composer/qgscomposerattributetablev2.cpp b/src/core/composer/qgscomposerattributetablev2.cpp
index bd381f3..2b58610 100644
--- a/src/core/composer/qgscomposerattributetablev2.cpp
+++ b/src/core/composer/qgscomposerattributetablev2.cpp
@@ -37,60 +37,8 @@ QgsComposerAttributeTableCompareV2::QgsComposerAttributeTableCompareV2()
 
 bool QgsComposerAttributeTableCompareV2::operator()( const QgsComposerTableRow& m1, const QgsComposerTableRow& m2 )
 {
-  QVariant v1 = m1[mCurrentSortColumn];
-  QVariant v2 = m2[mCurrentSortColumn];
-
-  bool less = false;
-
-  //sort null values first
-  if ( v1.isNull() && v2.isNull() )
-  {
-    less = false;
-  }
-  else if ( v1.isNull() )
-  {
-    less = true;
-  }
-  else if ( v2.isNull() )
-  {
-    less = false;
-  }
-  else
-  {
-    //otherwise sort by converting to corresponding type and comparing
-    switch ( v1.type() )
-    {
-      case QVariant::Int:
-      case QVariant::UInt:
-      case QVariant::LongLong:
-      case QVariant::ULongLong:
-        less = v1.toLongLong() < v2.toLongLong();
-        break;
-
-      case QVariant::Double:
-        less = v1.toDouble() < v2.toDouble();
-        break;
-
-      case QVariant::Date:
-        less = v1.toDate() < v2.toDate();
-        break;
-
-      case QVariant::DateTime:
-        less = v1.toDateTime() < v2.toDateTime();
-        break;
-
-      case QVariant::Time:
-        less = v1.toTime() < v2.toTime();
-        break;
-
-      default:
-        //use locale aware compare for strings
-        less = v1.toString().localeAwareCompare( v2.toString() ) < 0;
-        break;
-    }
-  }
-
-  return ( mAscending ? less : !less );
+  return ( mAscending ? qgsVariantLessThan( m1[mCurrentSortColumn], m2[mCurrentSortColumn] )
+           : qgsVariantGreaterThan( m1[mCurrentSortColumn], m2[mCurrentSortColumn] ) );
 }
 
 //
diff --git a/src/core/composer/qgscomposermap.cpp b/src/core/composer/qgscomposermap.cpp
index dae55d9..2eda9e0 100644
--- a/src/core/composer/qgscomposermap.cpp
+++ b/src/core/composer/qgscomposermap.cpp
@@ -2151,6 +2151,14 @@ QgsExpressionContext* QgsComposerMap::createExpressionContext() const
   scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_id", QgsComposerItem::id(), true ) );
   scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_rotation", mMapRotation, true ) );
   scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_scale", scale(), true ) );
+
+  QgsRectangle extent( *currentMapExtent() );
+  scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_width", extent.width(), true ) );
+  scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_height", extent.height(), true ) );
+  QgsGeometry* centerPoint = QgsGeometry::fromPoint( extent.center() );
+  scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_center", QVariant::fromValue( *centerPoint ), true ) );
+  delete centerPoint;
+
   context->appendScope( scope );
 
   return context;
diff --git a/src/core/composer/qgscomposertablev2.cpp b/src/core/composer/qgscomposertablev2.cpp
index 96e216f..fd297f3 100644
--- a/src/core/composer/qgscomposertablev2.cpp
+++ b/src/core/composer/qgscomposertablev2.cpp
@@ -427,7 +427,7 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &, const int frameInd
   {
     //draw the headers
     int col = 0;
-    for ( QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin(); columnIt != mColumns.constEnd(); ++columnIt )
+    Q_FOREACH ( const QgsComposerTableColumn* column, mColumns )
     {
       //draw background
       p->save();
@@ -439,7 +439,7 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &, const int frameInd
       currentX += mCellMargin;
 
       Qt::TextFlag textFlag = static_cast< Qt::TextFlag >( 0 );
-      if (( *columnIt )->width() <= 0 )
+      if ( column->width() <= 0 )
       {
         //automatic column width, so we use the Qt::TextDontClip flag when drawing contents, as this works nicer for italicised text
         //which may slightly exceed the calculated width
@@ -454,7 +454,7 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &, const int frameInd
       switch ( mHeaderHAlignment )
       {
         case FollowColumn:
-          headerAlign = ( *columnIt )->hAlignment();
+          headerAlign = column->hAlignment();
           break;
         case HeaderLeft:
           headerAlign = Qt::AlignLeft;
@@ -467,7 +467,7 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &, const int frameInd
           break;
       }
 
-      QgsComposerUtils::drawText( p, cell, ( *columnIt )->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, textFlag );
+      QgsComposerUtils::drawText( p, cell, column->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, textFlag );
 
       currentX += mMaxColumnWidthMap[ col ];
       currentX += mCellMargin;
@@ -494,7 +494,7 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &, const int frameInd
       double rowHeight = mMaxRowHeightMap[row + 1] + 2 * mCellMargin;
 
 
-      for ( QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin(); columnIt != mColumns.constEnd(); ++columnIt )
+      Q_FOREACH ( const QgsComposerTableColumn* column, mColumns )
       {
         //draw background
         p->save();
@@ -510,20 +510,20 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &, const int frameInd
         QString str = cellContents.toString();
 
         Qt::TextFlag textFlag = static_cast< Qt::TextFlag >( 0 );
-        if (( *columnIt )->width() <= 0 && mWrapBehaviour == TruncateText )
+        if ( column->width() <= 0 && mWrapBehaviour == TruncateText )
         {
           //automatic column width, so we use the Qt::TextDontClip flag when drawing contents, as this works nicer for italicised text
           //which may slightly exceed the calculated width
           //if column size was manually set then we do apply text clipping, to avoid painting text outside of columns width
           textFlag = Qt::TextDontClip;
         }
-        else if ( textRequiresWrapping( str, ( *columnIt )->width(), mContentFont ) )
+        else if ( textRequiresWrapping( str, column->width(), mContentFont ) )
         {
-          str = wrappedText( str, ( *columnIt )->width(), mContentFont );
+          str = wrappedText( str, column->width(), mContentFont );
         }
 
         cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], rowHeight );
-        QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), ( *columnIt )->vAlignment(), textFlag );
+        QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, column->hAlignment(), column->vAlignment(), textFlag );
 
         currentX += mMaxColumnWidthMap[ col ];
         currentX += mCellMargin;
diff --git a/src/core/composer/qgscomposertablev2.h b/src/core/composer/qgscomposertablev2.h
index fb17244..e5d56b2 100644
--- a/src/core/composer/qgscomposertablev2.h
+++ b/src/core/composer/qgscomposertablev2.h
@@ -372,7 +372,8 @@ class CORE_EXPORT QgsComposerTableV2: public QgsComposerMultiFrame
     QgsComposerTableColumns* columns() { return &mColumns; }
 
     /** Replaces the columns in the table with a specified list of QgsComposerTableColumns.
-     * @param columns list of QgsComposerTableColumns to show in table
+     * @param columns list of QgsComposerTableColumns to show in table. Ownership of columns
+     * is transferred to the table.
      * @see columns
      */
     void setColumns( const QgsComposerTableColumns& columns );
diff --git a/src/core/geometry/qgsgeometry.cpp b/src/core/geometry/qgsgeometry.cpp
index 66dec95..1395d0b 100644
--- a/src/core/geometry/qgsgeometry.cpp
+++ b/src/core/geometry/qgsgeometry.cpp
@@ -1509,8 +1509,9 @@ bool QgsGeometry::deleteRing( int ringNum, int partNum )
   }
 
   detach( true );
-
-  return QgsGeometryEditUtils::deleteRing( d->geometry, ringNum, partNum );
+  bool ok = QgsGeometryEditUtils::deleteRing( d->geometry, ringNum, partNum );
+  removeWkbGeos();
+  return ok;
 }
 
 bool QgsGeometry::deletePart( int partNum )
@@ -1661,6 +1662,7 @@ void QgsGeometry::mapToPixel( const QgsMapToPixel& mtp )
   {
     detach();
     d->geometry->transform( mtp.transform() );
+    removeWkbGeos();
   }
 }
 
diff --git a/src/core/layertree/qgslayertreemodellegendnode.cpp b/src/core/layertree/qgslayertreemodellegendnode.cpp
index 71cffe0..a7a8a67 100644
--- a/src/core/layertree/qgslayertreemodellegendnode.cpp
+++ b/src/core/layertree/qgslayertreemodellegendnode.cpp
@@ -362,7 +362,7 @@ QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, Ite
   //Consider symbol size for point markers
   double height = settings.symbolSize().height();
   double width = settings.symbolSize().width();
-  double size = 0;
+
   //Center small marker symbols
   double widthOffset = 0;
   double heightOffset = 0;
@@ -370,7 +370,7 @@ QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, Ite
   if ( QgsMarkerSymbolV2* markerSymbol = dynamic_cast<QgsMarkerSymbolV2*>( s ) )
   {
     // allow marker symbol to occupy bigger area if necessary
-    size = QgsSymbolLayerV2Utils::convertToPainterUnits( context, markerSymbol->size(), s->outputUnit(), s->mapUnitScale() ) / context.scaleFactor();
+    double size = QgsSymbolLayerV2Utils::convertToPainterUnits( context, markerSymbol->size(), markerSymbol->sizeUnit(), markerSymbol->sizeMapUnitScale() ) / context.scaleFactor();
     height = size;
     width = size;
     if ( width < settings.symbolSize().width() )
diff --git a/src/core/qgis.cpp b/src/core/qgis.cpp
index 05652f8..786837f 100644
--- a/src/core/qgis.cpp
+++ b/src/core/qgis.cpp
@@ -260,6 +260,14 @@ void qgsFree( void *ptr )
 
 bool qgsVariantLessThan( const QVariant& lhs, const QVariant& rhs )
 {
+  // invalid < NULL < any value
+  if ( !lhs.isValid() )
+    return rhs.isValid();
+  else if ( lhs.isNull() )
+    return rhs.isValid() && !rhs.isNull();
+  else if ( !rhs.isValid() || rhs.isNull() )
+    return false;
+
   switch ( lhs.type() )
   {
     case QVariant::Int:
@@ -280,6 +288,39 @@ bool qgsVariantLessThan( const QVariant& lhs, const QVariant& rhs )
       return lhs.toTime() < rhs.toTime();
     case QVariant::DateTime:
       return lhs.toDateTime() < rhs.toDateTime();
+    case QVariant::Bool:
+      return lhs.toBool() < rhs.toBool();
+
+    case QVariant::List:
+    {
+      const QList<QVariant> &lhsl = lhs.toList();
+      const QList<QVariant> &rhsl = rhs.toList();
+
+      int i, n = qMin( lhsl.size(), rhsl.size() );
+      for ( i = 0; i < n && lhsl[i].type() == rhsl[i].type() && lhsl[i].isNull() == rhsl[i].isNull() && lhsl[i] == rhsl[i]; i++ )
+        ;
+
+      if ( i == n )
+        return lhsl.size() < rhsl.size();
+      else
+        return qgsVariantLessThan( lhsl[i], rhsl[i] );
+    }
+
+    case QVariant::StringList:
+    {
+      const QStringList &lhsl = lhs.toStringList();
+      const QStringList &rhsl = rhs.toStringList();
+
+      int i, n = qMin( lhsl.size(), rhsl.size() );
+      for ( i = 0; i < n && lhsl[i] == rhsl[i]; i++ )
+        ;
+
+      if ( i == n )
+        return lhsl.size() < rhsl.size();
+      else
+        return lhsl[i] < rhsl[i];
+    }
+
     default:
       return QString::localeAwareCompare( lhs.toString(), rhs.toString() ) < 0;
   }
diff --git a/src/core/qgis.h b/src/core/qgis.h
index 71aa856..8950fbf 100644
--- a/src/core/qgis.h
+++ b/src/core/qgis.h
@@ -314,9 +314,17 @@ inline double qgsRound( double x )
   return x < 0.0 ? std::ceil( x - 0.5 ) : std::floor( x + 0.5 );
 }
 
-bool qgsVariantLessThan( const QVariant& lhs, const QVariant& rhs );
-
-bool qgsVariantGreaterThan( const QVariant& lhs, const QVariant& rhs );
+//! Compares two QVariant values and returns whether the first is less than the second.
+//! Useful for sorting lists of variants, correctly handling sorting of the various
+//! QVariant data types (such as strings, numeric values, dates and times)
+//! @see qgsVariantGreaterThan()
+CORE_EXPORT bool qgsVariantLessThan( const QVariant& lhs, const QVariant& rhs );
+
+//! Compares two QVariant values and returns whether the first is greater than the second.
+//! Useful for sorting lists of variants, correctly handling sorting of the various
+//! QVariant data types (such as strings, numeric values, dates and times)
+//! @see qgsVariantLessThan()
+CORE_EXPORT bool qgsVariantGreaterThan( const QVariant& lhs, const QVariant& rhs );
 
 CORE_EXPORT QString qgsVsiPrefix( const QString& path );
 
diff --git a/src/core/qgsdataprovider.h b/src/core/qgsdataprovider.h
index 6ebaadc..b4b3f6e 100644
--- a/src/core/qgsdataprovider.h
+++ b/src/core/qgsdataprovider.h
@@ -306,6 +306,11 @@ class CORE_EXPORT QgsDataProvider : public QObject
      */
     virtual QgsError error() const { return mError; }
 
+    /** Invalidate connections corresponding to specified name
+     * @note added in QGIS 2.16
+     */
+    virtual void invalidateConnections( const QString& connection ) { Q_UNUSED( connection ); }
+
   signals:
 
     /**
diff --git a/src/core/qgsexpression.cpp b/src/core/qgsexpression.cpp
index c83c9eb..737f6ce 100644
--- a/src/core/qgsexpression.cpp
+++ b/src/core/qgsexpression.cpp
@@ -21,6 +21,7 @@
 #include <QRegExp>
 #include <QColor>
 #include <QUuid>
+#include <QMutex>
 
 #include <math.h>
 #include <limits>
@@ -2857,6 +2858,13 @@ QList<QgsExpression::Function*> QgsExpression::gmOwnedFunctions;
 
 const QList<QgsExpression::Function*>& QgsExpression::Functions()
 {
+  // The construction of the list isn't thread-safe, and without the mutex,
+  // crashes in the WFS provider may occur, since it can parse expressions
+  // in parallel.
+  // The mutex needs to be recursive.
+  static QMutex sFunctionsMutex( QMutex::Recursive );
+  QMutexLocker locker( &sFunctionsMutex );
+
   if ( gmFunctions.isEmpty() )
   {
     gmFunctions
diff --git a/src/core/qgsexpressioncontext.cpp b/src/core/qgsexpressioncontext.cpp
index 42e0a07..1e1827a 100644
--- a/src/core/qgsexpressioncontext.cpp
+++ b/src/core/qgsexpressioncontext.cpp
@@ -713,6 +713,9 @@ void QgsExpressionContextUtils::setLayerVariables( QgsMapLayer* layer, const Qgs
 
 QgsExpressionContextScope* QgsExpressionContextUtils::mapSettingsScope( const QgsMapSettings& mapSettings )
 {
+  // IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsComposerMap::createExpressionContext()
+  // (rationale is described in QgsComposerMap::createExpressionContext() )
+
   QgsExpressionContextScope* scope = new QgsExpressionContextScope( QObject::tr( "Map Settings" ) );
 
   //add known map settings context variables
diff --git a/src/core/qgsmaplayer.cpp b/src/core/qgsmaplayer.cpp
index 0010cdd..d710c18 100644
--- a/src/core/qgsmaplayer.cpp
+++ b/src/core/qgsmaplayer.cpp
@@ -69,8 +69,8 @@ QgsMapLayer::QgsMapLayer( QgsMapLayer::LayerType type,
   mLayerName = capitaliseLayerName( mLayerOrigName );
   QgsDebugMsg( "display name: '" + mLayerName + '\'' );
 
-  // Set short name = the first original name
-  mShortName = lyrname;
+  mShortName = "";
+  //mShortName.replace( QRegExp( "[\\W]" ), "_" );
 
   // Generate the unique ID of this layer
   QDateTime dt = QDateTime::currentDateTime();
@@ -656,26 +656,34 @@ bool QgsMapLayer::writeLayerXML( QDomElement& layerElement, QDomDocument& docume
   QDomElement layerName = document.createElement( "layername" );
   QDomText layerNameText = document.createTextNode( originalName() );
   layerName.appendChild( layerNameText );
+  layerElement.appendChild( layerName );
 
   // layer short name
-  QDomElement layerShortName = document.createElement( "shortname" );
-  QDomText layerShortNameText = document.createTextNode( shortName() );
-  layerShortName.appendChild( layerShortNameText );
+  if ( !mShortName.isEmpty() )
+  {
+    QDomElement layerShortName = document.createElement( "shortname" );
+    QDomText layerShortNameText = document.createTextNode( mShortName );
+    layerShortName.appendChild( layerShortNameText );
+    layerElement.appendChild( layerShortName );
+  }
 
   // layer title
-  QDomElement layerTitle = document.createElement( "title" );
-  QDomText layerTitleText = document.createTextNode( title() );
-  layerTitle.appendChild( layerTitleText );
+  if ( !mTitle.isEmpty() )
+  {
+    QDomElement layerTitle = document.createElement( "title" );
+    QDomText layerTitleText = document.createTextNode( mTitle );
+    layerTitle.appendChild( layerTitleText );
+    layerElement.appendChild( layerTitle );
+  }
 
   // layer abstract
-  QDomElement layerAbstract = document.createElement( "abstract" );
-  QDomText layerAbstractText = document.createTextNode( abstract() );
-  layerAbstract.appendChild( layerAbstractText );
-
-  layerElement.appendChild( layerName );
-  layerElement.appendChild( layerShortName );
-  layerElement.appendChild( layerTitle );
-  layerElement.appendChild( layerAbstract );
+  if ( !mAbstract.isEmpty() )
+  {
+    QDomElement layerAbstract = document.createElement( "abstract" );
+    QDomText layerAbstractText = document.createTextNode( mAbstract );
+    layerAbstract.appendChild( layerAbstractText );
+    layerElement.appendChild( layerAbstract );
+  }
 
   // layer keyword list
   QStringList keywordStringList = keywordList().split( ',' );
diff --git a/src/core/qgsnetworkaccessmanager.cpp b/src/core/qgsnetworkaccessmanager.cpp
index 42f833a..2111cde 100644
--- a/src/core/qgsnetworkaccessmanager.cpp
+++ b/src/core/qgsnetworkaccessmanager.cpp
@@ -384,3 +384,21 @@ void QgsNetworkAccessManager::setupDefaultProxyAndCache()
   if ( cache() != newcache )
     setCache( newcache );
 }
+
+void QgsNetworkAccessManager::sendGet( const QNetworkRequest & request )
+{
+  QgsDebugMsg( "Entered" );
+  QNetworkReply * reply = get( request );
+  emit requestSent( reply, QObject::sender() );
+}
+
+void QgsNetworkAccessManager::deleteReply( QNetworkReply * reply )
+{
+  QgsDebugMsg( "Entered" );
+  if ( !reply )
+  {
+    return;
+  }
+  reply->abort();
+  reply->deleteLater();
+}
diff --git a/src/core/qgsnetworkaccessmanager.h b/src/core/qgsnetworkaccessmanager.h
index 10bb7fb..e388e4a 100644
--- a/src/core/qgsnetworkaccessmanager.h
+++ b/src/core/qgsnetworkaccessmanager.h
@@ -85,10 +85,29 @@ class CORE_EXPORT QgsNetworkAccessManager : public QNetworkAccessManager
     //! return whether the system proxy should be used
     bool useSystemProxy() { return mUseSystemProxy; }
 
+  public slots:
+    /** Send GET request, calls get().
+     * Emits requestSent().
+     * @param request request to be sent
+     * @deprecated use get() directly
+     */
+    Q_DECL_DEPRECATED void sendGet( const QNetworkRequest & request );
+    /** Abort and delete reply.
+     * @param reply reply to be aborted.
+     * @deprecated use abort() and deleteLayer() on the reply directly
+     */
+    Q_DECL_DEPRECATED void deleteReply( QNetworkReply * reply );
+
   signals:
     void requestAboutToBeCreated( QNetworkAccessManager::Operation, const QNetworkRequest &, QIODevice * );
     void requestCreated( QNetworkReply * );
     void requestTimedOut( QNetworkReply * );
+    /** Emitted when request was sent by request()
+     * @param reply request reply
+     * @param sender the object which called request() slot.
+     * @deprecated only emitted from deprecated sendGet
+     */
+    void requestSent( QNetworkReply * reply, QObject *sender );
 
   private slots:
     void abortRequest();
diff --git a/src/core/qgsofflineediting.cpp b/src/core/qgsofflineediting.cpp
index b1b9ae5..cfb6015 100644
--- a/src/core/qgsofflineediting.cpp
+++ b/src/core/qgsofflineediting.cpp
@@ -65,6 +65,17 @@ QgsOfflineEditing::~QgsOfflineEditing()
 /**
  * convert current project to offline project
  * returns offline project file path
+ *
+ * Workflow:
+ *  - copy layers to spatialite
+ *  - create spatialite db at offlineDataPath
+ *  - create table for each layer
+ *  - add new spatialite layer
+ *  - copy features
+ *  - save as offline project
+ *  - mark offline layers
+ *  - remove remote layers
+ *  - mark as offline project
  */
 bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds )
 {
@@ -129,6 +140,9 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
         if ( newLayer )
         {
           layerIdMapping.insert( origLayerId, newLayer );
+          // remove remote layer
+          QgsMapLayerRegistry::instance()->removeMapLayers(
+            QStringList() << origLayerId );
         }
       }
 
@@ -172,19 +186,7 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
       return true;
     }
   }
-
   return false;
-
-  // Workflow:
-  // copy layers to spatialite
-  // create spatialite db at offlineDataPath
-  // create table for each layer
-  // add new spatialite layer
-  // copy features
-  // save as offline project
-  // mark offline layers
-  // remove remote layers
-  // mark as offline project
 }
 
 bool QgsOfflineEditing::isOfflineProject()
@@ -285,11 +287,14 @@ void QgsOfflineEditing::synchronize()
           showWarning( remoteLayer->commitErrors().join( "\n" ) );
         }
       }
-
+      // Invalidate the connection to force a reload if the project is put offline
+      // again with the same path
+      offlineLayer->dataProvider()->invalidateConnections( QgsDataSourceURI( offlineLayer->source() ).database() );
       // remove offline layer
       QgsMapLayerRegistry::instance()->removeMapLayers(
         ( QStringList() << qgisLayerId ) );
 
+
       // disable offline project
       QString projectTitle = QgsProject::instance()->title();
       projectTitle.remove( QRegExp( " \\(offline\\)$" ) );
@@ -457,6 +462,7 @@ QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlit
     return nullptr;
 
   QString tableName = layer->id();
+  QgsDebugMsg( QString( "Creating offline table %1 ..." ).arg( tableName ) );
 
   // create table
   QString sql = QString( "CREATE TABLE '%1' (" ).arg( tableName );
@@ -539,9 +545,10 @@ QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlit
   if ( rc == SQLITE_OK )
   {
     // add new layer
-    QgsVectorLayer* newLayer = new QgsVectorLayer( QString( "dbname='%1' table='%2'%3 sql=" )
-        .arg( offlineDbPath,
-              tableName, layer->hasGeometryType() ? "(Geometry)" : "" ),
+    QString connectionString = QString( "dbname='%1' table='%2'%3 sql=" )
+                               .arg( offlineDbPath,
+                                     tableName, layer->hasGeometryType() ? "(Geometry)" : "" );
+    QgsVectorLayer* newLayer = new QgsVectorLayer( connectionString,
         layer->name() + " (offline)", "spatialite" );
     if ( newLayer->isValid() )
     {
@@ -646,7 +653,16 @@ QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlit
         int remoteCount = remoteFeatureIds.size();
         for ( int i = 0; i < remoteCount; i++ )
         {
-          addFidLookup( db, layerId, offlineFeatureIds.at( i ), remoteFeatureIds.at( remoteCount - ( i + 1 ) ) );
+          // Check if the online feature has been fetched (WFS download aborted for some reason)
+          if ( i < offlineFeatureIds.count() )
+          {
+            addFidLookup( db, layerId, offlineFeatureIds.at( i ), remoteFeatureIds.at( remoteCount - ( i + 1 ) ) );
+          }
+          else
+          {
+            showWarning( QString( "Feature cannot be copied to the offline layer, please check if the online layer '%1' is sill accessible." ).arg( layer->name() ) );
+            return nullptr;
+          }
           emit progressUpdated( featureCount++ );
         }
         sqlExec( db, "COMMIT" );
@@ -655,10 +671,6 @@ QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlit
       {
         showWarning( newLayer->commitErrors().join( "\n" ) );
       }
-
-      // remove remote layer
-      QgsMapLayerRegistry::instance()->removeMapLayers(
-        QStringList() << layer->id() );
     }
     return newLayer;
   }
@@ -1289,33 +1301,39 @@ void QgsOfflineEditing::committedGeometriesChanges( const QString& qgisLayerId,
 void QgsOfflineEditing::startListenFeatureChanges()
 {
   QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer *>( sender() );
-  // enable logging
-  connect( vLayer->editBuffer(), SIGNAL( committedAttributesAdded( const QString&, const QList<QgsField>& ) ),
-           this, SLOT( committedAttributesAdded( const QString&, const QList<QgsField>& ) ) );
+  // enable logging, check if editBuffer is not null
+  if ( vLayer->editBuffer() )
+  {
+    connect( vLayer->editBuffer(), SIGNAL( committedAttributesAdded( const QString&, const QList<QgsField>& ) ),
+             this, SLOT( committedAttributesAdded( const QString&, const QList<QgsField>& ) ) );
+    connect( vLayer->editBuffer(), SIGNAL( committedAttributeValuesChanges( const QString&, const QgsChangedAttributesMap& ) ),
+             this, SLOT( committedAttributeValuesChanges( const QString&, const QgsChangedAttributesMap& ) ) );
+    connect( vLayer->editBuffer(), SIGNAL( committedGeometriesChanges( const QString&, const QgsGeometryMap& ) ),
+             this, SLOT( committedGeometriesChanges( const QString&, const QgsGeometryMap& ) ) );
+  }
   connect( vLayer, SIGNAL( committedFeaturesAdded( const QString&, const QgsFeatureList& ) ),
            this, SLOT( committedFeaturesAdded( const QString&, const QgsFeatureList& ) ) );
   connect( vLayer, SIGNAL( committedFeaturesRemoved( const QString&, const QgsFeatureIds& ) ),
            this, SLOT( committedFeaturesRemoved( const QString&, const QgsFeatureIds& ) ) );
-  connect( vLayer->editBuffer(), SIGNAL( committedAttributeValuesChanges( const QString&, const QgsChangedAttributesMap& ) ),
-           this, SLOT( committedAttributeValuesChanges( const QString&, const QgsChangedAttributesMap& ) ) );
-  connect( vLayer->editBuffer(), SIGNAL( committedGeometriesChanges( const QString&, const QgsGeometryMap& ) ),
-           this, SLOT( committedGeometriesChanges( const QString&, const QgsGeometryMap& ) ) );
 }
 
 void QgsOfflineEditing::stopListenFeatureChanges()
 {
   QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer *>( sender() );
-  // disable logging
-  disconnect( vLayer->editBuffer(), SIGNAL( committedAttributesAdded( const QString&, const QList<QgsField>& ) ),
-              this, SLOT( committedAttributesAdded( const QString&, const QList<QgsField>& ) ) );
+  // disable logging, check if editBuffer is not null
+  if ( vLayer->editBuffer() )
+  {
+    disconnect( vLayer->editBuffer(), SIGNAL( committedAttributesAdded( const QString&, const QList<QgsField>& ) ),
+                this, SLOT( committedAttributesAdded( const QString&, const QList<QgsField>& ) ) );
+    disconnect( vLayer->editBuffer(), SIGNAL( committedAttributeValuesChanges( const QString&, const QgsChangedAttributesMap& ) ),
+                this, SLOT( committedAttributeValuesChanges( const QString&, const QgsChangedAttributesMap& ) ) );
+    disconnect( vLayer->editBuffer(), SIGNAL( committedGeometriesChanges( const QString&, const QgsGeometryMap& ) ),
+                this, SLOT( committedGeometriesChanges( const QString&, const QgsGeometryMap& ) ) );
+  }
   disconnect( vLayer, SIGNAL( committedFeaturesAdded( const QString&, const QgsFeatureList& ) ),
               this, SLOT( committedFeaturesAdded( const QString&, const QgsFeatureList& ) ) );
   disconnect( vLayer, SIGNAL( committedFeaturesRemoved( const QString&, const QgsFeatureIds& ) ),
               this, SLOT( committedFeaturesRemoved( const QString&, const QgsFeatureIds& ) ) );
-  disconnect( vLayer->editBuffer(), SIGNAL( committedAttributeValuesChanges( const QString&, const QgsChangedAttributesMap& ) ),
-              this, SLOT( committedAttributeValuesChanges( const QString&, const QgsChangedAttributesMap& ) ) );
-  disconnect( vLayer->editBuffer(), SIGNAL( committedGeometriesChanges( const QString&, const QgsGeometryMap& ) ),
-              this, SLOT( committedGeometriesChanges( const QString&, const QgsGeometryMap& ) ) );
 }
 
 void QgsOfflineEditing::layerAdded( QgsMapLayer* layer )
diff --git a/src/core/qgspallabeling.cpp b/src/core/qgspallabeling.cpp
index 7da5eb3..7fc6cd3 100644
--- a/src/core/qgspallabeling.cpp
+++ b/src/core/qgspallabeling.cpp
@@ -821,8 +821,16 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
 
   double fontSize = layer->customProperty( "labeling/fontSize" ).toDouble();
   fontSizeInMapUnits = layer->customProperty( "labeling/fontSizeInMapUnits" ).toBool();
-  fontSizeMapUnitScale.minScale = layer->customProperty( "labeling/fontSizeMapUnitMinScale", 0.0 ).toDouble();
-  fontSizeMapUnitScale.maxScale = layer->customProperty( "labeling/fontSizeMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/fontSizeMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    fontSizeMapUnitScale.minScale = layer->customProperty( "labeling/fontSizeMapUnitMinScale", 0.0 ).toDouble();
+    fontSizeMapUnitScale.maxScale = layer->customProperty( "labeling/fontSizeMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    fontSizeMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/fontSizeMapUnitScale" ).toString() );
+  }
   int fontWeight = layer->customProperty( "labeling/fontWeight" ).toInt();
   bool fontItalic = layer->customProperty( "labeling/fontItalic" ).toBool();
   textFont = QFont( fontFamily, fontSize, fontWeight, fontItalic );
@@ -876,8 +884,16 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
   }
 
   bufferSizeInMapUnits = layer->customProperty( "labeling/bufferSizeInMapUnits" ).toBool();
-  bufferSizeMapUnitScale.minScale = layer->customProperty( "labeling/bufferSizeMapUnitMinScale", 0.0 ).toDouble();
-  bufferSizeMapUnitScale.maxScale = layer->customProperty( "labeling/bufferSizeMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/bufferSizeMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    bufferSizeMapUnitScale.minScale = layer->customProperty( "labeling/bufferSizeMapUnitMinScale", 0.0 ).toDouble();
+    bufferSizeMapUnitScale.maxScale = layer->customProperty( "labeling/bufferSizeMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    bufferSizeMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/bufferSizeMapUnitScale" ).toString() );
+  }
   bufferColor = _readColor( layer, "labeling/bufferColor", Qt::white, false );
   bufferTransp = layer->customProperty( "labeling/bufferTransp" ).toInt();
   bufferBlendMode = QgsMapRenderer::getCompositionMode(
@@ -893,26 +909,58 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
   shapeSize = QPointF( layer->customProperty( "labeling/shapeSizeX", QVariant( 0.0 ) ).toDouble(),
                        layer->customProperty( "labeling/shapeSizeY", QVariant( 0.0 ) ).toDouble() );
   shapeSizeUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shapeSizeUnits", QVariant( MM ) ).toUInt() );
-  shapeSizeMapUnitScale.minScale = layer->customProperty( "labeling/shapeSizeMapUnitMinScale", 0.0 ).toDouble();
-  shapeSizeMapUnitScale.maxScale = layer->customProperty( "labeling/shapeSizeMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/shapeSizeMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    shapeSizeMapUnitScale.minScale = layer->customProperty( "labeling/shapeSizeMapUnitMinScale", 0.0 ).toDouble();
+    shapeSizeMapUnitScale.maxScale = layer->customProperty( "labeling/shapeSizeMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    shapeSizeMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/shapeSizeMapUnitScale" ).toString() );
+  }
   shapeRotationType = static_cast< RotationType >( layer->customProperty( "labeling/shapeRotationType", QVariant( RotationSync ) ).toUInt() );
   shapeRotation = layer->customProperty( "labeling/shapeRotation", QVariant( 0.0 ) ).toDouble();
   shapeOffset = QPointF( layer->customProperty( "labeling/shapeOffsetX", QVariant( 0.0 ) ).toDouble(),
                          layer->customProperty( "labeling/shapeOffsetY", QVariant( 0.0 ) ).toDouble() );
   shapeOffsetUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shapeOffsetUnits", QVariant( MM ) ).toUInt() );
-  shapeOffsetMapUnitScale.minScale = layer->customProperty( "labeling/shapeOffsetMapUnitMinScale", 0.0 ).toDouble();
-  shapeOffsetMapUnitScale.maxScale = layer->customProperty( "labeling/shapeOffsetMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/shapeOffsetMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    shapeOffsetMapUnitScale.minScale = layer->customProperty( "labeling/shapeOffsetMapUnitMinScale", 0.0 ).toDouble();
+    shapeOffsetMapUnitScale.maxScale = layer->customProperty( "labeling/shapeOffsetMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    shapeOffsetMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/shapeOffsetMapUnitScale" ).toString() );
+  }
   shapeRadii = QPointF( layer->customProperty( "labeling/shapeRadiiX", QVariant( 0.0 ) ).toDouble(),
                         layer->customProperty( "labeling/shapeRadiiY", QVariant( 0.0 ) ).toDouble() );
   shapeRadiiUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shapeRadiiUnits", QVariant( MM ) ).toUInt() );
-  shapeRadiiMapUnitScale.minScale = layer->customProperty( "labeling/shapeRaddiMapUnitMinScale", 0.0 ).toDouble();
-  shapeRadiiMapUnitScale.maxScale = layer->customProperty( "labeling/shapeRaddiMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/shapeRadiiMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    shapeRadiiMapUnitScale.minScale = layer->customProperty( "labeling/shapeRadiiMapUnitMinScale", 0.0 ).toDouble();
+    shapeRadiiMapUnitScale.maxScale = layer->customProperty( "labeling/shapeRadiiMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    shapeRadiiMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/shapeRadiiMapUnitScale" ).toString() );
+  }
   shapeFillColor = _readColor( layer, "labeling/shapeFillColor", Qt::white, true );
   shapeBorderColor = _readColor( layer, "labeling/shapeBorderColor", Qt::darkGray, true );
   shapeBorderWidth = layer->customProperty( "labeling/shapeBorderWidth", QVariant( .0 ) ).toDouble();
   shapeBorderWidthUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shapeBorderWidthUnits", QVariant( MM ) ).toUInt() );
-  shapeBorderWidthMapUnitScale.minScale = layer->customProperty( "labeling/shapeBorderWidthMapUnitMinScale", 0.0 ).toDouble();
-  shapeBorderWidthMapUnitScale.maxScale = layer->customProperty( "labeling/shapeBorderWidthMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/shapeBorderWidthMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    shapeBorderWidthMapUnitScale.minScale = layer->customProperty( "labeling/shapeBorderWidthMapUnitMinScale", 0.0 ).toDouble();
+    shapeBorderWidthMapUnitScale.maxScale = layer->customProperty( "labeling/shapeBorderWidthMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    shapeBorderWidthMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/shapeBorderWidthMapUnitScale" ).toString() );
+  }
   shapeJoinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( "labeling/shapeJoinStyle", QVariant( Qt::BevelJoin ) ).toUInt() );
   shapeTransparency = layer->customProperty( "labeling/shapeTransparency", QVariant( 0 ) ).toInt();
   shapeBlendMode = QgsMapRenderer::getCompositionMode(
@@ -924,13 +972,29 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
   shadowOffsetAngle = layer->customProperty( "labeling/shadowOffsetAngle", QVariant( 135 ) ).toInt();
   shadowOffsetDist = layer->customProperty( "labeling/shadowOffsetDist", QVariant( 1.0 ) ).toDouble();
   shadowOffsetUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shadowOffsetUnits", QVariant( MM ) ).toUInt() );
-  shadowOffsetMapUnitScale.minScale = layer->customProperty( "labeling/shadowOffsetMapUnitMinScale", 0.0 ).toDouble();
-  shadowOffsetMapUnitScale.maxScale = layer->customProperty( "labeling/shadowOffsetMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/shadowOffsetMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    shadowOffsetMapUnitScale.minScale = layer->customProperty( "labeling/shadowOffsetMapUnitMinScale", 0.0 ).toDouble();
+    shadowOffsetMapUnitScale.maxScale = layer->customProperty( "labeling/shadowOffsetMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    shadowOffsetMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/shadowOffsetMapUnitScale" ).toString() );
+  }
   shadowOffsetGlobal = layer->customProperty( "labeling/shadowOffsetGlobal", QVariant( true ) ).toBool();
   shadowRadius = layer->customProperty( "labeling/shadowRadius", QVariant( 1.5 ) ).toDouble();
   shadowRadiusUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shadowRadiusUnits", QVariant( MM ) ).toUInt() );
-  shadowRadiusMapUnitScale.minScale = layer->customProperty( "labeling/shadowRadiusMapUnitMinScale", 0.0 ).toDouble();
-  shadowRadiusMapUnitScale.maxScale = layer->customProperty( "labeling/shadowRadiusMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/shadowRadiusMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    shadowRadiusMapUnitScale.minScale = layer->customProperty( "labeling/shadowRadiusMapUnitMinScale", 0.0 ).toDouble();
+    shadowRadiusMapUnitScale.maxScale = layer->customProperty( "labeling/shadowRadiusMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    shadowRadiusMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/shadowRadiusMapUnitScale" ).toString() );
+  }
   shadowRadiusAlphaOnly = layer->customProperty( "labeling/shadowRadiusAlphaOnly", QVariant( false ) ).toBool();
   shadowTransparency = layer->customProperty( "labeling/shadowTransparency", QVariant( 30 ) ).toInt();
   shadowScale = layer->customProperty( "labeling/shadowScale", QVariant( 100 ) ).toInt();
@@ -949,15 +1013,31 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
   fitInPolygonOnly = layer->customProperty( "labeling/fitInPolygonOnly", QVariant( false ) ).toBool();
   dist = layer->customProperty( "labeling/dist" ).toDouble();
   distInMapUnits = layer->customProperty( "labeling/distInMapUnits" ).toBool();
-  distMapUnitScale.minScale = layer->customProperty( "labeling/distMapUnitMinScale", 0.0 ).toDouble();
-  distMapUnitScale.maxScale = layer->customProperty( "labeling/distMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/distMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    distMapUnitScale.minScale = layer->customProperty( "labeling/distMapUnitMinScale", 0.0 ).toDouble();
+    distMapUnitScale.maxScale = layer->customProperty( "labeling/distMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    distMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/distMapUnitScale" ).toString() );
+  }
   offsetType = static_cast< OffsetType >( layer->customProperty( "labeling/offsetType", QVariant( FromPoint ) ).toUInt() );
   quadOffset = static_cast< QuadrantPosition >( layer->customProperty( "labeling/quadOffset", QVariant( QuadrantOver ) ).toUInt() );
   xOffset = layer->customProperty( "labeling/xOffset", QVariant( 0.0 ) ).toDouble();
   yOffset = layer->customProperty( "labeling/yOffset", QVariant( 0.0 ) ).toDouble();
   labelOffsetInMapUnits = layer->customProperty( "labeling/labelOffsetInMapUnits", QVariant( true ) ).toBool();
-  labelOffsetMapUnitScale.minScale = layer->customProperty( "labeling/labelOffsetMapUnitMinScale", 0.0 ).toDouble();
-  labelOffsetMapUnitScale.maxScale = layer->customProperty( "labeling/labelOffsetMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/labelOffsetMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    labelOffsetMapUnitScale.minScale = layer->customProperty( "labeling/labelOffsetMapUnitMinScale", 0.0 ).toDouble();
+    labelOffsetMapUnitScale.maxScale = layer->customProperty( "labeling/labelOffsetMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    labelOffsetMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/labelOffsetMapUnitScale" ).toString() );
+  }
   angleOffset = layer->customProperty( "labeling/angleOffset", QVariant( 0.0 ) ).toDouble();
   preserveRotation = layer->customProperty( "labeling/preserveRotation", QVariant( true ) ).toBool();
   maxCurvedCharAngleIn = layer->customProperty( "labeling/maxCurvedCharAngleIn", QVariant( 20.0 ) ).toDouble();
@@ -965,8 +1045,16 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
   priority = layer->customProperty( "labeling/priority" ).toInt();
   repeatDistance = layer->customProperty( "labeling/repeatDistance", 0.0 ).toDouble();
   repeatDistanceUnit = static_cast< SizeUnit >( layer->customProperty( "labeling/repeatDistanceUnit", QVariant( MM ) ).toUInt() );
-  repeatDistanceMapUnitScale.minScale = layer->customProperty( "labeling/repeatDistanceMapUnitMinScale", 0.0 ).toDouble();
-  repeatDistanceMapUnitScale.maxScale = layer->customProperty( "labeling/repeatDistanceMapUnitMaxScale", 0.0 ).toDouble();
+  if ( layer->customProperty( "labeling/repeatDistanceMapUnitScale" ).toString().isEmpty() )
+  {
+    //fallback to older property
+    repeatDistanceMapUnitScale.minScale = layer->customProperty( "labeling/repeatDistanceMapUnitMinScale", 0.0 ).toDouble();
+    repeatDistanceMapUnitScale.maxScale = layer->customProperty( "labeling/repeatDistanceMapUnitMaxScale", 0.0 ).toDouble();
+  }
+  else
+  {
+    repeatDistanceMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( layer->customProperty( "labeling/repeatDistanceMapUnitScale" ).toString() );
+  }
 
   // rendering
   int scalemn = layer->customProperty( "labeling/scaleMin", QVariant( 0 ) ).toInt();
@@ -1027,8 +1115,7 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
   layer->setCustomProperty( "labeling/namedStyle", QgsFontUtils::untranslateNamedStyle( textNamedStyle ) );
   layer->setCustomProperty( "labeling/fontSize", textFont.pointSizeF() );
   layer->setCustomProperty( "labeling/fontSizeInMapUnits", fontSizeInMapUnits );
-  layer->setCustomProperty( "labeling/fontSizeMapUnitMinScale", fontSizeMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/fontSizeMapUnitMaxScale", fontSizeMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/fontSizeMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( fontSizeMapUnitScale ) );
   layer->setCustomProperty( "labeling/fontWeight", textFont.weight() );
   layer->setCustomProperty( "labeling/fontItalic", textFont.italic() );
   layer->setCustomProperty( "labeling/fontStrikeout", textFont.strikeOut() );
@@ -1058,8 +1145,7 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
   layer->setCustomProperty( "labeling/bufferDraw", bufferDraw );
   layer->setCustomProperty( "labeling/bufferSize", bufferSize );
   layer->setCustomProperty( "labeling/bufferSizeInMapUnits", bufferSizeInMapUnits );
-  layer->setCustomProperty( "labeling/bufferSizeMapUnitMinScale", bufferSizeMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/bufferSizeMapUnitMaxScale", bufferSizeMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/bufferSizeMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( bufferSizeMapUnitScale ) );
   _writeColor( layer, "labeling/bufferColor", bufferColor );
   layer->setCustomProperty( "labeling/bufferNoFill", bufferNoFill );
   layer->setCustomProperty( "labeling/bufferTransp", bufferTransp );
@@ -1074,26 +1160,22 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
   layer->setCustomProperty( "labeling/shapeSizeX", shapeSize.x() );
   layer->setCustomProperty( "labeling/shapeSizeY", shapeSize.y() );
   layer->setCustomProperty( "labeling/shapeSizeUnits", static_cast< unsigned int >( shapeSizeUnits ) );
-  layer->setCustomProperty( "labeling/shapeSizeMapUnitMinScale", shapeSizeMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/shapeSizeMapUnitMaxScale", shapeSizeMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/shapeSizeMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shapeSizeMapUnitScale ) );
   layer->setCustomProperty( "labeling/shapeRotationType", static_cast< unsigned int >( shapeRotationType ) );
   layer->setCustomProperty( "labeling/shapeRotation", shapeRotation );
   layer->setCustomProperty( "labeling/shapeOffsetX", shapeOffset.x() );
   layer->setCustomProperty( "labeling/shapeOffsetY", shapeOffset.y() );
   layer->setCustomProperty( "labeling/shapeOffsetUnits", static_cast< unsigned int >( shapeOffsetUnits ) );
-  layer->setCustomProperty( "labeling/shapeOffsetMapUnitMinScale", shapeOffsetMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/shapeOffsetMapUnitMaxScale", shapeOffsetMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/shapeOffsetMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shapeOffsetMapUnitScale ) );
   layer->setCustomProperty( "labeling/shapeRadiiX", shapeRadii.x() );
   layer->setCustomProperty( "labeling/shapeRadiiY", shapeRadii.y() );
   layer->setCustomProperty( "labeling/shapeRadiiUnits", static_cast< unsigned int >( shapeRadiiUnits ) );
-  layer->setCustomProperty( "labeling/shapeRadiiMapUnitMinScale", shapeRadiiMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/shapeRadiiMapUnitMaxScale", shapeRadiiMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/shapeRadiiMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shapeRadiiMapUnitScale ) );
   _writeColor( layer, "labeling/shapeFillColor", shapeFillColor, true );
   _writeColor( layer, "labeling/shapeBorderColor", shapeBorderColor, true );
   layer->setCustomProperty( "labeling/shapeBorderWidth", shapeBorderWidth );
   layer->setCustomProperty( "labeling/shapeBorderWidthUnits", static_cast< unsigned int >( shapeBorderWidthUnits ) );
-  layer->setCustomProperty( "labeling/shapeBorderWidthMapUnitMinScale", shapeBorderWidthMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/shapeBorderWidthMapUnitMaxScale", shapeBorderWidthMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/shapeBorderWidthMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shapeBorderWidthMapUnitScale ) );
   layer->setCustomProperty( "labeling/shapeJoinStyle", static_cast< unsigned int >( shapeJoinStyle ) );
   layer->setCustomProperty( "labeling/shapeTransparency", shapeTransparency );
   layer->setCustomProperty( "labeling/shapeBlendMode", QgsMapRenderer::getBlendModeEnum( shapeBlendMode ) );
@@ -1104,13 +1186,11 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
   layer->setCustomProperty( "labeling/shadowOffsetAngle", shadowOffsetAngle );
   layer->setCustomProperty( "labeling/shadowOffsetDist", shadowOffsetDist );
   layer->setCustomProperty( "labeling/shadowOffsetUnits", static_cast< unsigned int >( shadowOffsetUnits ) );
-  layer->setCustomProperty( "labeling/shadowOffsetMapUnitMinScale", shadowOffsetMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/shadowOffsetMapUnitMaxScale", shadowOffsetMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/shadowOffsetMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shadowOffsetMapUnitScale ) );
   layer->setCustomProperty( "labeling/shadowOffsetGlobal", shadowOffsetGlobal );
   layer->setCustomProperty( "labeling/shadowRadius", shadowRadius );
   layer->setCustomProperty( "labeling/shadowRadiusUnits", static_cast< unsigned int >( shadowRadiusUnits ) );
-  layer->setCustomProperty( "labeling/shadowRadiusMapUnitMinScale", shadowRadiusMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/shadowRadiusMapUnitMaxScale", shadowRadiusMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/shadowRadiusMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shadowRadiusMapUnitScale ) );
   layer->setCustomProperty( "labeling/shadowRadiusAlphaOnly", shadowRadiusAlphaOnly );
   layer->setCustomProperty( "labeling/shadowTransparency", shadowTransparency );
   layer->setCustomProperty( "labeling/shadowScale", shadowScale );
@@ -1126,15 +1206,13 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
   layer->setCustomProperty( "labeling/fitInPolygonOnly", fitInPolygonOnly );
   layer->setCustomProperty( "labeling/dist", dist );
   layer->setCustomProperty( "labeling/distInMapUnits", distInMapUnits );
-  layer->setCustomProperty( "labeling/distMapUnitMinScale", distMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/distMapUnitMaxScale", distMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/distMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( distMapUnitScale ) );
   layer->setCustomProperty( "labeling/offsetType", static_cast< unsigned int >( offsetType ) );
   layer->setCustomProperty( "labeling/quadOffset", static_cast< unsigned int >( quadOffset ) );
   layer->setCustomProperty( "labeling/xOffset", xOffset );
   layer->setCustomProperty( "labeling/yOffset", yOffset );
   layer->setCustomProperty( "labeling/labelOffsetInMapUnits", labelOffsetInMapUnits );
-  layer->setCustomProperty( "labeling/labelOffsetMapUnitMinScale", labelOffsetMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/labelOffsetMapUnitMaxScale", labelOffsetMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/labelOffsetMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( labelOffsetMapUnitScale ) );
   layer->setCustomProperty( "labeling/angleOffset", angleOffset );
   layer->setCustomProperty( "labeling/preserveRotation", preserveRotation );
   layer->setCustomProperty( "labeling/maxCurvedCharAngleIn", maxCurvedCharAngleIn );
@@ -1142,8 +1220,7 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
   layer->setCustomProperty( "labeling/priority", priority );
   layer->setCustomProperty( "labeling/repeatDistance", repeatDistance );
   layer->setCustomProperty( "labeling/repeatDistanceUnit", repeatDistanceUnit );
-  layer->setCustomProperty( "labeling/repeatDistanceMapUnitMinScale", repeatDistanceMapUnitScale.minScale );
-  layer->setCustomProperty( "labeling/repeatDistanceMapUnitMaxScale", repeatDistanceMapUnitScale.maxScale );
+  layer->setCustomProperty( "labeling/repeatDistanceMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( repeatDistanceMapUnitScale ) );
 
   // rendering
   layer->setCustomProperty( "labeling/scaleVisibility", scaleVisibility );
@@ -1196,8 +1273,16 @@ void QgsPalLayerSettings::readXml( QDomElement& elem )
 
   double fontSize = textStyleElem.attribute( "fontSize" ).toDouble();
   fontSizeInMapUnits = textStyleElem.attribute( "fontSizeInMapUnits" ).toInt();
-  fontSizeMapUnitScale.minScale = textStyleElem.attribute( "fontSizeMapUnitMinScale", "0" ).toDouble();
-  fontSizeMapUnitScale.maxScale = textStyleElem.attribute( "fontSizeMapUnitMaxScale", "0" ).toDouble();
+  if ( !textStyleElem.hasAttribute( "fontSizeMapUnitScale" ) )
+  {
+    //fallback to older property
+    fontSizeMapUnitScale.minScale = textStyleElem.attribute( "fontSizeMapUnitMinScale", "0" ).toDouble();
+    fontSizeMapUnitScale.maxScale = textStyleElem.attribute( "fontSizeMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    fontSizeMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( textStyleElem.attribute( "fontSizeMapUnitScale" ) );
+  }
   int fontWeight = textStyleElem.attribute( "fontWeight" ).toInt();
   bool fontItalic = textStyleElem.attribute( "fontItalic" ).toInt();
   textFont = QFont( fontFamily, fontSize, fontWeight, fontItalic );
@@ -1253,8 +1338,16 @@ void QgsPalLayerSettings::readXml( QDomElement& elem )
   }
 
   bufferSizeInMapUnits = textBufferElem.attribute( "bufferSizeInMapUnits" ).toInt();
-  bufferSizeMapUnitScale.minScale = textBufferElem.attribute( "bufferSizeMapUnitMinScale", "0" ).toDouble();
-  bufferSizeMapUnitScale.maxScale = textBufferElem.attribute( "bufferSizeMapUnitMaxScale", "0" ).toDouble();
+  if ( !textBufferElem.hasAttribute( "bufferSizeMapUnitScale" ) )
+  {
+    //fallback to older property
+    bufferSizeMapUnitScale.minScale = textBufferElem.attribute( "bufferSizeMapUnitMinScale", "0" ).toDouble();
+    bufferSizeMapUnitScale.maxScale = textBufferElem.attribute( "bufferSizeMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    bufferSizeMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( textBufferElem.attribute( "bufferSizeMapUnitScale" ) );
+  }
   bufferColor = QgsSymbolLayerV2Utils::decodeColor( textBufferElem.attribute( "bufferColor", QgsSymbolLayerV2Utils::encodeColor( Qt::white ) ) );
   bufferTransp = textBufferElem.attribute( "bufferTransp" ).toInt();
   bufferBlendMode = QgsMapRenderer::getCompositionMode(
@@ -1271,26 +1364,58 @@ void QgsPalLayerSettings::readXml( QDomElement& elem )
   shapeSize = QPointF( backgroundElem.attribute( "shapeSizeX", "0" ).toDouble(),
                        backgroundElem.attribute( "shapeSizeY", "0" ).toDouble() );
   shapeSizeUnits = static_cast< SizeUnit >( backgroundElem.attribute( "shapeSizeUnits", QString::number( MM ) ).toUInt() );
-  shapeSizeMapUnitScale.minScale = backgroundElem.attribute( "shapeSizeMapUnitMinScale", "0" ).toDouble();
-  shapeSizeMapUnitScale.maxScale = backgroundElem.attribute( "shapeSizeMapUnitMaxScale", "0" ).toDouble();
+  if ( !backgroundElem.hasAttribute( "shapeSizeMapUnitScale" ) )
+  {
+    //fallback to older property
+    shapeSizeMapUnitScale.minScale = backgroundElem.attribute( "shapeSizeMapUnitMinScale", "0" ).toDouble();
+    shapeSizeMapUnitScale.maxScale = backgroundElem.attribute( "shapeSizeMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    shapeSizeMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( backgroundElem.attribute( "shapeSizeMapUnitScale" ) );
+  }
   shapeRotationType = static_cast< RotationType >( backgroundElem.attribute( "shapeRotationType", QString::number( RotationSync ) ).toUInt() );
   shapeRotation = backgroundElem.attribute( "shapeRotation", "0" ).toDouble();
   shapeOffset = QPointF( backgroundElem.attribute( "shapeOffsetX", "0" ).toDouble(),
                          backgroundElem.attribute( "shapeOffsetY", "0" ).toDouble() );
   shapeOffsetUnits = static_cast< SizeUnit >( backgroundElem.attribute( "shapeOffsetUnits", QString::number( MM ) ).toUInt() );
-  shapeOffsetMapUnitScale.minScale = backgroundElem.attribute( "shapeOffsetMapUnitMinScale", "0" ).toDouble();
-  shapeOffsetMapUnitScale.maxScale = backgroundElem.attribute( "shapeOffsetMapUnitMaxScale", "0" ).toDouble();
+  if ( !backgroundElem.hasAttribute( "shapeOffsetMapUnitScale" ) )
+  {
+    //fallback to older property
+    shapeOffsetMapUnitScale.minScale = backgroundElem.attribute( "shapeOffsetMapUnitMinScale", "0" ).toDouble();
+    shapeOffsetMapUnitScale.maxScale = backgroundElem.attribute( "shapeOffsetMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    shapeOffsetMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( backgroundElem.attribute( "shapeOffsetMapUnitScale" ) );
+  }
   shapeRadii = QPointF( backgroundElem.attribute( "shapeRadiiX", "0" ).toDouble(),
                         backgroundElem.attribute( "shapeRadiiY", "0" ).toDouble() );
   shapeRadiiUnits = static_cast< SizeUnit >( backgroundElem.attribute( "shapeRadiiUnits", QString::number( MM ) ).toUInt() );
-  shapeRadiiMapUnitScale.minScale = backgroundElem.attribute( "shapeRaddiMapUnitMinScale", "0" ).toDouble();
-  shapeRadiiMapUnitScale.maxScale = backgroundElem.attribute( "shapeRaddiMapUnitMaxScale", "0" ).toDouble();
+  if ( !backgroundElem.hasAttribute( "shapeRadiiMapUnitScale" ) )
+  {
+    //fallback to older property
+    shapeRadiiMapUnitScale.minScale = backgroundElem.attribute( "shapeRadiiMapUnitMinScale", "0" ).toDouble();
+    shapeRadiiMapUnitScale.maxScale = backgroundElem.attribute( "shapeRadiiMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    shapeRadiiMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( backgroundElem.attribute( "shapeRadiiMapUnitScale" ) );
+  }
   shapeFillColor = QgsSymbolLayerV2Utils::decodeColor( backgroundElem.attribute( "shapeFillColor", QgsSymbolLayerV2Utils::encodeColor( Qt::white ) ) );
   shapeBorderColor = QgsSymbolLayerV2Utils::decodeColor( backgroundElem.attribute( "shapeBorderColor", QgsSymbolLayerV2Utils::encodeColor( Qt::darkGray ) ) );
   shapeBorderWidth = backgroundElem.attribute( "shapeBorderWidth", "0" ).toDouble();
   shapeBorderWidthUnits = static_cast< SizeUnit >( backgroundElem.attribute( "shapeBorderWidthUnits", QString::number( MM ) ).toUInt() );
-  shapeBorderWidthMapUnitScale.minScale = backgroundElem.attribute( "shapeBorderWidthMapUnitMinScale", "0" ).toDouble();
-  shapeBorderWidthMapUnitScale.maxScale = backgroundElem.attribute( "shapeBorderWidthMapUnitMaxScale", "0" ).toDouble();
+  if ( !backgroundElem.hasAttribute( "shapeBorderWidthMapUnitScale" ) )
+  {
+    //fallback to older property
+    shapeBorderWidthMapUnitScale.minScale = backgroundElem.attribute( "shapeBorderWidthMapUnitMinScale", "0" ).toDouble();
+    shapeBorderWidthMapUnitScale.maxScale = backgroundElem.attribute( "shapeBorderWidthMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    shapeBorderWidthMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( backgroundElem.attribute( "shapeBorderWidthMapUnitScale" ) );
+  }
   shapeJoinStyle = static_cast< Qt::PenJoinStyle >( backgroundElem.attribute( "shapeJoinStyle", QString::number( Qt::BevelJoin ) ).toUInt() );
   shapeTransparency = backgroundElem.attribute( "shapeTransparency", "0" ).toInt();
   shapeBlendMode = QgsMapRenderer::getCompositionMode(
@@ -1303,13 +1428,29 @@ void QgsPalLayerSettings::readXml( QDomElement& elem )
   shadowOffsetAngle = shadowElem.attribute( "shadowOffsetAngle", "135" ).toInt();
   shadowOffsetDist = shadowElem.attribute( "shadowOffsetDist", "1" ).toDouble();
   shadowOffsetUnits = static_cast< SizeUnit >( shadowElem.attribute( "shadowOffsetUnits", QString::number( MM ) ).toUInt() );
-  shadowOffsetMapUnitScale.minScale = shadowElem.attribute( "shadowOffsetMapUnitMinScale", "0" ).toDouble();
-  shadowOffsetMapUnitScale.maxScale = shadowElem.attribute( "shadowOffsetMapUnitMaxScale", "0" ).toDouble();
+  if ( !shadowElem.hasAttribute( "shadowOffsetMapUnitScale" ) )
+  {
+    //fallback to older property
+    shadowOffsetMapUnitScale.minScale = shadowElem.attribute( "shadowOffsetMapUnitMinScale", "0" ).toDouble();
+    shadowOffsetMapUnitScale.maxScale = shadowElem.attribute( "shadowOffsetMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    shadowOffsetMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( shadowElem.attribute( "shadowOffsetMapUnitScale" ) );
+  }
   shadowOffsetGlobal = shadowElem.attribute( "shadowOffsetGlobal", "1" ).toInt();
   shadowRadius = shadowElem.attribute( "shadowRadius", "1.5" ).toDouble();
   shadowRadiusUnits = static_cast< SizeUnit >( shadowElem.attribute( "shadowRadiusUnits", QString::number( MM ) ).toUInt() );
-  shadowRadiusMapUnitScale.minScale = shadowElem.attribute( "shadowRadiusMapUnitMinScale", "0" ).toDouble();
-  shadowRadiusMapUnitScale.maxScale = shadowElem.attribute( "shadowRadiusMapUnitMaxScale", "0" ).toDouble();
+  if ( !shadowElem.hasAttribute( "shadowRadiusMapUnitScale" ) )
+  {
+    //fallback to older property
+    shadowRadiusMapUnitScale.minScale = shadowElem.attribute( "shadowRadiusMapUnitMinScale", "0" ).toDouble();
+    shadowRadiusMapUnitScale.maxScale = shadowElem.attribute( "shadowRadiusMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    shadowRadiusMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( shadowElem.attribute( "shadowRadiusMapUnitScale" ) );
+  }
   shadowRadiusAlphaOnly = shadowElem.attribute( "shadowRadiusAlphaOnly", "0" ).toInt();
   shadowTransparency = shadowElem.attribute( "shadowTransparency", "30" ).toInt();
   shadowScale = shadowElem.attribute( "shadowScale", "100" ).toInt();
@@ -1329,15 +1470,31 @@ void QgsPalLayerSettings::readXml( QDomElement& elem )
   fitInPolygonOnly = placementElem.attribute( "fitInPolygonOnly", "0" ).toInt();
   dist = placementElem.attribute( "dist" ).toDouble();
   distInMapUnits = placementElem.attribute( "distInMapUnits" ).toInt();
-  distMapUnitScale.minScale = placementElem.attribute( "distMapUnitMinScale", "0" ).toDouble();
-  distMapUnitScale.maxScale = placementElem.attribute( "distMapUnitMaxScale", "0" ).toDouble();
+  if ( !placementElem.hasAttribute( "distMapUnitScale" ) )
+  {
+    //fallback to older property
+    distMapUnitScale.minScale = placementElem.attribute( "distMapUnitMinScale", "0" ).toDouble();
+    distMapUnitScale.maxScale = placementElem.attribute( "distMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    distMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( placementElem.attribute( "distMapUnitScale" ) );
+  }
   offsetType = static_cast< OffsetType >( placementElem.attribute( "offsetType", QString::number( FromPoint ) ).toUInt() );
   quadOffset = static_cast< QuadrantPosition >( placementElem.attribute( "quadOffset", QString::number( QuadrantOver ) ).toUInt() );
   xOffset = placementElem.attribute( "xOffset", "0" ).toDouble();
   yOffset = placementElem.attribute( "yOffset", "0" ).toDouble();
   labelOffsetInMapUnits = placementElem.attribute( "labelOffsetInMapUnits", "1" ).toInt();
-  labelOffsetMapUnitScale.minScale = placementElem.attribute( "labelOffsetMapUnitMinScale", "0" ).toDouble();
-  labelOffsetMapUnitScale.maxScale = placementElem.attribute( "labelOffsetMapUnitMaxScale", "0" ).toDouble();
+  if ( !placementElem.hasAttribute( "labelOffsetMapUnitScale" ) )
+  {
+    //fallback to older property
+    labelOffsetMapUnitScale.minScale = placementElem.attribute( "labelOffsetMapUnitMinScale", "0" ).toDouble();
+    labelOffsetMapUnitScale.maxScale = placementElem.attribute( "labelOffsetMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    labelOffsetMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( placementElem.attribute( "labelOffsetMapUnitScale" ) );
+  }
   angleOffset = placementElem.attribute( "angleOffset", "0" ).toDouble();
   preserveRotation = placementElem.attribute( "preserveRotation", "1" ).toInt();
   maxCurvedCharAngleIn = placementElem.attribute( "maxCurvedCharAngleIn", "20" ).toDouble();
@@ -1345,8 +1502,16 @@ void QgsPalLayerSettings::readXml( QDomElement& elem )
   priority = placementElem.attribute( "priority" ).toInt();
   repeatDistance = placementElem.attribute( "repeatDistance", "0" ).toDouble();
   repeatDistanceUnit = static_cast< SizeUnit >( placementElem.attribute( "repeatDistanceUnit", QString::number( MM ) ).toUInt() );
-  repeatDistanceMapUnitScale.minScale = placementElem.attribute( "repeatDistanceMapUnitMinScale", "0" ).toDouble();
-  repeatDistanceMapUnitScale.maxScale = placementElem.attribute( "repeatDistanceMapUnitMaxScale", "0" ).toDouble();
+  if ( !placementElem.hasAttribute( "repeatDistanceMapUnitScale" ) )
+  {
+    //fallback to older property
+    repeatDistanceMapUnitScale.minScale = placementElem.attribute( "repeatDistanceMapUnitMinScale", "0" ).toDouble();
+    repeatDistanceMapUnitScale.maxScale = placementElem.attribute( "repeatDistanceMapUnitMaxScale", "0" ).toDouble();
+  }
+  else
+  {
+    repeatDistanceMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( placementElem.attribute( "repeatDistanceMapUnitScale" ) );
+  }
 
   // rendering
   QDomElement renderingElem = elem.firstChildElement( "rendering" );
@@ -1388,8 +1553,7 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc )
   textStyleElem.setAttribute( "namedStyle", QgsFontUtils::untranslateNamedStyle( textNamedStyle ) );
   textStyleElem.setAttribute( "fontSize", textFont.pointSizeF() );
   textStyleElem.setAttribute( "fontSizeInMapUnits", fontSizeInMapUnits );
-  textStyleElem.setAttribute( "fontSizeMapUnitMinScale", fontSizeMapUnitScale.minScale );
-  textStyleElem.setAttribute( "fontSizeMapUnitMaxScale", fontSizeMapUnitScale.maxScale );
+  textStyleElem.setAttribute( "fontSizeMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( fontSizeMapUnitScale ) );
   textStyleElem.setAttribute( "fontWeight", textFont.weight() );
   textStyleElem.setAttribute( "fontItalic", textFont.italic() );
   textStyleElem.setAttribute( "fontStrikeout", textFont.strikeOut() );
@@ -1421,8 +1585,7 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc )
   textBufferElem.setAttribute( "bufferDraw", bufferDraw );
   textBufferElem.setAttribute( "bufferSize", bufferSize );
   textBufferElem.setAttribute( "bufferSizeInMapUnits", bufferSizeInMapUnits );
-  textBufferElem.setAttribute( "bufferSizeMapUnitMinScale", bufferSizeMapUnitScale.minScale );
-  textBufferElem.setAttribute( "bufferSizeMapUnitMaxScale", bufferSizeMapUnitScale.maxScale );
+  textBufferElem.setAttribute( "bufferSizeMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( bufferSizeMapUnitScale ) );
   textBufferElem.setAttribute( "bufferColor", QgsSymbolLayerV2Utils::encodeColor( bufferColor ) );
   textBufferElem.setAttribute( "bufferNoFill", bufferNoFill );
   textBufferElem.setAttribute( "bufferTransp", bufferTransp );
@@ -1438,26 +1601,22 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc )
   backgroundElem.setAttribute( "shapeSizeX", shapeSize.x() );
   backgroundElem.setAttribute( "shapeSizeY", shapeSize.y() );
   backgroundElem.setAttribute( "shapeSizeUnits", static_cast< unsigned int >( shapeSizeUnits ) );
-  backgroundElem.setAttribute( "shapeSizeMapUnitMinScale", shapeSizeMapUnitScale.minScale );
-  backgroundElem.setAttribute( "shapeSizeMapUnitMaxScale", shapeSizeMapUnitScale.maxScale );
+  backgroundElem.setAttribute( "shapeSizeMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shapeSizeMapUnitScale ) );
   backgroundElem.setAttribute( "shapeRotationType", static_cast< unsigned int >( shapeRotationType ) );
   backgroundElem.setAttribute( "shapeRotation", shapeRotation );
   backgroundElem.setAttribute( "shapeOffsetX", shapeOffset.x() );
   backgroundElem.setAttribute( "shapeOffsetY", shapeOffset.y() );
   backgroundElem.setAttribute( "shapeOffsetUnits", static_cast< unsigned int >( shapeOffsetUnits ) );
-  backgroundElem.setAttribute( "shapeOffsetMapUnitMinScale", shapeOffsetMapUnitScale.minScale );
-  backgroundElem.setAttribute( "shapeOffsetMapUnitMaxScale", shapeOffsetMapUnitScale.maxScale );
+  backgroundElem.setAttribute( "shapeOffsetMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shapeOffsetMapUnitScale ) );
   backgroundElem.setAttribute( "shapeRadiiX", shapeRadii.x() );
   backgroundElem.setAttribute( "shapeRadiiY", shapeRadii.y() );
   backgroundElem.setAttribute( "shapeRadiiUnits", static_cast< unsigned int >( shapeRadiiUnits ) );
-  backgroundElem.setAttribute( "shapeRadiiMapUnitMinScale", shapeRadiiMapUnitScale.minScale );
-  backgroundElem.setAttribute( "shapeRadiiMapUnitMaxScale", shapeRadiiMapUnitScale.maxScale );
+  backgroundElem.setAttribute( "shapeRadiiMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shapeRadiiMapUnitScale ) );
   backgroundElem.setAttribute( "shapeFillColor", QgsSymbolLayerV2Utils::encodeColor( shapeFillColor ) );
   backgroundElem.setAttribute( "shapeBorderColor", QgsSymbolLayerV2Utils::encodeColor( shapeBorderColor ) );
   backgroundElem.setAttribute( "shapeBorderWidth", shapeBorderWidth );
   backgroundElem.setAttribute( "shapeBorderWidthUnits", static_cast< unsigned int >( shapeBorderWidthUnits ) );
-  backgroundElem.setAttribute( "shapeBorderWidthMapUnitMinScale", shapeBorderWidthMapUnitScale.minScale );
-  backgroundElem.setAttribute( "shapeBorderWidthMapUnitMaxScale", shapeBorderWidthMapUnitScale.maxScale );
+  backgroundElem.setAttribute( "shapeBorderWidthMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shapeBorderWidthMapUnitScale ) );
   backgroundElem.setAttribute( "shapeJoinStyle", static_cast< unsigned int >( shapeJoinStyle ) );
   backgroundElem.setAttribute( "shapeTransparency", shapeTransparency );
   backgroundElem.setAttribute( "shapeBlendMode", QgsMapRenderer::getBlendModeEnum( shapeBlendMode ) );
@@ -1469,13 +1628,11 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc )
   shadowElem.setAttribute( "shadowOffsetAngle", shadowOffsetAngle );
   shadowElem.setAttribute( "shadowOffsetDist", shadowOffsetDist );
   shadowElem.setAttribute( "shadowOffsetUnits", static_cast< unsigned int >( shadowOffsetUnits ) );
-  shadowElem.setAttribute( "shadowOffsetMapUnitMinScale", shadowOffsetMapUnitScale.minScale );
-  shadowElem.setAttribute( "shadowOffsetMapUnitMaxScale", shadowOffsetMapUnitScale.maxScale );
+  shadowElem.setAttribute( "shadowOffsetMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shadowOffsetMapUnitScale ) );
   shadowElem.setAttribute( "shadowOffsetGlobal", shadowOffsetGlobal );
   shadowElem.setAttribute( "shadowRadius", shadowRadius );
   shadowElem.setAttribute( "shadowRadiusUnits", static_cast< unsigned int >( shadowRadiusUnits ) );
-  shadowElem.setAttribute( "shadowRadiusMapUnitMinScale", shadowRadiusMapUnitScale.minScale );
-  shadowElem.setAttribute( "shadowRadiusMapUnitMaxScale", shadowRadiusMapUnitScale.maxScale );
+  shadowElem.setAttribute( "shadowRadiusMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( shadowRadiusMapUnitScale ) );
   shadowElem.setAttribute( "shadowRadiusAlphaOnly", shadowRadiusAlphaOnly );
   shadowElem.setAttribute( "shadowTransparency", shadowTransparency );
   shadowElem.setAttribute( "shadowScale", shadowScale );
@@ -1492,15 +1649,13 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc )
   placementElem.setAttribute( "fitInPolygonOnly", fitInPolygonOnly );
   placementElem.setAttribute( "dist", dist );
   placementElem.setAttribute( "distInMapUnits", distInMapUnits );
-  placementElem.setAttribute( "distMapUnitMinScale", distMapUnitScale.minScale );
-  placementElem.setAttribute( "distMapUnitMaxScale", distMapUnitScale.maxScale );
+  placementElem.setAttribute( "distMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( distMapUnitScale ) );
   placementElem.setAttribute( "offsetType", static_cast< unsigned int >( offsetType ) );
   placementElem.setAttribute( "quadOffset", static_cast< unsigned int >( quadOffset ) );
   placementElem.setAttribute( "xOffset", xOffset );
   placementElem.setAttribute( "yOffset", yOffset );
   placementElem.setAttribute( "labelOffsetInMapUnits", labelOffsetInMapUnits );
-  placementElem.setAttribute( "labelOffsetMapUnitMinScale", labelOffsetMapUnitScale.minScale );
-  placementElem.setAttribute( "labelOffsetMapUnitMaxScale", labelOffsetMapUnitScale.maxScale );
+  placementElem.setAttribute( "labelOffsetMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( labelOffsetMapUnitScale ) );
   placementElem.setAttribute( "angleOffset", angleOffset );
   placementElem.setAttribute( "preserveRotation", preserveRotation );
   placementElem.setAttribute( "maxCurvedCharAngleIn", maxCurvedCharAngleIn );
@@ -1508,8 +1663,7 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc )
   placementElem.setAttribute( "priority", priority );
   placementElem.setAttribute( "repeatDistance", repeatDistance );
   placementElem.setAttribute( "repeatDistanceUnit", repeatDistanceUnit );
-  placementElem.setAttribute( "repeatDistanceMapUnitMinScale", repeatDistanceMapUnitScale.minScale );
-  placementElem.setAttribute( "repeatDistanceMapUnitMaxScale", repeatDistanceMapUnitScale.maxScale );
+  placementElem.setAttribute( "repeatDistanceMapUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( repeatDistanceMapUnitScale ) );
 
   // rendering
   QDomElement renderingElem = doc.createElement( "rendering" );
diff --git a/src/core/qgstracer.cpp b/src/core/qgstracer.cpp
index 5aa5b4e..bf92286 100644
--- a/src/core/qgstracer.cpp
+++ b/src/core/qgstracer.cpp
@@ -17,6 +17,7 @@
 
 #include "qgsgeometry.h"
 #include "qgsgeometryutils.h"
+#include "qgsgeos.h"
 #include "qgslogger.h"
 #include "qgsvectorlayer.h"
 
@@ -439,6 +440,7 @@ QgsTracer::QgsTracer()
     : mGraph( 0 )
     , mReprojectionEnabled( false )
     , mMaxFeatureCount( 0 )
+    , mHasTopologyProblem( false )
 {
 }
 
@@ -448,6 +450,8 @@ bool QgsTracer::initGraph()
   if ( mGraph )
     return true; // already initialized
 
+  mHasTopologyProblem = false;
+
   QgsFeature f;
   QgsMultiPolyline mpl;
 
@@ -499,23 +503,37 @@ bool QgsTracer::initGraph()
 
   t2.start();
 
+  int timeNodingCall = 0;
+
 #if 0
   // without noding - if data are known to be noded beforehand
-  int timeNodingCall = 0;
 #else
   QgsGeometry* allGeom = QgsGeometry::fromMultiPolyline( mpl );
 
-  t2a.start();
-  GEOSGeometry* allNoded = GEOSNode_r( QgsGeometry::getGEOSHandler(), allGeom->asGeos() );
-  int timeNodingCall = t2a.elapsed();
+  try
+  {
+    t2a.start();
+    // GEOSNode_r may throw an exception
+    GEOSGeometry* allNoded = GEOSNode_r( QgsGeometry::getGEOSHandler(), allGeom->asGeos() );
+    timeNodingCall = t2a.elapsed();
+
+    QgsGeometry* noded = new QgsGeometry;
+    noded->fromGeos( allNoded );
+    delete allGeom;
 
-  QgsGeometry* noded = new QgsGeometry;
-  noded->fromGeos( allNoded );
-  delete allGeom;
+    mpl = noded->asMultiPolyline();
 
-  mpl = noded->asMultiPolyline();
+    delete noded;
+  }
+  catch ( GEOSException &e )
+  {
+    // no big deal... we will just not have nicely noded linework, potentially
+    // missing some intersections
 
-  delete noded;
+    mHasTopologyProblem = true;
+
+    QgsDebugMsg( "Tracer Noding Exception: " + e.what() );
+  }
 #endif
 
   int timeNoding = t2.elapsed();
diff --git a/src/core/qgstracer.h b/src/core/qgstracer.h
index cb99dd3..dd3a503 100644
--- a/src/core/qgstracer.h
+++ b/src/core/qgstracer.h
@@ -76,6 +76,11 @@ class CORE_EXPORT QgsTracer : public QObject
     //! Whether the internal data structures have been initialized
     bool isInitialized() const { return mGraph != nullptr; }
 
+    //! Whether there was an error during graph creation due to noding exception,
+    //! indicating some input data topology problems
+    //! @note added in QGIS 2.14.2
+    bool hasTopologyProblem() const { return mHasTopologyProblem; }
+
     //! Possible errors that may happen when calling findShortestPath()
     enum PathError
     {
@@ -127,6 +132,9 @@ class CORE_EXPORT QgsTracer : public QObject
     //! Limit of how many features can be in the graph (0 means no limit).
     //! This is to avoid possibly long graph preparation for complicated layers
     int mMaxFeatureCount;
+    //! A flag indicating that there was an error during graph creation
+    //! due to noding exception, indicating some input data topology problems
+    bool mHasTopologyProblem;
 };
 
 
diff --git a/src/core/qgsvectordataprovider.cpp b/src/core/qgsvectordataprovider.cpp
index 1edb74d..7a4cebd 100644
--- a/src/core/qgsvectordataprovider.cpp
+++ b/src/core/qgsvectordataprovider.cpp
@@ -18,6 +18,7 @@
 
 #include <cfloat> // for DBL_MAX
 #include <climits>
+#include <limits>
 
 #include "qgsvectordataprovider.h"
 #include "qgsfeature.h"
@@ -402,6 +403,11 @@ void QgsVectorDataProvider::fillMinMaxCache()
       mCacheMinValues[i] = QVariant( INT_MAX );
       mCacheMaxValues[i] = QVariant( INT_MIN );
     }
+    else if ( flds[i].type() == QVariant::LongLong )
+    {
+      mCacheMinValues[i] = QVariant( std::numeric_limits<qlonglong>::max() );
+      mCacheMaxValues[i] = QVariant( std::numeric_limits<qlonglong>::min() );
+    }
     else if ( flds[i].type() == QVariant::Double )
     {
       mCacheMinValues[i] = QVariant( DBL_MAX );
@@ -436,6 +442,14 @@ void QgsVectorDataProvider::fillMinMaxCache()
         if ( value > mCacheMaxValues[*it].toInt() )
           mCacheMaxValues[*it] = value;
       }
+      else if ( flds[*it].type() == QVariant::LongLong )
+      {
+        qlonglong value = varValue.toLongLong();
+        if ( value < mCacheMinValues[*it].toLongLong() )
+          mCacheMinValues[*it] = value;
+        if ( value > mCacheMaxValues[*it].toLongLong() )
+          mCacheMaxValues[*it] = value;
+      }
       else if ( flds[*it].type() == QVariant::Double )
       {
         double value = varValue.toDouble();
diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp
index df0c016..851954d 100644
--- a/src/core/qgsvectorlayer.cpp
+++ b/src/core/qgsvectorlayer.cpp
@@ -1004,7 +1004,10 @@ bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId,
     return false;
 
   QgsVectorLayerEditUtils utils( this );
-  return utils.insertVertex( x, y, atFeatureId, beforeVertex );
+  bool result = utils.insertVertex( x, y, atFeatureId, beforeVertex );
+  if ( result )
+    updateExtents();
+  return result;
 }
 
 
@@ -1014,7 +1017,11 @@ bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, i
     return false;
 
   QgsVectorLayerEditUtils utils( this );
-  return utils.moveVertex( x, y, atFeatureId, atVertex );
+  bool result = utils.moveVertex( x, y, atFeatureId, atVertex );
+
+  if ( result )
+    updateExtents();
+  return result;
 }
 
 bool QgsVectorLayer::moveVertex( const QgsPointV2& p, QgsFeatureId atFeatureId, int atVertex )
@@ -1023,13 +1030,21 @@ bool QgsVectorLayer::moveVertex( const QgsPointV2& p, QgsFeatureId atFeatureId,
     return false;
 
   QgsVectorLayerEditUtils utils( this );
-  return utils.moveVertex( p, atFeatureId, atVertex );
+  bool result = utils.moveVertex( p, atFeatureId, atVertex );
+
+  if ( result )
+    updateExtents();
+  return result;
 }
 
 bool QgsVectorLayer::deleteVertex( QgsFeatureId atFeatureId, int atVertex )
 {
   QgsVectorLayer::EditResult res = deleteVertexV2( atFeatureId, atVertex );
-  return res == QgsVectorLayer::Success || res == QgsVectorLayer::EmptyGeometry;
+  bool result = ( res == QgsVectorLayer::Success || res == QgsVectorLayer::EmptyGeometry );
+
+  if ( result )
+    updateExtents();
+  return result;
 }
 
 QgsVectorLayer::EditResult QgsVectorLayer::deleteVertexV2( QgsFeatureId featureId, int vertex )
@@ -1038,7 +1053,11 @@ QgsVectorLayer::EditResult QgsVectorLayer::deleteVertexV2( QgsFeatureId featureI
     return QgsVectorLayer::InvalidLayer;
 
   QgsVectorLayerEditUtils utils( this );
-  return utils.deleteVertexV2( featureId, vertex );
+  EditResult result = utils.deleteVertexV2( featureId, vertex );
+
+  if ( result == Success )
+    updateExtents();
+  return result;
 }
 
 
@@ -1154,7 +1173,11 @@ int QgsVectorLayer::addPart( const QList<QgsPoint> &points )
   }
 
   QgsVectorLayerEditUtils utils( this );
-  return utils.addPart( points, *mSelectedFeatureIds.constBegin() );
+  int result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
+
+  if ( result == 0 )
+    updateExtents();
+  return result;
 }
 
 int QgsVectorLayer::addPart( const QgsPointSequenceV2 &points )
@@ -1176,7 +1199,11 @@ int QgsVectorLayer::addPart( const QgsPointSequenceV2 &points )
   }
 
   QgsVectorLayerEditUtils utils( this );
-  return utils.addPart( points, *mSelectedFeatureIds.constBegin() );
+  int result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
+
+  if ( result == 0 )
+    updateExtents();
+  return result;
 }
 
 int QgsVectorLayer::addPart( QgsCurveV2* ring )
@@ -1198,7 +1225,11 @@ int QgsVectorLayer::addPart( QgsCurveV2* ring )
   }
 
   QgsVectorLayerEditUtils utils( this );
-  return utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
+  int result = utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
+
+  if ( result == 0 )
+    updateExtents();
+  return result;
 }
 
 int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
@@ -1207,7 +1238,11 @@ int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double
     return -1;
 
   QgsVectorLayerEditUtils utils( this );
-  return utils.translateFeature( featureId, dx, dy );
+  int result = utils.translateFeature( featureId, dx, dy );
+
+  if ( result == 0 )
+    updateExtents();
+  return result;
 }
 
 int QgsVectorLayer::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
@@ -2093,7 +2128,11 @@ bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, QgsGeometry* geom )
 
   updateExtents();
 
-  return mEditBuffer->changeGeometry( fid, geom );
+  bool result = mEditBuffer->changeGeometry( fid, geom );
+
+  if ( result )
+    updateExtents();
+  return result;
 }
 
 
@@ -2210,9 +2249,10 @@ bool QgsVectorLayer::deleteFeature( QgsFeatureId fid )
 
   bool res = mEditBuffer->deleteFeature( fid );
   if ( res )
+  {
     mSelectedFeatureIds.remove( fid ); // remove it from selection
-
-  updateExtents();
+    updateExtents();
+  }
 
   return res;
 }
@@ -2225,9 +2265,10 @@ bool QgsVectorLayer::deleteFeatures( const QgsFeatureIds& fids )
   bool res = mEditBuffer->deleteFeatures( fids );
 
   if ( res )
+  {
     mSelectedFeatureIds.subtract( fids ); // remove it from selection
-
-  updateExtents();
+    updateExtents();
+  }
 
   return res;
 }
diff --git a/src/core/qgsvectorlayerlabelprovider.cpp b/src/core/qgsvectorlayerlabelprovider.cpp
index fb81278..4807264 100644
--- a/src/core/qgsvectorlayerlabelprovider.cpp
+++ b/src/core/qgsvectorlayerlabelprovider.cpp
@@ -353,9 +353,9 @@ QgsGeometry* QgsVectorLayerLabelProvider::getPointObstacleGeometry( QgsFeature&
       if ( symbol->type() == QgsSymbolV2::Marker )
       {
         if ( bounds.isValid() )
-          bounds = bounds.united( static_cast< QgsMarkerSymbolV2* >( symbol )->bounds( pt, context ) );
+          bounds = bounds.united( static_cast< QgsMarkerSymbolV2* >( symbol )->bounds( pt, context, fet ) );
         else
-          bounds = static_cast< QgsMarkerSymbolV2* >( symbol )->bounds( pt, context );
+          bounds = static_cast< QgsMarkerSymbolV2* >( symbol )->bounds( pt, context, fet );
       }
     }
 
diff --git a/src/core/symbology-ng/qgsellipsesymbollayerv2.cpp b/src/core/symbology-ng/qgsellipsesymbollayerv2.cpp
index 86bb805..16b14db 100644
--- a/src/core/symbology-ng/qgsellipsesymbollayerv2.cpp
+++ b/src/core/symbology-ng/qgsellipsesymbollayerv2.cpp
@@ -348,7 +348,31 @@ void QgsEllipseSymbolLayerV2::stopRender( QgsSymbolV2RenderContext & )
 
 QgsEllipseSymbolLayerV2* QgsEllipseSymbolLayerV2::clone() const
 {
-  return dynamic_cast< QgsEllipseSymbolLayerV2* >( QgsEllipseSymbolLayerV2::create( properties() ) );
+  QgsEllipseSymbolLayerV2* m = new QgsEllipseSymbolLayerV2();
+  m->setSymbolName( mSymbolName );
+  m->setSymbolWidth( mSymbolWidth );
+  m->setSymbolHeight( mSymbolHeight );
+  m->setOutlineStyle( mOutlineStyle );
+  m->setOffset( mOffset );
+  m->setOffsetUnit( mOffsetUnit );
+  m->setOffsetMapUnitScale( mOffsetMapUnitScale );
+  m->setOutlineStyle( mOutlineStyle );
+  m->setOutlineWidth( mOutlineWidth );
+  m->setColor( color() );
+  m->setOutlineColor( mOutlineColor );
+  m->setSymbolWidthUnit( mSymbolWidthUnit );
+  m->setSymbolWidthMapUnitScale( mSymbolWidthMapUnitScale );
+  m->setSymbolHeightUnit( mSymbolHeightUnit );
+  m->setSymbolHeightMapUnitScale( mSymbolHeightMapUnitScale );
+  m->setOutlineWidthUnit( mOutlineWidthUnit );
+  m->setOutlineWidthMapUnitScale( mOutlineWidthMapUnitScale );
+  m->setAngle( mAngle );
+  m->setHorizontalAnchorPoint( mHorizontalAnchorPoint );
+  m->setVerticalAnchorPoint( mVerticalAnchorPoint );
+
+  copyDataDefinedProperties( m );
+  copyPaintEffect( m );
+  return m;
 }
 
 void QgsEllipseSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const
diff --git a/src/core/symbology-ng/qgssymbollayerv2utils.cpp b/src/core/symbology-ng/qgssymbollayerv2utils.cpp
index d79afe7..9c70f30 100644
--- a/src/core/symbology-ng/qgssymbollayerv2utils.cpp
+++ b/src/core/symbology-ng/qgssymbollayerv2utils.cpp
@@ -3590,40 +3590,6 @@ void QgsSymbolLayerV2Utils::premultiplyColor( QColor &rgb, int alpha )
   }
 }
 
-#if 0
-static bool _QVariantLessThan( const QVariant& lhs, const QVariant& rhs )
-{
-  switch ( lhs.type() )
-  {
-    case QVariant::Int:
-      return lhs.toInt() < rhs.toInt();
-    case QVariant::UInt:
-      return lhs.toUInt() < rhs.toUInt();
-    case QVariant::LongLong:
-      return lhs.toLongLong() < rhs.toLongLong();
-    case QVariant::ULongLong:
-      return lhs.toULongLong() < rhs.toULongLong();
-    case QVariant::Double:
-      return lhs.toDouble() < rhs.toDouble();
-    case QVariant::Char:
-      return lhs.toChar() < rhs.toChar();
-    case QVariant::Date:
-      return lhs.toDate() < rhs.toDate();
-    case QVariant::Time:
-      return lhs.toTime() < rhs.toTime();
-    case QVariant::DateTime:
-      return lhs.toDateTime() < rhs.toDateTime();
-    default:
-      return QString::localeAwareCompare( lhs.toString(), rhs.toString() ) < 0;
-  }
-}
-
-static bool _QVariantGreaterThan( const QVariant& lhs, const QVariant& rhs )
-{
-  return ! _QVariantLessThan( lhs, rhs );
-}
-#endif
-
 void QgsSymbolLayerV2Utils::sortVariantList( QList<QVariant>& list, Qt::SortOrder order )
 {
   if ( order == Qt::AscendingOrder )
diff --git a/src/core/symbology-ng/qgssymbolv2.cpp b/src/core/symbology-ng/qgssymbolv2.cpp
index 9bd57f5..1154f12 100644
--- a/src/core/symbology-ng/qgssymbolv2.cpp
+++ b/src/core/symbology-ng/qgssymbolv2.cpp
@@ -758,7 +758,7 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
         //draw debugging rect
         context.painter()->setPen( Qt::red );
         context.painter()->setBrush( QColor( 255, 0, 0, 100 ) );
-        context.painter()->drawRect( static_cast<QgsMarkerSymbolV2*>( this )->bounds( pt, context ) );
+        context.painter()->drawRect( static_cast<QgsMarkerSymbolV2*>( this )->bounds( pt, context, feature ) );
       }
     }
     break;
@@ -934,7 +934,8 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
     delete segmentizedGeometry;
   }
 
-  context.expressionContext().popScope();
+  if ( mSymbolRenderContext->expressionContextScope() )
+    context.expressionContext().popScope();
 }
 
 QgsSymbolV2RenderContext* QgsSymbolV2::symbolRenderContext()
@@ -1189,6 +1190,67 @@ double QgsMarkerSymbolV2::size() const
   return maxSize;
 }
 
+void QgsMarkerSymbolV2::setSizeUnit( QgsSymbolV2::OutputUnit unit )
+{
+  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
+  {
+    if ( layer->type() !=  QgsSymbolV2::Marker )
+      continue;
+
+    QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
+    markerLayer->setSizeUnit( unit );
+  }
+}
+
+QgsSymbolV2::OutputUnit QgsMarkerSymbolV2::sizeUnit() const
+{
+  bool first = true;
+  OutputUnit unit = Mixed;
+
+  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
+  {
+    if ( layer->type() !=  QgsSymbolV2::Marker )
+      continue;
+    const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
+
+    if ( first )
+      unit = markerLayer->sizeUnit();
+    else
+    {
+      if ( unit != markerLayer->sizeUnit() )
+        return Mixed;
+    }
+
+    first = false;
+  }
+  return unit;
+}
+
+void QgsMarkerSymbolV2::setSizeMapUnitScale( const QgsMapUnitScale &scale )
+{
+  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
+  {
+    if ( layer->type() !=  QgsSymbolV2::Marker )
+      continue;
+
+    QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
+    markerLayer->setSizeMapUnitScale( scale );
+  }
+}
+
+QgsMapUnitScale QgsMarkerSymbolV2::sizeMapUnitScale() const
+{
+  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
+  {
+    if ( layer->type() !=  QgsSymbolV2::Marker )
+      continue;
+
+    QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
+    return markerLayer->sizeMapUnitScale();
+  }
+  return QgsMapUnitScale();
+}
+
 void QgsMarkerSymbolV2::setDataDefinedSize( const QgsDataDefined &dd )
 {
   const double symbolSize = size();
@@ -1360,9 +1422,9 @@ void QgsMarkerSymbolV2::renderPoint( QPointF point, const QgsFeature* f, QgsRend
   }
 }
 
-QRectF QgsMarkerSymbolV2::bounds( QPointF point, QgsRenderContext& context ) const
+QRectF QgsMarkerSymbolV2::bounds( QPointF point, QgsRenderContext& context, const QgsFeature& feature ) const
 {
-  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, nullptr, mapUnitScale() );
+  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, &feature, feature.fields(), mapUnitScale() );
 
   QRectF bound;
   Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
diff --git a/src/core/symbology-ng/qgssymbolv2.h b/src/core/symbology-ng/qgssymbolv2.h
index b89bb2e..1183290 100644
--- a/src/core/symbology-ng/qgssymbolv2.h
+++ b/src/core/symbology-ng/qgssymbolv2.h
@@ -424,6 +424,7 @@ class CORE_EXPORT QgsSymbolV2RenderContext
 class CORE_EXPORT QgsMarkerSymbolV2 : public QgsSymbolV2
 {
   public:
+
     /** Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
      * This is a convenience method for easier creation of marker symbols.
      */
@@ -431,7 +432,19 @@ class CORE_EXPORT QgsMarkerSymbolV2 : public QgsSymbolV2
 
     QgsMarkerSymbolV2( const QgsSymbolLayerV2List& layers = QgsSymbolLayerV2List() );
 
+    /** Sets the angle for the whole symbol. Individual symbol layer sizes
+     * will be rotated to maintain their current relative angle to the whole symbol angle.
+     * @param angle new symbol angle
+     * @see angle()
+     */
     void setAngle( double angle );
+
+    /** Returns the marker angle for the whole symbol. Note that for symbols with
+     * multiple symbol layers, this will correspond just to the angle of
+     * the first symbol layer.
+     * @note added in QGIS 2.16
+     * @see setAngle()
+     */
     double angle() const;
 
     /** Set data defined angle for whole symbol (including all symbol layers).
@@ -457,9 +470,60 @@ class CORE_EXPORT QgsMarkerSymbolV2 : public QgsSymbolV2
      */
     void setLineAngle( double lineAngle );
 
+    /** Sets the size for the whole symbol. Individual symbol layer sizes
+     * will be scaled to maintain their current relative size to the whole symbol size.
+     * @param size new symbol size
+     * @see size()
+     * @see setSizeUnit()
+     * @see setSizeMapUnitScale()
+     */
     void setSize( double size );
+
+    /** Returns the size for the whole symbol, which is the maximum size of
+     * all marker symbol layers in the symbol.
+     * @see setSize()
+     * @see sizeUnit()
+     * @see sizeMapUnitScale()
+     */
     double size() const;
 
+    /** Sets the size units for the whole symbol (including all symbol layers).
+     * @param unit size units
+     * @note added in QGIS 2.16
+     * @see sizeUnit()
+     * @see setSizeMapUnitScale()
+     * @see setSize()
+     */
+    void setSizeUnit( OutputUnit unit );
+
+    /** Returns the size units for the whole symbol (including all symbol layers).
+     * @returns size units, or mixed units if symbol layers have different units
+     * @note added in QGIS 2.16
+     * @see setSizeUnit()
+     * @see sizeMapUnitScale()
+     * @see size()
+     */
+    OutputUnit sizeUnit() const;
+
+    /** Sets the size map unit scale for the whole symbol (including all symbol layers).
+     * @param scale map unit scale
+     * @note added in QGIS 2.16
+     * @see sizeMapUnitScale()
+     * @see setSizeUnit()
+     * @see setSize()
+     */
+    void setSizeMapUnitScale( const QgsMapUnitScale& scale );
+
+    /** Returns the size map unit scale for the whole symbol. Note that for symbols with
+     * multiple symbol layers, this will correspond just to the map unit scale
+     * for the first symbol layer.
+     * @note added in QGIS 2.16
+     * @see setSizeMapUnitScale()
+     * @see sizeUnit()
+     * @see size()
+     */
+    QgsMapUnitScale sizeMapUnitScale() const;
+
     /** Set data defined size for whole symbol (including all symbol layers).
      * @param dd data defined size
      * @note added in QGIS 2.9
@@ -481,10 +545,16 @@ class CORE_EXPORT QgsMarkerSymbolV2 : public QgsSymbolV2
     void renderPoint( QPointF point, const QgsFeature* f, QgsRenderContext& context, int layer = -1, bool selected = false );
 
     /** Returns the approximate bounding box of the marker symbol, which includes the bounding box
-     * of all symbol layers for the symbol.
+     * of all symbol layers for the symbol. It is recommended to use this method only between startRender()
+     * and stopRender() calls, or data defined rotation and offset will not be correctly calculated.
+     * @param point location of rendered point in painter units
+     * @param context render context
+     * @param feature feature being rendered at point (optional). If not specified, the bounds calculation will not
+     * include data defined parameters such as offset and rotation
      * @returns approximate symbol bounds, in painter units
-     * @note added in QGIS 2.14     */
-    QRectF bounds( QPointF point, QgsRenderContext& context ) const;
+     * @note added in QGIS 2.14
+    */
+    QRectF bounds( QPointF point, QgsRenderContext& context, const QgsFeature &feature = QgsFeature() ) const;
 
     virtual QgsMarkerSymbolV2* clone() const override;
 
diff --git a/src/gui/attributetable/qgsattributetablefiltermodel.cpp b/src/gui/attributetable/qgsattributetablefiltermodel.cpp
index c64b78e..b7e298a 100644
--- a/src/gui/attributetable/qgsattributetablefiltermodel.cpp
+++ b/src/gui/attributetable/qgsattributetablefiltermodel.cpp
@@ -15,6 +15,7 @@
 
 #include <QItemSelectionModel>
 
+#include "qgis.h"
 #include "qgsattributetablefiltermodel.h"
 #include "qgsattributetablemodel.h"
 #include "qgsvectorlayer.h"
@@ -56,39 +57,8 @@ bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QMod
     }
   }
 
-
-  QVariant leftData = left.data( QgsAttributeTableModel::SortRole );
-  QVariant rightData = right.data( QgsAttributeTableModel::SortRole );
-
-  if ( leftData.isNull() )
-    return true;
-
-  if ( rightData.isNull() )
-    return false;
-
-  switch ( leftData.type() )
-  {
-    case QVariant::Int:
-    case QVariant::UInt:
-    case QVariant::LongLong:
-    case QVariant::ULongLong:
-      return leftData.toLongLong() < rightData.toLongLong();
-
-    case QVariant::Double:
-      return leftData.toDouble() < rightData.toDouble();
-
-    case QVariant::Date:
-      return leftData.toDate() < rightData.toDate();
-
-    case QVariant::Time:
-      return leftData.toTime() < rightData.toTime();
-
-    case QVariant::DateTime:
-      return leftData.toDateTime() < rightData.toDateTime();
-
-    default:
-      return leftData.toString().localeAwareCompare( rightData.toString() ) < 0;
-  }
+  return qgsVariantLessThan( left.data( QgsAttributeTableModel::SortRole ),
+                             right.data( QgsAttributeTableModel::SortRole ) );
 }
 
 void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order )
diff --git a/src/gui/editorwidgets/qgsrelationreferencewidget.cpp b/src/gui/editorwidgets/qgsrelationreferencewidget.cpp
index 0ee2346..b3fc72c 100644
--- a/src/gui/editorwidgets/qgsrelationreferencewidget.cpp
+++ b/src/gui/editorwidgets/qgsrelationreferencewidget.cpp
@@ -34,22 +34,6 @@
 #include "qgsvectorlayer.h"
 #include "qgsattributetablemodel.h"
 
-bool orderByLessThan( const QgsRelationReferenceWidget::ValueRelationItem& p1
-                      , const QgsRelationReferenceWidget::ValueRelationItem& p2 )
-{
-  switch ( p1.first.type() )
-  {
-    case QVariant::String:
-      return p1.first.toString() < p2.first.toString();
-
-    case QVariant::Double:
-      return p1.first.toDouble() < p2.first.toDouble();
-
-    default:
-      return p1.first.toInt() < p2.first.toInt();
-  }
-}
-
 QgsRelationReferenceWidget::QgsRelationReferenceWidget( QWidget* parent )
     : QWidget( parent )
     , mEditorContext( QgsAttributeEditorContext() )
@@ -351,7 +335,11 @@ QVariant QgsRelationReferenceWidget::foreignKey()
   }
   else
   {
-    if ( !mFeature.isValid() )
+    if ( mReferencingFieldIdx < 0 || mReferencingFieldIdx >= mReferencingLayer->fields().count() )
+    {
+      return QVariant();
+    }
+    else if ( !mFeature.isValid() )
     {
       return QVariant( mReferencingLayer->fields().at( mReferencingFieldIdx ).type() );
     }
diff --git a/src/gui/editorwidgets/qgsvaluerelationwidgetwrapper.cpp b/src/gui/editorwidgets/qgsvaluerelationwidgetwrapper.cpp
index 32fccf3..90155ac 100644
--- a/src/gui/editorwidgets/qgsvaluerelationwidgetwrapper.cpp
+++ b/src/gui/editorwidgets/qgsvaluerelationwidgetwrapper.cpp
@@ -15,6 +15,7 @@
 
 #include "qgsvaluerelationwidgetwrapper.h"
 
+#include "qgis.h"
 #include "qgsfield.h"
 #include "qgsmaplayerregistry.h"
 #include "qgsvaluerelationwidgetfactory.h"
@@ -27,23 +28,13 @@
 bool QgsValueRelationWidgetWrapper::orderByKeyLessThan( const QgsValueRelationWidgetWrapper::ValueRelationItem& p1
     , const QgsValueRelationWidgetWrapper::ValueRelationItem& p2 )
 {
-  switch ( p1.first.type() )
-  {
-    case QVariant::String:
-      return p1.first.toString() < p2.first.toString();
-
-    case QVariant::Double:
-      return p1.first.toDouble() < p2.first.toDouble();
-
-    default:
-      return p1.first.toInt() < p2.first.toInt();
-  }
+  return qgsVariantLessThan( p1.first, p2.first );
 }
 
 bool QgsValueRelationWidgetWrapper::orderByValueLessThan( const QgsValueRelationWidgetWrapper::ValueRelationItem& p1
     , const QgsValueRelationWidgetWrapper::ValueRelationItem& p2 )
 {
-  return p1.second < p2.second;
+  return qgsVariantLessThan( p1.second, p2.second );
 }
 
 QgsValueRelationWidgetWrapper::QgsValueRelationWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent )
diff --git a/src/gui/qgsfieldexpressionwidget.cpp b/src/gui/qgsfieldexpressionwidget.cpp
index 4b35ec7..c0af008 100644
--- a/src/gui/qgsfieldexpressionwidget.cpp
+++ b/src/gui/qgsfieldexpressionwidget.cpp
@@ -122,13 +122,15 @@ bool QgsFieldExpressionWidget::isExpression() const
 QString QgsFieldExpressionWidget::currentField( bool *isExpression, bool *isValid ) const
 {
   QString text = currentText();
+  bool valueIsExpression = this->isExpression();
   if ( isValid )
   {
-    *isValid = isValidExpression();
+    // valid if not an expression (ie, set to a field), or set to an expression and expression is valid
+    *isValid = !valueIsExpression || isValidExpression();
   }
   if ( isExpression )
   {
-    *isExpression = this->isExpression();
+    *isExpression = valueIsExpression;
   }
   return text;
 }
diff --git a/src/gui/qgsmapcanvastracer.cpp b/src/gui/qgsmapcanvastracer.cpp
index 16b2064..22724b2 100644
--- a/src/gui/qgsmapcanvastracer.cpp
+++ b/src/gui/qgsmapcanvastracer.cpp
@@ -65,6 +65,11 @@ void QgsMapCanvasTracer::reportError( QgsTracer::PathError err, bool addingVerte
       break;
   }
 
+  if ( message.isEmpty() && hasTopologyProblem() )
+  {
+    message = tr( "Tracing may not work correctly. Please check topology of the input layers." );
+  }
+
   if ( message.isEmpty() )
     return;
 
diff --git a/src/gui/qgsnewnamedialog.cpp b/src/gui/qgsnewnamedialog.cpp
index 70a8d8c..d0ce7cc 100644
--- a/src/gui/qgsnewnamedialog.cpp
+++ b/src/gui/qgsnewnamedialog.cpp
@@ -76,6 +76,9 @@ QgsNewNameDialog::QgsNewNameDialog( const QString& source, const QString& initia
   mErrorLabel->setWordWrap( true );
   layout()->addWidget( mErrorLabel );
 
+  mLineEdit->setFocus();
+  mLineEdit->selectAll();
+
   nameChanged();
 }
 
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
index 8093893..fbfcec7 100644
--- a/src/plugins/CMakeLists.txt
+++ b/src/plugins/CMakeLists.txt
@@ -1,4 +1,5 @@
 IF (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+  SET(CMAKE_CXX_FLAGS_OLD "${CMAKE_CXX_FLAGS}")
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden")
 ENDIF()
 # override default path where built files are put to allow running qgis without installing
diff --git a/src/plugins/globe/CMakeLists.txt b/src/plugins/globe/CMakeLists.txt
index c068663..c8ab44a 100644
--- a/src/plugins/globe/CMakeLists.txt
+++ b/src/plugins/globe/CMakeLists.txt
@@ -1,5 +1,8 @@
 # set path to additional CMake modules
 SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules ${CMAKE_MODULE_PATH})
+IF (KEEP_GLOBE_CXX_FLAGS)
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_OLD}")
+ENDIF()
 
 FIND_PACKAGE(OSG REQUIRED)
 FIND_PACKAGE(OSGEARTH REQUIRED)
diff --git a/src/plugins/globe/globe_plugin.cpp b/src/plugins/globe/globe_plugin.cpp
index 5efcfae..c40cdc3 100644
--- a/src/plugins/globe/globe_plugin.cpp
+++ b/src/plugins/globe/globe_plugin.cpp
@@ -826,7 +826,7 @@ void GlobePlugin::setupProxy()
 
 void GlobePlugin::extentsChanged()
 {
-  QgsDebugMsg( "extentsChanged: " + mQGisIface->mapCanvas()->extent().toString() );
+  QgsDebugMsg( "extentsChanged: " + qobject_cast<QgsMapCanvas *>( sender() )->extent().toString() );
 }
 
 void GlobePlugin::imageLayersChanged()
@@ -1014,6 +1014,21 @@ void GlobePlugin::unload()
   mQGisIface->removeToolBarIcon( mQActionPointer );
 
   delete mQActionPointer;
+  delete mQActionSettingsPointer;
+  delete mQActionUnload;
+
+  disconnect( mQGisIface->mapCanvas(), SIGNAL( extentsChanged() ),
+              this, SLOT( extentsChanged() ) );
+  disconnect( mQGisIface->mapCanvas(), SIGNAL( layersChanged() ),
+              this, SLOT( imageLayersChanged() ) );
+  disconnect( mSettingsDialog, SIGNAL( elevationDatasourcesChanged() ),
+              this, SLOT( elevationLayersChanged() ) );
+  disconnect( mQGisIface->mainWindow(), SIGNAL( projectRead() ), this,
+              SLOT( projectReady() ) );
+  disconnect( mQGisIface, SIGNAL( newProjectCreated() ), this,
+              SLOT( blankProjectReady() ) );
+  disconnect( this, SIGNAL( xyCoordinates( const QgsPoint & ) ),
+              mQGisIface->mapCanvas(), SIGNAL( xyCoordinates( const QgsPoint & ) ) );
 
 #if 0
   if ( mCoutRdBuf )
diff --git a/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp b/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
index 2e958f1..6af54bf 100644
--- a/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
+++ b/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
@@ -56,7 +56,7 @@ QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTe
     QgsRectangle rect = request.filterRect();
 
     // If request doesn't overlap extents, then nothing to return
-    if ( ! rect.intersects( mSource->mExtent ) )
+    if ( ! rect.intersects( mSource->mExtent ) && !mTestSubset )
     {
       QgsDebugMsg( "Rectangle outside layer extents - no features to return" );
       mMode = FeatureIds;
@@ -64,11 +64,12 @@ QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTe
     // If the request extents include the entire layer, then revert to
     // a file scan
 
-    else if ( rect.contains( mSource->mExtent ) )
+    else if ( rect.contains( mSource->mExtent ) && !mTestSubset )
     {
       QgsDebugMsg( "Rectangle contains layer extents - bypass spatial filter" );
       mTestGeometry = false;
     }
+
     // If we have a spatial index then use it.  The spatial index already accounts
     // for the subset.  Also means we don't have to test geometries unless doing exact
     // intersection
@@ -138,6 +139,19 @@ QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTe
     mLoadGeometry = false;
   }
 
+  // ensure that all attributes required for expression filter are being fetched
+  if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes && request.filterType() == QgsFeatureRequest::FilterExpression )
+  {
+    QgsAttributeList attrs = request.subsetOfAttributes();
+    Q_FOREACH ( const QString& field, request.filterExpression()->referencedColumns() )
+    {
+      int attrIdx = mSource->mFields.fieldNameIndex( field );
+      if ( !attrs.contains( attrIdx ) )
+        attrs << attrIdx;
+    }
+    mRequest.setSubsetOfAttributes( attrs );
+  }
+
   QgsDebugMsg( QString( "Iterator is scanning file: " ) + ( mMode == FileScan ? "Yes" : "No" ) );
   QgsDebugMsg( QString( "Iterator is loading geometries: " ) + ( mLoadGeometry ? "Yes" : "No" ) );
   QgsDebugMsg( QString( "Iterator is testing geometries: " ) + ( mTestGeometry ? "Yes" : "No" ) );
@@ -319,9 +333,7 @@ bool QgsDelimitedTextFeatureIterator::nextFeatureInternal( QgsFeature& feature )
     feature.setFields( mSource->mFields ); // allow name-based attribute lookups
     feature.setFeatureId( fid );
     feature.initAttributes( mSource->mFields.count() );
-
-    if ( geom )
-      feature.setGeometry( geom );
+    feature.setGeometry( geom );
 
     // If we are testing subset expression, then need all attributes just in case.
     // Could be more sophisticated, but probably not worth it!
diff --git a/src/providers/delimitedtext/qgsdelimitedtextprovider.cpp b/src/providers/delimitedtext/qgsdelimitedtextprovider.cpp
index b48c758..f29c86e 100644
--- a/src/providers/delimitedtext/qgsdelimitedtextprovider.cpp
+++ b/src/providers/delimitedtext/qgsdelimitedtextprovider.cpp
@@ -779,7 +779,7 @@ void QgsDelimitedTextProvider::rescanFile()
   bool foundFirstGeometry = false;
   while ( fi.nextFeature( f ) )
   {
-    if ( mGeometryType != QGis::NoGeometry )
+    if ( mGeometryType != QGis::NoGeometry && f.constGeometry() )
     {
       if ( !foundFirstGeometry )
       {
@@ -1078,6 +1078,7 @@ bool QgsDelimitedTextProvider::setSubsetString( const QString& subset, bool upda
     }
   }
 
+  mCacheMinMaxDirty = true;
   emit dataChanged();
   return valid;
 }
diff --git a/src/providers/memory/qgsmemoryfeatureiterator.cpp b/src/providers/memory/qgsmemoryfeatureiterator.cpp
index 9f40e61..ea7f201 100644
--- a/src/providers/memory/qgsmemoryfeatureiterator.cpp
+++ b/src/providers/memory/qgsmemoryfeatureiterator.cpp
@@ -93,7 +93,7 @@ bool QgsMemoryFeatureIterator::nextFeatureUsingList( QgsFeature& feature )
     if ( !mRequest.filterRect().isNull() && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
     {
       // do exact check in case we're doing intersection
-      if ( mSource->mFeatures[*mFeatureIdListIterator].geometry() && mSource->mFeatures[*mFeatureIdListIterator].geometry()->intersects( mSelectRectGeom ) )
+      if ( mSource->mFeatures.value( *mFeatureIdListIterator ).constGeometry() && mSource->mFeatures.value( *mFeatureIdListIterator ).constGeometry()->intersects( mSelectRectGeom ) )
         hasFeature = true;
     }
     else
@@ -101,7 +101,7 @@ bool QgsMemoryFeatureIterator::nextFeatureUsingList( QgsFeature& feature )
 
     if ( mSubsetExpression )
     {
-      mSource->mExpressionContext.setFeature( mSource->mFeatures[*mFeatureIdListIterator] );
+      mSource->mExpressionContext.setFeature( mSource->mFeatures.value( *mFeatureIdListIterator ) );
       if ( !mSubsetExpression->evaluate( &mSource->mExpressionContext ).toBool() )
         hasFeature = false;
     }
@@ -115,7 +115,7 @@ bool QgsMemoryFeatureIterator::nextFeatureUsingList( QgsFeature& feature )
   // copy feature
   if ( hasFeature )
   {
-    feature = mSource->mFeatures[*mFeatureIdListIterator];
+    feature = mSource->mFeatures.value( *mFeatureIdListIterator );
     ++mFeatureIdListIterator;
   }
   else
diff --git a/src/providers/memory/qgsmemoryprovider.cpp b/src/providers/memory/qgsmemoryprovider.cpp
index 1dfcae1..1f74b11 100644
--- a/src/providers/memory/qgsmemoryprovider.cpp
+++ b/src/providers/memory/qgsmemoryprovider.cpp
@@ -481,6 +481,7 @@ bool QgsMemoryProvider::setSubsetString( const QString& theSQL, bool updateFeatu
   }
 
   mSubsetString = theSQL;
+  mCacheMinMaxDirty = true;
 
   emit dataChanged();
   return true;
diff --git a/src/providers/mssql/qgsmssqlfeatureiterator.cpp b/src/providers/mssql/qgsmssqlfeatureiterator.cpp
index 560d344..5cff00a 100644
--- a/src/providers/mssql/qgsmssqlfeatureiterator.cpp
+++ b/src/providers/mssql/qgsmssqlfeatureiterator.cpp
@@ -77,7 +77,20 @@ void QgsMssqlFeatureIterator::BuildStatement( const QgsFeatureRequest& request )
   mAttributesToFetch.append( mFidCol );
 
   bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes;
-  Q_FOREACH ( int i, subsetOfAttributes ? mRequest.subsetOfAttributes() : mSource->mFields.allAttributesList() )
+  QgsAttributeList attrs = subsetOfAttributes ? mRequest.subsetOfAttributes() : mSource->mFields.allAttributesList();
+
+  // ensure that all attributes required for expression filter are being fetched
+  if ( subsetOfAttributes && request.filterType() == QgsFeatureRequest::FilterExpression )
+  {
+    Q_FOREACH ( const QString& field, request.filterExpression()->referencedColumns() )
+    {
+      int attrIdx = mSource->mFields.fieldNameIndex( field );
+      if ( !attrs.contains( attrIdx ) )
+        attrs << attrIdx;
+    }
+  }
+
+  Q_FOREACH ( int i, attrs )
   {
     QString fieldname = mSource->mFields.at( i ).name();
     if ( mSource->mFidColName == fieldname )
@@ -302,6 +315,14 @@ bool QgsMssqlFeatureIterator::fetchFeature( QgsFeature& feature )
         g->fromWkb( wkb, mParser.GetWkbLen() );
         feature.setGeometry( g );
       }
+      else
+      {
+        feature.setGeometry( nullptr );
+      }
+    }
+    else
+    {
+      feature.setGeometry( nullptr );
     }
 
     feature.setValid( true );
diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp
index 4dcb06a..9bb8294 100644
--- a/src/providers/ogr/qgsogrfeatureiterator.cpp
+++ b/src/providers/ogr/qgsogrfeatureiterator.cpp
@@ -63,6 +63,18 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrFeatureSource* source, bool
   mFetchGeometry = ( !mRequest.filterRect().isNull() ) || !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
   QgsAttributeList attrs = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) ? mRequest.subsetOfAttributes() : mSource->mFields.allAttributesList();
 
+  // ensure that all attributes required for expression filter are being fetched
+  if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes && request.filterType() == QgsFeatureRequest::FilterExpression )
+  {
+    Q_FOREACH ( const QString& field, request.filterExpression()->referencedColumns() )
+    {
+      int attrIdx = mSource->mFields.fieldNameIndex( field );
+      if ( !attrs.contains( attrIdx ) )
+        attrs << attrIdx;
+    }
+    mRequest.setSubsetOfAttributes( attrs );
+  }
+
   // make sure we fetch just relevant fields
   // unless it's a VRT data source filtered by geometry as we don't know which
   // attributes make up the geometry and OGR won't fetch them to evaluate the
diff --git a/src/providers/oracle/qgsoraclefeatureiterator.cpp b/src/providers/oracle/qgsoraclefeatureiterator.cpp
index 914f0e8..e73fe33 100644
--- a/src/providers/oracle/qgsoraclefeatureiterator.cpp
+++ b/src/providers/oracle/qgsoraclefeatureiterator.cpp
@@ -29,6 +29,7 @@ QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleFeatureSource* sour
     : QgsAbstractFeatureIteratorFromSource<QgsOracleFeatureSource>( source, ownSource, request )
     , mRewind( false )
     , mExpressionCompiled( false )
+    , mFetchGeometry( false )
 {
   mConnection = QgsOracleConnPool::instance()->acquireConnection( mSource->mUri.connectionInfo() );
   if ( !mConnection )
@@ -44,47 +45,88 @@ QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleFeatureSource* sour
     mAttributeList = mRequest.subsetOfAttributes();
     if ( mAttributeList.isEmpty() )
       mAttributeList = mSource->mFields.allAttributesList();
+
+    // ensure that all attributes required for expression filter are being fetched
+    if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression )
+    {
+      Q_FOREACH ( const QString& field, mRequest.filterExpression()->referencedColumns() )
+      {
+        int attrIdx = mSource->mFields.fieldNameIndex( field );
+        if ( !mAttributeList.contains( attrIdx ) )
+          mAttributeList << attrIdx;
+      }
+    }
+
   }
   else
     mAttributeList = mSource->mFields.allAttributesList();
 
+
   QString whereClause;
 
-  if ( !mRequest.filterRect().isNull() && !mSource->mGeometryColumn.isNull() && mSource->mHasSpatialIndex )
+  if ( !mSource->mGeometryColumn.isNull() )
   {
-    QgsRectangle rect( mRequest.filterRect() );
-    QString bbox = QString( "mdsys.sdo_geometry(2003,%1,NULL,"
-                            "mdsys.sdo_elem_info_array(1,1003,3),"
-                            "mdsys.sdo_ordinate_array(%2,%3,%4,%5)"
-                            ")" )
-                   .arg( mSource->mSrid < 1 ? "NULL" : QString::number( mSource->mSrid ) )
-                   .arg( qgsDoubleToString( rect.xMinimum() ) )
-                   .arg( qgsDoubleToString( rect.yMinimum() ) )
-                   .arg( qgsDoubleToString( rect.xMaximum() ) )
-                   .arg( qgsDoubleToString( rect.yMaximum() ) );
-
-    whereClause = QString( "sdo_filter(%1,%2)='TRUE'" ).arg( QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn ) ).arg( bbox );
-
-    if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect && mConnection->hasSpatial() )
+    // fetch geometry if requested
+    mFetchGeometry = ( mRequest.flags() & QgsFeatureRequest::NoGeometry ) == 0;
+
+    if ( !mRequest.filterRect().isNull() )
     {
-      whereClause += QString( " AND sdo_relate(%1,%2,'mask=ANYINTERACT')='TRUE'" )
-                     .arg( QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn ) )
-                     .arg( bbox );
+      // sdo_filter requires spatial index
+      if ( mSource->mHasSpatialIndex )
+      {
+        QgsRectangle rect( mRequest.filterRect() );
+        QString bbox = QString( "mdsys.sdo_geometry(2003,%1,NULL,"
+                                "mdsys.sdo_elem_info_array(1,1003,3),"
+                                "mdsys.sdo_ordinate_array(%2,%3,%4,%5)"
+                                ")" )
+                       .arg( mSource->mSrid < 1 ? "NULL" : QString::number( mSource->mSrid ) )
+                       .arg( qgsDoubleToString( rect.xMinimum() ) )
+                       .arg( qgsDoubleToString( rect.yMinimum() ) )
+                       .arg( qgsDoubleToString( rect.xMaximum() ) )
+                       .arg( qgsDoubleToString( rect.yMaximum() ) );
+
+        whereClause = QString( "sdo_filter(%1,%2)='TRUE'" ).arg( QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn ) ).arg( bbox );
+
+        if (( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) != 0 )
+        {
+          // sdo_relate requires Spatial
+          if ( mConnection->hasSpatial() )
+          {
+            whereClause += QString( " AND sdo_relate(%1,%2,'mask=ANYINTERACT')='TRUE'" )
+                           .arg( QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn ) )
+                           .arg( bbox );
+          }
+          else
+          {
+            // request geometry to do exact intersect in fetchFeature
+            mFetchGeometry = true;
+          }
+        }
+      }
+      else
+      {
+        // request geometry to do bbox intersect in fetchFeature
+        mFetchGeometry = true;
+      }
     }
   }
+  else if ( !mRequest.filterRect().isNull() )
+  {
+    QgsDebugMsg( "filterRect without geometry ignored" );
+  }
 
-  switch ( request.filterType() )
+  switch ( mRequest.filterType() )
   {
     case QgsFeatureRequest::FilterFid:
     {
-      QString fidWhereClause = QgsOracleUtils::whereClause( request.filterFid(), mSource->mFields, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
+      QString fidWhereClause = QgsOracleUtils::whereClause( mRequest.filterFid(), mSource->mFields, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
       whereClause = QgsOracleUtils::andWhereClauses( whereClause, fidWhereClause );
     }
     break;
 
     case QgsFeatureRequest::FilterFids:
     {
-      QString fidsWhereClause = QgsOracleUtils::whereClause( request.filterFids(), mSource->mFields, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
+      QString fidsWhereClause = QgsOracleUtils::whereClause( mRequest.filterFids(), mSource->mFields, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
       whereClause = QgsOracleUtils::andWhereClauses( whereClause, fidsWhereClause );
     }
     break;
@@ -96,7 +138,7 @@ QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleFeatureSource* sour
       if ( QSettings().value( "/qgis/compileExpressions", true ).toBool() )
       {
         QgsOracleExpressionCompiler compiler( mSource );
-        if ( compiler.compile( request.filterExpression() ) == QgsSqlExpressionCompiler::Complete )
+        if ( compiler.compile( mRequest.filterExpression() ) == QgsSqlExpressionCompiler::Complete )
         {
           whereClause = QgsOracleUtils::andWhereClauses( whereClause, compiler.result() );
           mExpressionCompiled = true;
@@ -114,15 +156,15 @@ QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleFeatureSource* sour
     if ( !whereClause.isEmpty() )
       whereClause += " AND ";
 
-    whereClause += QgsOracleConn::databaseTypeFilter( "featureRequest", mSource->mGeometryColumn, mSource->mRequestedGeomType );
+    whereClause += QgsOracleConn::databaseTypeFilter( "FEATUREREQUEST", mSource->mGeometryColumn, mSource->mRequestedGeomType );
   }
 
-  if ( request.limit() >= 0 )
+  if ( mRequest.limit() >= 0 )
   {
     if ( !whereClause.isEmpty() )
       whereClause += " AND ";
 
-    whereClause += QString( "rownum<=%1" ).arg( request.limit() );
+    whereClause += QString( "rownum<=%1" ).arg( mRequest.limit() );
   }
 
   if ( !mSource->mSqlWhereClause.isEmpty() )
@@ -173,29 +215,60 @@ bool QgsOracleFeatureIterator::fetchFeature( QgsFeature& feature )
 
     int col = 0;
 
-    if ((( mRequest.flags() & QgsFeatureRequest::NoGeometry ) == 0 && !mSource->mGeometryColumn.isNull() ) ||
-        (( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) != 0 && ( !mConnection->hasSpatial() || !mSource->mHasSpatialIndex ) ) )
+    if ( mFetchGeometry )
     {
       QByteArray *ba = static_cast<QByteArray*>( mQry.value( col++ ).data() );
-      unsigned char *copy = new unsigned char[ba->size()];
-      memcpy( copy, ba->constData(), ba->size() );
-
-      QgsGeometry *g = new QgsGeometry();
-      g->fromWkb( copy, ba->size() );
-      feature.setGeometry( g );
+      if ( ba->size() > 0 )
+      {
+        unsigned char *copy = new unsigned char[ba->size()];
+        memcpy( copy, ba->constData(), ba->size() );
 
-      if (( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) != 0 && ( !mConnection->hasSpatial() || !mSource->mHasSpatialIndex ) &&
-          mRequest.filterType() == QgsFeatureRequest::FilterRect &&
-          ( !feature.geometry() || !feature.geometry()->intersects( mRequest.filterRect() ) ) )
+        QgsGeometry *g = new QgsGeometry();
+        g->fromWkb( copy, ba->size() );
+        feature.setGeometry( g );
+      }
+      else
       {
-        // skip feature that don't intersect with our rectangle
-        QgsDebugMsg( "no intersect" );
-        continue;
+        feature.setGeometry( 0 );
       }
 
+      if ( !mRequest.filterRect().isNull() )
+      {
+        if ( !feature.geometry() )
+        {
+          QgsDebugMsg( "no geometry to intersect" );
+          continue;
+        }
+
+        if (( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) == 0 )
+        {
+          // couldn't use sdo_filter earlier
+          if ( !mSource->mHasSpatialIndex )
+          {
+            // only intersect with bbox
+            if ( !feature.geometry()->boundingBox().intersects( mRequest.filterRect() ) )
+            {
+              // skip feature that don't intersect with our rectangle
+              QgsDebugMsg( "no bbox intersect" );
+              continue;
+            }
+          }
+        }
+        else if ( !mConnection->hasSpatial() || !mSource->mHasSpatialIndex )
+        {
+          // couldn't use sdo_relate earlier
+          if ( !feature.geometry()->intersects( mRequest.filterRect() ) )
+          {
+            // skip feature that don't intersect with our rectangle
+            QgsDebugMsg( "no exact intersect" );
+            continue;
+          }
+        }
+      }
 
       if (( mRequest.flags() & QgsFeatureRequest::NoGeometry ) != 0 )
       {
+        // clear not requested geometry
         feature.setGeometry( 0 );
       }
     }
@@ -262,13 +335,20 @@ bool QgsOracleFeatureIterator::fetchFeature( QgsFeature& feature )
       if ( fld.type() == QVariant::ByteArray && fld.typeName().endsWith( ".SDO_GEOMETRY" ) )
       {
         QByteArray *ba = static_cast<QByteArray*>( v.data() );
-        unsigned char *copy = new unsigned char[ba->size()];
-        memcpy( copy, ba->constData(), ba->size() );
+        if ( ba->size() > 0 )
+        {
+          unsigned char *copy = new unsigned char[ba->size()];
+          memcpy( copy, ba->constData(), ba->size() );
 
-        QgsGeometry *g = new QgsGeometry();
-        g->fromWkb( copy, ba->size() );
-        v = g->exportToWkt();
-        delete g;
+          QgsGeometry *g = new QgsGeometry();
+          g->fromWkb( copy, ba->size() );
+          v = g->exportToWkt();
+          delete g;
+        }
+        else
+        {
+          v = QVariant( QVariant::String );
+        }
       }
       else if ( v.type() != fld.type() )
         v = QgsVectorDataProvider::convertValue( fld.type(), v.toString() );
@@ -314,7 +394,7 @@ bool QgsOracleFeatureIterator::openQuery( QString whereClause )
   {
     QString query = "SELECT ", delim = "";
 
-    if (( mRequest.flags() & QgsFeatureRequest::NoGeometry ) == 0 && !mSource->mGeometryColumn.isNull() )
+    if ( mFetchGeometry )
     {
       query += QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn );
       delim = ",";
@@ -354,7 +434,7 @@ bool QgsOracleFeatureIterator::openQuery( QString whereClause )
       query += delim + mConnection->fieldExpression( mSource->mFields[idx] );
     }
 
-    query += QString( " FROM %1 \"featureRequest\"" ).arg( mSource->mQuery );
+    query += QString( " FROM %1 \"FEATUREREQUEST\"" ).arg( mSource->mQuery );
 
     if ( !whereClause.isEmpty() )
       query += QString( " WHERE %1" ).arg( whereClause );
diff --git a/src/providers/oracle/qgsoraclefeatureiterator.h b/src/providers/oracle/qgsoraclefeatureiterator.h
index 056fe79..8c3430a 100644
--- a/src/providers/oracle/qgsoraclefeatureiterator.h
+++ b/src/providers/oracle/qgsoraclefeatureiterator.h
@@ -82,6 +82,7 @@ class QgsOracleFeatureIterator : public QgsAbstractFeatureIteratorFromSource<Qgs
     QSqlQuery mQry;
     bool mRewind;
     bool mExpressionCompiled;
+    bool mFetchGeometry;
     QgsAttributeList mAttributeList;
 };
 
diff --git a/src/providers/postgres/qgspostgresfeatureiterator.cpp b/src/providers/postgres/qgspostgresfeatureiterator.cpp
index a65224f..8cbc710 100644
--- a/src/providers/postgres/qgspostgresfeatureiterator.cpp
+++ b/src/providers/postgres/qgspostgresfeatureiterator.cpp
@@ -89,6 +89,19 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
   }
   else if ( request.filterType() == QgsFeatureRequest::FilterExpression )
   {
+    // ensure that all attributes required for expression filter are being fetched
+    if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
+    {
+      QgsAttributeList attrs = mRequest.subsetOfAttributes();
+      Q_FOREACH ( const QString& field, request.filterExpression()->referencedColumns() )
+      {
+        int attrIdx = mSource->mFields.fieldNameIndex( field );
+        if ( !attrs.contains( attrIdx ) )
+          attrs << attrIdx;
+      }
+      mRequest.setSubsetOfAttributes( attrs );
+    }
+
     if ( QSettings().value( "/qgis/compileExpressions", true ).toBool() )
     {
       //IMPORTANT - this MUST be the last clause added!
diff --git a/src/providers/spatialite/qgsspatialitefeatureiterator.cpp b/src/providers/spatialite/qgsspatialitefeatureiterator.cpp
index 7be3917..72dbd5b 100644
--- a/src/providers/spatialite/qgsspatialitefeatureiterator.cpp
+++ b/src/providers/spatialite/qgsspatialitefeatureiterator.cpp
@@ -83,6 +83,19 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
   //IMPORTANT - this MUST be the last clause added!
   else if ( request.filterType() == QgsFeatureRequest::FilterExpression )
   {
+    // ensure that all attributes required for expression filter are being fetched
+    if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes && request.filterType() == QgsFeatureRequest::FilterExpression )
+    {
+      QgsAttributeList attrs = request.subsetOfAttributes();
+      Q_FOREACH ( const QString& field, request.filterExpression()->referencedColumns() )
+      {
+        int attrIdx = mSource->mFields.fieldNameIndex( field );
+        if ( !attrs.contains( attrIdx ) )
+          attrs << attrIdx;
+      }
+      mRequest.setSubsetOfAttributes( attrs );
+    }
+
     if ( QSettings().value( "/qgis/compileExpressions", true ).toBool() )
     {
       QgsSpatiaLiteExpressionCompiler compiler = QgsSpatiaLiteExpressionCompiler( source );
diff --git a/src/providers/spatialite/qgsspatialiteprovider.cpp b/src/providers/spatialite/qgsspatialiteprovider.cpp
index 7738ce1..149a18f 100644
--- a/src/providers/spatialite/qgsspatialiteprovider.cpp
+++ b/src/providers/spatialite/qgsspatialiteprovider.cpp
@@ -5001,7 +5001,10 @@ const QgsField & QgsSpatiaLiteProvider::field( int index ) const
   return attributeFields[index];
 }
 
-
+void QgsSpatiaLiteProvider::invalidateConnections( const QString& connection )
+{
+  QgsSpatiaLiteConnPool::instance()->invalidateConnections( connection );
+}
 
 /**
  * Class factory to return a pointer to a newly created
diff --git a/src/providers/spatialite/qgsspatialiteprovider.h b/src/providers/spatialite/qgsspatialiteprovider.h
index d2c0ef8..1b9929f 100644
--- a/src/providers/spatialite/qgsspatialiteprovider.h
+++ b/src/providers/spatialite/qgsspatialiteprovider.h
@@ -233,6 +233,8 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
      */
     QgsAttributeList pkAttributeIndexes() override;
 
+    void invalidateConnections( const QString& connection ) override;
+
   signals:
     /**
      *   This is emitted whenever the worker thread has fully calculated the
diff --git a/src/providers/virtual/qgsvirtuallayerfeatureiterator.cpp b/src/providers/virtual/qgsvirtuallayerfeatureiterator.cpp
index d47e290..3c70825 100644
--- a/src/providers/virtual/qgsvirtuallayerfeatureiterator.cpp
+++ b/src/providers/virtual/qgsvirtuallayerfeatureiterator.cpp
@@ -80,12 +80,22 @@ QgsVirtualLayerFeatureIterator::QgsVirtualLayerFeatureIterator( QgsVirtualLayerF
     mFields = mSource->provider()->fields();
     if ( request.flags() & QgsFeatureRequest::SubsetOfAttributes )
     {
-
       // copy only selected fields
       Q_FOREACH ( int idx, request.subsetOfAttributes() )
       {
         mAttributes << idx;
       }
+
+      // ensure that all attributes required for expression filter are being fetched
+      if ( request.filterType() == QgsFeatureRequest::FilterExpression )
+      {
+        Q_FOREACH ( const QString& field, request.filterExpression()->referencedColumns() )
+        {
+          int attrIdx = mFields.fieldNameIndex( field );
+          if ( !mAttributes.contains( attrIdx ) )
+            mAttributes << attrIdx;
+        }
+      }
     }
     else
     {
@@ -218,6 +228,10 @@ bool QgsVirtualLayerFeatureIterator::fetchFeature( QgsFeature& feature )
     {
       feature.setGeometry( spatialiteBlobToQgsGeometry( blob.constData(), blob.size() ) );
     }
+    else
+    {
+      feature.setGeometry( nullptr );
+    }
   }
 
   feature.setValid( true );
diff --git a/src/providers/virtual/qgsvirtuallayerprovider.cpp b/src/providers/virtual/qgsvirtuallayerprovider.cpp
index 1663187..6147ad2 100644
--- a/src/providers/virtual/qgsvirtuallayerprovider.cpp
+++ b/src/providers/virtual/qgsvirtuallayerprovider.cpp
@@ -493,6 +493,7 @@ QString QgsVirtualLayerProvider::subsetString()
 bool QgsVirtualLayerProvider::setSubsetString( const QString& subset, bool updateFeatureCount )
 {
   mSubset = subset;
+  mCacheMinMaxDirty = true;
   if ( updateFeatureCount )
     updateStatistics();
   return true;
diff --git a/src/providers/wfs/qgswfsprovider.cpp b/src/providers/wfs/qgswfsprovider.cpp
index dd6b17c..33f3c92 100644
--- a/src/providers/wfs/qgswfsprovider.cpp
+++ b/src/providers/wfs/qgswfsprovider.cpp
@@ -168,10 +168,7 @@ void QgsWFSProvider::reloadData()
 void QgsWFSProvider::deleteData()
 {
   mSelectedFeatures.clear();
-  for ( int i = 0; i < mFeatures.size(); i++ )
-  {
-    delete mFeatures[i];
-  }
+  qDeleteAll( mFeatures );
   mFeatures.clear();
 }
 
@@ -213,85 +210,13 @@ bool QgsWFSProvider::isValid()
 
 QgsFeatureIterator QgsWFSProvider::getFeatures( const QgsFeatureRequest& request )
 {
-#if 0
-  if ( !( request.flags() & QgsFeatureRequest::NoGeometry ) )
-  {
-    QgsRectangle rect = request.filterRect();
-    if ( !rect.isEmpty() )
-    {
-      QString dsURI = dataSourceUri();
-      //first time through, initialize GetRenderedOnly args
-      //ctor cannot initialize because layer object not available then
-      if ( ! mInitGro )
-      { //did user check "Cache Features" in WFS layer source selection?
-        if ( dsURI.contains( "BBOX=" ) )
-        { //no: initialize incremental getFeature
-          if ( initGetRenderedOnly( rect ) )
-          {
-            mGetRenderedOnly = true;
-          }
-          else
-          { //initialization failed;
-            QgsDebugMsg( QString( "GetRenderedOnly initialization failed; incorrect operation may occur\n%1" )
-                         .arg( dataSourceUri() ) );
-            QMessageBox( QMessageBox::Warning, "Non-Cached layer initialization failed!",
-                         QString( "Incorrect operation may occur:\n%1" ).arg( dataSourceUri() ) );
-          }
-        }
-        mInitGro = true;
-      }
-
-      if ( mGetRenderedOnly )
-      { //"Cache Features" was not selected for this layer
-        //has rendered extent expanded beyond last-retrieved WFS extent?
-        //NB: "intersect" instead of "contains" tolerates rounding errors;
-        //    avoids unnecessary second fetch on zoom-in/zoom-out sequences
-        QgsRectangle olap( rect );
-        olap = olap.intersect( &mGetExtent );
-        if ( qgsDoubleNear( rect.width(), olap.width() ) && qgsDoubleNear( rect.height(), olap.height() ) )
-        { //difference between canvas and layer extents is within rounding error: do not re-fetch
-          QgsDebugMsg( QString( "Layer %1 GetRenderedOnly: no fetch required" ).arg( mLayer->name() ) );
-        }
-        else
-        { //combined old and new extents might speed up local panning & zooming
-          mGetExtent.combineExtentWith( &rect );
-          //but see if the combination is useless or too big
-          double pArea = mGetExtent.width() * mGetExtent.height();
-          double cArea = rect.width() * rect.height();
-          if ( olap.isEmpty() || pArea > ( cArea * 4.0 ) )
-          { //new canvas extent does not overlap or combining old and new extents would
-            //fetch > 4 times the area to be rendered; get only what will be rendered
-            mGetExtent = rect;
-          }
-          QgsDebugMsg( QString( "Layer %1 GetRenderedOnly: fetching extent %2" )
-                       .arg( mLayer->name(), mGetExtent.asWktCoordinates() ) );
-          dsURI = dsURI.replace( QRegExp( "BBOX=[^&]*" ),
-                                 QString( "BBOX=%1,%2,%3,%4" )
-                                 .arg( qgsDoubleToString( mGetExtent.xMinimum() ) )
-                                 .arg( qgsDoubleToString( mGetExtent.yMinimum() ) )
-                                 .arg( qgsDoubleToString( mGetExtent.xMaximum() ) )
-                                 .arg( qgsDoubleToString( mGetExtent.yMaximum() ) ) );
-          //TODO: BBOX may not be combined with FILTER. WFS spec v. 1.1.0, sec. 14.7.3 ff.
-          //      if a FILTER is present, the BBOX must be merged into it, capabilities permitting.
-          //      Else one criterion must be abandoned and the user warned.  [WBC 111221]
-          setDataSourceUri( dsURI );
-          reloadData();
-          mLayer->updateExtents();
-        }
-      }
-    }
-
-  }
-  return new QgsWFSFeatureIterator( new QgsWFSFeatureSource( this ), true, request );
-#else
   QgsRectangle rect = request.filterRect();
   if ( !( request.flags() & QgsFeatureRequest::NoGeometry ) && !rect.isEmpty() )
   {
     deleteData();
     reloadData();
   }
-  return new QgsWFSFeatureIterator( new QgsWFSFeatureSource( this ), true, request );
-#endif
+  return QgsFeatureIterator( new QgsWFSFeatureIterator( new QgsWFSFeatureSource( this ), true, request ) );
 }
 
 int QgsWFSProvider::getFeature( const QString& uri )
@@ -347,7 +272,14 @@ bool QgsWFSProvider::addFeatures( QgsFeatureList &flist )
 
     //add geometry column (as gml)
     QDomElement geomElem = transactionDoc.createElementNS( mWfsNamespace, mGeometryAttribute );
-    QDomElement gmlElem = QgsOgcUtils::geometryToGML( featureIt->constGeometry(), transactionDoc );
+
+    QgsGeometry the_geom( *featureIt->constGeometry() );
+    // convert to multi if the layer geom type is multi and the geom is not
+    if ( QGis::isMultiType( this->geometryType( ) ) && ! the_geom.isMultipart( ) )
+    {
+      the_geom.convertToMultiType();
+    }
+    QDomElement gmlElem = QgsOgcUtils::geometryToGML( &the_geom, transactionDoc );
     if ( !gmlElem.isNull() )
     {
       gmlElem.setAttribute( "srsName", crs().authid() );
@@ -1409,6 +1341,7 @@ bool QgsWFSProvider::sendTransactionDocument( const QDomDocument& doc, QDomDocum
 
   request.setHeader( QNetworkRequest::ContentTypeHeader, "text/xml" );
   QNetworkReply* reply = QgsNetworkAccessManager::instance()->post( request, doc.toByteArray( -1 ) );
+  QgsDebugMsg( "WFS transaction: " + doc.toByteArray( ) );
 
   connect( reply, SIGNAL( finished() ), this, SLOT( networkRequestFinished() ) );
   while ( !mNetworkRequestFinished )
diff --git a/src/server/qgsconfigparserutils.cpp b/src/server/qgsconfigparserutils.cpp
index 8a04eb0..be8647e 100644
--- a/src/server/qgsconfigparserutils.cpp
+++ b/src/server/qgsconfigparserutils.cpp
@@ -92,8 +92,12 @@ void QgsConfigParserUtils::appendLayerBoundingBoxes( QDomElement& layerElem, QDo
   //Ex_GeographicBoundingBox
   QDomElement ExGeoBBoxElement;
   //transform the layers native CRS into WGS84
-  QgsCoordinateTransform exGeoTransform( layerCRS, wgs84 );
-  QgsRectangle wgs84BoundingRect = exGeoTransform.transformBoundingBox( layerExtent );
+  QgsRectangle wgs84BoundingRect;
+  if ( !layerExtent.isNull() )
+  {
+    QgsCoordinateTransform exGeoTransform( layerCRS, wgs84 );
+    wgs84BoundingRect = exGeoTransform.transformBoundingBox( layerExtent );
+  }
   if ( version == "1.1.1" )   // WMS Version 1.1.1
   {
     ExGeoBBoxElement = doc.createElement( "LatLonBoundingBox" );
@@ -185,8 +189,12 @@ void QgsConfigParserUtils::appendLayerBoundingBox( QDomElement& layerElem, QDomD
   const QgsCoordinateReferenceSystem& crs = QgsCRSCache::instance()->crsByAuthId( crsText );
 
   //transform the layers native CRS into CRS
-  QgsCoordinateTransform crsTransform( layerCRS, crs );
-  QgsRectangle crsExtent = crsTransform.transformBoundingBox( layerExtent );
+  QgsRectangle crsExtent;
+  if ( !layerExtent.isNull() )
+  {
+    QgsCoordinateTransform crsTransform( layerCRS, crs );
+    crsExtent = crsTransform.transformBoundingBox( layerExtent );
+  }
 
   //BoundingBox element
   QDomElement bBoxElement = doc.createElement( "BoundingBox" );
diff --git a/src/server/qgsserverprojectparser.cpp b/src/server/qgsserverprojectparser.cpp
index f81fdb2..47559d1 100644
--- a/src/server/qgsserverprojectparser.cpp
+++ b/src/server/qgsserverprojectparser.cpp
@@ -50,7 +50,7 @@ QgsServerProjectParser::QgsServerProjectParser( QDomDocument* xmlDoc, const QStr
       currentElement = layerNodeList.at( i ).toElement();
       mProjectLayerElements.push_back( currentElement );
       QString lName = layerShortName( currentElement );
-      if ( lName.isNull() )
+      if ( lName.isEmpty() )
         lName = layerName( currentElement );
       mProjectLayerElementsByName.insert( lName, currentElement );
       mProjectLayerElementsById.insert( layerId( currentElement ), currentElement );
diff --git a/src/server/qgswfsserver.cpp b/src/server/qgswfsserver.cpp
index 490d5ce..4e4fbcb 100644
--- a/src/server/qgswfsserver.cpp
+++ b/src/server/qgswfsserver.cpp
@@ -1897,6 +1897,10 @@ QString QgsWFSServer::createFeatureGeoJSON( QgsFeature* feat, int prec, QgsCoord
   for ( int i = 0; i < attrIndexes.count(); ++i )
   {
     int idx = attrIndexes[i];
+    if ( idx >= fields->count() )
+    {
+      continue;
+    }
     QString attributeName = fields->at( idx ).name();
     //skip attribute if it is excluded from WFS publication
     if ( excludedAttributes.contains( attributeName ) )
@@ -1992,6 +1996,10 @@ QDomElement QgsWFSServer::createFeatureGML2( QgsFeature* feat, QDomDocument& doc
   for ( int i = 0; i < attrIndexes.count(); ++i )
   {
     int idx = attrIndexes[i];
+    if ( idx >= fields->count() )
+    {
+      continue;
+    }
     QString attributeName = fields->at( idx ).name();
     //skip attribute if it is excluded from WFS publication
     if ( excludedAttributes.contains( attributeName ) )
@@ -2065,6 +2073,10 @@ QDomElement QgsWFSServer::createFeatureGML3( QgsFeature* feat, QDomDocument& doc
   for ( int i = 0; i < attrIndexes.count(); ++i )
   {
     int idx = attrIndexes[i];
+    if ( idx >= fields->count() )
+    {
+      continue;
+    }
     QString attributeName = fields->at( idx ).name();
     //skip attribute if it is excluded from WFS publication
     if ( excludedAttributes.contains( attributeName ) )
diff --git a/src/ui/composer/qgscomposerlegendwidgetbase.ui b/src/ui/composer/qgscomposerlegendwidgetbase.ui
index ad11062..5c8b6f9 100644
--- a/src/ui/composer/qgscomposerlegendwidgetbase.ui
+++ b/src/ui/composer/qgscomposerlegendwidgetbase.ui
@@ -63,9 +63,9 @@
       <property name="geometry">
        <rect>
         <x>0</x>
-        <y>-334</y>
+        <y>0</y>
         <width>375</width>
-        <height>1306</height>
+        <height>1478</height>
        </rect>
       </property>
       <layout class="QVBoxLayout" name="mainLayout">
@@ -210,6 +210,12 @@
           </item>
           <item>
            <widget class="QgsLayerTreeView" name="mItemTreeView">
+            <property name="minimumSize">
+             <size>
+              <width>0</width>
+              <height>250</height>
+             </size>
+            </property>
             <property name="selectionMode">
              <enum>QAbstractItemView::ContiguousSelection</enum>
             </property>
diff --git a/tests/src/core/testqgis.cpp b/tests/src/core/testqgis.cpp
index 5bc42bb..1b724c6 100644
--- a/tests/src/core/testqgis.cpp
+++ b/tests/src/core/testqgis.cpp
@@ -37,6 +37,8 @@ class TestQGis : public QObject
     void permissiveToInt();
     void doubleToString();
     void qgsround();
+    void qVariantCompare_data();
+    void qVariantCompare();
 
   private:
     QString mReport;
@@ -151,5 +153,71 @@ void TestQGis::qgsround()
   QCOMPARE( qgsRound( -1.5 ), -2. );
 }
 
+void TestQGis::qVariantCompare_data()
+{
+  QTest::addColumn<QVariant>( "lhs" );
+  QTest::addColumn<QVariant>( "rhs" );
+  QTest::addColumn<bool>( "lessThan" );
+  QTest::addColumn<bool>( "greaterThan" );
+
+  QTest::newRow( "invalid to value" ) << QVariant() << QVariant( 2 ) << true << false;
+  QTest::newRow( "invalid to value 2" ) << QVariant( 2 ) << QVariant() << false << true;
+  QTest::newRow( "invalid to null" ) << QVariant() << QVariant( QVariant::String ) << true << false;
+  QTest::newRow( "invalid to null2 " ) << QVariant( QVariant::String ) << QVariant() << false << true;
+  QTest::newRow( "null to value" ) <<  QVariant( QVariant::String ) << QVariant( "a" ) << true << false;
+  QTest::newRow( "null to value 2" ) << QVariant( "a" ) << QVariant( QVariant::String ) << false << true;
+
+  QTest::newRow( "int" ) << QVariant( 1 ) << QVariant( 2 ) << true << false;
+  QTest::newRow( "int 2" ) << QVariant( 1 ) << QVariant( -2 ) << false << true;
+  QTest::newRow( "int 3" ) << QVariant( 0 ) << QVariant( 1 ) << true << false;
+  QTest::newRow( "uint" ) << QVariant( 1u ) << QVariant( 2u ) << true << false;
+  QTest::newRow( "uint 2" ) << QVariant( 2u ) << QVariant( 0u ) << false << true;
+  QTest::newRow( "long long" ) << QVariant( 1LL ) << QVariant( 2LL ) << true << false;
+  QTest::newRow( "long long 2" ) << QVariant( 1LL ) << QVariant( -2LL ) << false << true;
+  QTest::newRow( "long long 3" ) << QVariant( 0LL ) << QVariant( 1LL ) << true << false;
+  QTest::newRow( "ulong long" ) << QVariant( 1uLL ) << QVariant( 2uLL ) << true << false;
+  QTest::newRow( "ulong long 2" ) << QVariant( 2uLL ) << QVariant( 0uLL ) << false << true;
+  QTest::newRow( "double" ) << QVariant( 1.5 ) << QVariant( 2.5 ) << true << false;
+  QTest::newRow( "double 2" ) << QVariant( 1.5 ) << QVariant( -2.5 ) << false << true;
+  QTest::newRow( "double 3" ) << QVariant( 0.5 ) << QVariant( 1.5 ) << true << false;
+  QTest::newRow( "char" ) << QVariant( 'b' ) << QVariant( 'x' ) << true << false;
+  QTest::newRow( "char 2" ) << QVariant( 'x' ) << QVariant( 'b' ) << false << true;
+  QTest::newRow( "date" ) << QVariant( QDate( 2000, 5, 6 ) ) << QVariant( QDate( 2000, 8, 6 ) ) << true << false;
+  QTest::newRow( "date 2" ) << QVariant( QDate( 2000, 8, 6 ) ) << QVariant( QDate( 2000, 5, 6 ) ) << false << true;
+  QTest::newRow( "time" ) << QVariant( QTime( 13, 5, 6 ) ) << QVariant( QTime( 13, 8, 6 ) ) << true << false;
+  QTest::newRow( "time 2" ) << QVariant( QTime( 18, 8, 6 ) ) << QVariant( QTime( 13, 5, 6 ) ) << false << true;
+  QTest::newRow( "datetime" ) << QVariant( QDateTime( QDate( 2000, 5, 6 ), QTime( 13, 5, 6 ) ) ) << QVariant( QDateTime( QDate( 2000, 8, 6 ), QTime( 13, 5, 6 ) ) ) << true << false;
+  QTest::newRow( "datetime 2" ) << QVariant( QDateTime( QDate( 2000, 8, 6 ), QTime( 13, 5, 6 ) ) ) << QVariant( QDateTime( QDate( 2000, 5, 6 ), QTime( 13, 5, 6 ) ) ) << false << true;
+  QTest::newRow( "datetime 3" ) << QVariant( QDateTime( QDate( 2000, 5, 6 ), QTime( 13, 5, 6 ) ) ) << QVariant( QDateTime( QDate( 2000, 5, 6 ), QTime( 13, 9, 6 ) ) ) << true << false;
+  QTest::newRow( "datetime 4" ) << QVariant( QDateTime( QDate( 2000, 5, 6 ), QTime( 13, 9, 6 ) ) ) << QVariant( QDateTime( QDate( 2000, 5, 6 ), QTime( 13, 5, 6 ) ) ) << false << true;
+  QTest::newRow( "bool" ) << QVariant( false ) << QVariant( true ) << true << false;
+  QTest::newRow( "bool 2" ) << QVariant( true ) << QVariant( false ) << false << true;
+  QTest::newRow( "qvariantlist" ) << QVariant( QVariantList() << QVariant( 5 ) ) << QVariant( QVariantList() << QVariant( 9 ) ) << true << false;
+  QTest::newRow( "qvariantlist 2" ) << QVariant( QVariantList() << QVariant( 9 ) ) << QVariant( QVariantList() << QVariant( 5 ) ) << false << true;
+  QTest::newRow( "qvariantlist 3" ) << QVariant( QVariantList() << QVariant( 5 ) << QVariant( 3 ) ) << QVariant( QVariantList() << QVariant( 5 ) << QVariant( 6 ) ) << true << false;
+  QTest::newRow( "qvariantlist 4" ) << QVariant( QVariant( QVariantList() << QVariant( 5 ) << QVariant( 6 ) ) ) << QVariant( QVariantList() << QVariant( 5 ) << QVariant( 3 ) ) << false << true;
+  QTest::newRow( "qvariantlist 5" ) << QVariant( QVariantList() << QVariant( 5 ) ) << QVariant( QVariantList() << QVariant( 5 ) << QVariant( 6 ) ) << true << false;
+  QTest::newRow( "qvariantlist 5" ) << QVariant( QVariantList() << QVariant( 5 ) << QVariant( 6 ) ) << QVariant( QVariantList() << QVariant( 5 ) ) << false << true;
+  QTest::newRow( "qstringlist" ) << QVariant( QStringList() << "aa" ) << QVariant( QStringList() << "bb" ) << true << false;
+  QTest::newRow( "qstringlist 2" ) << QVariant( QStringList() << "bb" ) << QVariant( QStringList() << "aa" ) << false << true;
+  QTest::newRow( "qstringlist 3" ) << QVariant( QStringList() << "aa" << "cc" ) << QVariant( QStringList() << "aa" << "xx" ) << true << false;
+  QTest::newRow( "qstringlist 4" ) << QVariant( QStringList() << "aa" << "xx" ) << QVariant( QStringList() << "aa" << "cc" ) << false << true;
+  QTest::newRow( "qstringlist 5" ) << QVariant( QStringList() << "aa" ) << QVariant( QStringList() << "aa" << "xx" ) << true << false;
+  QTest::newRow( "qstringlist 6" ) << QVariant( QStringList() << "aa" << "xx" ) << QVariant( QStringList() << "aa" ) << false << true;
+  QTest::newRow( "string" ) << QVariant( "a b c" ) << QVariant( "d e f" ) << true << false;
+  QTest::newRow( "string 2" ) << QVariant( "d e f" ) << QVariant( "a b c" ) << false << true;
+}
+
+void TestQGis::qVariantCompare()
+{
+  QFETCH( QVariant, lhs );
+  QFETCH( QVariant, rhs );
+  QFETCH( bool, lessThan );
+  QFETCH( bool, greaterThan );
+
+  QCOMPARE( qgsVariantLessThan( lhs, rhs ), lessThan );
+  QCOMPARE( qgsVariantGreaterThan( lhs, rhs ), greaterThan );
+}
+
 QTEST_MAIN( TestQGis )
 #include "testqgis.moc"
diff --git a/tests/src/core/testqgslegendrenderer.cpp b/tests/src/core/testqgslegendrenderer.cpp
index d33cd12..7d9e251 100644
--- a/tests/src/core/testqgslegendrenderer.cpp
+++ b/tests/src/core/testqgslegendrenderer.cpp
@@ -110,6 +110,7 @@ class TestQgsLegendRenderer : public QObject
 
     void testBasic();
     void testBigMarker();
+    void testMapUnits();
     void testLongSymbolText();
     void testThreeColumns();
     void testFilterByMap();
@@ -290,6 +291,42 @@ void TestQgsLegendRenderer::testBigMarker()
   QVERIFY( _verifyImage( testName, mReport ) );
 }
 
+void TestQgsLegendRenderer::testMapUnits()
+{
+  QString testName = "legend_mapunits";
+
+  QgsMarkerSymbolV2* sym = new QgsMarkerSymbolV2();
+  sym->setColor( Qt::red );
+  sym->setSize( 100 );
+  sym->setSizeUnit( QgsSymbolV2::MapUnit );
+  QgsCategorizedSymbolRendererV2* catRenderer = dynamic_cast<QgsCategorizedSymbolRendererV2*>( mVL3->rendererV2() );
+  QVERIFY( catRenderer );
+  catRenderer->updateCategorySymbol( 0, sym );
+
+  sym = new QgsMarkerSymbolV2();
+  sym->setColor( Qt::green );
+  sym->setSize( 300 );
+  sym->setSizeUnit( QgsSymbolV2::MapUnit );
+  catRenderer->updateCategorySymbol( 1, sym );
+
+  sym = new QgsMarkerSymbolV2();
+  sym->setColor( Qt::blue );
+  sym->setSize( 5 );
+  sym->setSizeUnit( QgsSymbolV2::MM );
+  catRenderer->updateCategorySymbol( 2, sym );
+
+  QgsLayerTreeGroup* root = new QgsLayerTreeGroup();
+  root->addLayer( mVL3 );
+  QgsLayerTreeModel legendModel( root );
+
+  QgsLegendSettings settings;
+  _setStandardTestFont( settings );
+  settings.setMmPerMapUnit( 0.1 );
+  settings.setMapScale( 1000 );
+  _renderLegend( testName, &legendModel, settings );
+  QVERIFY( _verifyImage( testName, mReport ) );
+}
+
 void TestQgsLegendRenderer::testLongSymbolText()
 {
   QString testName = "legend_long_symbol_text";
diff --git a/tests/src/core/testqgssimplemarker.cpp b/tests/src/core/testqgssimplemarker.cpp
index 92d42d7..d8b0a1a 100644
--- a/tests/src/core/testqgssimplemarker.cpp
+++ b/tests/src/core/testqgssimplemarker.cpp
@@ -60,6 +60,9 @@ class TestQgsSimpleMarkerSymbol : public QObject
 
     void simpleMarkerSymbol();
     void bounds();
+    void boundsWithOffset();
+    void boundsWithRotation();
+    void boundsWithRotationAndOffset();
 
   private:
     bool mTestHasError;
@@ -152,6 +155,57 @@ void TestQgsSimpleMarkerSymbol::bounds()
   mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, true );
   bool result = imageCheck( "simplemarker_bounds" );
   mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, false );
+  mSimpleMarkerLayer->removeDataDefinedProperty( "size" );
+  QVERIFY( result );
+}
+
+void TestQgsSimpleMarkerSymbol::boundsWithOffset()
+{
+  mSimpleMarkerLayer->setColor( QColor( 200, 200, 200 ) );
+  mSimpleMarkerLayer->setBorderColor( QColor( 0, 0, 0 ) );
+  mSimpleMarkerLayer->setName( "circle" );
+  mSimpleMarkerLayer->setSize( 5 );
+  mSimpleMarkerLayer->setDataDefinedProperty( "offset", new QgsDataDefined( true, true, "if(importance > 2, '5,10', '10, 5')" ) );
+  mSimpleMarkerLayer->setOutlineWidth( 0.5 );
+
+  mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, true );
+  bool result = imageCheck( "simplemarker_boundsoffset" );
+  mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, false );
+  mSimpleMarkerLayer->removeDataDefinedProperty( "offset" );
+  QVERIFY( result );
+}
+
+void TestQgsSimpleMarkerSymbol::boundsWithRotation()
+{
+  mSimpleMarkerLayer->setColor( QColor( 200, 200, 200 ) );
+  mSimpleMarkerLayer->setBorderColor( QColor( 0, 0, 0 ) );
+  mSimpleMarkerLayer->setName( "square" );
+  mSimpleMarkerLayer->setSize( 5 );
+  mSimpleMarkerLayer->setDataDefinedProperty( "angle", new QgsDataDefined( true, true, "importance * 20" ) );
+  mSimpleMarkerLayer->setOutlineWidth( 0.5 );
+
+  mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, true );
+  bool result = imageCheck( "simplemarker_boundsrotation" );
+  mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, false );
+  mSimpleMarkerLayer->removeDataDefinedProperty( "angle" );
+  QVERIFY( result );
+}
+
+void TestQgsSimpleMarkerSymbol::boundsWithRotationAndOffset()
+{
+  mSimpleMarkerLayer->setColor( QColor( 200, 200, 200 ) );
+  mSimpleMarkerLayer->setBorderColor( QColor( 0, 0, 0 ) );
+  mSimpleMarkerLayer->setName( "square" );
+  mSimpleMarkerLayer->setSize( 5 );
+  mSimpleMarkerLayer->setDataDefinedProperty( "offset", new QgsDataDefined( true, true, "if(importance > 2, '5,10', '10, 5')" ) );
+  mSimpleMarkerLayer->setDataDefinedProperty( "angle", new QgsDataDefined( true, false, QString(), "heading" ) );
+  mSimpleMarkerLayer->setOutlineWidth( 0.5 );
+
+  mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, true );
+  bool result = imageCheck( "simplemarker_boundsrotationoffset" );
+  mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, false );
+  mSimpleMarkerLayer->removeDataDefinedProperty( "offset" );
+  mSimpleMarkerLayer->removeDataDefinedProperty( "angle" );
   QVERIFY( result );
 }
 
diff --git a/tests/src/gui/testqgsfieldexpressionwidget.cpp b/tests/src/gui/testqgsfieldexpressionwidget.cpp
index bdf78f5..ff8d5f0 100644
--- a/tests/src/gui/testqgsfieldexpressionwidget.cpp
+++ b/tests/src/gui/testqgsfieldexpressionwidget.cpp
@@ -49,6 +49,7 @@ class TestQgsFieldExpressionWidget : public QObject
 
     void testRemoveJoin();
     void asExpression();
+    void testIsValid();
 
   private:
     QgsFieldExpressionWidget* mWidget;
@@ -161,6 +162,62 @@ void TestQgsFieldExpressionWidget::asExpression()
   QgsMapLayerRegistry::instance()->removeMapLayer( layer );
 }
 
+void TestQgsFieldExpressionWidget::testIsValid()
+{
+  QgsVectorLayer* layer = new QgsVectorLayer( "point?field=fld:int&field=name%20with%20space:string", "x", "memory" );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer );
+
+  QScopedPointer< QgsFieldExpressionWidget > widget( new QgsFieldExpressionWidget() );
+  widget->setLayer( layer );
+
+  // also check the fieldChanged signal to ensure that the emitted bool isValid value is correct
+  QSignalSpy spy( widget.data(), SIGNAL( fieldChanged( QString, bool ) ) );
+
+  // check with simple field name set
+  bool isExpression = false;
+  bool isValid = false;
+  widget->setField( "fld" );
+  QCOMPARE( widget->currentField( &isExpression, &isValid ), QString( "fld" ) );
+  QVERIFY( !isExpression );
+  QVERIFY( isValid );
+  QVERIFY( widget->isValidExpression() );
+  QCOMPARE( spy.count(), 1 );
+  QCOMPARE( spy.last().at( 0 ).toString(), QString( "fld" ) );
+  QVERIFY( spy.last().at( 1 ).toBool() );
+
+
+  //check with complex field name set
+  widget->setField( "name with space" );
+  QCOMPARE( widget->currentField( &isExpression, &isValid ), QString( "name with space" ) );
+  QVERIFY( !isExpression );
+  QVERIFY( isValid );
+  QVERIFY( !widget->isValidExpression() );
+  QCOMPARE( spy.count(), 2 );
+  QCOMPARE( spy.last().at( 0 ).toString(), QString( "name with space" ) );
+  QVERIFY( spy.last().at( 1 ).toBool() );
+
+  //check with valid expression set
+  widget->setField( "2 * 4" );
+  QCOMPARE( widget->currentField( &isExpression, &isValid ), QString( "2 * 4" ) );
+  QVERIFY( isExpression );
+  QVERIFY( isValid );
+  QVERIFY( widget->isValidExpression() );
+  QCOMPARE( spy.count(), 3 );
+  QCOMPARE( spy.last().at( 0 ).toString(), QString( "2 * 4" ) );
+  QVERIFY( spy.last().at( 1 ).toBool() );
+
+  //check with invalid expression set
+  widget->setField( "2 *" );
+  QCOMPARE( widget->currentField( &isExpression, &isValid ), QString( "2 *" ) );
+  QVERIFY( isExpression );
+  QVERIFY( !isValid );
+  QVERIFY( !widget->isValidExpression() );
+  QCOMPARE( spy.count(), 4 );
+  QCOMPARE( spy.last().at( 0 ).toString(), QString( "2 *" ) );
+  QVERIFY( !spy.last().at( 1 ).toBool() );
+
+  QgsMapLayerRegistry::instance()->removeMapLayer( layer );
+}
 
 QTEST_MAIN( TestQgsFieldExpressionWidget )
 #include "testqgsfieldexpressionwidget.moc"
diff --git a/tests/src/python/providertestbase.py b/tests/src/python/providertestbase.py
index 26e6d86..be585b2 100644
--- a/tests/src/python/providertestbase.py
+++ b/tests/src/python/providertestbase.py
@@ -14,13 +14,61 @@ __revision__ = '$Format:%H$'
 
 from qgis.core import QgsRectangle, QgsFeatureRequest, QgsFeature, QgsGeometry, NULL
 
+from utilities import(
+    compareWkt
+)
+
 
 class ProviderTestCase(object):
 
+    def testGetFeatures(self):
+        """ Test that expected results are returned when fetching all features """
+
+        # IMPORTANT - we do not use `for f in provider.getFeatures()` as we are also
+        # testing that existing attributes & geometry in f are overwritten correctly
+        # (for f in ... uses a new QgsFeature for every iteration)
+
+        it = self.provider.getFeatures()
+        f = QgsFeature()
+        attributes = {}
+        geometries = {}
+        while it.nextFeature(f):
+            # split off the first 5 attributes only - some provider test datasets will include
+            # additional attributes which we ignore
+            attrs = f.attributes()[0:5]
+            # force the num_char attribute to be text - some providers (eg delimited text) will
+            # automatically detect that this attribute contains numbers and set it as a numeric
+            # field
+            attrs[4] = str(attrs[4])
+            attributes[f['pk']] = attrs
+            geometries[f['pk']] = f.constGeometry() and f.constGeometry().exportToWkt()
+
+        expected_attributes = {5: [5, -200, NULL, 'NuLl', '5'],
+                               3: [3, 300, 'Pear', 'PEaR', '3'],
+                               1: [1, 100, 'Orange', 'oranGe', '1'],
+                               2: [2, 200, 'Apple', 'Apple', '2'],
+                               4: [4, 400, 'Honey', 'Honey', '4']}
+        self.assertEqual(attributes, expected_attributes, 'Expected {}, got {}'.format(expected_attributes, attributes))
+
+        expected_geometries = {1: 'Point (-70.332 66.33)',
+                               2: 'Point (-68.2 70.8)',
+                               3: None,
+                               4: 'Point(-65.32 78.3)',
+                               5: 'Point(-71.123 78.23)'}
+        for pk, geom in expected_geometries.iteritems():
+            if geom:
+                assert compareWkt(geom, geometries[pk]), "Geometry {} mismatch Expected:\n{}\nGot:\n{}\n".format(pk, geom, geometries[pk].exportToWkt())
+            else:
+                self.assertFalse(geometries[pk], 'Expected null geometry for {}'.format(pk))
+
     def assert_query(self, provider, expression, expected):
         result = set([f['pk'] for f in provider.getFeatures(QgsFeatureRequest().setFilterExpression(expression))])
         assert set(expected) == result, 'Expected {} and got {} when testing expression "{}"'.format(set(expected), result, expression)
 
+        # Also check that filter works when referenced fields are not being retrieved by request
+        result = set([f['pk'] for f in provider.getFeatures(QgsFeatureRequest().setFilterExpression(expression).setSubsetOfAttributes([0]))])
+        assert set(expected) == result, 'Expected {} and got {} when testing expression "{}" using empty attribute subset'.format(set(expected), result, expression)
+
     '''
         This is a collection of tests for vector data providers and kept generic.
         To make use of it, subclass it and set self.provider to a provider you want to test.
@@ -161,6 +209,10 @@ class ProviderTestCase(object):
         """Individual providers may need to override this depending on their subset string formats"""
         return '"cnt" > 100 and "cnt" < 410'
 
+    def getSubsetString2(self):
+        """Individual providers may need to override this depending on their subset string formats"""
+        return '"cnt" > 100 and "cnt" < 400'
+
     def testOrderByUncompiled(self):
         try:
             self.disableCompiler()
@@ -345,10 +397,22 @@ class ProviderTestCase(object):
         self.assertEqual(self.provider.minimumValue(1), -200)
         self.assertEqual(self.provider.minimumValue(2), 'Apple')
 
+        subset = self.getSubsetString()
+        self.provider.setSubsetString(subset)
+        min_value = self.provider.minimumValue(1)
+        self.provider.setSubsetString(None)
+        self.assertEqual(min_value, 200)
+
     def testMaxValue(self):
         self.assertEqual(self.provider.maximumValue(1), 400)
         self.assertEqual(self.provider.maximumValue(2), 'Pear')
 
+        subset = self.getSubsetString2()
+        self.provider.setSubsetString(subset)
+        max_value = self.provider.maximumValue(1)
+        self.provider.setSubsetString(None)
+        self.assertEqual(max_value, 300)
+
     def testExtent(self):
         reference = QgsGeometry.fromRect(
             QgsRectangle(-71.123, 66.33, -65.32, 78.3))
@@ -360,6 +424,12 @@ class ProviderTestCase(object):
         self.assertEqual(set(self.provider.uniqueValues(1)), set([-200, 100, 200, 300, 400]))
         assert set([u'Apple', u'Honey', u'Orange', u'Pear', NULL]) == set(self.provider.uniqueValues(2)), 'Got {}'.format(set(self.provider.uniqueValues(2)))
 
+        subset = self.getSubsetString2()
+        self.provider.setSubsetString(subset)
+        values = self.provider.uniqueValues(1)
+        self.provider.setSubsetString(None)
+        self.assertEqual(set(values), set([200, 300]))
+
     def testFeatureCount(self):
         assert self.provider.featureCount() == 5, 'Got {}'.format(self.provider.featureCount())
 
diff --git a/tests/src/python/test_provider_memory.py b/tests/src/python/test_provider_memory.py
index 3165a56..4e94c29 100644
--- a/tests/src/python/test_provider_memory.py
+++ b/tests/src/python/test_provider_memory.py
@@ -264,7 +264,7 @@ class TestPyQgsMemoryProviderIndexed(unittest.TestCase, ProviderTestCase):
     def setUpClass(cls):
         """Run before all tests"""
         # Create test layer
-        cls.vl = QgsVectorLayer(u'Point?crs=epsg:4326&index=yes&field=pk:integer&field=cnt:integer&field=name:string(0)&field=name2:string(0)&field=num_char:string&key=pk',
+        cls.vl = QgsVectorLayer(u'Point?crs=epsg:4326&index=yes&field=pk:integer&field=cnt:int8&field=name:string(0)&field=name2:string(0)&field=num_char:string&key=pk',
                                 u'test', u'memory')
         assert (cls.vl.isValid())
         cls.provider = cls.vl.dataProvider()
diff --git a/tests/src/python/test_qgsdelimitedtextprovider_wanted.py b/tests/src/python/test_qgsdelimitedtextprovider_wanted.py
index 8c5db86..aa5d808 100644
--- a/tests/src/python/test_qgsdelimitedtextprovider_wanted.py
+++ b/tests/src/python/test_qgsdelimitedtextprovider_wanted.py
@@ -2395,3 +2395,57 @@ def test_039_issue_13749():
         u'1 records have missing geometry definitions',
     ]
     return wanted
+
+
+def test_040_issue_14666():
+    wanted = {}
+    wanted['uri'] = u'file://test14666.csv?yField=y&xField=x&type=csv&delimiter=\\t'
+    wanted['fieldTypes'] = ['integer', 'double', 'double']
+    wanted['geometryType'] = 0
+    wanted['data'] = {
+        2: {
+            'id': u'1',
+            'description': u'7.15417',
+            'x': u'7.15417',
+            'y': u'50.680622',
+            '#fid': 2,
+            '#geometry': 'Point (7.1541699999999997 50.68062199999999962)',
+        },
+        3: {
+            'id': u'2',
+            'description': u'7.119219',
+            'x': u'7.119219',
+            'y': u'50.739814',
+            '#fid': 3,
+            '#geometry': 'Point (7.11921900000000019 50.73981400000000264)',
+        },
+        4: {
+            'id': u'3',
+            'description': u'NULL',
+            'x': u'NULL',
+            'y': u'NULL',
+            '#fid': 4,
+            '#geometry': 'None',
+        },
+        5: {
+            'id': u'4',
+            'description': u'NULL',
+            'x': u'NULL',
+            'y': u'NULL',
+            '#fid': 5,
+            '#geometry': 'None',
+        },
+        6: {
+            'id': u'5',
+            'description': u'7.129229',
+            'x': u'7.129229',
+            'y': u'50.703692',
+            '#fid': 6,
+            '#geometry': 'Point (7.12922899999999959 50.70369199999999665)',
+        },
+    }
+    wanted['log'] = [
+        u'Errors in file test14666.csv',
+        u'2 records have missing geometry definitions',
+    ]
+    return wanted
diff --git a/tests/testdata/control_images/legend/expected_legend_mapunits/expected_legend_mapunits.png b/tests/testdata/control_images/legend/expected_legend_mapunits/expected_legend_mapunits.png
new file mode 100644
index 0000000..3053dae
Binary files /dev/null and b/tests/testdata/control_images/legend/expected_legend_mapunits/expected_legend_mapunits.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_mapunits/expected_legend_mapunits_mask.png b/tests/testdata/control_images/legend/expected_legend_mapunits/expected_legend_mapunits_mask.png
new file mode 100644
index 0000000..74a3009
Binary files /dev/null and b/tests/testdata/control_images/legend/expected_legend_mapunits/expected_legend_mapunits_mask.png differ
diff --git a/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsoffset/expected_simplemarker_boundsoffset.png b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsoffset/expected_simplemarker_boundsoffset.png
new file mode 100644
index 0000000..980b80f
Binary files /dev/null and b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsoffset/expected_simplemarker_boundsoffset.png differ
diff --git a/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsoffset/expected_simplemarker_boundsoffset_mask.png b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsoffset/expected_simplemarker_boundsoffset_mask.png
new file mode 100644
index 0000000..75b1e9a
Binary files /dev/null and b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsoffset/expected_simplemarker_boundsoffset_mask.png differ
diff --git a/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotation/expected_simplemarker_boundsrotation.png b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotation/expected_simplemarker_boundsrotation.png
new file mode 100644
index 0000000..a5e38c2
Binary files /dev/null and b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotation/expected_simplemarker_boundsrotation.png differ
diff --git a/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotation/expected_simplemarker_boundsrotation_mask.png b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotation/expected_simplemarker_boundsrotation_mask.png
new file mode 100644
index 0000000..8004f79
Binary files /dev/null and b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotation/expected_simplemarker_boundsrotation_mask.png differ
diff --git a/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotationoffset/expected_simplemarker_boundsrotationoffset.png b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotationoffset/expected_simplemarker_boundsrotationoffset.png
new file mode 100644
index 0000000..ebd50f7
Binary files /dev/null and b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotationoffset/expected_simplemarker_boundsrotationoffset.png differ
diff --git a/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotationoffset/expected_simplemarker_boundsrotationoffset_mask.png b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotationoffset/expected_simplemarker_boundsrotationoffset_mask.png
new file mode 100644
index 0000000..ef2bd50
Binary files /dev/null and b/tests/testdata/control_images/symbol_simplemarker/expected_simplemarker_boundsrotationoffset/expected_simplemarker_boundsrotationoffset_mask.png differ
diff --git a/tests/testdata/delimitedtext/test14666.csv b/tests/testdata/delimitedtext/test14666.csv
new file mode 100644
index 0000000..91ff974
--- /dev/null
+++ b/tests/testdata/delimitedtext/test14666.csv
@@ -0,0 +1,7 @@
+id	x	y
+1	7.15417	50.680622
+2	7.119219	50.739814
+3		
+4		
+5	7.129229	50.703692
+

-- 
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