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