[qgis] 01/01: Imported Upstream version 2.18.7+dfsg

Bas Couwenberg sebastic at debian.org
Sat Apr 22 14:18:29 UTC 2017


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

sebastic pushed a commit to branch upstream
in repository qgis.

commit 4676c1e64a7cd3e1353cfa110e50425c8f5c103e
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat Apr 22 16:09:18 2017 +0200

    Imported Upstream version 2.18.7+dfsg
---
 CMakeLists.txt                                     |   2 +-
 ChangeLog                                          | 181 +++++++++++++++++
 INSTALL                                            |  23 ++-
 debian/changelog                                   |  16 +-
 debian/compat.in                                   |   2 +-
 debian/control.in                                  |  41 ++--
 debian/qgis-providers.install.in                   |   4 +-
 debian/rules                                       |   6 +-
 doc/INSTALL.html                                   |  38 ++--
 doc/linux.t2t                                      |  15 +-
 doc/msys.t2t                                       |   2 +-
 python/core/raster/qgsrasterinterface.sip          |   5 +-
 .../MetaSearch/resources/connections-default.xml   |   2 +-
 .../plugins/processing/algs/grass7/Grass7Utils.py  |  53 ++++-
 .../plugins/processing/algs/qgis/FieldsMapper.py   |  55 +++---
 .../processing/algs/saga/SagaAlgorithmProvider.py  |   2 +-
 python/plugins/processing/algs/saga/SagaUtils.py   |  27 ++-
 .../plugins/processing/algs/taudem/TauDEMUtils.py  |  13 +-
 python/plugins/processing/tools/spatialite.py      |   5 +-
 src/app/composer/qgscomposermapwidget.cpp          |   7 +-
 src/app/composer/qgscomposermapwidget.h            |   3 +-
 src/app/pluginmanager/qgspluginmanager.cpp         |   2 +-
 src/app/qgsfeatureaction.cpp                       |  28 ++-
 src/core/CMakeLists.txt                            |   3 +
 src/core/composer/qgsatlascomposition.cpp          |  31 ++-
 src/core/composer/qgsatlascomposition.h            |   5 +-
 src/core/composer/qgscomposerattributetablev2.cpp  |  41 ++--
 src/core/composer/qgscomposerattributetablev2.h    |   5 +-
 src/core/composer/qgscomposermap.cpp               |  45 ++++-
 src/core/qgsmaplayerlistutils.h                    |  57 ++++++
 src/core/qgsmaplayerref.h                          | 220 +++++++++++++++++++++
 src/core/qgsmaprendererparalleljob.cpp             |  10 +-
 src/core/qgsmaprendererparalleljob.h               |   4 +
 src/core/qgsvectorfilewriter.cpp                   |  34 +++-
 src/core/qgsvectorlayerref.h                       |  10 +
 src/providers/mssql/qgsmssqlprovider.cpp           |  20 +-
 src/providers/wms/qgswmscapabilities.cpp           |   6 -
 src/python/qgspythonutils.h                        |   4 +-
 src/server/qgsserverprojectparser.cpp              |   2 +-
 src/server/qgswmsprojectparser.cpp                 |   2 +-
 tests/src/core/testqgscomposition.cpp              | 215 ++++++++++++++++++++
 tests/src/core/testqgsmaplayer.cpp                 | 111 ++++++++++-
 tests/src/python/test_qgsvectorfilewriter.py       |  62 +++++-
 43 files changed, 1217 insertions(+), 202 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1b366b7..8d029e2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 SET(CPACK_PACKAGE_VERSION_MAJOR "2")
 SET(CPACK_PACKAGE_VERSION_MINOR "18")
-SET(CPACK_PACKAGE_VERSION_PATCH "5")
+SET(CPACK_PACKAGE_VERSION_PATCH "7")
 SET(COMPLETE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
 SET(RELEASE_NAME "Las Palmas")
 IF (POLICY CMP0048) # in CMake 3.0.0+
diff --git a/ChangeLog b/ChangeLog
index 1b789df..6fc642f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,184 @@
+Juergen E. Fischer <jef at norbit.de>	2017-04-21
+
+    fix windows build
+
+Juergen E. Fischer <jef at norbit.de>	2017-04-20
+
+    avoid opening multiple attribute forms for a single feature in identify
+    (fixes #13520)
+
+    On behalf of Faunalia, sponsored by ENEL
+
+rldhont <rldhont at gmail.com>	2017-04-20
+
+    [BUGFIX][Processing] Fix spatialite version comparison
+
+Mathieu Pellerin <nirvn.asia at gmail.com>	2017-04-19
+
+    fix qgis startup crash with plugin manager (#4371)
+
+Merge: 1cc2c410ac 4c7cff5ae7
+Nyall Dawson <nyall.dawson at gmail.com>	2017-04-19
+
+    Merge pull request #4370 from nyalldawson/backport_composer_template_fixes
+
+    Backport composer template fixes
+
+Nyall Dawson <nyall.dawson at gmail.com>	2017-04-19
+
+    [composer] Correctly handle restoring map layer style overrides from template
+
+    (when template was created in a different project)
+
+    On behalf of Faunalia, sponsored by ENEL
+
+    (cherry-picked from 58ded289)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2017-04-19
+
+    Correctly handle restoring atlas coverage layer from template
+
+    (when template was created in a different project)
+
+    On behalf of Faunalia, sponsored by ENEL
+
+    (cherry-picked from 5b6b035)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2017-04-19
+
+    [composer] Correctly restore map item layers when loading a template
+    in a different project to that which the template was created in
+
+    On behalf of Faunalia, sponsored by ENEL
+
+    (cherry-picked from 2ca70dc)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2017-04-19
+
+    [composer] Use weak layer reference matching when loading attribute table from XML
+
+    Allows attribute tables in templates to reattach to matching layers
+    when loaded in a different project to the project the template was
+    created in.
+
+    On behalf of Faunalia, sponsored by ENEL
+
+    (cherry-picked from eb1e820)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2017-04-19
+
+    Backport weak layer reference utilities from 3.0
+
+Merge: 14d96fcf1b 6b5a997df5
+mhugent <marco.hugentobler at sourcepole.ch>	2017-04-18
+
+    Merge pull request #4369 from mhugent/server_layerorder
+
+    Fix layer drawing order in server to also work in complex projects and with custom drawing order
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2017-04-18
+
+    Fix layer drawing order in server to also work in complex projects and with custom drawing order
+
+Juergen E. Fischer <jef at norbit.de>	2017-04-11
+
+    debian packaging: add zesty
+
+Nathan Woodrow <nathan_woodrow at technologyonecorp.com>	2017-04-12
+
+    backport [MSSQL] Fix update/insert with timestamp columns
+
+Nyall Dawson <nyall.dawson at gmail.com>	2017-04-12
+
+    [composer] Only update map rotation when editing finishes
+
+    Avoids multiple map updates when entering values like "90".
+    Previously the map would be updated at every keystroke,
+    so "9" and "90" degree rotations.
+
+    Backported from 49e1ae4
+
+Nyall Dawson <nyall.dawson at gmail.com>	2017-04-10
+
+    Much faster save as vector layer when using restricted extent
+
+    Use a provider filter rect to avoid looping through every single
+    feature in this case, and also use a prepared extent geometry
+    to speed up the remaining intersection checks.
+
+    (cherry-picked from d2f3eb1ba)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2017-04-10
+
+    Fix missing sip cast for QgsHillshadeRenderer
+
+    (cherry-picked from 8cf586)
+
+Juergen E. Fischer <jef at norbit.de>	2017-04-07
+
+    Release of 2.18.6
+
+Borys Jurgiel <info at borysjurgiel.pl>	2017-04-06
+
+    Fix Refactor Fields error if layer has no features
+
+Tom Kralidis <tomkralidis at gmail.com>	2017-04-05
+
+    backport a30cf2923c75e786f085593a1c69463310aae66d
+
+Nyall Dawson <nyall.dawson at gmail.com>	2017-04-01
+
+    Followup 90f381, fix memory leaks when rendering canvas
+
+Alexander Bruy <alexander.bruy at gmail.com>	2017-03-28
+
+    [processing] temporarily disable escaping commands as it produced
+    strange results
+
+Alexander Bruy <alexander.bruy at gmail.com>	2017-03-28
+
+    [processing] add missed escapeAndJoin function to TauDEM provider
+
+Juergen E. Fischer <jef at norbit.de>	2017-03-28
+
+    debian packaging: remove python-owslib from python-qgis dependencies
+        on trusty
+
+Alessandro Pasotti <apasotti at boundlessgeo.com>	2017-03-28
+
+    Removed a few debug messages (credentials leakage)
+
+Juergen E. Fischer <jef at norbit.de>	2017-01-25
+
+    [processing] find grass >=7.0
+
+    (backport of 099e7a7)
+
+Juergen E. Fischer <jef at norbit.de>	2017-03-27
+
+    debian packaging: remove python-future from python-qgis dependencies
+    on jessie and trusty
+
+rldhont <rldhont at gmail.com>	2017-03-27
+
+    [BUGFIX][Processing] SAGA not loaded on QGIS 2.18.5
+
+    Fixed #16378
+
+Juergen E. Fischer <jef at norbit.de>	2017-03-24
+
+    make travis happy
+
+Juergen E. Fischer <jef at norbit.de>	2017-02-19
+
+    processing: improve saga detection on windows
+
+    (cherry picked from commit 0d1ab702fc7112afabf5319ad947a445bb219acd)
+
+Juergen E. Fischer <jef at norbit.de>	2017-03-24
+
+    Release of 2.18.5
+
 Alessandro Pasotti <apasotti at boundlessgeo.com>	2017-03-24
 
     [bugfix][backport] Apply authentication configuration to xyz layers
diff --git a/INSTALL b/INSTALL
index eaf1f2b..249db47 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,10 +1,10 @@
 QGIS
 Building QGIS from source - step by step
-Thursday June 09, 2016
+Wednesday April 12, 2017
 
 
-Last Updated: Thursday June 09, 2016
-Last Change : Thursday June 09, 2016
+Last Updated: Wednesday April 12, 2017
+Last Change : Wednesday April 12, 2017
 
 
   1. Introduction
@@ -181,14 +181,13 @@ Now update your local sources database:
   ===============================
 
   || Distribution | install command for packages |
-  | wheezy | ``apt-get install bison cmake doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal1-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools python python-dev python-gdal py [...]
-  | jessie | ``apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-a [...]
-  | stretch | ``apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all python-all-de [...]
-  | precise | ``apt-get install bison cmake doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools python python-gdal python-mock python-ps [...]
-  | trusty | ``apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools python-all python- [...]
-  | wily | ``apt-get install bison cmake cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev [...]
-  | xenial | ``apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all python-al [...]
-  | sid | ``apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all python-all-d [...]
+  | jessie | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.q [...]
+  | stretch | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.q [...]
+  | trusty | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools py [...]
+  | xenial | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyq [...]
+  | yakkety | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools py [...]
+  | zesty | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt [...]
+  | sid | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4. [...]
 
 (extracted from the control.in file in debian/)
 
@@ -721,7 +720,7 @@ to get versions that match your current Qt installed version.
       ===========================
 
 /!\ You can delete the directories with unpacked SIP and PyQt4 sources after a
-successfull install, they're not needed anymore.
+successful install, they're not needed anymore.
 
 
     4.2.5. git
diff --git a/debian/changelog b/debian/changelog
index 5fbb86c..eb609a1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,20 @@
-qgis (2.18.5) UNRELEASED; urgency=medium
+qgis (2.18.7) UNRELEASED; urgency=medium
+
+  * Release of 2.18.7
+
+ -- Jürgen E. Fischer <jef at norbit.de>  Fri, 21 Apr 2017 14:35:39 +0200
+
+qgis (2.18.6) unstable; urgency=medium
+
+  * Release of 2.18.6
+
+ -- Jürgen E. Fischer <jef at norbit.de>  Fri, 21 Apr 2017 14:35:39 +0200
+
+qgis (2.18.5) unstable; urgency=medium
 
   * Release of 2.18.5
 
- -- Jürgen E. Fischer <jef at norbit.de>  Fri, 24 Mar 2017 13:21:57 +0100
+ -- Jürgen E. Fischer <jef at norbit.de>  Fri, 07 Apr 2017 14:12:04 +0200
 
 qgis (2.18.4) unstable; urgency=medium
 
diff --git a/debian/compat.in b/debian/compat.in
index fa27883..a4bd164 100644
--- a/debian/compat.in
+++ b/debian/compat.in
@@ -1,2 +1,2 @@
-#stretch sid jessie trusty xenial yakkety#9
+#stretch sid jessie trusty xenial yakkety zesty#9
 #jessie#8
diff --git a/debian/control.in b/debian/control.in
index 633e86d..4a25286 100644
--- a/debian/control.in
+++ b/debian/control.in
@@ -6,18 +6,17 @@ Priority: optional
 Build-Depends:
  bison,
  cmake (>= 2.8),
-#sid stretch jessie trusty xenial yakkety# debhelper (>= 9),
-#sid stretch jessie trusty xenial yakkety# dh-python,
+ debhelper (>= 9), dh-python,
  flex,
  grass-dev,
  libexpat1-dev,
  libfcgi-dev,
-#sid stretch jessie trusty xenial yakkety# libgdal-dev (>= 1.10.1-0~),
+ libgdal-dev (>= 1.10.1-0~),
  gdal-bin,
  python-gdal,
  libgeos-dev (>= 3.0.0),
-#jessie trusty# libgsl0-dev,
-#sid stretch xenial yakkety# libgsl-dev,
+#    jessie         trusty                     # libgsl0-dev,
+#sid        stretch        xenial yakkety zesty# libgsl-dev,
  libpq-dev,
  libproj-dev,
  libqt4-dev (>= 4.7.0),
@@ -25,9 +24,9 @@ Build-Depends:
  libqca2-dev,
  libqca2-plugin-ossl,
  libqtwebkit-dev,
-#stretch jessie# libqwt-dev,
-#trusty xenial yakkety sid# libqwt5-qt4-dev,
-#sid stretch jessie trusty xenial yakkety# libqjson-dev,
+#    jessie stretch                            # libqwt-dev,
+#sid                trusty xenial yakkety zesty# libqwt5-qt4-dev,
+ libqjson-dev,
  libspatialite-dev,
  libsqlite3-dev,
  libspatialindex-dev,
@@ -38,11 +37,9 @@ Build-Depends:
  python-qt4-dev,
  python-qt4-sql,
  python-yaml, python-mock,
-#stretch sid xenial yakkety# python-future,
-#sid stretch jessie trusty xenial yakkety# python-all (>= 2.6.6-3~), python-all-dev (>= 2.6.6-3~),
-#sid stretch jessie xenial yakkety# pyqt4.qsci-dev,
-#sid stretch jessie trusty xenial yakkety# python-pyspatialite,
-#sid jessie stretch xenial yakkety# python-nose2,
+ python-all (>= 2.6.6-3~), python-all-dev (>= 2.6.6-3~), python-pyspatialite,
+#sid        stretch        xenial yakkety zesty# python-future,
+#sid jessie stretch        xenial yakkety zesty# pyqt4.qsci-dev, python-nose2,
  python-sip (>= 4.5.0),
  python-sip-dev (>= 4.5.0),
  libosgearth-dev,
@@ -59,11 +56,11 @@ Build-Depends:
  qt4-dev-tools,
  libqt4-sql-sqlite, python-psycopg2, ca-certificates
 Build-Conflicts: libqgis-dev, qgis-dev
-#sid stretch xenial yakkety#Standards-Version: 3.9.7
+#sid stretch xenial yakkety zesty#Standards-Version: 3.9.7
 #jessie#Standards-Version: 3.9.6
 #trusty#Standards-Version: 3.8.4
 #sid stretch jessie#X-Python-Version: >= 2.7, << 2.8
-#trusty xenial yakkety#XS-Python-Version: current
+#trusty xenial yakkety zesty#XS-Python-Version: current
 Vcs-Browser: https://github.com/qgis/QGIS/
 Vcs-Git: https://github.com/qgis/QGIS.git
 Homepage: http://qgis.org/
@@ -236,10 +233,10 @@ Section: libdevel
 Depends:
  grass-dev,
  libexpat1-dev,
-#sid stretch jessie trusty xenial yakkety# libgdal-dev (>= 1.10.1-0~),
+ libgdal-dev (>= 1.10.1-0~),
  libgeos-dev (>= 3.0.0),
-#jessie trusty# libgsl0-dev,
-#sid stretch xenial yakkety# libgsl-dev,
+#    jessie         trusty                     # libgsl0-dev,
+#sid        stretch        xenial yakkety zesty# libgsl-dev,
  libpq-dev,
  libproj-dev,
  libqgis-app{QGIS_ABI} (= ${binary:Version}),
@@ -371,8 +368,12 @@ Depends:
  python-jinja2,
  python-pygments,
  python-requests,
-#!trusty# python-markupsafe, python-dateutil, python-yaml,
-#sid stretch jessie trusty xenial yakkety# python-owslib, python-tz, python-pyproj, python-future, python-six, python-pyspatialite,
+ python-tz,
+ python-pyproj,
+ python-six,
+ python-pyspatialite,
+#sid stretch               xenial yakkety zesty# python-future,
+#sid stretch jessie        xenial yakkety zesty# python-markupsafe, python-dateutil, python-yaml, python-owslib,
  libqgispython{QGIS_ABI},
  ${shlibs:Depends},
  ${python:Depends},
diff --git a/debian/qgis-providers.install.in b/debian/qgis-providers.install.in
index bbf9d4f..b0b683a 100644
--- a/debian/qgis-providers.install.in
+++ b/debian/qgis-providers.install.in
@@ -17,6 +17,6 @@ usr/lib/qgis/plugins/libvirtuallayerprovider.so
 usr/lib/qgis/plugins/libwcsprovider.so
 usr/lib/qgis/plugins/libwfsprovider.so
 usr/lib/qgis/plugins/libwmsprovider.so
-#sid stretch jessie trusty xenial yakkety#usr/lib/qgis/plugins/libarcgismapserverprovider.so
-#sid stretch jessie trusty xenial yakkety#usr/lib/qgis/plugins/libarcgisfeatureserverprovider.so
+#sid stretch jessie trusty xenial yakkety zesty#usr/lib/qgis/plugins/libarcgismapserverprovider.so
+#sid stretch jessie trusty xenial yakkety zesty#usr/lib/qgis/plugins/libarcgisfeatureserverprovider.so
 {QT_PLUGIN_DIR}/sqldrivers/libqsqlspatialite.so
diff --git a/debian/rules b/debian/rules
index d585e9d..9b6c37c 100755
--- a/debian/rules
+++ b/debian/rules
@@ -34,7 +34,7 @@ ifneq (,$(findstring -oracle,$(DISTRIBUTION)))
 	WITH_ORACLE=1
 endif
 
-ifneq ($(DISTRIBUTION),$(findstring $(DISTRIBUTION),"jessie stretch trusty xenial yakkety"))
+ifneq ($(DISTRIBUTION),$(findstring $(DISTRIBUTION),"jessie stretch trusty xenial yakkety zesty"))
 	DISTRIBUTION := sid
 endif
 
@@ -135,7 +135,7 @@ ifneq (,$(findstring $(DISTRIBUTION),"sid stretch"))
 	CMAKE_OPTS += -DPOSTGRES_LIBRARY=/usr/lib/$(DEB_BUILD_MULTIARCH)/libpq.so
 endif
 
-ifneq (,$(findstring $(DISTRIBUTION),"sid stretch yakkety"))
+ifneq (,$(findstring $(DISTRIBUTION),"sid stretch yakkety zesty"))
 	CMAKE_OPTS += -DWITH_INTERNAL_WEBKIT_BINDINGS=TRUE
 endif
 
@@ -143,7 +143,7 @@ ifneq (,$(findstring $(DISTRIBUTION),"sid"))
 	CMAKE_OPTS += -DGEOS_LIBRARY=/usr/lib/$(DEB_BUILD_MULTIARCH)/libgeos_c.so
 endif
 
-ifneq (,$(findstring $(DISTRIBUTION),"jessie stretch trusty xenial yakkety sid"))
+ifneq (,$(findstring $(DISTRIBUTION),"jessie stretch trusty xenial yakkety zesty sid"))
 	CMAKE_OPTS += -DPYTHON_LIBRARY=/usr/lib/$(DEB_BUILD_MULTIARCH)/libpython2.7.so
 endif
 
diff --git a/doc/INSTALL.html b/doc/INSTALL.html
index 971435a..cd9c7ae 100644
--- a/doc/INSTALL.html
+++ b/doc/INSTALL.html
@@ -5,7 +5,7 @@
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
 <TITLE>QGIS</TITLE>
 
-<!-- Included /home/fischer/src/qgis/doc/style.css -->
+<!-- Included /home/fischer/src/qgis-2.18/doc/style.css -->
 <STYLE TYPE="text/css">
 body{  background: white;
   color: black;
@@ -77,13 +77,13 @@ label{  background-color: #FFFFCC;
 <DIV CLASS="header" ID="header">
 <H1>QGIS</H1>
 <H2>Building QGIS from source - step by step</H2>
-<H3>Thursday June 09, 2016</H3>
+<H3>Wednesday April 12, 2017</H3>
 </DIV>
 
 <DIV CLASS="body" ID="body">
 <P>
-Last Updated: Thursday June 09, 2016
-Last Change : Thursday June 09, 2016
+Last Updated: Wednesday April 12, 2017
+Last Change : Wednesday April 12, 2017
 </P>
 <DIV CLASS="toc">
 
@@ -312,36 +312,32 @@ sudo apt-get update
 <TH>install command for packages</TH>
 </TR>
 <TR>
-<TD>wheezy</TD>
-<TD><CODE>apt-get install bison cmake doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal1-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools python python-dev python-gdal python- [...]
-</TR>
-<TR>
 <TD>jessie</TD>
-<TD><CODE>apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all py [...]
+<TD><CODE>apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-d [...]
 </TR>
 <TR>
 <TD>stretch</TD>
-<TD><CODE>apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all python-all-dev pyth [...]
+<TD><CODE>apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-de [...]
 </TR>
 <TR>
-<TD>precise</TD>
-<TD><CODE>apt-get install bison cmake doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools python python-gdal python-mock python-psycopg2 [...]
+<TD>trusty</TD>
+<TD><CODE>apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools python- [...]
 </TR>
 <TR>
-<TD>trusty</TD>
-<TD><CODE>apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools python-all python-all-d [...]
+<TD>xenial</TD>
+<TD><CODE>apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qs [...]
 </TR>
 <TR>
-<TD>wily</TD>
-<TD><CODE>apt-get install bison cmake cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev py [...]
+<TD>yakkety</TD>
+<TD><CODE>apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qs [...]
 </TR>
 <TR>
-<TD>xenial</TD>
-<TD><CODE>apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all python-all-dev [...]
+<TD>zesty</TD>
+<TD><CODE>apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qs [...]
 </TR>
 <TR>
 <TD>sid</TD>
-<TD><CODE>apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all python-all-dev [...]
+<TD><CODE>apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qs [...]
 </TR>
 </TABLE>
 
@@ -1047,7 +1043,7 @@ make install
 
 <P>
 /!\ You can delete the directories with unpacked SIP and PyQt4 sources after a
-successfull install, they're not needed anymore.
+successful install, they're not needed anymore.
 </P>
 
 <H3>4.2.5. git</H3>
@@ -3016,5 +3012,5 @@ The following people have contributed to this document:
 
 </DIV>
 <!-- html code generated by txt2tags 2.6 (http://txt2tags.org) -->
-<!-- cmdline: txt2tags -\-encoding=utf-8 -o/home/fischer/src/qgis/debian/build-master-pyqtwrapper-qt4/doc/INSTALL.html -t html /home/fischer/src/qgis/doc/INSTALL.t2t -->
+<!-- cmdline: txt2tags -\-encoding=utf-8 -o/home/fischer/src/qgis-2.18/debian/build-release-2_18-qt4/doc/INSTALL.html -t html /home/fischer/src/qgis-2.18/doc/INSTALL.t2t -->
 </BODY></HTML>
diff --git a/doc/linux.t2t b/doc/linux.t2t
index 614a18f..ea5c3a7 100644
--- a/doc/linux.t2t
+++ b/doc/linux.t2t
@@ -44,14 +44,13 @@ sudo apt-get update
 == Install build dependencies ==
 
 || Distribution | install command for packages |
-| wheezy | ``apt-get install bison cmake doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal1-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools python python-dev python-gdal pyth [...]
-| jessie | ``apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all [...]
-| stretch | ``apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all python-all-dev  [...]
-| precise | ``apt-get install bison cmake doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools python python-gdal python-mock python-psyc [...]
-| trusty | ``apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools python-all python-al [...]
-| wily | ``apt-get install bison cmake cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev p [...]
-| xenial | ``apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all python-all- [...]
-| sid | ``apt-get install bison cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsci-dev python-all python-all-dev [...]
+| jessie | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsc [...]
+| stretch | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qsc [...]
+| trusty | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyth [...]
+| xenial | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4 [...]
+| yakkety | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt [...]
+| zesty | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4. [...]
+| sid | ``apt-get install bison ca-certificates cmake dh-python doxygen flex gdal-bin git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqca2-dev libqca2-plugin-ossl libqjson-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqt4-sql-sqlite libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd locales pkg-config poppler-utils pyqt4-dev-tools pyqt4.qs [...]
 
 (extracted from the control.in file in ``debian/``)
 
diff --git a/doc/msys.t2t b/doc/msys.t2t
index eb1bd12..73e72a9 100644
--- a/doc/msys.t2t
+++ b/doc/msys.t2t
@@ -108,7 +108,7 @@ make install
 ==== Final python notes ====
 
 /!\ You can delete the directories with unpacked SIP and PyQt4 sources after a
-successfull install, they're not needed anymore.
+successful install, they're not needed anymore.
 
 === git ===
 
diff --git a/python/core/raster/qgsrasterinterface.sip b/python/core/raster/qgsrasterinterface.sip
index efec4b1..ed3357c 100644
--- a/python/core/raster/qgsrasterinterface.sip
+++ b/python/core/raster/qgsrasterinterface.sip
@@ -55,6 +55,7 @@ class QgsRasterInterface
 #include <qgsrasterresamplefilter.h>
 
 // QgsRasterRenderer subclasses
+#include <qgshillshaderenderer.h>
 #include <qgsmultibandcolorrenderer.h>
 #include <qgspalettedrasterrenderer.h>
 #include <qgssinglebandcolordatarenderer.h>
@@ -80,7 +81,9 @@ class QgsRasterInterface
     sipType = sipType_QgsRasterProjector;
   else if (dynamic_cast<QgsRasterRenderer*>(sipCpp))
   {
-    if (     dynamic_cast<QgsMultiBandColorRenderer*>(sipCpp))
+    if ( dynamic_cast<QgsHillshadeRenderer*>(sipCpp))
+      sipType = sipType_QgsHillshadeRenderer;
+    else if ( dynamic_cast<QgsMultiBandColorRenderer*>(sipCpp))
       sipType = sipType_QgsMultiBandColorRenderer;
     else if (dynamic_cast<QgsPalettedRasterRenderer*>(sipCpp))
       sipType = sipType_QgsPalettedRasterRenderer;
diff --git a/python/plugins/MetaSearch/resources/connections-default.xml b/python/plugins/MetaSearch/resources/connections-default.xml
index 49a8dbf..7068fc3 100644
--- a/python/plugins/MetaSearch/resources/connections-default.xml
+++ b/python/plugins/MetaSearch/resources/connections-default.xml
@@ -9,7 +9,7 @@
     <csw name="Italy: National CSW (Geoportale Nazionale - Servizio di ricerca Italiano)" url="http://www.pcn.minambiente.it/geoportal/csw"/>
     <csw name="Italy: RNDT - Repertorio Nazionale dei Dati Territoriali - Servizio di ricerca" url="http://www.rndt.gov.it/RNDT/CSW"/>
     <csw name="New Zealand: LINZ Data Service" url="http://data.linz.govt.nz/feeds/csw"/>
-    <csw name="Netherlands: National CSW (Nationaal Georegister)" url="http://www.nationaalgeoregister.nl/geonetwork/srv/eng/csw"/>
+    <csw name="Netherlands: National CSW (Nationaal Georegister)" url="http://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw"/>
     <csw name="Norway: National CSW (Geonorge)" url="http://www.geonorge.no/geonetwork/srv/no/csw"/>
     <csw name="Sweden: National CSW" url="http://www.geodata.se/InspireCswProxy/csw"/>
     <csw name="UK Location Catalogue Publishing Service" url="http://csw.data.gov.uk/geonetwork/srv/en/csw"/>
diff --git a/python/plugins/processing/algs/grass7/Grass7Utils.py b/python/plugins/processing/algs/grass7/Grass7Utils.py
index 399ed8e..d318c9f 100644
--- a/python/plugins/processing/algs/grass7/Grass7Utils.py
+++ b/python/plugins/processing/algs/grass7/Grass7Utils.py
@@ -55,6 +55,9 @@ class Grass7Utils:
 
     isGrass7Installed = False
 
+    version = None
+    command = None
+
     @staticmethod
     def grassBatchJobFilename():
         '''This is used in Linux. This is the batch job that we assign to
@@ -74,10 +77,33 @@ class Grass7Utils:
         return filename
 
     @staticmethod
-    def getGrassVersion():
-        # FIXME: I do not know if this should be removed or let the user enter it
-        # or something like that... This is just a temporary thing
-        return '7.0.0'
+    def installedVersion(run=False):
+        if Grass7Utils.isGrass7Installed and not run:
+            return Grass7Utils.version
+
+        if Grass7Utils.grassPath() is None:
+            return None
+
+        for command in ["grass73", "grass72", "grass71", "grass70", "grass"]:
+            proc = subprocess.Popen(
+                ["{} -v".format(command)],
+                shell=True,
+                stdout=subprocess.PIPE,
+                stdin=open(os.devnull),
+                stderr=subprocess.STDOUT,
+                universal_newlines=True,
+            )
+            if proc:
+                lines = proc.stdout.readlines()
+                for line in lines:
+                    if "GRASS GIS " in line:
+                        line = line.split(" ")[-1].strip()
+                        if line.startswith("7."):
+                            Grass7Utils.version = line
+                            Grass7Utils.command = command
+                            return Grass7Utils.version
+
+        return Grass7Utils.version
 
     @staticmethod
     def grassPath():
@@ -98,6 +124,16 @@ class Grass7Utils:
                     for subfolder in os.listdir(testfolder):
                         if subfolder.startswith('grass-7'):
                             folder = os.path.join(testfolder, subfolder)
+                            fn = os.path.join(folder, "etc", "VERSIONNUMBER")
+                            if not os.path.isfile(fn):
+                                continue
+
+                            f = open(fn, "r")
+                            Grass7Utils.version = f.read().split(' ')[0]
+                            f.close()
+
+                            major, minor, patch = Grass7Utils.version.split('.')
+                            Grass7Utils.command = "grass{}{}".format(major, minor)
                             break
             else:
                 folder = os.path.join(unicode(QgsApplication.prefixPath()), 'grass7')
@@ -140,7 +176,7 @@ class Grass7Utils:
             output.write('if "%GRASS_ADDON_PATH%"=="" set PATH=%WINGISBASE%\\bin;%WINGISBASE%\\lib;%PATH%\n')
             output.write('if not "%GRASS_ADDON_PATH%"=="" set PATH=%WINGISBASE%\\bin;%WINGISBASE%\\lib;%GRASS_ADDON_PATH%;%PATH%\n')
             output.write('\n')
-            output.write('set GRASS_VERSION=' + Grass7Utils.getGrassVersion() + '\n')
+            output.write('set GRASS_VERSION=' + Grass7Utils.installedVersion() + '\n')
             output.write('if not "%LANG%"=="" goto langset\n')
             output.write('FOR /F "usebackq delims==" %%i IN (`"%WINGISBASE%\\etc\\winlocale"`) DO @set LANG=%%i\n')
             output.write(':langset\n')
@@ -248,8 +284,9 @@ class Grass7Utils:
                 command = Grass7Utils.grassPath() + os.sep + 'grass.sh ' \
                     + Grass7Utils.grassMapsetFolder() + '/PERMANENT'
             else:
-                command = 'grass70 ' + Grass7Utils.grassMapsetFolder() \
-                    + '/PERMANENT'
+                if Grass7Utils.command is None:
+                    Grass7Utils.installedVersion()
+                command = Grass7Utils.command + ' ' + os.path.join(Grass7Utils.grassMapsetFolder(), 'PERMANENT')
 
         return command, env
 
@@ -423,4 +460,4 @@ class Grass7Utils:
                         helpPath = os.path.abspath(path)
                         break
 
-        return helpPath if helpPath is not None else 'http://grass.osgeo.org/grass70/manuals/'
+        return helpPath if helpPath is not None else 'http://grass.osgeo.org/{}/manuals/'.format(Grass7Utils.command)
diff --git a/python/plugins/processing/algs/qgis/FieldsMapper.py b/python/plugins/processing/algs/qgis/FieldsMapper.py
index d8c9679..dfb7d39 100644
--- a/python/plugins/processing/algs/qgis/FieldsMapper.py
+++ b/python/plugins/processing/algs/qgis/FieldsMapper.py
@@ -117,32 +117,35 @@ class FieldsMapper(GeoAlgorithm):
         inFeat = QgsFeature()
         outFeat = QgsFeature()
         features = vector.features(layer)
-        total = 100.0 / len(features)
-        for current, inFeat in enumerate(features):
-            rownum = current + 1
-
-            geometry = inFeat.geometry()
-            if geometry is not None:
-                outFeat.setGeometry(geometry)
-
-            attrs = []
-            for i in xrange(0, len(mapping)):
-                field_def = mapping[i]
-                expression = expressions[i]
-                exp_context.setFeature(inFeat)
-                exp_context.lastScope().setVariable("row_number", rownum)
-                value = expression.evaluate(exp_context)
-                if expression.hasEvalError():
-                    calculationSuccess = False
-                    error = expression.evalErrorString()
-                    break
-
-                attrs.append(value)
-            outFeat.setAttributes(attrs)
-
-            writer.addFeature(outFeat)
-
-            progress.setPercentage(int(current * total))
+        if len(features):
+            total = 100.0 / len(features)
+            for current, inFeat in enumerate(features):
+                rownum = current + 1
+
+                geometry = inFeat.geometry()
+                if geometry is not None:
+                    outFeat.setGeometry(geometry)
+
+                attrs = []
+                for i in xrange(0, len(mapping)):
+                    field_def = mapping[i]
+                    expression = expressions[i]
+                    exp_context.setFeature(inFeat)
+                    exp_context.lastScope().setVariable("row_number", rownum)
+                    value = expression.evaluate(exp_context)
+                    if expression.hasEvalError():
+                        calculationSuccess = False
+                        error = expression.evalErrorString()
+                        break
+
+                    attrs.append(value)
+                outFeat.setAttributes(attrs)
+
+                writer.addFeature(outFeat)
+
+                progress.setPercentage(int(current * total))
+        else:
+            progress.setPercentage(100)
 
         del writer
 
diff --git a/python/plugins/processing/algs/saga/SagaAlgorithmProvider.py b/python/plugins/processing/algs/saga/SagaAlgorithmProvider.py
index 2f7ff56..62ecc71 100644
--- a/python/plugins/processing/algs/saga/SagaAlgorithmProvider.py
+++ b/python/plugins/processing/algs/saga/SagaAlgorithmProvider.py
@@ -53,7 +53,7 @@ class SagaAlgorithmProvider(AlgorithmProvider):
                          "2.2.2": ("2.2.2", SagaAlgorithm214),
                          "2.2.3": ("2.2.3", SagaAlgorithm214),
                          "2.3.0": ("2.3.0", SagaAlgorithm230),
-                         "2.3.1": ("2.3.1", SagaAlgorithm230)}
+                         "2.3.1": ("2.3.0", SagaAlgorithm230)}
 
     def __init__(self):
         AlgorithmProvider.__init__(self)
diff --git a/python/plugins/processing/algs/saga/SagaUtils.py b/python/plugins/processing/algs/saga/SagaUtils.py
index ee13c78..835e18e 100644
--- a/python/plugins/processing/algs/saga/SagaUtils.py
+++ b/python/plugins/processing/algs/saga/SagaUtils.py
@@ -64,9 +64,17 @@ def findSagaFolder():
             if os.path.exists(os.path.join(testfolder, 'saga_cmd')):
                 folder = testfolder
     elif isWindows():
-        testfolder = os.path.join(os.path.dirname(QgsApplication.prefixPath()), 'saga')
-        if os.path.exists(os.path.join(testfolder, 'saga_cmd.exe')):
-            folder = testfolder
+        folders = []
+        folders.append(os.path.join(os.path.dirname(QgsApplication.prefixPath()), 'saga'))
+        if "OSGEO4W_ROOT" in os.environ:
+            folders.append(os.path.join(str(os.environ['OSGEO4W_ROOT']), "apps", "saga-ltr"))
+            folders.append(os.path.join(str(os.environ['OSGEO4W_ROOT']), "apps", "saga"))
+
+        for testfolder in folders:
+            if os.path.exists(os.path.join(testfolder, 'saga_cmd.exe')):
+                folder = testfolder
+                break
+
     return folder
 
 
@@ -91,12 +99,12 @@ def createSagaBatchJobFileFromSagaCommands(commands):
     fout = open(sagaBatchJobFilename(), 'w')
     if isWindows():
         fout.write('set SAGA=' + sagaPath() + '\n')
-        fout.write('set SAGA_MLB=' + sagaPath() + os.sep
-                   + 'modules' + '\n')
+        fout.write('set SAGA_MLB=' + sagaPath() + os.sep +
+                   'modules' + '\n')
         fout.write('PATH=%PATH%;%SAGA%;%SAGA_MLB%\n')
     elif isMac():
-        fout.write('export SAGA_MLB=' + sagaPath()
-                   + '/../lib/saga\n')
+        fout.write('export SAGA_MLB=' + sagaPath() +
+                   '/../lib/saga\n')
         fout.write('export PATH=' + sagaPath() + ':$PATH\n')
     else:
         pass
@@ -111,6 +119,7 @@ def createSagaBatchJobFileFromSagaCommands(commands):
     fout.write('exit')
     fout.close()
 
+
 _installedVersion = None
 _installedVersionFound = False
 
@@ -164,8 +173,8 @@ def executeSaga(progress):
     if isWindows():
         command = ['cmd.exe', '/C ', sagaBatchJobFilename()]
     else:
-        os.chmod(sagaBatchJobFilename(), stat.S_IEXEC
-                 | stat.S_IREAD | stat.S_IWRITE)
+        os.chmod(sagaBatchJobFilename(), stat.S_IEXEC |
+                 stat.S_IREAD | stat.S_IWRITE)
         command = [sagaBatchJobFilename()]
     loglines = []
     loglines.append(QCoreApplication.translate('SagaUtils', 'SAGA execution console output'))
diff --git a/python/plugins/processing/algs/taudem/TauDEMUtils.py b/python/plugins/processing/algs/taudem/TauDEMUtils.py
index 41567a2..3a0b6b4 100644
--- a/python/plugins/processing/algs/taudem/TauDEMUtils.py
+++ b/python/plugins/processing/algs/taudem/TauDEMUtils.py
@@ -102,7 +102,6 @@ class TauDEMUtils:
     def executeTauDEM(command, progress):
         loglines = []
         loglines.append(TauDEMUtils.tr('TauDEM execution console output'))
-        command = escapeAndJoin(command)
         fused_command = ''.join(['"%s" ' % c for c in command])
         progress.setInfo(TauDEMUtils.tr('TauDEM command:'))
         progress.setCommand(fused_command.replace('" "', ' ').strip('"'))
@@ -124,3 +123,15 @@ class TauDEMUtils:
         if context == '':
             context = 'TauDEMUtils'
         return QCoreApplication.translate(context, string)
+
+    @staticmethod
+    def escapeAndJoin(strList):
+        joined = ''
+        for s in strList:
+            if s[0] != '-' and ' ' in s:
+                escaped = '"' + s.replace('\\', '\\\\').replace('"', '\\"') \
+                    + '"'
+            else:
+                escaped = s
+            joined += escaped + ' '
+        return joined.strip()
diff --git a/python/plugins/processing/tools/spatialite.py b/python/plugins/processing/tools/spatialite.py
index 6742d0f..966226f 100644
--- a/python/plugins/processing/tools/spatialite.py
+++ b/python/plugins/processing/tools/spatialite.py
@@ -67,11 +67,10 @@ class GeoDB:
         try:
             self._exec_sql(c, u'SELECT spatialite_version()')
             rep = c.fetchall()
-            v = [int(a) for a in rep[0][0].split('.')]
-            vv = v[0] * 100000 + v[1] * 1000 + v[2] * 10
+            v = [int(x) if x.isdigit() else x for x in re.findall("\d+|[a-zA-Z]+", rep[0][0])]
 
             # Add spatialite support
-            if vv >= 401000:
+            if v >= [4, 1, 0]:
                 # 4.1 and above
                 sql = "SELECT initspatialmetadata(1)"
             else:
diff --git a/src/app/composer/qgscomposermapwidget.cpp b/src/app/composer/qgscomposermapwidget.cpp
index 90dddd7..0a19e91 100644
--- a/src/app/composer/qgscomposermapwidget.cpp
+++ b/src/app/composer/qgscomposermapwidget.cpp
@@ -197,6 +197,9 @@ QgsComposerMapWidget::QgsComposerMapWidget( QgsComposerMap* composerMap )
   updateGuiElements();
   loadGridEntries();
   loadOverviewEntries();
+
+  connect( mMapRotationSpinBox, SIGNAL( editingFinished() ), this, SLOT( rotationChanged() ) );
+
   blockAllSignals( false );
 }
 
@@ -578,7 +581,7 @@ void QgsComposerMapWidget::on_mScaleLineEdit_editingFinished()
   mComposerMap->endCommand();
 }
 
-void QgsComposerMapWidget::on_mMapRotationSpinBox_valueChanged( double value )
+void QgsComposerMapWidget::rotationChanged()
 {
   if ( !mComposerMap )
   {
@@ -586,7 +589,7 @@ void QgsComposerMapWidget::on_mMapRotationSpinBox_valueChanged( double value )
   }
 
   mComposerMap->beginCommand( tr( "Map rotation changed" ), QgsComposerMergeCommand::ComposerMapRotation );
-  mComposerMap->setMapRotation( value );
+  mComposerMap->setMapRotation( mMapRotationSpinBox->value() );
   mComposerMap->endCommand();
   mComposerMap->cache();
   mComposerMap->update();
diff --git a/src/app/composer/qgscomposermapwidget.h b/src/app/composer/qgscomposermapwidget.h
index 59c1136..19e4b5d 100644
--- a/src/app/composer/qgscomposermapwidget.h
+++ b/src/app/composer/qgscomposermapwidget.h
@@ -39,7 +39,6 @@ class QgsComposerMapWidget: public QgsComposerItemBaseWidget, private Ui::QgsCom
   public slots:
     void on_mPreviewModeComboBox_activated( int i );
     void on_mScaleLineEdit_editingFinished();
-    void on_mMapRotationSpinBox_valueChanged( double value );
     void on_mSetToMapCanvasExtentButton_clicked();
     void on_mViewExtentInCanvasButton_clicked();
     void on_mUpdatePreviewButton_clicked();
@@ -160,6 +159,8 @@ class QgsComposerMapWidget: public QgsComposerItemBaseWidget, private Ui::QgsCom
 
   private slots:
 
+    void rotationChanged();
+
     /** Sets the GUI elements to the values of mPicture*/
     void setGuiElementValues();
 
diff --git a/src/app/pluginmanager/qgspluginmanager.cpp b/src/app/pluginmanager/qgspluginmanager.cpp
index ef4efec..1a610b0 100644
--- a/src/app/pluginmanager/qgspluginmanager.cpp
+++ b/src/app/pluginmanager/qgspluginmanager.cpp
@@ -1531,7 +1531,7 @@ void QgsPluginManager::updateWindowTitle()
   if ( curitem )
   {
     QString title = QString( "%1 | %2" ).arg( tr( "Plugins" ), curitem->text() );
-    if ( mOptionsListWidget->currentRow() < mOptionsListWidget->count() - 1 )
+    if ( mOptionsListWidget->currentRow() < mOptionsListWidget->count() - 1 && mModelPlugins )
     {
       // if it's not the Settings tab, add the plugin count
       title += QString( " (%3)" ).arg( mModelProxy->countWithCurrentStatus() );
diff --git a/src/app/qgsfeatureaction.cpp b/src/app/qgsfeatureaction.cpp
index 9a35e80..2bad841 100644
--- a/src/app/qgsfeatureaction.cpp
+++ b/src/app/qgsfeatureaction.cpp
@@ -63,6 +63,7 @@ QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature )
 
   QgsAttributeDialog *dialog = new QgsAttributeDialog( mLayer, f, cloneFeature, parentWidget(), true, context );
   dialog->setWindowFlags( dialog->windowFlags() | Qt::Tool );
+  dialog->setObjectName( QString( "featureactiondlg:%1:%2" ).arg( mLayer->id(), f->id() ) );
 
   if ( mLayer->actions()->size() > 0 )
   {
@@ -95,10 +96,19 @@ QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature )
 
 bool QgsFeatureAction::viewFeatureForm( QgsHighlight *h )
 {
-  if ( !mLayer )
+  if ( !mLayer || !mFeature )
     return false;
 
-  QgsAttributeDialog *dialog = newDialog( true );
+  QString name( QString( "featureactiondlg:%1:%2" ).arg( mLayer->id(), mFeature->id() ) );
+
+  QgsAttributeDialog *dialog = QgisApp::instance()->findChild<QgsAttributeDialog *>( name );
+  if ( dialog )
+  {
+    dialog->raise();
+    return true;
+  }
+
+  dialog = newDialog( true );
   dialog->setHighlight( h );
   // delete the dialog when it is closed
   dialog->setAttribute( Qt::WA_DeleteOnClose );
@@ -125,7 +135,16 @@ bool QgsFeatureAction::editFeature( bool showModal )
   }
   else
   {
-    QgsAttributeDialog* dialog = newDialog( false );
+    QString name( QString( "featureactiondlg:%1:%2" ).arg( mLayer->id(), mFeature->id() ) );
+
+    QgsAttributeDialog *dialog = QgisApp::instance()->findChild<QgsAttributeDialog *>( name );
+    if ( dialog )
+    {
+      dialog->raise();
+      return true;
+    }
+
+    dialog = newDialog( false );
 
     if ( !mFeature->isValid() )
       dialog->setMode( QgsAttributeForm::AddFeatureMode );
@@ -151,7 +170,8 @@ bool QgsFeatureAction::addFeature( const QgsAttributeMap& defaultAttributes, boo
   QgsDebugMsg( QString( "reuseLastValues: %1" ).arg( reuseLastValues ) );
 
   QgsExpressionContext context;
-  context << QgsExpressionContextUtils::globalScope()
+  context
+  << QgsExpressionContextUtils::globalScope()
   << QgsExpressionContextUtils::projectScope()
   << QgsExpressionContextUtils::layerScope( mLayer );
 
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index cd8e305..ad99338 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -672,6 +672,8 @@ SET(QGIS_CORE_HDRS
   qgslegendsettings.h
   qgslogger.h
   qgsmaphittest.h
+  qgsmaplayerlistutils.h
+  qgsmaplayerref.h
   qgsmaplayerrenderer.h
   qgsmaplayerstylemanager.h
   qgsmapsettings.h
@@ -723,6 +725,7 @@ SET(QGIS_CORE_HDRS
 
   qgsvectordataprovider.h
   qgsvectorlayercache.h
+  qgsvectorlayerref.h
   qgsvectorfilewriter.h
   qgsvectorlayerdiagramprovider.h
   qgsvectorlayereditutils.h
diff --git a/src/core/composer/qgsatlascomposition.cpp b/src/core/composer/qgsatlascomposition.cpp
index 610c61f..3de23fb 100644
--- a/src/core/composer/qgsatlascomposition.cpp
+++ b/src/core/composer/qgsatlascomposition.cpp
@@ -35,7 +35,6 @@ QgsAtlasComposition::QgsAtlasComposition( QgsComposition* composition )
     , mEnabled( false )
     , mHideCoverage( false )
     , mFilenamePattern( "'output_'||@atlas_featurenumber" )
-    , mCoverageLayer( nullptr )
     , mSingleFile( false )
     , mSortFeatures( false )
     , mSortAscending( true )
@@ -73,10 +72,10 @@ void QgsAtlasComposition::removeLayers( const QStringList& layers )
 
   Q_FOREACH ( const QString& layerId, layers )
   {
-    if ( layerId == mCoverageLayer->id() )
+    if ( layerId == mCoverageLayer.layerId )
     {
       //current coverage layer removed
-      mCoverageLayer = nullptr;
+      mCoverageLayer.setLayer( nullptr );
       setEnabled( false );
       return;
     }
@@ -85,12 +84,12 @@ void QgsAtlasComposition::removeLayers( const QStringList& layers )
 
 void QgsAtlasComposition::setCoverageLayer( QgsVectorLayer* layer )
 {
-  if ( layer == mCoverageLayer )
+  if ( layer == mCoverageLayer.get() )
   {
     return;
   }
 
-  mCoverageLayer = layer;
+  mCoverageLayer.setLayer( layer );
   emit coverageLayerChanged( layer );
 }
 
@@ -644,7 +643,10 @@ void QgsAtlasComposition::writeXML( QDomElement& elem, QDomDocument& doc ) const
 
   if ( mCoverageLayer )
   {
-    atlasElem.setAttribute( "coverageLayer", mCoverageLayer->id() );
+    atlasElem.setAttribute( "coverageLayer", mCoverageLayer.layerId );
+    atlasElem.setAttribute( "coverageLayerName", mCoverageLayer.name );
+    atlasElem.setAttribute( "coverageLayerSource", mCoverageLayer.source );
+    atlasElem.setAttribute( "coverageLayerProvider", mCoverageLayer.provider );
   }
   else
   {
@@ -682,16 +684,13 @@ void QgsAtlasComposition::readXML( const QDomElement& atlasElem, const QDomDocum
   }
 
   // look for stored layer name
-  mCoverageLayer = nullptr;
-  QMap<QString, QgsMapLayer*> layers = QgsMapLayerRegistry::instance()->mapLayers();
-  for ( QMap<QString, QgsMapLayer*>::const_iterator it = layers.begin(); it != layers.end(); ++it )
-  {
-    if ( it.key() == atlasElem.attribute( "coverageLayer" ) )
-    {
-      mCoverageLayer = dynamic_cast<QgsVectorLayer*>( it.value() );
-      break;
-    }
-  }
+  QString layerId = atlasElem.attribute( "coverageLayer" );
+  QString layerName = atlasElem.attribute( "coverageLayerName" );
+  QString layerSource = atlasElem.attribute( "coverageLayerSource" );
+  QString layerProvider = atlasElem.attribute( "coverageLayerProvider" );
+
+  mCoverageLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
+  mCoverageLayer.resolveWeakly();
 
   mPageNameExpression = atlasElem.attribute( "pageNameExpression", QString() );
   mSingleFile = atlasElem.attribute( "singleFile", "false" ) == "true" ? true : false;
diff --git a/src/core/composer/qgsatlascomposition.h b/src/core/composer/qgsatlascomposition.h
index b051ce4..c962bfb 100644
--- a/src/core/composer/qgsatlascomposition.h
+++ b/src/core/composer/qgsatlascomposition.h
@@ -19,6 +19,7 @@
 #include "qgscoordinatetransform.h"
 #include "qgsfeature.h"
 #include "qgsgeometry.h"
+#include "qgsvectorlayerref.h"
 
 #include <memory>
 #include <QString>
@@ -101,7 +102,7 @@ class CORE_EXPORT QgsAtlasComposition : public QObject
      * @returns atlas coverage layer
      * @see setCoverageLayer
      */
-    QgsVectorLayer* coverageLayer() const { return mCoverageLayer; }
+    QgsVectorLayer* coverageLayer() const { return mCoverageLayer.get(); }
 
     /** Sets the coverage layer to use for the atlas features
      * @param layer vector coverage layer
@@ -355,7 +356,7 @@ class CORE_EXPORT QgsAtlasComposition : public QObject
     bool mEnabled;
     bool mHideCoverage;
     QString mFilenamePattern;
-    QgsVectorLayer* mCoverageLayer;
+    QgsVectorLayerRef mCoverageLayer;
     bool mSingleFile;
 
     QString mCurrentFilename;
diff --git a/src/core/composer/qgscomposerattributetablev2.cpp b/src/core/composer/qgscomposerattributetablev2.cpp
index a0366f0..16cec85 100644
--- a/src/core/composer/qgscomposerattributetablev2.cpp
+++ b/src/core/composer/qgscomposerattributetablev2.cpp
@@ -49,7 +49,6 @@ bool QgsComposerAttributeTableCompareV2::operator()( const QgsComposerTableRow&
 QgsComposerAttributeTableV2::QgsComposerAttributeTableV2( QgsComposition* composition, bool createUndoCommands )
     : QgsComposerTableV2( composition, createUndoCommands )
     , mSource( LayerAttributes )
-    , mVectorLayer( nullptr )
     , mCurrentAtlasLayer( nullptr )
     , mComposerMap( nullptr )
     , mMaximumNumberOfFeatures( 30 )
@@ -67,7 +66,7 @@ QgsComposerAttributeTableV2::QgsComposerAttributeTableV2( QgsComposition* compos
     QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( mapIt.value() );
     if ( vl )
     {
-      mVectorLayer = vl;
+      mVectorLayer.setLayer( vl );
       break;
     }
   }
@@ -75,7 +74,7 @@ QgsComposerAttributeTableV2::QgsComposerAttributeTableV2( QgsComposition* compos
   {
     resetColumns();
     //listen for modifications to layer and refresh table when they occur
-    connect( mVectorLayer, SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) );
+    connect( mVectorLayer.get(), SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) );
   }
   connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( removeLayer( const QString& ) ) );
 
@@ -104,14 +103,14 @@ QString QgsComposerAttributeTableV2::displayName() const
 
 void QgsComposerAttributeTableV2::setVectorLayer( QgsVectorLayer* layer )
 {
-  if ( layer == mVectorLayer )
+  if ( layer == mVectorLayer.get() )
   {
     //no change
     return;
   }
 
   QgsVectorLayer* prevLayer = sourceLayer();
-  mVectorLayer = layer;
+  mVectorLayer.setLayer( layer );
 
   if ( mSource == QgsComposerAttributeTableV2::LayerAttributes && layer != prevLayer )
   {
@@ -125,7 +124,7 @@ void QgsComposerAttributeTableV2::setVectorLayer( QgsVectorLayer* layer )
     resetColumns();
 
     //listen for modifications to layer and refresh table when they occur
-    connect( mVectorLayer, SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) );
+    connect( mVectorLayer.get(), SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) );
   }
 
   refreshAttributes();
@@ -591,7 +590,7 @@ QgsExpressionContext *QgsComposerAttributeTableV2::createExpressionContext() con
 
   if ( mSource == LayerAttributes )
   {
-    context->appendScope( QgsExpressionContextUtils::layerScope( mVectorLayer ) );
+    context->appendScope( QgsExpressionContextUtils::layerScope( mVectorLayer.get() ) );
   }
 
   return context;
@@ -615,7 +614,7 @@ QgsVectorLayer *QgsComposerAttributeTableV2::sourceLayer()
     case QgsComposerAttributeTableV2::AtlasFeature:
       return mComposition->atlasComposition().coverageLayer();
     case QgsComposerAttributeTableV2::LayerAttributes:
-      return mVectorLayer;
+      return mVectorLayer.get();
     case QgsComposerAttributeTableV2::RelationChildren:
     {
       QgsRelation relation = QgsProject::instance()->relationManager()->relation( mRelationId );
@@ -631,7 +630,7 @@ void QgsComposerAttributeTableV2::removeLayer( const QString& layerId )
   {
     if ( layerId == mVectorLayer->id() )
     {
-      mVectorLayer = nullptr;
+      mVectorLayer.setLayer( nullptr );
       //remove existing columns
       qDeleteAll( mColumns );
       mColumns.clear();
@@ -709,7 +708,10 @@ bool QgsComposerAttributeTableV2::writeXML( QDomElement& elem, QDomDocument & do
   }
   if ( mVectorLayer )
   {
-    composerTableElem.setAttribute( "vectorLayer", mVectorLayer->id() );
+    composerTableElem.setAttribute( "vectorLayer", mVectorLayer.layerId );
+    composerTableElem.setAttribute( "vectorLayerName", mVectorLayer.name );
+    composerTableElem.setAttribute( "vectorLayerSource", mVectorLayer.source );
+    composerTableElem.setAttribute( "vectorLayerProvider", mVectorLayer.provider );
   }
 
   bool ok = QgsComposerTableV2::writeXML( composerTableElem, doc, ignoreFrames );
@@ -778,19 +780,12 @@ bool QgsComposerAttributeTableV2::readXML( const QDomElement& itemElem, const QD
   }
 
   //vector layer
-  QString layerId = itemElem.attribute( "vectorLayer", "not_existing" );
-  if ( layerId == "not_existing" )
-  {
-    mVectorLayer = nullptr;
-  }
-  else
-  {
-    QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerId );
-    if ( ml )
-    {
-      mVectorLayer = dynamic_cast<QgsVectorLayer*>( ml );
-    }
-  }
+  QString layerId = itemElem.attribute( "vectorLayer" );
+  QString layerName = itemElem.attribute( "vectorLayerName" );
+  QString layerSource = itemElem.attribute( "vectorLayerSource" );
+  QString layerProvider = itemElem.attribute( "vectorLayerProvider" );
+  mVectorLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
+  mVectorLayer.resolveWeakly();
 
   //connect to new layer
   connect( sourceLayer(), SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) );
diff --git a/src/core/composer/qgscomposerattributetablev2.h b/src/core/composer/qgscomposerattributetablev2.h
index 809848e..8c5e0ed 100644
--- a/src/core/composer/qgscomposerattributetablev2.h
+++ b/src/core/composer/qgscomposerattributetablev2.h
@@ -20,6 +20,7 @@
 
 #include "qgscomposertablev2.h"
 #include "qgscomposerattributetable.h"
+#include "qgsvectorlayerref.h"
 
 class QgsComposerMap;
 class QgsVectorLayer;
@@ -120,7 +121,7 @@ class CORE_EXPORT QgsComposerAttributeTableV2: public QgsComposerTableV2
      * @returns attribute table's current vector layer
      * @see setVectorLayer
      */
-    QgsVectorLayer* vectorLayer() const { return mVectorLayer; }
+    QgsVectorLayer* vectorLayer() const { return mVectorLayer.get(); }
 
     /** Sets the relation id from which to display child features
      * @param relationId id for relation to display child features from
@@ -314,7 +315,7 @@ class CORE_EXPORT QgsComposerAttributeTableV2: public QgsComposerTableV2
     /** Attribute source*/
     ContentSource mSource;
     /** Associated vector layer*/
-    QgsVectorLayer* mVectorLayer;
+    QgsVectorLayerRef mVectorLayer;
     /** Relation id, if in relation children mode*/
     QString mRelationId;
 
diff --git a/src/core/composer/qgscomposermap.cpp b/src/core/composer/qgscomposermap.cpp
index b7b9968..b9d25d5 100644
--- a/src/core/composer/qgscomposermap.cpp
+++ b/src/core/composer/qgscomposermap.cpp
@@ -35,6 +35,7 @@
 #include "qgsexpression.h"
 #include "qgsvisibilitypresetcollection.h"
 #include "qgsannotation.h"
+#include "qgsvectorlayerref.h"
 
 #include "qgslabel.h"
 #include "qgslabelattributes.h"
@@ -1323,12 +1324,21 @@ bool QgsComposerMap::writeXML( QDomElement& elem, QDomDocument & doc ) const
 
   //layer set
   QDomElement layerSetElem = doc.createElement( "LayerSet" );
-  QStringList::const_iterator layerIt = mLayerSet.constBegin();
-  for ( ; layerIt != mLayerSet.constEnd(); ++layerIt )
+  Q_FOREACH ( const QString &layerId, mLayerSet )
   {
+    QgsVectorLayerRef layerRef( layerId );
+    layerRef.resolve();
+
+    if ( !layerRef )
+      continue;
+
     QDomElement layerElem = doc.createElement( "Layer" );
-    QDomText layerIdText = doc.createTextNode( *layerIt );
+    QDomText layerIdText = doc.createTextNode( layerRef.layerId );
     layerElem.appendChild( layerIdText );
+    layerElem.setAttribute( "name", layerRef.name );
+    layerElem.setAttribute( "source", layerRef.source );
+    layerElem.setAttribute( "provider", layerRef.provider );
+
     layerSetElem.appendChild( layerElem );
   }
   composerMapElem.appendChild( layerSetElem );
@@ -1341,7 +1351,15 @@ bool QgsComposerMap::writeXML( QDomElement& elem, QDomDocument & doc ) const
     for ( ; styleIt != mLayerStyleOverrides.constEnd(); ++styleIt )
     {
       QDomElement styleElem = doc.createElement( "LayerStyle" );
-      styleElem.setAttribute( "layerid", styleIt.key() );
+
+      QgsMapLayerRef ref( styleIt.key() );
+      ref.resolve();
+
+      styleElem.setAttribute( "layerid", ref.layerId );
+      styleElem.setAttribute( "name", ref.name );
+      styleElem.setAttribute( "source", ref.source );
+      styleElem.setAttribute( "provider", ref.provider );
+
       QgsMapLayerStyle style( styleIt.value() );
       style.writeXml( styleElem );
       stylesElem.appendChild( styleElem );
@@ -1456,8 +1474,15 @@ bool QgsComposerMap::readXML( const QDomElement& itemElem, const QDomDocument& d
     layerSet.reserve( layerIdNodeList.size() );
     for ( int i = 0; i < layerIdNodeList.size(); ++i )
     {
-      const QDomElement& layerIdElement = layerIdNodeList.at( i ).toElement();
-      layerSet << layerIdElement.text();
+      QDomElement layerElem = layerIdNodeList.at( i ).toElement();
+      QString layerId = layerElem.text();
+      QString layerName = layerElem.attribute( "name" );
+      QString layerSource = layerElem.attribute( "source" );
+      QString layerProvider = layerElem.attribute( "provider" );
+
+      QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
+      ref.resolveWeakly();
+      layerSet << ref.layerId;
     }
   }
   mLayerSet = layerSet;
@@ -1473,9 +1498,15 @@ bool QgsComposerMap::readXML( const QDomElement& itemElem, const QDomDocument& d
     {
       const QDomElement& layerStyleElement = layerStyleNodeList.at( i ).toElement();
       QString layerId = layerStyleElement.attribute( "layerid" );
+      QString layerName = layerStyleElement.attribute( "name" );
+      QString layerSource = layerStyleElement.attribute( "source" );
+      QString layerProvider = layerStyleElement.attribute( "provider" );
+      QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
+      ref.resolveWeakly();
+
       QgsMapLayerStyle style;
       style.readXml( layerStyleElement );
-      mLayerStyleOverrides.insert( layerId, style.xmlData() );
+      mLayerStyleOverrides.insert( ref.layerId, style.xmlData() );
     }
   }
 
diff --git a/src/core/qgsmaplayerlistutils.h b/src/core/qgsmaplayerlistutils.h
new file mode 100644
index 0000000..86bbe18
--- /dev/null
+++ b/src/core/qgsmaplayerlistutils.h
@@ -0,0 +1,57 @@
+#ifndef QGSMAPLAYERLISTUTILS_H
+#define QGSMAPLAYERLISTUTILS_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the QGIS API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+
+#include <QPointer>
+
+#include "qgsmaplayer.h"
+#include "qgsmaplayerref.h"
+
+/// @cond PRIVATE
+
+inline QList<QgsMapLayer *> _qgis_listRefToRaw( const QList< QgsMapLayerRef > &layers )
+{
+  QList<QgsMapLayer *> lst;
+  lst.reserve( layers.count() );
+  Q_FOREACH ( const QgsMapLayerRef &layer, layers )
+  {
+    if ( layer )
+      lst.append( layer.get() );
+  }
+  return lst;
+}
+
+inline QList< QgsMapLayerRef > _qgis_listRawToRef( const QList<QgsMapLayer *> &layers )
+{
+  QList< QgsMapLayerRef > lst;
+  lst.reserve( layers.count() );
+  Q_FOREACH ( QgsMapLayer *layer, layers )
+  {
+    lst.append( QgsMapLayerRef( layer ) );
+  }
+  return lst;
+}
+
+inline void _qgis_removeLayers( QList< QgsMapLayerRef > &list, QList< QgsMapLayer *> layersToRemove )
+{
+  QMutableListIterator<QgsMapLayerRef> it( list );
+  while ( it.hasNext() )
+  {
+    QgsMapLayerRef &ref = it.next();
+    if ( layersToRemove.contains( ref.get() ) )
+      it.remove();
+  }
+}
+
+
+///@endcond
+
+#endif // QGSMAPLAYERLISTUTILS_H
diff --git a/src/core/qgsmaplayerref.h b/src/core/qgsmaplayerref.h
new file mode 100644
index 0000000..b6a4b59
--- /dev/null
+++ b/src/core/qgsmaplayerref.h
@@ -0,0 +1,220 @@
+/***************************************************************************
+  qgsmaplayerref.h
+  --------------------------------------
+  Date                 : January 2017
+  Copyright            : (C) 2017 by Martin Dobias
+  Email                : wonder dot sk at gmail dot com
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef QGSMAPLAYERREF_H
+#define QGSMAPLAYERREF_H
+
+#include <QPointer>
+
+#include "qgsmaplayer.h"
+#include "qgsdataprovider.h"
+#include "qgsmaplayerregistry.h"
+#include "qgsvectorlayer.h"
+#include "qgsvectordataprovider.h"
+#include "qgsrasterlayer.h"
+#include "qgsrasterdataprovider.h"
+
+/** Internal structure to keep weak pointer to QgsMapLayer or layerId
+ *  if the layer is not available yet.
+ *  \note not available in Python bindings
+ */
+template<typename TYPE>
+struct _LayerRef
+{
+
+  /**
+   * Constructor for a layer reference from an existing map layer.
+   * The layerId, source, name and provider members will automatically
+   * be populated from this layer.
+   */
+  _LayerRef( TYPE *l = nullptr )
+      : layer( l )
+      , layerId( l ? l->id() : QString() )
+      , source( l ? l->publicSource() : QString() )
+      , name( l ? l->name() : QString() )
+      , provider( layerProviderName( l ) )
+  {}
+
+  /**
+   * Constructor for a weak layer reference, using a combination of layer ID,
+   * \a name, public \a source and \a provider key.
+   */
+  _LayerRef( const QString &id, const QString &name = QString(), const QString &source = QString(), const QString &provider = QString() )
+      : layer()
+      , layerId( id )
+      , source( source )
+      , name( name )
+      , provider( provider )
+  {}
+
+  /**
+   * Sets the reference to point to a specified layer.
+   */
+  void setLayer( TYPE *l )
+  {
+    layer = l;
+    layerId = l ? l->id() : QString();
+    source = l ? l->publicSource() : QString();
+    name = l ? l->name() : QString();
+    provider = layerProviderName( l );
+  }
+
+  /**
+   * Returns true if the layer reference is resolved and contains a reference to an existing
+   * map layer.
+   */
+  operator bool() const
+  {
+    return static_cast< bool >( layer.data() );
+  }
+
+  /**
+   * Forwards the to map layer.
+   */
+  TYPE *operator->() const
+  {
+    return layer.data();
+  }
+
+  /**
+   * Returns a pointer to the layer, or nullptr if the reference has not yet been matched
+   * to a layer.
+   */
+  TYPE *get() const
+  {
+    return layer.data();
+  }
+
+  //! Weak pointer to map layer
+  QPointer<TYPE> layer;
+
+  //! Original layer ID
+  QString layerId;
+
+  //! Weak reference to layer public source
+  QString source;
+  //! Weak reference to layer name
+  QString name;
+  //! Weak reference to layer provider
+  QString provider;
+
+  /**
+   * Returns true if a layer matches the weak references to layer public source,
+   * layer name and data provider contained in this layer reference.
+   * \see resolveWeakly()
+   */
+  bool layerMatchesSource( QgsMapLayer *layer ) const
+  {
+    if ( layer->publicSource() != source ||
+         layer->name() != name )
+      return false;
+
+    if ( layerProviderName( layer ) != provider )
+      return false;
+
+    return true;
+  }
+
+  /**
+   * Resolves the map layer by attempting to find a layer with matching ID
+   * within the map layer registry. If found, this reference will be updated to match
+   * the found layer and the layer will be returned. If no matching layer is
+   * found, a nullptr is returned.
+   * \see resolveWeakly()
+   */
+  TYPE *resolve()
+  {
+    if ( !layerId.isEmpty() )
+    {
+      if ( TYPE *l = qobject_cast<TYPE *>( QgsMapLayerRegistry::instance()->mapLayer( layerId ) ) )
+      {
+        setLayer( l );
+        return l;
+      }
+    }
+    return nullptr;
+  }
+
+  /**
+   * Resolves the map layer by attempting to find a matching layer
+   * in the map layer registry using a weak match.
+   *
+   * First, the layer is attempted to match to registry layers using the
+   * layer's ID (calling this method implicitly calls resolve()).
+   *
+   * Failing a match by layer ID, the layer will be matched by using
+   * the weak references to layer public source, layer name and data
+   * provider contained in this layer reference.
+   *
+   * If a matching layer is found, this reference will be updated to match
+   * the found layer and the layer will be returned. If no matching layer is
+   * found, a nullptr is returned.
+   * \see resolve()
+   * \see layerMatchesSource()
+   */
+  TYPE *resolveWeakly()
+  {
+    // first try matching by layer ID
+    if ( resolve() )
+      return layer;
+
+    if ( !name.isEmpty() )
+    {
+      Q_FOREACH ( QgsMapLayer *l, QgsMapLayerRegistry::instance()->mapLayersByName( name ) )
+      {
+        if ( TYPE *tl = qobject_cast< TYPE *>( l ) )
+        {
+          if ( layerMatchesSource( tl ) )
+          {
+            setLayer( tl );
+            return tl;
+          }
+        }
+      }
+    }
+    return nullptr;
+  }
+
+private:
+
+  static QString layerProviderName( const QgsMapLayer *layer )
+  {
+    if ( !layer )
+      return QString();
+
+    switch ( layer->type() )
+    {
+      case QgsMapLayer::VectorLayer:
+      {
+        const QgsVectorLayer *vl = qobject_cast< const QgsVectorLayer *>( layer );
+        return vl->dataProvider()->name();
+      }
+
+      case QgsMapLayer::RasterLayer:
+      {
+        const QgsRasterLayer *rl = qobject_cast< const QgsRasterLayer *>( layer );
+        return rl->dataProvider()->name();
+      }
+      case QgsMapLayer::PluginLayer:
+        return QString();
+    }
+    return QString();
+
+  }
+};
+
+typedef _LayerRef<QgsMapLayer> QgsMapLayerRef;
+
+#endif // QGSMAPLAYERREF_H
diff --git a/src/core/qgsmaprendererparalleljob.cpp b/src/core/qgsmaprendererparalleljob.cpp
index 7c25233..99db48a 100644
--- a/src/core/qgsmaprendererparalleljob.cpp
+++ b/src/core/qgsmaprendererparalleljob.cpp
@@ -141,7 +141,7 @@ void QgsMapRendererParallelJob::cancelWithoutBlocking()
   if ( mStatus == RenderingLayers )
   {
     disconnect( &mFutureWatcher, SIGNAL( finished() ), this, SLOT( renderLayersFinished() ) );
-    connect( &mFutureWatcher, SIGNAL( finished() ), this, SLOT( renderingFinished() ) );
+    connect( &mFutureWatcher, SIGNAL( finished() ), this, SLOT( renderLayersFinishedWhenJobCanceled() ) );
   }
 }
 
@@ -306,3 +306,11 @@ void QgsMapRendererParallelJob::renderLabelsStatic( QgsMapRendererParallelJob* s
   painter.end();
 }
 
+void QgsMapRendererParallelJob::renderLayersFinishedWhenJobCanceled()
+{
+  logRenderingTime( mLayerJobs );
+
+  cleanupJobs( mLayerJobs );
+  renderingFinished();
+}
+
diff --git a/src/core/qgsmaprendererparalleljob.h b/src/core/qgsmaprendererparalleljob.h
index dc418ac..03c34ee 100644
--- a/src/core/qgsmaprendererparalleljob.h
+++ b/src/core/qgsmaprendererparalleljob.h
@@ -74,6 +74,10 @@ class CORE_EXPORT QgsMapRendererParallelJob : public QgsMapRendererQImageJob
     QgsRenderContext mLabelingRenderContext;
     QFuture<void> mLabelingFuture;
     QFutureWatcher<void> mLabelingFutureWatcher;
+
+  private slots:
+
+    void renderLayersFinishedWhenJobCanceled();
 };
 
 
diff --git a/src/core/qgsvectorfilewriter.cpp b/src/core/qgsvectorfilewriter.cpp
index 600c0be..d9a16af 100644
--- a/src/core/qgsvectorfilewriter.cpp
+++ b/src/core/qgsvectorfilewriter.cpp
@@ -28,6 +28,8 @@
 #include "qgssymbollayerv2.h"
 #include "qgsvectordataprovider.h"
 #include "qgslocalec.h"
+#include "qgscsexception.h"
+#include "qgsgeometryengine.h"
 
 #include <QFile>
 #include <QSettings>
@@ -2443,6 +2445,34 @@ QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
   req.setSubsetOfAttributes( attributes );
   if ( options.onlySelectedFeatures )
     req.setFilterFids( layer->selectedFeaturesIds() );
+
+  QScopedPointer< QgsGeometry > filterRectGeometry;
+  QScopedPointer< QgsGeometryEngine  > filterRectEngine;
+  if ( !options.filterExtent.isNull() )
+  {
+    QgsRectangle filterRect = options.filterExtent;
+    bool useFilterRect = true;
+    if ( shallTransform )
+    {
+      try
+      {
+        // map filter rect back from destination CRS to layer CRS
+        filterRect = options.ct->transformBoundingBox( filterRect, QgsCoordinateTransform::ReverseTransform );
+      }
+      catch ( QgsCsException & )
+      {
+        useFilterRect = false;
+      }
+    }
+    if ( useFilterRect )
+    {
+      req.setFilterRect( filterRect );
+    }
+    filterRectGeometry.reset( QgsGeometry::fromRect( options.filterExtent ) );
+    filterRectEngine.reset( QgsGeometry::createGeometryEngine( filterRectGeometry->geometry() ) );
+    filterRectEngine->prepareGeometry();
+  }
+
   QgsFeatureIterator fit = layer->getFeatures( req );
 
   //create symbol table if needed
@@ -2494,7 +2524,7 @@ QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
     {
       try
       {
-        if ( fet.geometry() )
+        if ( fet.constGeometry() )
         {
           fet.geometry()->transform( *( options.ct ) );
         }
@@ -2513,7 +2543,7 @@ QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
       }
     }
 
-    if ( fet.constGeometry() && !options.filterExtent.isNull() && !fet.constGeometry()->intersects( options.filterExtent ) )
+    if ( fet.constGeometry() && filterRectEngine && !filterRectEngine->intersects( *fet.constGeometry()->geometry() ) )
       continue;
 
     if ( attributes.size() < 1 && options.skipAttributeCreation )
diff --git a/src/core/qgsvectorlayerref.h b/src/core/qgsvectorlayerref.h
new file mode 100644
index 0000000..6b5eca1
--- /dev/null
+++ b/src/core/qgsvectorlayerref.h
@@ -0,0 +1,10 @@
+#ifndef QGSVECTORLAYERREF_H
+#define QGSVECTORLAYERREF_H
+
+#include "qgsmaplayerref.h"
+
+#include "qgsvectorlayer.h"
+
+typedef _LayerRef<QgsVectorLayer> QgsVectorLayerRef;
+
+#endif // QGSVECTORLAYERREF_H
diff --git a/src/providers/mssql/qgsmssqlprovider.cpp b/src/providers/mssql/qgsmssqlprovider.cpp
index 0b6c983..7989ffa 100644
--- a/src/providers/mssql/qgsmssqlprovider.cpp
+++ b/src/providers/mssql/qgsmssqlprovider.cpp
@@ -810,7 +810,10 @@ bool QgsMssqlProvider::addFeatures( QgsFeatureList & flist )
     {
       QgsField fld = mAttributeFields.at( i );
 
-      if ( fld.typeName().endsWith( " identity", Qt::CaseInsensitive ) )
+      if ( fld.typeName().toLower() == QLatin1String( "timestamp" ) )
+        continue; // You can't update timestamp columns they are server only.
+
+      if ( fld.typeName().endsWith( QLatin1String( " identity" ), Qt::CaseInsensitive ) )
         continue; // skip identity field
 
       if ( fld.name().isEmpty() )
@@ -881,7 +884,10 @@ bool QgsMssqlProvider::addFeatures( QgsFeatureList & flist )
     {
       QgsField fld = mAttributeFields.at( i );
 
-      if ( fld.typeName().endsWith( " identity", Qt::CaseInsensitive ) )
+      if ( fld.typeName().toLower() == QLatin1String( "timestamp" ) )
+        continue; // You can't update timestamp columns they are server only.
+
+      if ( fld.typeName().endsWith( QLatin1String( " identity" ), Qt::CaseInsensitive ) )
         continue; // skip identity field
 
       if ( fld.name().isEmpty() )
@@ -1111,7 +1117,10 @@ bool QgsMssqlProvider::changeAttributeValues( const QgsChangedAttributesMap &att
     {
       QgsField fld = mAttributeFields.at( it2.key() );
 
-      if ( fld.typeName().endsWith( " identity", Qt::CaseInsensitive ) )
+      if ( fld.typeName().toLower() == QLatin1String( "timestamp" ) )
+        continue; // You can't update timestamp columns they are server only.
+
+      if ( fld.typeName().endsWith( QLatin1String( " identity" ), Qt::CaseInsensitive ) )
         continue; // skip identity field
 
       if ( fld.name().isEmpty() )
@@ -1142,7 +1151,10 @@ bool QgsMssqlProvider::changeAttributeValues( const QgsChangedAttributesMap &att
     {
       QgsField fld = mAttributeFields.at( it2.key() );
 
-      if ( fld.typeName().endsWith( " identity", Qt::CaseInsensitive ) )
+      if ( fld.typeName().toLower() == QLatin1String( "timestamp" ) )
+        continue; // You can't update timestamp columns they are server only.
+
+      if ( fld.typeName().endsWith( QLatin1String( " identity" ), Qt::CaseInsensitive ) )
         continue; // skip identity field
 
       if ( fld.name().isEmpty() )
diff --git a/src/providers/wms/qgswmscapabilities.cpp b/src/providers/wms/qgswmscapabilities.cpp
index b518749..0f9d5ff 100644
--- a/src/providers/wms/qgswmscapabilities.cpp
+++ b/src/providers/wms/qgswmscapabilities.cpp
@@ -43,20 +43,14 @@ bool QgsWmsSettings::parseUri( const QString& uriString )
 
   // Setup authentication
   mAuth.mUserName = uri.param( "username" );
-  QgsDebugMsg( "set username to " + mAuth.mUserName );
-
   mAuth.mPassword = uri.param( "password" );
-  QgsDebugMsg( "set password to " + mAuth.mPassword );
 
   if ( uri.hasParam( "authcfg" ) )
   {
     mAuth.mAuthCfg = uri.param( "authcfg" );
   }
-  QgsDebugMsg( "set authcfg to " + mAuth.mAuthCfg );
 
   mAuth.mReferer = uri.param( "referer" );
-  QgsDebugMsg( "set referer to " + mAuth.mReferer );
-
   mXyz = false;  // assume WMS / WMTS
 
   if ( uri.param( "type" ) == "xyz" )
diff --git a/src/python/qgspythonutils.h b/src/python/qgspythonutils.h
index 265edd1..9df25d9 100644
--- a/src/python/qgspythonutils.h
+++ b/src/python/qgspythonutils.h
@@ -50,11 +50,11 @@ class PYTHON_EXPORT QgsPythonUtils
     virtual bool isEnabled() = 0;
 
     //! initialize python and import bindings
-    virtual void initPython( QgisInterface* interface ) = 0;
+    virtual void initPython( QgisInterface* iface ) = 0;
 
 #ifdef HAVE_SERVER_PYTHON_PLUGINS
     //! initialize python and import server bindings
-    virtual void initServerPython( QgsServerInterface* interface ) = 0;
+    virtual void initServerPython( QgsServerInterface* iface ) = 0;
 
     //! start server plugin: call plugin's classServerFactory(serverInterface) add to active plugins
     virtual bool startServerPlugin( QString packageName ) = 0;
diff --git a/src/server/qgsserverprojectparser.cpp b/src/server/qgsserverprojectparser.cpp
index 584ccfe..9f53b31 100644
--- a/src/server/qgsserverprojectparser.cpp
+++ b/src/server/qgsserverprojectparser.cpp
@@ -1216,7 +1216,7 @@ bool QgsServerProjectParser::findUseLayerIDs() const
 void QgsServerProjectParser::layerFromLegendLayer( const QDomElement& legendLayerElem, QMap< int, QgsMapLayer*>& layers, bool useCache ) const
 {
   QString id = legendLayerElem.firstChild().firstChild().toElement().attribute( "layerid" );
-  int drawingOrder = updateLegendDrawingOrder() ? -1 : mCustomLayerOrder.indexOf( id );
+  int drawingOrder = updateLegendDrawingOrder() ? mCustomLayerOrder.indexOf( id ) : -1;
 
   QHash< QString, QDomElement >::const_iterator layerIt = mProjectLayerElementsById.find( id );
   if ( layerIt != mProjectLayerElementsById.constEnd() )
diff --git a/src/server/qgswmsprojectparser.cpp b/src/server/qgswmsprojectparser.cpp
index 7a3015f..0fbe4bb 100644
--- a/src/server/qgswmsprojectparser.cpp
+++ b/src/server/qgswmsprojectparser.cpp
@@ -203,7 +203,7 @@ QList<QgsMapLayer*> QgsWMSProjectParser::mapLayerFromStyle( const QString& lName
   if ( !groupElement.isNull() )
   {
     addLayersFromGroup( groupElement, layers, useCache );
-    return QgsConfigParserUtils::layerMapToList( layers, mProjectParser->updateLegendDrawingOrder() );
+    return QgsConfigParserUtils::layerMapToList( layers, false );
   }
 
   //still not found. Check if it is a single embedded layer (embedded layers are not contained in mProjectLayerElementsByName)
diff --git a/tests/src/core/testqgscomposition.cpp b/tests/src/core/testqgscomposition.cpp
index 154c9c3..69fe947 100644
--- a/tests/src/core/testqgscomposition.cpp
+++ b/tests/src/core/testqgscomposition.cpp
@@ -17,6 +17,7 @@
 
 #include "qgsapplication.h"
 #include "qgscomposition.h"
+#include "qgscomposerattributetablev2.h"
 #include "qgscomposerlabel.h"
 #include "qgscomposershape.h"
 #include "qgscomposerarrow.h"
@@ -60,6 +61,10 @@ class TestQgsComposition : public QObject
     void georeference();
     void variablesEdited();
     void legendRestoredFromTemplate();
+    void attributeTableRestoredFromTemplate();
+    void mapLayersRestoredFromTemplate();
+    void mapLayersStyleOverrideRestoredFromTemplate();
+    void atlasLayerRestoredFromTemplate();
 
   private:
     QgsComposition *mComposition;
@@ -688,5 +693,215 @@ void TestQgsComposition::legendRestoredFromTemplate()
   QCOMPARE( model3->data( model->node2index( layerNode3 ), Qt::DisplayRole ).toString(), QString( "new title!" ) );
 }
 
+void TestQgsComposition::attributeTableRestoredFromTemplate()
+{
+  QgsMapLayerRegistry::instance()->removeAllMapLayers();
+
+  // load some layers
+  QFileInfo vectorFileInfo( QString( TEST_DATA_DIR ) + "/points.shp" );
+  QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
+      vectorFileInfo.completeBaseName(),
+      "ogr" );
+  QgsVectorLayer *layer2 = new QgsVectorLayer( "Point", "memory", "memory" );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer2 );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer );
+
+  // create composition
+  QgsMapSettings ms;
+  QgsComposition c( ms );
+  // add an attribute table
+  QgsComposerAttributeTableV2 *table = new QgsComposerAttributeTableV2( &c, false );
+  c.addMultiFrame( table );
+  table->setVectorLayer( layer );
+  QgsComposerFrame *frame = new QgsComposerFrame( &c, table, 1, 1, 10, 10 );
+  c.addComposerTableFrame( table, frame );
+  table->addFrame( frame );
+
+  // save composition to template
+  QDomDocument doc;
+  QDomElement composerElem = doc.createElement( "Composer" );
+  doc.appendChild( composerElem );
+  c.writeXML( composerElem, doc );
+  c.atlasComposition().writeXML( composerElem, doc );
+
+  // new project
+  QgsMapLayerRegistry::instance()->removeAllMapLayers();
+  QgsVectorLayer *layer3 = new QgsVectorLayer( vectorFileInfo.filePath(),
+      vectorFileInfo.completeBaseName(),
+      "ogr" );
+  QgsVectorLayer *layer4 = new QgsVectorLayer( "Point", "memory", "memory" );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer4 );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer3 );
+
+  // make a new composition from template
+  QgsComposition c2( ms );
+  QVERIFY( c2.loadFromTemplate( doc ) );
+  // get table from new composition
+  QList< QgsComposerFrame * > frames2;
+  c2.composerItems( frames2 );
+  QgsComposerAttributeTableV2 *table2 = static_cast< QgsComposerAttributeTableV2 *>( frames2.at( 0 )->multiFrame() );
+  QVERIFY( table2 );
+
+  QCOMPARE( table2->vectorLayer(), layer3 );
+}
+
+void TestQgsComposition::mapLayersRestoredFromTemplate()
+{
+  QgsMapLayerRegistry::instance()->removeAllMapLayers();
+
+  // load some layers
+  QFileInfo vectorFileInfo( QString( TEST_DATA_DIR ) + "/points.shp" );
+  QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
+      vectorFileInfo.completeBaseName(),
+      "ogr" );
+  QFileInfo vectorFileInfo2( QString( TEST_DATA_DIR ) + "/polys.shp" );
+  QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo2.filePath(),
+      vectorFileInfo2.completeBaseName(),
+      "ogr" );
+
+  QgsMapLayerRegistry::instance()->addMapLayer( layer2 );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer );
+
+  // create composition
+  QgsMapSettings ms;
+  QgsComposition c( ms );
+  // add a map
+  QgsComposerMap *map = new QgsComposerMap( &c, 1, 1, 10, 10 );
+  c.addComposerMap( map );
+  map->setLayerSet( QStringList() << layer->id() << layer2->id() );
+
+  // save composition to template
+  QDomDocument doc;
+  QDomElement composerElem = doc.createElement( "Composer" );
+  doc.appendChild( composerElem );
+  c.writeXML( composerElem, doc );
+  c.atlasComposition().writeXML( composerElem, doc );
+
+  // new project
+  QgsMapLayerRegistry::instance()->removeAllMapLayers();
+  QgsVectorLayer *layer3 = new QgsVectorLayer( vectorFileInfo.filePath(),
+      vectorFileInfo.completeBaseName(),
+      "ogr" );
+  QgsVectorLayer *layer4 = new QgsVectorLayer( vectorFileInfo2.filePath(),
+      vectorFileInfo2.completeBaseName(),
+      "ogr" );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer4 );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer3 );
+
+  // make a new composition from template
+  QgsComposition c2( ms );
+  QVERIFY( c2.loadFromTemplate( doc ) );
+  // get map from new composition
+  QList< QgsComposerMap * > maps;
+  c2.composerItems( maps );
+  QgsComposerMap *map2 = static_cast< QgsComposerMap *>( maps.at( 0 ) );
+  QVERIFY( map2 );
+
+  QCOMPARE( map2->layerSet(), QStringList() << layer3->id() << layer4->id() );
+}
+
+void TestQgsComposition::mapLayersStyleOverrideRestoredFromTemplate()
+{
+  QgsMapLayerRegistry::instance()->removeAllMapLayers();
+
+  // load some layers
+  QFileInfo vectorFileInfo( QString( TEST_DATA_DIR ) + "/points.shp" );
+  QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
+      vectorFileInfo.completeBaseName(),
+      "ogr" );
+  QFileInfo vectorFileInfo2( QString( TEST_DATA_DIR ) + "/polys.shp" );
+  QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo2.filePath(),
+      vectorFileInfo2.completeBaseName(),
+      "ogr" );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer2 );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer );
+
+  // create composition
+  QgsMapSettings ms;
+  QgsComposition c( ms );
+  // add a map
+  QgsComposerMap *map = new QgsComposerMap( &c, 1, 1, 10, 10 );
+  c.addComposerMap( map );
+  map->setKeepLayerStyles( true );
+  QgsStringMap styles;
+  // just close your eyes and pretend these are real styles
+  styles.insert( layer->id(), "<b>xxxxx</b>" );
+  styles.insert( layer2->id(), "<blink>yyyyy</blink>" );
+  map->setLayerStyleOverrides( styles );
+
+  // save composition to template
+  QDomDocument doc;
+  QDomElement composerElem = doc.createElement( "Composer" );
+  doc.appendChild( composerElem );
+  c.writeXML( composerElem, doc );
+  c.atlasComposition().writeXML( composerElem, doc );
+
+  // new project
+  QgsMapLayerRegistry::instance()->removeAllMapLayers();
+  QgsVectorLayer *layer3 = new QgsVectorLayer( vectorFileInfo.filePath(),
+      vectorFileInfo.completeBaseName(),
+      "ogr" );
+  QgsVectorLayer *layer4 = new QgsVectorLayer( vectorFileInfo2.filePath(),
+      vectorFileInfo2.completeBaseName(),
+      "ogr" );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer4 );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer3 );
+
+  // make a new composition from template
+  QgsComposition c2( ms );
+  QVERIFY( c2.loadFromTemplate( doc ) );
+  // get map from new composition
+  QList< QgsComposerMap * > maps;
+  c2.composerItems( maps );
+  QgsComposerMap *map2 = static_cast< QgsComposerMap *>( maps.at( 0 ) );
+  QVERIFY( map2 );
+  QVERIFY( map2->keepLayerStyles() );
+
+  QgsStringMap restoredStyles = map2->layerStyleOverrides();
+  QVERIFY( restoredStyles.contains( layer3->id() ) );
+  QCOMPARE( restoredStyles.value( layer3->id() ).trimmed(), QString( "<b>xxxxx</b>" ) );
+  QVERIFY( restoredStyles.contains( layer4->id() ) );
+  QCOMPARE( restoredStyles.value( layer4->id() ).trimmed(), QString( "<blink>yyyyy</blink>" ) );
+}
+
+void TestQgsComposition::atlasLayerRestoredFromTemplate()
+{
+  QgsMapLayerRegistry::instance()->removeAllMapLayers();
+
+  // load some layers
+  QFileInfo vectorFileInfo( QString( TEST_DATA_DIR ) + "/points.shp" );
+  QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
+      vectorFileInfo.completeBaseName(),
+      "ogr" );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer );
+
+  // create composition
+  QgsMapSettings ms;
+  QgsComposition c( ms );
+  // set atlas layer
+  c.atlasComposition().setEnabled( true );
+  c.atlasComposition().setCoverageLayer( layer );
+
+  // save composition to template
+  QDomDocument doc;
+  QDomElement composerElem = doc.createElement( "Composer" );
+  doc.appendChild( composerElem );
+  c.writeXML( composerElem, doc );
+  c.atlasComposition().writeXML( composerElem, doc );
+
+  // new project
+  QgsMapLayerRegistry::instance()->removeAllMapLayers();
+  QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo.filePath(),
+      vectorFileInfo.completeBaseName(),
+      "ogr" );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer2 );
+
+  // make a new composition from template
+  QgsComposition c2( ms );
+  QVERIFY( c2.loadFromTemplate( doc ) );
+  // check atlas layer
+  QCOMPARE( c2.atlasComposition().coverageLayer(), layer2 );
+}
+
 QTEST_MAIN( TestQgsComposition )
 #include "testqgscomposition.moc"
diff --git a/tests/src/core/testqgsmaplayer.cpp b/tests/src/core/testqgsmaplayer.cpp
index a80088c..8121627 100644
--- a/tests/src/core/testqgsmaplayer.cpp
+++ b/tests/src/core/testqgsmaplayer.cpp
@@ -25,6 +25,8 @@
 #include <qgsvectorlayer.h>
 #include <qgsapplication.h>
 #include <qgsproviderregistry.h>
+#include "qgsvectorlayerref.h"
+#include "qgsmaplayerlistutils.h"
 
 class TestSignalReceiver : public QObject
 {
@@ -68,9 +70,11 @@ class TestQgsMapLayer : public QObject
     void isInScaleRange_data();
     void isInScaleRange();
 
+    void layerRef();
+    void layerRefListUtils();
 
   private:
-    QgsMapLayer * mpLayer;
+    QgsVectorLayer * mpLayer;
 };
 
 void TestQgsMapLayer::initTestCase()
@@ -94,11 +98,12 @@ void TestQgsMapLayer::init()
   QFileInfo myMapFileInfo( myFileName );
   mpLayer = new QgsVectorLayer( myMapFileInfo.filePath(),
                                 myMapFileInfo.completeBaseName(), "ogr" );
+  QgsMapLayerRegistry::instance()->addMapLayer( mpLayer );
 }
 
 void TestQgsMapLayer::cleanup()
 {
-  delete mpLayer;
+  QgsMapLayerRegistry::instance()->removeAllMapLayers();
 }
 
 void TestQgsMapLayer::cleanupTestCase()
@@ -152,5 +157,107 @@ void TestQgsMapLayer::isInScaleRange()
 
 }
 
+void TestQgsMapLayer::layerRef()
+{
+  // construct from layer
+  QgsVectorLayerRef ref( mpLayer );
+  QCOMPARE( ref.get(), mpLayer );
+  QCOMPARE( ref.layer.data(), mpLayer );
+  QCOMPARE( ref.layerId, mpLayer->id() );
+  QCOMPARE( ref.name, QString( "points" ) );
+  QCOMPARE( ref.source, mpLayer->publicSource() );
+  QCOMPARE( ref.provider, QString( "ogr" ) );
+
+  // bool operator
+  QVERIFY( ref );
+  // -> operator
+  QCOMPARE( ref->id(), mpLayer->id() );
+
+  // verify that layer matches layer
+  QVERIFY( ref.layerMatchesSource( mpLayer ) );
+
+  // create a weak reference
+  QgsVectorLayerRef ref2( mpLayer->id(), QString( "points" ), mpLayer->publicSource(), QString( "ogr" ) );
+  QVERIFY( !ref2 );
+  QVERIFY( !ref2.get() );
+  QVERIFY( !ref2.layer.data() );
+  QCOMPARE( ref2.layerId, mpLayer->id() );
+  QCOMPARE( ref2.name, QString( "points" ) );
+  QCOMPARE( ref2.source, mpLayer->publicSource() );
+  QCOMPARE( ref2.provider, QString( "ogr" ) );
+
+  // verify that weak reference matches layer
+  QVERIFY( ref2.layerMatchesSource( mpLayer ) );
+
+  // resolve layer using project
+  QCOMPARE( ref2.resolve(), mpLayer );
+  QVERIFY( ref2 );
+  QCOMPARE( ref2.get(), mpLayer );
+  QCOMPARE( ref2.layer.data(), mpLayer );
+  QCOMPARE( ref2.layerId, mpLayer->id() );
+  QCOMPARE( ref2.name, QString( "points" ) );
+  QCOMPARE( ref2.source, mpLayer->publicSource() );
+  QCOMPARE( ref2.provider, QString( "ogr" ) );
+
+  // setLayer
+  QgsVectorLayerRef ref3;
+  QVERIFY( !ref3.get() );
+  ref3.setLayer( mpLayer );
+  QCOMPARE( ref3.get(), mpLayer );
+  QCOMPARE( ref3.layer.data(), mpLayer );
+  QCOMPARE( ref3.layerId, mpLayer->id() );
+  QCOMPARE( ref3.name, QString( "points" ) );
+  QCOMPARE( ref3.source, mpLayer->publicSource() );
+  QCOMPARE( ref3.provider, QString( "ogr" ) );
+
+  // weak resolve
+  QgsVectorLayerRef ref4( QString( "badid" ), QString( "points" ), mpLayer->publicSource(), QString( "ogr" ) );
+  QVERIFY( !ref4 );
+  QVERIFY( !ref4.resolve() );
+  QCOMPARE( ref4.resolveWeakly(), mpLayer );
+  QCOMPARE( ref4.get(), mpLayer );
+  QCOMPARE( ref4.layer.data(), mpLayer );
+  QCOMPARE( ref4.layerId, mpLayer->id() );
+  QCOMPARE( ref4.name, QString( "points" ) );
+  QCOMPARE( ref4.source, mpLayer->publicSource() );
+  QCOMPARE( ref4.provider, QString( "ogr" ) );
+
+  // try resolving a bad reference
+  QgsVectorLayerRef ref5( QString( "badid" ), QString( "points" ), mpLayer->publicSource(), QString( "xxx" ) );
+  QVERIFY( !ref5.get() );
+  QVERIFY( !ref5.resolve() );
+  QVERIFY( !ref5.resolveWeakly() );
+}
+
+void TestQgsMapLayer::layerRefListUtils()
+{
+  // conversion utils
+  QgsVectorLayer *vlA = new QgsVectorLayer( "Point", "a", "memory" );
+  QgsVectorLayer *vlB = new QgsVectorLayer( "Point", "b", "memory" );
+
+  QList<QgsMapLayer *> listRawSource;
+  listRawSource << vlA << vlB;
+
+  QList< QgsMapLayerRef > refs = _qgis_listRawToRef( listRawSource );
+  QCOMPARE( refs.at( 0 ).get(), vlA );
+  QCOMPARE( refs.at( 1 ).get(), vlB );
+
+  QList<QgsMapLayer *> raw = _qgis_listRefToRaw( refs );
+  QCOMPARE( raw, QList< QgsMapLayer *>() << vlA << vlB );
+
+  //remove layers
+  QgsVectorLayer *vlC = new QgsVectorLayer( "Point", "c", "memory" );
+  QgsVectorLayer *vlD = new QgsVectorLayer( "Point", "d", "memory" );
+  refs << QgsMapLayerRef( vlC ) << QgsMapLayerRef( vlD );
+
+  _qgis_removeLayers( refs, QList< QgsMapLayer *>() << vlB << vlD );
+  QCOMPARE( refs.size(), 2 );
+  QCOMPARE( refs.at( 0 ).get(), vlA );
+  QCOMPARE( refs.at( 1 ).get(), vlC );
+
+
+}
+
+
 QTEST_MAIN( TestQgsMapLayer )
 #include "testqgsmaplayer.moc"
diff --git a/tests/src/python/test_qgsvectorfilewriter.py b/tests/src/python/test_qgsvectorfilewriter.py
old mode 100644
new mode 100755
index bd261bc..d6e12e9
--- a/tests/src/python/test_qgsvectorfilewriter.py
+++ b/tests/src/python/test_qgsvectorfilewriter.py
@@ -24,7 +24,9 @@ from qgis.core import (QgsVectorLayer,
                        QgsCoordinateReferenceSystem,
                        QgsVectorFileWriter,
                        QgsFeatureRequest,
-                       QgsWKBTypes
+                       QgsWKBTypes,
+                       QgsRectangle,
+                       QgsCoordinateTransform
                        )
 from qgis.PyQt.QtCore import QDate, QTime, QDateTime, QVariant, QDir
 import os
@@ -32,8 +34,9 @@ import osgeo.gdal
 from osgeo import gdal, ogr
 import platform
 from qgis.testing import start_app, unittest
-from utilities import writeShape, compareWkt
+from utilities import writeShape, compareWkt, unitTestDataPath
 
+TEST_DATA_DIR = unitTestDataPath()
 start_app()
 
 
@@ -66,8 +69,7 @@ class TestFieldValueConverter(QgsVectorFileWriter.FieldValueConverter):
         return 'unexpected_idx'
 
 
-class TestQgsVectorLayer(unittest.TestCase):
-
+class TestQgsVectorFileWriter(unittest.TestCase):
     mMemoryLayer = None
 
     def testWrite(self):
@@ -145,6 +147,58 @@ class TestQgsVectorLayer(unittest.TestCase):
         self.assertIsInstance(f.attributes()[datetime_idx], str)
         self.assertEqual(f.attributes()[datetime_idx], QDateTime(QDate(2014, 3, 5), QTime(13, 45, 22)).toString("yyyy/MM/dd hh:mm:ss.zzz"))
 
+    def testWriterWithExtent(self):
+        """Check writing using extent filter."""
+        source_file = os.path.join(TEST_DATA_DIR, 'points.shp')
+        source_layer = QgsVectorLayer(source_file, 'Points', 'ogr')
+        self.assertTrue(source_layer.isValid())
+
+        options = QgsVectorFileWriter.SaveVectorOptions()
+        options.driverName = 'ESRI Shapefile'
+        options.filterExtent = QgsRectangle(-111, 26, -96, 38)
+
+        dest_file_name = os.path.join(str(QDir.tempPath()), 'extent_no_transform.shp')
+        write_result = QgsVectorFileWriter.writeAsVectorFormat(
+            source_layer,
+            dest_file_name,
+            options)
+        self.assertEqual(write_result, QgsVectorFileWriter.NoError)
+
+        # Open result and check
+        created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name), 'test', 'ogr')
+        features = [f for f in created_layer.getFeatures()]
+        self.assertEqual(len(features), 5)
+        for f in features:
+            self.assertTrue(f.geometry().intersects(options.filterExtent))
+
+    def testWriterWithExtentAndReprojection(self):
+        """Check writing using extent filter with reprojection."""
+        source_file = os.path.join(TEST_DATA_DIR, 'points.shp')
+        source_layer = QgsVectorLayer(source_file, 'Points', 'ogr')
+        self.assertTrue(source_layer.isValid())
+
+        options = QgsVectorFileWriter.SaveVectorOptions()
+        options.driverName = 'ESRI Shapefile'
+        options.filterExtent = QgsRectangle(-12511460, 3045157, -10646621, 4683497)
+        crs = QgsCoordinateReferenceSystem()
+        self.assertTrue(crs.createFromOgcWmsCrs('EPSG:3785'))
+        ct = QgsCoordinateTransform(source_layer.crs(), crs)
+        options.ct = ct
+
+        dest_file_name = os.path.join(str(QDir.tempPath()), 'extent_transform.shp')
+        write_result = QgsVectorFileWriter.writeAsVectorFormat(
+            source_layer,
+            dest_file_name,
+            options)
+        self.assertEqual(write_result, QgsVectorFileWriter.NoError)
+
+        # Open result and check
+        created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name), 'test', 'ogr')
+        features = [f for f in created_layer.getFeatures()]
+        self.assertEqual(len(features), 5)
+        for f in features:
+            self.assertTrue(f.geometry().intersects(options.filterExtent))
+
     def testDateTimeWriteTabfile(self):
         """Check writing date and time fields to an MapInfo tabfile."""
         ml = QgsVectorLayer(

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