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