[qgis] 01/06: Imported Upstream version 2.14.3+dfsg

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Fri May 20 15:40:07 UTC 2016


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

sebastic pushed a commit to branch master
in repository qgis.

commit bf5cbed3365f03250d0c8f4f8b8416d4071eded7
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri May 20 14:59:53 2016 +0200

    Imported Upstream version 2.14.3+dfsg
---
 CMakeLists.txt                                     |   2 +-
 ChangeLog                                          | 179 +++++++++++++++++++++
 debian/changelog                                   |  10 +-
 debian/python-qgis.install.in                      |   3 +-
 ms-windows/osgeo4w/browser-grass.bat.tmpl          |   1 +
 python/PyQt/CMakeLists.txt                         |  22 ++-
 python/PyQt/PyQt4/QtCore.py                        |  40 +++++
 python/PyQt/PyQt4/{QtCore.py => QtNetwork.py}      |  16 +-
 python/PyQt/PyQt4/{QtCore.py => QtSql.py}          |  16 +-
 python/PyQt/PyQt4/{QtCore.py => QtSvg.py}          |  16 +-
 python/PyQt/PyQt4/{QtCore.py => QtTest.py}         |  16 +-
 python/PyQt/PyQt4/{QtCore.py => QtXml.py}          |  16 +-
 python/PyQt/PyQt4/{QtCore.py => uic/__init__.py}   |  19 ++-
 python/PyQt/PyQt4/uic/properties.py                |   1 +
 python/PyQt/PyQt4/{QtCore.py => uic/pyuic.py}      |  21 ++-
 python/PyQt/PyQt5/QtCore.py                        |   2 +
 python/PyQt/PyQt5/QtNetwork.py                     |   1 +
 python/PyQt/PyQt5/QtSql.py                         |   1 +
 python/PyQt/PyQt5/QtSvg.py                         |   1 +
 python/PyQt/PyQt5/QtTest.py                        |   1 +
 python/PyQt/PyQt5/QtWidgets.py                     |   2 +
 python/PyQt/PyQt5/QtXml.py                         |   1 +
 .../{PyQt4/QtCore.py => PyQt5/uic/__init__.py}     |  19 ++-
 python/PyQt/PyQt5/uic/properties.py                |   1 +
 python/PyQt/PyQt5/uic/pyuic.py                     |   1 +
 python/core/__init__.py                            |   2 +-
 python/core/symbology-ng/qgsfillsymbollayerv2.sip  |   4 +
 python/core/symbology-ng/qgslinesymbollayerv2.sip  |   1 +
 python/plugins/processing/gui/ParametersPanel.py   |   4 +-
 .../plugins/processing/gui/ScriptEditorDialog.py   |   3 +
 resources/function_help/json/$scale                |   2 +-
 scripts/qgis_fixes/fix_pyqt.py                     |  18 +--
 scripts/release.pl                                 |   6 +-
 src/app/qgisapp.cpp                                |  13 +-
 src/app/qgsfieldsproperties.cpp                    |   2 +-
 src/core/geometry/qgsgeometry.cpp                  |   2 +-
 src/core/qgsapplication.cpp                        |   4 +-
 src/core/qgsexpression.cpp                         |  16 +-
 src/core/qgsvectorlayerfeatureiterator.cpp         |  15 +-
 src/core/symbology-ng/qgsfillsymbollayerv2.cpp     |  22 +++
 src/core/symbology-ng/qgsfillsymbollayerv2.h       |   5 +-
 src/core/symbology-ng/qgslinesymbollayerv2.cpp     |   5 +
 src/core/symbology-ng/qgslinesymbollayerv2.h       |   1 +
 src/gui/qgsadvanceddigitizingdockwidget.cpp        |   4 +-
 src/gui/qgsfieldproxymodel.cpp                     |   4 +-
 src/gui/symbology-ng/qgssymbollayerv2widget.cpp    |   1 +
 .../qgsdelimitedtextfeatureiterator.cpp            |   1 +
 src/providers/mssql/qgsmssqlfeatureiterator.cpp    |   5 +-
 src/providers/ogr/qgsogrconnpool.h                 |   3 +-
 src/providers/ogr/qgsogrfeatureiterator.cpp        |  15 +-
 src/providers/ogr/qgsogrfeatureiterator.h          |   2 +-
 src/providers/ogr/qgsogrprovider.cpp               |  16 +-
 src/providers/oracle/qgsoraclefeatureiterator.cpp  |   4 +
 .../postgres/qgspostgresfeatureiterator.cpp        |   4 +-
 .../postgres/qgspostgresfeatureiterator.h          |   1 +
 .../spatialite/qgsspatialitefeatureiterator.cpp    |   4 +
 .../virtual/qgsvirtuallayerfeatureiterator.cpp     |   4 +-
 src/python/qgspythonutilsimpl.cpp                  |   6 +-
 src/server/qgswfsserver.cpp                        |  33 ++--
 tests/src/core/CMakeLists.txt                      |   1 +
 tests/src/core/testqgsconnectionpool.cpp           | 141 ++++++++++++++++
 tests/src/core/testqgsexpression.cpp               |  41 +++++
 tests/src/core/testqgsgeometry.cpp                 |   6 +
 tests/src/gui/testqgsfieldexpressionwidget.cpp     |  50 ++++++
 tests/src/python/providertestbase.py               |   5 +-
 tests/src/python/qgis_interface.py                 |   2 +-
 tests/src/python/test_qgsblendmodes.py             |   1 +
 tests/src/python/test_qgscomposition.py            |   1 +
 .../test_qgsgeometrygeneratorsymbollayerv2.py      |   2 +-
 tests/src/python/test_qgsrelationeditwidget.py     |   6 +-
 tests/src/python/test_qgssymbollayerv2.py          |  41 ++++-
 tests/src/python/test_qgsvectorlayer.py            |  11 +-
 tests/src/python/utilities.py                      |   4 +-
 73 files changed, 792 insertions(+), 160 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 21fdbc4..6e16eac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 SET(CPACK_PACKAGE_VERSION_MAJOR "2")
 SET(CPACK_PACKAGE_VERSION_MINOR "14")
-SET(CPACK_PACKAGE_VERSION_PATCH "2")
+SET(CPACK_PACKAGE_VERSION_PATCH "3")
 SET(COMPLETE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
 SET(RELEASE_NAME "Essen")
 IF (POLICY CMP0048) # in CMake 3.0.0+
diff --git a/ChangeLog b/ChangeLog
index 73312a3..9760ef2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,182 @@
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-20
+
+    Precise that scale function returns the denominator and not the scale itself
+
+    (cherry-picked from 69a8c381abeb810625bf972354e3492827b28915)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-20
+
+    Save annotations to project.qgs in creation order (fix #14812)
+
+    Save annotations to project file in the order they were loaded or
+    created, so that annotations have the same display order each
+    time the project is opened.
+
+    (cherry-picked from 82d465cd9434d4445fe4fa44af8a5fd085cbc566)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-20
+
+    Ensure that providers fetch geometry for a QgsFeatureRequest
+    with an expression filter which requires geometry
+
+    (cherry-picked from 858914eef589b2426209d500c162c4773c41fbd5)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-20
+
+    Set expression context for geometry generator builder (fix #14833)
+
+    (cherry-picked from 7187148afb9d7c2d6670ef82b361f7d3b116fdc7)
+
+Juergen E. Fischer <jef at norbit.de>	2016-05-17
+
+    osgeo4w: add qt plugin directories to browser with grass (followup b758a8c)
+
+    (cherry picked from commit 6663a4cc821a9cf3ddc7ced1e65ba42f8fa945da)
+
+Matthias Kuhn <matthias at opengis.ch>	2016-05-16
+
+    Fix bug in edit virtual field
+
+    The index was transformed twice from field index to field origin index,
+    resulting in a corrupted index (most often being 0 in the end).
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-16
+
+    [expressions] Fix fetching joined column refs when expression is
+    not prepared (fix #14746)
+
+    (cherry-picked from febe30d991111712f95a476e97862ca5a890b9aa)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-16
+
+    [cad] Fix invalid coordinates when x/y snapping is enabled and
+    subsequent segments are parallel
+
+    (cherry-picked from 90d116c6f509098f001bf1b10e8a58d081e46a14)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-16
+
+    Ensure that @symbol_color is always correct for symbol layer types
+    with subsymbols
+
+    (cherry-picked from cda387cb6f96e01d0c677c974f1a18e5d0bcbce9)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-16
+
+    Fix memory leak in OGR provider when feature has no geometry
+    and FilterRect is used
+
+    (cherry-picked from 6b80518a5b55ab30fb19493266d5626d0f89d26b)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-16
+
+    Fix major(?) memory leak with python code execution
+
+    (cherry-picked from 73733a65edd2bbc8156bf36484995457c35f6b68)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-16
+
+    Avoid refreshing canvas for every joined feature
+
+    Instead of setting the provider's subsetString to fetch joined
+    features, use a feature request with FilterExpression instead.
+    (Setting the subsetString results in a canvas refresh.)
+
+    Performance should be similar (if expression compilation is
+    enabled) and this also has the advantage of avoiding provider-
+    specific behaviour (eg case insensitive matching).
+
+    (fix #14800)
+
+    (cherry-picked from 22acf3b1a3e7a6afe094ec6dec83776256d2655a)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-16
+
+    Fix QgsFieldComboWidget not updating fields when calling setFilter()
+
+    (cherry-picked from a389d237fcff1f61941cdba5237079e80abe6717)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-16
+
+    Fix datetime fields not shown in QgsFieldComboWidget when set to date filter
+
+    (cherry-picked from b4029dc7f0169b60117c4ece7c15a31a8766cb4f)
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-05-09
+
+    [processing] don't crash if user canceled script loading
+
+    (cherry picked from commit 583eaeff7f1994290b1a9428d8b1a7c42848a5c9)
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-05-09
+
+    [processing] add support for int64 fields (fix #14777)
+
+    (cherry picked from commit f1e6d8731b67b47ce44dc03c5e4d9b7dfe676a0f)
+
+Nyall Dawson <nyall.dawson at gmail.com>	2016-05-10
+
+    Fix feature fields does not include virtual or joined fields when
+    feature is requested using a QgsFeatureRequest with FilterFid
+
+Alessandro Pasotti <apasotti at boundlessgeo.com>	2016-05-05
+
+    [server] Fixes segfault on wrong TypeName
+
+    Unreported - WFS-T
+
+    (cherry-picked from 8e781b4ec01b276e0c2be76db5742cf5227d6bd7)
+
+    Funded by Boundless
+
+Sandro Mani <manisandro at gmail.com>	2016-05-04
+
+    Also use datasource instead of filepath when ref/unref-ing and invalidating.
+
+Juergen E. Fischer <jef at norbit.de>	2016-05-04
+
+    release.pl: don't created branches from tag names
+
+    (cherry picked from commit 919c54ef5fabe7b7c2eef9c91094642c47b2eb7c)
+
+Matthias Kuhn <matthias at opengis.ch>	2016-05-02
+
+    Fixup for AppStartup test which requires SIP API V1
+
+Matthias Kuhn <matthias at opengis.ch>	2016-05-02
+
+    Early import qgis in tests to set SIP API
+
+Matthias Kuhn <matthias at opengis.ch>	2016-05-02
+
+    Improve qgis.PyQt compatibility layer
+
+Sandro Mani <manisandro at gmail.com>	2016-04-20
+
+    Add connection pool test
+
+Sandro Mani <manisandro at gmail.com>	2016-04-11
+
+    Move QgsProviderRegistry::instance delete call after deferred delete call
+
+Sandro Mani <manisandro at gmail.com>	2016-04-10
+
+    Pass the full ogr data source URI as connInfo in qgsConnectionPool_ConnectionCreate.
+
+    This fixes corrupt rendering when loading the same dataset twice with different options (i.e. layers), see issue #14560.
+
+rldhont <rldhont at gmail.com>	2016-04-29
+
+    [BUGFIX][QGIS Server] WFS GetFeature with propertyname retrieves requested fields
+
+rldhont <rldhont at gmail.com>	2016-04-29
+
+    [BUGFIX] QgsGeometry exportToGeoJSON return 'null' for null Geometry
+
+Juergen E. Fischer <jef at norbit.de>	2016-04-29
+
+    Release of 2.14.2
+
 Nyall Dawson <nyall.dawson at gmail.com>	2016-04-29
 
     Fix calculation of point symbol bounds using data defined rotation or offset
diff --git a/debian/changelog b/debian/changelog
index 2c0290e..8d1b55c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,14 @@
-qgis (2.14.2) UNRELEASED; urgency=medium
+qgis (2.14.3) UNRELEASED; urgency=medium
+
+  * Release of 2.14.3
+
+ -- Jürgen E. Fischer <jef at norbit.de>  Fri, 20 May 2016 14:05:10 +0200
+
+qgis (2.14.2) unstable; urgency=medium
 
   * Release of 2.14.2
 
- -- Jürgen E. Fischer <jef at norbit.de>  Fri, 29 Apr 2016 14:00:28 +0200
+ -- Jürgen E. Fischer <jef at norbit.de>  Fri, 20 May 2016 14:05:09 +0200
 
 qgis (2.14.1) unstable; urgency=medium
 
diff --git a/debian/python-qgis.install.in b/debian/python-qgis.install.in
index 34a677a..87920d8 100644
--- a/debian/python-qgis.install.in
+++ b/debian/python-qgis.install.in
@@ -1,8 +1,9 @@
 usr/lib/python*/*-packages/qgis/*.py
 usr/lib/python*/*-packages/qgis/*.so
+usr/lib/python*/*-packages/qgis/PyQt/*
+usr/lib/python*/*-packages/qgis/analysis/*
 usr/lib/python*/*-packages/qgis/core/*
 usr/lib/python*/*-packages/qgis/gui/*
-usr/lib/python*/*-packages/qgis/analysis/*
 usr/lib/python*/*-packages/qgis/networkanalysis/*
 usr/lib/python*/*-packages/qgis/server/*
 usr/lib/python*/*-packages/qgis/testing/*
diff --git a/ms-windows/osgeo4w/browser-grass.bat.tmpl b/ms-windows/osgeo4w/browser-grass.bat.tmpl
index ef05a8c..72f77e9 100644
--- a/ms-windows/osgeo4w/browser-grass.bat.tmpl
+++ b/ms-windows/osgeo4w/browser-grass.bat.tmpl
@@ -4,4 +4,5 @@ call "%OSGEO4W_ROOT%"\apps\grass\grass- at grassversion@\etc\env.bat
 @echo off
 path %OSGEO4W_ROOT%\apps\@package@\bin;%OSGEO4W_ROOT%\apps\grass\grass- at grassversion@\lib;%OSGEO4W_ROOT%\apps\grass\grass- at grassversion@\bin;%PATH%
 set QGIS_PREFIX_PATH=%OSGEO4W_ROOT:\=/%/apps/@package@
+set QT_PLUGIN_PATH=%OSGEO4W_ROOT%\apps\@package@\qtplugins;%OSGEO4W_ROOT%\apps\qt4\plugins
 start "QGIS Browser" /B "%OSGEO4W_ROOT%"\bin\@package at -browser-bin.exe %*
diff --git a/python/PyQt/CMakeLists.txt b/python/PyQt/CMakeLists.txt
index e005a81..80fe79c 100644
--- a/python/PyQt/CMakeLists.txt
+++ b/python/PyQt/CMakeLists.txt
@@ -1,5 +1,5 @@
-SET (QGIS_PYQT_DIR ${QGIS_DATA_DIR}/python/PyQt)
-SET (PYTHON_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/python)
+SET (QGIS_PYQT_DIR ${PYTHON_SITE_PACKAGES_DIR}/qgis/PyQt)
+SET (PYTHON_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/python/qgis/PyQt)
 
 SET(PYQT_COMPAT_FILES
   __init__.py
@@ -9,7 +9,15 @@ SET(PYQT_COMPAT_FILES
   QtPrintSupport.py
   QtWebKit.py
   QtWebKitWidgets.py
+  QtNetwork.py
+  QtXml.py
+  QtSql.py
+  QtTest.py
+  QtSvg.py
   Qsci.py
+  uic/__init__.py
+  uic/pyuic.py
+  uic/properties.py
 )
 
 ADD_CUSTOM_TARGET(pyqtcompat ALL)
@@ -21,16 +29,16 @@ ELSE(ENABLE_QT5)
 ENDIF(ENABLE_QT5)
 
 FOREACH(pyfile ${PYQT_COMPAT_FILES})
+  GET_FILENAME_COMPONENT(_dir ${pyfile} PATH)
   SET(pyfile ${PYQT_PREFIX}/${pyfile})
-  LIST(APPEND PYQT_COMPAT_FILES_PREFIXED ${pyfile})
   ADD_CUSTOM_COMMAND(TARGET pyqtcompat
     POST_BUILD
-    COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTHON_OUTPUT_DIRECTORY}/PyQt
-    COMMAND ${CMAKE_COMMAND} -E copy ${pyfile} ${PYTHON_OUTPUT_DIRECTORY}/PyQt
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTHON_OUTPUT_DIRECTORY}/${_dir}
+    COMMAND ${CMAKE_COMMAND} -E copy ${pyfile} ${PYTHON_OUTPUT_DIRECTORY}/${_dir}
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
     DEPENDS ${pyfile}
   )
+  INSTALL(FILES ${pyfile} DESTINATION "${QGIS_PYQT_DIR}/${_dir}")
 ENDFOREACH(pyfile)
-PY_COMPILE(pyqtcompat "${PYTHON_OUTPUT_DIRECTORY}/PyQt")
 
-INSTALL(FILES ${PYQT_COMPAT_FILES_PREFIXED} DESTINATION "${QGIS_PYQT_DIR}")
+PY_COMPILE(pyqtcompat "${PYTHON_OUTPUT_DIRECTORY}")
diff --git a/python/PyQt/PyQt4/QtCore.py b/python/PyQt/PyQt4/QtCore.py
index cca3d6b..b4cdbf9 100644
--- a/python/PyQt/PyQt4/QtCore.py
+++ b/python/PyQt/PyQt4/QtCore.py
@@ -23,4 +23,44 @@ __copyright__ = '(C) 2015, Matthias Kuhn'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
+import sip
+for api in ["QDate", "QDateTime", "QString", "QTextStream", "QTime", "QUrl", "QVariant"]:
+    sip.setapi(api, 2)
+
 from PyQt4.QtCore import *
+from PyQt4.QtGui import QItemSelectionModel, QSortFilterProxyModel
+
+# Add a __nonzero__ method onto QPyNullVariant so we can check for null values easier.
+#   >>> value = QPyNullVariant("int")
+#   >>> if value:
+#   >>>       print "Not a null value"
+from types import MethodType
+from PyQt4.QtCore import QPyNullVariant
+
+
+def __nonzero__(self):
+    return False
+
+
+def __repr__(self):
+    return 'NULL'
+
+
+def __eq__(self, other):
+    return isinstance(other, QPyNullVariant) or other is None
+
+
+def __ne__(self, other):
+    return not isinstance(other, QPyNullVariant) and other is not None
+
+
+def __hash__(self):
+    return 2178309
+
+QPyNullVariant.__nonzero__ = MethodType(__nonzero__, None, QPyNullVariant)
+QPyNullVariant.__repr__ = MethodType(__repr__, None, QPyNullVariant)
+QPyNullVariant.__eq__ = MethodType(__eq__, None, QPyNullVariant)
+QPyNullVariant.__ne__ = MethodType(__ne__, None, QPyNullVariant)
+QPyNullVariant.__hash__ = MethodType(__hash__, None, QPyNullVariant)
+
+NULL = QPyNullVariant(int)
diff --git a/python/PyQt/PyQt4/QtCore.py b/python/PyQt/PyQt4/QtNetwork.py
similarity index 73%
copy from python/PyQt/PyQt4/QtCore.py
copy to python/PyQt/PyQt4/QtNetwork.py
index cca3d6b..98192db 100644
--- a/python/PyQt/PyQt4/QtCore.py
+++ b/python/PyQt/PyQt4/QtNetwork.py
@@ -2,11 +2,11 @@
 
 """
 ***************************************************************************
-    QtCore.py
+    QtNetwork.py
     ---------------------
-    Date                 : November 2015
-    Copyright            : (C) 2015 by Matthias Kuhn
-    Email                : matthias at opengis dot ch
+    Date                 : February 2016
+    Copyright            : (C) 2016 by Jürgen E. Fischer
+    Email                : jef at norbit dot de
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
@@ -17,10 +17,10 @@
 ***************************************************************************
 """
 
-__author__ = 'Matthias Kuhn'
-__date__ = 'November 2015'
-__copyright__ = '(C) 2015, Matthias Kuhn'
+__author__ = 'Jürgen E. Fischer'
+__date__ = 'February 2016'
+__copyright__ = '(C) 2016, Jürgen E. Fischer'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
-from PyQt4.QtCore import *
+from PyQt4.QtNetwork import *
diff --git a/python/PyQt/PyQt4/QtCore.py b/python/PyQt/PyQt4/QtSql.py
similarity index 74%
copy from python/PyQt/PyQt4/QtCore.py
copy to python/PyQt/PyQt4/QtSql.py
index cca3d6b..a5a0638 100644
--- a/python/PyQt/PyQt4/QtCore.py
+++ b/python/PyQt/PyQt4/QtSql.py
@@ -2,11 +2,11 @@
 
 """
 ***************************************************************************
-    QtCore.py
+    QtSql.py
     ---------------------
-    Date                 : November 2015
-    Copyright            : (C) 2015 by Matthias Kuhn
-    Email                : matthias at opengis dot ch
+    Date                 : February 2016
+    Copyright            : (C) 2016 by Jürgen E. Fischer
+    Email                : jef at norbit dot de
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
@@ -17,10 +17,10 @@
 ***************************************************************************
 """
 
-__author__ = 'Matthias Kuhn'
-__date__ = 'November 2015'
-__copyright__ = '(C) 2015, Matthias Kuhn'
+__author__ = 'Jürgen E. Fischer'
+__date__ = 'February 2016'
+__copyright__ = '(C) 2016, Jürgen E. Fischer'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
-from PyQt4.QtCore import *
+from PyQt4.QtSql import *
diff --git a/python/PyQt/PyQt4/QtCore.py b/python/PyQt/PyQt4/QtSvg.py
similarity index 74%
copy from python/PyQt/PyQt4/QtCore.py
copy to python/PyQt/PyQt4/QtSvg.py
index cca3d6b..9b14b4b 100644
--- a/python/PyQt/PyQt4/QtCore.py
+++ b/python/PyQt/PyQt4/QtSvg.py
@@ -2,11 +2,11 @@
 
 """
 ***************************************************************************
-    QtCore.py
+    QtSvg.py
     ---------------------
-    Date                 : November 2015
-    Copyright            : (C) 2015 by Matthias Kuhn
-    Email                : matthias at opengis dot ch
+    Date                 : March 2016
+    Copyright            : (C) 2016 by Jürgen E. Fischer
+    Email                : jef at norbit dot de
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
@@ -17,10 +17,10 @@
 ***************************************************************************
 """
 
-__author__ = 'Matthias Kuhn'
-__date__ = 'November 2015'
-__copyright__ = '(C) 2015, Matthias Kuhn'
+__author__ = 'Jürgen E. Fischer'
+__date__ = 'March 2016'
+__copyright__ = '(C) 2016, Jürgen E. Fischer'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
-from PyQt4.QtCore import *
+from PyQt4.QtSvg import *
diff --git a/python/PyQt/PyQt4/QtCore.py b/python/PyQt/PyQt4/QtTest.py
similarity index 73%
copy from python/PyQt/PyQt4/QtCore.py
copy to python/PyQt/PyQt4/QtTest.py
index cca3d6b..19ebec2 100644
--- a/python/PyQt/PyQt4/QtCore.py
+++ b/python/PyQt/PyQt4/QtTest.py
@@ -2,11 +2,11 @@
 
 """
 ***************************************************************************
-    QtCore.py
+    QtTest.py
     ---------------------
-    Date                 : November 2015
-    Copyright            : (C) 2015 by Matthias Kuhn
-    Email                : matthias at opengis dot ch
+    Date                 : February 2016
+    Copyright            : (C) 2016 by Jürgen E. Fischer
+    Email                : jef at norbit dot de
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
@@ -17,10 +17,10 @@
 ***************************************************************************
 """
 
-__author__ = 'Matthias Kuhn'
-__date__ = 'November 2015'
-__copyright__ = '(C) 2015, Matthias Kuhn'
+__author__ = 'Jürgen E. Fischer'
+__date__ = 'February 2016'
+__copyright__ = '(C) 2016, Jürgen E. Fischer'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
-from PyQt4.QtCore import *
+from PyQt4.QtTest import *
diff --git a/python/PyQt/PyQt4/QtCore.py b/python/PyQt/PyQt4/QtXml.py
similarity index 74%
copy from python/PyQt/PyQt4/QtCore.py
copy to python/PyQt/PyQt4/QtXml.py
index cca3d6b..e73e911 100644
--- a/python/PyQt/PyQt4/QtCore.py
+++ b/python/PyQt/PyQt4/QtXml.py
@@ -2,11 +2,11 @@
 
 """
 ***************************************************************************
-    QtCore.py
+    QtXml.py
     ---------------------
-    Date                 : November 2015
-    Copyright            : (C) 2015 by Matthias Kuhn
-    Email                : matthias at opengis dot ch
+    Date                 : February 2016
+    Copyright            : (C) 2016 by Jürgen E. Fischer
+    Email                : jef at norbit dot de
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
@@ -17,10 +17,10 @@
 ***************************************************************************
 """
 
-__author__ = 'Matthias Kuhn'
-__date__ = 'November 2015'
-__copyright__ = '(C) 2015, Matthias Kuhn'
+__author__ = 'Jürgen E. Fischer'
+__date__ = 'February 2016'
+__copyright__ = '(C) 2016, Jürgen E. Fischer'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
-from PyQt4.QtCore import *
+from PyQt4.QtXml import *
diff --git a/python/PyQt/PyQt4/QtCore.py b/python/PyQt/PyQt4/uic/__init__.py
similarity index 65%
copy from python/PyQt/PyQt4/QtCore.py
copy to python/PyQt/PyQt4/uic/__init__.py
index cca3d6b..99123d9 100644
--- a/python/PyQt/PyQt4/QtCore.py
+++ b/python/PyQt/PyQt4/uic/__init__.py
@@ -2,11 +2,11 @@
 
 """
 ***************************************************************************
-    QtCore.py
+    __init__.py
     ---------------------
-    Date                 : November 2015
-    Copyright            : (C) 2015 by Matthias Kuhn
-    Email                : matthias at opengis dot ch
+    Date                 : February 2016
+    Copyright            : (C) 2016 by Jürgen E. Fischer
+    Email                : jef at norbit dot de
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
@@ -17,10 +17,13 @@
 ***************************************************************************
 """
 
-__author__ = 'Matthias Kuhn'
-__date__ = 'November 2015'
-__copyright__ = '(C) 2015, Matthias Kuhn'
+__author__ = 'Jürgen E. Fischer'
+__date__ = 'February 2016'
+__copyright__ = '(C) 2016, Jürgen E. Fischer'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
-from PyQt4.QtCore import *
+from PyQt4.uic.Compiler import indenter, compiler
+from PyQt4.uic.objcreator import widgetPluginPath
+from PyQt4.uic import properties, uiparser, Compiler
+from PyQt4.uic import *
diff --git a/python/PyQt/PyQt4/uic/properties.py b/python/PyQt/PyQt4/uic/properties.py
new file mode 100644
index 0000000..4601fce
--- /dev/null
+++ b/python/PyQt/PyQt4/uic/properties.py
@@ -0,0 +1 @@
+from PyQt4.uic import properties
diff --git a/python/PyQt/PyQt4/QtCore.py b/python/PyQt/PyQt4/uic/pyuic.py
similarity index 66%
copy from python/PyQt/PyQt4/QtCore.py
copy to python/PyQt/PyQt4/uic/pyuic.py
index cca3d6b..68a0cb8 100644
--- a/python/PyQt/PyQt4/QtCore.py
+++ b/python/PyQt/PyQt4/uic/pyuic.py
@@ -2,11 +2,11 @@
 
 """
 ***************************************************************************
-    QtCore.py
+    pyuic.py
     ---------------------
-    Date                 : November 2015
-    Copyright            : (C) 2015 by Matthias Kuhn
-    Email                : matthias at opengis dot ch
+    Date                 : February 2016
+    Copyright            : (C) 2016 by Jürgen E. Fischer
+    Email                : jef at norbit dot de
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
@@ -17,10 +17,15 @@
 ***************************************************************************
 """
 
-__author__ = 'Matthias Kuhn'
-__date__ = 'November 2015'
-__copyright__ = '(C) 2015, Matthias Kuhn'
+__author__ = 'Jürgen E. Fischer'
+__date__ = 'February 2016'
+__copyright__ = '(C) 2016, Jürgen E. Fischer'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
-from PyQt4.QtCore import *
+
+import sip
+for api in ["QDate", "QDateTime", "QString", "QTextStream", "QTime", "QUrl", "QVariant"]:
+    sip.setapi(api, 2)
+
+from PyQt4.uic import pyuic
diff --git a/python/PyQt/PyQt5/QtCore.py b/python/PyQt/PyQt5/QtCore.py
index 3518202..b024ae8 100644
--- a/python/PyQt/PyQt5/QtCore.py
+++ b/python/PyQt/PyQt5/QtCore.py
@@ -1 +1,3 @@
 from PyQt5.QtCore import *
+NULL = QVariant()
+QPyNullVariant = QVariant()
diff --git a/python/PyQt/PyQt5/QtNetwork.py b/python/PyQt/PyQt5/QtNetwork.py
new file mode 100644
index 0000000..aff365e
--- /dev/null
+++ b/python/PyQt/PyQt5/QtNetwork.py
@@ -0,0 +1 @@
+from PyQt5.QtNetwork import *
diff --git a/python/PyQt/PyQt5/QtSql.py b/python/PyQt/PyQt5/QtSql.py
new file mode 100644
index 0000000..736745e
--- /dev/null
+++ b/python/PyQt/PyQt5/QtSql.py
@@ -0,0 +1 @@
+from PyQt5.QtSql import *
diff --git a/python/PyQt/PyQt5/QtSvg.py b/python/PyQt/PyQt5/QtSvg.py
new file mode 100644
index 0000000..7f76c2b
--- /dev/null
+++ b/python/PyQt/PyQt5/QtSvg.py
@@ -0,0 +1 @@
+from PyQt5.QtSvg import *
diff --git a/python/PyQt/PyQt5/QtTest.py b/python/PyQt/PyQt5/QtTest.py
new file mode 100644
index 0000000..7230171
--- /dev/null
+++ b/python/PyQt/PyQt5/QtTest.py
@@ -0,0 +1 @@
+from PyQt5.QtTest import *
diff --git a/python/PyQt/PyQt5/QtWidgets.py b/python/PyQt/PyQt5/QtWidgets.py
index c82e3d4..738ebfb 100644
--- a/python/PyQt/PyQt5/QtWidgets.py
+++ b/python/PyQt/PyQt5/QtWidgets.py
@@ -1 +1,3 @@
 from PyQt5.QtWidgets import *
+
+QLayout.setMargin = lambda self, m: self.setContentsMargins(m, m, m, m)
diff --git a/python/PyQt/PyQt5/QtXml.py b/python/PyQt/PyQt5/QtXml.py
new file mode 100644
index 0000000..b556556
--- /dev/null
+++ b/python/PyQt/PyQt5/QtXml.py
@@ -0,0 +1 @@
+from PyQt5.QtXml import *
diff --git a/python/PyQt/PyQt4/QtCore.py b/python/PyQt/PyQt5/uic/__init__.py
similarity index 65%
copy from python/PyQt/PyQt4/QtCore.py
copy to python/PyQt/PyQt5/uic/__init__.py
index cca3d6b..fe97eb1 100644
--- a/python/PyQt/PyQt4/QtCore.py
+++ b/python/PyQt/PyQt5/uic/__init__.py
@@ -2,11 +2,11 @@
 
 """
 ***************************************************************************
-    QtCore.py
+    __init__.py
     ---------------------
-    Date                 : November 2015
-    Copyright            : (C) 2015 by Matthias Kuhn
-    Email                : matthias at opengis dot ch
+    Date                 : February 2016
+    Copyright            : (C) 2016 by Jürgen E. Fischer
+    Email                : jef at norbit dot de
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
@@ -17,10 +17,13 @@
 ***************************************************************************
 """
 
-__author__ = 'Matthias Kuhn'
-__date__ = 'November 2015'
-__copyright__ = '(C) 2015, Matthias Kuhn'
+__author__ = 'Jürgen E. Fischer'
+__date__ = 'February 2016'
+__copyright__ = '(C) 2016, Jürgen E. Fischer'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
-from PyQt4.QtCore import *
+from PyQt5.uic.Compiler import indenter, compiler
+from PyQt5.uic.objcreator import widgetPluginPath
+from PyQt5.uic import properties, uiparser, Compiler
+from PyQt5.uic import *
diff --git a/python/PyQt/PyQt5/uic/properties.py b/python/PyQt/PyQt5/uic/properties.py
new file mode 100644
index 0000000..95c9981
--- /dev/null
+++ b/python/PyQt/PyQt5/uic/properties.py
@@ -0,0 +1 @@
+from PyQt5.uic import properties
diff --git a/python/PyQt/PyQt5/uic/pyuic.py b/python/PyQt/PyQt5/uic/pyuic.py
new file mode 100644
index 0000000..98e5be2
--- /dev/null
+++ b/python/PyQt/PyQt5/uic/pyuic.py
@@ -0,0 +1 @@
+from PyQt5.uic import pyuic
diff --git a/python/core/__init__.py b/python/core/__init__.py
index 647de19..e8fe1b7 100644
--- a/python/core/__init__.py
+++ b/python/core/__init__.py
@@ -174,7 +174,7 @@ except ImportError:
         # TODO: Fixme, this creates an invalid variant, not a NULL one
         from PyQt5.QtCore import QVariant
         NULL = QVariant()
-    except ImportError:
+    except (ImportError, RuntimeError):
         pass
 
 
diff --git a/python/core/symbology-ng/qgsfillsymbollayerv2.sip b/python/core/symbology-ng/qgsfillsymbollayerv2.sip
index 353f10c..0f4fbaf 100644
--- a/python/core/symbology-ng/qgsfillsymbollayerv2.sip
+++ b/python/core/symbology-ng/qgsfillsymbollayerv2.sip
@@ -843,6 +843,9 @@ class QgsPointPatternFillSymbolLayer : QgsImageFillSymbolLayer
 
     virtual QSet<QString> usedAttributes() const;
 
+    void setColor( const QColor& c );
+    virtual QColor color() const;
+
   protected:
     void applyDataDefinedSettings( QgsSymbolV2RenderContext& context );
 };
@@ -879,6 +882,7 @@ class QgsCentroidFillSymbolLayerV2 : QgsFillSymbolLayerV2
     void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const;
 
     void setColor( const QColor& color );
+    QColor color() const;
 
     QgsSymbolV2* subSymbol();
     bool setSubSymbol( QgsSymbolV2* symbol /Transfer/ );
diff --git a/python/core/symbology-ng/qgslinesymbollayerv2.sip b/python/core/symbology-ng/qgslinesymbollayerv2.sip
index e7ba989..d376e9c 100644
--- a/python/core/symbology-ng/qgslinesymbollayerv2.sip
+++ b/python/core/symbology-ng/qgslinesymbollayerv2.sip
@@ -145,6 +145,7 @@ class QgsMarkerLineSymbolLayerV2 : QgsLineSymbolLayerV2
     void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const;
 
     void setColor( const QColor& color );
+    virtual QColor color() const;
 
     QgsSymbolV2* subSymbol();
     bool setSubSymbol( QgsSymbolV2* symbol /Transfer/);
diff --git a/python/plugins/processing/gui/ParametersPanel.py b/python/plugins/processing/gui/ParametersPanel.py
index 27dc9d8..bf3dcf7 100644
--- a/python/plugins/processing/gui/ParametersPanel.py
+++ b/python/plugins/processing/gui/ParametersPanel.py
@@ -437,8 +437,8 @@ class ParametersPanel(BASE, WIDGET):
         if datatype == ParameterTableField.DATA_TYPE_STRING:
             fieldTypes = [QVariant.String]
         elif datatype == ParameterTableField.DATA_TYPE_NUMBER:
-            fieldTypes = [QVariant.Int, QVariant.Double, QVariant.ULongLong,
-                          QVariant.UInt]
+            fieldTypes = [QVariant.Int, QVariant.Double, QVariant.LongLong,
+                          QVariant.UInt, QVariant.ULongLong]
 
         fieldNames = set()
         for field in layer.pendingFields():
diff --git a/python/plugins/processing/gui/ScriptEditorDialog.py b/python/plugins/processing/gui/ScriptEditorDialog.py
index 1870be0..db7e6bf 100644
--- a/python/plugins/processing/gui/ScriptEditorDialog.py
+++ b/python/plugins/processing/gui/ScriptEditorDialog.py
@@ -202,6 +202,9 @@ class ScriptEditorDialog(BASE, WIDGET):
         self.filename = QFileDialog.getOpenFileName(
             self, self.tr('Save script'), scriptDir, filterName)
 
+        if self.filename == '':
+            return
+
         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
         with codecs.open(self.filename, 'r', encoding='utf-8') as f:
             txt = f.read()
diff --git a/resources/function_help/json/$scale b/resources/function_help/json/$scale
index 35c171c..34d1734 100644
--- a/resources/function_help/json/$scale
+++ b/resources/function_help/json/$scale
@@ -1,7 +1,7 @@
 {
   "name": "$scale",
   "type": "function",
-  "description": "Returns the current scale of the map canvas.<br><br>Note: This function is only available in some contexts and will be 0 otherwise.",
+  "description": "Returns the current scale denominator of the map canvas.<br><br>Note: This function is only available in some contexts and will be 0 otherwise.",
   "examples": [
 	{ "expression":"$scale", "returns":"10000"}
   ]
diff --git a/scripts/qgis_fixes/fix_pyqt.py b/scripts/qgis_fixes/fix_pyqt.py
index c464ad0..2717d10 100644
--- a/scripts/qgis_fixes/fix_pyqt.py
+++ b/scripts/qgis_fixes/fix_pyqt.py
@@ -11,7 +11,7 @@ from lib2to3.fixer_util import (Name, Comma, FromImport, Newline,
 
 MAPPING = {
     "PyQt4.QtGui": [
-        ("PyQt.QtGui", [
+        ("qgis.PyQt.QtGui", [
          "QIcon",
          "QCursor",
          "QColor",
@@ -34,7 +34,7 @@ MAPPING = {
          "QFontMetricsF",
          "QGradient",
          ]),
-        ("PyQt.QtWidgets", [
+        ("qgis.PyQt.QtWidgets", [
          "QAbstractButton",
          "QAbstractGraphicsShapeItem",
          "QAbstractItemDelegate",
@@ -235,7 +235,7 @@ MAPPING = {
          "qDrawWinButton",
          "qDrawWinPanel",
          ]),
-        ("PyQt.QtPrintSupport", [
+        ("qgis.PyQt.QtPrintSupport", [
             "QPrinter",
             "QAbstractPrintDialog",
             "QPageSetupDialog",
@@ -245,13 +245,13 @@ MAPPING = {
             "QPrintPreviewWidget",
             "QPrinterInfo",
         ]),
-        ("PyQt.QtCore", [
+        ("qgis.PyQt.QtCore", [
          "QItemSelectionModel",
          "QSortFilterProxyModel",
          ]),
     ],
     "PyQt4.QtCore": [
-        ("PyQt.QtCore", [
+        ("qgis.PyQt.QtCore", [
             "QAbstractItemModel",
             "QAbstractTableModel",
             "QByteArray",
@@ -304,15 +304,15 @@ MAPPING = {
         ]),
     ],
     "PyQt4.QtNetwork": [
-        ("PyQt.QtNetwork", ["QNetworkReply", "QNetworkRequest"])
+        ("qgis.PyQt.QtNetwork", ["QNetworkReply", "QNetworkRequest"])
     ],
     "PyQt4.QtXml": [
-        ("PyQt.QtXml", [
+        ("qgis.PyQt.QtXml", [
             "QDomDocument"
         ]),
     ],
     "PyQt4.QtSci": [
-        ("PyQt.QtSci", [
+        ("qgis.PyQt.QtSci", [
             "QsciAPIs",
             "QsciLexerCustom",
             "QsciLexerPython",
@@ -321,7 +321,7 @@ MAPPING = {
         ]),
     ],
     "PyQt4.QtWebkit": [
-        ("PyQt.QtWebkitWidgets", [
+        ("qgis.PyQt.QtWebkitWidgets", [
             "QGraphicsWebView",
             "QWebFrame",
             "QWebHitTestResult",
diff --git a/scripts/release.pl b/scripts/release.pl
index 1032af2..4fdd30c 100755
--- a/scripts/release.pl
+++ b/scripts/release.pl
@@ -202,11 +202,11 @@ unless( $dopoint ) {
 	run( "git commit -a -m 'Bump version to $newmajor.$newminor'", "bump version failed" );
 }
 
-my $topush = ($dopoint ? "" : "master ") . "$relbranch $reltag $ltrtag";
+my $topush = ($dopoint ? "" : "master ") . "$relbranch";
 
 print "Push dry-run...\n";
-run( "git push -n origin $topush", "push dry run failed" );
-print "Now manually push and upload the tarballs :\n\tgit push origin $topush\n\trsync qgis-$version.tar.bz2* qgis.org:/var/www/downloads/\n\n";
+run( "git push -n --follow-tags origin $topush", "push dry run failed" );
+print "Now manually push and upload the tarballs :\n\tgit push --follow-tags origin $topush\n\trsync qgis-$version.tar.bz2* qgis.org:/var/www/downloads/\n\n";
 
 
 =head1 NAME
diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp
index 928d3cb..cb05993 100644
--- a/src/app/qgisapp.cpp
+++ b/src/app/qgisapp.cpp
@@ -1574,14 +1574,19 @@ void QgisApp::showStyleManagerV2()
 void QgisApp::writeAnnotationItemsToProject( QDomDocument& doc )
 {
   QList<QgsAnnotationItem*> items = annotationItems();
-  QList<QgsAnnotationItem*>::const_iterator itemIt = items.constBegin();
-  for ( ; itemIt != items.constEnd(); ++itemIt )
+  QgsAnnotationItem* item;
+  QListIterator<QgsAnnotationItem*> i( items );
+  // save lowermost annotation (at end of list) first
+  i.toBack();
+  while ( i.hasPrevious() )
   {
-    if ( ! *itemIt )
+    item = i.previous();
+
+    if ( ! item )
     {
       continue;
     }
-    ( *itemIt )->writeXML( doc );
+    item->writeXML( doc );
   }
 }
 
diff --git a/src/app/qgsfieldsproperties.cpp b/src/app/qgsfieldsproperties.cpp
index 6b43ab4..c47ef2e 100644
--- a/src/app/qgsfieldsproperties.cpp
+++ b/src/app/qgsfieldsproperties.cpp
@@ -289,7 +289,7 @@ void QgsFieldsProperties::setRow( int row, int idx, const QgsField& field )
     QWidget* expressionWidget = new QWidget;
     expressionWidget->setLayout( new QHBoxLayout );
     QToolButton* editExpressionButton = new QToolButton;
-    editExpressionButton->setProperty( "Index", mLayer->fields().fieldOriginIndex( idx ) );
+    editExpressionButton->setProperty( "Index", idx );
     editExpressionButton->setIcon( QgsApplication::getThemeIcon( "/mIconExpression.svg" ) );
     connect( editExpressionButton, SIGNAL( clicked() ), this, SLOT( updateExpression() ) );
     expressionWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
diff --git a/src/core/geometry/qgsgeometry.cpp b/src/core/geometry/qgsgeometry.cpp
index 1395d0b..ae3a176 100644
--- a/src/core/geometry/qgsgeometry.cpp
+++ b/src/core/geometry/qgsgeometry.cpp
@@ -912,7 +912,7 @@ QString QgsGeometry::exportToGeoJSON( int precision ) const
 {
   if ( !d->geometry )
   {
-    return QString();
+    return QString( "null" );
   }
   return d->geometry->asJSON( precision );
 }
diff --git a/src/core/qgsapplication.cpp b/src/core/qgsapplication.cpp
index 986a797..dc6f26b 100644
--- a/src/core/qgsapplication.cpp
+++ b/src/core/qgsapplication.cpp
@@ -867,8 +867,6 @@ void QgsApplication::initQgis()
 
 void QgsApplication::exitQgis()
 {
-  delete QgsProviderRegistry::instance();
-
   delete QgsAuthManager::instance();
 
   //Ensure that all remaining deleteLater QObjects are actually deleted before we exit.
@@ -876,6 +874,8 @@ void QgsApplication::exitQgis()
   //LeakSanitiser noise which hides real issues
   QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
 
+  delete QgsProviderRegistry::instance();
+
   //delete all registered functions from expression engine (see above comment)
   QgsExpression::cleanRegisteredFunctions();
 
diff --git a/src/core/qgsexpression.cpp b/src/core/qgsexpression.cpp
index 737f6ce..a478da7 100644
--- a/src/core/qgsexpression.cpp
+++ b/src/core/qgsexpression.cpp
@@ -4262,11 +4262,23 @@ QgsExpression::Node*QgsExpression::NodeLiteral::clone() const
 QVariant QgsExpression::NodeColumnRef::eval( QgsExpression *parent, const QgsExpressionContext *context )
 {
   Q_UNUSED( parent );
+  int index = mIndex;
+
+  if ( index < 0 )
+  {
+    // have not yet found field index - first check explicitly set fields collection
+    if ( context && context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
+    {
+      QgsFields fields = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
+      index = fields.fieldNameIndex( mName );
+    }
+  }
+
   if ( context && context->hasVariable( QgsExpressionContext::EXPR_FEATURE ) )
   {
     QgsFeature feature = qvariant_cast<QgsFeature>( context->variable( QgsExpressionContext::EXPR_FEATURE ) );
-    if ( mIndex >= 0 )
-      return feature.attribute( mIndex );
+    if ( index >= 0 )
+      return feature.attribute( index );
     else
       return feature.attribute( mName );
   }
diff --git a/src/core/qgsvectorlayerfeatureiterator.cpp b/src/core/qgsvectorlayerfeatureiterator.cpp
index 0694001..184e5ca 100644
--- a/src/core/qgsvectorlayerfeatureiterator.cpp
+++ b/src/core/qgsvectorlayerfeatureiterator.cpp
@@ -685,12 +685,7 @@ void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesCached( Qg
 void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesDirect( QgsFeature& f, const QVariant& joinValue ) const
 {
   // no memory cache, query the joined values by setting substring
-  QString subsetString = joinLayer->dataProvider()->subsetString(); // provider might already have a subset string
-  QString bkSubsetString = subsetString;
-  if ( !subsetString.isEmpty() )
-  {
-    subsetString.prepend( '(' ).append( ") AND " );
-  }
+  QString subsetString;
 
   QString joinFieldName;
   if ( joinInfo->joinFieldName.isEmpty() && joinInfo->joinFieldIndex >= 0 && joinInfo->joinFieldIndex < joinLayer->fields().count() )
@@ -723,8 +718,6 @@ void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesDirect( Qg
     subsetString += '=' + v;
   }
 
-  joinLayer->dataProvider()->setSubsetString( subsetString, false );
-
   // maybe user requested just a subset of layer's attributes
   // so we do not have to cache everything
   bool hasSubset = joinInfo->joinFieldNamesSubset();
@@ -736,6 +729,8 @@ void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesDirect( Qg
   QgsFeatureRequest request;
   request.setFlags( QgsFeatureRequest::NoGeometry );
   request.setSubsetOfAttributes( attributes );
+  request.setFilterExpression( subsetString );
+  request.setLimit( 1 );
   QgsFeatureIterator fi = joinLayer->getFeatures( request );
 
   // get first feature
@@ -765,8 +760,6 @@ void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesDirect( Qg
   {
     // no suitable join feature found, keeping empty (null) attributes
   }
-
-  joinLayer->dataProvider()->setSubsetString( bkSubsetString, false );
 }
 
 
@@ -801,6 +794,8 @@ bool QgsVectorLayerFeatureIterator::nextFeatureFid( QgsFeature& f )
   QgsFeatureIterator fi = mSource->mProviderFeatureSource->getFeatures( mProviderRequest );
   if ( fi.nextFeature( f ) )
   {
+    f.setFields( mSource->mFields );
+
     if ( mSource->mHasEditBuffer )
       updateChangedAttributes( f );
 
diff --git a/src/core/symbology-ng/qgsfillsymbollayerv2.cpp b/src/core/symbology-ng/qgsfillsymbollayerv2.cpp
index ec27bd5..ba5229e 100644
--- a/src/core/symbology-ng/qgsfillsymbollayerv2.cpp
+++ b/src/core/symbology-ng/qgsfillsymbollayerv2.cpp
@@ -2317,6 +2317,11 @@ void QgsLinePatternFillSymbolLayer::setColor( const QColor& c )
   mColor = c;
 }
 
+QColor QgsLinePatternFillSymbolLayer::color() const
+{
+  return mFillLineSymbol ? mFillLineSymbol->color() : mColor;
+}
+
 QgsLinePatternFillSymbolLayer::~QgsLinePatternFillSymbolLayer()
 {
   delete mFillLineSymbol;
@@ -3370,6 +3375,18 @@ QSet<QString> QgsPointPatternFillSymbolLayer::usedAttributes() const
   return attributes;
 }
 
+void QgsPointPatternFillSymbolLayer::setColor( const QColor& c )
+{
+  mColor = c;
+  if ( mMarkerSymbol )
+    mMarkerSymbol->setColor( c );
+}
+
+QColor QgsPointPatternFillSymbolLayer::color() const
+{
+  return mMarkerSymbol ? mMarkerSymbol->color() : mColor;
+}
+
 //////////////
 
 
@@ -3404,6 +3421,11 @@ void QgsCentroidFillSymbolLayerV2::setColor( const QColor& color )
   mColor = color;
 }
 
+QColor QgsCentroidFillSymbolLayerV2::color() const
+{
+  return mMarker ? mMarker->color() : mColor;
+}
+
 void QgsCentroidFillSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
 {
   mMarker->setAlpha( context.alpha() );
diff --git a/src/core/symbology-ng/qgsfillsymbollayerv2.h b/src/core/symbology-ng/qgsfillsymbollayerv2.h
index 48bca51..d14dd30 100644
--- a/src/core/symbology-ng/qgsfillsymbollayerv2.h
+++ b/src/core/symbology-ng/qgsfillsymbollayerv2.h
@@ -896,7 +896,7 @@ class CORE_EXPORT QgsLinePatternFillSymbolLayer: public QgsImageFillSymbolLayer
     void setLineWidth( double w );
     double lineWidth() const { return mLineWidth; }
     void setColor( const QColor& c ) override;
-    QColor color() const override { return mColor; }
+    QColor color() const override;
     void setOffset( double offset ) { mOffset = offset; }
     double offset() const { return mOffset; }
 
@@ -1026,6 +1026,8 @@ class CORE_EXPORT QgsPointPatternFillSymbolLayer: public QgsImageFillSymbolLayer
     QgsMapUnitScale mapUnitScale() const override;
 
     virtual QSet<QString> usedAttributes() const override;
+    void setColor( const QColor& c ) override;
+    virtual QColor color() const override;
 
   protected:
     QgsMarkerSymbolV2* mMarkerSymbol;
@@ -1077,6 +1079,7 @@ class CORE_EXPORT QgsCentroidFillSymbolLayerV2 : public QgsFillSymbolLayerV2
     void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const override;
 
     void setColor( const QColor& color ) override;
+    QColor color() const override;
 
     QgsSymbolV2* subSymbol() override;
     bool setSubSymbol( QgsSymbolV2* symbol ) override;
diff --git a/src/core/symbology-ng/qgslinesymbollayerv2.cpp b/src/core/symbology-ng/qgslinesymbollayerv2.cpp
index 26b6843..cfd9d48 100644
--- a/src/core/symbology-ng/qgslinesymbollayerv2.cpp
+++ b/src/core/symbology-ng/qgslinesymbollayerv2.cpp
@@ -809,6 +809,11 @@ void QgsMarkerLineSymbolLayerV2::setColor( const QColor& color )
   mColor = color;
 }
 
+QColor QgsMarkerLineSymbolLayerV2::color() const
+{
+  return mMarker ? mMarker->color() : mColor;
+}
+
 void QgsMarkerLineSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
 {
   mMarker->setAlpha( context.alpha() );
diff --git a/src/core/symbology-ng/qgslinesymbollayerv2.h b/src/core/symbology-ng/qgslinesymbollayerv2.h
index 83a118f..0b0cbda 100644
--- a/src/core/symbology-ng/qgslinesymbollayerv2.h
+++ b/src/core/symbology-ng/qgslinesymbollayerv2.h
@@ -194,6 +194,7 @@ class CORE_EXPORT QgsMarkerLineSymbolLayerV2 : public QgsLineSymbolLayerV2
     void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const override;
 
     void setColor( const QColor& color ) override;
+    virtual QColor color() const override;
 
     QgsSymbolV2* subSymbol() override;
     bool setSubSymbol( QgsSymbolV2* symbol ) override;
diff --git a/src/gui/qgsadvanceddigitizingdockwidget.cpp b/src/gui/qgsadvanceddigitizingdockwidget.cpp
index 87dec83..03d1c3c 100644
--- a/src/gui/qgsadvanceddigitizingdockwidget.cpp
+++ b/src/gui/qgsadvanceddigitizingdockwidget.cpp
@@ -574,7 +574,7 @@ bool QgsAdvancedDigitizingDockWidget::applyConstraints( QgsMapMouseEvent* e )
     }
     else if ( mXConstraint->isLocked() )
     {
-      if ( cosa == 0 )
+      if ( qgsDoubleNear( cosa, 0.0 ) )
       {
         res = false;
       }
@@ -590,7 +590,7 @@ bool QgsAdvancedDigitizingDockWidget::applyConstraints( QgsMapMouseEvent* e )
     }
     else if ( mYConstraint->isLocked() )
     {
-      if ( sina == 0 )
+      if ( qgsDoubleNear( sina, 0.0 ) )
       {
         res = false;
       }
diff --git a/src/gui/qgsfieldproxymodel.cpp b/src/gui/qgsfieldproxymodel.cpp
index f0a14aa..d65c693 100644
--- a/src/gui/qgsfieldproxymodel.cpp
+++ b/src/gui/qgsfieldproxymodel.cpp
@@ -28,6 +28,7 @@ QgsFieldProxyModel::QgsFieldProxyModel( QObject *parent )
 QgsFieldProxyModel *QgsFieldProxyModel::setFilters( const Filters& filters )
 {
   mFilters = filters;
+  invalidateFilter();
   return this;
 }
 
@@ -52,7 +53,8 @@ bool QgsFieldProxyModel::filterAcceptsRow( int source_row, const QModelIndex &so
       ( mFilters.testFlag( LongLong ) && type == QVariant::LongLong ) ||
       ( mFilters.testFlag( Int ) && type == QVariant::Int ) ||
       ( mFilters.testFlag( Double ) && type == QVariant::Double ) ||
-      ( mFilters.testFlag( Date ) && type == QVariant::Date ) )
+      ( mFilters.testFlag( Date ) && type == QVariant::Date ) ||
+      ( mFilters.testFlag( Date ) && type == QVariant::DateTime ) )
     return true;
 
   return false;
diff --git a/src/gui/symbology-ng/qgssymbollayerv2widget.cpp b/src/gui/symbology-ng/qgssymbollayerv2widget.cpp
index a840de9..ed76136 100644
--- a/src/gui/symbology-ng/qgssymbollayerv2widget.cpp
+++ b/src/gui/symbology-ng/qgssymbollayerv2widget.cpp
@@ -3109,6 +3109,7 @@ QgsGeometryGeneratorSymbolLayerWidget::QgsGeometryGeneratorSymbolLayerWidget( co
   setupUi( this );
   modificationExpressionSelector->setLayer( const_cast<QgsVectorLayer*>( vl ) );
   modificationExpressionSelector->loadFieldNames();
+  modificationExpressionSelector->setExpressionContext( _getExpressionContext( this ) );
   cbxGeometryType->addItem( QgsApplication::getThemeIcon( "/mIconPolygonLayer.svg" ), tr( "Polygon / MultiPolygon" ), QgsSymbolV2::Fill );
   cbxGeometryType->addItem( QgsApplication::getThemeIcon( "/mIconLineLayer.svg" ), tr( "LineString / MultiLineString" ), QgsSymbolV2::Line );
   cbxGeometryType->addItem( QgsApplication::getThemeIcon( "/mIconPointLayer.svg" ), tr( "Point / MultiPoint" ), QgsSymbolV2::Marker );
diff --git a/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp b/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
index 6af54bf..43eacf8 100644
--- a/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
+++ b/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
@@ -128,6 +128,7 @@ QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTe
          !( mRequest.flags() & QgsFeatureRequest::NoGeometry )
          || mTestGeometry
          || ( mTestSubset && mSource->mSubsetExpression->needsGeometry() )
+         || ( request.filterType() == QgsFeatureRequest::FilterExpression && request.filterExpression()->needsGeometry() )
        )
      )
   {
diff --git a/src/providers/mssql/qgsmssqlfeatureiterator.cpp b/src/providers/mssql/qgsmssqlfeatureiterator.cpp
index 5cff00a..d315b52 100644
--- a/src/providers/mssql/qgsmssqlfeatureiterator.cpp
+++ b/src/providers/mssql/qgsmssqlfeatureiterator.cpp
@@ -102,7 +102,10 @@ void QgsMssqlFeatureIterator::BuildStatement( const QgsFeatureRequest& request )
   }
 
   // get geometry col
-  if ( !( request.flags() & QgsFeatureRequest::NoGeometry ) && mSource->isSpatial() )
+  if (( !( request.flags() & QgsFeatureRequest::NoGeometry )
+        || ( request.filterType() == QgsFeatureRequest::FilterExpression && request.filterExpression()->needsGeometry() )
+      )
+      && mSource->isSpatial() )
   {
     mStatement += QString( ",[%1]" ).arg( mSource->mGeometryColName );
   }
diff --git a/src/providers/ogr/qgsogrconnpool.h b/src/providers/ogr/qgsogrconnpool.h
index 6f5e059..5d28f78 100644
--- a/src/providers/ogr/qgsogrconnpool.h
+++ b/src/providers/ogr/qgsogrconnpool.h
@@ -35,7 +35,8 @@ inline QString qgsConnectionPool_ConnectionToName( QgsOgrConn* c )
 inline void qgsConnectionPool_ConnectionCreate( QString connInfo, QgsOgrConn*& c )
 {
   c = new QgsOgrConn;
-  c->ds = OGROpen( connInfo.toUtf8().constData(), false, nullptr );
+  QString filePath = connInfo.left( connInfo.indexOf( "|" ) );
+  c->ds = OGROpen( filePath.toUtf8().constData(), false, nullptr );
   c->path = connInfo;
   c->valid = true;
 }
diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp
index 9bb8294..8850109 100644
--- a/src/providers/ogr/qgsogrfeatureiterator.cpp
+++ b/src/providers/ogr/qgsogrfeatureiterator.cpp
@@ -43,7 +43,7 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrFeatureSource* source, bool
 {
   mFeatureFetched = false;
 
-  mConn = QgsOgrConnPool::instance()->acquireConnection( mSource->mFilePath );
+  mConn = QgsOgrConnPool::instance()->acquireConnection( mSource->mProvider->dataSourceUri() );
 
   if ( mSource->mLayerName.isNull() )
   {
@@ -74,6 +74,10 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrFeatureSource* source, bool
     }
     mRequest.setSubsetOfAttributes( attrs );
   }
+  if ( request.filterType() == QgsFeatureRequest::FilterExpression && request.filterExpression()->needsGeometry() )
+  {
+    mFetchGeometry = true;
+  }
 
   // make sure we fetch just relevant fields
   // unless it's a VRT data source filtered by geometry as we don't know which
@@ -226,13 +230,14 @@ bool QgsOgrFeatureIterator::fetchFeature( QgsFeature& feature )
   {
     if ( !readFeature( fet, feature ) )
       continue;
+    else
+      OGR_F_Destroy( fet );
 
     if ( !mRequest.filterRect().isNull() && !feature.constGeometry() )
       continue;
 
     // we have a feature, end this cycle
     feature.setValid( true );
-    OGR_F_Destroy( fet );
     return true;
 
   } // while
@@ -408,7 +413,7 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )
 QgsOgrFeatureSource::QgsOgrFeatureSource( const QgsOgrProvider* p )
     : mProvider( p )
 {
-  mFilePath = p->filePath();
+  mDataSource = p->dataSourceUri();
   mLayerName = p->layerName();
   mLayerIndex = p->layerIndex();
   mSubsetString = p->mSubsetString;
@@ -416,12 +421,12 @@ QgsOgrFeatureSource::QgsOgrFeatureSource( const QgsOgrProvider* p )
   mFields = p->mAttributeFields;
   mDriverName = p->ogrDriverName;
   mOgrGeometryTypeFilter = wkbFlatten( p->mOgrGeometryTypeFilter );
-  QgsOgrConnPool::instance()->ref( mFilePath );
+  QgsOgrConnPool::instance()->ref( mDataSource );
 }
 
 QgsOgrFeatureSource::~QgsOgrFeatureSource()
 {
-  QgsOgrConnPool::instance()->unref( mFilePath );
+  QgsOgrConnPool::instance()->unref( mDataSource );
 }
 
 QgsFeatureIterator QgsOgrFeatureSource::getFeatures( const QgsFeatureRequest& request )
diff --git a/src/providers/ogr/qgsogrfeatureiterator.h b/src/providers/ogr/qgsogrfeatureiterator.h
index f9732b7..57b2a82 100644
--- a/src/providers/ogr/qgsogrfeatureiterator.h
+++ b/src/providers/ogr/qgsogrfeatureiterator.h
@@ -34,7 +34,7 @@ class QgsOgrFeatureSource : public QgsAbstractFeatureSource
 
   protected:
     const QgsOgrProvider* mProvider;
-    QString mFilePath;
+    QString mDataSource;
     QString mLayerName;
     int mLayerIndex;
     QString mSubsetString;
diff --git a/src/providers/ogr/qgsogrprovider.cpp b/src/providers/ogr/qgsogrprovider.cpp
index 7e6df60..a170890 100644
--- a/src/providers/ogr/qgsogrprovider.cpp
+++ b/src/providers/ogr/qgsogrprovider.cpp
@@ -374,7 +374,7 @@ QgsOgrProvider::QgsOgrProvider( QString const & uri )
     << QgsVectorDataProvider::NativeType( tr( "Date & Time" ), "datetime", QVariant::DateTime );
   }
 
-  QgsOgrConnPool::instance()->ref( mFilePath );
+  QgsOgrConnPool::instance()->ref( dataSourceUri() );
 }
 
 QgsOgrProvider::~QgsOgrProvider()
@@ -685,7 +685,7 @@ OGRwkbGeometryType QgsOgrProvider::getOgrGeomType( OGRLayerH ogrLayer )
 
 void QgsOgrProvider::loadFields()
 {
-  QgsOgrConnPool::instance()->invalidateConnections( filePath() );
+  QgsOgrConnPool::instance()->invalidateConnections( dataSourceUri() );
   //the attribute fields need to be read again when the encoding changes
   mAttributeFields.clear();
 
@@ -1276,7 +1276,7 @@ bool QgsOgrProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_
   {
     pushError( tr( "OGR error syncing to disk: %1" ).arg( CPLGetLastErrorMsg() ) );
   }
-  QgsOgrConnPool::instance()->invalidateConnections( filePath() );
+  QgsOgrConnPool::instance()->invalidateConnections( dataSourceUri() );
   return true;
 }
 
@@ -1341,7 +1341,7 @@ bool QgsOgrProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
 
     OGR_F_Destroy( theOGRFeature );
   }
-  QgsOgrConnPool::instance()->invalidateConnections( filePath() );
+  QgsOgrConnPool::instance()->invalidateConnections( dataSourceUri() );
   return syncToDisc();
 }
 
@@ -2540,7 +2540,7 @@ QByteArray QgsOgrProvider::quotedIdentifier( QByteArray field ) const
 
 void QgsOgrProvider::forceReload()
 {
-  QgsOgrConnPool::instance()->invalidateConnections( filePath() );
+  QgsOgrConnPool::instance()->invalidateConnections( dataSourceUri() );
 }
 
 QByteArray QgsOgrUtils::quotedIdentifier( QByteArray field, const QString& ogrDriverName )
@@ -2605,7 +2605,7 @@ bool QgsOgrProvider::syncToDisc()
     {
       shapeIndex = true;
       close();
-      QgsOgrConnPool::instance()->invalidateConnections( mFilePath );
+      QgsOgrConnPool::instance()->invalidateConnections( dataSourceUri() );
       QFile::remove( sbnIndexFile );
       open();
     }
@@ -2621,7 +2621,7 @@ bool QgsOgrProvider::syncToDisc()
 
   mShapefileMayBeCorrupted = false;
 
-  QgsOgrConnPool::instance()->ref( mFilePath );
+  QgsOgrConnPool::instance()->ref( dataSourceUri() );
   if ( shapeIndex )
   {
     return createSpatialIndex();
@@ -2671,7 +2671,7 @@ void QgsOgrProvider::recalculateFeatureCount()
     OGR_L_SetSpatialFilter( ogrLayer, filter );
   }
 
-  QgsOgrConnPool::instance()->invalidateConnections( filePath() );
+  QgsOgrConnPool::instance()->invalidateConnections( dataSourceUri() );
 }
 
 bool QgsOgrProvider::doesStrictFeatureTypeCheck() const
diff --git a/src/providers/oracle/qgsoraclefeatureiterator.cpp b/src/providers/oracle/qgsoraclefeatureiterator.cpp
index e73fe33..f3ae92e 100644
--- a/src/providers/oracle/qgsoraclefeatureiterator.cpp
+++ b/src/providers/oracle/qgsoraclefeatureiterator.cpp
@@ -68,6 +68,10 @@ QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleFeatureSource* sour
   {
     // fetch geometry if requested
     mFetchGeometry = ( mRequest.flags() & QgsFeatureRequest::NoGeometry ) == 0;
+    if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression && mRequest.filterExpression()->needsGeometry() )
+    {
+      mFetchGeometry = true;
+    }
 
     if ( !mRequest.filterRect().isNull() )
     {
diff --git a/src/providers/postgres/qgspostgresfeatureiterator.cpp b/src/providers/postgres/qgspostgresfeatureiterator.cpp
index 8cbc710..c66eaf3 100644
--- a/src/providers/postgres/qgspostgresfeatureiterator.cpp
+++ b/src/providers/postgres/qgspostgresfeatureiterator.cpp
@@ -37,6 +37,7 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
     , mExpressionCompiled( false )
     , mOrderByCompiled( false )
     , mLastFetch( false )
+    , mFilterRequiresGeometry( false )
 {
   if ( !source->mTransactionConnection )
   {
@@ -101,6 +102,7 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
       }
       mRequest.setSubsetOfAttributes( attrs );
     }
+    mFilterRequiresGeometry = request.filterExpression()->needsGeometry();
 
     if ( QSettings().value( "/qgis/compileExpressions", true ).toBool() )
     {
@@ -436,7 +438,7 @@ QString QgsPostgresFeatureIterator::whereClauseRect()
 
 bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause, long limit, bool closeOnFail, const QString& orderBy )
 {
-  mFetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && !mSource->mGeometryColumn.isNull();
+  mFetchGeometry = ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) || mFilterRequiresGeometry ) && !mSource->mGeometryColumn.isNull();
 #if 0
   // TODO: check that all field indexes exist
   if ( !hasAllFields )
diff --git a/src/providers/postgres/qgspostgresfeatureiterator.h b/src/providers/postgres/qgspostgresfeatureiterator.h
index aad3a1b..c61deda 100644
--- a/src/providers/postgres/qgspostgresfeatureiterator.h
+++ b/src/providers/postgres/qgspostgresfeatureiterator.h
@@ -129,6 +129,7 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIteratorFromSource<Q
     bool mExpressionCompiled;
     bool mOrderByCompiled;
     bool mLastFetch;
+    bool mFilterRequiresGeometry;
 };
 
 #endif // QGSPOSTGRESFEATUREITERATOR_H
diff --git a/src/providers/spatialite/qgsspatialitefeatureiterator.cpp b/src/providers/spatialite/qgsspatialitefeatureiterator.cpp
index 72dbd5b..d2b5b79 100644
--- a/src/providers/spatialite/qgsspatialitefeatureiterator.cpp
+++ b/src/providers/spatialite/qgsspatialitefeatureiterator.cpp
@@ -95,6 +95,10 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
       }
       mRequest.setSubsetOfAttributes( attrs );
     }
+    if ( request.filterExpression()->needsGeometry() )
+    {
+      mFetchGeometry = true;
+    }
 
     if ( QSettings().value( "/qgis/compileExpressions", true ).toBool() )
     {
diff --git a/src/providers/virtual/qgsvirtuallayerfeatureiterator.cpp b/src/providers/virtual/qgsvirtuallayerfeatureiterator.cpp
index 3c70825..21c06e2 100644
--- a/src/providers/virtual/qgsvirtuallayerfeatureiterator.cpp
+++ b/src/providers/virtual/qgsvirtuallayerfeatureiterator.cpp
@@ -121,7 +121,9 @@ QgsVirtualLayerFeatureIterator::QgsVirtualLayerFeatureIterator( QgsVirtualLayerF
       }
     }
     // the last column is the geometry, if any
-    if ( !( request.flags() & QgsFeatureRequest::NoGeometry ) && !mDefinition.geometryField().isNull() && mDefinition.geometryField() != "*no*" )
+    if (( !( request.flags() & QgsFeatureRequest::NoGeometry )
+          || ( request.filterType() == QgsFeatureRequest::FilterExpression && request.filterExpression()->needsGeometry() ) )
+        && !mDefinition.geometryField().isNull() && mDefinition.geometryField() != "*no*" )
     {
       columns += "," + quotedColumn( mDefinition.geometryField() );
     }
diff --git a/src/python/qgspythonutilsimpl.cpp b/src/python/qgspythonutilsimpl.cpp
index 3607f74..1c8f5ad 100644
--- a/src/python/qgspythonutilsimpl.cpp
+++ b/src/python/qgspythonutilsimpl.cpp
@@ -298,9 +298,9 @@ bool QgsPythonUtilsImpl::runStringUnsafe( const QString& command, bool single )
   // TODO: convert special characters from unicode strings u"..." to \uXXXX
   // so that they're not mangled to utf-8
   // (non-unicode strings can be mangled)
-  PyRun_String( command.toUtf8().data(), single ? Py_single_input : Py_file_input, mMainDict, mMainDict );
-
+  PyObject* obj = PyRun_String( command.toUtf8().data(), single ? Py_single_input : Py_file_input, mMainDict, mMainDict );
   bool res = nullptr == PyErr_Occurred();
+  Py_DECREF( obj );
 
   // we are done calling python API, release global interpreter lock
   PyGILState_Release( gstate );
@@ -581,6 +581,8 @@ bool QgsPythonUtilsImpl::evalString( const QString& command, QString& result )
   if ( success )
     result = PyObjectToQString( res );
 
+  Py_XDECREF( res );
+
   // we are done calling python API, release global interpreter lock
   PyGILState_Release( gstate );
 
diff --git a/src/server/qgswfsserver.cpp b/src/server/qgswfsserver.cpp
index 4e4fbcb..51115ba 100644
--- a/src/server/qgswfsserver.cpp
+++ b/src/server/qgswfsserver.cpp
@@ -507,7 +507,8 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
         QgsFeature feature;
 
         mWithGeom = true;
-        //QgsAttributeList attrIndexes = provider->attributeIndexes();
+
+        //Using pending attributes and pending fields
         QgsAttributeList attrIndexes = layer->pendingAllAttributesList();
 
         QDomNodeList queryChildNodes = queryElem.childNodes();
@@ -515,8 +516,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
         {
           QStringList::const_iterator alstIt;
           QList<int> idxList;
-          QMap<QString, int> fieldMap = provider->fieldNameMap();
-          QMap<QString, int>::const_iterator fieldIt;
+          QgsFields fields = layer->pendingFields();
           QString fieldName;
           QDomElement propertyElem;
           for ( int q = 0; q < queryChildNodes.size(); q++ )
@@ -529,10 +529,10 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
               {
                 fieldName = fieldName.section( ":", 1, 1 );
               }
-              fieldIt = fieldMap.find( fieldName );
-              if ( fieldIt != fieldMap.end() )
+              int fieldNameIdx = fields.fieldNameIndex( fieldName );
+              if ( fieldNameIdx > -1 )
               {
-                idxList.append( fieldIt.value() );
+                idxList.append( fieldNameIdx );
               }
             }
           }
@@ -896,7 +896,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
       //map extent
       searchRect = layer->extent();
 
-      //QgsAttributeList attrIndexes = provider->attributeIndexes();
+      //Using pending attributes and pending fields
       QgsAttributeList attrIndexes = layer->pendingAllAttributesList();
       if ( mPropertyName != "*" )
       {
@@ -905,16 +905,15 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
         {
           QStringList::const_iterator alstIt;
           QList<int> idxList;
-          QMap<QString, int> fieldMap = provider->fieldNameMap();
-          QMap<QString, int>::const_iterator fieldIt;
+          QgsFields fields = layer->pendingFields();
           QString fieldName;
           for ( alstIt = attrList.begin(); alstIt != attrList.end(); ++alstIt )
           {
             fieldName = *alstIt;
-            fieldIt = fieldMap.find( fieldName );
-            if ( fieldIt != fieldMap.end() )
+            int fieldNameIdx = fields.fieldNameIndex( fieldName );
+            if ( fieldNameIdx > -1 )
             {
-              idxList.append( fieldIt.value() );
+              idxList.append( fieldNameIdx );
             }
           }
           if ( !idxList.isEmpty() )
@@ -1475,7 +1474,15 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
     mTypeName = typeNameElem.tagName();
 
     layerList = mConfigParser->mapLayerFromTypeName( mTypeName );
-    currentLayer = layerList.at( 0 );
+    // Could be empty!
+    if ( layerList.count() > 0 )
+    {
+      currentLayer = layerList.at( 0 );
+    }
+    else
+    {
+      throw QgsMapServiceException( "RequestNotWellFormed", QString( "Wrong TypeName: %1" ).arg( mTypeName ) );
+    }
 
     QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( currentLayer );
     // it's a vectorlayer and defined by the administrator as a WFS layer
diff --git a/tests/src/core/CMakeLists.txt b/tests/src/core/CMakeLists.txt
index 9c69357..2e19743 100644
--- a/tests/src/core/CMakeLists.txt
+++ b/tests/src/core/CMakeLists.txt
@@ -112,6 +112,7 @@ ADD_QGIS_TEST(composertabletest testqgscomposertable.cpp)
 ADD_QGIS_TEST(composertablev2test testqgscomposertablev2.cpp)
 ADD_QGIS_TEST(composerutils testqgscomposerutils.cpp)
 ADD_QGIS_TEST(compositiontest testqgscomposition.cpp)
+ADD_QGIS_TEST(connectionpooltest testqgsconnectionpool.cpp)
 ADD_QGIS_TEST(contrastenhancementtest  testcontrastenhancements.cpp)
 ADD_QGIS_TEST(coordinatereferencesystemtest testqgscoordinatereferencesystem.cpp)
 ADD_QGIS_TEST(coordinatetransformtest testqgscoordinatetransform.cpp)
diff --git a/tests/src/core/testqgsconnectionpool.cpp b/tests/src/core/testqgsconnectionpool.cpp
new file mode 100644
index 0000000..a350997
--- /dev/null
+++ b/tests/src/core/testqgsconnectionpool.cpp
@@ -0,0 +1,141 @@
+/***************************************************************************
+                         testqgsconnectionpool.cpp
+                         -----------------------
+    begin                : April 2016
+    copyright            : (C) 2016 by Sandro Mani
+    email                : manisandro at gmail.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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+#include "qgsapplication.h"
+#include "qgsgeometry.h"
+#include "qgspointv2.h"
+#include "qgslinestringv2.h"
+#include "qgsvectorlayer.h"
+#include <QEventLoop>
+#include <QObject>
+#include <QTemporaryFile>
+#include <QtConcurrentMap>
+#include <QtTest/QtTest>
+
+class TestQgsConnectionPool: public QObject
+{
+    Q_OBJECT
+
+  private slots:
+    void initTestCase();
+    void cleanupTestCase();
+    void layersFromSameDatasetGPX();
+
+  private:
+    struct ReadJob
+    {
+      ReadJob( QgsVectorLayer* _layer ) : layer( _layer ) {}
+      QgsVectorLayer* layer;
+      QList<QgsFeature> features;
+    };
+
+    static void processJob( ReadJob& job )
+    {
+      QgsFeatureIterator it = job.layer->getFeatures();
+      QgsFeature f;
+      while ( it.nextFeature( f ) )
+      {
+        job.features.append( f );
+      }
+    }
+
+};
+
+void TestQgsConnectionPool::initTestCase()
+{
+  QgsApplication::init();
+  QgsApplication::initQgis();
+
+}
+
+void TestQgsConnectionPool::cleanupTestCase()
+{
+  QgsApplication::exitQgis();
+}
+
+void TestQgsConnectionPool::layersFromSameDatasetGPX()
+{
+  // Tests whether features are correctly retrevied from different layers which are
+  // loaded from the same dataset. See issue #14560
+  int nWaypoints = 100000;
+  int nRoutes = 100000;
+  int nRoutePts = 10;
+  QTemporaryFile testFile( "testXXXXXX.gpx" );
+  testFile.setAutoRemove( false );
+  testFile.open();
+  testFile.write( "<gpx version=\"1.1\" creator=\"qgis\">\n" );
+  for ( int i = 0; i < nWaypoints; ++i )
+  {
+    testFile.write( QString( "<wpt lon=\"%1\" lat=\"%1\"><name></name></wpt>\n" ).arg( i ).toLocal8Bit() );
+  }
+  for ( int i = 0; i < nRoutes; ++i )
+  {
+    testFile.write( "<rte><name></name><number></number>\n" );
+    for ( int j = 0; j < nRoutePts; ++j )
+    {
+      testFile.write( QString( "<rtept lon=\"%1\" lat=\"%2\"/>\n" ).arg( j ).arg( i ).toLocal8Bit() );
+    }
+    testFile.write( "</rte>\n" );
+  }
+  testFile.write( "</gpx>\n" );
+  testFile.close();
+
+  QgsVectorLayer* layer1 = new QgsVectorLayer( testFile.fileName() + "|layername=waypoints", "Waypoints", "ogr" );
+  QVERIFY( layer1->isValid() );
+  QgsVectorLayer* layer2 = new QgsVectorLayer( testFile.fileName() + "|layername=routes", "Routes", "ogr" );
+  QVERIFY( layer2->isValid() );
+
+  QList<ReadJob> jobs = QList<ReadJob>() << ReadJob( layer1 ) << ReadJob( layer2 );
+
+  QEventLoop evLoop;
+  QFutureWatcher<void> futureWatcher;
+  connect( &futureWatcher, SIGNAL( finished() ), &evLoop, SLOT( quit() ) );
+  futureWatcher.setFuture( QtConcurrent::map( jobs, processJob ) );
+  evLoop.exec();
+
+  QList<QgsFeature>& layer1Features = jobs[0].features;
+  QList<QgsFeature>& layer2Features = jobs[1].features;
+
+  QVERIFY( layer1Features.count() == nWaypoints );
+  QVERIFY( layer2Features.count() == nRoutes );
+
+  for ( int i = 0, n = layer1Features.count(); i < n; ++i )
+  {
+    const QgsPointV2* geom = dynamic_cast<const QgsPointV2*>( layer1Features[i].geometry()->geometry() );
+    QVERIFY( geom != nullptr );
+    QVERIFY( qFuzzyCompare( geom->x(), i ) );
+    QVERIFY( qFuzzyCompare( geom->y(), i ) );
+  }
+  for ( int i = 0, n = layer2Features.count(); i < n; ++i )
+  {
+    const QgsLineStringV2* geom = dynamic_cast<const QgsLineStringV2*>( layer2Features[i].geometry()->geometry() );
+    QVERIFY( geom != nullptr );
+    int nVtx = geom->vertexCount();
+    QVERIFY( nVtx == nRoutePts );
+    for ( int j = 0; j < nVtx; ++j )
+    {
+      QgsPointV2 p = geom->vertexAt( QgsVertexId( 0, 0, j ) );
+      QVERIFY( qFuzzyCompare( p.x(), j ) );
+      QVERIFY( qFuzzyCompare( p.y(), i ) );
+    }
+  }
+  delete layer1;
+  delete layer2;
+  QFile( testFile.fileName() ).remove();
+}
+
+QTEST_MAIN( TestQgsConnectionPool )
+#include "testqgsconnectionpool.moc"
diff --git a/tests/src/core/testqgsexpression.cpp b/tests/src/core/testqgsexpression.cpp
index ad81e47..4edfe0b 100644
--- a/tests/src/core/testqgsexpression.cpp
+++ b/tests/src/core/testqgsexpression.cpp
@@ -2036,6 +2036,47 @@ class TestQgsExpression: public QObject
       QgsExpression nodeExpression( "1 IN (1, 2, 3, 4)" );
       QgsExpression nodeExpression2( nodeExpression );
     }
+
+    void test_columnRefUnprepared()
+    {
+      //test retrieving fields from feature when expression is unprepared - explicitly specified fields collection
+      //should take precedence over feature's field collection
+
+      QgsFields fields;
+      fields.append( QgsField( "f1", QVariant::String ) );
+
+      QgsFeature f( 1 );
+      f.setFields( fields );
+
+      //also add a joined field - this will not be available in feature's field collection
+      fields.append( QgsField( "j1", QVariant::String ), QgsFields::OriginJoin, 1 );
+
+      f.setAttributes( QgsAttributes() << QVariant( "f1" ) << QVariant( "j1" ) );
+      f.setValid( true );
+
+      QgsExpression e( "\"f1\"" );
+      QgsExpressionContext context;
+      context.setFeature( f );
+      context.setFields( fields );
+      QVariant result = e.evaluate( &context );
+      QCOMPARE( result.toString(), QString( "f1" ) );
+
+      //test joined field
+      QgsExpression e2( "\"j1\"" );
+      result = e2.evaluate( &context );
+      QCOMPARE( result.toString(), QString( "j1" ) );
+
+      // final test - check that feature's field collection is also used when corresponding field NOT found
+      // in explicitly passed field collection
+      fields.append( QgsField( "f2", QVariant::String ) );
+      f.setFields( fields );
+      f.setAttributes( QgsAttributes() << QVariant( "f1" ) << QVariant( "j1" ) << QVariant( "f2" ) );
+      context.setFeature( f );
+      QgsExpression e3( "\"f2\"" );
+      result = e3.evaluate( &context );
+      QCOMPARE( result.toString(), QString( "f2" ) );
+    }
+
 };
 
 QTEST_MAIN( TestQgsExpression )
diff --git a/tests/src/core/testqgsgeometry.cpp b/tests/src/core/testqgsgeometry.cpp
index f0e9663..9a05468 100644
--- a/tests/src/core/testqgsgeometry.cpp
+++ b/tests/src/core/testqgsgeometry.cpp
@@ -3311,6 +3311,12 @@ void TestQgsGeometry::exportToGeoJSON()
   obtained = geom->exportToGeoJSON();
   geojson = "{\"type\": \"MultiPolygon\", \"coordinates\": [[[ [0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]], [[ [2, 2], [4, 2], [4, 4], [2, 4], [2, 2]]]] }";
   QCOMPARE( obtained, geojson );
+
+  // no geometry
+  QgsGeometry nullGeom( nullptr );
+  obtained = nullGeom.exportToGeoJSON();
+  geojson = "null";
+  QCOMPARE( obtained, geojson );
 }
 
 bool TestQgsGeometry::renderCheck( const QString& theTestName, const QString& theComment, int mismatchCount )
diff --git a/tests/src/gui/testqgsfieldexpressionwidget.cpp b/tests/src/gui/testqgsfieldexpressionwidget.cpp
index ff8d5f0..9700f38 100644
--- a/tests/src/gui/testqgsfieldexpressionwidget.cpp
+++ b/tests/src/gui/testqgsfieldexpressionwidget.cpp
@@ -50,6 +50,7 @@ class TestQgsFieldExpressionWidget : public QObject
     void testRemoveJoin();
     void asExpression();
     void testIsValid();
+    void testFilters();
 
   private:
     QgsFieldExpressionWidget* mWidget;
@@ -219,6 +220,55 @@ void TestQgsFieldExpressionWidget::testIsValid()
   QgsMapLayerRegistry::instance()->removeMapLayer( layer );
 }
 
+void TestQgsFieldExpressionWidget::testFilters()
+{
+  QgsVectorLayer* layer = new QgsVectorLayer( "point?field=intfld:int&field=stringfld:string&field=string2fld:string&field=longfld:long&field=doublefld:double&field=datefld:date&field=timefld:time&field=datetimefld:datetime", "x", "memory" );
+  QgsMapLayerRegistry::instance()->addMapLayer( layer );
+
+  QScopedPointer< QgsFieldExpressionWidget > widget( new QgsFieldExpressionWidget() );
+  widget->setLayer( layer );
+
+  QCOMPARE( widget->mCombo->count(), 8 );
+  QCOMPARE( widget->mCombo->itemText( 0 ), QString( "intfld" ) );
+  QCOMPARE( widget->mCombo->itemText( 1 ), QString( "stringfld" ) );
+  QCOMPARE( widget->mCombo->itemText( 2 ), QString( "string2fld" ) );
+  QCOMPARE( widget->mCombo->itemText( 3 ), QString( "longfld" ) );
+  QCOMPARE( widget->mCombo->itemText( 4 ), QString( "doublefld" ) );
+  QCOMPARE( widget->mCombo->itemText( 5 ), QString( "datefld" ) );
+  QCOMPARE( widget->mCombo->itemText( 6 ), QString( "timefld" ) );
+  QCOMPARE( widget->mCombo->itemText( 7 ), QString( "datetimefld" ) );
+
+  widget->setFilters( QgsFieldProxyModel::String );
+  QCOMPARE( widget->mCombo->count(), 2 );
+  QCOMPARE( widget->mCombo->itemText( 0 ), QString( "stringfld" ) );
+  QCOMPARE( widget->mCombo->itemText( 1 ), QString( "string2fld" ) );
+
+  widget->setFilters( QgsFieldProxyModel::Int );
+  QCOMPARE( widget->mCombo->count(), 1 );
+  QCOMPARE( widget->mCombo->itemText( 0 ), QString( "intfld" ) );
+
+  widget->setFilters( QgsFieldProxyModel::LongLong );
+  QCOMPARE( widget->mCombo->count(), 1 );
+  QCOMPARE( widget->mCombo->itemText( 0 ), QString( "longfld" ) );
+
+  widget->setFilters( QgsFieldProxyModel::Double );
+  QCOMPARE( widget->mCombo->count(), 1 );
+  QCOMPARE( widget->mCombo->itemText( 0 ), QString( "doublefld" ) );
+
+  widget->setFilters( QgsFieldProxyModel::Numeric );
+  QCOMPARE( widget->mCombo->count(), 3 );
+  QCOMPARE( widget->mCombo->itemText( 0 ), QString( "intfld" ) );
+  QCOMPARE( widget->mCombo->itemText( 1 ), QString( "longfld" ) );
+  QCOMPARE( widget->mCombo->itemText( 2 ), QString( "doublefld" ) );
+
+  widget->setFilters( QgsFieldProxyModel::Date );
+  QCOMPARE( widget->mCombo->count(), 2 );
+  QCOMPARE( widget->mCombo->itemText( 0 ), QString( "datefld" ) );
+  QCOMPARE( widget->mCombo->itemText( 1 ), QString( "datetimefld" ) );
+
+  QgsMapLayerRegistry::instance()->removeMapLayer( layer );
+}
+
 QTEST_MAIN( TestQgsFieldExpressionWidget )
 #include "testqgsfieldexpressionwidget.moc"
 
diff --git a/tests/src/python/providertestbase.py b/tests/src/python/providertestbase.py
index be585b2..c2ff215 100644
--- a/tests/src/python/providertestbase.py
+++ b/tests/src/python/providertestbase.py
@@ -62,7 +62,7 @@ class ProviderTestCase(object):
                 self.assertFalse(geometries[pk], 'Expected null geometry for {}'.format(pk))
 
     def assert_query(self, provider, expression, expected):
-        result = set([f['pk'] for f in provider.getFeatures(QgsFeatureRequest().setFilterExpression(expression))])
+        result = set([f['pk'] for f in provider.getFeatures(QgsFeatureRequest().setFilterExpression(expression).setFlags(QgsFeatureRequest.NoGeometry))])
         assert set(expected) == result, 'Expected {} and got {} when testing expression "{}"'.format(set(expected), result, expression)
 
         # Also check that filter works when referenced fields are not being retrieved by request
@@ -154,6 +154,9 @@ class ProviderTestCase(object):
         # against numeric literals
         self.assert_query(provider, 'num_char IN (2, 4, 5)', [2, 4, 5])
 
+        # geometry
+        self.assert_query(provider, 'intersects($geometry,geom_from_wkt( \'Polygon ((-72.2 66.1, -65.2 66.1, -65.2 72.0, -72.2 72.0, -72.2 66.1))\'))', [1, 2])
+
     def testGetFeaturesUncompiled(self):
         try:
             self.disableCompiler()
diff --git a/tests/src/python/qgis_interface.py b/tests/src/python/qgis_interface.py
index 6c73118..3732205 100644
--- a/tests/src/python/qgis_interface.py
+++ b/tests/src/python/qgis_interface.py
@@ -26,7 +26,7 @@ __copyright__ = ('Copyright (c) 2010 by Ivan Mincik, ivan.mincik at gista.sk and '
 
 import qgis
 
-from PyQt.QtCore import QObject
+from qgis.PyQt.QtCore import QObject
 from qgis.core import QgsMapLayerRegistry
 
 
diff --git a/tests/src/python/test_qgsblendmodes.py b/tests/src/python/test_qgsblendmodes.py
index 76aa6b6..2878eea 100644
--- a/tests/src/python/test_qgsblendmodes.py
+++ b/tests/src/python/test_qgsblendmodes.py
@@ -23,6 +23,7 @@ __copyright__ = '(C) 2013, Nyall Dawson, Massimo Endrighi'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
+import qgis
 import os
 
 from PyQt4.QtCore import QSize
diff --git a/tests/src/python/test_qgscomposition.py b/tests/src/python/test_qgscomposition.py
index 518a6ce..f758c5b 100644
--- a/tests/src/python/test_qgscomposition.py
+++ b/tests/src/python/test_qgscomposition.py
@@ -12,6 +12,7 @@ __copyright__ = 'Copyright 2012, The QGIS Project'
 # This will get replaced with a git SHA1 when you do a git archive
 __revision__ = '$Format:%H$'
 
+import qgis
 import os
 
 from PyQt4.QtCore import QFileInfo, QDir
diff --git a/tests/src/python/test_qgsgeometrygeneratorsymbollayerv2.py b/tests/src/python/test_qgsgeometrygeneratorsymbollayerv2.py
index 0ef8302..f9e145b 100644
--- a/tests/src/python/test_qgsgeometrygeneratorsymbollayerv2.py
+++ b/tests/src/python/test_qgsgeometrygeneratorsymbollayerv2.py
@@ -25,7 +25,7 @@ __revision__ = '$Format:%H$'
 
 import os
 
-from PyQt.QtCore import QSize
+from qgis.PyQt.QtCore import QSize
 
 from qgis.core import (
     QgsVectorLayer,
diff --git a/tests/src/python/test_qgsrelationeditwidget.py b/tests/src/python/test_qgsrelationeditwidget.py
index 0097d36..5ca8350 100644
--- a/tests/src/python/test_qgsrelationeditwidget.py
+++ b/tests/src/python/test_qgsrelationeditwidget.py
@@ -36,18 +36,18 @@ from qgis.gui import (
     QgsFeatureListView
 )
 
-from PyQt.QtCore import (
+from qgis.PyQt.QtCore import (
     QTimer
 )
 
-from PyQt.QtWidgets import (
+from qgis.PyQt.QtWidgets import (
     QWidget,
     QToolButton,
     QTableView,
     QListView
 )
 
-from PyQt.QtGui import (
+from qgis.PyQt.QtGui import (
     QApplication
 )
 
diff --git a/tests/src/python/test_qgssymbollayerv2.py b/tests/src/python/test_qgssymbollayerv2.py
index 9a673d4..bc96748 100644
--- a/tests/src/python/test_qgssymbollayerv2.py
+++ b/tests/src/python/test_qgssymbollayerv2.py
@@ -364,6 +364,14 @@ class TestQgsSymbolLayerV2(unittest.TestCase):
         mMessage = 'Expected "%s" got "%s"' % (mExpectedValue, mValue)
         assert mExpectedValue == mValue, mMessage
 
+        # test colors, need to make sure colors are passed/retrieved from subsymbol
+        mSymbolLayer.setColor(QColor(150, 50, 100))
+        self.assertEqual(mSymbolLayer.color(), QColor(150, 50, 100))
+        self.assertEqual(mSymbolLayer.subSymbol().color(), QColor(150, 50, 100))
+        mSymbolLayer.subSymbol().setColor(QColor(250, 150, 200))
+        self.assertEqual(mSymbolLayer.subSymbol().color(), QColor(250, 150, 200))
+        self.assertEqual(mSymbolLayer.color(), QColor(250, 150, 200))
+
     def testQgsLinePatternFillSymbolLayer(self):
         """
         Create a new style from a .sld file and match test
@@ -404,8 +412,16 @@ class TestQgsSymbolLayerV2(unittest.TestCase):
         mMessage = 'Expected "%s" got "%s"' % (mExpectedValue, mValue)
         assert mExpectedValue == mValue, mMessage
 
+        # test colors, need to make sure colors are passed/retrieved from subsymbol
+        mSymbolLayer.setColor(QColor(150, 50, 100))
+        self.assertEqual(mSymbolLayer.color(), QColor(150, 50, 100))
+        self.assertEqual(mSymbolLayer.subSymbol().color(), QColor(150, 50, 100))
+        mSymbolLayer.subSymbol().setColor(QColor(250, 150, 200))
+        self.assertEqual(mSymbolLayer.subSymbol().color(), QColor(250, 150, 200))
+        self.assertEqual(mSymbolLayer.color(), QColor(250, 150, 200))
+
     @unittest.expectedFailure
-    def testQgsPointPatternFillSymbolLayer(self):
+    def testQgsPointPatternFillSymbolLayerSld(self):
         """
         Create a new style from a .sld file and match test
         """
@@ -452,6 +468,20 @@ class TestQgsSymbolLayerV2(unittest.TestCase):
         mMessage = 'Expected "%s" got "%s"' % (mExpectedValue, mValue)
         assert mExpectedValue == mValue, mMessage
 
+    def testQgsPointPatternFillSymbolLayer(self):
+        """
+        Test point pattern fill
+        """
+        # test colors, need to make sure colors are passed/retrieved from subsymbol
+        mSymbolLayer = QgsPointPatternFillSymbolLayer.create()
+
+        mSymbolLayer.setColor(QColor(150, 50, 100))
+        self.assertEqual(mSymbolLayer.color(), QColor(150, 50, 100))
+        self.assertEqual(mSymbolLayer.subSymbol().color(), QColor(150, 50, 100))
+        mSymbolLayer.subSymbol().setColor(QColor(250, 150, 200))
+        self.assertEqual(mSymbolLayer.subSymbol().color(), QColor(250, 150, 200))
+        self.assertEqual(mSymbolLayer.color(), QColor(250, 150, 200))
+
     def testQgsSVGFillSymbolLayer(self):
         """
         Create a new style from a .sld file and match test
@@ -522,6 +552,14 @@ class TestQgsSymbolLayerV2(unittest.TestCase):
         mMessage = 'Expected "%s" got "%s"' % (mExpectedValue, mValue)
         assert mExpectedValue == mValue, mMessage
 
+        # test colors, need to make sure colors are passed/retrieved from subsymbol
+        mSymbolLayer.setColor(QColor(150, 50, 100))
+        self.assertEqual(mSymbolLayer.color(), QColor(150, 50, 100))
+        self.assertEqual(mSymbolLayer.subSymbol().color(), QColor(150, 50, 100))
+        mSymbolLayer.subSymbol().setColor(QColor(250, 150, 200))
+        self.assertEqual(mSymbolLayer.subSymbol().color(), QColor(250, 150, 200))
+        self.assertEqual(mSymbolLayer.color(), QColor(250, 150, 200))
+
     def testQgsSimpleLineSymbolLayerV2(self):
         """
         Create a new style from a .sld file and match test
@@ -692,6 +730,5 @@ class TestQgsSymbolLayerV2(unittest.TestCase):
         mMessage = 'Expected "%s" got "%s"' % (mExpectedValue, mValue)
         assert mExpectedValue == mValue, mMessage
 
-
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/src/python/test_qgsvectorlayer.py b/tests/src/python/test_qgsvectorlayer.py
index ce3a835..6849901 100644
--- a/tests/src/python/test_qgsvectorlayer.py
+++ b/tests/src/python/test_qgsvectorlayer.py
@@ -967,8 +967,15 @@ class TestQgsVectorLayer(unittest.TestCase):
 
         idx = layer.addExpressionField('5', QgsField('test', QVariant.LongLong))
 
-        self.assertEquals(layer.getFeatures().next()[idx], 5)
-        self.assertEquals(layer.pendingFields().count(), cnt + 1)
+        fet = next(layer.getFeatures())
+        self.assertEqual(fet[idx], 5)
+        # check fields
+        self.assertEqual(layer.fields().count(), cnt + 1)
+        self.assertEqual(fet.fields(), layer.fields())
+
+        # retrieve single feature and check fields
+        fet = next(layer.getFeatures(QgsFeatureRequest().setFilterFid(1)))
+        self.assertEqual(fet.fields(), layer.fields())
 
         layer.updateExpressionField(idx, '9')
 
diff --git a/tests/src/python/utilities.py b/tests/src/python/utilities.py
index 1f5f6fa..14930a7 100644
--- a/tests/src/python/utilities.py
+++ b/tests/src/python/utilities.py
@@ -18,8 +18,8 @@ import glob
 import platform
 import tempfile
 
-from PyQt.QtCore import QSize, QDir
-from PyQt.QtWidgets import QWidget
+from PyQt4.QtCore import QSize, QDir
+from PyQt4.QtGui import QWidget
 
 from qgis.core import (
     QgsApplication,

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