[qgis] 01/01: Imported Upstream version 2.18.0+dfsg
Bas Couwenberg
sebastic at debian.org
Fri Oct 21 19:28:59 UTC 2016
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch upstream
in repository qgis.
commit 69edb36b3db50d8661f4158a13b428bd9bdd712f
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Fri Oct 21 21:25:37 2016 +0200
Imported Upstream version 2.18.0+dfsg
---
.editorconfig | 4 +
CMakeLists.txt | 6 +-
CTestConfig.cmake | 2 +-
ChangeLog | 2980 +++-
NEWS | 209 +-
ci/travis/linux/qt4/script.sh | 2 +-
ci/travis/linux/qt5/blacklist.txt | 1 +
ci/travis/linux/qt5/script.sh | 2 +-
cmake/FindSpatiaLite.cmake | 2 +-
cmake/SIPMacros.cmake | 4 -
debian/changelog | 20 +-
debian/compat.in | 2 +-
debian/control.in | 36 +-
debian/copyright | 11 +-
debian/qgis-providers.install.in | 4 +-
debian/rules | 8 +-
doc/TRANSLATORS | 76 +-
doc/news.html | 268 +-
doc/news.t2t | 30 +
i18n/qgis_de.ts | 13909 ++++++++++---------
images/images.qrc | 109 +-
images/splash/splash.png | Bin 3251283 -> 2839175 bytes
images/themes/default/extents.png | Bin 701 -> 0 bytes
images/themes/default/histogram.png | Bin 510 -> 0 bytes
images/themes/default/mActionAddBasicShape.png | Bin 1102 -> 0 bytes
images/themes/default/mActionCalculateField.png | Bin 1177 -> 0 bytes
images/themes/default/mActionCaptureLine.png | Bin 942 -> 0 bytes
images/themes/default/mActionDeleteAttribute.png | Bin 728 -> 0 bytes
images/themes/default/mActionFilter.png | Bin 1726 -> 0 bytes
images/themes/default/mActionNewAttribute.png | Bin 821 -> 0 bytes
images/themes/default/mActionRotateLabel.png | Bin 1323 -> 0 bytes
images/themes/default/mActionToggleEditing.png | Bin 1046 -> 0 bytes
images/themes/default/mIconClear.png | Bin 773 -> 0 bytes
images/themes/default/mIconClearText.svg | 72 +
images/themes/default/mIconClearTextHover.svg | 72 +
images/themes/default/mIconClose.png | Bin 502 -> 0 bytes
images/themes/default/mIconClose.svg | 55 +
images/themes/default/mIconWarn.png | Bin 658 -> 0 bytes
images/themes/default/symbologyAdd.png | Bin 249 -> 0 bytes
images/themes/default/symbologyDown.png | Bin 514 -> 0 bytes
images/themes/default/symbologyRemove.png | Bin 202 -> 0 bytes
images/themes/default/transformed.png | Bin 3344 -> 0 bytes
images/themes/default/transformed.svg | 155 +
ms-windows/Installer-Files/WelcomeFinishPage.bmp | Bin 154542 -> 154542 bytes
ms-windows/osgeo4w/creatensis.pl | 7 +-
ms-windows/osgeo4w/package-nightly.cmd | 2 +-
ms-windows/osgeo4w/package.cmd | 3 +-
python/PyQt/PyQt4/Qt.py | 27 +
python/PyQt/PyQt5/Qt.py | 27 +
python/console/console.py | 6 +-
python/console/console_editor.py | 8 +-
python/core/composer/qgscomposerattributetable.sip | 4 +-
.../core/composer/qgscomposerattributetablev2.sip | 2 +-
python/core/composer/qgscomposerlegend.sip | 4 +-
python/core/composer/qgscomposerpicture.sip | 39 +
python/core/composer/qgscomposition.sip | 2 +-
python/core/core.sip | 3 +
python/core/dxf/qgsdxfexport.sip | 16 +-
python/core/geometry/qgsabstractgeometryv2.sip | 9 +-
python/core/geometry/qgscurvepolygonv2.sip | 2 +
python/core/geometry/qgscurvev2.sip | 2 +
python/core/geometry/qgsgeometry.sip | 43 +-
python/core/geometry/qgsgeometrycollectionv2.sip | 1 +
python/core/geometry/qgsmulticurvev2.sip | 2 +
python/core/geometry/qgsmultipointv2.sip | 2 +
python/core/geometry/qgsmultipolygonv2.sip | 2 +
python/core/geometry/qgsmultisurfacev2.sip | 2 +
python/core/geometry/qgspointv2.sip | 1 +
python/core/geometry/qgspolygonv2.sip | 1 +
python/core/layertree/qgslayertreemodel.sip | 10 +-
python/core/qgsannotation.sip | 2 +-
python/core/qgsapplication.sip | 4 +-
python/core/qgsbearingutils.sip | 21 +
python/core/qgscolorscheme.sip | 8 +
python/core/qgseditformconfig.sip | 65 +-
python/core/qgsexpression.sip | 65 +-
python/core/qgsexpressioncontext.sip | 2 +-
python/core/qgsexpressionfieldbuffer.sip | 10 +
python/core/qgsfeedback.sip | 43 +
python/core/qgsfield.sip | 51 +-
python/core/qgsgeometryvalidator.sip | 2 +-
python/core/qgsmaplayer.sip | 13 +-
python/core/qgsmaplayerrenderer.sip | 4 +
python/core/qgsmapsettings.sip | 3 +-
python/core/qgsofflineediting.sip | 4 +-
python/core/qgsoptionalexpression.sip | 112 +
python/core/qgspallabeling.sip | 6 +
python/core/qgsproject.sip | 10 +-
python/core/qgsrendercontext.sip | 1 +
python/core/qgsstringutils.sip | 123 +-
python/core/qgsvectorlayer.sip | 45 +-
python/core/raster/qgsbrightnesscontrastfilter.sip | 3 +-
python/core/raster/qgshillshaderenderer.sip | 1 +
python/core/raster/qgshuesaturationfilter.sip | 3 +-
python/core/raster/qgsmultibandcolorrenderer.sip | 1 +
python/core/raster/qgspalettedrasterrenderer.sip | 1 +
python/core/raster/qgsrasterdataprovider.sip | 3 +-
python/core/raster/qgsrasterdrawer.sip | 5 +-
python/core/raster/qgsrasterinterface.sip | 51 +
python/core/raster/qgsrasteriterator.sip | 3 +-
python/core/raster/qgsrasternuller.sip | 1 +
python/core/raster/qgsrasterprojector.sip | 30 +-
python/core/raster/qgsrasterrenderer.sip | 2 -
python/core/raster/qgsrasterresamplefilter.sip | 1 +
.../core/raster/qgssinglebandcolordatarenderer.sip | 1 +
python/core/raster/qgssinglebandgrayrenderer.sip | 1 +
.../raster/qgssinglebandpseudocolorrenderer.sip | 1 +
python/ext-libs/owslib/swe/common.py | 2 +-
python/ext-libs/owslib/wmts.py | 2 +-
python/ext-libs/owslib/wps.py | 4 +-
.../editorwidgets/core/qgseditorconfigwidget.sip | 7 +
python/gui/editorwidgets/qgsdoublespinbox.sip | 40 +-
.../gui/editorwidgets/qgsrelationwidgetwrapper.sip | 48 +
python/gui/editorwidgets/qgsspinbox.sip | 41 +-
python/gui/gui.sip | 2 +
python/gui/layertree/qgslayertreeview.sip | 8 +
python/gui/qgscolorschemelist.sip | 7 +
python/gui/qgscolorwidgets.sip | 1 +
python/gui/qgscompoundcolorwidget.sip | 12 +-
python/gui/qgsexpressionlineedit.sip | 82 +
python/gui/qgsfieldexpressionwidget.sip | 19 +
python/gui/qgsfilterlineedit.sip | 118 +-
python/gui/qgspanelwidget.sip | 15 +-
python/gui/qgsrelationeditorwidget.sip | 40 +
python/gui/qgstabwidget.sip | 84 +
python/plugins/GdalTools/tools/doBuildVRT.py | 1 +
python/plugins/GdalTools/tools/doExtractProj.py | 8 +-
python/plugins/db_manager/db_manager.py | 9 +
python/plugins/db_manager/db_manager_plugin.py | 39 +
python/plugins/db_manager/db_plugins/plugin.py | 3 +
.../db_manager/db_plugins/postgis/plugin.py | 3 +
.../db_manager/db_plugins/spatialite/connector.py | 2 +-
python/plugins/db_manager/dlg_import_vector.py | 17 +-
python/plugins/db_manager/dlg_sql_layer_window.py | 530 +
python/plugins/db_manager/ui/DlgImportVector.ui | 9 +-
python/plugins/db_manager/ui/DlgSqlLayerWindow.ui | 407 +
python/plugins/processing/ProcessingPlugin.py | 2 +-
.../plugins/processing/algs/gdal/GdalAlgorithm.py | 3 +-
.../processing/algs/gdal/ogr2ogrtopostgis.py | 52 +-
.../processing/algs/gdal/ogr2ogrtopostgislist.py | 2 +-
python/plugins/processing/algs/gdal/warp.py | 13 +-
.../processing/algs/grass/GrassAlgorithm.py | 10 +-
.../processing/algs/grass7/Grass7Algorithm.py | 9 +-
.../plugins/processing/algs/grass7/Grass7Utils.py | 4 +-
.../processing/algs/grass7/ext/i_aster_toar.py | 2 +-
python/plugins/processing/algs/help/qgis.yaml | 52 +-
python/plugins/processing/algs/help/saga.yaml | 48 +
python/plugins/processing/algs/qgis/Boundary.py | 92 +
python/plugins/processing/algs/qgis/BoundingBox.py | 86 +
python/plugins/processing/algs/qgis/Buffer.py | 14 +-
python/plugins/processing/algs/qgis/Clip.py | 147 +-
python/plugins/processing/algs/qgis/Difference.py | 2 +-
python/plugins/processing/algs/qgis/Dissolve.py | 75 +-
python/plugins/processing/algs/qgis/Eliminate.py | 20 +-
.../processing/algs/qgis/ImportIntoPostGIS.py | 8 +-
.../plugins/processing/algs/qgis/Intersection.py | 34 +-
python/plugins/processing/algs/qgis/MergeLines.py | 89 +
.../processing/algs/qgis/MergeLines_BACKUP_1606.py | 89 +
.../processing/algs/qgis/MergeLines_BASE_1606.py | 90 +
.../processing/algs/qgis/MergeLines_LOCAL_1606.py | 0
.../processing/algs/qgis/MergeLines_REMOTE_1606.py | 89 +
.../plugins/processing/algs/qgis/PointOnSurface.py | 83 +
.../processing/algs/qgis/QGISAlgorithmProvider.py | 9 +-
.../processing/algs/qgis/RemoveNullGeometry.py | 65 +
.../processing/algs/qgis/SymmetricalDifference.py | 2 +-
python/plugins/processing/algs/qgis/Union.py | 2 +-
.../algs/qgis/ui/FieldsCalculatorDialog.py | 15 +-
.../processing/algs/qgis/ui/FieldsMappingPanel.py | 48 +-
python/plugins/processing/algs/r/RAlgorithm.py | 2 +-
python/plugins/processing/algs/r/RUtils.py | 9 +-
.../processing/algs/saga/SagaNameDecorator.py | 2 +-
python/plugins/processing/core/GeoAlgorithm.py | 3 +-
python/plugins/processing/core/ProcessingConfig.py | 5 +
python/plugins/processing/core/parameters.py | 6 +-
python/plugins/processing/gui/AlgorithmDialog.py | 42 +
.../plugins/processing/gui/AlgorithmDialogBase.py | 2 +-
python/plugins/processing/gui/AlgorithmExecutor.py | 5 +-
python/plugins/processing/gui/BatchPanel.py | 15 +-
.../processing/gui/ListMultiselectWidget.py | 2 +-
.../plugins/processing/gui/OutputSelectionPanel.py | 35 +-
.../plugins/processing/gui/ScriptEditorDialog.py | 25 +-
.../plugins/processing/modeler/ModelerAlgorithm.py | 15 +-
python/plugins/processing/modeler/ModelerDialog.py | 2 +-
python/plugins/processing/script/ScriptSelector.py | 2 +-
python/plugins/processing/tests/CMakeLists.txt | 1 +
.../plugins/processing/tests/GdalAlgorithmsTest.py | 48 +
python/plugins/processing/tests/ParametersTest.py | 2 +-
python/plugins/processing/tests/ToolsTest.py | 159 +
.../processing/tests/testdata/dissolve_polys.gfs | 31 +
.../processing/tests/testdata/dissolve_polys.gml | 87 +
.../expected/clip_lines_by_multipolygon.gml | 34 +
.../expected/clip_lines_by_multipolygon.xsd | 23 +
.../clip_lines_by_multipolygon_BACKUP_3790.gml | 34 +
.../clip_lines_by_multipolygon_BASE_3790.gml | 34 +
.../clip_lines_by_multipolygon_LOCAL_3790.gml | 0
.../clip_lines_by_multipolygon_REMOTE_3790.gml | 34 +
.../testdata/expected/clip_lines_by_polygon.gml | 24 +
.../testdata/expected/clip_lines_by_polygon.xsd | 23 +
.../expected/clip_multipolygons_by_polygons.gml | 35 +
.../expected/clip_multipolygons_by_polygons.xsd | 43 +
.../expected/clip_points_by_multipolygons.gml | 44 +
.../expected/clip_points_by_multipolygons.xsd | 23 +
.../testdata/expected/clip_points_by_polygons.gml | 44 +
.../testdata/expected/clip_points_by_polygons.xsd | 23 +
.../expected/clip_polys_by_multipolygon.gml | 37 +
.../expected/clip_polys_by_multipolygon.xsd | 43 +
.../tests/testdata/expected/dissolve_field.gml | 50 +
.../tests/testdata/expected/dissolve_field.xsd | 43 +
.../testdata/expected/dissolve_two_fields.gml | 58 +
.../testdata/expected/dissolve_two_fields.xsd | 43 +
.../tests/testdata/expected/lines_boundary.gml | 48 +
.../tests/testdata/expected/lines_boundary.xsd | 23 +
.../tests/testdata/expected/lines_bounds.gml | 48 +
.../tests/testdata/expected/lines_bounds.xsd | 23 +
.../tests/testdata/expected/merge_lines.gml | 33 +
.../tests/testdata/expected/merge_lines.xsd | 23 +
.../tests/testdata/expected/multi_to_single.gml | 48 +
.../tests/testdata/expected/multi_to_single.xsd | 23 +
.../tests/testdata/expected/multiline_boundary.gml | 33 +
.../tests/testdata/expected/multiline_boundary.xsd | 23 +
.../tests/testdata/expected/multiline_bounds.gml | 33 +
.../tests/testdata/expected/multiline_bounds.xsd | 23 +
.../tests/testdata/expected/multipoint_bounds.gml | 43 +
.../tests/testdata/expected/multipoint_bounds.xsd | 30 +
.../tests/testdata/expected/multipoly_boundary.gml | 42 +
.../tests/testdata/expected/multipoly_boundary.xsd | 43 +
.../tests/testdata/expected/multipoly_bounds.gml | 42 +
.../tests/testdata/expected/multipoly_bounds.xsd | 43 +
.../tests/testdata/expected/point_bounds.gml | 59 +
.../tests/testdata/expected/point_bounds.xsd | 23 +
.../tests/testdata/expected/point_on_line.gml | 48 +
.../tests/testdata/expected/point_on_line.xsd | 23 +
.../testdata/expected/point_on_multipoint.gml | 43 +
.../testdata/expected/point_on_multipoint.xsd | 30 +
.../tests/testdata/expected/point_on_poly.gml | 58 +
.../tests/testdata/expected/point_on_poly.xsd | 43 +
.../tests/testdata/expected/poly_boundary.gml | 58 +
.../tests/testdata/expected/poly_boundary.xsd | 43 +
.../tests/testdata/expected/poly_bounds.gml | 58 +
.../tests/testdata/expected/poly_bounds.xsd | 43 +
.../processing/tests/testdata/multilines.gfs | 15 +
.../processing/tests/testdata/multilines.gml | 33 +
.../processing/tests/testdata/multipoints.gfs | 19 +
.../processing/tests/testdata/multipoints.gml | 43 +
.../tests/testdata/qgis_algorithm_tests.yaml | 279 +-
python/plugins/processing/tools/dataobjects.py | 18 +-
python/plugins/processing/tools/postgis.py | 3 +-
python/plugins/processing/tools/vector.py | 101 +-
python/pyplugin_installer/installer_data.py | 2 +-
python/qsci_apis/pyqgis.pap | Bin 1270051 -> 1275750 bytes
python/server/qgswmsconfigparser.sip | 3 +
python/server/qgswmsprojectparser.sip | 4 +
resources/context_help/HeatmapGui | 2 +-
resources/function_help/json/ILIKE | 24 +-
resources/function_help/json/LIKE | 19 +-
resources/function_help/json/angle_at_vertex | 8 +
resources/function_help/json/boundary | 8 +
resources/function_help/json/distance_to_vertex | 8 +
.../function_help/json/line_interpolate_angle | 8 +
.../function_help/json/line_interpolate_point | 8 +
resources/function_help/json/line_locate_point | 8 +
resources/function_help/json/line_merge | 9 +
resources/function_help/json/regexp_match | 4 +-
resources/function_help/json/regexp_replace | 6 +-
resources/function_help/json/regexp_substr | 4 +-
resources/symbology-ng-style.db | Bin 84992 -> 98304 bytes
resources/symbology-ng-style.xml | 24 +
scripts/chkspelling.sh | 2 +-
scripts/generate_test_mask_image.py | 2 +-
scripts/qgm2cpp.pl | 2 +-
scripts/release.pl | 16 +-
src/app/CMakeLists.txt | 13 +-
src/app/composer/qgscomposer.cpp | 2 +-
src/app/composer/qgscomposerlegendwidget.cpp | 34 +-
src/app/composer/qgscomposermapwidget.cpp | 2 +-
src/app/composer/qgscomposerpicturewidget.cpp | 37 +
src/app/composer/qgscomposerpicturewidget.h | 2 +
src/app/gps/qwtpolar-0.1/qwt_polar_plot.cpp | 2 +-
src/app/gps/qwtpolar-1.0/qwt_polar_plot.cpp | 2 +-
src/app/gps/qwtpolar-1.1.1/qwt_polar_plot.cpp | 2 +-
src/app/main.cpp | 8 +
src/app/nodetool/qgsmaptoolnodetool.cpp | 8 +-
src/app/pluginmanager/qgspluginmanager.cpp | 12 +-
src/app/qgisapp.cpp | 73 +-
src/app/qgisapp.h | 3 +
src/app/qgsannotationwidget.cpp | 11 +-
src/app/qgsannotationwidget.h | 2 +-
src/app/qgsapplayertreeviewmenuprovider.cpp | 4 +-
src/app/qgsattributetypedialog.cpp | 84 +-
src/app/qgsattributetypedialog.h | 28 +-
src/app/qgsdiagramproperties.cpp | 105 +-
src/app/qgsdiagramproperties.h | 30 +
src/app/qgsdxfexportdialog.cpp | 27 +-
src/app/qgsdxfexportdialog.h | 4 +
src/app/qgsfeatureaction.cpp | 10 +
src/app/qgsfieldsproperties.cpp | 164 +-
src/app/qgsfieldsproperties.h | 29 +-
src/app/qgsformannotationdialog.cpp | 8 +
src/app/qgsformannotationdialog.h | 1 +
src/app/qgshtmlannotationdialog.cpp | 8 +
src/app/qgshtmlannotationdialog.h | 1 +
src/app/qgsidentifyresultsdialog.cpp | 49 +-
src/app/qgslabelinggui.cpp | 98 +-
src/app/qgslabelinggui.h | 7 +
src/app/qgslabelingwidget.cpp | 1 +
src/app/qgslayerstylingwidget.cpp | 49 +-
src/app/qgsmeasuredialog.cpp | 29 +-
src/app/qgsmergeattributesdialog.cpp | 13 +-
src/app/qgsprojectproperties.cpp | 4 +
src/app/qgsrelationmanagerdialog.cpp | 2 +
src/app/qgsstatusbarcoordinateswidget.cpp | 4 +-
src/app/qgssubstitutionlistwidget.cpp | 230 +
src/app/qgssubstitutionlistwidget.h | 111 +
src/app/qgssvgannotationdialog.cpp | 8 +
src/app/qgssvgannotationdialog.h | 1 +
src/app/qgstextannotationdialog.cpp | 9 +
src/app/qgstextannotationdialog.h | 1 +
src/app/qgsvectorlayerproperties.cpp | 6 +-
src/app/qgsvisibilitypresets.cpp | 6 +-
src/core/CMakeLists.txt | 8 +-
src/core/composer/qgscomposerattributetable.h | 4 +-
src/core/composer/qgscomposerattributetablev2.h | 2 +-
src/core/composer/qgscomposeritem.cpp | 8 +-
src/core/composer/qgscomposeritemcommand.h | 1 +
src/core/composer/qgscomposerlegend.h | 4 +-
src/core/composer/qgscomposermodel.cpp | 2 +-
src/core/composer/qgscomposermousehandles.cpp | 7 +-
src/core/composer/qgscomposerpicture.cpp | 79 +-
src/core/composer/qgscomposerpicture.h | 47 +
src/core/composer/qgscomposition.h | 2 +-
src/core/dxf/qgsdxfexport.cpp | 333 +-
src/core/dxf/qgsdxfexport.h | 18 +-
src/core/effects/qgspainteffect.cpp | 5 +
src/core/geometry/qgsabstractgeometryv2.h | 10 +-
src/core/geometry/qgscircularstringv2.cpp | 3 +
src/core/geometry/qgscurvepolygonv2.cpp | 22 +-
src/core/geometry/qgscurvepolygonv2.h | 1 +
src/core/geometry/qgscurvev2.cpp | 16 +
src/core/geometry/qgscurvev2.h | 2 +
src/core/geometry/qgsgeometry.cpp | 146 +-
src/core/geometry/qgsgeometry.h | 43 +-
src/core/geometry/qgsgeometrycollectionv2.cpp | 5 +
src/core/geometry/qgsgeometrycollectionv2.h | 1 +
src/core/geometry/qgsgeometryutils.cpp | 59 +-
src/core/geometry/qgsgeometryutils.h | 23 +-
src/core/geometry/qgsgeos.cpp | 49 +
src/core/geometry/qgsgeos.h | 21 +
src/core/geometry/qgslinestringv2.cpp | 10 +-
src/core/geometry/qgsmulticurvev2.cpp | 23 +
src/core/geometry/qgsmulticurvev2.h | 3 +
src/core/geometry/qgsmultilinestringv2.cpp | 1 +
src/core/geometry/qgsmultipointv2.cpp | 5 +
src/core/geometry/qgsmultipointv2.h | 2 +
src/core/geometry/qgsmultipolygonv2.cpp | 36 +
src/core/geometry/qgsmultipolygonv2.h | 3 +-
src/core/geometry/qgsmultisurfacev2.cpp | 19 +
src/core/geometry/qgsmultisurfacev2.h | 2 +
src/core/geometry/qgspointv2.cpp | 12 +-
src/core/geometry/qgspointv2.h | 1 +
src/core/geometry/qgspolygonv2.cpp | 23 +
src/core/geometry/qgspolygonv2.h | 2 +
src/core/layertree/qgslayertreemodel.cpp | 97 +-
src/core/layertree/qgslayertreemodel.h | 22 +-
src/core/layertree/qgslayertreemodellegendnode.cpp | 6 +-
src/core/pal/feature.cpp | 800 +-
src/core/pal/feature.h | 65 +-
src/core/pal/labelposition.cpp | 29 +-
src/core/pal/labelposition.h | 6 +
src/core/pal/layer.cpp | 1 +
src/core/pal/layer.h | 4 +
src/core/pal/pal.cpp | 6 +-
src/core/pal/problem.cpp | 2 +-
src/core/pal/util.cpp | 9 +-
src/core/qgsannotation.h | 2 +-
src/core/qgsapplication.cpp | 16 +-
src/core/qgsapplication.h | 4 +-
src/core/qgsbearingutils.cpp | 51 +
src/core/qgsbearingutils.h | 45 +
src/core/qgscolorscheme.cpp | 32 +
src/core/qgscolorscheme.h | 8 +
src/core/qgsdataitem.cpp | 4 +-
src/core/qgsdataitemproviderregistry.cpp | 13 +
src/core/qgseditformconfig.cpp | 149 +-
src/core/qgseditformconfig.h | 126 +-
src/core/qgsexpression.cpp | 163 +-
src/core/qgsexpression.h | 135 +-
src/core/qgsexpressioncontext.cpp | 4 +-
src/core/qgsexpressioncontext.h | 2 +-
src/core/qgsexpressionfieldbuffer.cpp | 5 +
src/core/qgsexpressionfieldbuffer.h | 10 +
src/core/qgsfeedback.h | 73 +
src/core/qgsfield.cpp | 41 +-
src/core/qgsfield.h | 61 +-
src/core/qgsfield_p.h | 11 +-
src/core/qgsgeometryvalidator.cpp | 24 +-
src/core/qgsgml.cpp | 18 +-
src/core/qgslabelfeature.h | 6 +-
src/core/qgslabelingenginev2.cpp | 12 +-
src/core/qgslegendrenderer.cpp | 3 +-
src/core/qgsmaplayer.cpp | 4 +-
src/core/qgsmaplayerrenderer.h | 6 +
src/core/qgsmaprenderercustompainterjob.cpp | 21 +-
src/core/qgsmaprendererjob.cpp | 7 +
src/core/qgsmaprendererjob.h | 1 +
src/core/qgsmaprendererparalleljob.cpp | 11 +-
src/core/qgsmapsettings.h | 3 +-
src/core/qgsmimedatautils.h | 2 +
src/core/qgsnetworkaccessmanager.cpp | 17 +-
src/core/qgsofflineediting.cpp | 75 +-
src/core/qgsofflineediting.h | 13 +-
src/core/qgsogcutils.cpp | 85 +-
src/core/qgsogrutils.cpp | 2 +-
src/core/qgsoptional.h | 137 +
src/core/qgsoptionalexpression.cpp | 48 +
src/core/qgsoptionalexpression.h | 76 +
src/core/qgspallabeling.cpp | 144 +-
src/core/qgspallabeling.h | 7 +
src/core/qgspointlocator.cpp | 14 +
src/core/qgsproject.cpp | 10 +
src/core/qgsproject.h | 12 +-
src/core/qgsprojectproperty.cpp | 12 +
src/core/qgsprojectproperty.h | 14 +-
src/core/qgsproviderregistry.cpp | 5 +-
src/core/qgsrendercontext.cpp | 1 +
src/core/qgsrendercontext.h | 1 +
src/core/qgsstringutils.cpp | 128 +
src/core/qgsstringutils.h | 149 +-
src/core/qgsvectorlayer.cpp | 288 +-
src/core/qgsvectorlayer.h | 55 +-
src/core/qgsvectorlayereditbuffer.cpp | 4 +-
src/core/qgsvectorlayerfeatureiterator.cpp | 32 +-
src/core/qgsvectorlayerrenderer.cpp | 14 -
src/core/qgsvectorlayerrenderer.h | 1 -
src/core/qgswebpage.h | 2 +
src/core/qgswebview.h | 12 +-
src/core/raster/qgsbrightnesscontrastfilter.cpp | 7 +-
src/core/raster/qgsbrightnesscontrastfilter.h | 1 +
src/core/raster/qgshillshaderenderer.cpp | 9 +-
src/core/raster/qgshillshaderenderer.h | 1 +
src/core/raster/qgshuesaturationfilter.cpp | 7 +-
src/core/raster/qgshuesaturationfilter.h | 1 +
src/core/raster/qgsmultibandcolorrenderer.cpp | 7 +-
src/core/raster/qgsmultibandcolorrenderer.h | 1 +
src/core/raster/qgspalettedrasterrenderer.cpp | 9 +-
src/core/raster/qgspalettedrasterrenderer.h | 1 +
src/core/raster/qgsrasterdataprovider.cpp | 9 +-
src/core/raster/qgsrasterdataprovider.h | 5 +-
src/core/raster/qgsrasterdrawer.cpp | 22 +-
src/core/raster/qgsrasterdrawer.h | 4 +-
src/core/raster/qgsrasterinterface.h | 59 +
src/core/raster/qgsrasteriterator.cpp | 6 +-
src/core/raster/qgsrasteriterator.h | 5 +-
src/core/raster/qgsrasterlayer.cpp | 4 +-
src/core/raster/qgsrasterlayerrenderer.cpp | 43 +-
src/core/raster/qgsrasterlayerrenderer.h | 31 +
src/core/raster/qgsrasternuller.cpp | 7 +-
src/core/raster/qgsrasternuller.h | 1 +
src/core/raster/qgsrasterpipe.h | 1 +
src/core/raster/qgsrasterprojector.cpp | 256 +-
src/core/raster/qgsrasterprojector.h | 109 +-
src/core/raster/qgsrasterrenderer.h | 2 -
src/core/raster/qgsrasterresamplefilter.cpp | 9 +-
src/core/raster/qgsrasterresamplefilter.h | 1 +
src/core/raster/qgssinglebandcolordatarenderer.cpp | 7 +-
src/core/raster/qgssinglebandcolordatarenderer.h | 1 +
src/core/raster/qgssinglebandgrayrenderer.cpp | 9 +-
src/core/raster/qgssinglebandgrayrenderer.h | 1 +
.../raster/qgssinglebandpseudocolorrenderer.cpp | 9 +-
src/core/raster/qgssinglebandpseudocolorrenderer.h | 1 +
src/core/symbology-ng/qgsarrowsymbollayer.cpp | 12 +-
.../qgscategorizedsymbolrendererv2.cpp | 15 +-
.../qgsgeometrygeneratorsymbollayerv2.cpp | 2 +
src/core/symbology-ng/qgslinesymbollayerv2.cpp | 36 +-
src/core/symbology-ng/qgsmarkersymbollayerv2.cpp | 4 +-
src/gui/CMakeLists.txt | 23 +-
.../qgsattributetablefiltermodel.cpp | 2 +-
src/gui/attributetable/qgsattributetablemodel.cpp | 7 +-
src/gui/attributetable/qgsdualview.cpp | 9 +-
src/gui/editorwidgets/core/qgseditorconfigwidget.h | 7 +
src/gui/editorwidgets/qgscheckboxconfigdlg.cpp | 3 +
src/gui/editorwidgets/qgsdatetimeeditconfig.cpp | 5 +
src/gui/editorwidgets/qgsdoublespinbox.cpp | 36 +-
src/gui/editorwidgets/qgsdoublespinbox.h | 48 +-
.../editorwidgets/qgsexternalresourceconfigdlg.cpp | 14 +
src/gui/editorwidgets/qgsphotoconfigdlg.cpp | 2 +
src/gui/editorwidgets/qgsrangeconfigdlg.cpp | 10 +
.../qgsrelationreferenceconfigdlg.cpp | 14 +-
.../qgsrelationreferencesearchwidgetwrapper.cpp | 6 +
.../editorwidgets/qgsrelationreferencewidget.cpp | 24 +-
src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp | 36 +
src/gui/editorwidgets/qgsrelationwidgetwrapper.h | 42 +
src/gui/editorwidgets/qgsspinbox.cpp | 36 +-
src/gui/editorwidgets/qgsspinbox.h | 49 +-
src/gui/editorwidgets/qgstexteditconfigdlg.cpp | 2 +
src/gui/editorwidgets/qgstexteditwrapper.cpp | 10 +
src/gui/editorwidgets/qgsuniquevaluesconfigdlg.cpp | 1 +
src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp | 3 +
.../editorwidgets/qgsvaluerelationconfigdlg.cpp | 9 +
.../qgsvaluerelationwidgetfactory.cpp | 2 -
src/gui/editorwidgets/qgswebviewconfigdlg.cpp | 2 +
src/gui/effects/qgseffectstackpropertieswidget.cpp | 14 +-
src/gui/layertree/qgslayertreeview.cpp | 50 +-
src/gui/layertree/qgslayertreeview.h | 8 +
src/gui/qgsattributeform.cpp | 111 +-
src/gui/qgsattributeform.h | 35 +
src/gui/qgscolorbuttonv2.cpp | 32 +-
src/gui/qgscolorbuttonv2.h | 9 +
src/gui/qgscolorschemelist.cpp | 5 +
src/gui/qgscolorschemelist.h | 7 +
src/gui/qgscolorwidgets.cpp | 21 +
src/gui/qgscolorwidgets.h | 1 +
src/gui/qgscomposeritemcombobox.cpp | 2 +-
src/gui/qgscompoundcolorwidget.cpp | 68 +-
src/gui/qgscompoundcolorwidget.h | 20 +-
src/gui/qgsexpressionbuilderwidget.cpp | 21 +-
src/gui/qgsexpressionbuilderwidget.h | 14 +
src/gui/qgsexpressionlineedit.cpp | 214 +
src/gui/qgsexpressionlineedit.h | 143 +
src/gui/qgsfieldexpressionwidget.cpp | 10 +
src/gui/qgsfieldexpressionwidget.h | 22 +-
src/gui/qgsfilterlineedit.cpp | 149 +-
src/gui/qgsfilterlineedit.h | 168 +-
src/gui/qgshighlight.cpp | 79 +-
src/gui/qgshtmlannotationitem.cpp | 60 +-
src/gui/qgsidentifymenu.cpp | 8 +-
src/gui/qgsmapcanvas.cpp | 12 +-
src/gui/qgsmapoverviewcanvas.cpp | 13 +-
src/gui/qgsmessagebar.cpp | 2 +-
src/gui/qgsmessagebaritem.cpp | 2 +-
src/gui/qgspanelwidget.cpp | 25 +-
src/gui/qgspanelwidget.h | 15 +-
src/gui/qgsprojectionselector.cpp | 6 +-
src/gui/qgsrasterlayersaveasdialog.cpp | 2 +-
src/gui/qgsrelationeditorwidget.cpp | 41 +-
src/gui/qgsrelationeditorwidget.h | 42 +
src/gui/qgsscalecombobox.cpp | 4 +-
src/gui/qgsscalecombobox.h | 8 +-
src/gui/qgsscalerangewidget.cpp | 16 +-
src/gui/qgsscalerangewidget.h | 16 +-
src/gui/qgsscalewidget.cpp | 6 +-
src/gui/qgsscalewidget.h | 2 +-
src/gui/qgssourceselectdialog.cpp | 21 -
src/gui/qgssourceselectdialog.h | 2 -
src/gui/qgstabwidget.cpp | 159 +
src/gui/qgstabwidget.h | 119 +
src/gui/raster/qgsrastertransparencywidget.cpp | 11 +-
.../raster/qgsrendererrasterpropertieswidget.cpp | 1 +
.../qgssinglebandpseudocolorrendererwidget.cpp | 15 +-
.../qgscategorizedsymbolrendererv2widget.cpp | 10 +-
.../qgsgraduatedsymbolrendererv2widget.cpp | 10 +-
.../symbology-ng/qgsrulebasedrendererv2widget.cpp | 29 +-
src/gui/symbology-ng/qgsstylev2managerdialog.cpp | 2 +-
src/gui/symbology-ng/qgssvgselectorwidget.cpp | 306 +-
src/gui/symbology-ng/qgssvgselectorwidget.h | 161 +-
src/gui/symbology-ng/qgssymbollayerv2widget.cpp | 152 +-
src/gui/symbology-ng/qgssymbollayerv2widget.h | 33 -
.../qgsvectorgradientcolorrampv2dialog.cpp | 10 +-
.../coordinate_capture/coordinatecapture.cpp | 4 +-
.../coordinate_capture/coordinatecapture.qrc | 4 +-
.../coordinatecapturemaptool.cpp | 2 +-
src/plugins/coordinate_capture/tracking.png | Bin 2165 -> 0 bytes
src/plugins/coordinate_capture/transformed.png | Bin 3344 -> 0 bytes
.../dxf2shp_converter/dxflib/src/dl_entities.h | 2 +-
src/plugins/evis/README.TXT | 2 +-
.../evisdatabaseconnectiongui.cpp | 4 +-
.../eventbrowser/evisgenericeventbrowsergui.cpp | 4 +-
.../evis/ui/evisdatabaseconnectionguibase.ui | 4 +-
.../evis/ui/evisgenericeventbrowserguibase.ui | 4 +-
.../georeferencer/qgsgeorefpluginguibase.ui | 2 +-
src/plugins/globe/globe_plugin.cpp | 4 +-
src/plugins/grass/qgsgrassplugin.cpp | 6 +-
src/plugins/grass/qgsgrasstools.cpp | 4 +-
src/plugins/interpolation/interpolator.qrc | 3 +-
src/plugins/interpolation/options.png | Bin 3797 -> 0 bytes
.../interpolation/qgsinterpolationdialogbase.ui | 6 +-
.../offline_editing/offline_editing_plugin.cpp | 2 +-
.../offline_editing/offline_editing_plugin_gui.cpp | 7 +-
.../offline_editing/offline_editing_plugin_gui.h | 3 +-
.../offline_editing_plugin_guibase.ui | 11 +-
src/plugins/roadgraph/shortestpathwidget.cpp | 6 -
src/providers/arcgisrest/qgsafssourceselect.cpp | 4 +
src/providers/arcgisrest/qgsamsprovider.cpp | 4 +-
src/providers/arcgisrest/qgsamsprovider.h | 2 +-
src/providers/arcgisrest/qgsamssourceselect.cpp | 4 +
src/providers/db2/qgsdb2tablemodel.cpp | 2 +-
src/providers/gdal/qgsgdalprovider.cpp | 14 +-
src/providers/gdal/qgsgdalprovider.h | 3 +-
src/providers/gdal/qgsgdalproviderbase.cpp | 29 +-
src/providers/gdal/qgsgdalproviderbase.h | 2 +-
src/providers/grass/qgsgrassrasterprovider.cpp | 3 +-
src/providers/grass/qgsgrassrasterprovider.h | 2 +-
src/providers/mssql/qgsmssqltablemodel.cpp | 2 +-
src/providers/ogr/qgsogrfeatureiterator.cpp | 11 +-
src/providers/ogr/qgsogrprovider.cpp | 48 +-
src/providers/ogr/qgsogrprovider.h | 4 +
src/providers/oracle/qgsoracleprovider.cpp | 38 +-
src/providers/oracle/qgsoracletablemodel.cpp | 2 +-
src/providers/postgres/qgspgtablemodel.cpp | 4 +-
src/providers/postgres/qgspostgresprovider.cpp | 230 +-
src/providers/postgres/qgspostgresprovider.h | 14 +-
.../virtual/qgsvirtuallayersourceselectbase.ui | 2 +-
src/providers/wcs/qgswcscapabilities.cpp | 35 +
src/providers/wcs/qgswcscapabilities.h | 3 +
src/providers/wcs/qgswcsprovider.cpp | 106 +-
src/providers/wcs/qgswcsprovider.h | 19 +-
src/providers/wfs/qgswfscapabilities.cpp | 4 +-
src/providers/wfs/qgswfscapabilities.h | 2 +-
src/providers/wfs/qgswfsconstants.cpp | 2 +-
src/providers/wfs/qgswfsdataitems.cpp | 4 +-
src/providers/wfs/qgswfsdatasourceuri.cpp | 47 +-
src/providers/wfs/qgswfsdatasourceuri.h | 20 +-
src/providers/wfs/qgswfsfeatureiterator.cpp | 7 +-
src/providers/wfs/qgswfsprovider.cpp | 17 +-
src/providers/wfs/qgswfsrequest.cpp | 23 +
src/providers/wfs/qgswfssourceselect.cpp | 4 +-
src/providers/wfs/qgswfsutils.cpp | 4 +-
src/providers/wms/CMakeLists.txt | 2 +
src/providers/wms/qgstilecache.cpp | 57 +
src/providers/wms/qgstilecache.h | 56 +
src/providers/wms/qgswmscapabilities.cpp | 156 +-
src/providers/wms/qgswmscapabilities.h | 82 +-
src/providers/wms/qgswmsdataitems.cpp | 127 +-
src/providers/wms/qgswmsdataitems.h | 60 +
src/providers/wms/qgswmsprovider.cpp | 968 +-
src/providers/wms/qgswmsprovider.h | 89 +-
src/providers/wms/qgsxyzconnection.cpp | 59 +
src/providers/wms/qgsxyzconnection.h | 47 +
src/python/qgspythonutilsimpl.cpp | 40 +-
src/server/qgsconfigparserutils.cpp | 10 +-
src/server/qgshostedrdsbuilder.cpp | 2 +-
src/server/qgsowsserver.cpp | 4 +-
src/server/qgsremoteowsbuilder.cpp | 4 +-
src/server/qgsserver.cpp | 4 +-
src/server/qgsserverlogger.cpp | 3 +
src/server/qgsserverprojectparser.cpp | 14 +-
src/server/qgsserverprojectparser.h | 1 +
src/server/qgssldconfigparser.cpp | 9 +
src/server/qgssldconfigparser.h | 3 +
src/server/qgswcsprojectparser.cpp | 4 +-
src/server/qgswcsserver.cpp | 2 +-
src/server/qgswfsprojectparser.cpp | 6 +-
src/server/qgswfsserver.cpp | 12 +-
src/server/qgswmsconfigparser.h | 3 +
src/server/qgswmsprojectparser.cpp | 38 +-
src/server/qgswmsprojectparser.h | 3 +
src/server/qgswmsserver.cpp | 73 +-
src/ui/auth/qgsauthauthoritieseditor.ui | 6 +-
src/ui/auth/qgsauthconfigeditor.ui | 4 +-
src/ui/auth/qgsauthconfigselect.ui | 2 +-
src/ui/auth/qgsauthidentitieseditor.ui | 4 +-
src/ui/auth/qgsauthserverseditor.ui | 4 +-
src/ui/composer/qgsattributeselectiondialogbase.ui | 2 +-
src/ui/composer/qgscomposerpicturewidgetbase.ui | 39 +-
src/ui/qgisapp.ui | 15 +-
src/ui/qgsattributeactiondialogbase.ui | 2 +-
src/ui/qgsattributetabledialog.ui | 12 +-
src/ui/qgsattributetypeedit.ui | 159 +-
src/ui/qgscategorizedsymbolrendererv2widget.ui | 4 +-
src/ui/qgscompoundcolorwidget.ui | 1154 +-
src/ui/qgsdualviewbase.ui | 2 +-
src/ui/qgsdxfexportdialogbase.ui | 70 +-
src/ui/qgserrordialogbase.ui | 2 +-
src/ui/qgsfieldconditionalformatwidget.ui | 2 +-
src/ui/qgsformannotationdialogbase.ui | 2 +-
src/ui/qgsgraduatedsymbolrendererv2widget.ui | 6 +-
src/ui/qgslabelingguibase.ui | 624 +-
src/ui/qgsnewgeopackagelayerdialogbase.ui | 4 +-
src/ui/qgsnewspatialitelayerdialogbase.ui | 4 +-
src/ui/qgsnewvectorlayerdialogbase.ui | 4 +-
src/ui/qgsprojectpropertiesbase.ui | 149 +-
src/ui/qgssqlcomposerdialogbase.ui | 4 +-
src/ui/qgsstylev2managerdialogbase.ui | 8 +-
src/ui/qgssubstitutionlistwidgetbase.ui | 134 +
src/ui/qgstextannotationdialogbase.ui | 4 +-
src/ui/qgsunitselectionwidget.ui | 6 +-
src/ui/qgsvectorlayerpropertiesbase.ui | 2 +-
src/ui/symbollayer/widget_svgfill.ui | 15 +
tests/src/app/testqgisapppython.cpp | 4 +
tests/src/core/testqgs25drenderer.cpp | 1 +
tests/src/core/testqgsexpression.cpp | 38 +-
tests/src/core/testqgsfield.cpp | 50 +
tests/src/core/testqgsgeometry.cpp | 334 +-
tests/src/core/testqgsgeometryutils.cpp | 101 +
tests/src/core/testqgslabelingenginev2.cpp | 42 +
tests/src/core/testqgslegendrenderer.cpp | 23 +
tests/src/core/testqgsmarkerlinesymbol.cpp | 65 +
tests/src/core/testqgsogcutils.cpp | 220 +-
tests/src/core/testqgspointlocator.cpp | 43 +
tests/src/core/testqgsstringutils.cpp | 36 +
tests/src/python/CMakeLists.txt | 9 +
tests/src/python/offlineditingtestbase.py | 5 +-
tests/src/python/qgis_wrapped_server.py | 67 +-
tests/src/python/test_authmanager_endpoint.py | 182 +
tests/src/python/test_offline_editing_wfs.py | 66 +-
tests/src/python/test_provider_ogr.py | 19 +
tests/src/python/test_provider_ogr_gpkg.py | 46 +-
tests/src/python/test_provider_postgres.py | 80 +
tests/src/python/test_provider_shapefile.py | 101 +
tests/src/python/test_provider_wfs.py | 34 +-
tests/src/python/test_provider_wfs_gui.py | 4 +-
tests/src/python/test_qgsbearingutils.py | 60 +
tests/src/python/test_qgscolorscheme.py | 29 +-
tests/src/python/test_qgscomposerpicture.py | 63 +-
tests/src/python/test_qgseditwidgets.py | 32 +-
tests/src/python/test_qgsexpression.py | 8 +
tests/src/python/test_qgsexpressionlineedit.py | 78 +
tests/src/python/test_qgsfilterlineedit.py | 136 +
tests/src/python/test_qgsgeometry.py | 155 +
tests/src/python/test_qgsgeometryvalidator.py | 71 +
tests/src/python/test_qgsoptional.py | 59 +
tests/src/python/test_qgspallabeling_base.py | 3 +-
tests/src/python/test_qgspallabeling_placement.py | 161 +
tests/src/python/test_qgspanelwidget.py | 60 +
tests/src/python/test_qgsserver.py | 107 +-
tests/src/python/test_qgsserver_wfst.py | 23 +-
tests/src/python/test_qgsstringutils.py | 181 +
tests/src/python/test_qgstabwidget.py | 88 +
tests/src/python/test_qgsvectorlayer.py | 215 +-
tests/src/python/utilities.py | 30 +-
.../expected_composerpaper_markerborder_mask.png | Bin 18524 -> 18639 bytes
.../sp_letter_spacing/sp_letter_spacing_mask.png | Bin 1857 -> 1779 bytes
.../sp_word_spacing/sp_word_spacing_mask.png | Bin 1857 -> 1749 bytes
.../sp_curved_placement_above.png | Bin 12116 -> 12196 bytes
.../sp_curved_placement_above_mask.png | Bin 3494 -> 9496 bytes
.../sp_curved_placement_below.png | Bin 12044 -> 12047 bytes
.../sp_curved_placement_below_mask.png | Bin 3625 -> 9999 bytes
.../sp_curved_placement_online.png | Bin 11014 -> 10889 bytes
.../sp_curved_placement_online_mask.png | Bin 10684 -> 8546 bytes
.../sp_line_placement_above_line_orientation.png | Bin 13178 -> 12019 bytes
..._line_placement_above_line_orientation_mask.png | Bin 10006 -> 3626 bytes
.../sp_line_placement_above_map_orientation.png | Bin 12909 -> 11684 bytes
...p_line_placement_above_map_orientation_mask.png | Bin 7882 -> 3477 bytes
.../sp_line_placement_below_line_orientation.png | Bin 12909 -> 11684 bytes
..._line_placement_below_line_orientation_mask.png | Bin 7343 -> 3477 bytes
.../sp_line_placement_below_map_orientation.png | Bin 13178 -> 12019 bytes
...p_line_placement_below_map_orientation_mask.png | Bin 7222 -> 3626 bytes
.../sp_line_placement_online.png | Bin 12343 -> 11480 bytes
.../sp_line_placement_online_mask.png | Bin 7389 -> 3496 bytes
.../sp_img_letter_spacing_mask.png | Bin 1868 -> 1779 bytes
.../sp_img_word_spacing_mask.png | Bin 1864 -> 1749 bytes
.../sp_img_curved_placement_above.png | Bin 12116 -> 12196 bytes
.../sp_img_curved_placement_above_mask.png | Bin 3494 -> 11097 bytes
.../sp_img_curved_placement_below.png | Bin 12044 -> 12047 bytes
.../sp_img_curved_placement_below_mask.png | Bin 3625 -> 9269 bytes
.../sp_img_curved_placement_online.png | Bin 11014 -> 10889 bytes
.../sp_img_curved_placement_online_mask.png | Bin 3398 -> 7219 bytes
...p_img_line_placement_above_line_orientation.png | Bin 13178 -> 12019 bytes
..._line_placement_above_line_orientation_mask.png | Bin 9380 -> 3703 bytes
...sp_img_line_placement_above_map_orientation.png | Bin 12909 -> 11684 bytes
...g_line_placement_above_map_orientation_mask.png | Bin 8793 -> 3650 bytes
...p_img_line_placement_below_line_orientation.png | Bin 12909 -> 11684 bytes
..._line_placement_below_line_orientation_mask.png | Bin 9316 -> 3650 bytes
...sp_img_line_placement_below_map_orientation.png | Bin 13178 -> 12019 bytes
...g_line_placement_below_map_orientation_mask.png | Bin 9285 -> 3703 bytes
.../sp_img_line_placement_online.png | Bin 12343 -> 11480 bytes
.../sp_img_line_placement_online_mask.png | Bin 14408 -> 3496 bytes
.../sp_pdf_curved_placement_above.png | Bin 11536 -> 11694 bytes
.../sp_pdf_curved_placement_above_mask.png | Bin 3645 -> 9553 bytes
.../sp_pdf_curved_placement_below.png | Bin 11542 -> 11507 bytes
.../sp_pdf_curved_placement_below_mask.png | Bin 3552 -> 9322 bytes
.../sp_pdf_curved_placement_online.png | Bin 10775 -> 10528 bytes
.../sp_pdf_curved_placement_online_mask.png | Bin 3416 -> 8385 bytes
...p_pdf_line_placement_above_line_orientation.png | Bin 10998 -> 11456 bytes
..._line_placement_above_line_orientation_mask.png | Bin 14579 -> 3686 bytes
...sp_pdf_line_placement_above_map_orientation.png | Bin 10797 -> 11252 bytes
...f_line_placement_above_map_orientation_mask.png | Bin 14523 -> 3570 bytes
...p_pdf_line_placement_below_line_orientation.png | Bin 10797 -> 11252 bytes
..._line_placement_below_line_orientation_mask.png | Bin 14523 -> 3570 bytes
...sp_pdf_line_placement_below_map_orientation.png | Bin 10998 -> 11456 bytes
...f_line_placement_below_map_orientation_mask.png | Bin 14579 -> 3686 bytes
.../sp_pdf_line_placement_online.png | Bin 10325 -> 11089 bytes
.../sp_pdf_line_placement_online_mask.png | Bin 14301 -> 3556 bytes
.../sp_svg_curved_placement_above.png | Bin 12108 -> 12218 bytes
.../sp_svg_curved_placement_above_mask.png | Bin 3503 -> 8664 bytes
.../sp_svg_curved_placement_below.png | Bin 12035 -> 12048 bytes
.../sp_svg_curved_placement_below_mask.png | Bin 3427 -> 8162 bytes
.../sp_svg_curved_placement_online.png | Bin 11028 -> 10890 bytes
.../sp_svg_curved_placement_online_mask.png | Bin 3044 -> 7593 bytes
...p_svg_line_placement_above_line_orientation.png | Bin 13171 -> 12022 bytes
..._line_placement_above_line_orientation_mask.png | Bin 8221 -> 3639 bytes
...sp_svg_line_placement_above_map_orientation.png | Bin 12916 -> 11765 bytes
...g_line_placement_above_map_orientation_mask.png | Bin 7727 -> 3505 bytes
...p_svg_line_placement_below_line_orientation.png | Bin 12916 -> 11765 bytes
..._line_placement_below_line_orientation_mask.png | Bin 8126 -> 3505 bytes
...sp_svg_line_placement_below_map_orientation.png | Bin 13171 -> 12022 bytes
...g_line_placement_below_map_orientation_mask.png | Bin 8230 -> 3639 bytes
.../sp_svg_line_placement_online.png | Bin 12359 -> 11420 bytes
.../sp_svg_line_placement_online_mask.png | Bin 7696 -> 3457 bytes
.../sp_label_line_avoid_jaggy.png | Bin 0 -> 5018 bytes
.../sp_label_line_avoid_jaggy_mask.png | Bin 0 -> 1143 bytes
.../sp_label_line_over_small_angles.png | Bin 0 -> 3239 bytes
.../sp_label_line_over_small_angles_mask.png | Bin 0 -> 1521 bytes
.../sp_label_line_toward_center.png | Bin 0 -> 2485 bytes
.../sp_label_line_toward_center_mask.png | Bin 0 -> 1226 bytes
...placement_around_obstacle_large_symbol_mask.png | Bin 1390 -> 1299 bytes
.../sp_polygon_placement_perimeter.png | Bin 0 -> 1310 bytes
.../sp_polygon_placement_perimeter_mask.png | Bin 0 -> 1021 bytes
..._polygon_placement_with_hole_and_point_mask.png | Bin 886 -> 880 bytes
.../sp_prefer_line_above_instead_of_below.png | Bin 0 -> 6902 bytes
.../sp_prefer_line_above_instead_of_below_mask.png | Bin 0 -> 2545 bytes
.../sp_prefer_line_above_instead_of_online.png | Bin 0 -> 6902 bytes
...sp_prefer_line_above_instead_of_online_mask.png | Bin 0 -> 2545 bytes
.../sp_prefer_line_below_instead_of_online.png | Bin 0 -> 7092 bytes
...sp_prefer_line_below_instead_of_online_mask.png | Bin 0 -> 2592 bytes
...p_prefer_line_curved_above_instead_of_below.png | Bin 0 -> 7989 bytes
...fer_line_curved_above_instead_of_below_mask.png | Bin 0 -> 2938 bytes
..._prefer_line_curved_above_instead_of_online.png | Bin 0 -> 7989 bytes
...er_line_curved_above_instead_of_online_mask.png | Bin 0 -> 2938 bytes
..._prefer_line_curved_below_instead_of_online.png | Bin 0 -> 7822 bytes
...er_line_curved_below_instead_of_online_mask.png | Bin 0 -> 2831 bytes
.../sp_prefer_longer_lines_over_shorter.png | Bin 0 -> 2719 bytes
.../sp_prefer_longer_lines_over_shorter_mask.png | Bin 0 -> 1808 bytes
.../sp_prefer_more_horizontal_lines.png | Bin 0 -> 4171 bytes
.../sp_prefer_more_horizontal_lines_mask.png | Bin 0 -> 1790 bytes
.../sp_small_polygon_curvedperimeter_only_fit.png | Bin 0 -> 1257 bytes
...small_polygon_curvedperimeter_only_fit_mask.png | Bin 0 -> 991 bytes
.../sp_small_polygon_over_point_only_fit.png | Bin 0 -> 1257 bytes
.../sp_small_polygon_over_point_only_fit_mask.png | Bin 0 -> 991 bytes
.../sp_small_polygon_perimeter_only_fit.png | Bin 0 -> 1257 bytes
.../sp_small_polygon_perimeter_only_fit_mask.png | Bin 0 -> 991 bytes
.../sp_small_polygon_placement_perimeter.png | Bin 0 -> 1496 bytes
.../sp_small_polygon_placement_perimeter_mask.png | Bin 0 -> 1117 bytes
.../sp_letter_spacing/sp_letter_spacing_mask.png | Bin 1876 -> 1741 bytes
.../sp_word_spacing/sp_word_spacing_mask.png | Bin 1974 -> 1764 bytes
.../sp_curved_placement_above.png | Bin 12139 -> 12194 bytes
.../sp_curved_placement_above_mask.png | Bin 2680 -> 6650 bytes
.../sp_curved_placement_below.png | Bin 12047 -> 12050 bytes
.../sp_curved_placement_below_mask.png | Bin 2648 -> 7727 bytes
.../sp_curved_placement_online.png | Bin 11016 -> 10890 bytes
.../sp_curved_placement_online_mask.png | Bin 2760 -> 6996 bytes
.../sp_line_placement_above_line_orientation.png | Bin 13178 -> 12022 bytes
..._line_placement_above_line_orientation_mask.png | Bin 11732 -> 2765 bytes
.../sp_line_placement_above_map_orientation.png | Bin 12909 -> 11684 bytes
...p_line_placement_above_map_orientation_mask.png | Bin 11664 -> 2627 bytes
.../sp_line_placement_below_line_orientation.png | Bin 12909 -> 11684 bytes
..._line_placement_below_line_orientation_mask.png | Bin 11664 -> 2627 bytes
.../sp_line_placement_below_map_orientation.png | Bin 13178 -> 12022 bytes
...p_line_placement_below_map_orientation_mask.png | Bin 11732 -> 2765 bytes
.../sp_line_placement_online.png | Bin 12343 -> 11481 bytes
.../sp_line_placement_online_mask.png | Bin 11865 -> 2482 bytes
.../expected_vector_layertransparency_mask.png | Bin 11487 -> 11815 bytes
.../expected_labeling_basic.png | Bin 24392 -> 24314 bytes
.../expected_labeling_basic_mask.png | Bin 21234 -> 7558 bytes
.../expected_legend_3_by_2_mask.png | Bin 1491 -> 1798 bytes
.../expected_legend_3_by_3_mask.png | Bin 1526 -> 1633 bytes
.../expected_legend_4_by_2_mask.png | Bin 1676 -> 2189 bytes
.../expected_legend_4_by_3_mask.png | Bin 1855 -> 2197 bytes
.../expected_legend_5_by_2_mask.png | Bin 1964 -> 2467 bytes
.../expected_legend_5_by_3_mask.png | Bin 2045 -> 2583 bytes
.../expected_legend_6_by_3_mask.png | Bin 2226 -> 2907 bytes
.../expected_legend_7_by_3_mask.png | Bin 2539 -> 3127 bytes
.../expected_legend_diagram_attributes.png | Bin 5729 -> 5235 bytes
.../expected_legend_diagram_attributes_mask.png | Bin 2374 -> 6304 bytes
.../expected_legend_diagram_size.png | Bin 14032 -> 13493 bytes
.../expected_legend_diagram_size_mask.png | Bin 3467 -> 15205 bytes
.../expected_legend_filter_by_map_mask.png | Bin 8402 -> 8843 bytes
.../expected_legend_tall_symbol.png | Bin 0 -> 20452 bytes
.../expected_legend_tall_symbol_mask.png | Bin 0 -> 23530 bytes
.../expected_lines-parallel-label+45.png | Bin 40258 -> 3716 bytes
.../expected_lines-parallel-label+45_mask.png | Bin 3062 -> 1122 bytes
.../WMS_GetLegendGraphic_test.png | Bin 0 -> 2962 bytes
.../WMS_GetLegendGraphic_test_mask.png | Bin 0 -> 265 bytes
.../WMS_GetLegendGraphic_test_layertitle_false.png | Bin 0 -> 355 bytes
...GetLegendGraphic_test_layertitle_false_mask.png | Bin 0 -> 166 bytes
.../expected_filledmarker_mask.png | Bin 4499 -> 4514 bytes
.../expected_filledmarker_bounds_mask.png | Bin 2383 -> 2387 bytes
.../expected_point_num_interval.png | Bin 0 -> 2765 bytes
.../expected_point_num_interval_mask.png | Bin 0 -> 981 bytes
.../expected_point_num_vertex.png | Bin 0 -> 1650 bytes
.../expected_point_num_vertex_mask.png | Bin 0 -> 719 bytes
tests/testdata/labeling/line_placement_1.qml | 272 +
tests/testdata/labeling/line_placement_2.qml | 273 +
tests/testdata/labeling/line_placement_3.qml | 273 +
tests/testdata/labeling/line_placement_4.qml | 273 +
tests/testdata/labeling/line_placement_5.qml | 249 +
tests/testdata/labeling/pal_features_v3.sqlite | Bin 144384 -> 198656 bytes
tests/testdata/labeling/polygon_perimeter.qml | 272 +
tests/testdata/labeling/polygon_small.qml | 272 +
tests/testdata/qgis_server/getcapabilities.txt | 18 +-
tests/testdata/qgis_server/getprojectsettings.txt | 23 +-
.../{test+project.qgs => test_project.qgs} | 239 +-
...roject_inspire.qgs => test_project_inspire.qgs} | 0
.../{test+project_wfs.qgs => test_project_wfs.qgs} | 0
.../qgis_server/wms_getfeatureinfo-text-html.txt | 2 +-
884 files changed, 33398 insertions(+), 11426 deletions(-)
diff --git a/.editorconfig b/.editorconfig
index 88bac2d..154ed65 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,3 +11,7 @@ trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 2
+
+# python scripts have 4 spaces indent
+[*.py]
+indent_size = 4
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e8d88c3..834f3b7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,8 +1,8 @@
SET(CPACK_PACKAGE_VERSION_MAJOR "2")
-SET(CPACK_PACKAGE_VERSION_MINOR "16")
-SET(CPACK_PACKAGE_VERSION_PATCH "3")
+SET(CPACK_PACKAGE_VERSION_MINOR "18")
+SET(CPACK_PACKAGE_VERSION_PATCH "0")
SET(COMPLETE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
-SET(RELEASE_NAME "Nødebo")
+SET(RELEASE_NAME "Las Palmas")
IF (POLICY CMP0048) # in CMake 3.0.0+
CMAKE_POLICY (SET CMP0048 OLD) # keep PROJECT() from clearing VERSION variables
ENDIF (POLICY CMP0048)
diff --git a/CTestConfig.cmake b/CTestConfig.cmake
index c592023..63d849a 100644
--- a/CTestConfig.cmake
+++ b/CTestConfig.cmake
@@ -7,7 +7,7 @@
set(CTEST_PROJECT_NAME "QGIS")
set(CTEST_NIGHTLY_START_TIME "20:00:00 CEST")
-set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_METHOD "https")
set(CTEST_DROP_SITE "dash.orfeo-toolbox.org")
set(CTEST_DROP_LOCATION "/submit.php?project=QGIS")
set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/ChangeLog b/ChangeLog
index b10f78c..02a3fdc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,529 +1,2697 @@
-Even Rouault <even.rouault at spatialys.com> 2016-09-22
+Juergen E. Fischer <jef at norbit.de> 2016-10-21
- Fix database locking when editing GeoPackage
+ release.pl: stay on same master* branch
- Concurrent read and write can lock a GeoPackage database given
- the default journaling mode of SQLite (delete). Use WAL when
- possible to avoid that.
+rldhont <rldhont at gmail.com> 2016-10-21
- Fixes #15351
+ [BUGFIX][QGIS-Server] Don't failed when transform boundingbox
-rldhont <rldhont at gmail.com> 2016-09-21
+Salvatore Larosa <lrssvtml at gmail.com> 2016-10-21
- [Server] GetStyles: no more needs to add units in SLD
+ [pyqgis-console] APIs file updated
- After @aaime works on SLD, no more needs to add units in SLD send by GetStyles
+volaya <volayaf at gmail.com> 2016-10-21
-Merge: 8190e4c cac25d3
-rldhont <rldhont at gmail.com> 2016-09-22
+ Revert "[processing] correct check for empty extent values. MAde extent params optional by default, to accept auto extent"
- Merge branch 'release-2_16-aaime_sld' into release-2_16
+ This reverts commit 8de56bf01a38fd75574a3a5bac1bcd52b0d88c55.
-rldhont <rldhont at gmail.com> 2016-09-15
+volaya <volayaf at gmail.com> 2016-10-21
- Keep API compatibility and update SIP
+ [processing] correct check for empty extent values. MAde extent params optional by default, to accept auto extent
-rldhont <rldhont at gmail.com> 2016-09-13
+volaya <volayaf at gmail.com> 2016-10-21
- Fix cherry-pickings
+ [processing] make CRS extent optional in gdal wapr
- Do not generate a ogc:Filter where a ogc:Expression is expected. #3366
- Emit valid SLD when mm are used as symbol unit #3414
- Export map level scale based dependencies in most vector symbology #3436
+volaya <volayaf at gmail.com> 2016-10-21
-Andrea Aime <andrea.aime at gmail.com> 2016-08-26
+ Revert "Make Extent and Extent CRS GDAL parameters optional"
- Export map level scale based dependencies in most vector symbology
+ This reverts commit dc2df62b88cdc01b0fc8839779da44fb87ccd213.
-Andrea Aime <andrea.aime at gmail.com> 2016-08-23
+Martin Dobias <wonder.sk at gmail.com> 2016-10-21
- Emit valid SLD when on screen mm are used
+ Fix import of shapefiles to postgres - regression introduced in 5abdfcb (#3652)
- SLD does not have a notion of on screen mm, rescale them to pixels to get an equivalent, more valid and more widely usable, output
+Merge: 1c2f0de ded486c
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-21
-Andrea Aime <andrea.aime at gmail.com> 2016-08-07
+ Merge pull request #3649 from nyalldawson/strip_null
- Do not generate a ogc:Filter where a ogc:Expression is expected. Fixes #10076 and #11202
+ [processing] Add algorithm to strip null geometries
-Martin Dobias <wonder.sk at gmail.com> 2016-09-21
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-21
- [snapping] fix default advanced mode values for added layers
+ [processing] Fix bad grammer in qgis alg help
- Backported from PR #3513
+Martin Dobias <wonder.sk at gmail.com> 2016-10-21
- (cherry picked from commit be636c178cd527f4533f467292acd05bde4238c9)
+ Hide import/export buttons for arcgis services as they do not work (fixes #15637)
-rldhont <rldhont at gmail.com> 2016-09-16
+Martin Dobias <wonder.sk at gmail.com> 2016-10-21
- [Processing] bugfix: intersection QGIS algorithm
+ Fix legend test images after changes in b385ebd
- fixing this by testing int_com.
- ```
- Traceback (most recent call last):
- File "C:/PROGRA~1/QGIS2~1.17/apps/qgis/./python/plugins\processing\core\GeoAlgorithm.py", line 203, in execute
- self.processAlgorithm(progress)
- File "C:/PROGRA~1/QGIS2~1.17/apps/qgis/./python/plugins\processing\algs\qgis\Intersection.py", line 100, in processAlgorithm
- int_geom = QgsGeometry(int_com.difference(int_sym))
- ```
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-21
- AttributeError: 'NoneType' object has no attribute 'difference'
- (cherry picked from commit 3661bc39dbee312b3a0887ca80287cbc7b2260ec)
- (cherry picked from commit 5b573179f3d2fb94542714a4bd3fcdb28f4e3307)
+ [processing] Add algorithm to strip null geometries
-Juergen E. Fischer <jef at norbit.de> 2016-09-17
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-21
- show command line help as message box on windows
+ Legend test mask updates
- (cherry picked from commit bd23bf1a2368fa68fe692d451f61bfe3095619bd)
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-20
-Alexander Bruy <alexander.bruy at gmail.com> 2016-09-16
+ [processing] more complete support for int64 fields (follow up 8d2cc8806b)
- [processing] allow all field types as unique ID field in Mean coords alg
+Germán Carrillo <geotux_tuxman at linuxmail.org> 2016-10-20
- (cherry picked from commit 75269d66b9d79c3b4a2b18bd9626c22840aa6713)
+ Using QVariant.Type enum instead of numbers for readability.
-arnaud.morvan at camptocamp.com <arnaud.morvan at camptocamp.com> 2016-09-08
+Germán Carrillo <geotux_tuxman at linuxmail.org> 2016-10-19
- Fix ParameterGeometryPredicate.getValueAsCommandLineParameter
+ Fixing issue with 'Eliminate sliver polygons' and fields of type long.
- (cherry picked from commit d85de7ccd8946ab3ded83abae674554d482dbcf5)
+Juergen E. Fischer <jef at norbit.de> 2016-10-20
-Alexander Bruy <alexander.bruy at gmail.com> 2016-09-15
+ release.pl:
+ * allow minor releases from master_2 branch
+ * convert windows splash screen to BMP3 from PNG
- [processing] fix search by alg name (fix #15562)
+Martin Dobias <wonder.sk at gmail.com> 2016-10-20
- (cherry picked from commit 11f8aa23198b01952660e2c1e7e20c4548c8b224)
+ Fix reordering and removal of legend nodes in composer legend
-Alexander Bruy <alexander.bruy at gmail.com> 2016-09-15
+Martin Dobias <wonder.sk at gmail.com> 2016-10-20
- [processing] remove obsolete methods
+ Fix building of legend node tree if embedded widgets are used in the layer
- (cherry picked from commit 6f6979ab0b9b6abfb13c3eb85f680b928fc8b97b)
+Martin Dobias <wonder.sk at gmail.com> 2016-10-20
-Nyall Dawson <nyall.dawson at gmail.com> 2016-09-15
+ Fix display of diagram legend entries (fixes #15448)
- Catch exceptions in transform() expression function
+ To make the implementation saner, the legend node that may be embedded within parent
+ layer node is kept separately from activeNodes.
- (cherry-picked from 2a8333ef6be003b8c391a72dbed033a33373d677)
+Matthias Kuhn <matthias at opengis.ch> 2016-10-20
-rldhont <rldhont at gmail.com> 2016-09-15
+ Check validity of input geometries in intersection algorithm, take 2
- GdalTools: In widgetBatchBase runItem method, refreshArgs is not a SIGNAL
+ Fail if invalid geometries are found.
+ And some easy performance wins. Just because.
- The commit 9db908ccbc2257d466c0593738944a08cea8a8bc GdalTools: new style signals generates a regression
- In the widgetBatchBase runItem method, refreshArgs is not a SIGNAL
+ Fix #11986
-Alexander Bruy <alexander.bruy at gmail.com> 2016-09-15
+Matthias Kuhn <matthias at opengis.ch> 2016-10-20
- [processing] correct error message (fix #15511)
+ Revert "Check validity of input geometries in intersection algorithm"
- (cherry picked from commit d393734bd3d368f52271838414a3edbf1d4eb1a5)
+ This reverts commit dbbbf610cfcf3fa655118d73d27a197ac1b3b224.
-Alexander Bruy <alexander.bruy at gmail.com> 2016-09-14
+ Has broken some tests, needs more investigation
- fix indentation
+Matthias Kuhn <matthias at opengis.ch> 2016-10-20
-Alexander Bruy <alexander.bruy at gmail.com> 2016-09-14
+ Check validity of input geometries in intersection algorithm
- [processing] refactor offset curve GDAL algorithm (fix #15478)
+ Fail if invalid geometries are found.
+ And some easy performance wins. Just because.
- (cherry picked from commit cac3b2ddfa7c43239f1c9abc84c965340a5b74b5)
+ Fix #11986
-Alexander Bruy <alexander.bruy at gmail.com> 2016-09-14
+volaya <volayaf at gmail.com> 2016-08-29
- [processing] fix substitution of the original layers in GDAL commands
+ [processing] fixed dialog for selecting scripts
- (cherry picked from commit 89774abed3740426d8aee4a8413c3a05ec705cad)
+ (cherry picked from commit 7884e50c3102b599f2aadfd54d6356414791cf8d)
- Conflicts:
- python/plugins/processing/algs/gdal/GdalAlgorithm.py
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-20
-Alexander Bruy <alexander.bruy at gmail.com> 2016-09-14
+ Update test mask
- [processing] use hex representation of uuid
+Sandro Santilli <strk at kbt.io> 2016-10-19
- (cherry picked from commit 2466083790255c2387fcd84bd6f5c330d272a5c4)
+ Make Extent and Extent CRS GDAL parameters optional
-Juergen E. Fischer <jef at norbit.de> 2016-09-14
+ Specify what the default is when extent CRS is not specified.
+ Allow using "auto" to have extent automatically set to min covering extent.
- fix a54bfc2
+ Fixes #15685
-Juergen E. Fischer <jef at norbit.de> 2016-09-14
+Matthias Kuhn <matthias at opengis.ch> 2016-10-20
- Enable plugins (eg. to show PDFs) in webview widgets used on feature info in identify or in forms
+ Fix backport of "force multitype output on processing overlay ops"
-Marco Bernasocchi <marco at bernawebdesign.ch> 2016-09-11
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-20
- qgsmessagebar timeout is not respected in python
+ Fix bad backport. pt 2
- the default timeout is not respected in python
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-20
- gui/qgsmessagebar.sip:51: void pushMessage( const QString &text, MessageLevel level = INFO, int duration = 0 );
+ Fix bad backports
- https://qgis.org/api/qgsmessagebar_8h_source.html#l00090
- void pushMessage( const QString &text, MessageLevel level = INFO, int duration = 5 ) { return pushMessage( QString::null, text, level, duration ); }
+nirvn <nirvn.asia at gmail.com> 2016-10-14
- (cherry-picked from bb4e6b8fb800b69d28407102a4f17494a4cd5ad9)
+ [legend] insure multi-line labels are vertically centered with tall symbols
-nirvn <nirvn.asia at gmail.com> 2016-09-13
+ (cherry-picked from 455874258cfe7deeb4de888483adbedd97c4da7b)
- [delimitertext] fix watcher check ignored and harmful watcher created for iterator
- (fixes #15558)
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-19
- (cherry-picked from b3e31087181732f7511d047b98352e97f08b0d04)
+ Fix badly worded string
-Nyall Dawson <nyall.dawson at gmail.com> 2016-09-10
+ (cherry-picked from 4b398d3c80ce76503b285bdd82859a16dfc4cb7d)
- Test masks
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-19
- (cherry-picked from e3313fac95ea143988ea32bf162b01b4df8e6fa1)
+ Fix more occurances of drawPolygon issues on Windows
-Nyall Dawson <nyall.dawson at gmail.com> 2016-09-10
+ (cherry-picked from 4bcd97066f0c52f6f4f95adc665193bca0ab4a93)
- Make sure items in legend always occupy the set number of columns
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-19
- In some cases (eg a legend with 4 items and 3 columns) less
- columns were being created
+ Select all text after reset line edit to null
- (cherry-picked from 52eef9006183a66d53926f33e73afa1dcd534e59)
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-19
-Nyall Dawson <nyall.dawson at gmail.com> 2016-09-10
+ Defer processing of dropped files
- Fix multi column legends with odd number of items would place
- more items in rightmost columns instead of leftmost columns
+ On Windows (and maybe other platforms) Qt locks the dragging
+ application for the duration of dropEvent. This means that
+ dropping large files or projects onto QGIS results in
+ Explorer windows being locked and unresponsive until
+ the entire file/project is loaded.
- Eg a 2 column legend with 3 items would put 1 item in
- the first column and 2 in the second. This was ugly, and now
- it places 2 in the first column and 1 in the second.
+ There does not seem to be any Qt method for releasing this lock
+ early, so instead we return from dropEvent as quickly as possible
+ and defer the actual file loading to a slot which is fired up
+ immediately after dropEvent concludes.
- The legend column assigner was incorrectly adding padding above
- the first item in a column during column size calculation
- (padding which is not present when actually rendering the column)
+ (cherry-picked from bd81edc36f867bd2774acc6bf956802ae8cd2cd7)
- (cherry-picked from a673fa8393146d9a8cd1a3bf6f0444bfa23352d7)
+Matthias Kuhn <matthias at opengis.ch> 2016-10-19
-Nyall Dawson <nyall.dawson at gmail.com> 2016-09-10
+ Followup: respect API changes
- Add a bunch of tests for legend grouping into columns
+Mathieu Pellerin <nirvn.asia at gmail.com> 2016-10-19
- (cherry-picked from 570e6936b655aef2877d2d63c9892f1df05df312)
+ [processing] ensure that outputs of vector overlay operations are multiparts (#3622)
-Nyall Dawson <nyall.dawson at gmail.com> 2016-09-06
+rldhont <rldhont at gmail.com> 2016-10-19
- Fix crash when 'use popup' is selected for time based datetime widgets
+ Fix [DB Manager] Allow lowercase field names for homogenize PostGIS Import
- (cherry-picked from 63cc76213979b26e59c17a603dda5e6bfe4463fb)
+rldhont <rldhont at gmail.com> 2016-10-18
-Nyall Dawson <nyall.dawson at gmail.com> 2016-09-14
+ [DB Manager] Allow lowercase field names for homogenize PostGIS Import
- Avoid excessive margins on rule based rule props widget
+ PostGIS provider has an option to lowercase field names. This options is available for user in QGIS algorithm ImportIntoPostGIS and not in DB Mananger.
- (cherry-picked from 9b762023e438d7e44e4fe23fceb7e29c0046e29b)
+ This commit fix it.
-Nyall Dawson <nyall.dawson at gmail.com> 2016-09-14
+Merge: acf74a6 838bf79
+rldhont <rldhont at gmail.com> 2016-10-19
- Don't continually refresh map while editing rule label/desc
+ Merge pull request #3627 from rldhont/fix_server_legend_layertitle-master_2
- (cherry-picked from 2c3548df1111c4709a38d7bacce717711b2a2da7)
+ [BUGFIX][QGIS Server] GetLegendGraphic: if LAYERTITLE is false disable layer name in legend
-Alexander Bruy <alexander.bruy at gmail.com> 2016-09-13
+rldhont <rldhont at gmail.com> 2016-10-10
- [processing] fix progress reporting (fix #15521)
+ [BUGFIX][QGIS Server] GetLegendGraphic: if LAYERTITLE is false disable layer name in legend
- (cherry picked from commit b14dfa65fe8c5db852bac0899f8aac64b91faada)
+ If the layer has only one legend node, it is embedded in parent.
+ In QGIS Server the user can specify no layer title, so the layer title has not be displayed.
-Juergen E. Fischer <jef at norbit.de> 2016-09-06
+Sandro Santilli <strk at kbt.io> 2016-10-19
- debian packaging update: add internal QtWebKit bindings
+ Fix crash upon setting non-integer Dpi while in debug mode
- (cherry picked from commit c2f0fff and d6b485)
+ Closes #15566
-Juergen E. Fischer <jef at norbit.de> 2016-09-03
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-19
+
+ [processing] add missed spatial index constructor
+
+volaya <volayaf at gmail.com> 2016-10-18
+
+ [processing] fixed parameterString test
+
+volaya <volayaf at gmail.com> 2016-10-18
+
+ [processing] dont set default value in param string, when passed null value
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-18
+
+ Fix failure on testGeopackageExtentUpdate test
+
+volaya <volayaf at gmail.com> 2016-10-18
+
+ [processing] correctly set default value for string parameters when no value is provided
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-18
+
+ Fix 70ae301310c7a58134ac699fae70af7fd1176684
+
+ 70ae301310c7a58134ac699fae70af7fd1176684 requires a recent enough GDAL trunk
+ or GDAL 2.1.2
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-18
+
+ [OGR provider] Update layer extent for GPKG layers
+
+ When moving or deleting a geometry that previously touched the layer extent,
+ the layer extent was never shrinked.
+
+ This fix requires GDAL 2.1.2 or above as well.
+
+ Fixes #15273
+
+Matthias Kuhn <matthias at opengis.ch> 2016-10-18
+
+ Hide constraint warnings when there are no constraints
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-18
+
+ qgm2cpp.pl fix
+
+ (cherry picked from commit 14fbb942c77e12b6d79092bb6bf31e54a02e86cd)
+
+Matthias Kuhn <matthias at opengis.ch> 2016-10-17
+
+ Fix QgsMapLayer ConvertToSubClassCode (#3611)
+
+ Fix #15683
+
+Matthias Kuhn <matthias at opengis.ch> 2016-10-18
+
+ Fix relation manager mess when adding new relations
+
+ The table showed wrong information because it didn't take sorting into account
+ and relied on stable row numbers.
+
+Sandro Santilli <strk at kbt.io> 2016-10-18
+
+ [processing] Fix handling of None shapeEncoding
+
+ Fixes #15719 -- object of type 'NoneType' has no len()
+
+Merge: f187707 6c4cb92
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-18
+
+ Merge pull request #3612 from ghtmtt/patch-2
+
+ [processing] Missing import fixed for R algorithm
+
+Matthias Kuhn <matthias at opengis.ch> 2016-10-18
+
+ Fix icon size for constraint warning
+
+Sandro Santilli <strk at kbt.io> 2016-10-18
+
+ Fix ogrLayerName handling of PostgreSQL dataset URIs
+
+ Also document "uri" parameter semantic, and add more tests.
+ See for background
+ https://lists.osgeo.org/pipermail/qgis-developer/2016-October/045311.html
+ REF #15698
+
+Matthias Kuhn <matthias at opengis.ch> 2016-10-18
+
+ Fix form constraints and group visibility
+
+ When a relation editor was shown (or more generally a widget which is not an
+ editor widget), constraints and group visibility were silently disabled.
+
+Matthias Kuhn <matthias at opengis.ch> 2016-10-18
+
+ [postgres] Avoid crash when fetching default value fails
+
+Matthias Kuhn <matthias at opengis.ch> 2016-10-18
+
+ Fix offline editing (#3620)
+
+ We cannot just restore all layer properties, offline editing relies on some not
+ being copied.
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-18
+
+ [composer] Allow syncing pictures to true north
+
+ Previously pictures could only be synced to grid north, which
+ can be totally wrong for many CRSes (especially in polar areas)
+
+ Users now are given a choice of grid or true north, and can also
+ enter an optional offset to apply if eg magnetic north is instead
+ desired.
+
+ When synced to true north the bearing is calculated using the
+ centre point of the linked map item.
+
+ Fix #192, #4711
+
+ This fix was sponsored by the Norwegian Polar Institute's
+ Quantarctica project (http://quantarctica.npolar.no) and
+ coordinated by Faunalia.
+
+ (cherry-picked from 89cc6454b989de1746779b2f648a32d2863ebada)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-18
+
+ Fix effects lost on geometry generator symbol layer
+
+ (cherry-picked from 2a873b83ade6ac2a49ad18598e25e27fd6e9d3d2)
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-17
german translation update
-Juergen E. Fischer <jef at norbit.de> 2016-09-03
+Juergen E. Fischer <jef at norbit.de> 2016-10-17
- fix ProcessingQgisAlgorithmsTest (followup 491c52c)
+ windows: prefer spatialite_i over spatialite
-Juergen E. Fischer <jef at norbit.de> 2016-09-03
+Matthias Kuhn <matthias at opengis.ch> 2016-10-17
- processing: use main vector menu translation (fixes #14535)
+ Use qIsInf instead of isinf
- (cherry picked from commit 11289a0d973e6e4a3f7f81972dd08f2e6d82941e)
+Matteo Ghetta <matteo.ghetta at gmail.com> 2016-10-17
-volaya <volayaf at gmail.com> 2016-09-02
+ [processing] avoid overlapping UI (#3616)
- [processing] fixed error in dissolve when there are features with null geometries
+ Super small changes that avoids the overlapping of multi selection widget with other widgets
-Even Rouault <even.rouault at spatialys.com> 2016-09-01
+rldhont <rldhont at gmail.com> 2016-10-14
- [DBManager] Fix exception raised when adding a new Spatialite connection
+ [BUGFIX][QGIS Server] GetFeatureInfo: Feature with no geometry is not returned even if FILTER param is set
- This was accidentaly broken since 1f0fce7852e9f6a27af967d7ac7ee3989dce7b45
+Matthias Kuhn <matthias at opengis.ch> 2016-10-17
- Fixes #15274
+ Also restore layer variables for raster layers from QML
-Larry Shaffer <lshaffer at boundlessgeo.com> 2016-09-01
+Matthias Kuhn <matthias at opengis.ch> 2016-10-17
- [auth] Fix return value for plugins that do not support an expansion
+ Restore layer variables from QML
- Bug not evident until there were providers with multiple credential
- expansions (now supported in OWS providers). Lack of support for an
- expansion should only trigger a debug message, not a failure.
+ Fix #14452
- (cherry-picked from 194b5adb1ed81bcfe7edd78477dfea81cae77aed)
+Matthias Kuhn <matthias at opengis.ch> 2016-10-17
-Hugo Mercier <hugo.mercier at oslandia.com> 2016-09-01
+ Allow 0 (infinite) for scale dependent visibility
- Fix virtual layer queries with accents in layer name
+ Fix #15414
- (cherry-picked from af0d6b93a6)
+Sandro Santilli <strk at kbt.io> 2016-10-17
-Matthias Kuhn <matthias at opengis.ch> 2016-09-01
+ Fix extraction of ogr LayerName from database dataset URIs
- Export main() when building for android
+ See https://github.com/qgis/QGIS/commit/6c5364186dd8d45ac51e5bd1a72c6a542f032cb1#commitcomment-19439676
+ Includes testcase.
-Hugo Mercier <hugo.mercier at oslandia.com> 2016-07-21
+ REF #15698
- Snapping: destroy index on dataChanged signal
+Matteo Ghetta <matteo.ghetta at gmail.com> 2016-10-17
- Snapping caches on layers that have been changed by the provider or
- by external sources are now invalidated.
+ [processing] Missing import fixed for R algorithm
- (Cherry-picked from e6fd2e25)
+volaya <volayaf at gmail.com> 2016-10-17
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-30
+ [processing] fixed handling of None param values in ogr2ogrtopostgis.py
- Fix Capitalize First Letter fails with curved labels (fix #14875)
+volaya <volayaf at gmail.com> 2016-10-17
- Instead of using QFont's inbuilt capitalization support, which
- applies only on rendering and accordingly fails for curved
- labels which are drawn one character at a time, we now manually
- capitalize label text while registering features.
+ [processing] made connection params optional in ogr2ogrtopostgis.py
- The capitalize first method from Qt was reimplemented in QgsStringUtils
- (together with what I expect is better handling of unicode characters
- over the Qt method).
+volaya <volayaf at gmail.com> 2016-10-17
- This change also makes it possible to implement other capitalization
- methods not directly supported by Qt
+ [processing] fixes for 'import into PostGIS' alg
- (cherry-picked from 15dd295)
+ fixes #15097
-Tim Sutton <tim at kartoza.com> 2016-08-22
+volaya <volayaf at gmail.com> 2016-10-14
- Spatialite error message fix (#3416)
+ [processing] fixed check for empty param for strings
- * Fixed issue where opening an invalid spatialite db fails and gives and poor warning message
+Merge: bec7cdd d4feb35
+volaya <volayaf at gmail.com> 2016-10-17
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-29
+ Merge pull request #3607 from strk/master_2-processing-libpq-defaults
- Fix calculation of certain aggregates from expressions when no
- matching features exist
+ [processing] Do not override libpq defaults
- Eg count should return 0 in this case rather than null
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-17
- (cherry-picked from 9ba41e9f275f42a5dfe5c1cdbc0a4d091a0e833f)
+ Fix bad fills when using marker line with render effects (fix #15696)
-Juergen E. Fischer <jef at norbit.de> 2016-08-28
+ (cherry-picked from a0bfc10, 55f207)
- processing: fix population of commander combobox (fixes #15283)
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-17
- (cherry picked from commit d3882d5)
+ Fix color widget opens in wrong panel (fix #15705)
-Juergen E. Fischer <jef at norbit.de> 2016-08-28
+ (cherry-picked from 721d3c5bfbd33f00ab675edebb3d3aa3854352e3)
- dxf export: link vertices to polyline (fixes #15484)
+Sandro Santilli <strk at kbt.io> 2016-10-15
- (cherry picked from commit 052d3ef851beef7cbbfa3c699c1c95b0d84dc3e2)
+ Add test for setting up connection string
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-26
+Sandro Santilli <strk at kbt.io> 2016-10-15
- [browser] Correctly refresh postgres schemas when dropping tables
+ [processing] Allow using libpq defaults for host,port,user,pass and dbname
- (cherry-picked from 5a41748b867505784a091a882a0eb1ca187c4ba8)
+ Fixes #15706
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-26
+Sandro Santilli <strk at kbt.io> 2016-10-14
- Make QgsVectorDataProvider defaults methods more efficient
+ Fix extraction of ogr LayerName from multi-layer dataset URIs
- (cherry-picked from a10b8fc3e5658290dd7e18df1001e543c3a75caa)
+ Adds supports for "layerid" when present.
+ Drop special handling for "table=" portions found in URI,
+ making the code more generic.
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-26
+ Includes testcase.
- Fix limited random color ramp always returns 1 less color than set
+ Fixes #15698 - import geodatabase to postgis via processing
- (cherry-picked from 1d98b10904884d8223372fc9248c2825c85591e9)
+Sandro Santilli <strk at kbt.io> 2016-10-14
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-25
+ Python scripts have 4-spaces indent
- Fix potential crash
+Juergen E. Fischer <jef at norbit.de> 2016-10-14
-Juergen E. Fischer <jef at norbit.de> 2016-08-26
+ debian packaging: add support for yakkety
- Release of 2.16.2
+Sandro Santilli <strk at kbt.io> 2016-10-13
-Alexander Bruy <alexander.bruy at gmail.com> 2016-08-23
+ Revert "postgres provider: quote compound key columns in uri"
+
+ This reverts commit daa6510970e9afbc4d41d28e0c94b4f238eb372d.
+
+ I've tested that reverting this does not re-introduce bug
+ http://hub.qgis.org/issues/13710
+
+Sandro Santilli <strk at kbt.io> 2016-10-13
+
+ Fix PostgreSQL import of layers with multi-column or quoted-column keys
+
+ Fixes #15226 (drag & drop of postgresql views)
+ Includes test
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-11
+
+ Fix unused variable warning
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-14
+
+ Fix layer tree expanded state when used expand/collapse all (fixes #15691)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-14
+
+ Fix incorrect selection rect drawn for composer items on windows
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-14
+
+ Add default shortcut to open attribute table (F6)
+
+Frits van Veen <fritsvanveen at ziggo.nl> 2016-08-04
+
+ Using 'perimeter (curved)' labels on polygon layers will
+ now respect 'Show upside-down labels' setting
+
+ (cherry-picked from 34e2bea, a21946a, 12a8891)
+
+volaya <volayaf at gmail.com> 2016-10-13
+
+ [processing] removed debug line
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-13
+
+ [processing] correctly handle help loading (fix #15641)
+
+volaya <volayaf at gmail.com> 2016-10-13
+
+ [processing] fixed wrong provider reference in union algorithm
+
+volaya <volayaf at gmail.com> 2016-10-13
+
+ [processing] warn if extent might not be in the expected CRS
+
+Merge: 6f84a00 ffd1a2c
+Jürgen Fischer <jef at norbit.de> 2016-10-13
+
+ Merge pull request #3598 from borysiasty/master_2
+
+ [Plugin Manager] Fix font size (issue #15302)
+
+borys <info at borysjurgiel.pl> 2016-10-13
+
+ [Plugin Manager] Fix font size (issue #15302)
+
+Merge: 25794d4 2d7164f
+Larry Shaffer <dakcarto at users.noreply.github.com> 2016-10-12
+
+ Merge pull request #3576 from dakcarto/master_2-ows-fixes
+
+Larry Shaffer <lshaffer at boundlessgeo.com> 2016-10-05
+
+ [auth] Reinstate auth system reply expansions for OWS providers
+
+ - Apparently this was lost during a git squash of commits for 2.12 PR
+
+Larry Shaffer <lshaffer at boundlessgeo.com> 2016-10-05
+
+ [WFS provider] Fix auth config extra expansion and auth prioritization
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-13
+
+ Avoid warning
+
+rldhont <rldhont at gmail.com> 2016-10-11
+
+ Last Redo [BUGFIX][QGIS Server] Joins was not reloaded if the layer is in cache
+
+ Add an accessor to QgsVectorLayer join buffer, to not duplicate QgsVectorLayerJoinBuffer::readXml code
+
+Sandro Santilli <strk at kbt.io> 2016-10-12
+
+ Fix hub link
+
+Sandro Santilli <strk at kbt.io> 2016-10-11
+
+ Fix bogus precision/scale in PostgreSQL for double values
+
+ This reverts commit 92f71b696ca93c792ae5602ed82863fcef0e5006,
+ which broke import of legit shapefiles by assuming wrong
+ semantic for the non-constraining QgsField length/precision
+ attributes.
+
+ Closes #15188
+
+ Includes test
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ Fix @geometry_point_num and @geometry_point_count for marker lines
+
+ Fixes #15673
+
+ (cherry-picked from ddfe91f76342578934398f9cc56aa68e4e525020)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ Correctly handle edit buffer when using request with limit (fix #15505)
+
+ (cherry-picked from 2665eb50a69220324f4a6d045e8eba6601760dd3)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ Fix HTML annotation does not display HTML (fix #8609)
+
+ Annotation was only rendering html when it was associated with a
+ map layer. Now if it isn't associated with a map layer it will
+ always render the html.
+
+ (cherry-picked from 53c3ed2dc02baf43c3a5cc7323f37869f434f25a)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ Add perceptually uniform colormaps to default styles
+
+ Adds the Viridis, Magma, Plasma and Inferno uniform color ramps
+ created by Stéfan van der Walt and Nathaniel Smith
+
+ See https://bids.github.io/colormap/ for more details
+
+ Note that I've thinned out the stops here, and only kept
+ every 5th stop from the original ramps
+
+ (cherry-picked from 60cc853747e53303fd9b2846b65c915dec28abfa)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ [labeling] When in line orientation placement mode, rename above/
+ below options to left of line/right of line
+
+ Makes their meaning clearer
+
+ (cherry-picked from c36c242e8ef242ef7f2da524fca0b7b16ee13ce7)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ [labeling] Fix line orientation option gets checked randomly
+
+ (cherry-picked from 01a402ca113b448f9a8891fda4c062d8bc310f77)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ Fix first marker is drawn twice for marker line interval mode
+
+ (cherry-picked from 748d8acddb5ab6e72b09d2ae6485d46fc17c4d16)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ Fix invalid values for @map_extent_width/height (fix #15672)
+
+ (cherry-picked from c1cf896c1a76fdac16b3e800b7e1f106f983e299)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ Fix escaping in regexp function help
+
+ (cherry-picked from e69dd9c9b2fa13efe3a4cd2a512885accfec60b4)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ Allow expression functions to appear in multiple groups (fix #15682)
+
+ Now functions which make sense for multiple contexts (eg length,
+ to_date) can appear in more than one group.
+
+ (cherry-picked from 0c4bf943c141ff88519ee7e2474d828230c84272)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-12
+
+ Fix renaming a virtual field leads to crash (fix #15669)
+
+ (cherry-picked from 3a76708bcb4785f5fe930be0b18396e5fa87031f)
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-17
+
+ typo fix
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-12
+
+ fix default for DEFAULT_WITH_INTERNAL_QWTPOLAR setting
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-11
+
+ Revert "[processing] Fix missing points in polygons menu item (fix #15670)"
+
+ This reverts commit ba7fdded19760a5ee526cf7357be2b4a7e1b440c.
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-11
+
+ Revert "[processing] restore Points in Polygons algorithm menu entry (follow up d4323addf0)"
+
+ This reverts commit 1051dbbdaaa4e4f3a02832f6a923eb9fccd85156.
+
+rldhont <rldhont at gmail.com> 2016-10-11
+
+ [QGIS Server] Loss qobject_cast when it's usefull
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-11
+
+ [processing] restore Points in Polygons algorithm menu entry (follow up d4323addf0)
+
+ (cherry picked from commit 85962653a2e07f2036964d02ec6e7a4229551183)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-11
+
+ [processing] Fix missing points in polygons menu item (fix #15670)
+
+ Also add a unit test
+
+ (cherry picked from commit d4323addf04e0a1bdccec2127c7b2b8a59661799)
+
+ Conflicts:
+ python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
+
+rldhont <rldhont at gmail.com> 2016-10-10
+
+ [QGIS Server] Use qobject_cast when it's usefull
+
+rldhont <rldhont at gmail.com> 2016-10-10
+
+ Redo [BUGFIX][QGIS Server] Joins was not reloaded if the layer is in cache
+
+ With the commit f6aad8b, the QgsMapLayerRegistry signal `layersWillBeRemoved` is always emit. This imply that the vector layer join buffer is empty and not reloaded if the layer is in cache.
+
+ To fix it, the QgsServerProjectParser has to have the same method as QgsVectorLayerJoinBuffer::readXml.
+
+ This commit fixed #15522 Qgis Server doesnt' respect the styling from Desktop
+
+rldhont <rldhont at gmail.com> 2016-10-10
+
+ Revert "[BUGFIX][QGIS Server] Joins was not reloaded if the layer is in cache"
+
+ This reverts commit ad32b5e1a7aa2e06bc8a6d29f2cba4e018d4a70c.
+
+rldhont <rldhont at gmail.com> 2016-10-10
+
+ Revert "fix typo ad32b5e1a7aa2e06bc8a6d29f2cba4e018d4a70c"
+
+ This reverts commit 03fdaa02acb4abb6f8407d805379b50ec132e997.
+
+rldhont <rldhont at gmail.com> 2016-10-10
+
+ Revert "Fix QGIS server for PyQgsServerAccessControl"
+
+ This reverts commit 6e4dbc0e45b41b163a9499dc16a0e4019853fd3e.
+
+volaya <volayaf at gmail.com> 2016-10-10
+
+ [processing] made -te parameter optional in gdal warp
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-10
+
+ fix warning
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-09
+
+ german translation update
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-09
+
+ fix typos
+
+Piotr Pociask <piotr.pociask at gis-support.pl> 2016-10-08
+
+ Fix VSIUnlink in QgsOgrUtils::stringToFeatureList
+
+ (cherry picked from commit a8d08891ce9a9b7add36955261cf402202a54e80)
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-08
+
+ fix warnings
+
+rldhont <rldhont at gmail.com> 2016-10-07
+
+ Fix QGIS server for PyQgsServerAccessControl
+
+rldhont <rldhont at gmail.com> 2016-10-07
+
+ fix typo ad32b5e1a7aa2e06bc8a6d29f2cba4e018d4a70c
+
+rldhont <rldhont at gmail.com> 2016-10-07
+
+ [BUGFIX][QGIS Server] Joins was not reloaded if the layer is in cache
+
+ With the commit f6aad8bad6db72d0b1e573998ac7dcb2405dce55, the QgsMapLayerRegistry signal `layersWillBeRemoved` is always emit. This imply that the vector layer join buffer is empty and not reloaded if the layer is in cache.
+
+ To fix it, the layer XML element has to be read each time the layer is used.
+
+ This commit fixed #15522 Qgis Server doesnt' respect the styling from Desktop
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-07
+
+ osgeo4w: really use package name (fixes 6db9a371)
+
+ (cherry picked from commit f971b0dbd16edd857cd76cc09fe7a08ac0b03cbe)
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-07
+
+ Remove useless debug trace
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-07
+
+ [OGR provider] Make feature iterator work on GeometryCollection sublayers
+
+ When trying to reproduce http://hub.qgis.org/issues/10485, I noticed a regression.
+ Now attribute table no longer shows features with OGR GeometryCollection.
+
+ Fixes also issues where sublayer geometry type is too strict regarding 2D vs 2.5D
+ geometry types.
+
+ Fixes #15675
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-07
+
+ [OGR provider] Force REPACK at the first edit action.
+
+ In the case where we deal with a shapefile, it is possible that it has
+ pre-existing holes in the DBF (see #15407), so if using a GDAL version
+ recent enough (>=2.1.2) to have reliable packing, do a packing at the
+ first edit action.
+
+ Fixes #15407
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-07
+
+ Fix crash in node tool after deleting the whole geometry (fixes #15659)
+
+ Made sure that both closestVertex() and closestSegment() return negative
+ distance on error (e.g. with null or emtpy geometry).
+
+ Also fixes snapping when dealing with layers with null/invalid geometries
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-07
+
+ osgeo4w: use package name in build directory
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-07
+
+ followup 43fa88e fix python3 (refs #15256)
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-07
+
+ Followup 5b2646c to fix tests (refs #15256)
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-07
+
+ Fix problems with plugins using unicode characters (fixes #15256)
+
+ regression introduced during python3 porting
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-06
+
+ [WFS provider] Be robust to field names ending with spaces in DescribeFeatureType
+
+ Fixes #3426
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-06
+
+ Properly deal with empty cache/directory in WFS provider, server and globe plugin
+
+ Fixes #15111
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-06
+
+ [WFS provider] Do not append crs at end of BBOX in WFS 1.0
+
+ Fixes #15464
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-06
+
+ [WFS provider] Force refresh of GetCapabilities when pressing Connect
+
+ The cached response to GetCapabilities was always used, even when
+ pressing Connect. Now a new request is sent over the network.
+
+ Fixes #15647
+
+Even Rouault <even.rouault at spatialys.com> 2016-10-06
+
+ [OGR provider] Check if REPACK has emitted errors
+
+ Refs #15393 and #15570
+ Real fix for the REPACK issues has been committed per
+ GDAL ticket https://trac.osgeo.org/gdal/ticket/6672 (GDAL 2.1.2 or above)
+
+ Add test to simulate the situations that caused problems.
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix right aligned contents in label spin boxes
+
+ (cherry-picked from 2dea055b32940af6c3f1f65b55fe45de4feafa2f)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix rule based renderer shows 0 count on first click of "show counts"
+
+ (cherry-picked from 291f7bdaa3d6463e7e413e92a1a5b39d16efb039)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix many labeling unit settings are lost on closing dialog
+
+ (and also don't trigger auto preview)
+
+ (cherry-picked from dc481955a5848ee355238bf93f82068de71aca4f)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix arrow and filled marker symbols don't show selection state
+
+ (cherry-picked from 8ffa08447aee097568d8be7f5876bd395202ab80)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Rename duplicate menu item causing Qt warning
+
+ (cherry-picked from 35b3b7949bcfd32e8e2959f7d922ead3e7921a87)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Preserve edits for multiline editor when length exceeds field size
+
+ Previously when using the multiline option for text edit widgets
+ the entire contents of the field would be discarded if the entered
+ value exceeded the maximum length for a string field.
+
+ Now the entered string is truncated to the maximum field length.
+
+ (cherry-picked from 7d8fba8b8c1a2e39b0814053029bf64c20e85c73)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ [labeling] Fix data defined placement with rotated maps
+ For layers requiring reprojection and with rotated maps any
+ labels with data defined x/y would not be rendered
+
+ Fix #14236
+
+ (cherry-picked from d36fb619b5a210406aaa50ed3aab59763f5f749a)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix identify menu highlight only works with simple geometry types
+
+ Fix #15625
+
+ (cherry-picked from 5b3f10a531765a8c3951fa35a33d7da5a0c27644)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix data defined buttons sometimes incorrectly show error state
+
+ (cherry-picked from 7d27b43e79d58412d8c894f05cc984af47583bc0)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix cannot modify diagram attribute expression (fix #15514)
+
+ Also clean up some code
+
+ (cherry-picked from 111106c64fcf4288617e65fc160a2b6112606cfc)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-04
+
+ Fix SVG preview blocks QGIS (fix #14255)
+
+ Now SVG preview loading occurs in a background thread so that
+ dialogs can open instantly
+
+ Also guard against circular symbolic links in SVG selector widget
+
+ (cherry-picked from c60c4f7f0ca09dc6bbc8e3f721339a238154ff57)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix layers with layer wide opacity "flashing" by rendering
+ intermediate states without opacity
+
+ (cherry-picked from 19f6b62cd8e99fc73e5f89f3c0f82f586d5214ec)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix last segment length in measure dialog is incorrect after
+ completing measurement with right mouse click
+
+ (cherry-picked from bad137283b7d22ab2f7bf889bc72b1088efaa742)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix measure dialog shows wrong results when changing units
+
+ If the measurement was not finished (ie right click occurred)
+ then the last length would be missing from the table
+
+ Fix #15433
+
+ (cherry-picked from 03bff507d9814ec1a3d9fdfdbe5cfbc5b6274689)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Correctly emit panelAccepted when panel is not in dock mode
+
+ Fixes #15373 - refine current rule not working when symbol widgets
+ are not used in the style dock
+
+ This fixes a behavioural difference when new panels are opened
+ in a QgsPanelWidget when in docked/undocked mode. When in
+ docked mode, the newly opened panel will emit panelAccepted
+ when it is accepted. But for undocked mode, the parent
+ panel was emitting the panelAccepted signal and so the
+ connection to update the renderer was never
+ triggered. Now both docked/undocked panels will always
+ emit panelAccepted ONLY from the newly opened panel itself.
+
+ This also fixes memory leaks as the clean up code was never
+ run in undocked mode.
+
+ I've updated the docs to clarify this behaviour.
+
+ (cherry-picked from ddbd25d046ad514719b41c5f61f3c7fe34304a74)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix crash when validating geometry (fix #15660)
+
+ Also fix python bindings for QgsGeometryValidator
+
+ (cherry-picked from bc32b1fe5a9ac05f1763f45268eab833cc46e546)
+
+nirvn <nirvn.asia at gmail.com> 2016-07-04
+
+ [pseudocolor renderer] fix invert check box in continous mode
+ (fixes #15209)
+
+ (cherry-picked from 1e0e9c2e9549fd77e93b3c93597d3716708ce5d1)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix crash in raster transparency widget on close
+
+ mPixelSelectorTool is owned by canvas, which may be deleted
+ before the QgsRasterTransparencyWidget on QGIS exit
+
+ (cherry-picked from 3e1536f1da20097eb68a57a34d65bdae45fb1568)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix raster style dock widgets not opened with dock mode flag
+
+ Makes the color picker open inline for the raster properties pages
+
+ (cherry-picked from 79fd6fa0ac9f078c916d90fbfc2ff458206008cf)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Fix missing live updates when raster colorize color changes
+
+ (cherry-picked from b95a5e98c8cbd9bc388e42634eb11a2b161eecbb)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-10-06
+
+ Make modifications through the style dock much faster
+
+ Before any change in the style dock would invalidate the cache
+ for ALL map layers, resulting in every layer being redrawn.
+
+ Now only the affected layer is redrawn and all others just use
+ the cached render.
+
+ (cherry-picked from c6436f897129829647e79654bdc8530367c5de62)
+
+Merge: f36b403 fddd56c
+rldhont <rldhont at gmail.com> 2016-10-06
+
+ Merge pull request #3580 from rldhont/ogcutils_propertyIsLike_attributs-master_2
+
+ Backport [BUGFIX] Support OGC PropertyIsLike attributs #3551
+
+Marco Bernasocchi <marco at opengis.ch> 2016-10-05
+
+ fix save to postgis table in processing
+
+ (cherry picked from commit 7c59e4117712dc9f730380e06e0b903474fbb954)
+
+rldhont <rldhont at gmail.com> 2016-10-04
+
+ Update ogcutils tests
+
+rldhont <rldhont at gmail.com> 2016-09-30
+
+ [BUGFIX] Support OGC PropertyIsLike attributs
+
+ The OGC PropertyIsLike element can have 4 attributs:
+ * matchCase to specify LIKE or ILIKE
+ * wildCard to specify a wildcard char symbol
+ * signleChar to specify a single char symbol
+ * escape to specify an escape char symbol
+
+Etienne Trimaille <gustrimaille at yahoo.fr> 2016-10-05
+
+ backport from #3301 add qscintilla to cmakelists (#3573)
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-05
+
+ fix indendation
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-05
+
+ Cancel WCS requests just like it is done in WMS
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-05
+
+ Fix crash when loading WCS layers (fixes #15595)
+
+ The problem is that some providers would still issue network
+ requests in prepareJobs() - this should be ideally avoided,
+ because it is run in main thread - all the work should be deferred
+ to be done in worker thread.
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-04
+
+ [processing] correct GRASS 7 detection on Mac (fix #15645)
+ follow up e1ff6e896a
+
+ (cherry picked from commit d03d2069b96b2c25abe64588f54f24dab7ea7cc2)
+
+ Conflicts:
+ python/plugins/processing/algs/grass7/Grass7Utils.py
+
+Merge: 7a9018e dfcd1ea
+Alessandro Pasotti <elpaso at itopen.it> 2016-10-04
+
+ Merge pull request #3570 from elpaso/test-wait-for-network-backport
+
+ Backport of the new test pick a free port strategy
+
+Alessandro Pasotti <apasotti at boundlessgeo.com> 2016-10-04
+
+ Py3 compat
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-04
+
+ fix indentation
+
+Merge: a6bb8a9 bd1cf0c
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-04
+
+ Merge pull request #3568 from volaya/processing_fixes
+
+ [processing] various fixes
+
+Merge: 4bcdecd 641c09b
+volaya <volayaf at gmail.com> 2016-10-04
+
+ Merge pull request #3 from alexbruy/fix-spatial-index
+
+ fix spatialindex creation
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-10-04
+
+ fix spatialindex creation
+
+Alessandro Pasotti <apasotti at boundlessgeo.com> 2016-10-04
+
+ Backport of the new test pick a free port strategy
+
+volaya <volayaf at gmail.com> 2016-10-04
+
+ [processing] fixed iterative execution
+
+ fixes #15650
+
+volaya <volayaf at gmail.com> 2016-09-21
+
+ [processing] don't use full path for naming layers when loaded in dataobjects.load
+
+volaya <volayaf at gmail.com> 2016-09-20
+
+ [processing] do not set param value in batch interface if default is none
+
+volaya <volayaf at gmail.com> 2016-09-21
+
+ [processing] alternative way of copying algorithms in a model.
+
+ should fix #15060 and #15480
+
+volaya <volayaf at gmail.com> 2016-09-21
+
+ [processing] dont use hidden outputs when exporting to python or displaying alg help
+
+ fixes #14998
+
+volaya <volayaf at gmail.com> 2016-09-20
+
+ [processing] use only selected features for spatial index
+
+ fixes #15584
+
+Merge: 430694b 8ab8c7b
+volaya <volayaf at gmail.com> 2016-10-03
+
+ Merge pull request #3544 from ghtmtt/processing_script_font
+
+ [processing] fix button for font size
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-03
+
+ Fix identify tool for WMS if webkit is not available (fixes #14658)
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-03
+
+ Fix WMS identify when using "Feature" format and the layer has named CRS
+
+Martin Dobias <wonder.sk at gmail.com> 2016-10-03
+
+ Fix listing of WMTS layers in browser (fixes #15350)
+
+volaya <volayaf at gmail.com> 2016-10-01
+
+ [processing] fixed multiple fields input in R algorithms
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-01
+
+ fix typos
+
+ (cherry picked from commit 1c298684ff6cedb9c9759442b55feba6b7241cee)
+
+Juergen E. Fischer <jef at norbit.de> 2016-10-01
+
+ debian packaging: add ca-certificates as build dependency for dash upload (followup c2f0fff)
+
+Merge: a8fbf8a 02dfb4f
+Alessandro Pasotti <elpaso at itopen.it> 2016-09-30
+
+ Merge pull request #3553 from elpaso/server-tests-backport
+
+ [Server] Backport of the test improved stability
+
+Alessandro Pasotti <apasotti at boundlessgeo.com> 2016-09-30
+
+ Ignore data type differences
+
+Alessandro Pasotti <apasotti at boundlessgeo.com> 2016-09-30
+
+ Blacklist the new auth test (Qt5/Py3 version is in master)
+
+Alessandro Pasotti <apasotti at boundlessgeo.com> 2016-09-30
+
+ [Server] Backport of the test improved stability
+
+rldhont <rldhont at gmail.com> 2016-09-28
+
+ [BUGFIX] Expression in like escape % and _
+
+ The Expression LIKE binary operator does not care about escape % and _ char.
+ No-one has already open an issue about it but in the OGC element PropertyIsLike the user can defined is own wild and single char. This mean that QGIS has to escape % and _ if they are not used as wild and single char.
+
+rldhont <rldhont at gmail.com> 2016-09-15
+
+ [Processing][Rscripts] Use temp script filename
+
+ The build RScript is stored in the User folder, so the script is erased at each RAlgorithm execute.
+ Server side or for debugging this could be a problem.
+ So processing_script.r will be stored in temp folder.
+
+julienmalik <julienmalik at users.noreply.github.com> 2016-09-30
+
+ CDash submissions should be done with https now
+ (cherry picked from commit 19378c22802668f592f0ffc268451c5a946371af)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-30
+
+ [composer] Fix save world file does not work (fix #15268)
+
+ (cherry-picked from 38a811b377cf7d0d50e2c76346eadfdd8ef87956)
+
+Bas Couwenberg <sebastic at xs4all.nl> 2016-09-29
+
+ Only enable globe plugin for osgEarth 2.7, it is not compatible with 2.8. (#3541)
+
+matteo <matteo.ghetta at gmail.com> 2016-09-29
+
+ [processing] fix button for font size
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-29
+
+ nodetool: use exact intersect when picking features (fixes #15294)
+
+ (cherry picked from commit 6b2799414a3b6434818adc859d3f1363029eb579)
+
+volaya <volayaf at gmail.com> 2016-09-29
+
+ [processing] better update of expression widget when layer is changed in fields calculator
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-29
+
+ [travis] Disable flaky qgis_ziplayertest and qgis_ogcutilstest tests
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-28
+
+ fix #15634
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-28
+
+ gdal tools: disconnect canvas signal after building vrt (fixes #15389)
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-28
+
+ categorized renderer: also setup symbol render context for hashed symbols
+
+volaya <volayaf at gmail.com> 2016-09-27
+
+ [processing] added short help for saga raster calculator
+
+Orion Poplawski <orion at cora.nwra.com> 2016-09-26
+
+ Cast to qreal for arm support
+
+volaya <volayaf at gmail.com> 2016-09-27
+
+ [processing] fixed saga group name
+
+volaya <volayaf at gmail.com> 2016-09-27
+
+ [processing] fixed wrong import in i_aster_toar
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-27
+
+ Change default label buffer join style to round
+
+ Looks much nicer and is more appropriate for buffers
+
+ (cherry-picked from 4dbea7f5a4277a7411152ca1f82c8769bd765093)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-23
+
+ Update test masks
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-27
+
+ Set initial effect selection in layer effects widget to
+ first enabled effect
+
+ Hopefully makes the widget a bit more user friendly - otherwise
+ the initial settings shown may be for a disabled effect and the
+ users is left wondering why changes have no impact
+
+ (cherry-picked from f67a48a39ba93f57597f6c7cc021e78460091200)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-27
+
+ Fix server error when no log file set
+
+ (cherry-picked from f5ffbbf801ff299d6abbba7e2f85ccab67a5c374)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-21
+
+ Remove icon with bad sRGB profile (causing Qt warnings)
+
+ (cherry-picked from 2a2bf2cbe4567a0c053db64cb4d78addb9e49a2c)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-27
+
+ Fix invalid QString arg warning
+
+ (cherry-picked from f62a0bfbd6bd748dcb39ba9cd943ef1cf72bee9e)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-27
+
+ Make counting and testing filters in rule based renderers faster
+
+ Hand filters off to the provider where possible and avoid fetching
+ unnecessary attributes/geometry
+
+ (cherry-picked from 99000369892ac985e6b13f8a8eb62cea0b73117e)
+
+Even Rouault <even.rouault at spatialys.com> 2016-09-22
+
+ Fix database locking when editing GeoPackage
+
+ Concurrent read and write can lock a GeoPackage database given
+ the default journaling mode of SQLite (delete). Use WAL when
+ possible to avoid that.
+
+ Fixes #15351
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-23
+
+ Fix crash when cancelling render
+
+ Partial backport of 23909a
+
+Marco Bernasocchi <marco at bernawebdesign.ch> 2016-09-16
+
+ Add qgis.PyQt.Qt compat files (#3491)
+
+ * added PyQt.Qt
+
+ * fix matthias comments
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-22
+
+ update dxf sip bindings
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-19
+
+ dxf export: support reprojection
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-21
+
+ Enable link/unlink button by default
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-21
+
+ [Feature] Allow configuring link/unlink feature buttons on relation editor widget
+
+rldhont <rldhont at gmail.com> 2016-09-21
+
+ [Server] GetStyles: no more needs to add units in SLD
+
+ After @aaime works on SLD, no more needs to add units in SLD send by GetStyles
+
+volaya <volayaf at gmail.com> 2016-09-21
+
+ [processing] fied issue with grass icons slowing down toolbox
+
+ fixes #15550
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-21
+
+ Chained filters for relation reference search widget
+
+ Fix #15589
+
+Martin Dobias <wonder.sk at gmail.com> 2016-09-21
+
+ [snapping] fix default advanced mode values for added layers
+
+ Backported from PR #3513
+
+Merge: 1856a37 4d153be
+rldhont <rldhont at gmail.com> 2016-09-20
+
+ Merge branch 'master_2_aaime_sld' into master_2
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-20
+
+ Hide proper column in attribute table
+
+ Fix #15458
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-20
+
+ Less debug noise
+
+rldhont <rldhont at gmail.com> 2016-09-15
+
+ Keep API compatibility and update SIP
+
+rldhont <rldhont at gmail.com> 2016-09-13
+
+ Fix cherry-pickings
+
+ Do not generate a ogc:Filter where a ogc:Expression is expected. #3366
+ Emit valid SLD when mm are used as symbol unit #3414
+ Export map level scale based dependencies in most vector symbology #3436
+
+Andrea Aime <andrea.aime at gmail.com> 2016-08-26
+
+ Export map level scale based dependencies in most vector symbology
+
+Andrea Aime <andrea.aime at gmail.com> 2016-08-23
+
+ Emit valid SLD when on screen mm are used
+
+ SLD does not have a notion of on screen mm, rescale them to pixels to get an equivalent, more valid and more widely usable, output
+
+Andrea Aime <andrea.aime at gmail.com> 2016-08-07
+
+ Do not generate a ogc:Filter where a ogc:Expression is expected. Fixes #10076 and #11202
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-20
+
+ Fix sorting of expressions in relation reference widget
+
+ Fix #15451
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-20
+
+ Fix some const-issues
+
+rldhont <rldhont at gmail.com> 2016-09-16
+
+ [Processing] bugfix: intersection QGIS algorithm
+
+ fixing this by testing int_com.
+ ```
+ Traceback (most recent call last):
+ File "C:/PROGRA~1/QGIS2~1.17/apps/qgis/./python/plugins\processing\core\GeoAlgorithm.py", line 203, in execute
+ self.processAlgorithm(progress)
+ File "C:/PROGRA~1/QGIS2~1.17/apps/qgis/./python/plugins\processing\algs\qgis\Intersection.py", line 100, in processAlgorithm
+ int_geom = QgsGeometry(int_com.difference(int_sym))
+ ```
+
+ AttributeError: 'NoneType' object has no attribute 'difference'
+ (cherry picked from commit 3661bc39dbee312b3a0887ca80287cbc7b2260ec)
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-17
+
+ fix warnings on windows
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-17
+
+ show command line help as message box on windows
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-17
+
+ Fix constant background CPU usage
+
+ (cherry picked from commit 59583e97deef732f6884a54b518fc34225fd6012)
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-16
+
+ fix mIconClose.svg
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-16
+
+ fix typo
+
+Martin Dobias <wonder.sk at gmail.com> 2016-09-16
+
+ Added {q} for XYZ tile layers to support Bing maps
+
+ (cherry picked from commit 2e1abdab64efb24f0525f69d21f716753805504a)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-09-16
+
+ [processing] allow all field types as unique ID field in Mean coords alg
+
+ (cherry picked from commit 75269d66b9d79c3b4a2b18bd9626c22840aa6713)
+
+arnaud.morvan at camptocamp.com <arnaud.morvan at camptocamp.com> 2016-09-08
+
+ Fix ParameterGeometryPredicate.getValueAsCommandLineParameter
+
+ (cherry picked from commit d85de7ccd8946ab3ded83abae674554d482dbcf5)
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-14
+
+ fix windows build
+
+ (cherry picked from commit c23e96d3a63df65173452dc2d91fc2562d2d02f7)
+
+Martin Dobias <wonder.sk at gmail.com> 2016-09-16
+
+ [FEATURE] Preview for WMTS + added XYZ tile layers
+
+ This is a port of the functionality from master (to be QGIS 3.0) to 2.x that keeps backward API compatibility.
+
+ - added support for XYZ tile layers to WMS provider
+ - rendering of raster layers can be interrupted, support in WMS provider
+ - temporary preview of tiled layers (WMTS / XYZ) in WMS provider
+
+ WMTS improvements funded by Land Information New Zealand.
+
+ XYZ tile layer funded by Lutra Consulting.
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-09-15
+
+ [processing] fix search by alg name (fix #15562)
+
+ (cherry picked from commit 11f8aa23198b01952660e2c1e7e20c4548c8b224)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-09-15
+
+ [processing] remove obsolete methods
+
+ (cherry picked from commit 6f6979ab0b9b6abfb13c3eb85f680b928fc8b97b)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-15
+
+ Catch exceptions in transform() expression function
+
+ (cherry-picked from 2a8333ef6be003b8c391a72dbed033a33373d677)
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-15
+
+ Improve selected features offline editing performance
+
+rldhont <rldhont at gmail.com> 2016-09-15
+
+ GdalTools: In widgetBatchBase runItem method, refreshArgs is not a SIGNAL
+
+ The commit 9db908ccbc2257d466c0593738944a08cea8a8bc GdalTools: new style signals generates a regression
+ In the widgetBatchBase runItem method, refreshArgs is not a SIGNAL
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-15
+
+ [feature] Add flag to only copy selected features
+
+ This extends the offline editing possibilities to only work on subset of
+ large layers
+
+ Sponsored by DB Fahrwegdienste GmbH
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-09-15
+
+ [processing] correct error message (fix #15511)
+
+ (cherry picked from commit d393734bd3d368f52271838414a3edbf1d4eb1a5)
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-14
+
+ fix windows build (tests & bindings)
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-14
+
+ fix 1e192a4
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-14
+
+ Enable plugins (eg. to show PDFs) in webview widgets used on feature info in identify or in forms
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-14
+
+ remove duplicate svg
+
+ (cherry picked from commit 2d145162ed662be2594fa01330834b2b9f11e609)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-09-14
+
+ partially revert d2189acbb3
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-09-14
+
+ fix indentation
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-09-14
+
+ [processing] refactor offset curve GDAL algorithm (fix #15478)
+
+ (cherry picked from commit cac3b2ddfa7c43239f1c9abc84c965340a5b74b5)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-09-14
+
+ [processing] fix substitution of the original layers in GDAL commands
+
+ (cherry picked from commit 89774abed3740426d8aee4a8413c3a05ec705cad)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-09-14
+
+ [processing] use hex representation of uuid
+
+ (cherry picked from commit 2466083790255c2387fcd84bd6f5c330d272a5c4)
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-14
+
+ @Note added in 2.18
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-14
+
+ Add \ingroup core
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-14
+
+ fix 3.0 version attribution
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-14
+
+ Export QgsOptional<QgsExpression> to dll/so
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-14
+
+ Don't continually refresh map while editing rule label/desc
+
+ (cherry-picked from 2c3548df1111c4709a38d7bacce717711b2a2da7)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-14
+
+ Avoid excessive margins on rule based rule props widget
+
+ (cherry-picked from 9b762023e438d7e44e4fe23fceb7e29c0046e29b)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-11
+
+ When a panel widget opens a new panel, the new panel should inherit
+ the dock mode of the previous panel
+
+ (cherry-picked from 01ec0e423c9d7b729ed7572b9cb2c25484e190e2)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-14
+
+ Fix excessive margins on color picker when in style dock
+
+ (cherry-picked from c9f0901b5be95f9ddd3337a3f8c70f0ed192ca19)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-06
+
+ Fix crash when 'use popup' is selected for time based datetime widgets
+
+ (cherry-picked from 63cc76213979b26e59c17a603dda5e6bfe4463fb)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-10
+
+ Test masks
+
+ (cherry-picked from e3313fac95ea143988ea32bf162b01b4df8e6fa1)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-10
+
+ Make sure items in legend always occupy the set number of columns
+
+ In some cases (eg a legend with 4 items and 3 columns) less
+ columns were being created
+
+ (cherry-picked from 52eef9006183a66d53926f33e73afa1dcd534e59)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-10
+
+ Fix multi column legends with odd number of items would place
+ more items in rightmost columns instead of leftmost columns
+
+ Eg a 2 column legend with 3 items would put 1 item in
+ the first column and 2 in the second. This was ugly, and now
+ it places 2 in the first column and 1 in the second.
+
+ The legend column assigner was incorrectly adding padding above
+ the first item in a column during column size calculation
+ (padding which is not present when actually rendering the column)
+
+ (cherry-picked from a673fa8393146d9a8cd1a3bf6f0444bfa23352d7)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-10
+
+ Add a bunch of tests for legend grouping into columns
+
+ (cherry-picked from 570e6936b655aef2877d2d63c9892f1df05df312)
+
+nirvn <nirvn.asia at gmail.com> 2016-09-13
+
+ [delimitertext] fix watcher check ignored and harmful watcher created for iterator
+ (fixes #15558)
+
+ (cherry-picked from b3e31087181732f7511d047b98352e97f08b0d04)
+
+Marco Bernasocchi <marco at bernawebdesign.ch> 2016-09-11
+
+ qgsmessagebar timeout is not respected in python
+
+ the default timeout is not respected in python
+
+ gui/qgsmessagebar.sip:51: void pushMessage( const QString &text, MessageLevel level = INFO, int duration = 0 );
+
+ https://qgis.org/api/qgsmessagebar_8h_source.html#l00090
+ void pushMessage( const QString &text, MessageLevel level = INFO, int duration = 5 ) { return pushMessage( QString::null, text, level, duration ); }
+
+ (cherry-picked from bb4e6b8fb800b69d28407102a4f17494a4cd5ad9)
+
+Merge: ee9c684 39f7c04
+Matthias Kuhn <matthias at opengis.ch> 2016-09-13
+
+ Merge pull request #3475 from m-kuhn/visibilityTab218
+
+ [Feature] conditional visibility for tabs and groupboxes (backport)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-09-13
+
+ [processing] fix progress reporting (fix #15521)
+
+ (cherry picked from commit b14dfa65fe8c5db852bac0899f8aac64b91faada)
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-09
+
+ Bindings and API docs
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-12
+
+ fix warning fix (followup d4a0e35)
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-12
+
+ fix warnings (followup cc3a053)
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-11
+
+ dxf export: segmentize curves
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-11
+
+ remove pngs which are available as svg
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-08
+
+ [Feature] conditional visibility for tabs and groupboxes
+
+ This adds a new configuration option to conditionally show or hide
+ tabs and groupboxes in drag and drop designer forms.
+
+ Configuration is done via a double click in the designer tree in the
+ fields configuration interface.
+
+ An expression can be entered to control the visibility. The expression
+ will be re-evaluated everytime values in the form change and the tab or
+ groupbox shown/hidden accordingly.
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-08
+
+ Add QgsOptional and QgsOptionalExpression
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-07
+
+ Public default constructor and comparison operator for QgsExpression
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-09
+
+ Add QgsTabWidget
+
+ This is almost like the QTabWidget but has additional methods for
+ showing and hiding individual tabs
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-09
+
+ Use QgsFilterLineEdit for Qgs(Double)SpinBox
+
+ Fixes issues with the current approach:
+ - poor appearance on certain environments (esp OSX)
+ - large area on spin boxes' right which "swallows" clicks
+ and blocks interactivity
+
+ Fix #12920
+
+ (cherry-picked from f16b3870fa21aabb614ab81fa2ddd63b98df75ee)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-09
+
+ Fix cursor not always reset when clearing widget
+
+ (cherry-picked from 228ff23d81a5001a3b323902081264931731a8ef)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-09
+
+ Allow hiding clear button in QgsFilterLineEdit
+
+ (cherry-pick from d959384c8b1aa4efe91cc24ae9ffdc972c43849b)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-09
+
+ Add ability to set default values for QgsFilterLineEdit
+ and have clearing the widget reset to default rather than
+ null
+
+ (cherry-picked from d71453d84ad6821bfa6aa8f745de9dac2eb0b2ba)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-09
+
+ Add unit tests for QgsFilterLineEdit, improve docs, add clearValue slot
+
+ (cherry-picked from edcc247c3e4de5975b9ddbf8fbbe8499a58fe7e1)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-09
+
+ Remove min size from QgsFilterLineEdit
+
+ Now the widget gracefully handles shrinking
+
+ (cherry-picked from 0f5f09401e58b96f0515ce8e379d1fddfa646f4c)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-09-09
+
+ Rework QgsFilterLineEdit handling of clear button
+
+ Don't use a child button but instead paint the icon when
+ required. Improves interaction with the widget/clear
+ button.
+
+ Cherry-picked from 98f25f59e72992d29279bcba9dbba53c5598b2fe
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-08
+
+ debian packaging update: PyQt4.QtWebKit still available on xenial
+ (followup c2f0fff)
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-06
+
+ debian packaging update: add internal QtWebKit bindings
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-03
+
+ translation string fix
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-03
+
+ processing: use main vector menu translation (fixes #14535)
+
+Juergen E. Fischer <jef at norbit.de> 2016-09-03
+
+ oracle provider: add updates on lob fields
+
+Even Rouault <even.rouault at spatialys.com> 2016-09-01
+
+ [DBManager] Fix exception raised when adding a new Spatialite connection
+
+ This was accidentaly broken since 1f0fce7852e9f6a27af967d7ac7ee3989dce7b45
+
+ Fixes #15274
+
+Larry Shaffer <lshaffer at boundlessgeo.com> 2016-09-01
+
+ [auth] Fix return value for plugins that do not support an expansion
+
+ Bug not evident until there were providers with multiple credential
+ expansions (now supported in OWS providers). Lack of support for an
+ expansion should only trigger a debug message, not a failure.
+
+ (cherry-picked from 194b5adb1ed81bcfe7edd78477dfea81cae77aed)
+
+Hugo Mercier <hugo.mercier at oslandia.com> 2016-09-01
+
+ Fix virtual layer queries with accents in layer name
+
+ (cherry-picked from af0d6b93a6)
+
+Matthias Kuhn <matthias at opengis.ch> 2016-09-01
+
+ Export main() when building for android
+
+Hugo Mercier <hugo.mercier at oslandia.com> 2016-07-21
+
+ Snapping: destroy index on dataChanged signal
+
+ Snapping caches on layers that have been changed by the provider or
+ by external sources are now invalidated.
+
+ (cherry-picked from e6fd2e25)
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-30
+
+ db manager: don't consider added layer w/o a dataProvider
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-30
+
+ Fix Capitalize First Letter fails with curved labels (fix #14875)
+
+ Instead of using QFont's inbuilt capitalization support, which
+ applies only on rendering and accordingly fails for curved
+ labels which are drawn one character at a time, we now manually
+ capitalize label text while registering features.
+
+ The capitalize first method from Qt was reimplemented in QgsStringUtils
+ (together with what I expect is better handling of unicode characters
+ over the Qt method).
+
+ This change also makes it possible to implement other capitalization
+ methods not directly supported by Qt
+
+ (cherry-picked from 15dd295)
+
+Martin Dobias <wonder.sk at gmail.com> 2016-08-01
+
+ Fix doc coverage test for "added in XXX" check
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-30
+
+ Fix indentation
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-30
+
+ Move storage of field alias and default value to QgsField
+
+ This is a partial implementation - QMaps are still used internally
+ within QgsVectorLayer to track the alias/default values
+ between attribute edit operations.
+
+ Sponsored by DB Fahrwegdienste GmbH
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-29
+
+ Add a changed signal to QgsEditorConfigWidget
+
+ And update default value expression preview whenever editor
+ config changes
+
+ Sponsored by DB Fahrwegdienste GmbH
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-23
+
+ Use widget representValue to preview default expression results
+
+ Sponsored by DB Fahrwegdienste GmbH
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-22
+
+ Use client side default values when creating new features
+
+ Sponsored by DB Fahrwegdienste GmbH
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-30
+
+ Add UI for setting default field value expressions in the
+ field property dialog
+
+ Sponsored by DB Fahrwegdienste GmbH
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-30
+
+ New QgsExpressionLineEdit widget
+
+ Consists of a filter line edit + button to open expression builder
+
+ This widget is a bit like the existing QgsFieldExpressionWidget,
+ but for cases where a combo box does not make sense. Eg, when
+ no fields are available for the expression to use.
+
+ It also has an optional multiline mode, which allows it to be
+ used in place of the full-blown QgsExpressionBuilderWidget when
+ space is a problem.
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-30
+
+ [FEATURE] Client side default field values
+
+ Allows an expression to be set for a vector layer field which
+ is used to evaluate a default value for this field.
+
+ A new method,
+ QgsVectorLayer::defaultValue( int index,
+ const QgsFeature& feature = QgsFeature(),
+ QgsExpressionContext* context = nullptr )
+ has been added which evaluates the default value for a given field
+ using the optionally passed feature and expression context. This
+ allows default values to utilise properties of the feature
+ which exist at the time of calling, such as digitized geometries.
+ The expression context parameter allows variables to be used
+ in default value expressions, making it easier to eg insert
+ a user's name, current datetime, project path, etc
+
+ Default values are set using QgsVectorLayer::setDefaultValueExpression()
+ and retrieved using defaultValueExpression()
+
+ Sponsored by DB Fahrwegdienste GmbH
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-30
+
+ [FEATURE] Substitution list support for labeling
+
+ Adds the ability to specify a list of text substitutes to make
+ which apply to label text. Eg abbrevating street types.
+
+ Users can export and import lists of substitutes to make
+ reuse and sharing easier.
+
+ (cherry-picked from 46fba7ce80039d5feb8445410ddf98e485f5951f)
+
+Tim Sutton <tim at kartoza.com> 2016-08-22
+
+ Spatialite error message fix (#3416)
+
+ * Fixed issue where opening an invalid spatialite db fails and gives and poor warning message
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-29
+
+ creatensis.pl: use passed in version number
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-29
+
+ Fix bad merge pt 2
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-29
+
+ Fix bad merge
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-29
+
+ Fix calculation of certain aggregates from expressions when no
+ matching features exist
+
+ Eg count should return 0 in this case rather than null
+
+ (cherry-picked from 9ba41e9f275f42a5dfe5c1cdbc0a4d091a0e833f)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-29
+
+ [FEATURE] New expression functions for angle/distance interpolation
+
+ angle_at_vertex: returns average (bisector) angle to a geometry
+ at a specified vertex index
+ distance_to_vertex: returns distance along geometry to a specified
+ vertex index
+ line_interpolate_angle: calculates the angle parallel to a geometry
+ at the specified distance along the geometry
+ line_interpolate_point: returns a point on line at distance
+ line_locate_point: returns distance along line to nearest line
+ location closest to specified point
+
+ Sponsored by Andreas Neumann
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-29
+
+ Add QgsGeometry method to get bisector of angle at vertex
+
+ Sponsored by Andreas Neumann
+
+ (cherry-picked from 986b5313ed72bedbbe4f360e43ff95c8bb2dc81b)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-29
+
+ Make QgsGeometry::interpolate handle polygon geometries
+
+ (cherry-picked from 9a9a49c16ab6fd460059437311739fb266c783bb)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-24
+
+ Add geometry methods for interpolating angle along geometry
+
+ Sponsored by Andreas Neumann
+
+ (cherry-picked from 93c7f5f8b2dc4512f39748d8713eb35fd6e4f5d3)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-21
+
+ [FEATURE] Expose GEOS linear referencing function to QgsGeometry
+
+ Adds a new QgsGeometry::lineLocatePoint() function for
+ retrieving the distance along a linestring to the nearest
+ position on the linestring to a given point.
+
+ (cherry-picked from 409dfdf5395c9136090f28a58678b1d0c66b7543)
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-28
+
+ processing: fix population of commander combobox (fixes #15283)
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-28
+
+ dxf export: link vertices to polyline (fixes #15484)
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch> 2016-08-19
+
+ [FEATURE]: possibility to segmentize feature info geometry in server
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-26
+
+ [browser] Correctly refresh postgres schemas when dropping tables
+
+ (cherry-picked from 5a41748b867505784a091a882a0eb1ca187c4ba8)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-26
+
+ Make QgsVectorDataProvider defaults methods more efficient
+
+ (cherry-picked from a10b8fc3e5658290dd7e18df1001e543c3a75caa)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-26
+
+ Fix limited random color ramp always returns 1 less color than set
+
+ (cherry-picked from 1d98b10904884d8223372fc9248c2825c85591e9)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-25
+
+ Fix potential crash
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-08-23
+
+ fix typo
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-23
+
+ fix switching of projects within unicode folders
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-08-23
+
+ [processing] add missed error() method
+
+ (cherry picked from commit 6a7fa7dd5a199bfa0ced8e4768b910171c3b8e8e)
+
+Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+
+ Followup fixup f10f4a5
+
+Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+
+ Fixup f10f4a5a12bd
+
+Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+
+ Respect the "showLabel" flag on attribute editor elements
+
+Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+
+ [feature] Allow controlling labels for individual edit widgets
+
+ In the drag and drop designer, a double click on an item will allow
+ controlling if the label should be shown for each item individually.
+
+ Fix #15450
+
+Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+
+ Improve wording
+
+ Fix #15456
+
+Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+
+ Sort values in chained filter comboboxes (relation reference)
+
+ Fix #15454
+
+Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+
+ Hide invalid constraints label when it's unused
+
+ Fix #15452
+
+Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+
+ Widget constraints: use field alias where available
+
+ Fix #15455
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-18
+
+ dxf export: avoid symbology scale 0 (fixes #14138)
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-18
+
+ debian packaging update
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+
+ Fix indentation
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+
+ Vertically stack the color widget when in dock mode
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+
+ [FEATURE] Color dialog can be embedded in layer style panel
+
+ Now clicking color buttons inside the layer style panel causes
+ the color picker dialog to be opened inside the style panel itself
+ rather than as a separate dialog
+
+ (cherry-picked from 5407ae8a6ad2a3599081588d1b3f04bbe4c6fe4b)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+
+ New method to find parent QgsPanelWidget for a widget
+
+ (cherry-picked from a2fe4c4f594e2e8d29de65f09271d148ac669028)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+
+ fix repeated labels on curved lines when label width > repeat distance
+
+ (cherry-picked from fb346ecf4fda53ccac7ef939bc6ec84a361a9d58)
+ o
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+
+ [processing] If supported, use memory layers instead of shapefiles
+ when writing to a temporary result
+
+ Avoids truncation of field names and other format specific
+ limitations
+
+ (cherry-picked from 001ae44b67bb2bc542e11d69ab52706e65ae15c5)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+
+ [processing] Fix some potential errors in clip algorithm
+
+ (cherry-picked from f9e10888cbf567b09d334b286c92c918f59c9bfe)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+
+ Make QgsVectorLayer uniqueValues/min/maxValue consider edits
+
+ Previously these methods would inconsistently handle the
+ edit buffer, eg uniqueValues would consider changed attributes
+ but not added features. Now uniqueValues, minimumValue and
+ maximumValue all consider both added features and changed
+ attribute values when performing their calculation.
+
+ The most noticable effect of this fix is that the unique
+ values widget now correctly shows values for features which
+ have been added but not yet committed to the provider.
+
+ (cherry-picked from 50c35929d86ab01b22c29cd129fd7019a1bf624a)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+
+ Don't crash raster shader with nan or inf values (fix #15444)
+
+ (cherry-picked from 34ebe124ff62956095941b5bb76809c6ba4b1a0f)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+
+ Fix some missing autoupdates for raster psuedo color widget
+
+ (cherry-picked from b349eb8a982d762d399ad4c21e3214195e6cd778)
+
+Matthias Kuhn <matthias at opengis.ch> 2016-08-16
+
+ Add isNumeric and QML bindings to QgsField
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-15
+
+ exclude release name from version string
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-15
+
+ debian packaging update
+
+Anita Graser <anitagraser at gmx.at> 2016-08-10
+
+ fixed failure to insert only one point
+
+ Previously, if pointsNumber was 1, it wouldn't insert a new point in the middle.
+ (cherry picked from commit 754ccefabc5c5fb9ba4472b182f1f05cd2a0ebb2)
+
+Merge: 24af533 ace9d2b
+Alessandro Pasotti <elpaso at itopen.it> 2016-08-12
+
+ Merge pull request #3389 from elpaso/timeout_fixes
+
+ Stop the timer when the reply finishes
+
+Alessandro Pasotti <apasotti at boundlessgeo.com> 2016-08-12
+
+ Stop the timer when the reply finish
+
+ This should fix a few reported and unreported issues
+ with false positive timeout errors.
+
+ Fixes: #12243
+
+Denis Rouzaud <denis.rouzaud at gmail.com> 2016-08-12
+
+ followup c4dcfbfb9f8f62ff9445f23061a69daf4f70ada8
+
+Martin Dobias <wonder.sk at gmail.com> 2016-08-11
+
+ Fix closest segment for points (#3383)
+
+ * Make closestSegment() behave as expected by QgsGeometry::closestSegmentWithContext
+
+ This fixes a bug that QgsPointLocator::nearestEdge() would return valid match even for point layers.
+
+ * Shortcut if using QgsPointLocator with a wrong layer type
+
+Juergen E. Fischer <jef at norbit.de> 2016-08-10
+
+ creatensis.pl: exclude point release component from path
+
+ (cherry picked from commit 38229d3ef0db873d0fa434d9dd841533ab2792a0)
+
+Matthias Kuhn <matthias at opengis.ch> 2016-08-10
+
+ Fix crash when clicking in empty relation editor
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ [FEATURE][processing] Point on surface algorithm
+
+ (cherry-picked from 142de7cb08601c3262974cc74689372d4652198c)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ [FEATURE][processing] New algorithm for geometry boundary
+
+ (cherry-picked from ab022451a58196f2c96f6a0482e2155b5171bad5)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ [FEATURE][processing] New algorithm for calculating feature bounding boxes
+
+ (cherry-picked from bd8db5d156071b308f9e091bc444857424879f06)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Label test mask updates
+
+ (cherry-picked from 863c73db8f5ae5142808e56f184dfa290f6647f9)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Reset layers for each pal placement test, avoids all tests failing
+ because of one
+
+ (cherry-picked from 95ecdaf4383a0337710fd98fe34c93323be8e0ad)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Fix warning
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ [pal] Only apply distance from line midpoint penalty to non closed linestrings
+
+ Sponsored by Andreas Neumann
+
+ (cherry-picked from c3f720f80ba8df48a31502c1aee52c0aba2e30be)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Further tweaks to line labeling, add tests
+
+ Sponsored by Andreas Neumann
+
+ (cherry-picked from dc0cc32046dd3c168b86f9e4ca5c1e5f4f57f4fa)
+ o
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ [pal] Also prefer above -> below for parallel line placement
+
+ (cherry-picked from 3b940fbbd0116f2855cac75909bb3ca35e623339)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Labeling tests
+
+ (cherry-picked from 01e6c0498054b6db56262db3ad6b55b29bf389e7)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Add missing sip binding
+
+ (cherry-picked from 37ef6b80073a163b9c1ec040c59cc0a1cb83d72c)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ [pal] Improve line placement algorithm
+
+ Avoid placing labels over jagged sections of lines
+
+ Sponsored by Andreas Neumann
+
+ (cherry-picked from 92ab671979d447bf1de4db2e911645de057bba70)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Slightly increase default maximum angles for curved labels
+
+ The recent improvements to curve label rendering make this possible
+
+ (cherry-picked from 1b1db22a4dadd78b33274c79a97fbe18f569e6ad)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Default to follow placement alignment for labels
+
+ (cherry-picked from dc9ed2b4b5f6a359c70a7bdcc45cb4e69f8090f8)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Default to cartographic label placement for point layers
+
+ It's much nicer than "around point"
+
+ (cherry-picked from 66d4af3922acbd3cdb1f0e25615fd01b5eeb3dee)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Bump default number of label candidates
+
+ Results in much nicer label placement and little to no speed
+ regression in most cases
+
+ (cherry-picked from ed69bf26b2df4d38304605c0c1fe21cc00531a13)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ [pal] When labels can be placed both above and below the line, prefer above
+
+ (cherry-picked from 99521f456ab1a08a59913594a3d6280f780d8b5e)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Avoid labels being marked as overlapping obstacles when features
+ neighbour each other
+
+ (cherry-picked from 655fc93cef99542738cf0eebd371222c35380c80)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ [pal] Respect user set number of line candidates
+
+ The number of positions used for generating line label candidates
+ was hardcoded and was not using the pal number of line candidate
+ setting.
+
+ This change means the number of line candidates can be bumped up
+ resulting in more candidates actually being generated and
+ a better final label placement
+
+ (cherry-picked from 7797e80c66d236fba8524042bc8a3e971de4ab07)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+
+ Fix "label only inside polygon" mode when used with perimeter placement
+
+ The option was not working with perimeter placements as perimeter placements alter
+ the label feature geometry to be a boundary linestring - hence no labels where
+ ever inside this boundary.
+
+ Accordingly this refactors how the force label inside polygon option functions.
+ Now QgsLabelFeatures can have a permissible zone geometry set, such that any
+ label candidates outside of this permissible zone are discarded.
+
+ This approach is more flexible as it could also be used for more labeling options
+ in future, eg discarding label candidates which are too far from a centroid or
+ something.
- fix typo
+ Sponsored by Andreas Neumann
-Juergen E. Fischer <jef at norbit.de> 2016-08-23
+ (cherry-picked from c234d80e1e6c07813140df416b26ad5665b9ab99)
- fix switching of projects within unicode folders
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
- (cherry picked from commit 3951f15b6481a85b551e2f33f26c2aeb6687a24a)
+ [FEATURE] Optimise processing clip algorithm
+ Before the algorithm was written to optimise clipping a few
+ features against thousands of mask features. The revised algorithm
+ is optimised for clipping thousands of input features against
+ a few mask features.
-Alexander Bruy <alexander.bruy at gmail.com> 2016-08-23
+ Given that this second operation is much more likely, it makes
+ sense to optimise for this use case.
- [processing] add missed error() method
+ I've also applied some other optimisations like taking advantage
+ of spatial indexes on the providers, using prepared geometries
+ and also only applying an intersection operation if the geometry
+ isn't wholly contained by the mask geometry.
- (cherry picked from commit 6a7fa7dd5a199bfa0ced8e4768b910171c3b8e8e)
+ Benchmarks:
-Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+ clipping roads layer with 1 million lines against 2 polygons
- Improve wording
+ before: 5 mins 30 seconds
+ after: 10 seconds
- Fix #15456
+ clipping address layer with 5 million points against 2 polygons
-Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+ before: 50 minutes
+ after: 30 seconds
- Hide invalid constraints label when it's unused
+ (cherry-picked from 71ebdb8f693672fdfc297e529fa20b5cd63779d9)
- Fix #15452
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
-Matthias Kuhn <matthias at opengis.ch> 2016-08-19
+ [processing] Add tests for clip algorithm
- Widget constraints: use field alias where available
+ (cherry-picked from 2db7fca7a653a3d417b98d8236a10491ab97b0a5)
- Fix #15455
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
-Juergen E. Fischer <jef at norbit.de> 2016-08-18
+ [processing] Allow modification of feature request when using
+ vector.features
- dxf export: avoid symbology scale 0 (fixes #14138)
+ Allows for optimising the request through subsets of attributes
+ or no geometry fetching
- (cherry picked from commit 0a07fee15297e18a73b63f194f5aeecffd76800c)
+ (cherry-picked from 9e1ddcb54d4399b2ca90b8a854a592f4fd1a7653)
-Juergen E. Fischer <jef at norbit.de> 2016-08-18
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
- debian packaging update
+ Fix expected test data
- (cherry picked from commit 127fb683b226908c4f34a78a8fa1e43965a51dfa)
+ (cherry-picked from 4bfdcf0927146759325d9c65ca358e1777c22d05)
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
- fix repeated labels on curved lines when label width > repeat distance
+ [FEATURE] Make processing dissolve algorithm accept multiple fields
- (cherry-picked from fb346ecf4fda53ccac7ef939bc6ec84a361a9d58)
- o
+ This allows you to dissolve based on more than one field value
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+ (cherry-picked from bb54b4f41a726737d5d28a71632ed29a9a8045df)
- Make QgsVectorLayer uniqueValues/min/maxValue consider edits
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
- Previously these methods would inconsistently handle the
- edit buffer, eg uniqueValues would consider changed attributes
- but not added features. Now uniqueValues, minimumValue and
- maximumValue all consider both added features and changed
- attribute values when performing their calculation.
+ Make test layer comparison handle different order of features
- The most noticable effect of this fix is that the unique
- values widget now correctly shows values for features which
- have been added but not yet committed to the provider.
+ (cherry-picked from f449bf236198ced18bbd7078144f12a9aab77cd0)
- (cherry-picked from 50c35929d86ab01b22c29cd129fd7019a1bf624a)
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+ [processing] Fix broken multi field selection widget
- Don't crash raster shader with nan or inf values (fix #15444)
+ (cherry-picked from fda93dfc574a152be2509d7f370af073abd3ba37)
- (cherry-picked from 34ebe124ff62956095941b5bb76809c6ba4b1a0f)
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-17
+ [processing] Fix multipart to singlepart handling of null geometry
- Fix some missing autoupdates for raster psuedo color widget
+ (cherry-picked from 0455b6600d2ab443ea8d691e3c007ee481a30910)
- (cherry-picked from b349eb8a982d762d399ad4c21e3214195e6cd778)
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
-Juergen E. Fischer <jef at norbit.de> 2016-08-15
+ [processing] Add test for dissolve using field values
- exclude release name from version string (fixes #15258)
+ (cherry-picked from ccfd4c36be2234c31980dc84a3711c525229b4f5)
- (cherry picked from commit 1391aad2f713a796b0ac3d0c22bec6c1c7ada3bb)
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
-Juergen E. Fischer <jef at norbit.de> 2016-08-15
+ Add processing test .aux.xml to .gitignore
- debian packaging update
+ (cherry-picked from 0939dbf9df5d0cb6867a4d0b3ea6a543eea77366)
- (cherry picked from commit 977b5f2b8c9d5ee93e166a7c95f1f70fc2e800ec)
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
-Anita Graser <anitagraser at gmx.at> 2016-08-10
+ [FEATURE][processing] New algorithm for merging connected lines
- fixed failure to insert only one point
+ This algorithm joins all connected parts of MultiLineString
+ geometries into single LineString geometries.
- Previously, if pointsNumber was 1, it wouldn't insert a new point in the middle.
- (cherry picked from commit 754ccefabc5c5fb9ba4472b182f1f05cd2a0ebb2)
+ If any parts of the input MultiLineString geometries are not
+ connected, the resultant geometry will be a MultiLineString
+ containing any lines which could be merged and any non-connected
+ line parts.
-Larry Shaffer <lshaffer at boundlessgeo.com> 2016-08-10
+ (cherry-picked from 30fcaed634aa43d01528a031fd8f2d255f97f837)
- [auth] Add missing auth system ui headers for external C++ apps
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
- (cherry-picked from f3e90f1d5a87b2a7c6c693aa8ba3eaad64161b1d)
+ Improve polygon perimeter labeling
-Matthias Kuhn <matthias at opengis.ch> 2016-08-10
+ This commit changes the way polygon perimeter labeling works.
+ Previously the polygon would be clipped to the view extent, and
+ then the boundary of the clipped polygon used for perimeter
+ labeling.
- Fix crash when clicking in empty relation editor
+ This tended to push the labels to the outside of the map extent
+ (the clip boundary), since that's the longest straight section
+ of the resultant geometry.
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+ Now, the boundary is taken *before* the clip, so that perimeter
+ based labels will never be placed on the artificial boundary
+ created at the map's extent.
- Reset layers for each pal placement test, avoids all tests failing
- because of one
+ (cherry-picked from 27697e6efc32f67e9ff31cf784d294178c221be2)
- (cherry-picked from 95ecdaf4383a0337710fd98fe34c93323be8e0ad)
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-10
+ [FEATURE] Label polygons using curved labels along perimeter
- Fix "label only inside polygon" mode when used with perimeter placement
+ This adds a new mode for labeling polygons, where the perimeter
+ of the polygon is labeled using curved labeling.
- The option was not working with perimeter placements as perimeter placements alter
- the label feature geometry to be a boundary linestring - hence no labels where
- ever inside this boundary.
+ (cherry-picked from 5f33991e7bcd95069ba88e01cafa7078bbad5f24)
- Accordingly this refactors how the force label inside polygon option functions.
- Now QgsLabelFeatures can have a permissible zone geometry set, such that any
- label candidates outside of this permissible zone are discarded.
+Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
- This approach is more flexible as it could also be used for more labeling options
- in future, eg discarding label candidates which are too far from a centroid or
- something.
+ [FEATURE] Expression function for calculating geometry boundary
- Sponsored by Andreas Neumann
+ The new 'boundary(...)' function returns a geometry's topological
+ boundary, ie for polygons this is a multilinestring representing
+ the polygons rings
- (cherry-picked from c234d80e1e6c07813140df416b26ad5665b9ab99)
+ (cherry-picked from 1a4ceb1680e9adb4dd78c1bc11887c5a05ba0d19)
Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
- Make test layer comparison handle different order of features
-
- (cherry-picked from f449bf236198ced18bbd7078144f12a9aab77cd0)
+ Add method to QgsAbstractGeometryV2 for boundary
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
+ Returns the closure of the combinatorial boundary of the
+ geometry (ie the topological boundary of the geometry).
+ For instance, a polygon geometry will have a boundary
+ consisting of the linestrings for each ring in the polygon.
- [processing] Fix broken multi field selection widget
+ Follows OGC / SQL/MM specs for boundary calculation
- (cherry-picked from fda93dfc574a152be2509d7f370af073abd3ba37)
+ (cherry-picked from 85f37eebb3685db6005842b40ac5b39b35a77122)
Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
- [processing] Fix multipart to singlepart handling of null geometry
-
- (cherry-picked from 0455b6600d2ab443ea8d691e3c007ee481a30910)
+ [FEATURE] API + expression function for merging linestrings
-Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
+ Adds a new method to QgsGeometry for merging linestrings.
+ By passing a multilinestring, any connected lines will
+ be joined into single linestrings. Behind the scenes this
+ uses GEOS' line merge.
- Add processing test .aux.xml to .gitignore
+ A corresponding expression function "line_merge" has also
+ been added.
- (cherry-picked from 0939dbf9df5d0cb6867a4d0b3ea6a543eea77366)
+ (cherry-picked from 10c92394e7ccacb7dacef163f04ae7bdc0d910b1)
Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
@@ -537,13 +2705,6 @@ Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
(cherry-picked from 06c4b07222f9410e1669387a6497897c61748a16)
-Merge: 005d467 f49bd5c
-Alessandro Pasotti <elpaso at itopen.it> 2016-08-09
-
- Merge pull request #3368 from elpaso/wfs_fixes
-
- Try to fix #15360
-
Alessandro Pasotti <apasotti at boundlessgeo.com> 2016-08-08
[WFS] Fixes #15360 and other issues
@@ -553,6 +2714,8 @@ Alessandro Pasotti <apasotti at boundlessgeo.com> 2016-08-08
- fixes version parameter ignored in old style URI
- check for "user" in addition to "username" in WFS URI
+ (cherry-picked from f49bd5ca449e332aa547f9dac31b391e438d2b31)
+
Nyall Dawson <nyall.dawson at gmail.com> 2016-08-09
Implement provider side FilterFids iterators for OGR provider
@@ -575,32 +2738,20 @@ Even Rouault <even.rouault at spatialys.com> 2016-08-08
[WFS provider] Succesfully analyze DescribeFeatureType response with <complexType> as inline element of <element> (#15395)
-Juergen E. Fischer <jef at norbit.de> 2016-08-04
-
- debian packaging update
-
- (cherry picked from commit aef87037254729583590102e86a59ea51262cf78)
+Alexander Bruy <alexander.bruy at gmail.com> 2016-08-02
-Alexander Bruy <alexander.bruy at gmail.com> 2016-07-25
+ [dbmanager] fix signal/slot connection
- [processing] always use user-defined default folder for scripts/models
+ (cherry picked from commit 2134112aab2defda41e8d16c3ddd27a17e66f553)
- (cherry picked from commit 48cca3bc12e874d681669b47ce2ee24b96baa4de)
+Juergen E. Fischer <jef at norbit.de> 2016-08-04
- Conflicts:
- python/plugins/processing/modeler/AddModelFromFileAction.py
- python/plugins/processing/script/AddScriptFromFileAction.py
+ debian packaging update
Matthias Kuhn <matthias at opengis.ch> 2016-08-03
Don't show scrollbar in embedded drag and drop designer form
-Juergen E. Fischer <jef at norbit.de> 2016-07-31
-
- debian packaging update
-
- (cherry picked from commit 750e60fe19eb89489e5e0803717dbbfabfb75e0e)
-
Juergen E. Fischer <jef at norbit.de> 2016-08-03
fix crash when QSQLITE is unavailable (fixes #15358)
@@ -626,32 +2777,35 @@ Alexander Bruy <alexander.bruy at gmail.com> 2016-08-01
(cherry picked from commit 98a55274063fcfe8174b3c3d0369d72d5e2f7c73)
-Juergen E. Fischer <jef at norbit.de> 2016-07-29
+Juergen E. Fischer <jef at norbit.de> 2016-07-31
- Release of 2.16.1
+ debian packaging update
-Nyall Dawson <nyall.dawson at gmail.com> 2016-07-29
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-27
- Fix map not refreshed after using pan to selected (fix #15324)
+ Add labeling tests for letter/word spacing
- (cherry-picked from 530a85216ee63db320196fd808f8eb654ac918d7)
+ (cherry-picked from 3d6688cce5598d0c09d13f2cd8db30f1f073e928)
-Nyall Dawson <nyall.dawson at gmail.com> 2016-07-29
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-26
- [gui] gray lock icon, and flat style for extent button
+ Update curved label test reference images
- (cherry-picked from 6bd15ff79e0c9f749595a1e2d6439fd15edfd1e8)
+ (cherry-picked from 5228de353c84337b3d753fe15c47ee09ecb2643a)
-Merge: 4fadd79 3224e9c
-Tom Kralidis <tomkralidis at gmail.com> 2016-07-27
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-27
- Merge pull request #3342 from tomkralidis/owslib-0.11.2
+ [labels] Fix word and letter spacing truncated to integers
- upgrade OWSLib to 0.11.2
+ (cherry-picked from 449fcad8ce0808780cf662362cf5c6568abd09bb)
-Tom Kralidis <tomkralidis at gmail.com> 2016-07-25
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-27
- upgrade OWSLib to 0.11.2
+ [labeling] Curved labels are now angled per character
+
+ ...instead of shifted along base line (fix #15210)
+
+ (cherry-picked from 22fdb6ab9fcb076f3f3e8601fa4bdc7e0894a103)
Nyall Dawson <nyall.dawson at gmail.com> 2016-07-27
@@ -673,31 +2827,57 @@ Nyall Dawson <nyall.dawson at gmail.com> 2016-07-27
(cherry-picked from c0b1684058a5acf3ae58ea63bea7b00520e27725)
-Nyall Dawson <nyall.dawson at gmail.com> 2016-07-27
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-29
- Add labeling tests for letter/word spacing
+ [gui] gray lock icon, and flat style for extent button
- (cherry-picked from 3d6688cce5598d0c09d13f2cd8db30f1f073e928)
+ (cherry-picked from 6bd15ff79e0c9f749595a1e2d6439fd15edfd1e8)
-Nyall Dawson <nyall.dawson at gmail.com> 2016-07-26
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-29
- Update curved label test reference images
+ Fix map not refreshed after using pan to selected (fix #15324)
- (cherry-picked from 5228de353c84337b3d753fe15c47ee09ecb2643a)
+ (cherry-picked from 530a85216ee63db320196fd808f8eb654ac918d7)
-Nyall Dawson <nyall.dawson at gmail.com> 2016-07-27
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-28
- [labels] Fix word and letter spacing truncated to integers
+ [processing] use '-te_crs' parameter only if supported by GDAL
- (cherry-picked from 449fcad8ce0808780cf662362cf5c6568abd09bb)
+ (cherry picked from commit 7f6bae1f5e149ed9170835310676d1340de26cd4)
-Nyall Dawson <nyall.dawson at gmail.com> 2016-07-27
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-28
- [labeling] Curved labels are now angled per character
+ [GdalTools] add missed signals (fix #15348)
+ follow up 9db908ccbc
- ...instead of shifted along base line (fix #15210)
+ (cherry picked from commit 572a60b7afdb78f8642d958b0cf7c3b7771ddcdf)
- (cherry-picked from 22fdb6ab9fcb076f3f3e8601fa4bdc7e0894a103)
+Merge: bf77d09 7ead969
+Tom Kralidis <tomkralidis at gmail.com> 2016-07-27
+
+ Merge pull request #3340 from tomkralidis/owslib-0.11.2
+
+ upgrade OWSLib to 0.11.2
+
+Tom Kralidis <tomkralidis at gmail.com> 2016-07-25
+
+ upgrade OWSLib to 0.11.2
+
+rldhont <rldhont at gmail.com> 2016-07-20
+
+ [DB Manager] Add the ability to update SQL Layer
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-26
+
+ [processing] fix issues with exported layers in GDAL provider
+
+ (cherry picked from commit b3a38f4018e7b34550f39cffa8bf1197f011dc1e)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-26
+
+ [processing] fix condition in warp alg
+
+ (cherry picked from commit 6ccf7264a672d4d256d4803b2c184fd818c64f91)
Nyall Dawson <nyall.dawson at gmail.com> 2016-07-26
@@ -708,6 +2888,28 @@ Nyall Dawson <nyall.dawson at gmail.com> 2016-07-26
Nyall Dawson <nyall.dawson at gmail.com> 2016-07-26
+ [FEATURE] Add an option to show user color schemes menus
+
+ This adds the ability for users to set whether a user created
+ color scheme should show up in the color button drop-down menus.
+
+ It's accessed through the color picker dialog, on the lists tab.
+ Just add a new color scheme, then from the scheme menu tick the
+ new "show in buttons" option.
+
+ Handy if you have sets of common palettes and want them to be
+ instantly available through the color menu.
+
+ (cherry-picked from 12a21474276322084e9c67ad46dd68aa486c34f1)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-21
+
+ Add apply buttons to annotation dialogs
+
+ (cherry-picked from 03527452d79c7e712fa494755f7fc71daeaf2a74)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-26
+
[composer] Fix editing of map item variables
On behalf of Faunalia, sponsored by ENEL
@@ -773,12 +2975,82 @@ Nyall Dawson <nyall.dawson at gmail.com> 2016-07-26
(cherry-picked from 6dac8e18bd828bbccfa9971b7cb6fee417c0a068)
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-25
+
+ [plugin manager] mark installed plugins as trusted (fix #15338)
+
+ (cherry picked from commit 156c09880be34348ed672c92cfb6178527902b43)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-25
+
+ [processing] fix dialog title
+
+ (cherry picked from commit 01dd33867772ffa5a07d497b2f4b149383182c4c)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-25
+
+ [processing] always use user-defined default folder for scripts/models
+
+ (cherry picked from commit 48cca3bc12e874d681669b47ce2ee24b96baa4de)
+
+ Conflicts:
+ python/plugins/processing/script/AddScriptFromFileAction.py
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-25
+
+ [processing] use default models folder when adding model from file (fix #15335)
+
+ (cherry picked from commit b167c09e4412b1bf8559020a529b80e520b28b22)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-25
+
+ [processing] different shortcut for commander (fix #15334)
+
+ (cherry picked from commit 4e94963af54894a3811ea8c44cbb6523ceec4ea0)
+
+Juergen E. Fischer <jef at norbit.de> 2016-07-24
+
+ update splash
+
+ (cherry picked from commit 2bbfe8a6f901aaa38ef6a632da31500b710b1116)
+
Juergen E. Fischer <jef at norbit.de> 2016-07-23
oracle provider: fix binding of output values
(cherry picked from commit 1368038ca93ce923cae7f507f5f387690a2f3136)
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-22
+
+ [processing] also fix case without dissolving
+
+ (cherry picked from commit 2fbb617d618c31ca9ba0d412712ca6ac823ace04)
+
+Alexander Bruy <alexander.bruy at gmail.com> 2016-07-22
+
+ [processing] fix buffer tool
+
+ (cherry picked from commit 9976c30c9aa7b0134b7e72e64157ac9fdb0b042f)
+
+Juergen E. Fischer <jef at norbit.de> 2016-07-22
+
+ debian packing build with webkit on xenial
+
+ (cherry picked from commit e8bac30230e20a2d15152711aca7589c5648da58)
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-11
+
+ Followups and fixes to identify results linking
+
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-11
+
+ [FEATURE] Mouse wheel over sliders in color dialog to change value by
+ increments
+
+Sandro Mani <manisandro at gmail.com> 2015-09-03
+
+ [FEATURE] Make links in feature identify results clickable
+
Nyall Dawson <nyall.dawson at gmail.com> 2016-07-19
[composer] Load all composition properties from template/duplicate
@@ -812,8 +3084,6 @@ Nyall Dawson <nyall.dawson at gmail.com> 2016-07-19
On behalf of Faunalia, sponsored by ENEL
- (cherry-picked from c7ffdfa5e991743e862f10ae2dbec2c05c4b795c)
-
Nyall Dawson <nyall.dawson at gmail.com> 2016-07-19
[composer] Avoid crash when atlas page name field has spaces
@@ -914,15 +3184,19 @@ Nyall Dawson <nyall.dawson at gmail.com> 2016-07-19
(cherry-picked from 7d822f01c7aff8a58fcb9116855a94362f43d367)
-Nyall Dawson <nyall.dawson at gmail.com> 2016-07-19
+Nyall Dawson <nyall.dawson at gmail.com> 2016-07-20
[oracle] Fix minor Coverity issues
(cherry-picked from b94fbc0485b3998312749327974bf8e8f49504a9)
-Etienne Trimaille <etienne at Etiennes-MacBook-Pro.local> 2016-07-12
+Juergen E. Fischer <jef at norbit.de> 2016-07-15
+
+ creatensis.pl: use version number instead of release name for installation path
+
+Matthias Kuhn <matthias at opengis.ch> 2016-07-12
- add qscintilla to cmakelists
+ Use Q_FOREACH
Matthias Kuhn <matthias at opengis.ch> 2016-07-12
@@ -934,6 +3208,10 @@ Matthias Kuhn <matthias at opengis.ch> 2016-07-12
Matthias Kuhn <matthias at opengis.ch> 2016-07-12
+ Add missing bindings
+
+Matthias Kuhn <matthias at opengis.ch> 2016-07-12
+
Fix single process build
A race condition triggered that sometimes the file
@@ -969,18 +3247,24 @@ nirvn <nirvn.asia at gmail.com> 2016-07-11
Juergen E. Fischer <jef at norbit.de> 2016-07-10
- msvc: use /bigobj for sip modules
+ fix 39d6e79
+
+ (cherry picked from commit 2f9ed29d9a5ec7fa79c7f902f036a81c43b8a2da)
+
+Matthias Kuhn <matthias at opengis.ch> 2016-07-05
+
+ Create some properties on QgsProject
Juergen E. Fischer <jef at norbit.de> 2016-07-10
- fix 39d6e79
+ fix typos and debian/copyright
+
+ (cherry picked from commit 2eee2e5c9cd771b0a4c8603b9db83ce516f63891)
Juergen E. Fischer <jef at norbit.de> 2016-07-10
support utf-8 encoded release names
- (cherry picked from commit c9838ccea481c8ca87c4e1647099cfe78777e795)
-
Bas Couwenberg <sebastic at xs4all.nl> 2016-07-09
Fix installation path of scalable icons.
@@ -989,7 +3273,7 @@ Bas Couwenberg <sebastic at xs4all.nl> 2016-07-09
Juergen E. Fischer <jef at norbit.de> 2016-07-08
- Release of 2.16 (Nødebo)
+ New development branch for interim 2.x releases
Juergen E. Fischer <jef at norbit.de> 2016-07-08
diff --git a/NEWS b/NEWS
index c60e588..1d8625c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,49 +1,80 @@
QGIS News
Change history for the QGIS Project
-Friday July 08, 2016
+Friday October 21, 2016
------------------------------------------------------------------------
- 1. What's new in Version 2.16 'Nødebo'?
- 2. What's new in Version 2.14 'Essen'?
- 3. What's new in Version 2.12 'Lyon'?
- 4. What's new in Version 2.10 'Pisa'?
- 5. What's new in Version 2.8 'Wien'?
- 6. What's new in Version 2.6.0 'Brighton'?
- 7. What's new in Version 2.4.0 'Chugiak'?
- 8. Whats new in Version 2.2.0 'Valmiera'?
- 9. Whats new in Version 2.0.1 'Dufour'?
- 10. Whats new in Version 2.0.0 'Dufour'?
- 11. Whats new in Version 1.8.0 'Lisboa'?
- 12. Whats new in Version 1.7.2 'Wroclaw'?
- 13. Whats new in Version 1.7.1 'Wroclaw'?
- 14. Whats new in Version 1.7.0 'Wroclaw'?
- 15. Whats new in Version 1.6.0 'Capiapo'?
- 16. Whats new in Version 1.5.0?
- 17. Whats new in Version 1.4.0 'Enceladus'?
- 18. Whats new in Version 1.3.0 'Mimas'?
- 19. Version 1.2.0 'Daphnis'
- 20. Version 1.0.0 'Kore'
- 21. Version 0.11.0 'Metis'
- 22. Version 0.10.0 'Io'
- 23. Version 0.9.2rc1 'Ganymede'
- 24. Version 0.9.1 'Ganymede'
- 25. Version 0.9 'Ganymede'
- 26. Version 0.8 'Joesephine' .... development version
- 27. Version 0.6 'Simon'
- 28. 0.5
+ 1. What's new in Version 2.18 'Las Palmas'?
+ 2. What's new in Version 2.16 'Nødebo'?
+ 3. What's new in Version 2.14 'Essen'?
+ 4. What's new in Version 2.12 'Lyon'?
+ 5. What's new in Version 2.10 'Pisa'?
+ 6. What's new in Version 2.8 'Wien'?
+ 7. What's new in Version 2.6.0 'Brighton'?
+ 8. What's new in Version 2.4.0 'Chugiak'?
+ 9. Whats new in Version 2.2.0 'Valmiera'?
+ 10. Whats new in Version 2.0.1 'Dufour'?
+ 11. Whats new in Version 2.0.0 'Dufour'?
+ 12. Whats new in Version 1.8.0 'Lisboa'?
+ 13. Whats new in Version 1.7.2 'Wroclaw'?
+ 14. Whats new in Version 1.7.1 'Wroclaw'?
+ 15. Whats new in Version 1.7.0 'Wroclaw'?
+ 16. Whats new in Version 1.6.0 'Capiapo'?
+ 17. Whats new in Version 1.5.0?
+ 18. Whats new in Version 1.4.0 'Enceladus'?
+ 19. Whats new in Version 1.3.0 'Mimas'?
+ 20. Version 1.2.0 'Daphnis'
+ 21. Version 1.0.0 'Kore'
+ 22. Version 0.11.0 'Metis'
+ 23. Version 0.10.0 'Io'
+ 24. Version 0.9.2rc1 'Ganymede'
+ 25. Version 0.9.1 'Ganymede'
+ 26. Version 0.9 'Ganymede'
+ 27. Version 0.8 'Joesephine' .... development version
+ 28. Version 0.6 'Simon'
+ 29. 0.5
------------------------------------------------------------------------
-Last Updated: Friday July 08, 2016
-Last Change : Friday July 08, 2016
+Last Updated: Friday October 21, 2016
+Last Change : Friday October 21, 2016
- 1. What's new in Version 2.16 'Nødebo'?
+ 1. What's new in Version 2.18 'Las Palmas'?
+ ===========================================
+
+This release has following new features:
+
+- Symbology: Color picker is now embedded in layer style panel
+- Labelling: Substitution list support for labeling
+- Labelling: Improved line label placement algorithm
+- Labelling: Label polygons using curved labels along perimeter
+- Data Management: Add flag to only copy selected features
+- Forms and Widgets: Allow controlling labels for individual edit widgets
+- Forms and Widgets: Conditional visibility for tabs and group boxes
+- Forms and Widgets: Client side default field values
+- Map Composer: True North Arrows
+- Processing: Point on surface algorithm added
+- Processing: New algorithm for geometry boundary
+- Processing: New algorithm for calculating feature bounding box
+- Processing: Processing dissolve algorithm accepts multiple fields
+- Processing: Optimised processing clip algorithm
+- Processing: New algorithm for merging connected lines
+- General: Automatic links in identify results
+- General: Mouse wheel over color dialog sliders
+- General: Add custom color schemes to color button drop down menu
+- Data Providers: Preview for WMTS + added XYZ tile layers
+- QGIS Server: Possibility to segmentize feature info geometry in server
+- Plugins: DB Manager: Add the ability to update SQL Layer
+- Programmability: New expression functions
+- Programmability: Expose GEOS linear referencing function to QgsGeometry
+
+
+ 2. What's new in Version 2.16 'Nødebo'?
========================================
This release has following new features:
@@ -140,7 +171,7 @@ This release has following new features:
- Programmability: Plugins can add pages to vector layer properties
- 2. What's new in Version 2.14 'Essen'?
+ 3. What's new in Version 2.14 'Essen'?
======================================
This release has following new features:
@@ -216,7 +247,7 @@ This release has following new features:
- User Interface : Show/hide all legend items via the the context menu
- 3. What's new in Version 2.12 'Lyon'?
+ 4. What's new in Version 2.12 'Lyon'?
=====================================
This release has following new features:
@@ -270,7 +301,7 @@ This release has following new features:
- Symbology : Add pixels as option for all symbology size unit choices
- 4. What's new in Version 2.10 'Pisa'?
+ 5. What's new in Version 2.10 'Pisa'?
=====================================
This is a minor release increment with the following new features:
@@ -318,7 +349,7 @@ This is a minor release increment with the following new features:
- User interface improvements.
- 5. What's new in Version 2.8 'Wien'?
+ 6. What's new in Version 2.8 'Wien'?
====================================
This is a minor release increment with the following feature:
@@ -351,7 +382,7 @@ This is a minor release increment with the following feature:
DescribeLayer, python plugins.
- 6. What's new in Version 2.6.0 'Brighton'?
+ 7. What's new in Version 2.6.0 'Brighton'?
==========================================
This is a minor release increment with the following new features:
@@ -397,7 +428,7 @@ This is a minor release increment with the following new features:
- Context menu for identify tool
- 7. What's new in Version 2.4.0 'Chugiak'?
+ 8. What's new in Version 2.4.0 'Chugiak'?
=========================================
This is the minor release sports a number of great new features:
@@ -417,7 +448,7 @@ This is the minor release sports a number of great new features:
- New Inverted Polygon renderer
- 8. Whats new in Version 2.2.0 'Valmiera'?
+ 9. Whats new in Version 2.2.0 'Valmiera'?
=========================================
This is the minor release sports a number of great new features:
@@ -458,15 +489,15 @@ This is the minor release sports a number of great new features:
- 'Processing' can be used headless in scripts.
- 9. Whats new in Version 2.0.1 'Dufour'?
- =======================================
+ 10. Whats new in Version 2.0.1 'Dufour'?
+ ========================================
This is a small bugfix release to address the missing copyright / credits for
our new splash screen and to update supporting documentation. The spanish
translation was also updated.
- 10. Whats new in Version 2.0.0 'Dufour'?
+ 11. Whats new in Version 2.0.0 'Dufour'?
========================================
This is a new major release. Building on the foundation of
@@ -552,7 +583,7 @@ key new features.
you to explore the software and discover them all!
- 11. Whats new in Version 1.8.0 'Lisboa'?
+ 12. Whats new in Version 1.8.0 'Lisboa'?
========================================
This is a new feature release. Building on the foundation of
@@ -607,7 +638,7 @@ added gdal_fillnodata to GDALTools plugin
- Support for nesting projects within other projects
- 12. Whats new in Version 1.7.2 'Wroclaw'?
+ 13. Whats new in Version 1.7.2 'Wroclaw'?
=========================================
This is a bugfix release over version 1.7.1. The following changes
@@ -654,7 +685,7 @@ were made.
- Fix broken Assign projection functionality in GDALTools and improve handling output file extension
- 13. Whats new in Version 1.7.1 'Wroclaw'?
+ 14. Whats new in Version 1.7.1 'Wroclaw'?
=========================================
This is a bugfix release over version 1.7.0. The following changes
@@ -717,7 +748,7 @@ http://linfiniti.com/2011/08/improvements-to-raster-performance-in-qgis-master/]
- Fixed a bug where map= was not being published in onlineresource url when project files are not in the same dir as cgi
- 14. Whats new in Version 1.7.0 'Wroclaw'?
+ 15. Whats new in Version 1.7.0 'Wroclaw'?
=========================================
This release is named after the town of Wroclaw in Poland. The Department of
@@ -734,7 +765,7 @@ enhancements. Once again it is impossible to document everything here that has
changed so we will just provide a bullet list of key new features here.
- 14.1. Symbology labels and diagrams
+ 15.1. Symbology labels and diagrams
===================================
- New symbology now used by default!
@@ -752,7 +783,7 @@ changed so we will just provide a bullet list of key new features here.
- Move/rotate/change label edit tools to interactively change data defined label properties.
- 14.2. New Tools
+ 15.2. New Tools
===============
- Added GUI for gdaldem.
@@ -761,7 +792,7 @@ changed so we will just provide a bullet list of key new features here.
- Added voronoi polygon tool to Vector menu.
- 14.3. User interface updates
+ 15.3. User interface updates
============================
- Allow managing missing layers in a list.
@@ -772,7 +803,7 @@ changed so we will just provide a bullet list of key new features here.
- General clean-ups and usability improvements.
- 14.4. CRS Handling
+ 15.4. CRS Handling
==================
- Show active crs in status bar.
@@ -782,7 +813,7 @@ changed so we will just provide a bullet list of key new features here.
- Default to last selection when prompting for CRS.
- 14.5. Rasters
+ 15.5. Rasters
=============
- Added AND and OR operator for raster calculator
@@ -791,7 +822,7 @@ changed so we will just provide a bullet list of key new features here.
- Added raster toolbar with histogram stretch functions.
- 14.6. Providers and Data Handling
+ 15.6. Providers and Data Handling
=================================
- New SQLAnywhere vector provider.
@@ -817,7 +848,7 @@ changed so we will just provide a bullet list of key new features here.
- Allow OGR 'save as' without attributes (for eg. DGN/DXF).
- 14.7. Api and Developer Centric
+ 15.7. Api and Developer Centric
===============================
- Refactored attribute dialog calls to QgsFeatureAttribute.
@@ -829,7 +860,7 @@ changed so we will just provide a bullet list of key new features here.
new QgsGeometry.validateGeometry function
- 14.8. QGIS Mapserver
+ 15.8. QGIS Mapserver
====================
- Ability to specify wms service capabilities in the properties
@@ -837,7 +868,7 @@ changed so we will just provide a bullet list of key new features here.
- Support for wms printing with GetPrint-Request.
- 14.9. Plugins
+ 15.9. Plugins
=============
- Support for icons of plugins in the plugin manager dialog.
@@ -845,13 +876,13 @@ changed so we will just provide a bullet list of key new features here.
- Removed ogr converter plugin - use 'save as' context menu rather.
- 14.10. Printing
+ 15.10. Printing
===============
- Undo/Redo support for the print composer
- 15. Whats new in Version 1.6.0 'Capiapo'?
+ 16. Whats new in Version 1.6.0 'Capiapo'?
=========================================
Please note that this is a release in our 'cutting edge' release series. As
@@ -863,7 +894,7 @@ Once again it is impossible to document everything here that has changed so we w
just provide a bullet list of key new features here.
- 15.1. General Improvements
+ 16.1. General Improvements
==========================
- Added gpsd support to live gps tracking.
@@ -897,7 +928,7 @@ caching providers (currently WMS and WFS) can synchronize with changes in
the datasource.
- 15.2. Table of contents (TOC) improvements
+ 16.2. Table of contents (TOC) improvements
==========================================
- Added a new option to the raster legend menu that will stretch the current
@@ -907,14 +938,14 @@ as' option, you can now specify OGR creation options.
- In the table of contents, it is now possible to select and remove several layers at once.
- 15.3. Labelling (New generation only)
+ 16.3. Labelling (New generation only)
=====================================
- Data defined label position in labeling-ng.
- Line wrapping, data defined font and buffer settings for labeling-ng.
- 15.4. Layer properties and symbology
+ 16.4. Layer properties and symbology
====================================
- Three new classification modes added to graduated symbol renderer (version
@@ -935,7 +966,7 @@ the transparency table in the raster layer properties dialog.
the style manager more easily.
- 15.5. Map Composer
+ 16.5. Map Composer
==================
- add capability to show and manipulate composer item width/ height in item
@@ -944,7 +975,7 @@ position dialog.
- Sorting for composer attribute table (several columns and ascending / descending).
- 16. Whats new in Version 1.5.0?
+ 17. Whats new in Version 1.5.0?
===============================
Please note that this is a release in our 'cutting edge' release series. As
@@ -959,7 +990,7 @@ Once again it is impossible to document everything here that has changed so we w
just provide a bullet list of key new features here.
- 16.1. Main GUI
+ 17.1. Main GUI
==============
- There is a new angle measuring tool that allows you to interactively
@@ -1014,7 +1045,7 @@ only visible features in composer table or all features
closed and reappears when reactivated.
- 16.2. WMS and WMS-C Support
+ 17.2. WMS and WMS-C Support
===========================
- WMS-C support, new spatial authorities, wms selection improvements
@@ -1027,7 +1058,7 @@ IGNF definitions in srs.db
- WMS-C scale slider gui added and more selection improvements
- 16.3. API Updates
+ 17.3. API Updates
=================
- QgsDataProvider & QgsMapLayer: add dataChanged() signal, so that a
@@ -1044,7 +1075,7 @@ variables. More paths can be passed, separated by semicolon.
- Support more GEOS operators
- 17. Whats new in Version 1.4.0 'Enceladus'?
+ 18. Whats new in Version 1.4.0 'Enceladus'?
===========================================
Please note that this is a release in our 'cutting edge' release series. As
@@ -1102,13 +1133,13 @@ For power users, you can now create customizable attribute forms using Qt
Designer dialog UIs.
- 18. Whats new in Version 1.3.0 'Mimas'?
+ 19. Whats new in Version 1.3.0 'Mimas'?
=======================================
This release includes over 30 bug fixes and several useful new features:
- 18.1. OSM plugin & provider updates
+ 19.1. OSM plugin & provider updates
=======================================
- new OSM style files.
@@ -1120,7 +1151,7 @@ This release includes over 30 bug fixes and several useful new features:
- other OSM related bugfixes.
- 18.2. Other notable features and improvements in this release
+ 19.2. Other notable features and improvements in this release
=============================================================
- Marker size is now configurable when editing a layer.
@@ -1135,7 +1166,7 @@ This release includes over 30 bug fixes and several useful new features:
- Zoom to a coordinate by entering it in the status bar coordinate display.
- 19. Version 1.2.0 'Daphnis'
+ 20. Version 1.2.0 'Daphnis'
===========================
Please note that this is a release in our 'cutting edge' release series. As
@@ -1148,7 +1179,7 @@ over the QGIS 1.1.0 release. In addition we have added
the following new features:
- 19.1. Editing
+ 20.1. Editing
=============
Editing functionality in QGIS has had a major update in this release. This
@@ -1180,14 +1211,14 @@ this tool: the redraws are much faster and the map is not cluttered with
markers.
- 19.2. Keyboard shortcuts
+ 20.2. Keyboard shortcuts
========================
New feature: configure shortcuts for actions within main window of qgis!
See menu Setting->Configure shortcuts
- 19.3. Map Composer
+ 20.3. Map Composer
==================
It is now possible to lock/unlock composer item positions by right mouse click.
@@ -1198,7 +1229,7 @@ It is now possible to keep the current layers in a composer map even if further
layers are added to the main map. Export to PDF in composer is now possible.
- 19.4. Attribute tables
+ 20.4. Attribute tables
======================
It is now possible to search the attribute table within selected records only.
@@ -1214,7 +1245,7 @@ for layer attributes. A new dialog allows loading a value map from a layer
be respected in the attribute table.
- 19.5. Plugins
+ 20.5. Plugins
=============
- The order of layers in the WMS dialog can now be changed.
@@ -1227,14 +1258,14 @@ be respected in the attribute table.
- An new OpenStreetMap provider and plugin have been added to QGIS.
- 19.6. Projects Management
+ 20.6. Projects Management
=========================
QGIS now includes support for project relative position of file data sources
and svgs. The saving of relative paths of file data sources is optional.
- 19.7. PostGIS & the PostgreSQL Provider
+ 20.7. PostGIS & the PostgreSQL Provider
=======================================
You can now select the SSL mode when adding a new DB connection. Turning off
@@ -1243,7 +1274,7 @@ connection security is not required. Support has been added for more native
types and for setting of column comments.
- 19.8. Symbology enhancements
+ 20.8. Symbology enhancements
============================
- allow refresh of symbols via popup menu on the renderer's symbol selection
@@ -1253,7 +1284,7 @@ types and for setting of column comments.
independent of the mapscale)
- 19.9. Command line arguments
+ 20.9. Command line arguments
============================
Added command line argument support on windows.
@@ -1324,7 +1355,7 @@ implementation based on the SQLITE database.
layers based on attribute data.
- 20. Version 1.0.0 'Kore'
+ 21. Version 1.0.0 'Kore'
========================
This release includes over 265 bug fixes and enhancements over the
@@ -1353,7 +1384,7 @@ running will support a plugin that is being installed.
- Ported all GDAL/OGR and GEOS usage to use C APIs only.
- 21. Version 0.11.0 'Metis'
+ 22. Version 0.11.0 'Metis'
==========================
This release includes over 60 bug fixes and enhancements over the
@@ -1369,7 +1400,7 @@ QGIS 0.10.0 release. In addition we have made the following changes:
- QML Style support for rasters and database layers
- 22. Version 0.10.0 'Io'
+ 23. Version 0.10.0 'Io'
=======================
This release includes over 120 bug fixes and enchancements
@@ -1390,7 +1421,7 @@ improvements 'under the hood'.
- Support for migration of old projects to work in newer QGIS versions.
- 23. Version 0.9.2rc1 'Ganymede'
+ 24. Version 0.9.2rc1 'Ganymede'
===============================
- This release candidate includes over 40 bug fixes and enchancements
@@ -1407,7 +1438,7 @@ in raster layers. Support for color ramps in raster layers.
improvements 'under the hood'.
- 24. Version 0.9.1 'Ganymede'
+ 25. Version 0.9.1 'Ganymede'
============================
This is a bug fix release
@@ -1420,7 +1451,7 @@ This is a bug fix release
- Python Plugin installer to install PyQGIS plugins from the repository
- 25. Version 0.9 'Ganymede'
+ 26. Version 0.9 'Ganymede'
==========================
- Python bindings - This is the major focus of this release
@@ -1435,7 +1466,7 @@ This is a bug fix release
- Improvements to the GeoReferencer
- 26. Version 0.8 'Joesephine' .... development version
+ 27. Version 0.8 'Joesephine' .... development version
=====================================================
- 2006-01-23 [timlinux] 0.7.9.10 Dropped use of qpicture and resampling for point markers in favour of
@@ -1459,7 +1490,7 @@ over time,
grid_maker plugin
- 27. Version 0.6 'Simon'
+ 28. Version 0.6 'Simon'
=======================
QGIS Change Log
@@ -1547,7 +1578,7 @@ under construction.
save or save as (if not specified by the user).
- 28. 0.5
+ 29. 0.5
=======
- 2004-12-01 [gsherman] 0.5.0devel30 Added functions to qgsdataprovider.h to support updating the feature count
diff --git a/ci/travis/linux/qt4/script.sh b/ci/travis/linux/qt4/script.sh
index 6e3a554..8e499f4 100755
--- a/ci/travis/linux/qt4/script.sh
+++ b/ci/travis/linux/qt4/script.sh
@@ -24,4 +24,4 @@ if [ "${TRAVIS_PULL_REQUEST}" != "false" ]; then
chmod -R ugo-w ~/.ccache
fi
-xvfb-run ctest -V -E 'qgis_openstreetmaptest|qgis_wcsprovidertest' -S ./qgis-test-travis.ctest --output-on-failure
+xvfb-run ctest -V -E 'qgis_openstreetmaptest|qgis_wcsprovidertest|qgis_ziplayertest' -S ./qgis-test-travis.ctest --output-on-failure
diff --git a/ci/travis/linux/qt5/blacklist.txt b/ci/travis/linux/qt5/blacklist.txt
index c84049c..9321962 100755
--- a/ci/travis/linux/qt5/blacklist.txt
+++ b/ci/travis/linux/qt5/blacklist.txt
@@ -6,6 +6,7 @@ PyQgsMapUnitScale
PyQgsPalLabelingServer
PyQgsRelationEditWidget
PyQgsServer
+PyQgsAuthManagerEndpointTest
PyQgsServerAccessControl
PyQgsSipCoverage
PyQgsSpatialiteProvider
diff --git a/ci/travis/linux/qt5/script.sh b/ci/travis/linux/qt5/script.sh
index 58d581d..017a7e7 100755
--- a/ci/travis/linux/qt5/script.sh
+++ b/ci/travis/linux/qt5/script.sh
@@ -25,5 +25,5 @@ fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-xvfb-run ctest -V -E "qgis_openstreetmaptest|qgis_wcsprovidertest|$(cat ${DIR}/blacklist.txt | paste -sd '|' -)" -S ./qgis-test-travis.ctest --output-on-failure
+xvfb-run ctest -V -E "qgis_openstreetmaptest|qgis_wcsprovidertest|qgis_ziplayertest|qgis_ogcutilstest|$(cat ${DIR}/blacklist.txt | paste -sd '|' -)" -S ./qgis-test-travis.ctest --output-on-failure
# xvfb-run ctest -V -E "qgis_openstreetmaptest|qgis_wcsprovidertest" -S ./qgis-test-travis.ctest --output-on-failure
diff --git a/cmake/FindSpatiaLite.cmake b/cmake/FindSpatiaLite.cmake
index 5d49478..941a15c 100644
--- a/cmake/FindSpatiaLite.cmake
+++ b/cmake/FindSpatiaLite.cmake
@@ -48,7 +48,7 @@ FIND_PATH(SPATIALITE_INCLUDE_DIR spatialite.h
"$ENV{LIB_DIR}/include/spatialite"
)
-FIND_LIBRARY(SPATIALITE_LIBRARY NAMES spatialite spatialite_i PATHS
+FIND_LIBRARY(SPATIALITE_LIBRARY NAMES spatialite_i spatialite PATHS
/usr/lib
$ENV{LIB}
$ENV{LIB_DIR}/lib
diff --git a/cmake/SIPMacros.cmake b/cmake/SIPMacros.cmake
index e684bd3..0583a09 100644
--- a/cmake/SIPMacros.cmake
+++ b/cmake/SIPMacros.cmake
@@ -92,10 +92,6 @@ MACRO(GENERATE_SIP_PYTHON_MODULE_CODE MODULE_NAME MODULE_SIP CPP_FILES)
ENDIF(MSVC)
ENDIF(PEDANTIC)
- IF(MSVC)
- ADD_DEFINITIONS( /bigobj )
- ENDIF(MSVC)
-
SET(SIPCMD ${SIP_BINARY_PATH} ${_sip_tags} -w -e ${_sip_x} ${SIP_EXTRA_OPTIONS} -j ${SIP_CONCAT_PARTS} -c ${CMAKE_CURRENT_BINARY_DIR}/${_module_path} ${_sip_includes} ${_abs_module_sip})
SET(SUPPRESS_SIP_WARNINGS FALSE CACHE BOOL "Hide SIP warnings")
MARK_AS_ADVANCED(SUPPRESS_SIP_WARNINGS)
diff --git a/debian/changelog b/debian/changelog
index c48bf17..ae164de 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,30 +1,24 @@
-qgis (2.16.3) UNRELEASED; urgency=medium
+qgis (2.18.0) UNRELEASED; urgency=medium
- * Release of 2.16.3
+ * Release of 2.18.0
- -- Jürgen E. Fischer <jef at norbit.de> Fri, 23 Sep 2016 20:24:14 +0200
+ -- Jürgen E. Fischer <jef at norbit.de> Fri, 21 Oct 2016 14:14:02 +0200
-qgis (2.16.2) unstable; urgency=medium
+qgis (2.17.0) unstable; urgency=medium
- * Release of 2.16.2
-
- -- Jürgen E. Fischer <jef at norbit.de> Fri, 23 Sep 2016 20:24:14 +0200
-
-qgis (2.16.1) unstable; urgency=medium
-
- * Release of 2.16.1
+ * New development version 2.17 after branch of 2.16
* drop support for debian wheezy and ubuntu wily
* add python-requests dependency for metasearch plugin
* lintian fixes
* add version constraint to libqgis-customwidgets dependency.
- -- Jürgen E. Fischer <jef at norbit.de> Fri, 26 Aug 2016 13:58:36 +0200
+ -- Jürgen E. Fischer <jef at norbit.de> Fri, 21 Oct 2016 14:14:02 +0200
qgis (2.16.0) unstable; urgency=medium
* Release of 2.16.0
- -- Jürgen E. Fischer <jef at norbit.de> Fri, 29 Jul 2016 14:04:56 +0200
+ -- Jürgen E. Fischer <jef at norbit.de> Fri, 08 Jul 2016 14:12:35 +0200
qgis (2.15.0) unstable; urgency=medium
diff --git a/debian/compat.in b/debian/compat.in
index d00268c..35300fb 100644
--- a/debian/compat.in
+++ b/debian/compat.in
@@ -1,3 +1,3 @@
-#stretch sid jessie trusty xenial#9
+#stretch sid jessie trusty xenial yakkety#9
#jessie#8
#precise#7
diff --git a/debian/control.in b/debian/control.in
index b41399c..6df1687 100644
--- a/debian/control.in
+++ b/debian/control.in
@@ -6,20 +6,20 @@ Priority: optional
Build-Depends:
bison,
cmake (>= 2.8),
-#sid stretch jessie trusty xenial# debhelper (>= 9),
-#sid stretch jessie trusty xenial# dh-python,
+#sid stretch jessie trusty xenial yakkety# debhelper (>= 9),
+#sid stretch jessie trusty xenial yakkety# dh-python,
#precise# debhelper (>= 7),
flex,
grass-dev,
libexpat1-dev,
libfcgi-dev,
-#sid stretch jessie trusty xenial# libgdal-dev (>= 1.10.1-0~),
+#sid stretch jessie trusty xenial yakkety# libgdal-dev (>= 1.10.1-0~),
#precise# libgdal-dev (>= 1.9.0) | libgdal1-dev (<< 1.9.0),
gdal-bin,
python-gdal,
libgeos-dev (>= 3.0.0),
#jessie precise trusty# libgsl0-dev,
-#sid stretch xenial# libgsl-dev,
+#sid stretch xenial yakkety# libgsl-dev,
libpq-dev,
libproj-dev,
libqt4-dev (>= 4.7.0),
@@ -28,8 +28,8 @@ Build-Depends:
libqca2-plugin-ossl,
libqtwebkit-dev,
#stretch jessie# libqwt-dev,
-#precise trusty xenial sid# libqwt5-qt4-dev,
-#sid stretch jessie trusty xenial# libqjson-dev,
+#precise trusty xenial yakkety sid# libqwt5-qt4-dev,
+#sid stretch jessie trusty xenial yakkety# libqjson-dev,
libspatialite-dev,
libsqlite3-dev,
libspatialindex-dev,
@@ -40,13 +40,13 @@ Build-Depends:
python-qt4-dev,
python-qt4-sql,
python-yaml, python-mock,
-#stretch sid xenial# python-future,
+#stretch sid xenial yakkety# python-future,
#precise# python,
#precise# python-central (>= 0.5),
-#sid stretch jessie trusty xenial# python-all (>= 2.6.6-3~), python-all-dev (>= 2.6.6-3~),
-#sid stretch jessie xenial# pyqt4.qsci-dev,
-#sid stretch jessie trusty xenial# python-pyspatialite,
-#sid jessie stretch trusty xenial# python-nose2,
+#sid stretch jessie trusty xenial yakkety# python-all (>= 2.6.6-3~), python-all-dev (>= 2.6.6-3~),
+#sid stretch jessie xenial yakkety# pyqt4.qsci-dev,
+#sid stretch jessie trusty xenial yakkety# python-pyspatialite,
+#sid jessie stretch trusty xenial yakkety# python-nose2,
python-sip (>= 4.5.0),
python-sip-dev (>= 4.5.0),
libosgearth-dev,
@@ -61,13 +61,13 @@ Build-Depends:
#oracle# oracle-instantclient12.1-devel,
spawn-fcgi, lighttpd, poppler-utils, locales, qt4-doc-html,
qt4-dev-tools,
- libqt4-sql-sqlite, python-psycopg2
+ libqt4-sql-sqlite, python-psycopg2, ca-certificates
Build-Conflicts: libqgis-dev, qgis-dev
-#sid stretch xenial#Standards-Version: 3.9.7
+#sid stretch xenial yakkety#Standards-Version: 3.9.7
#jessie#Standards-Version: 3.9.6
#precise trusty#Standards-Version: 3.8.4
#sid stretch jessie#X-Python-Version: >= 2.7, << 2.8
-#precise trusty xenial#XS-Python-Version: current
+#precise trusty xenial yakkety#XS-Python-Version: current
Vcs-Browser: https://github.com/qgis/QGIS/
Vcs-Git: https://github.com/qgis/QGIS.git
Homepage: http://qgis.org/
@@ -240,11 +240,11 @@ Section: libdevel
Depends:
grass-dev,
libexpat1-dev,
-#sid stretch jessie trusty xenial# libgdal-dev (>= 1.10.1-0~),
+#sid stretch jessie trusty xenial yakkety# libgdal-dev (>= 1.10.1-0~),
#precise# libgdal-dev (>= 1.9.0) | libgdal1-dev (<< 1.9.0),
libgeos-dev (>= 3.0.0),
#jessie precise trusty# libgsl0-dev,
-#sid stretch xenial# libgsl-dev,
+#sid stretch xenial yakkety# libgsl-dev,
libpq-dev,
libproj-dev,
libqgis-app{QGIS_ABI} (= ${binary:Version}),
@@ -382,8 +382,8 @@ Depends:
python-tz,
python-six,
python-yaml,
-#stretch sid xenial# python-future,
-#sid stretch jessie trusty xenial# python-pyspatialite,
+#stretch sid xenial yakkety# python-future,
+#sid stretch jessie trusty xenial yakkety# python-pyspatialite,
libqgispython{QGIS_ABI},
${shlibs:Depends},
${python:Depends},
diff --git a/debian/copyright b/debian/copyright
index adb1643..0858004 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -198,10 +198,6 @@ Files: python/ext-libs/yaml/*
Copyright: 2006, Kirill Simonov <xi at resolvent.net>
License: MIT
-Files: python/plugins/fTools/*
-Copyright: 2009, Carson J.Q. Farmer
-License: MIT
-
Files: python/plugins/GdalTools/*
Copyright: 2009, Faunalia
License: MIT
@@ -351,11 +347,6 @@ Files: src/plugins/evis/*
Copyright: 2007, American Museum of Natural History
License: LGPL-2+
-Files: src/plugins/globe/osgEarthQt/ViewerWidget.cpp
- src/plugins/globe/osgEarthUtil/Controls.cpp
-Copyright: 2008-2012, Pelican Mapping
-License: LGPL-2+
-
Files: src/plugins/grass/qtermwidget/BlockArray.*
Copyright: 2000, Stephan Kulow <coolo at kde.org>
2008, e_k <e_k at users.sourceforge.net>
@@ -521,7 +512,7 @@ Files: cmake/FindQwt.cmake
Copyright: 2010, Tim Sutton <tim at linfiniti.com>
License: BSD-3-Clause
-Files: cmake/FindSPATIALITE.cmake
+Files: cmake/FindSpatiaLite.cmake
Copyright: 2009, Sandro Furieri <a.furieri at lqt.it>
License: BSD-3-Clause
diff --git a/debian/qgis-providers.install.in b/debian/qgis-providers.install.in
index 7e82c0f..bbf9d4f 100644
--- a/debian/qgis-providers.install.in
+++ b/debian/qgis-providers.install.in
@@ -17,6 +17,6 @@ usr/lib/qgis/plugins/libvirtuallayerprovider.so
usr/lib/qgis/plugins/libwcsprovider.so
usr/lib/qgis/plugins/libwfsprovider.so
usr/lib/qgis/plugins/libwmsprovider.so
-#sid stretch jessie trusty xenial#usr/lib/qgis/plugins/libarcgismapserverprovider.so
-#sid stretch jessie trusty xenial#usr/lib/qgis/plugins/libarcgisfeatureserverprovider.so
+#sid stretch jessie trusty xenial yakkety#usr/lib/qgis/plugins/libarcgismapserverprovider.so
+#sid stretch jessie trusty xenial yakkety#usr/lib/qgis/plugins/libarcgisfeatureserverprovider.so
{QT_PLUGIN_DIR}/sqldrivers/libqsqlspatialite.so
diff --git a/debian/rules b/debian/rules
index 464e350..dccf69d 100755
--- a/debian/rules
+++ b/debian/rules
@@ -34,7 +34,7 @@ ifneq (,$(findstring -oracle,$(DISTRIBUTION)))
WITH_ORACLE=1
endif
-ifneq ($(DISTRIBUTION),$(findstring $(DISTRIBUTION),"jessie stretch precise trusty xenial"))
+ifneq ($(DISTRIBUTION),$(findstring $(DISTRIBUTION),"jessie stretch precise trusty xenial yakkety"))
DISTRIBUTION := sid
endif
@@ -53,7 +53,7 @@ QGIS_ABI=$(QGIS_MAJOR).$(QGIS_MINOR).$(QGIS_PATCH)
GRASS=grass$(subst .,,$(shell pkg-config --modversion grass|cut -d. -f1,2))
GRASSVER=$(subst .,,$(shell pkg-config --modversion grass|cut -d. -f1))
-WITH_GLOBE=$(shell dpkg --compare-versions "$$(dpkg-query -W --showformat='$${Version}' libosgearth-dev)" ge 2.7 && echo 1)
+WITH_GLOBE=$(shell dpkg --compare-versions "$$(dpkg-query -W --showformat='$${Version}' libosgearth-dev)" ge 2.7 && dpkg --compare-versions "$$(dpkg-query -W --showformat='$${Version}' libosgearth-dev)" lt 2.8 && echo 1)
CMAKE_OPTS := \
-DBUILDNAME=$(DEB_BUILD_NAME) \
@@ -107,7 +107,7 @@ else
CMAKE_OPTS += -DWITH_INTERNAL_NOSE2=FALSE -DWITH_INTERNAL_SIX=FALSE
endif
-ifeq (,$(findstring $(DISTRIBUTION),"stretch sid xenial"))
+ifeq (,$(findstring $(DISTRIBUTION),"stretch sid xenial yakkety"))
CMAKE_OPTS += -DWITH_INTERNAL_FUTURE=TRUE
else
CMAKE_OPTS += -DWITH_INTERNAL_FUTURE=FALSE
@@ -133,7 +133,7 @@ ifneq (,$(findstring $(DISTRIBUTION),"sid"))
CMAKE_OPTS += -DGEOS_LIBRARY=/usr/lib/$(DEB_BUILD_MULTIARCH)/libgeos_c.so
endif
-ifneq (,$(findstring $(DISTRIBUTION),"jessie stretch trusty xenial sid"))
+ifneq (,$(findstring $(DISTRIBUTION),"jessie stretch trusty xenial yakkety sid"))
CMAKE_OPTS += -DPYTHON_LIBRARY=/usr/lib/$(DEB_BUILD_MULTIARCH)/libpython2.7.so
endif
diff --git a/doc/TRANSLATORS b/doc/TRANSLATORS
index 6ebec0b..59a8b68 100644
--- a/doc/TRANSLATORS
+++ b/doc/TRANSLATORS
@@ -1,40 +1,40 @@
<style>table {font-size:80%;}th {text-align:left; }.bartodo{ background-color:red;width:100px;height:20px;}.bardone{ background-color:green;width:80px;height:20px;font-size:80%;text-align:center;padding-top:4px;height:16px;color:white;}</style><table><tr><th colspan="2" style="width:250px;">Language</th><th>Finished %</th><th>Translators</th></tr>
-<tr><td><img src="qrc:/images/flags/de.png"></td><td>German</td><td><div title="finished:18129 unfinished:135 untranslated:14" class="bartodo"><div class="bardone" style="width:99px">99.6</div></div></td><td>Jürgen E. Fischer, Stephan Holl, Otto Dassau, Werner Macho</td></tr>
-<tr><td><img src="qrc:/images/flags/eu.png"></td><td>Basque</td><td><div title="finished:18128 unfinished:134 untranslated:16" class="bartodo"><div class="bardone" style="width:99px">99.5</div></div></td><td>Asier Sarasua Garmendia, Irantzu Alvarez</td></tr>
-<tr><td><img src="qrc:/images/flags/sv.png"></td><td>Swedish</td><td><div title="finished:18128 unfinished:134 untranslated:16" class="bartodo"><div class="bardone" style="width:99px">99.5</div></div></td><td>Victor Axbom, Lars Luthman, Magnus Homann, Klas Karlsson, Isabelle J Wigren, Daniel Rosander, Anders Ekwall, Magnus Nilsson, Jonas Svensson, Christian Brinkenberg</td></tr>
-<tr><td><img src="qrc:/images/flags/pt_BR.png"></td><td>Portuguese (Brazil)</td><td><div title="finished:18128 unfinished:132 untranslated:18" class="bartodo"><div class="bardone" style="width:99px">99.5</div></div></td><td>Sidney Schaberle Goveia, Arthur Nanni, Marcelo Soares Souza, Narcélio de Sá Pereira Filho, Leônidas Descovi Filho, Felipe Sodré Barros </td></tr>
-<tr><td><img src="qrc:/images/flags/ro.png"></td><td>Romanian</td><td><div title="finished:18128 unfinished:132 untranslated:18" class="bartodo"><div class="bardone" style="width:99px">99.5</div></div></td><td>Sorin Călinică, Tudor Bărăscu, Georgiana Ioanovici, Alex Bădescu, Lonut Losifescu-Enescu, Bogdan Pacurar</td></tr>
-<tr><td><img src="qrc:/images/flags/gl.png"></td><td>Galician</td><td><div title="finished:18127 unfinished:133 untranslated:18" class="bartodo"><div class="bardone" style="width:99px">99.5</div></div></td><td>Xan Vieiro</td></tr>
-<tr><td><img src="qrc:/images/flags/nl.png"></td><td>Dutch</td><td><div title="finished:18123 unfinished:134 untranslated:21" class="bartodo"><div class="bardone" style="width:99px">99.5</div></div></td><td>Richard Duivenvoorde, Raymond Nijssen, Carlo van Rijswijk, Diethard Jansen, Willem Hoffmans, Dick Groskamp</td></tr>
-<tr><td><img src="qrc:/images/flags/fr.png"></td><td>French</td><td><div title="finished:18102 unfinished:133 untranslated:43" class="bartodo"><div class="bardone" style="width:99px">99.4</div></div></td><td>Arnaud Morvan, Augustin Roche, DelazJ, Didier Vanden Berghe, Dofabien, etrimaille, Jean-Roc Morreale, Jérémy Garniaux, Loïc Buscoz, Lsam, Marc-André Saia, Marie Silvestre, Mathieu Bossaert, Mathieu Lattes, Mayeul Kauffmann, Médéric Ribreux, Mehdi Semchaoui, Michael Douchin, Nicolas B [...]
-<tr><td><img src="qrc:/images/flags/bs.png"></td><td>Bosnian</td><td><div title="finished:17981 unfinished:134 untranslated:163" class="bartodo"><div class="bardone" style="width:98px">98.7</div></div></td><td>Almir Karabegovic</td></tr>
-<tr><td><img src="qrc:/images/flags/da.png"></td><td>Danish</td><td><div title="finished:17780 unfinished:89 untranslated:409" class="bartodo"><div class="bardone" style="width:97px">97.5</div></div></td><td>Jacob Overgaard Madsen, Bo Victor Thomsen</td></tr>
-<tr><td><img src="qrc:/images/flags/es.png"></td><td>Spanish</td><td><div title="finished:17674 unfinished:57 untranslated:547" class="bartodo"><div class="bardone" style="width:96px">96.9</div></div></td><td>Carlos Dávila, Javier César Aldariz, Gabriela Awad, Edwin Amado, Mayeul Kauffmann, Diana Galindo</td></tr>
-<tr><td><img src="qrc:/images/flags/ja.png"></td><td>Japanese</td><td><div title="finished:17264 unfinished:135 untranslated:879" class="bartodo"><div class="bardone" style="width:94px">94.8</div></div></td><td>BABA Yoshihiko, Yoichi Kayama, Minoru Akagi, Takayuki Nuimura, Takayuki Mizutani, Norihiro Yamate</td></tr>
-<tr><td><img src="qrc:/images/flags/hu.png"></td><td>Hungarian</td><td><div title="finished:16553 unfinished:71 untranslated:1654" class="bartodo"><div class="bardone" style="width:90px">90.8</div></div></td><td>Zoltan Siki</td></tr>
-<tr><td><img src="qrc:/images/flags/vi.png"></td><td>Vietnamese</td><td><div title="finished:16519 unfinished:22 untranslated:1737" class="bartodo"><div class="bardone" style="width:90px">90.4</div></div></td><td>Phùng Văn Doanh, Bùi Hữu Mạnh, Nguyễn Văn Thanh, Nguyễn Hữu Phúc, Cao Minh Tu</td></tr>
-<tr><td><img src="qrc:/images/flags/zh.png"></td><td>Chinese simplified</td><td><div title="finished:16116 unfinished:27 untranslated:2135" class="bartodo"><div class="bardone" style="width:88px">88.2</div></div></td><td>Calvin Ngei, Lisashen</td></tr>
-<tr><td><img src="qrc:/images/flags/pt_PT.png"></td><td>Portuguese (Portugal)</td><td><div title="finished:15530 unfinished:27 untranslated:2721" class="bartodo"><div class="bardone" style="width:85px">85.0</div></div></td><td>Giovanni Manghi, Joana Simões, Duarte Carreira, Alexandre Neto, Pedro Pereira, Pedro Palheiro, Nelson Silva, Ricardo Sena, Leandro Infantini, João Gaspar</td></tr>
-<tr><td><img src="qrc:/images/flags/ru.png"></td><td>Russian</td><td><div title="finished:15459 unfinished:93 untranslated:2726" class="bartodo"><div class="bardone" style="width:84px">84.8</div></div></td><td>Alexander Bruy, Artem Popov</td></tr>
-<tr><td><img src="qrc:/images/flags/pl.png"></td><td>Polish</td><td><div title="finished:14738 unfinished:26 untranslated:3514" class="bartodo"><div class="bardone" style="width:80px">80.7</div></div></td><td>Robert Szczepanek, Milena Nowotarska, Borys Jurgiel, Mateusz Łoskot, Tomasz Paul, Andrzej Świąder, Radosław Pasiok, Michał Kułach, Ewelina Krawczak, Michał Smoczyk, Jakub Bobrowski</td></tr>
-<tr><td><img src="qrc:/images/flags/cs.png"></td><td>Czech</td><td><div title="finished:14659 unfinished:57 untranslated:3562" class="bartodo"><div class="bardone" style="width:80px">80.4</div></div></td><td>Jan Helebrant, Martin Landa, Peter Antolik, Martin Dzurov, Stanislav Horáček</td></tr>
-<tr><td><img src="qrc:/images/flags/nb.png"></td><td>Norwegian Bokmal</td><td><div title="finished:14570 unfinished:61 untranslated:3647" class="bartodo"><div class="bardone" style="width:79px">79.9</div></div></td><td>James Stott, Maléne Peterson</td></tr>
-<tr><td><img src="qrc:/images/flags/fi.png"></td><td>Finnish</td><td><div title="finished:14046 unfinished:290 untranslated:3942" class="bartodo"><div class="bardone" style="width:77px">77.6</div></div></td><td>Kari Mikkonen, Matti Mäntynen</td></tr>
-<tr><td><img src="qrc:/images/flags/zh.png"></td><td>Chinese traditional</td><td><div title="finished:14070 unfinished:86 untranslated:4122" class="bartodo"><div class="bardone" style="width:77px">77.2</div></div></td><td>Calvin Ngei, Zhang Jun, Richard Xie</td></tr>
-<tr><td><img src="qrc:/images/flags/it.png"></td><td>Italian</td><td><div title="finished:14011 unfinished:87 untranslated:4180" class="bartodo"><div class="bardone" style="width:76px">76.9</div></div></td><td>Roberto Angeletti, Michele Beneventi, Marco Braida, Stefano Campus, Luca Casagrande, Paolo Cavallini, Giuliano Curti, Luca Delucchi, Alessandro Fanna, Michele Ferretti, Matteo Ghetta, Anne Gishla, Maurizio Napolitano, Flavio Rigolon</td></tr>
-<tr><td><img src="qrc:/images/flags/et.png"></td><td>Estonian</td><td><div title="finished:13165 unfinished:101 untranslated:5012" class="bartodo"><div class="bardone" style="width:72px">72.3</div></div></td><td>Veiko Viil</td></tr>
-<tr><td><img src="qrc:/images/flags/ca.png"></td><td>Catalan</td><td><div title="finished:12896 unfinished:77 untranslated:5305" class="bartodo"><div class="bardone" style="width:70px">70.8</div></div></td><td>Albert F, Pau Reguant Ridó, Xavier Roijals</td></tr>
-<tr><td><img src="qrc:/images/flags/hi.png"></td><td>Hindi</td><td><div title="finished:12461 unfinished:129 untranslated:5688" class="bartodo"><div class="bardone" style="width:68px">68.5</div></div></td><td>Harish Kumar Solanki</td></tr>
-<tr><td><img src="qrc:/images/flags/bg.png"></td><td>Bulgarian</td><td><div title="finished:12373 unfinished:94 untranslated:5811" class="bartodo"><div class="bardone" style="width:67px">68.0</div></div></td><td>Захари Савов, Jordan Tzvetkov</td></tr>
-<tr><td><img src="qrc:/images/flags/ko.png"></td><td>Korean</td><td><div title="finished:11755 unfinished:130 untranslated:6393" class="bartodo"><div class="bardone" style="width:64px">64.7</div></div></td><td>OSGeo Korean Chapter</td></tr>
-<tr><td><img src="qrc:/images/flags/lt.png"></td><td>Lithuanian</td><td><div title="finished:11327 unfinished:131 untranslated:6820" class="bartodo"><div class="bardone" style="width:62px">62.3</div></div></td><td>Paulius Litvinas, Tomas Straupis, Kestas M</td></tr>
-<tr><td><img src="qrc:/images/flags/tr.png"></td><td>Turkish</td><td><div title="finished:10861 unfinished:95 untranslated:7322" class="bartodo"><div class="bardone" style="width:59px">59.7</div></div></td><td>Osman Yalçın YILMAZ, Omur Saygin</td></tr>
-<tr><td><img src="qrc:/images/flags/id.png"></td><td>Indonesian</td><td><div title="finished:10717 unfinished:271 untranslated:7290" class="bartodo"><div class="bardone" style="width:59px">59.4</div></div></td><td>Emir Hartato, Muhammad Iqnaul Haq Siregar, Trias Aditya, Januar V. Simarmata, I Made Anombawa</td></tr>
-<tr><td><img src="qrc:/images/flags/el.png"></td><td>Modern Greek (1453-)</td><td><div title="finished:10734 unfinished:59 untranslated:7485" class="bartodo"><div class="bardone" style="width:58px">58.9</div></div></td><td>Theodoros Vakkas, Ioannis Tsimpiris, Evripidis Argyropoulos, Mike Pegnigiannis, Nikos Ves</td></tr>
-<tr><td><img src="qrc:/images/flags/sl.png"></td><td>Slovenian</td><td><div title="finished:9512 unfinished:130 untranslated:8636" class="bartodo"><div class="bardone" style="width:52px">52.4</div></div></td><td>Jože Detečnik, Dejan Gregor, Jaka Kranjc</td></tr>
-<tr><td><img src="qrc:/images/flags/km.png"></td><td>Central Khmer</td><td><div title="finished:9338 unfinished:138 untranslated:8802" class="bartodo"><div class="bardone" style="width:51px">51.5</div></div></td><td>Khoem Sokhem</td></tr>
-<tr><td><img src="qrc:/images/flags/ar.png"></td><td>Arabic</td><td><div title="finished:9294 unfinished:138 untranslated:8846" class="bartodo"><div class="bardone" style="width:51px">51.2</div></div></td><td>Ichaouia Amine, Hosham Munier</td></tr>
-<tr><td><img src="qrc:/images/flags/lv.png"></td><td>Latvian</td><td><div title="finished:9168 unfinished:206 untranslated:8904" class="bartodo"><div class="bardone" style="width:50px">50.7</div></div></td><td>Maris Nartiss, Pēteris Brūns</td></tr>
-<tr><td><img src="qrc:/images/flags/sk.png"></td><td>Slovak</td><td><div title="finished:7764 unfinished:813 untranslated:9701" class="bartodo"><div class="bardone" style="width:44px">44.7</div></div></td><td>Lubos Balazovic, Jana Kormanikova, Ivan Mincik</td></tr>
-<tr><td><img src="qrc:/images/flags/hr.png"></td><td>Croatian</td><td><div title="finished:7292 unfinished:139 untranslated:10847" class="bartodo"><div class="bardone" style="width:40px">40.3</div></div></td><td>Zoran Jankovic</td></tr></table>
+<tr><td><img src="qrc:/images/flags/de.png"></td><td>German</td><td><div title="finished:18426 unfinished:0 untranslated:0" class="bartodo"><div class="bardone" style="width:100px">100.0</div></div></td><td>Jürgen E. Fischer, Stephan Holl, Otto Dassau, Werner Macho</td></tr>
+<tr><td><img src="qrc:/images/flags/sv.png"></td><td>Swedish</td><td><div title="finished:18107 unfinished:186 untranslated:133" class="bartodo"><div class="bardone" style="width:98px">98.8</div></div></td><td>Victor Axbom, Lars Luthman, Magnus Homann, Klas Karlsson, Isabelle J Wigren, Daniel Rosander, Anders Ekwall, Magnus Nilsson, Jonas Svensson, Christian Brinkenberg</td></tr>
+<tr><td><img src="qrc:/images/flags/eu.png"></td><td>Basque</td><td><div title="finished:18107 unfinished:185 untranslated:134" class="bartodo"><div class="bardone" style="width:98px">98.8</div></div></td><td>Asier Sarasua Garmendia, Irantzu Alvarez</td></tr>
+<tr><td><img src="qrc:/images/flags/gl.png"></td><td>Galician</td><td><div title="finished:18106 unfinished:183 untranslated:137" class="bartodo"><div class="bardone" style="width:98px">98.8</div></div></td><td>Xan Vieiro</td></tr>
+<tr><td><img src="qrc:/images/flags/nl.png"></td><td>Dutch</td><td><div title="finished:18102 unfinished:188 untranslated:136" class="bartodo"><div class="bardone" style="width:98px">98.8</div></div></td><td>Richard Duivenvoorde, Raymond Nijssen, Carlo van Rijswijk, Diethard Jansen, Willem Hoffmans, Dick Groskamp</td></tr>
+<tr><td><img src="qrc:/images/flags/pt_BR.png"></td><td>Portuguese (Brazil)</td><td><div title="finished:18107 unfinished:177 untranslated:142" class="bartodo"><div class="bardone" style="width:98px">98.7</div></div></td><td>Sidney Schaberle Goveia, Arthur Nanni, Marcelo Soares Souza, Narcélio de Sá Pereira Filho, Leônidas Descovi Filho, Felipe Sodré Barros </td></tr>
+<tr><td><img src="qrc:/images/flags/ro.png"></td><td>Romanian</td><td><div title="finished:18107 unfinished:177 untranslated:142" class="bartodo"><div class="bardone" style="width:98px">98.7</div></div></td><td>Sorin Călinică, Tudor Bărăscu, Georgiana Ioanovici, Alex Bădescu, Lonut Losifescu-Enescu, Bogdan Pacurar</td></tr>
+<tr><td><img src="qrc:/images/flags/fr.png"></td><td>French</td><td><div title="finished:18081 unfinished:180 untranslated:165" class="bartodo"><div class="bardone" style="width:98px">98.6</div></div></td><td>Arnaud Morvan, Augustin Roche, DelazJ, Didier Vanden Berghe, Dofabien, etrimaille, Jean-Roc Morreale, Jérémy Garniaux, Loïc Buscoz, Lsam, Marc-André Saia, Marie Silvestre, Mathieu Bossaert, Mathieu Lattes, Mayeul Kauffmann, Médéric Ribreux, Mehdi Semchaoui, Michael Douchin, Nicolas [...]
+<tr><td><img src="qrc:/images/flags/bs.png"></td><td>Bosnian</td><td><div title="finished:17960 unfinished:188 untranslated:278" class="bartodo"><div class="bardone" style="width:97px">98.0</div></div></td><td>Almir Karabegovic</td></tr>
+<tr><td><img src="qrc:/images/flags/da.png"></td><td>Danish</td><td><div title="finished:17761 unfinished:142 untranslated:523" class="bartodo"><div class="bardone" style="width:96px">96.8</div></div></td><td>Jacob Overgaard Madsen, Bo Victor Thomsen</td></tr>
+<tr><td><img src="qrc:/images/flags/es.png"></td><td>Spanish</td><td><div title="finished:17654 unfinished:111 untranslated:661" class="bartodo"><div class="bardone" style="width:96px">96.1</div></div></td><td>Carlos Dávila, Javier César Aldariz, Gabriela Awad, Edwin Amado, Mayeul Kauffmann, Diana Galindo</td></tr>
+<tr><td><img src="qrc:/images/flags/ja.png"></td><td>Japanese</td><td><div title="finished:17243 unfinished:189 untranslated:994" class="bartodo"><div class="bardone" style="width:94px">94.1</div></div></td><td>BABA Yoshihiko, Yoichi Kayama, Minoru Akagi, Takayuki Nuimura, Takayuki Mizutani, Norihiro Yamate</td></tr>
+<tr><td><img src="qrc:/images/flags/hu.png"></td><td>Hungarian</td><td><div title="finished:16533 unfinished:124 untranslated:1769" class="bartodo"><div class="bardone" style="width:90px">90.1</div></div></td><td>Zoltan Siki</td></tr>
+<tr><td><img src="qrc:/images/flags/vi.png"></td><td>Vietnamese</td><td><div title="finished:16500 unfinished:76 untranslated:1850" class="bartodo"><div class="bardone" style="width:89px">89.8</div></div></td><td>Phùng Văn Doanh, Bùi Hữu Mạnh, Nguyễn Văn Thanh, Nguyễn Hữu Phúc, Cao Minh Tu</td></tr>
+<tr><td><img src="qrc:/images/flags/zh.png"></td><td>Chinese simplified</td><td><div title="finished:16105 unfinished:82 untranslated:2239" class="bartodo"><div class="bardone" style="width:87px">87.6</div></div></td><td>Calvin Ngei, Lisashen</td></tr>
+<tr><td><img src="qrc:/images/flags/pt_PT.png"></td><td>Portuguese (Portugal)</td><td><div title="finished:15518 unfinished:75 untranslated:2833" class="bartodo"><div class="bardone" style="width:84px">84.4</div></div></td><td>Giovanni Manghi, Joana Simões, Duarte Carreira, Alexandre Neto, Pedro Pereira, Pedro Palheiro, Nelson Silva, Ricardo Sena, Leandro Infantini, João Gaspar</td></tr>
+<tr><td><img src="qrc:/images/flags/ru.png"></td><td>Russian</td><td><div title="finished:15446 unfinished:139 untranslated:2841" class="bartodo"><div class="bardone" style="width:84px">84.2</div></div></td><td>Alexander Bruy, Artem Popov</td></tr>
+<tr><td><img src="qrc:/images/flags/pl.png"></td><td>Polish</td><td><div title="finished:14724 unfinished:75 untranslated:3627" class="bartodo"><div class="bardone" style="width:80px">80.1</div></div></td><td>Robert Szczepanek, Milena Nowotarska, Borys Jurgiel, Mateusz Łoskot, Tomasz Paul, Andrzej Świąder, Radosław Pasiok, Michał Kułach, Ewelina Krawczak, Michał Smoczyk, Jakub Bobrowski</td></tr>
+<tr><td><img src="qrc:/images/flags/cs.png"></td><td>Czech</td><td><div title="finished:14653 unfinished:112 untranslated:3661" class="bartodo"><div class="bardone" style="width:79px">79.8</div></div></td><td>Jan Helebrant, Martin Landa, Peter Antolik, Martin Dzurov, Stanislav Horáček</td></tr>
+<tr><td><img src="qrc:/images/flags/nb.png"></td><td>Norwegian Bokmal</td><td><div title="finished:14559 unfinished:114 untranslated:3753" class="bartodo"><div class="bardone" style="width:79px">79.3</div></div></td><td>James Stott, Maléne Peterson</td></tr>
+<tr><td><img src="qrc:/images/flags/fi.png"></td><td>Finnish</td><td><div title="finished:14040 unfinished:334 untranslated:4052" class="bartodo"><div class="bardone" style="width:77px">77.1</div></div></td><td>Kari Mikkonen, Matti Mäntynen</td></tr>
+<tr><td><img src="qrc:/images/flags/zh.png"></td><td>Chinese traditional</td><td><div title="finished:14061 unfinished:139 untranslated:4226" class="bartodo"><div class="bardone" style="width:76px">76.7</div></div></td><td>Calvin Ngei, Zhang Jun, Richard Xie</td></tr>
+<tr><td><img src="qrc:/images/flags/it.png"></td><td>Italian</td><td><div title="finished:14004 unfinished:129 untranslated:4293" class="bartodo"><div class="bardone" style="width:76px">76.4</div></div></td><td>Roberto Angeletti, Michele Beneventi, Marco Braida, Stefano Campus, Luca Casagrande, Paolo Cavallini, Giuliano Curti, Luca Delucchi, Alessandro Fanna, Michele Ferretti, Matteo Ghetta, Anne Gishla, Maurizio Napolitano, Flavio Rigolon</td></tr>
+<tr><td><img src="qrc:/images/flags/et.png"></td><td>Estonian</td><td><div title="finished:13154 unfinished:151 untranslated:5121" class="bartodo"><div class="bardone" style="width:71px">71.8</div></div></td><td>Veiko Viil</td></tr>
+<tr><td><img src="qrc:/images/flags/ca.png"></td><td>Catalan</td><td><div title="finished:12886 unfinished:131 untranslated:5409" class="bartodo"><div class="bardone" style="width:70px">70.3</div></div></td><td>Albert F, Pau Reguant Ridó, Xavier Roijals</td></tr>
+<tr><td><img src="qrc:/images/flags/hi.png"></td><td>Hindi</td><td><div title="finished:12456 unfinished:173 untranslated:5797" class="bartodo"><div class="bardone" style="width:68px">68.1</div></div></td><td>Harish Kumar Solanki</td></tr>
+<tr><td><img src="qrc:/images/flags/bg.png"></td><td>Bulgarian</td><td><div title="finished:12368 unfinished:142 untranslated:5916" class="bartodo"><div class="bardone" style="width:67px">67.5</div></div></td><td>Захари Савов, Jordan Tzvetkov</td></tr>
+<tr><td><img src="qrc:/images/flags/ko.png"></td><td>Korean</td><td><div title="finished:11750 unfinished:169 untranslated:6507" class="bartodo"><div class="bardone" style="width:64px">64.2</div></div></td><td>OSGeo Korean Chapter</td></tr>
+<tr><td><img src="qrc:/images/flags/lt.png"></td><td>Lithuanian</td><td><div title="finished:11323 unfinished:178 untranslated:6925" class="bartodo"><div class="bardone" style="width:61px">61.9</div></div></td><td>Paulius Litvinas, Tomas Straupis, Kestas M</td></tr>
+<tr><td><img src="qrc:/images/flags/tr.png"></td><td>Turkish</td><td><div title="finished:10856 unfinished:142 untranslated:7428" class="bartodo"><div class="bardone" style="width:59px">59.3</div></div></td><td>Osman Yalçın YILMAZ, Omur Saygin</td></tr>
+<tr><td><img src="qrc:/images/flags/id.png"></td><td>Indonesian</td><td><div title="finished:10714 unfinished:314 untranslated:7398" class="bartodo"><div class="bardone" style="width:58px">59.0</div></div></td><td>Emir Hartato, Muhammad Iqnaul Haq Siregar, Trias Aditya, Januar V. Simarmata, I Made Anombawa</td></tr>
+<tr><td><img src="qrc:/images/flags/el.png"></td><td>Modern Greek (1453-)</td><td><div title="finished:10728 unfinished:107 untranslated:7591" class="bartodo"><div class="bardone" style="width:58px">58.5</div></div></td><td>Theodoros Vakkas, Ioannis Tsimpiris, Evripidis Argyropoulos, Mike Pegnigiannis, Nikos Ves</td></tr>
+<tr><td><img src="qrc:/images/flags/sl.png"></td><td>Slovenian</td><td><div title="finished:9510 unfinished:172 untranslated:8744" class="bartodo"><div class="bardone" style="width:52px">52.1</div></div></td><td>Jože Detečnik, Dejan Gregor, Jaka Kranjc</td></tr>
+<tr><td><img src="qrc:/images/flags/km.png"></td><td>Central Khmer</td><td><div title="finished:9334 unfinished:174 untranslated:8918" class="bartodo"><div class="bardone" style="width:51px">51.1</div></div></td><td>Khoem Sokhem</td></tr>
+<tr><td><img src="qrc:/images/flags/ar.png"></td><td>Arabic</td><td><div title="finished:9292 unfinished:170 untranslated:8964" class="bartodo"><div class="bardone" style="width:50px">50.9</div></div></td><td>Ichaouia Amine, Hosham Munier</td></tr>
+<tr><td><img src="qrc:/images/flags/lv.png"></td><td>Latvian</td><td><div title="finished:9165 unfinished:255 untranslated:9006" class="bartodo"><div class="bardone" style="width:50px">50.4</div></div></td><td>Maris Nartiss, Pēteris Brūns</td></tr>
+<tr><td><img src="qrc:/images/flags/sk.png"></td><td>Slovak</td><td><div title="finished:7762 unfinished:854 untranslated:9810" class="bartodo"><div class="bardone" style="width:44px">44.4</div></div></td><td>Lubos Balazovic, Jana Kormanikova, Ivan Mincik</td></tr>
+<tr><td><img src="qrc:/images/flags/hr.png"></td><td>Croatian</td><td><div title="finished:7290 unfinished:177 untranslated:10959" class="bartodo"><div class="bardone" style="width:40px">40.0</div></div></td><td>Zoran Jankovic</td></tr></table>
diff --git a/doc/news.html b/doc/news.html
index d43506a..50bd9a1 100644
--- a/doc/news.html
+++ b/doc/news.html
@@ -2,7 +2,7 @@
<HTML>
<HEAD>
<META NAME="generator" CONTENT="http://txt2tags.org">
-<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>QGIS News</TITLE>
<!-- Included doc/style.css -->
@@ -77,51 +77,85 @@ label{ background-color: #FFFFCC;
<DIV CLASS="header" ID="header">
<H1>QGIS News</H1>
<H2>Change history for the QGIS Project</H2>
-<H3>Friday July 08, 2016</H3>
+<H3>Friday October 21, 2016</H3>
</DIV>
<DIV CLASS="toc">
<OL>
- <LI><A HREF="#toc1">What's new in Version 2.16 'Nødebo'?</A>
- <LI><A HREF="#toc2">What's new in Version 2.14 'Essen'?</A>
- <LI><A HREF="#toc3">What's new in Version 2.12 'Lyon'?</A>
- <LI><A HREF="#toc4">What's new in Version 2.10 'Pisa'?</A>
- <LI><A HREF="#toc5">What's new in Version 2.8 'Wien'?</A>
- <LI><A HREF="#toc6">What's new in Version 2.6.0 'Brighton'?</A>
- <LI><A HREF="#toc7">What's new in Version 2.4.0 'Chugiak'?</A>
- <LI><A HREF="#toc8">Whats new in Version 2.2.0 'Valmiera'?</A>
- <LI><A HREF="#toc9">Whats new in Version 2.0.1 'Dufour'?</A>
- <LI><A HREF="#toc10">Whats new in Version 2.0.0 'Dufour'?</A>
- <LI><A HREF="#toc11">Whats new in Version 1.8.0 'Lisboa'?</A>
- <LI><A HREF="#toc12">Whats new in Version 1.7.2 'Wroclaw'?</A>
- <LI><A HREF="#toc13">Whats new in Version 1.7.1 'Wroclaw'?</A>
- <LI><A HREF="#toc14">Whats new in Version 1.7.0 'Wroclaw'?</A>
- <LI><A HREF="#toc15">Whats new in Version 1.6.0 'Capiapo'?</A>
- <LI><A HREF="#toc16">Whats new in Version 1.5.0?</A>
- <LI><A HREF="#toc17">Whats new in Version 1.4.0 'Enceladus'?</A>
- <LI><A HREF="#toc18">Whats new in Version 1.3.0 'Mimas'?</A>
- <LI><A HREF="#toc19">Version 1.2.0 'Daphnis'</A>
- <LI><A HREF="#toc20">Version 1.0.0 'Kore'</A>
- <LI><A HREF="#toc21">Version 0.11.0 'Metis'</A>
- <LI><A HREF="#toc22">Version 0.10.0 'Io'</A>
- <LI><A HREF="#toc23">Version 0.9.2rc1 'Ganymede'</A>
- <LI><A HREF="#toc24">Version 0.9.1 'Ganymede'</A>
- <LI><A HREF="#toc25">Version 0.9 'Ganymede'</A>
- <LI><A HREF="#toc26">Version 0.8 'Joesephine' .... development version</A>
- <LI><A HREF="#toc27">Version 0.6 'Simon'</A>
- <LI><A HREF="#toc28">0.5</A>
+ <LI><A HREF="#toc1">What's new in Version 2.18 'Las Palmas'?</A>
+ <LI><A HREF="#toc2">What's new in Version 2.16 'Nødebo'?</A>
+ <LI><A HREF="#toc3">What's new in Version 2.14 'Essen'?</A>
+ <LI><A HREF="#toc4">What's new in Version 2.12 'Lyon'?</A>
+ <LI><A HREF="#toc5">What's new in Version 2.10 'Pisa'?</A>
+ <LI><A HREF="#toc6">What's new in Version 2.8 'Wien'?</A>
+ <LI><A HREF="#toc7">What's new in Version 2.6.0 'Brighton'?</A>
+ <LI><A HREF="#toc8">What's new in Version 2.4.0 'Chugiak'?</A>
+ <LI><A HREF="#toc9">Whats new in Version 2.2.0 'Valmiera'?</A>
+ <LI><A HREF="#toc10">Whats new in Version 2.0.1 'Dufour'?</A>
+ <LI><A HREF="#toc11">Whats new in Version 2.0.0 'Dufour'?</A>
+ <LI><A HREF="#toc12">Whats new in Version 1.8.0 'Lisboa'?</A>
+ <LI><A HREF="#toc13">Whats new in Version 1.7.2 'Wroclaw'?</A>
+ <LI><A HREF="#toc14">Whats new in Version 1.7.1 'Wroclaw'?</A>
+ <LI><A HREF="#toc15">Whats new in Version 1.7.0 'Wroclaw'?</A>
+ <LI><A HREF="#toc16">Whats new in Version 1.6.0 'Capiapo'?</A>
+ <LI><A HREF="#toc17">Whats new in Version 1.5.0?</A>
+ <LI><A HREF="#toc18">Whats new in Version 1.4.0 'Enceladus'?</A>
+ <LI><A HREF="#toc19">Whats new in Version 1.3.0 'Mimas'?</A>
+ <LI><A HREF="#toc20">Version 1.2.0 'Daphnis'</A>
+ <LI><A HREF="#toc21">Version 1.0.0 'Kore'</A>
+ <LI><A HREF="#toc22">Version 0.11.0 'Metis'</A>
+ <LI><A HREF="#toc23">Version 0.10.0 'Io'</A>
+ <LI><A HREF="#toc24">Version 0.9.2rc1 'Ganymede'</A>
+ <LI><A HREF="#toc25">Version 0.9.1 'Ganymede'</A>
+ <LI><A HREF="#toc26">Version 0.9 'Ganymede'</A>
+ <LI><A HREF="#toc27">Version 0.8 'Joesephine' .... development version</A>
+ <LI><A HREF="#toc28">Version 0.6 'Simon'</A>
+ <LI><A HREF="#toc29">0.5</A>
</OL>
</DIV>
<DIV CLASS="body" ID="body">
<P>
-Last Updated: Friday July 08, 2016
-Last Change : Friday July 08, 2016
+Last Updated: Friday October 21, 2016
+Last Change : Friday October 21, 2016
</P>
<A NAME="toc1"></A>
-<H1>1. What's new in Version 2.16 'Nødebo'?</H1>
+<H1>1. What's new in Version 2.18 'Las Palmas'?</H1>
+
+<P>
+This release has following new features:
+</P>
+
+<UL>
+<LI>Symbology: Color picker is now embedded in layer style panel
+<LI>Labelling: Substitution list support for labeling
+<LI>Labelling: Improved line label placement algorithm
+<LI>Labelling: Label polygons using curved labels along perimeter
+<LI>Data Management: Add flag to only copy selected features
+<LI>Forms and Widgets: Allow controlling labels for individual edit widgets
+<LI>Forms and Widgets: Conditional visibility for tabs and group boxes
+<LI>Forms and Widgets: Client side default field values
+<LI>Map Composer: True North Arrows
+<LI>Processing: Point on surface algorithm added
+<LI>Processing: New algorithm for geometry boundary
+<LI>Processing: New algorithm for calculating feature bounding box
+<LI>Processing: Processing dissolve algorithm accepts multiple fields
+<LI>Processing: Optimised processing clip algorithm
+<LI>Processing: New algorithm for merging connected lines
+<LI>General: Automatic links in identify results
+<LI>General: Mouse wheel over color dialog sliders
+<LI>General: Add custom color schemes to color button drop down menu
+<LI>Data Providers: Preview for WMTS + added XYZ tile layers
+<LI>QGIS Server: Possibility to segmentize feature info geometry in server
+<LI>Plugins: DB Manager: Add the ability to update SQL Layer
+<LI>Programmability: New expression functions
+<LI>Programmability: Expose GEOS linear referencing function to QgsGeometry
+</UL>
+
+<A NAME="toc2"></A>
+<H1>2. What's new in Version 2.16 'Nødebo'?</H1>
<P>
This release has following new features:
@@ -220,8 +254,8 @@ This release has following new features:
<LI>Programmability: Plugins can add pages to vector layer properties
</UL>
-<A NAME="toc2"></A>
-<H1>2. What's new in Version 2.14 'Essen'?</H1>
+<A NAME="toc3"></A>
+<H1>3. What's new in Version 2.14 'Essen'?</H1>
<P>
This release has following new features:
@@ -299,8 +333,8 @@ This release has following new features:
<LI>User Interface : Show/hide all legend items via the the context menu
</UL>
-<A NAME="toc3"></A>
-<H1>3. What's new in Version 2.12 'Lyon'?</H1>
+<A NAME="toc4"></A>
+<H1>4. What's new in Version 2.12 'Lyon'?</H1>
<P>
This release has following new features:
@@ -356,8 +390,8 @@ This release has following new features:
<LI>Symbology : Add pixels as option for all symbology size unit choices
</UL>
-<A NAME="toc4"></A>
-<H1>4. What's new in Version 2.10 'Pisa'?</H1>
+<A NAME="toc5"></A>
+<H1>5. What's new in Version 2.10 'Pisa'?</H1>
<P>
This is a minor release increment with the following new features:
@@ -407,8 +441,8 @@ This is a minor release increment with the following new features:
<LI>User interface improvements.
</UL>
-<A NAME="toc5"></A>
-<H1>5. What's new in Version 2.8 'Wien'?</H1>
+<A NAME="toc6"></A>
+<H1>6. What's new in Version 2.8 'Wien'?</H1>
<P>
This is a minor release increment with the following feature:
@@ -443,8 +477,8 @@ This is a minor release increment with the following feature:
DescribeLayer, python plugins.
</UL>
-<A NAME="toc6"></A>
-<H1>6. What's new in Version 2.6.0 'Brighton'?</H1>
+<A NAME="toc7"></A>
+<H1>7. What's new in Version 2.6.0 'Brighton'?</H1>
<P>
This is a minor release increment with the following new features:
@@ -492,8 +526,8 @@ This is a minor release increment with the following new features:
<LI>Context menu for identify tool
</UL>
-<A NAME="toc7"></A>
-<H1>7. What's new in Version 2.4.0 'Chugiak'?</H1>
+<A NAME="toc8"></A>
+<H1>8. What's new in Version 2.4.0 'Chugiak'?</H1>
<P>
This is the minor release sports a number of great new features:
@@ -515,8 +549,8 @@ This is the minor release sports a number of great new features:
<LI>New Inverted Polygon renderer
</UL>
-<A NAME="toc8"></A>
-<H1>8. Whats new in Version 2.2.0 'Valmiera'?</H1>
+<A NAME="toc9"></A>
+<H1>9. Whats new in Version 2.2.0 'Valmiera'?</H1>
<P>
This is the minor release sports a number of great new features:
@@ -559,8 +593,8 @@ This is the minor release sports a number of great new features:
<LI>'Processing' can be used headless in scripts.
</UL>
-<A NAME="toc9"></A>
-<H1>9. Whats new in Version 2.0.1 'Dufour'?</H1>
+<A NAME="toc10"></A>
+<H1>10. Whats new in Version 2.0.1 'Dufour'?</H1>
<P>
This is a small bugfix release to address the missing copyright / credits for
@@ -568,8 +602,8 @@ our new splash screen and to update supporting documentation. The spanish
translation was also updated.
</P>
-<A NAME="toc10"></A>
-<H1>10. Whats new in Version 2.0.0 'Dufour'?</H1>
+<A NAME="toc11"></A>
+<H1>11. Whats new in Version 2.0.0 'Dufour'?</H1>
<P>
This is a new major release. Building on the foundation of
@@ -657,8 +691,8 @@ key new features.
you to explore the software and discover them all!
</UL>
-<A NAME="toc11"></A>
-<H1>11. Whats new in Version 1.8.0 'Lisboa'?</H1>
+<A NAME="toc12"></A>
+<H1>12. Whats new in Version 1.8.0 'Lisboa'?</H1>
<P>
This is a new feature release. Building on the foundation of
@@ -715,8 +749,8 @@ added gdal_fillnodata to GDALTools plugin
<LI>Support for nesting projects within other projects
</UL>
-<A NAME="toc12"></A>
-<H1>12. Whats new in Version 1.7.2 'Wroclaw'?</H1>
+<A NAME="toc13"></A>
+<H1>13. Whats new in Version 1.7.2 'Wroclaw'?</H1>
<P>
This is a bugfix release over version 1.7.1. The following changes
@@ -765,8 +799,8 @@ were made.
<LI>Fix broken Assign projection functionality in GDALTools and improve handling output file extension
</UL>
-<A NAME="toc13"></A>
-<H1>13. Whats new in Version 1.7.1 'Wroclaw'?</H1>
+<A NAME="toc14"></A>
+<H1>14. Whats new in Version 1.7.1 'Wroclaw'?</H1>
<P>
This is a bugfix release over version 1.7.0. The following changes
@@ -831,8 +865,8 @@ were made.
<LI>Fixed a bug where map= was not being published in onlineresource url when project files are not in the same dir as cgi
</UL>
-<A NAME="toc14"></A>
-<H1>14. Whats new in Version 1.7.0 'Wroclaw'?</H1>
+<A NAME="toc15"></A>
+<H1>15. Whats new in Version 1.7.0 'Wroclaw'?</H1>
<P>
This release is named after the town of Wroclaw in Poland. The Department of
@@ -850,7 +884,7 @@ enhancements. Once again it is impossible to document everything here that has
changed so we will just provide a bullet list of key new features here.
</P>
-<H2>14.1. Symbology labels and diagrams</H2>
+<H2>15.1. Symbology labels and diagrams</H2>
<UL>
<LI>New symbology now used by default!
@@ -868,7 +902,7 @@ changed so we will just provide a bullet list of key new features here.
<LI>Move/rotate/change label edit tools to interactively change data defined label properties.
</UL>
-<H2>14.2. New Tools</H2>
+<H2>15.2. New Tools</H2>
<UL>
<LI>Added GUI for gdaldem.
@@ -877,7 +911,7 @@ changed so we will just provide a bullet list of key new features here.
<LI>Added voronoi polygon tool to Vector menu.
</UL>
-<H2>14.3. User interface updates</H2>
+<H2>15.3. User interface updates</H2>
<UL>
<LI>Allow managing missing layers in a list.
@@ -888,7 +922,7 @@ changed so we will just provide a bullet list of key new features here.
<LI>General clean-ups and usability improvements.
</UL>
-<H2>14.4. CRS Handling</H2>
+<H2>15.4. CRS Handling</H2>
<UL>
<LI>Show active crs in status bar.
@@ -898,7 +932,7 @@ changed so we will just provide a bullet list of key new features here.
<LI>Default to last selection when prompting for CRS.
</UL>
-<H2>14.5. Rasters</H2>
+<H2>15.5. Rasters</H2>
<UL>
<LI>Added AND and OR operator for raster calculator
@@ -907,7 +941,7 @@ changed so we will just provide a bullet list of key new features here.
<LI>Added raster toolbar with histogram stretch functions.
</UL>
-<H2>14.6. Providers and Data Handling</H2>
+<H2>15.6. Providers and Data Handling</H2>
<UL>
<LI>New SQLAnywhere vector provider.
@@ -939,7 +973,7 @@ changed so we will just provide a bullet list of key new features here.
</UL>
</UL>
-<H2>14.7. Api and Developer Centric</H2>
+<H2>15.7. Api and Developer Centric</H2>
<UL>
<LI>Refactored attribute dialog calls to QgsFeatureAttribute.
@@ -951,7 +985,7 @@ changed so we will just provide a bullet list of key new features here.
new QgsGeometry.validateGeometry function
</UL>
-<H2>14.8. QGIS Mapserver</H2>
+<H2>15.8. QGIS Mapserver</H2>
<UL>
<LI>Ability to specify wms service capabilities in the properties
@@ -959,7 +993,7 @@ changed so we will just provide a bullet list of key new features here.
<LI>Support for wms printing with GetPrint-Request.
</UL>
-<H2>14.9. Plugins</H2>
+<H2>15.9. Plugins</H2>
<UL>
<LI>Support for icons of plugins in the plugin manager dialog.
@@ -967,14 +1001,14 @@ changed so we will just provide a bullet list of key new features here.
<LI>Removed ogr converter plugin - use 'save as' context menu rather.
</UL>
-<H2>14.10. Printing</H2>
+<H2>15.10. Printing</H2>
<UL>
<LI>Undo/Redo support for the print composer
</UL>
-<A NAME="toc15"></A>
-<H1>15. Whats new in Version 1.6.0 'Capiapo'?</H1>
+<A NAME="toc16"></A>
+<H1>16. Whats new in Version 1.6.0 'Capiapo'?</H1>
<P>
Please note that this is a release in our 'cutting edge' release series. As
@@ -987,7 +1021,7 @@ Once again it is impossible to document everything here that has changed so we w
just provide a bullet list of key new features here.
</P>
-<H2>15.1. General Improvements</H2>
+<H2>16.1. General Improvements</H2>
<UL>
<LI>Added gpsd support to live gps tracking.
@@ -1021,7 +1055,7 @@ caching providers (currently WMS and WFS) can synchronize with changes in
the datasource.
</UL>
-<H2>15.2. Table of contents (TOC) improvements</H2>
+<H2>16.2. Table of contents (TOC) improvements</H2>
<UL>
<LI>Added a new option to the raster legend menu that will stretch the current
@@ -1031,14 +1065,14 @@ as' option, you can now specify OGR creation options.
<LI>In the table of contents, it is now possible to select and remove several layers at once.
</UL>
-<H2>15.3. Labelling (New generation only)</H2>
+<H2>16.3. Labelling (New generation only)</H2>
<UL>
<LI>Data defined label position in labeling-ng.
<LI>Line wrapping, data defined font and buffer settings for labeling-ng.
</UL>
-<H2>15.4. Layer properties and symbology</H2>
+<H2>16.4. Layer properties and symbology</H2>
<UL>
<LI>Three new classification modes added to graduated symbol renderer (version
@@ -1059,7 +1093,7 @@ the transparency table in the raster layer properties dialog.
the style manager more easily.
</UL>
-<H2>15.5. Map Composer</H2>
+<H2>16.5. Map Composer</H2>
<UL>
<LI>add capability to show and manipulate composer item width/ height in item
@@ -1068,8 +1102,8 @@ position dialog.
<LI>Sorting for composer attribute table (several columns and ascending / descending).
</UL>
-<A NAME="toc16"></A>
-<H1>16. Whats new in Version 1.5.0?</H1>
+<A NAME="toc17"></A>
+<H1>17. Whats new in Version 1.5.0?</H1>
<P>
Please note that this is a release in our 'cutting edge' release series. As
@@ -1085,7 +1119,7 @@ Once again it is impossible to document everything here that has changed so we w
just provide a bullet list of key new features here.
</P>
-<H2>16.1. Main GUI</H2>
+<H2>17.1. Main GUI</H2>
<UL>
<LI>There is a new angle measuring tool that allows you to interactively
@@ -1140,7 +1174,7 @@ only visible features in composer table or all features
closed and reappears when reactivated.
</UL>
-<H2>16.2. WMS and WMS-C Support</H2>
+<H2>17.2. WMS and WMS-C Support</H2>
<UL>
<LI>WMS-C support, new spatial authorities, wms selection improvements
@@ -1153,7 +1187,7 @@ IGNF definitions in srs.db
<LI>WMS-C scale slider gui added and more selection improvements
</UL>
-<H2>16.3. API Updates</H2>
+<H2>17.3. API Updates</H2>
<UL>
<LI>QgsDataProvider & QgsMapLayer: add dataChanged() signal, so that a
@@ -1170,8 +1204,8 @@ variables. More paths can be passed, separated by semicolon.
<LI>Support more GEOS operators
</UL>
-<A NAME="toc17"></A>
-<H1>17. Whats new in Version 1.4.0 'Enceladus'?</H1>
+<A NAME="toc18"></A>
+<H1>18. Whats new in Version 1.4.0 'Enceladus'?</H1>
<P>
Please note that this is a release in our 'cutting edge' release series. As
@@ -1238,14 +1272,14 @@ For power users, you can now create customizable attribute forms using Qt
Designer dialog UIs.
</P>
-<A NAME="toc18"></A>
-<H1>18. Whats new in Version 1.3.0 'Mimas'?</H1>
+<A NAME="toc19"></A>
+<H1>19. Whats new in Version 1.3.0 'Mimas'?</H1>
<P>
This release includes over 30 bug fixes and several useful new features:
</P>
-<H2>18.1. OSM plugin & provider updates</H2>
+<H2>19.1. OSM plugin & provider updates</H2>
<UL>
<LI>new OSM style files.
@@ -1257,7 +1291,7 @@ This release includes over 30 bug fixes and several useful new features:
<LI>other OSM related bugfixes.
</UL>
-<H2>18.2. Other notable features and improvements in this release</H2>
+<H2>19.2. Other notable features and improvements in this release</H2>
<UL>
<LI>Marker size is now configurable when editing a layer.
@@ -1272,8 +1306,8 @@ This release includes over 30 bug fixes and several useful new features:
<LI>Zoom to a coordinate by entering it in the status bar coordinate display.
</UL>
-<A NAME="toc19"></A>
-<H1>19. Version 1.2.0 'Daphnis'</H1>
+<A NAME="toc20"></A>
+<H1>20. Version 1.2.0 'Daphnis'</H1>
<P>
Please note that this is a release in our 'cutting edge' release series. As
@@ -1286,7 +1320,7 @@ over the QGIS 1.1.0 release. In addition we have added
the following new features:
</P>
-<H2>19.1. Editing</H2>
+<H2>20.1. Editing</H2>
<P>
Editing functionality in QGIS has had a major update in this release. This
@@ -1324,14 +1358,14 @@ this tool: the redraws are much faster and the map is not cluttered with
markers.
</P>
-<H2>19.2. Keyboard shortcuts</H2>
+<H2>20.2. Keyboard shortcuts</H2>
<P>
New feature: configure shortcuts for actions within main window of qgis!
See menu Setting->Configure shortcuts
</P>
-<H2>19.3. Map Composer</H2>
+<H2>20.3. Map Composer</H2>
<P>
It is now possible to lock/unlock composer item positions by right mouse click.
@@ -1342,7 +1376,7 @@ It is now possible to keep the current layers in a composer map even if further
layers are added to the main map. Export to PDF in composer is now possible.
</P>
-<H2>19.4. Attribute tables</H2>
+<H2>20.4. Attribute tables</H2>
<P>
It is now possible to search the attribute table within selected records only.
@@ -1359,7 +1393,7 @@ for layer attributes. A new dialog allows loading a value map from a layer
be respected in the attribute table.
</P>
-<H2>19.5. Plugins</H2>
+<H2>20.5. Plugins</H2>
<UL>
<LI>The order of layers in the WMS dialog can now be changed.
@@ -1372,14 +1406,14 @@ be respected in the attribute table.
<LI>An new OpenStreetMap provider and plugin have been added to QGIS.
</UL>
-<H2>19.6. Projects Management</H2>
+<H2>20.6. Projects Management</H2>
<P>
QGIS now includes support for project relative position of file data sources
and svgs. The saving of relative paths of file data sources is optional.
</P>
-<H2>19.7. PostGIS & the PostgreSQL Provider</H2>
+<H2>20.7. PostGIS & the PostgreSQL Provider</H2>
<P>
You can now select the SSL mode when adding a new DB connection. Turning off
@@ -1388,7 +1422,7 @@ connection security is not required. Support has been added for more native
types and for setting of column comments.
</P>
-<H2>19.8. Symbology enhancements</H2>
+<H2>20.8. Symbology enhancements</H2>
<UL>
<LI>allow refresh of symbols via popup menu on the renderer's symbol selection
@@ -1398,7 +1432,7 @@ types and for setting of column comments.
independent of the mapscale)
</UL>
-<H2>19.9. Command line arguments</H2>
+<H2>20.9. Command line arguments</H2>
<P>
Added command line argument support on windows.
@@ -1471,8 +1505,8 @@ implementation based on the SQLITE database.
layers based on attribute data.
</UL>
-<A NAME="toc20"></A>
-<H1>20. Version 1.0.0 'Kore'</H1>
+<A NAME="toc21"></A>
+<H1>21. Version 1.0.0 'Kore'</H1>
<P>
This release includes over 265 bug fixes and enhancements over the
@@ -1503,8 +1537,8 @@ running will support a plugin that is being installed.
<LI>Ported all GDAL/OGR and GEOS usage to use C APIs only.
</UL>
-<A NAME="toc21"></A>
-<H1>21. Version 0.11.0 'Metis'</H1>
+<A NAME="toc22"></A>
+<H1>22. Version 0.11.0 'Metis'</H1>
<P>
This release includes over 60 bug fixes and enhancements over the
@@ -1522,8 +1556,8 @@ QGIS 0.10.0 release. In addition we have made the following changes:
<LI>QML Style support for rasters and database layers
</UL>
-<A NAME="toc22"></A>
-<H1>22. Version 0.10.0 'Io'</H1>
+<A NAME="toc23"></A>
+<H1>23. Version 0.10.0 'Io'</H1>
<P>
This release includes over 120 bug fixes and enchancements
@@ -1546,8 +1580,8 @@ improvements 'under the hood'.
<LI>Support for migration of old projects to work in newer QGIS versions.
</UL>
-<A NAME="toc23"></A>
-<H1>23. Version 0.9.2rc1 'Ganymede'</H1>
+<A NAME="toc24"></A>
+<H1>24. Version 0.9.2rc1 'Ganymede'</H1>
<UL>
<LI>This release candidate includes over 40 bug fixes and enchancements
@@ -1564,8 +1598,8 @@ in raster layers. Support for color ramps in raster layers.
improvements 'under the hood'.
</UL>
-<A NAME="toc24"></A>
-<H1>24. Version 0.9.1 'Ganymede'</H1>
+<A NAME="toc25"></A>
+<H1>25. Version 0.9.1 'Ganymede'</H1>
<P>
This is a bug fix release
@@ -1580,8 +1614,8 @@ This is a bug fix release
<LI>Python Plugin installer to install PyQGIS plugins from the repository
</UL>
-<A NAME="toc25"></A>
-<H1>25. Version 0.9 'Ganymede'</H1>
+<A NAME="toc26"></A>
+<H1>26. Version 0.9 'Ganymede'</H1>
<UL>
<LI>Python bindings - This is the major focus of this release
@@ -1596,8 +1630,8 @@ This is a bug fix release
<LI>Improvements to the GeoReferencer
</UL>
-<A NAME="toc26"></A>
-<H1>26. Version 0.8 'Joesephine' .... development version</H1>
+<A NAME="toc27"></A>
+<H1>27. Version 0.8 'Joesephine' .... development version</H1>
<UL>
<LI>2006-01-23 [timlinux] 0.7.9.10 Dropped use of qpicture and resampling for point markers in favour of
@@ -1621,8 +1655,8 @@ over time,
grid_maker plugin
</UL>
-<A NAME="toc27"></A>
-<H1>27. Version 0.6 'Simon'</H1>
+<A NAME="toc28"></A>
+<H1>28. Version 0.6 'Simon'</H1>
<P>
QGIS Change Log
@@ -1716,8 +1750,8 @@ under construction.
save or save as (if not specified by the user).
</UL>
-<A NAME="toc28"></A>
-<H1>28. 0.5</H1>
+<A NAME="toc29"></A>
+<H1>29. 0.5</H1>
<UL>
<LI>2004-12-01 [gsherman] 0.5.0devel30 Added functions to qgsdataprovider.h to support updating the feature count
@@ -3091,5 +3125,5 @@ July 6, 2002
</DIV>
<!-- html code generated by txt2tags 2.6 (http://txt2tags.org) -->
-<!-- cmdline: txt2tags -\-encoding=utf-8 -o/home/fischer/src/qgis/debian/build-master-pyqtwrapper-qt4/doc/news.html -t html /home/fischer/src/qgis/doc/news.t2t -->
+<!-- cmdline: txt2tags -odoc/news.html -t html doc/news.t2t -->
</BODY></HTML>
diff --git a/doc/news.t2t b/doc/news.t2t
index 1129311..9183ed2 100644
--- a/doc/news.t2t
+++ b/doc/news.t2t
@@ -38,6 +38,36 @@ Change history for the QGIS Project
Last Updated: %%date(%A %B %d, %Y)
Last Change : %%mtime(%A %B %d, %Y)
+= What's new in Version 2.18 'Las Palmas'? =
+
+This release has following new features:
+
+- Symbology: Color picker is now embedded in layer style panel
+- Labelling: Substitution list support for labeling
+- Labelling: Improved line label placement algorithm
+- Labelling: Label polygons using curved labels along perimeter
+- Data Management: Add flag to only copy selected features
+- Forms and Widgets: Allow controlling labels for individual edit widgets
+- Forms and Widgets: Conditional visibility for tabs and group boxes
+- Forms and Widgets: Client side default field values
+- Map Composer: True North Arrows
+- Processing: Point on surface algorithm added
+- Processing: New algorithm for geometry boundary
+- Processing: New algorithm for calculating feature bounding box
+- Processing: Processing dissolve algorithm accepts multiple fields
+- Processing: Optimised processing clip algorithm
+- Processing: New algorithm for merging connected lines
+- General: Automatic links in identify results
+- General: Mouse wheel over color dialog sliders
+- General: Add custom color schemes to color button drop down menu
+- Data Providers: Preview for WMTS + added XYZ tile layers
+- QGIS Server: Possibility to segmentize feature info geometry in server
+- Plugins: DB Manager: Add the ability to update SQL Layer
+- Programmability: New expression functions
+- Programmability: Expose GEOS linear referencing function to QgsGeometry
+-
+
+
= What's new in Version 2.16 'Nødebo'? =
This release has following new features:
diff --git a/i18n/qgis_de.ts b/i18n/qgis_de.ts
index 44e9bd6..eebb95d 100644
--- a/i18n/qgis_de.ts
+++ b/i18n/qgis_de.ts
@@ -215,172 +215,172 @@
<context>
<name>AlgorithmClassification</name>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="664"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="297"/>
<source>Polygon intersection</source>
<translation>Polygonverschneidung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="674"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="292"/>
<source>Vectorize raster layer</source>
<translation>Rasterlayer vektorisieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="681"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="284"/>
<source>Interpolate (Inverse distance weighting)</source>
<translation>Interpolation (Inverse Abstandsgewichtung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="663"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="298"/>
<source>RGB to PCT</source>
<translation>RGB nach PCT</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="692"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="272"/>
<source>Rasterize vector layer</source>
<translation>Vektorlayer rastern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="673"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="273"/>
<source>Polygon identity</source>
<translation>Polygonidentität</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="691"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="290"/>
<source>Polygon dissolve (all polygons)</source>
<translation>Polygon auflösen (alle Polygone)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="689"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="270"/>
<source>Polygon union</source>
<translation>Polygonvereinigung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="667"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="276"/>
<source>Interpolate (Natural neighbor)</source>
<translation>Interpolation (Natürlicher Nachbar)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="662"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="279"/>
<source>Merge raster layers</source>
<translation>Rasterlayer zusammenführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="677"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="277"/>
<source>Remove small pixel clumps (nearest neighbour)</source>
<translation>Kleine Pixelklumpen entfernen (nächster Nachbar)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="682"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="289"/>
<source>Interpolate (Nearest Neighbor)</source>
<translation>Interpolation (Nächster Nachbar)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="676"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="287"/>
<source>Interpolate (Cubic spline)</source>
<translation>Interpolieren (Kubisches Spline)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="675"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="278"/>
<source>Interpolate (Data metrics)</source>
<translation>Interpolation (Datenmetrik)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="685"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="271"/>
<source>Reproject raster layer</source>
<translation>Rasterlayer reprojizieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="690"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="301"/>
<source>Export raster layer</source>
<translation>Rasterlayer exportieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="669"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="268"/>
<source>PCT to RGB</source>
<translation>PCT nach RGB</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="679"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="299"/>
<source>Export vector layer</source>
<translation>Vektorlayer exportieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="672"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="291"/>
<source>Polygon dissolve (by attribute)</source>
<translation>Polygon auflösen (nach Attribut)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="678"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="275"/>
<source>Remove small pixel clumps (to no-data)</source>
<translation>Kleine Pixelklumpen entfernen (zu Nullwerten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="671"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="296"/>
<source>Interpolate (Modified quadratic shepard)</source>
<translation>Interpolieren (Modifizierte quadratische Shepard-Methode)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="665"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="281"/>
<source>Merge vector layers</source>
<translation>Vektorlayer zusammenführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="661"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="294"/>
<source>Reclassify (simple)</source>
<translation>Neuklassifizieren (einfach)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="680"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="286"/>
<source>Execute SQL on vector layer</source>
<translation>SQL auf Vektorlayer ausführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="670"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="283"/>
<source>Raster layer information</source>
<translation>Rasterlayerinformation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="668"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="280"/>
<source>Contour lines</source>
<translation>Konturlinien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="686"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="285"/>
<source>Create graticule</source>
<translation>Gradnetz erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="687"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="295"/>
<source>Fire spreading simulation</source>
<translation>Feuerausbreitungssimulation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="683"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="274"/>
<source>Polygon difference</source>
<translation>Polygondifferenz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="693"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="282"/>
<source>Create graticule from extent</source>
<translation>Gradnetz aus Grenzen erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="666"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="300"/>
<source>Polygon symmetrical difference</source>
<translation>Symmetrische Polygondifferenz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="688"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="293"/>
<source>Vector layer information</source>
<translation>Vektorlayerinformation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="660"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="269"/>
<source>Polygon update</source>
<translation>Polygonaktualisierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="684"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="288"/>
<source>Interpolate (Average)</source>
<translation>Interpolation (Durchschnitt)</translation>
</message>
@@ -406,31 +406,45 @@ Fortfahren?</translation>
</message>
<message>
<location filename="../python/plugins/processing/python-i18n.cpp" line="64"/>
+ <source>Extent CRS</source>
+ <translation>Grenz-KBS</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="65"/>
+ <source>Extent parameters must use the same CRS as the input layers.
+Your input layers do not have the same extent as the project, so the extent might be in a wrong CRS if you have selected it from the canvas.
+Do you want to continue?</source>
+ <translation>Die Grenzparameter müssen im gleichen KBS wie die Eingabelayer sein.
+Die gegebenen Layer habe nicht die gleichen Grenzen wie das Projekt und könnten daher in einem falschen KBS sein, wenn es aus der Karte gewählt wurde.
+Soll fortgefahren werden?</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="66"/>
<source>Unable to execute algorithm</source>
<translation>Konnte Algorithmus nicht ausführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="65"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="67"/>
<source>Processing algorithm...</source>
<translation>Algorithmus wird bearbeitet...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="66"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="68"/>
<source><b>Algorithm %s starting...</b></source>
<translation><b>Algorithmus %s startet...</b></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="67"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="69"/>
<source><b>Missing parameter value: %s</b></source>
<translation><b>Fehlender Parameterwert: %s</b></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="68"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="70"/>
<source>Wrong or missing parameter values</source>
<translation>Falsche oder fehlende Parameterwerte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="69"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="71"/>
<source>HTML output has been generated by this algorithm.
Open the results dialog to check it.</source>
<translation>HTML Ausgabe wurde vom Algorithmus erzeugt.
@@ -440,17 +454,17 @@ Zum Überprüfen Ergebnisdialog öffnen.</translation>
<context>
<name>AlgorithmDialogBase</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="73"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="75"/>
<source>Run</source>
<translation>Starte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="74"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="76"/>
<source><p>Downloading algorithm help... Please wait.</p></source>
<translation><p>Algorithmenhilfe wird heruntergeladen... Bitte warten.</p></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="75"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="77"/>
<source><h2>No help available for this algorithm</h2><p>{}</p></source>
<translation><h2>Keine Hilfe für diesen Algorithmus verfügbar.</h2><p>{}</p></translation>
</message>
@@ -458,12 +472,12 @@ Zum Überprüfen Ergebnisdialog öffnen.</translation>
<context>
<name>AlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="79"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="81"/>
<source>Activate</source>
<translation>Aktivieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="80"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="82"/>
<source>Generic algorithm provider</source>
<translation>Generischer Algorithmus-Anbieter</translation>
</message>
@@ -471,27 +485,27 @@ Zum Überprüfen Ergebnisdialog öffnen.</translation>
<context>
<name>AssignProjection</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="84"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="86"/>
<source>Assign projection</source>
<translation>Projektion zuweisen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="85"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="87"/>
<source>[GDAL] Projections</source>
<translation>[GDAL] Projektionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="86"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="88"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="87"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="89"/>
<source>Desired CRS</source>
<translation>Ziel-KBS</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="88"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="90"/>
<source>Layer with projection</source>
<translation>Layer mit Projektion</translation>
</message>
@@ -499,22 +513,22 @@ Zum Überprüfen Ergebnisdialog öffnen.</translation>
<context>
<name>AutoincrementalField</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="93"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="95"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="94"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="96"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="95"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="97"/>
<source>Incremented</source>
<translation>Inkrementiert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="92"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="94"/>
<source>Add autoincremental field</source>
<translation>Autoinkremetierendes Feld hinzufügen</translation>
</message>
@@ -522,27 +536,27 @@ Zum Überprüfen Ergebnisdialog öffnen.</translation>
<context>
<name>BarPlot</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="100"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="102"/>
<source>Graphics</source>
<translation>Grafik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="101"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="103"/>
<source>Input table</source>
<translation>Eingabetabelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="102"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="104"/>
<source>Category name field</source>
<translation>Kategorienamesfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="103"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="105"/>
<source>Value field</source>
<translation>Wertfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="99"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="101"/>
<source>Bar plot</source>
<translation>Balkengrafik</translation>
</message>
@@ -550,197 +564,197 @@ Zum Überprüfen Ergebnisdialog öffnen.</translation>
<context>
<name>BasicStatisticsNumbers</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="108"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="110"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="109"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="111"/>
<source>Input vector layer</source>
<translation>Eingabevektorlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="110"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="112"/>
<source>Field to calculate statistics on</source>
<translation>Feld für Statistikberechnung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="111"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="113"/>
<source>Statistics</source>
<translation>Statistik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="112"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="114"/>
<source>Coefficient of Variation</source>
<translation>Variationskoeffizient</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="113"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="115"/>
<source>Minimum value</source>
<translation>Minimalwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="114"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="116"/>
<source>Maximum value</source>
<translation>Maximalwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="115"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="117"/>
<source>Sum</source>
<translation>Summe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="116"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="118"/>
<source>Mean value</source>
<translation>Mittelwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="118"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="120"/>
<source>Count</source>
<translation>Anzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="119"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="121"/>
<source>Range</source>
<translation>Bereich</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="120"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="122"/>
<source>Median</source>
<translation>Median</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="121"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="123"/>
<source>Number of unique values</source>
<translation>Anzahl der eindeutigen Werte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="122"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="124"/>
<source>Minority (rarest occurring value)</source>
<translation>Minderheit (am seltensten vorkommender Wert)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="123"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="125"/>
<source>Majority (most frequently occurring value)</source>
<translation>Mehrheit (am häufigesten auftauchender Wert)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="124"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="126"/>
<source>First quartile</source>
<translation>Erstes Viertel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="125"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="127"/>
<source>Third quartile</source>
<translation>Drittes Viertel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="126"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="128"/>
<source>NULL (missed) values</source>
<translation>NULL (fehlende) Werte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="127"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="129"/>
<source>Interquartile Range (IQR)</source>
<translation>Interquartilsabstand (IQR)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="128"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="130"/>
<source>Analyzed layer: {}</source>
<translation>Analysierter Layer: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="129"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="131"/>
<source>Analyzed field: {}</source>
<translation>Analysiertes Feld: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="130"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="132"/>
<source>Count: {}</source>
<translation>Anzahl: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="131"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="133"/>
<source>Unique values: {}</source>
<translation>Eindeutige Werte: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="132"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="134"/>
<source>Minimum value: {}</source>
<translation>Minimalwert: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="133"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="135"/>
<source>Maximum value: {}</source>
<translation>Maximalwert: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="134"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="136"/>
<source>Range: {}</source>
<translation>Bereich: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="135"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="137"/>
<source>Sum: {}</source>
<translation>Summe: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="136"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="138"/>
<source>Mean value: {}</source>
<translation>Mittelwert: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="137"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="139"/>
<source>Median value: {}</source>
<translation>Median: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="138"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="140"/>
<source>Standard deviation: {}</source>
<translation>Standardabweichung: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="139"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="141"/>
<source>Coefficient of Variation: {}</source>
<translation>Variationskoeffizient: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="140"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="142"/>
<source>Minority (rarest occurring value): {}</source>
<translation>Minderheit (am seltensten vorkommender Wert): {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="141"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="143"/>
<source>Majority (most frequently occurring value): {}</source>
<translation>Mehrheit (am häufigesten auftauchender Wert): {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="142"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="144"/>
<source>First quartile: {}</source>
<translation>Erstes Viertel: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="143"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="145"/>
<source>Third quartile: {}</source>
<translation>Drittes Viertel: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="144"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="146"/>
<source>NULL (missing) values: {}</source>
<translation>Fehlende Leerwerte (NULL): {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="145"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="147"/>
<source>Interquartile Range (IQR): {}</source>
<translation>Interquartilsabstand (IQR): {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="117"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="119"/>
<source>Standard deviation</source>
<translation>Standardabweichung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="107"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="109"/>
<source>Basic statistics for numeric fields</source>
<translation>Grundstatistik für numerische Felder</translation>
</message>
@@ -748,107 +762,107 @@ Zum Überprüfen Ergebnisdialog öffnen.</translation>
<context>
<name>BasicStatisticsStrings</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="150"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="152"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="151"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="153"/>
<source>Input vector layer</source>
<translation>Eingabevektorlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="152"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="154"/>
<source>Field to calculate statistics on</source>
<translation>Feld für Statistikberechnung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="153"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="155"/>
<source>Statistics for text</source>
<translation>Textstatistik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="154"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="156"/>
<source>Minimum length</source>
<translation>Minimallänge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="155"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="157"/>
<source>Maximum length</source>
<translation>Maximallänge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="156"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="158"/>
<source>Mean length</source>
<translation>Mittlere Länge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="157"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="159"/>
<source>Count</source>
<translation>Anzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="158"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="160"/>
<source>Number of empty values</source>
<translation>Anzahl leerer Werte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="159"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="161"/>
<source>Number of non-empty values</source>
<translation>Anzahl nicht leerer Wert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="160"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="162"/>
<source>Number of unique values</source>
<translation>Anzahl eindeutiger Werte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="161"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="163"/>
<source>Analyzed layer: {}</source>
<translation>Analysierter Layer: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="162"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="164"/>
<source>Analyzed field: {}</source>
<translation>Analysiertes Feld: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="163"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="165"/>
<source>Minimum length: {}</source>
<translation>Minimallänge: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="164"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="166"/>
<source>Maximum length: {}</source>
<translation>Maximallänge: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="165"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="167"/>
<source>Mean length: {}</source>
<translation>Mittlere Länge: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="166"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="168"/>
<source>Filled values: {}</source>
<translation>Gefüllte Werte: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="167"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="169"/>
<source>NULL (missing) values: {}</source>
<translation>Fehlende Leerwerte (NULL): {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="168"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="170"/>
<source>Count: {}</source>
<translation>Anzahl: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="169"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="171"/>
<source>Unique: {}</source>
<translation>Eindeutig: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="149"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="151"/>
<source>Basic statistics for text fields</source>
<translation>Grundstatistik für Textfelder</translation>
</message>
@@ -856,44 +870,44 @@ Zum Überprüfen Ergebnisdialog öffnen.</translation>
<context>
<name>BatchAlgorithmDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="173"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="175"/>
<source>Batch Processing - %s</source>
<translation>Stapelverarbeitung - %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="174"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="176"/>
<source><b>Missing parameter value: %s (row %d)</b></source>
<translation><b>Fehlender Parameterwert: %s (Zeile %d)</b></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="175"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="177"/>
<source><b>Wrong or missing parameter value: %s (row %d)</b></source>
<translation><b>Falscher oder fehlender Parameterwert: %s (Zeile %d)</b></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="176"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="178"/>
<source>
Processing algorithm %d/%d...</source>
<translation>
Verarbeite Algorithmus %d/%d...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="180"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="182"/>
<source>Batch processing completed</source>
<translation>Stapelverarbeitung abgeschlossen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="177"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="179"/>
<source><b>Algorithm %s starting...</b></source>
<translation><b>Algorithmus %s startet...</b></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="178"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="180"/>
<source>Algorithm %s correctly executed...</source>
<translation>Algorithmus %s korrekt ausgeführt...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="179"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="181"/>
<source>Batch processing</source>
<translation>Stapelverarbeitung</translation>
</message>
@@ -901,22 +915,22 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>BatchInputSelectionPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="184"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="186"/>
<source>Select from open layers</source>
<translation>Wähle aus geöffneten Layern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="185"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="187"/>
<source>Select from filesystem</source>
<translation>Wähle vom Dateisystem</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="186"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="188"/>
<source>Open file</source>
<translation>Datei öffnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="187"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="189"/>
<source>All files(*.*);;</source>
<translation>Alle Dateien (*.*);;</translation>
</message>
@@ -924,12 +938,12 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>BatchOutputSelectionPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="191"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="193"/>
<source>Save file</source>
<translation>Datei speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="192"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="194"/>
<source>Select directory</source>
<translation>Verzeichnis wählen</translation>
</message>
@@ -937,80 +951,131 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>BatchPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="196"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="198"/>
<source>Load in QGIS</source>
<translation>Lade in QGIS</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="197"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="199"/>
<source>Yes</source>
<translation>Ja</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="198"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="200"/>
<source>No</source>
<translation>Nein</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="199"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="201"/>
<source>Open batch</source>
<translation>Stapel öffnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="200"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="202"/>
<source>JSON files (*.json)</source>
<translation>JSON-Dateien (*.json)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="201"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="203"/>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="202"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="204"/>
<source>An error occurred while reading your file.</source>
<translation>Ein Fehler trat beim Lesen der Datei auf.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="203"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="205"/>
<source><b>Missing parameter value: %s (row %d)</b></source>
<translation><b>Fehlender Parameterwert: %s (Zeile %d)</b></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="204"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="206"/>
<source><b>Wrong or missing parameter value: %s (row %d)</b></source>
<translation><b>Falscher oder fehlender Parameterwert: %s (Zeile %d)</b></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="205"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="207"/>
<source>Save batch</source>
<translation>Stapel speichern</translation>
</message>
</context>
<context>
+ <name>Boundary</name>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="211"/>
+ <source>Boundary</source>
+ <translation>Grenze</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="212"/>
+ <source>Vector geometry tools</source>
+ <translation>Vektorgeometriewerkzeuge</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="213"/>
+ <source>Input layer</source>
+ <translation>Eingabelayer</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="214"/>
+ <source>Error calculating boundary</source>
+ <translation>Fehler bei Grenzberechnung</translation>
+ </message>
+</context>
+<context>
+ <name>BoundingBox</name>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="218"/>
+ <source>Bounding boxes</source>
+ <translation>Umgrenzungsrahmen</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="219"/>
+ <source>Vector geometry tools</source>
+ <translation>Vektorgeometriewerkzeuge</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="220"/>
+ <source>Input layer</source>
+ <translation>Eingabelayer</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="221"/>
+ <source>Bounds</source>
+ <translation>Grenzen</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="222"/>
+ <source>Error calculating bounding box</source>
+ <translation>Fehler beim Berechnen der Umgrenzungsrahmen</translation>
+ </message>
+</context>
+<context>
<name>CalculatorModelerAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="209"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="226"/>
<source>Calculator</source>
<translation>Rechner</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="210"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="227"/>
<source>Modeler-only tools</source>
<translation>Nur-Modellierungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="211"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="228"/>
<source>Formula</source>
<translation>Formel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="212"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="229"/>
<source>Result</source>
<translation>Ergebnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="213"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="230"/>
<source>Wrong formula: %s</source>
<translation>Falsche Formel: %s</translation>
</message>
@@ -1018,26 +1083,26 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>CalculatorModelerParametersDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="217"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="234"/>
<source>You can refer to model values in your formula, using single-letter variables, as follows:
</source>
<translation>Mit Variablen mit einem Buchstaben kann auf Modellwerte in den Formeln wie folgt Bezug genommen werden:
</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="218"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="235"/>
<source>
- No numerical variables are available.</source>
<translation>
- Keine numerischen Variablen verfügbar.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="219"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="236"/>
<source>[Enter your formula here]</source>
<translation>[Formel hier eingeben]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="220"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="237"/>
<source>Calculator</source>
<translation>Rechner</translation>
</message>
@@ -1045,47 +1110,47 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>CanopyMaxima</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="224"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="241"/>
<source>Canopy Maxima</source>
<translation>Bodenbedeckungsmaxima</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="225"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="242"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="226"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="243"/>
<source>Input FUSION canopy height model</source>
<translation>Eingabe FUSION Bodenbedeckungs Höhenmodell</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="227"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="244"/>
<source>Input ground .dtm layer [optional]</source>
<translation>Eingabe Boden .dtm Layer [optional]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="228"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="245"/>
<source>Height threshold</source>
<translation>Höhenschwelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="229"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="246"/>
<source>Variable window size: parameter A</source>
<translation>Variable Fenstergröße: Parameter A</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="230"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="247"/>
<source>Parameter C</source>
<translation>Parameter C</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="231"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="248"/>
<source>Summary (tree height summary statistics)</source>
<translation>Zusammenfassung (Baumhöhenzusammenfassungsstatistik)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="232"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="249"/>
<source>Output file with maxima</source>
<translation>Ausgabedatei mit Maxima</translation>
</message>
@@ -1093,67 +1158,67 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>CanopyModel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="236"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="253"/>
<source>Canopy Model</source>
<translation>Bodenbedeckungsmodell</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="237"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="254"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="238"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="255"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="239"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="256"/>
<source>Cellsize</source>
<translation>Zellengröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="240"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="257"/>
<source>XY Units</source>
<translation>XY-Einheiten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="241"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="258"/>
<source>Z Units</source>
<translation>Z-Einheit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="242"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="259"/>
<source>.dtm output surface</source>
<translation>.dtm-Ausgabeoberfläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="243"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="260"/>
<source>Input ground DTM layer</source>
<translation>Eingabe-Boden-DTM-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="244"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="261"/>
<source>Median</source>
<translation>Median</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="245"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="262"/>
<source>Smooth</source>
<translation>Glatt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="247"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="264"/>
<source>Calculate slope</source>
<translation>Neigung berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="248"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="265"/>
<source>Add an ASCII output</source>
<translation>Eine ASCII-Ausgabe hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="246"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="263"/>
<source>Class</source>
<translation>Klasse</translation>
</message>
@@ -1161,42 +1226,42 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>Catalog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="252"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="269"/>
<source>Catalog</source>
<translation>Katalog</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="253"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="270"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="254"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="271"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="255"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="272"/>
<source>Output files</source>
<translation>Ausgabedateien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="256"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="273"/>
<source>Density - area, min, max (set blank if not used)</source>
<translation>Dichte - Fläche, min, max (leer lassen, wenn nicht genutzt)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="257"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="274"/>
<source>First Density - area, min, max (set blank if not used)</source>
<translation>Erste Dichte - Fläche, min, max (leer lassen, wenn nicht benutzt)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="258"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="275"/>
<source>Intensity - area, min, max (set blank if not used)</source>
<translation>Intensität - Fläche, min, max (leer lassen, wenn nicht benutzt)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="259"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="276"/>
<source>Additional modifiers</source>
<translation>Zusätzliche Einstellungen</translation>
</message>
@@ -1204,27 +1269,27 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>Centroids</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="264"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="281"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="265"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="282"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="266"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="283"/>
<source>Centroids</source>
<translation>Zentroide</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="267"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="284"/>
<source>Error calculating centroid</source>
- <translation>Felder bei Zentrumsberechnung</translation>
+ <translation>Fehler bei Zentrumsberechnung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="263"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="280"/>
<source>Polygon centroids</source>
<translation>Polygonschwerpunkt</translation>
</message>
@@ -1240,42 +1305,42 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>CheckValidity</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="272"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="289"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="273"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="290"/>
<source>The one selected in digitizing settings</source>
<translation>Die in den Digitalisierungseinstellungen gewählte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="274"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="291"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="275"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="292"/>
<source>Method</source>
<translation>Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="276"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="293"/>
<source>Valid output</source>
<translation>Gültige Ausgabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="277"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="294"/>
<source>Invalid output</source>
<translation>Ungültige Ausgabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="278"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="295"/>
<source>Error output</source>
<translation>Fehlerausgabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="271"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="288"/>
<source>Check validity</source>
<translation>Gültigkeit prüfen</translation>
</message>
@@ -1283,37 +1348,37 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>Clip</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="283"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="300"/>
<source>Vector overlay tools</source>
<translation>Vektorlayerüberlagerungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="284"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="301"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="285"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="302"/>
<source>Clip layer</source>
<translation>Layer zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="286"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="303"/>
<source>Clipped</source>
<translation>Zugeschnitten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="287"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="304"/>
<source>GEOS geoprocessing error: One or more input features have invalid geometry.</source>
<translation>GEOS-Verarbeitungsfehler: Ein oder mehrere Eingabeobjekte haben ungültige Geometrien.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="288"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="305"/>
<source>Feature geometry error: One or more output features ignored due to invalid geometry.</source>
<translation>Objektgeometriefehler: Ein oder mehrere Objekte wegen ungültiger Geometrie ignoriert.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="282"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="299"/>
<source>Clip</source>
<translation>Zuschneiden</translation>
</message>
@@ -1321,77 +1386,77 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>ClipByExtent</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="294"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="311"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="296"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="313"/>
<source>Clipping extent</source>
<translation>Maße zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="297"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="314"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="298"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="315"/>
<source>GeoTIFF options. Compression type:</source>
<translation>GeoTIFF-Optionen. Kompressionstyp:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="299"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="316"/>
<source>Set the JPEG compression level</source>
<translation>JPEG-Kompressionsstufe setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="300"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="317"/>
<source>Set the DEFLATE compression level</source>
<translation>DEFLATE-Kompressionsstufe setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="301"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="318"/>
<source>Set the predictor for LZW or DEFLATE compression</source>
<translation>LZW- oder DEFLATE-Kompressionsvorhersage setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="302"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="319"/>
<source>Create tiled output (only used for the GTiff format)</source>
<translation>Gekachelte Ausgabe (nur bei GTIFF-Format verwendet)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="303"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="320"/>
<source>Control whether the created file is a BigTIFF or a classic TIFF</source>
<translation>Ausgabe als BigTIFF oder klassisches TIFF steuern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="304"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="321"/>
<source>Force the generation of an associated ESRI world file (.tfw))</source>
<translation>Erzeugung der zugehörigen ESRI-Worlddatei (.tfw) erzwingen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="305"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="322"/>
<source>Additional creation parameters</source>
<translation>Weitere Erzeugungsparameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="306"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="323"/>
<source>Clipped (extent)</source>
<translation>Abgeschnitten (Grenze)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="292"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="309"/>
<source>Clip raster by extent</source>
<translation>Raster auf Ausmaße zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="293"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="310"/>
<source>[GDAL] Extraction</source>
<translation>[GDAL] Extraktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="295"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="312"/>
<source>Nodata value, leave blank to take the nodata value from input</source>
<translation>Leerwert, auf 'none' belassen, um den Leerwert aus der Eingabe zu übernehmen</translation>
</message>
@@ -1399,92 +1464,92 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>ClipByMask</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="312"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="329"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="313"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="330"/>
<source>Mask layer</source>
<translation>Maskenlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="315"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="332"/>
<source>Create and output alpha band</source>
<translation>Alphakanal erzeugen und ausgeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="316"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="333"/>
<source>Crop the extent of the target dataset to the extent of the cutline</source>
<translation>Ausmaße des Zieldatensatzes auf die Ausmaße der Schnittlinie abschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="317"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="334"/>
<source>Keep resolution of output raster</source>
<translation>Auflösung des Ausgaberasters beibehalten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="318"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="335"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="319"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="336"/>
<source>GeoTIFF options. Compression type:</source>
<translation>GeoTIFF-Optionen. Kompressionstyp:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="320"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="337"/>
<source>Set the JPEG compression level</source>
<translation>JPEG-Kompressionsstufe setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="321"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="338"/>
<source>Set the DEFLATE compression level</source>
<translation>DEFLATE-Kompressionsstufe setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="322"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="339"/>
<source>Set the predictor for LZW or DEFLATE compression</source>
<translation>LZW- oder DEFLATE-Kompressionsvorhersage setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="323"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="340"/>
<source>Create tiled output (only used for the GTiff format)</source>
<translation>Gekachelte Ausgabe (nur bei GTIFF-Format verwendet)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="324"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="341"/>
<source>Control whether the created file is a BigTIFF or a classic TIFF</source>
<translation>Ausgabe als BigTIFF oder klassisches TIFF steuern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="325"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="342"/>
<source>Force the generation of an associated ESRI world file (.tfw))</source>
<translation>Erzeugung der zugehörigen ESRI-Worlddatei (.tfw) erzwingen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="326"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="343"/>
<source>Additional creation parameters</source>
<translation>Weitere Erzeugungsparameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="327"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="344"/>
<source>Clipped (mask)</source>
<translation>Abgeschnitten (Maske)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="310"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="327"/>
<source>Clip raster by mask layer</source>
<translation>Raster auf Layermaske zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="311"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="328"/>
<source>[GDAL] Extraction</source>
<translation>[GDAL] Extraktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="314"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="331"/>
<source>Nodata value, leave blank to take the nodata value from input</source>
<translation>Leerwert, auf 'none' belassen, um den Leerwert aus der Eingabe zu übernehmen</translation>
</message>
@@ -1492,42 +1557,42 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>ClipData</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="331"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="348"/>
<source>Clip Data</source>
<translation>Daten zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="332"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="349"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="333"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="350"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="334"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="351"/>
<source>Extent</source>
<translation>Umfang</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="335"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="352"/>
<source>Shape</source>
<translation>Form</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="336"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="353"/>
<source>Output clipped LAS file</source>
<translation>Zugeschnittene LAS-Datei ausgeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="337"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="354"/>
<source>Ground file for height normalization</source>
<translation>Grunddatei für Höhennormalisierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="338"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="355"/>
<source>Convert point elevations into heights above ground (used with the above command)</source>
<translation>Punkthöhen in Höhe über Grund umwandeln (zur Verwendung mit dem obigen Befehl)</translation>
</message>
@@ -1535,42 +1600,42 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>CloudMetrics</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="342"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="359"/>
<source>Cloud Metrics</source>
<translation>Wolkenmessung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="343"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="360"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="344"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="361"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="345"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="362"/>
<source>Output file with tabular metric information</source>
<translation>Ausgabedatei mit metrischer Tabelleninformation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="346"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="363"/>
<source>Above</source>
<translation>Oben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="347"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="364"/>
<source>First Impulse</source>
<translation>Erster Impuls</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="348"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="365"/>
<source>First Return</source>
<translation>Erster Rückgabewert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="349"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="366"/>
<source>Htmin</source>
<translation>Htmin</translation>
</message>
@@ -1578,37 +1643,37 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>ColorRelief</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="354"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="371"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="355"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="372"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="356"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="373"/>
<source>Band number</source>
<translation>Kanalnummer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="357"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="374"/>
<source>Compute edges</source>
<translation>Kanten berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="358"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="375"/>
<source>Color configuration file</source>
<translation>Farbkonfigurationsdatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="359"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="376"/>
<source>Matching mode</source>
<translation>Zuordnungsmodus</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="353"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="370"/>
<source>Color relief</source>
<translation>Farbrelief</translation>
</message>
@@ -1616,7 +1681,7 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>CommanderWindow</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="363"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="380"/>
<source>Missing dependency</source>
<translation>Fehlende Abhängigkeit</translation>
</message>
@@ -1624,57 +1689,57 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>ConcaveHull</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="369"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="386"/>
<source>Input point layer</source>
<translation>Eingabepunktlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="370"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="387"/>
<source>Threshold (0-1, where 1 is equivalent with Convex Hull)</source>
<translation>Schwelle (0-1, bei der 1 der konvexen Hülle entspricht)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="371"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="388"/>
<source>Allow holes</source>
<translation>Löcher erlauben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="372"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="389"/>
<source>Split multipart geometry into singleparts geometries</source>
<translation>Mehrteilige in einzelteilige Geometrien zerlegen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="367"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="384"/>
<source>Concave hull</source>
<translation>Konkave Hülle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="368"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="385"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="373"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="390"/>
<source>Creating Delaunay triangles...</source>
<translation>Erzeuge Delaunay-Dreiecke...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="374"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="391"/>
<source>Computing edges max length...</source>
<translation>Berechne Kantenmaximallänge...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="375"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="392"/>
<source>Removing features...</source>
<translation>Entferne Objekt...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="376"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="393"/>
<source>Dissolving Delaunay triangles...</source>
<translation>Löse Delaunay-Dreiecke auf...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="377"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="394"/>
<source>Saving data...</source>
<translation>Speichere Daten...</translation>
</message>
@@ -1682,52 +1747,52 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>ConfigDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="381"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="398"/>
<source>Search...</source>
<translation>Suchen...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="382"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="399"/>
<source>Setting</source>
<translation>Einstellung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="383"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="400"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="384"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="401"/>
<source>General</source>
<translation>Allgemein</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="385"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="402"/>
<source>Models</source>
<translation>Modelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="386"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="403"/>
<source>Scripts</source>
<translation>Skripte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="387"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="404"/>
<source>Providers</source>
<translation>Datenanbieter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="388"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="405"/>
<source>Menus (requires restart)</source>
<translation>Menüs (erfordert Neustart)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="389"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="406"/>
<source>Wrong value</source>
<translation>Falscher Wert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="390"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="407"/>
<source>Wrong value for parameter "%s":
%s</source>
@@ -1739,42 +1804,42 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>ConvexHull</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="398"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="415"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="399"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="416"/>
<source>Field (optional, only used if creating convex hulls by classes)</source>
<translation>Feld (optional, wird nur zur Erzeugung von konvexen Hüllen nach Klassen verwendet)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="400"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="417"/>
<source>Method</source>
<translation>Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="394"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="411"/>
<source>Convex hull</source>
<translation>Konvexe Hülle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="395"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="412"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="396"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="413"/>
<source>Create single minimum convex hull</source>
<translation>Einzelne konvexe Minimalhülle erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="397"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="414"/>
<source>Create convex hulls based on field</source>
<translation>Konvexe Hüllen auf Basis eines Eingabefelds erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="401"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="418"/>
<source>Exception while computing convex hull</source>
<translation>Ausnahme während Berechnung der konvexen Hülle</translation>
</message>
@@ -1838,42 +1903,42 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>Cover</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="406"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="423"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="407"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="424"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="408"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="425"/>
<source>Input ground DTM layer</source>
<translation>Eingabe-Boden-DTM-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="409"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="426"/>
<source>Cellsize</source>
<translation>Zellengröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="410"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="427"/>
<source>Heightbreak</source>
<translation>Höhenbruch</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="411"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="428"/>
<source>XY Units</source>
<translation>XY-Einheiten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="412"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="429"/>
<source>Z Units</source>
<translation>Z-Einheit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="405"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="422"/>
<source>Cover</source>
<translation>Bedeckung</translation>
</message>
@@ -1881,27 +1946,27 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>CreateConstantRaster</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="417"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="434"/>
<source>Raster tools</source>
<translation>Rasterwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="418"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="435"/>
<source>Reference layer</source>
<translation>Referenzlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="419"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="436"/>
<source>Constant value</source>
<translation>Konstanter Wert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="420"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="437"/>
<source>Constant</source>
<translation>Konstantes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="416"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="433"/>
<source>Create constant raster layer</source>
<translation>Konstanten Rasterlayer erzeugen</translation>
</message>
@@ -1909,27 +1974,27 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>Csv2Grid</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="424"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="441"/>
<source>Csv2Grid</source>
<translation>CSV nach Grid</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="425"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="442"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="426"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="443"/>
<source>CSV Files</source>
<translation>CSV-Dateien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="427"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="444"/>
<source>Column</source>
<translation>Spalte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="428"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="445"/>
<source>Raster Output file</source>
<translation>Rasterausgabedatei</translation>
</message>
@@ -1953,61 +2018,66 @@ Verarbeite Algorithmus %d/%d...</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/python-i18n.cpp" line="13"/>
+ <source>Layer</source>
+ <translation>Layer</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="14"/>
<source>DB Manager</source>
<translation>DB-Verwaltung</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="14"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="15"/>
<source>Info</source>
<translation>Info</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="15"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="16"/>
<source>Table</source>
<translation>Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="16"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="17"/>
<source>Preview</source>
<translation>Vorschau</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="17"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="18"/>
<source>&Database</source>
<translation>&Datenbank</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="18"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="19"/>
<source>&Schema</source>
<translation>&Schema</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="19"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="20"/>
<source>&Table</source>
<translation>&Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="20"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="21"/>
<source>&Refresh</source>
<translation>&Aktualisieren</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="21"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="22"/>
<source>&SQL window</source>
<translation>S&QL-Fenster</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="22"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="23"/>
<source>&Exit</source>
<translation>&Verlassen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="23"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="24"/>
<source>&Import layer/file</source>
<translation>Layer/Datei &importieren</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="24"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="25"/>
<source>&Export to file</source>
<translation>In Datei e&xportieren</translation>
</message>
@@ -2015,414 +2085,414 @@ Verarbeite Algorithmus %d/%d...</translation>
<context>
<name>DBManagerPlugin</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="28"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="29"/>
<source>Unable to find a valid unique field</source>
<translation>Konnte kein gültiges eindeutiges Feld finden</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="173"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="174"/>
<source>Copy</source>
<translation>Kopieren</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="174"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="175"/>
<source>DB Manager</source>
<translation>DB-Verwaltung</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="49"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="50"/>
<source>Select an empty schema for deletion.</source>
<translation>Leeres zu löschendes Schema wählen.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="51"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="52"/>
<source>Select a table for editation.</source>
<translation>Tabelle zur Bearbeitung wählen.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="52"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="53"/>
<source>Select a table/view for deletion.</source>
<translation>Zu löschende Tabelle/Sicht wählen.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="54"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="55"/>
<source>Select a table to empty it.</source>
<translation>Zu leerende Tabelle wählen.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="56"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="57"/>
<source>Select a table/view.</source>
<translation>Tabelle/Sicht wählen.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="158"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="159"/>
<source>Server version: </source>
<translation>Server-Version: </translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="70"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="71"/>
<source>Host:</source>
<translation>Server:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="71"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="72"/>
<source>User:</source>
<translation>Benutzer:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="89"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="90"/>
<source>Library:</source>
<translation>Bibliothek:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="92"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="93"/>
<source><warning> geometry_columns table doesn't exist!
This table is essential for many GIS applications for enumeration of tables.</source>
<translation><warning> Tabelle geometry_columns nicht vorhanden!
Diese Tabelle ist für viele GIS-Anwendungen für die Bestimmung der Tabelle unverzichtbar.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="159"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="160"/>
<source>create new schemas</source>
<translation>Neue Schemata erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="160"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="161"/>
<source>create temporary tables</source>
<translation>Temporärtabellen erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="161"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="162"/>
<source>Not connected</source>
<translation>Nicht verbunden</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="162"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="163"/>
<source>Connection details</source>
<translation>Verbindungsdetails</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="131"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="132"/>
<source>General info</source>
<translation>Allgemeine Informationen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="163"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="164"/>
<source><warning> %s support not enabled!</source>
<translation><warnung> Unterstützung für %s nicht aktiv!</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="85"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="86"/>
<source><warning> This user has no privileges!</source>
<translation><warning> Dieser Benutzer hat keine Rechte!</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="164"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="165"/>
<source>User has privileges:</source>
<translation>Benutzerrechte:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="165"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="166"/>
<source>Privileges</source>
<translation>Rechte</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="77"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="78"/>
<source>Owner:</source>
<translation>Besitzer:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="78"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="79"/>
<source>Comment:</source>
<translation>Kommentar:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="137"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="138"/>
<source>Materialized View information</source>
<translation>Materialisierte Sichtinformation</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="166"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="167"/>
<source>create new objects</source>
<translation>Neue Objekte erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="167"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="168"/>
<source>access objects</source>
<translation>Zugriffsobjekte</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="168"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="169"/>
<source>Schema details</source>
<translation>Schemadetails</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="169"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="170"/>
<source><warning> This user has no privileges to access this schema!</source>
<translation><warning> Dieser Benutzer hat keine Zugriffsrechte für dieses Schema!</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="73"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="74"/>
<source>Relation type:</source>
<translation>Beziehungsart:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="74"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="75"/>
<source>View</source>
<translation>Sicht</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="76"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="77"/>
<source>Table</source>
<translation>Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="170"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="171"/>
<source>Rows:</source>
<translation>Zeilen:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="84"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="85"/>
<source>Unknown (<a href="action:rows/count">find out</a>)</source>
<translation>Unbekannt (<a href="action:rows/count">Feststellen</a>)</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="94"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="95"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="95"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="96"/>
<source>Type</source>
<translation>Typ</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="97"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="98"/>
<source>Null</source>
<translation>Null</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="98"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="99"/>
<source>Default</source>
<translation>Voreinstellung</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="124"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="125"/>
<source>Column(s)</source>
<translation>Spalte(n)</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="99"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="100"/>
<source>Function</source>
<translation>Funktion</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="132"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="133"/>
<source><warning> This is not a spatial table.</source>
<translation><warning> Keine räumliche Tabelle.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="133"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="134"/>
<source>Fields</source>
<translation>Felder</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="134"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="135"/>
<source>Constraints</source>
<translation>Restriktionen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="135"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="136"/>
<source>Indexes</source>
<translation>Indizes</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="136"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="137"/>
<source>Triggers</source>
<translation>Trigger</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="171"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="172"/>
<source>View definition</source>
<translation>Definition anzeigen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="148"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="149"/>
<source>Column:</source>
<translation>Spalte:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="149"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="150"/>
<source>Geometry:</source>
<translation>Geometrie:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="151"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="152"/>
<source>Dimension:</source>
<translation>Dimension:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="152"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="153"/>
<source>Undefined</source>
<translation>Undefiniert</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="153"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="154"/>
<source>Spatial ref:</source>
<translation>Räuml. Bez.:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="154"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="155"/>
<source>Estimated extent:</source>
<translation>Geschätzte Ausmaße:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="155"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="156"/>
<source>(unknown) (<a href="action:extent/get">find out</a>)</source>
<translation>Unbekannt (<a href="action:extent/get">Feststellen</a>)</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="156"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="157"/>
<source>Extent:</source>
<translation>Grenzen:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="172"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="173"/>
<source><warning> No spatial index defined (<a href="action:spatialindex/create">create it</a>)</source>
<translation><warning> Kein räumlicher Index definiert(<a href="action:spatialindex/create">Erzeugen</a>)</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="75"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="76"/>
<source>Materialized view</source>
<translation>Materialisierte Sicht</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="79"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="80"/>
<source>Pages:</source>
<translation>Seiten:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="80"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="81"/>
<source>Rows (estimation):</source>
<translation>Zeilen (geschätzt):</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="81"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="82"/>
<source>Privileges:</source>
<translation>Rechte:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="82"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="83"/>
<source><warning> This user doesn't have usage privileges for this schema!</source>
<translation><warning> Dieser Benutzer hat keine Nutzungsrechte für dieses Schema!</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="83"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="84"/>
<source>Rows (counted):</source>
<translation>Zeilen (gezählt):</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="86"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="87"/>
<source><warning> This user has read-only privileges.</source>
<translation><warning> Dieser Benutzer hat nur Leserechte.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="87"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="88"/>
<source><warning> There's a significant difference between estimated and real row count. Consider running <a href="action:vacuumanalyze/run">VACUUM ANALYZE</a>.</source>
<translation><warning> Es gibt einen signifikanten Unterschied zwischen der geschätzen und der wirklichen Zeilenanzahl. Erwägen Sie <a href="action:vacuumanalyze/run">VACUUM ANALYZE</a> auszuführen.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="88"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="89"/>
<source><warning> No primary key defined for this table!</source>
<translation><warning> Kein Primärschlüssel für diese Tabelle definiert!</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="90"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="91"/>
<source>Scripts:</source>
<translation>Skripte:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="91"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="92"/>
<source><warning> Version of installed scripts doesn't match version of released scripts!
This is probably a result of incorrect PostGIS upgrade.</source>
<translation><warning> Version der installierten Skripte entspricht nicht der der aktuellen Skripte! Die ist wahrscheinlich Folge einer falschen PostGIS-Aktualisierung.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="93"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="94"/>
<source><warning> This user doesn't have privileges to read contents of geometry_columns table!
This table is essential for many GIS applications for enumeration of tables.</source>
<translation><warning> Der Benutzer hat keine Rechte die Tabelle geometry_columns zu lesen!
Diese Tabelle ist für viele GIS-Anwendungen für die Bestimmung der Tabelle unverzichtbar.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="96"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="97"/>
<source>Length</source>
<translation>Länge</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="100"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="101"/>
<source>Enabled</source>
<translation>Eingeschaltet</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="101"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="102"/>
<source>Yes</source>
<translation>Ja</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="102"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="103"/>
<source>No</source>
<translation>Nein</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="103"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="104"/>
<source><a href="action:triggers/enable">Enable all triggers</a> / <a href="action:triggers/disable">Disable all triggers</a></source>
<translation><a href="action:triggers/enable">Alle Trigger aktivieren</a> / <a href="action:triggers/disable">Alle Trigger deaktivieren</a></translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="104"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="105"/>
<source>Definition</source>
<translation>Definition</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="105"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="106"/>
<source>Rules</source>
<translation>Regeln</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="69"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="70"/>
<source>&Versioning</source>
<translation>&Versionierung</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="40"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="41"/>
<source>&Table</source>
<translation>&Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="106"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="107"/>
<source>"{0}" not found</source>
<translation>"{0}" nicht gefunden</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="107"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="108"/>
<source>Filename:</source>
<translation>Dateiname:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="108"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="109"/>
<source>SQLite version:</source>
<translation>SQLIte-Version:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="29"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="30"/>
<source>Error:
%s</source>
<translation>Fehler:
%s</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="30"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="31"/>
<source>
Query:
@@ -2433,350 +2503,355 @@ Abfrage:
%s</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="33"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="34"/>
<source>&Re-connect</source>
<translation>&Neu verbinden</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="34"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="35"/>
<source>&Database</source>
<translation>&Datenbank</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="35"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="36"/>
<source>&Create schema</source>
<translation>&Schema anlegen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="36"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="37"/>
<source>&Schema</source>
<translation>&Schema</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="37"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="38"/>
<source>&Delete (empty) schema</source>
<translation>(&Leeres) Schema löschen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="38"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="39"/>
<source>Delete selected item</source>
<translation>Lösche gewähltes Element</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="39"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="40"/>
<source>&Create table</source>
<translation>Tabelle &anlegen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="41"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="42"/>
<source>&Edit table</source>
<translation>Tabelle &bearbeiten</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="42"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="43"/>
<source>&Delete table/view</source>
<translation>Tabelle/Sicht l&öschen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="43"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="44"/>
<source>&Empty table</source>
<translation>Tabelle &leeren</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="44"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="45"/>
<source>&Move to schema</source>
<translation>In Schema &verschieben</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="45"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="46"/>
<source>Cannot delete the selected item.</source>
<translation>Konnte gewähltes Objekt nicht löschen.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="46"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="47"/>
<source>No database selected or you are not connected to it.</source>
<translation>Keine Datenbank gewählt oder keine Verbindung möglich.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="47"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="48"/>
<source>New schema</source>
<translation>Neues Schema</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="48"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="49"/>
<source>Enter new schema name</source>
<translation>Neuen Schemanamen eingeben</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="31"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="32"/>
<source>hey!</source>
<translation>Hey!</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="32"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="33"/>
<source>Really remove connection to %s?</source>
<translation>Verbindung zu %s wirklich löschen?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="50"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="51"/>
<source>Really delete schema %s?</source>
<translation>Das Schema %s wirklich löschen?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="53"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="54"/>
<source>Really delete table/view %s?</source>
<translation>Tabelle/Sicht %s wirklich löschen?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="55"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="56"/>
<source>Really delete all items from table %s?</source>
<translation>Wirklich alle Elemente der Tabelle %s löschen?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="57"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="58"/>
<source>Do you want to %s all triggers?</source>
<translation>Aktion %s auf alle Trigger ausführen?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="58"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="59"/>
<source>Table triggers</source>
<translation>Tabellentrigger</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="59"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="60"/>
<source>Do you want to %s trigger %s?</source>
<translation>Aktion %s auf Trigger %s anwenden?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="60"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="61"/>
<source>Table trigger</source>
<translation>Tabellentrigger</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="61"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="62"/>
<source>Do you want to %s spatial index for field %s?</source>
<translation>Aktion %s auf räumlichen Index für Feld %s ausführen?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="62"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="63"/>
<source>Spatial Index</source>
<translation>Räumlicher Index</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="63"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="64"/>
<source>Check</source>
<translation>Prüfen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="64"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="65"/>
<source>Primary key</source>
<translation>Primärschlüssel</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="65"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="66"/>
<source>Foreign key</source>
<translation>Fremdschlüssel</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="66"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="67"/>
<source>Unique</source>
<translation>Eindeutig</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="67"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="68"/>
<source>Exclusion</source>
<translation>Ausschluß</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="68"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="69"/>
<source>Unknown</source>
<translation>Unbekannt</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="109"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="110"/>
<source>Table Index</source>
<translation>Tabellenindex</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="72"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="73"/>
<source>Database:</source>
<translation>Datenbank:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="110"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="111"/>
<source>SQLite list tables cache:</source>
<translation>SQLite-Tabellencache:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="111"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="112"/>
<source>Oracle Spatial:</source>
<translation>Oracle Spatial:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="112"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="113"/>
<source>Object type:</source>
<translation>Objekttyp:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="113"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="114"/>
<source>Creation Date:</source>
<translation>Erzeugungsdatum:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="114"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="115"/>
<source>Last Modification Date:</source>
<translation>Letztes Änderungsdatum:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="115"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="116"/>
<source>Comment</source>
<translation>Kommentar</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="116"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="117"/>
<source>Column</source>
<translation>Spalte</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="117"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="118"/>
<source>Status</source>
<translation>Status</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="118"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="119"/>
<source>Validated</source>
<translation>Überprüft</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="119"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="120"/>
<source>Generated</source>
<translation>Erzeugt</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="120"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="121"/>
<source>Check condition</source>
<translation>Prüfungsbedingung</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="121"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="122"/>
<source>Foreign Table</source>
<translation>Fremdtabelle</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="122"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="123"/>
<source>Foreign column</source>
<translation>Fremdspalte</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="123"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="124"/>
<source>On Delete</source>
<translation>Beim Löschen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="125"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="126"/>
<source>Index Type</source>
<translation>Indextyp</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="126"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="127"/>
<source>Last analyzed</source>
<translation>Zuletzt analysiert</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="127"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="128"/>
<source>Compression</source>
<translation>Kompression</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="128"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="129"/>
<source>Uniqueness</source>
<translation>Eindeutigkeit</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="129"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="130"/>
<source>Action</source>
<translation>Aktion</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="130"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="131"/>
<source>Event</source>
<translation>Ereignis</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="138"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="139"/>
<source>Refresh Mode:</source>
<translation>Aktualisierungsmodus:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="139"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="140"/>
<source>Refresh Method:</source>
<translation>Aktualisierungsmethode:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="140"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="141"/>
<source>Build Mode:</source>
<translation>Erzeugungsmodus:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="141"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="142"/>
<source>Last Refresh Date:</source>
<translation>Letztes Aktualisierungsdatum:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="142"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="143"/>
<source>Last Refresh Type:</source>
<translation>Letzter Aktualisierungstyp:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="143"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="144"/>
<source>Fast Refreshable:</source>
<translation>Schnell aktualisierbar:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="144"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="145"/>
<source>Staleness:</source>
<translation>Ungültigkeit:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="145"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="146"/>
<source>Stale since:</source>
<translation>Ungültig seit:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="146"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="147"/>
<source>Compile State:</source>
<translation>Übersetzungsstatus:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="147"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="148"/>
<source>Use no index:</source>
<translation>Keinen Index nutzen:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="150"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="151"/>
<source>QGis Geometry type:</source>
<translation>QGIS-Geometrietyp:</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="157"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="158"/>
<source><warning> There is no entry in geometry_columns!</source>
<translation><warning> Kein Eintrag in geometry_columns!</translation>
</message>
+ <message>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="176"/>
+ <source>Update Sql Layer</source>
+ <translation>Layerabfrage aktualisieren</translation>
+ </message>
</context>
<context>
<name>DBModel</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="178"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="180"/>
<source>Databases</source>
<translation>Datenbanken</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="179"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="181"/>
<source>Invalid layer</source>
<translation>Ungültiger Layer</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="180"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="182"/>
<source>Unable to load the layer %s</source>
<translation>Konnte den Layer %s nicht laden</translation>
</message>
@@ -2784,42 +2859,42 @@ Abfrage:
<context>
<name>DBTree</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="184"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="186"/>
<source>Rename</source>
<translation>Umbenennen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="185"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="187"/>
<source>Delete</source>
<translation>Löschen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="186"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="188"/>
<source>Add to canvas</source>
<translation>Zur Karte hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="187"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="189"/>
<source>Re-connect</source>
<translation>Neu verbinden</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="188"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="190"/>
<source>Remove</source>
<translation>Entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="189"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="191"/>
<source>New Connection...</source>
<translation>Neue Verbindung...</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="190"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="192"/>
<source>%1 is an invalid layer - not loaded</source>
<translation>%1 ist ein ungültiger Layer - nicht geladen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="191"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="193"/>
<source>%1 is an invalid layer and cannot be loaded. Please check the <a href="#messageLog">message log</a> for further info.</source>
<translation>%1 ist ein ungültiger Layer und kann nicht geladen werden. Bitte untersuchen Sie das <a href="#messageLog">Protokoll</a> auf weitere Informationen.</translation>
</message>
@@ -2827,22 +2902,22 @@ Abfrage:
<context>
<name>DTM2ASCII</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="432"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="449"/>
<source>DTM to ASCII</source>
<translation>DTM nach ASCII</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="433"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="450"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="434"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="451"/>
<source>Input canopy surface (.dtm)</source>
<translation>Eingabe Bodenbedeckung (.dtm)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="435"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="452"/>
<source>Output format</source>
<translation>Ausgabeformat</translation>
</message>
@@ -2850,22 +2925,22 @@ Abfrage:
<context>
<name>DTM2TIF</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="439"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="456"/>
<source>DTM to TIF</source>
<translation>DTM nach TIF</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="440"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="457"/>
<source>Conversion</source>
<translation>Konvertierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="441"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="458"/>
<source>Input .dtm layer</source>
<translation>Eingabe .dtm Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="442"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="459"/>
<source>Output file name</source>
<translation>Ausgabedateiname</translation>
</message>
@@ -2873,37 +2948,37 @@ Abfrage:
<context>
<name>Datasources2Vrt</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="447"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="464"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="448"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="465"/>
<source>Input datasources</source>
<translation>Eingabedatenquellen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="449"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="466"/>
<source>Create "unioned" VRT</source>
<translation>"Zusammengesetztes" VRT erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="452"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="469"/>
<source>Invalid datasource: {}</source>
<translation>Ungültige Datenquelle: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="450"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="467"/>
<source>Virtual vector</source>
<translation>Virtueller Vektor</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="451"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="468"/>
<source>Virtual string</source>
<translation>Virtuelle Zeichenkette</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="446"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="463"/>
<source>Build virtual vector</source>
<translation>Virtuellen Vektor erzeugen</translation>
</message>
@@ -2912,31 +2987,31 @@ Abfrage:
<name>DbManagerDlgAddGeometryColumn</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgAddGeometryColumn.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="195"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="197"/>
<source>Add geometry column</source>
<translation>Geometriespalte hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgAddGeometryColumn.ui" line="20"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="196"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="198"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgAddGeometryColumn.ui" line="37"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="197"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="199"/>
<source>Type</source>
<translation>Typ</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgAddGeometryColumn.ui" line="86"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="198"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="200"/>
<source>Dimensions</source>
<translation>Dimensionen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgAddGeometryColumn.ui" line="119"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="199"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="201"/>
<source>SRID</source>
<translation>SRID</translation>
</message>
@@ -2945,25 +3020,25 @@ Abfrage:
<name>DbManagerDlgCreateConstraint</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateConstraint.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="203"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="205"/>
<source>Add constraint</source>
<translation>Restriktion hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateConstraint.ui" line="20"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="204"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="206"/>
<source>Column</source>
<translation>Spalte</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateConstraint.ui" line="37"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="205"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="207"/>
<source>Primary key</source>
<translation>Primärschlüssel</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateConstraint.ui" line="47"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="206"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="208"/>
<source>Unique</source>
<translation>Eindeutig</translation>
</message>
@@ -2972,19 +3047,19 @@ Abfrage:
<name>DbManagerDlgCreateIndex</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateIndex.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="210"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="212"/>
<source>Create index</source>
<translation>Index erzeugen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateIndex.ui" line="20"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="211"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="213"/>
<source>Column</source>
<translation>Spalte</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateIndex.ui" line="30"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="212"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="214"/>
<source>Name</source>
<translation>Name</translation>
</message>
@@ -2993,74 +3068,74 @@ Abfrage:
<name>DbManagerDlgCreateTable</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="216"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="218"/>
<source>Create Table</source>
<translation>Tabelle erzeugen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="22"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="217"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="219"/>
<source>Schema</source>
<translation>Schema</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="35"/>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="171"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="218"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="220"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="56"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="219"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="221"/>
<source>Add field</source>
<translation>Feld hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="63"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="220"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="222"/>
<source>Delete field</source>
<translation>Feld löschen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="83"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="221"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="223"/>
<source>Up</source>
<translation>Auf</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="90"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="222"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="224"/>
<source>Down</source>
<translation>Ab</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="104"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="223"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="225"/>
<source>Primary key</source>
<translation>Primärschlüssel</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="125"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="224"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="226"/>
<source>Create geometry column</source>
<translation>Geometriespalte hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="188"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="225"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="227"/>
<source>Dimensions</source>
<translation>Dimensionen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="221"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="226"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="228"/>
<source>SRID</source>
<translation>SRID</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgCreateTable.ui" line="238"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="227"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="229"/>
<source>Create spatial index</source>
<translation>Räumlichen Index erzeugen</translation>
</message>
@@ -3069,25 +3144,25 @@ Abfrage:
<name>DbManagerDlgDbError</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgDbError.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="231"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="233"/>
<source>Database Error</source>
<translation>Datenbank-Fehler</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgDbError.ui" line="30"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="232"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="234"/>
<source>An error occurred:</source>
<translation>Ein Fehler trat auf:</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgDbError.ui" line="54"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="233"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="235"/>
<source>An error occurred when executing a query:</source>
<translation>Ein Fehler trat bei der Ausführung einer Abfrage auf:</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgDbError.ui" line="71"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="234"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="236"/>
<source>Query:</source>
<translation>Abfrage:</translation>
</message>
@@ -3096,55 +3171,55 @@ Abfrage:
<name>DbManagerDlgExportVector</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgExportVector.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="238"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="240"/>
<source>Export to vector file</source>
<translation>Als Vektordatei exportieren</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgExportVector.ui" line="149"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="245"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="247"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgExportVector.ui" line="46"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="239"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="241"/>
<source>Save as</source>
<translation>Speichern als</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgExportVector.ui" line="53"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="240"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="242"/>
<source>Options</source>
<translation>Optionen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgExportVector.ui" line="59"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="241"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="243"/>
<source>Replace destination file (if exists)</source>
<translation>Zieldatei ersetzen, falls vorhanden</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgExportVector.ui" line="68"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="242"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="244"/>
<source>Source SRID</source>
<translation>Quell-SRID</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgExportVector.ui" line="101"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="243"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="245"/>
<source>Target SRID</source>
<translation>Ziel-SRID</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgExportVector.ui" line="120"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="244"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="246"/>
<source>Encoding</source>
<translation>Kodierung</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgExportVector.ui" line="156"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="246"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="248"/>
<source>Format</source>
<translation>Format</translation>
</message>
@@ -3153,37 +3228,37 @@ Abfrage:
<name>DbManagerDlgFieldProperties</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgFieldProperties.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="250"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="252"/>
<source>Field properties</source>
<translation>Feldeigenschaften</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgFieldProperties.ui" line="22"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="251"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="253"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgFieldProperties.ui" line="36"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="252"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="254"/>
<source>Type</source>
<translation>Typ</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgFieldProperties.ui" line="53"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="253"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="255"/>
<source>Can be NULL</source>
<translation>Kann NULL sein</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgFieldProperties.ui" line="70"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="254"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="256"/>
<source>Default value</source>
<translation>Vorgabewert</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgFieldProperties.ui" line="84"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="255"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="257"/>
<source>Length</source>
<translation>Länge</translation>
</message>
@@ -3192,118 +3267,239 @@ Abfrage:
<name>DbManagerDlgImportVector</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="259"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="261"/>
<source>Import vector layer</source>
<translation>Vektorlayer importieren</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="29"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="260"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="262"/>
<source>Input</source>
<translation>Eingabe</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="36"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="261"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="263"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="68"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="262"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="264"/>
<source>Import only selected features</source>
<translation>Nur gewählte Objekte importieren</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="88"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="263"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="265"/>
<source>Update options</source>
<translation>Optionen ändern</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="100"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="264"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="266"/>
<source>Output table</source>
<translation>Ausgabetabelle</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="106"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="265"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="267"/>
<source>Schema</source>
<translation>Schema</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="123"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="266"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="268"/>
<source>Table</source>
<translation>Tabelle</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="153"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="267"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="269"/>
<source>Options</source>
<translation>Optionen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="159"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="268"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="270"/>
<source>Primary key</source>
<translation>Primärschlüssel</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="173"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="269"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="271"/>
<source>Geometry column</source>
<translation>Geometriespalte</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="189"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="270"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="272"/>
<source>Source SRID</source>
<translation>Quell-SRID</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="219"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="271"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="273"/>
<source>Target SRID</source>
<translation>Ziel-SRID</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="235"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="272"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="274"/>
<source>Encoding</source>
<translation>Kodierung</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="252"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="273"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="275"/>
<source>Create single-part geometries instead of multi-part</source>
<translation>Einteilige statt mehrteiliger Geometrien erzeugen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="259"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="274"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="276"/>
<source>Create spatial index</source>
<translation>Räumlichen Index erzeugen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgImportVector.ui" line="266"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="275"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="277"/>
<source>Replace destination table (if exists)</source>
<translation>Zieltabelle ersetzen, falls vorhanden</translation>
</message>
</context>
<context>
+ <name>DbManagerDlgSqlLayerWindow</name>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="14"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="281"/>
+ <source>SQL window</source>
+ <translation>SQL-Fenster</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="22"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="282"/>
+ <source><html><head/><body><p>Avoid selecting feature by id. Sometimes - especially when running expensive queries/views - fetching the data sequentially instead of fetching features by id can be much quicker.</p></body></html></source>
+ <translation><html><head/><body><p>Auswahl von Objekten nach ID vermeiden. Manchmal- besonders, wenn teure Abfragen durchgeführt/Sichten abgefragt werden - kann das sequentielle Laden der Objekte deutlich schneller als die Abfrage nach ID sein.</p></body></html></translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="25"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="283"/>
+ <source>Avoid selecting by feature id</source>
+ <translation>Objektabfrage nach ID vermeiden</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="45"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="284"/>
+ <source>Update</source>
+ <translation>Aktualisieren</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="83"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="285"/>
+ <source>Saved query:</source>
+ <translation>Gespeicherte Abfrage:</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="93"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="286"/>
+ <source>Name</source>
+ <translation>Name</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="107"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="287"/>
+ <source>Store</source>
+ <translation>Speichern</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="114"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="288"/>
+ <source>Delete</source>
+ <translation>Löschen</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="128"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="289"/>
+ <source>&Execute (F5)</source>
+ <translation>&Ausführen (F5)</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="131"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="290"/>
+ <source>F5</source>
+ <translation>F5</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="158"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="291"/>
+ <source>&Clear</source>
+ <translation>&Löschen</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="193"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="292"/>
+ <source>Column(s) with
+unique values</source>
+ <translation>Spalte(n) mit
+eindeutigen Werten</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="220"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="293"/>
+ <source>Geometry column</source>
+ <translation>Geometriespalte</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="265"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="294"/>
+ <source>Retrieve
+columns</source>
+ <translation>Spalten
+laden</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="277"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="295"/>
+ <source>Layer name (prefix)</source>
+ <translation>Layername (Präfix)</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="303"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="296"/>
+ <source>Type</source>
+ <translation>Typ</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="313"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="297"/>
+ <source>Vector</source>
+ <translation>Vektor</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="323"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="298"/>
+ <source>Raster</source>
+ <translation>Raster</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/ui/DlgSqlLayerWindow.ui" line="349"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="299"/>
+ <source>Set filter</source>
+ <translation>Filter setzen</translation>
+ </message>
+</context>
+<context>
<name>DbManagerDlgSqlWindow</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="279"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="303"/>
<source>SQL window</source>
<translation>SQL-Fenster</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="80"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="284"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="308"/>
<source>Column(s) with
unique values</source>
<translation>Spalte(n) mit
@@ -3311,61 +3507,61 @@ eindeutigen Werten</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="242"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="291"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="315"/>
<source>Set filter</source>
<translation>Filter setzen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="313"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="294"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="318"/>
<source>Store</source>
<translation>Speichern</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="320"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="295"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="319"/>
<source>Delete</source>
<translation>Löschen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="334"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="296"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="320"/>
<source>&Execute (F5)</source>
<translation>&Ausführen (F5)</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="337"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="297"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="321"/>
<source>F5</source>
<translation>F5</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="351"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="298"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="322"/>
<source>Create a view</source>
<translation>Sicht erzeugen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="371"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="299"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="323"/>
<source>&Clear</source>
<translation>&Löschen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="26"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="280"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="304"/>
<source>Load as new layer</source>
<translation>Als neuen Layer laden</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="107"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="285"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="309"/>
<source>Geometry column</source>
<translation>Geometriespalte</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="152"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="286"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="310"/>
<source>Retrieve
columns</source>
<translation>Spalten
@@ -3373,55 +3569,55 @@ laden</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="164"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="287"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="311"/>
<source>Layer name (prefix)</source>
<translation>Layername (Präfix)</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="196"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="288"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="312"/>
<source>Type</source>
<translation>Typ</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="206"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="289"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="313"/>
<source>Vector</source>
<translation>Vektor</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="216"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="290"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="314"/>
<source>Raster</source>
<translation>Raster</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="69"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="283"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="307"/>
<source>Load now!</source>
<translation>Jetzt laden!</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="46"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="281"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="305"/>
<source><html><head/><body><p>Avoid selecting feature by id. Sometimes - especially when running expensive queries/views - fetching the data sequentially instead of fetching features by id can be much quicker.</p></body></html></source>
<translation><html><head/><body><p>Auswahl von Objekten nach ID vermeiden. Manchmal- besonders, wenn teure Abfragen durchgeführt/Sichten abgefragt werden - kann das sequentielle Laden der Objekte deutlich schneller als die Abfrage nach ID sein.</p></body></html></translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="49"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="282"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="306"/>
<source>Avoid selecting by feature id</source>
<translation>Objektabfrage nach ID vermeiden</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="289"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="292"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="316"/>
<source>Saved query:</source>
<translation>Gespeicherte Abfrage:</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgSqlWindow.ui" line="299"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="293"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="317"/>
<source>Name</source>
<translation>Name</translation>
</message>
@@ -3430,97 +3626,97 @@ laden</translation>
<name>DbManagerDlgTableProperties</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="303"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="327"/>
<source>Table properties</source>
<translation>Tabellleneigenschaften</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="24"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="304"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="328"/>
<source>Columns</source>
<translation>Spalten</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="30"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="305"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="329"/>
<source>Table columns:</source>
<translation>Tabellenspalten:</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="46"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="306"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="330"/>
<source>Add column</source>
<translation>Spalte hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="53"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="307"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="331"/>
<source>Add geometry column</source>
<translation>Geometriespalte hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="60"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="308"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="332"/>
<source>Edit column</source>
<translation>Spalte bearbeiten</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="80"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="309"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="333"/>
<source>Delete column</source>
<translation>Spalte löschen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="90"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="310"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="334"/>
<source>Constraints</source>
<translation>Restriktionen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="96"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="311"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="335"/>
<source>Primary, foreign keys, unique and check constraints:</source>
<translation>Primär-, Fremdschlüssel-, eindeutige und Prüfrestriktionen:</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="112"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="312"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="336"/>
<source>Add primary key / unique</source>
<translation>Eindeutige/Primärschlüssel</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="132"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="313"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="337"/>
<source>Delete constraint</source>
<translation>Restriktion löschen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="142"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="314"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="338"/>
<source>Indexes</source>
<translation>Indizes</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="148"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="315"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="339"/>
<source>Indexes defined for this table:</source>
<translation>Für die Tabelle definierte Indizes:</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="164"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="316"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="340"/>
<source>Add index</source>
<translation>Index hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="171"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="317"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="341"/>
<source>Add spatial index</source>
<translation>Räumlichen Index hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgTableProperties.ui" line="191"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="318"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="342"/>
<source>Delete index</source>
<translation>Index löschen</translation>
</message>
@@ -3529,7 +3725,7 @@ laden</translation>
<name>DbManagerQueryBuilderDlg</name>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="322"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="346"/>
<source>SQL query builder</source>
<translation>SQL-Abfrageditor</translation>
</message>
@@ -3537,121 +3733,121 @@ laden</translation>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="30"/>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="192"/>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="281"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="323"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="347"/>
<source>Columns</source>
<translation>Spalten</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="47"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="324"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="348"/>
<source>Tables </source>
<translation>Tabellen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="108"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="325"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="349"/>
<source>Where </source>
<translation>Filter</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="115"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="326"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="350"/>
<source>Group by</source>
<translation>Gruppieren nach</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="122"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="327"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="351"/>
<source>Order by</source>
<translation>Sortieren nach</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="163"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="328"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="352"/>
<source>Data</source>
<translation>Daten</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="175"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="329"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="353"/>
<source>Show system tables</source>
<translation>Systemtabellen anzeigen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="183"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="330"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="354"/>
<source>Tables</source>
<translation>Tabellen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="221"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="331"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="355"/>
<source>Aggregates</source>
<translation>Aggregate</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="230"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="332"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="356"/>
<source>Functions</source>
<translation>Funktionen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="239"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="333"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="357"/>
<source>Math</source>
<translation>Mathe</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="248"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="334"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="358"/>
<source>Strings functions</source>
<translation>Zeichenkettenfunktionen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="257"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="335"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="359"/>
<source>Operators</source>
<translation>Operatoren</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="274"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="336"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="360"/>
<source>Columns' values</source>
<translation>Spaltenwerte</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="289"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="337"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="361"/>
<source>Only 10 first values</source>
<translation>Nur die zehn ersten Werte</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="327"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="338"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="362"/>
<source>Spatial index</source>
<translation>Räumlicher Index</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="334"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="339"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="363"/>
<source>Table (with spatial index)</source>
<translation>Tabelle (mit räuml. Index)</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="343"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="340"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="364"/>
<source>Table (Target)</source>
<translation>Tabelle (Ziel)</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="351"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="341"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="365"/>
<source>Use spatial index</source>
<translation>Räumlichen Index benutzen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/ui/DlgQueryBuilder.ui" line="381"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="342"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="366"/>
<source>&Reset</source>
<translation>&Zurücksetzen</translation>
</message>
@@ -3659,22 +3855,22 @@ laden</translation>
<context>
<name>DefineProjection</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="456"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="473"/>
<source>Define current projection</source>
<translation>Aktuelle Projektion festlegen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="457"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="474"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="458"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="475"/>
<source>Input Layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="459"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="476"/>
<source>Layer with projection</source>
<translation>Layer mit Projektion</translation>
</message>
@@ -3682,22 +3878,22 @@ laden</translation>
<context>
<name>Delaunay</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="465"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="482"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="463"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="480"/>
<source>Delaunay triangulation</source>
<translation>Delaunay-Triangulation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="464"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="481"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="466"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="483"/>
<source>Input file should contain at least 3 points. Choose another file and try again.</source>
<translation>Eingabedatei sollte mindestens 3 Punkte enthalten. Eine andere Datei wählen und nochmal versuchen.</translation>
</message>
@@ -3705,27 +3901,27 @@ laden</translation>
<context>
<name>DeleteColumn</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="471"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="488"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="472"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="489"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="473"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="490"/>
<source>Field to delete</source>
<translation>Zu löschendes Feld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="474"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="491"/>
<source>Deleted column</source>
<translation>Gelöschte Spalte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="470"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="487"/>
<source>Delete column</source>
<translation>Spalte löschen</translation>
</message>
@@ -3733,22 +3929,22 @@ laden</translation>
<context>
<name>DeleteDuplicateGeometries</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="479"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="496"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="480"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="497"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="481"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="498"/>
<source>Cleaned</source>
<translation>Bereinigt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="478"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="495"/>
<source>Delete duplicate geometries</source>
<translation>Doppelte Geometrien löschen</translation>
</message>
@@ -3756,22 +3952,22 @@ laden</translation>
<context>
<name>DeleteHoles</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="486"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="503"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="487"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="504"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="488"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="505"/>
<source>Cleaned</source>
<translation>Bereinigt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="485"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="502"/>
<source>Delete holes</source>
<translation>Löcher löschen</translation>
</message>
@@ -3779,17 +3975,17 @@ laden</translation>
<context>
<name>DeleteModelAction</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="492"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="509"/>
<source>Delete model</source>
<translation>Lösche Modell</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="493"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="510"/>
<source>Confirmation</source>
<translation>Bestätigung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="494"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="511"/>
<source>Are you sure you want to delete this model?</source>
<translation>Dieses Modell wirklich löschen?</translation>
</message>
@@ -3797,17 +3993,17 @@ laden</translation>
<context>
<name>DeletePreconfiguredAlgorithmAction</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="498"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="515"/>
<source>Delete preconfigured algorithm</source>
<translation>Vorkonfigurierten Algorithmus entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="499"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="516"/>
<source>Confirmation</source>
<translation>Bestätigung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="500"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="517"/>
<source>Are you sure you want to delete this algorithm?</source>
<translation>Soll dieser Algorithmus wirklich gelöscht werden?</translation>
</message>
@@ -3815,17 +4011,17 @@ laden</translation>
<context>
<name>DeleteScriptAction</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="504"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="521"/>
<source>Delete script</source>
<translation>Lösche Skript</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="505"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="522"/>
<source>Confirmation</source>
<translation>Bestätigung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="506"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="523"/>
<source>Are you sure you want to delete this script?</source>
<translation>Dieses Skript wirklich löschen?</translation>
</message>
@@ -3833,27 +4029,27 @@ laden</translation>
<context>
<name>DensifyGeometries</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="511"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="528"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="512"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="529"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="513"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="530"/>
<source>Vertices to add</source>
<translation>Zu ergänzende Stützpunkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="514"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="531"/>
<source>Densified</source>
<translation>Verdichtet</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="510"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="527"/>
<source>Densify geometries</source>
<translation>Geometrien verdichten</translation>
</message>
@@ -3861,27 +4057,27 @@ laden</translation>
<context>
<name>DensifyGeometriesInterval</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="519"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="536"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="520"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="537"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="521"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="538"/>
<source>Interval between vertices to add</source>
<translation>Intervall zwischen hinzuzufügenden Stützpunkten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="522"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="539"/>
<source>Densified</source>
<translation>Verdichtet</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="518"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="535"/>
<source>Densify geometries given an interval</source>
<translation>Geometrien mit gegebenem Intervall verdichten</translation>
</message>
@@ -3889,129 +4085,164 @@ laden</translation>
<context>
<name>DesignerTree</name>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="1274"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1297"/>
+ <source>Base configuration</source>
+ <translation>Grundkonfiguration</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1310"/>
<source>Configure container</source>
<translation>Bereich einrichten</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="1284"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1318"/>
+ <source>Control visibility by expression </source>
+ <translation>Darstellung durch Ausdruck steuern </translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1324"/>
+ <source>Visibility expression</source>
+ <translation>Darstellungsausdruck</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1331"/>
<source>Title</source>
<translation>Titel</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="1285"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1332"/>
<source>Column count</source>
<translation>Spaltenanzahl</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="1289"/>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="1291"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1337"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1339"/>
<source>Show as group box</source>
<translation>Als Gruppenrahmen anzeigen</translation>
</message>
+ <message>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1369"/>
+ <source>Configure relation editor</source>
+ <translation>Beziehungseditor konfigurieren</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1374"/>
+ <source>Show link button</source>
+ <translation>Verknüpfungsknopf anzeigen</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1376"/>
+ <source>Show unlink button</source>
+ <translation>Trennknopf anzeigen</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="1402"/>
+ <source>Configure field</source>
+ <translation>Feld einstellen</translation>
+ </message>
</context>
<context>
<name>Dialog</name>
<message>
<location filename="../python/plugins/processing/ui/DlgAlgorithmBase.ui" line="26"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="540"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="557"/>
<source>Parameters</source>
<translation>Parameter</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgAlgorithmBase.ui" line="14"/>
<location filename="../python/plugins/processing/ui/DlgMessage.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="529"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="546"/>
<source>Dialog</source>
<translation>Dialog</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgAlgorithmBase.ui" line="39"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="541"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="558"/>
<source>Log</source>
<translation>Protokoll</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgAlgorithmBase.ui" line="59"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="542"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="559"/>
<source>Help</source>
<translation>Hilfe</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgPostgisTableSelector.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="526"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="543"/>
<source> output table</source>
<translation>Ausgabetabelle</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgPostgisTableSelector.ui" line="20"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="527"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="544"/>
<source>Select connection and schema</source>
<translation>Verbindung und Schema wählen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgPostgisTableSelector.ui" line="41"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="528"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="545"/>
<source>Table name</source>
<translation>Tabellenname</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/scriptselector.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="530"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="547"/>
<source>Script selector</source>
<translation>Skriptauswahl</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/scriptselector.ui" line="26"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="531"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="548"/>
<source>Scripts to include</source>
<translation>Einzuschließende Skripte</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/scriptselector.ui" line="46"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="532"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="549"/>
<source><a href='#'>All</a></source>
<translation><a href='#'>Alle</a></translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/scriptselector.ui" line="53"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="533"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="550"/>
<source><a href='#'>None</a></source>
<translation><a href='#'>Keine</a></translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/scriptselector.ui" line="85"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="534"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="551"/>
<source>Plugin name</source>
<translation>Erweiterungsname</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/scriptselector.ui" line="95"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="535"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="552"/>
<source>Plugin description</source>
<translation>Erweiterungsbeschreibung</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/scriptselector.ui" line="105"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="536"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="553"/>
<source>Author's name</source>
<translation>Autorenname</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/scriptselector.ui" line="115"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="537"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="554"/>
<source>Author's email</source>
<translation>E-Mail-Adresse des Autors</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/scriptselector.ui" line="132"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="538"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="555"/>
<source>Output folder</source>
<translation>Ausgabeverzeichnis</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/scriptselector.ui" line="144"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="539"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="556"/>
<source>...</source>
<translation>...</translation>
</message>
@@ -4019,48 +4250,48 @@ laden</translation>
<context>
<name>Difference</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="548"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="565"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="549"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="566"/>
<source>Difference layer</source>
<translation>Differenzlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="550"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="567"/>
<source>Ignore invalid input features</source>
<translation>Ungültige Eingabeobjekte ignorieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="551"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="568"/>
<source>Feature with NULL geometry found.</source>
<translation>Objekt mut NULL-Geometrie gefunden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="552"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="569"/>
<source>GEOS geoprocessing error: One or more input features have invalid geometry.</source>
<translation>GEOS-Verarbeitungsfehler: Ein oder mehrere Eingabeobjekte haben ungültige Geometrien.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="553"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="570"/>
<source>Features with invalid geometries found. Please fix these errors or specify the "Ignore invalid input features" flag</source>
<translation>Objekt mit ungütligen Geometrien gefunden. Bitte diese Fehler korrigieren oder "Ungültige Eingabeobjekte ignorieren" angeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="554"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="571"/>
<source>Feature geometry error: One or more output features ignored due to invalid geometry.</source>
<translation>
Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometrie wurden ignoriert.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="546"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="563"/>
<source>Difference</source>
<translation>Differenz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="547"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="564"/>
<source>Vector overlay tools</source>
<translation>Vektorlayerüberlagerungswerkzeuge</translation>
</message>
@@ -4068,57 +4299,57 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DinfDistDown</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="558"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="575"/>
<source>D-Infinity Distance Down</source>
<translation>D-Infinity Entfernung nach unten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="559"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="576"/>
<source>Specialized Grid Analysis tools</source>
<translation>Spezialisierte Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="560"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="577"/>
<source>D-Infinity Flow Direction Grid</source>
<translation>D-Infinity Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="561"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="578"/>
<source>Pit Filled Elevation Grid</source>
<translation>Höhengitter mit gefüllten Löchern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="562"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="579"/>
<source>Stream Raster Grid</source>
<translation>Stromrastergitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="563"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="580"/>
<source>Weight Path Grid</source>
<translation>Pfadgewichtungsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="564"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="581"/>
<source>Statistical Method</source>
<translation>Statistische Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="565"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="582"/>
<source>Distance Method</source>
<translation>Distanz Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="566"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="583"/>
<source>Check for edge contamination</source>
<translation>Kantenverunreinigung prüfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="567"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="584"/>
<source>D-Infinity Drop to Stream Grid</source>
<translation>D-Infinity Abstand nach unten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="568"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="585"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -4126,57 +4357,57 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DinfDistDownMulti</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="572"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="589"/>
<source>D-Infinity Distance Down (multifile)</source>
<translation>D-Infinity Entfernung nach unten (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="573"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="590"/>
<source>Specialized Grid Analysis tools</source>
<translation>Spezialisierte Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="574"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="591"/>
<source>D-Infinity Flow Direction Grid</source>
<translation>D-Infinity Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="575"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="592"/>
<source>Pit Filled Elevation Grid</source>
<translation>Höhengitter mit gefüllten Löchern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="576"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="593"/>
<source>Stream Raster Grid</source>
<translation>Stromrastergitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="577"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="594"/>
<source>Weight Path Grid</source>
<translation>Pfadgewichtungsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="578"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="595"/>
<source>Statistical Method</source>
<translation>Statistische Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="579"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="596"/>
<source>Distance Method</source>
<translation>Distanz Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="580"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="597"/>
<source>Check for edge contamination</source>
<translation>Kantenverunreinigung prüfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="581"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="598"/>
<source>D-Infinity Drop to Stream Grid</source>
<translation>D-Infinity Sende and Strom Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="582"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="599"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -4184,52 +4415,52 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DinfDistUp</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="588"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="605"/>
<source>D-Infinity Flow Direction Grid</source>
<translation>D-Infinity Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="589"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="606"/>
<source>Pit Filled Elevation Grid</source>
<translation>Höhengitter mit gefüllten Löchern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="590"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="607"/>
<source>Slope Grid</source>
<translation>Neigungsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="591"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="608"/>
<source>Statistical Method</source>
<translation>Statistische Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="592"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="609"/>
<source>Distance Method</source>
<translation>Distanz Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="593"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="610"/>
<source>Proportion Threshold</source>
<translation>Anteils Schwellenwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="594"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="611"/>
<source>Check for edge contamination</source>
<translation>Kantenverunreinigung prüfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="586"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="603"/>
<source>D-Infinity Distance Up</source>
<translation>D-Infinity Entfernung hoch</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="587"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="604"/>
<source>Specialized Grid Analysis tools</source>
<translation>Spezialisierte Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="595"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="612"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -4237,57 +4468,57 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DinfDistUpMulti</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="599"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="616"/>
<source>D-Infinity Distance Up (multifile)</source>
<translation>D-Infinity Entfernung nach oben (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="600"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="617"/>
<source>Specialized Grid Analysis tools</source>
<translation>Spezialisierte Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="601"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="618"/>
<source>D-Infinity Flow Direction Grid</source>
<translation>D-Infinity Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="602"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="619"/>
<source>Pit Filled Elevation Grid</source>
<translation>Höhengitter mit gefüllten Löchern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="603"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="620"/>
<source>Slope Grid</source>
<translation>Neigungsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="604"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="621"/>
<source>Statistical Method</source>
<translation>Statistische Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="605"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="622"/>
<source>Distance Method</source>
<translation>Distanz Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="606"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="623"/>
<source>Proportion Threshold</source>
<translation>Anteils Schwellenwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="607"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="624"/>
<source>Check for edge contamination</source>
<translation>Kantenverunreinigung prüfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="608"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="625"/>
<source>D-Infinity Distance Up</source>
<translation>D-Infinity Entfernung hoch</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="609"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="626"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -4295,52 +4526,52 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DinfTransLimAccum</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="613"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="630"/>
<source>D-Infinity Transport Limited Accumulation</source>
<translation>D-Infinity transportbegrenzte Akkumulation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="614"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="631"/>
<source>Specialized Grid Analysis tools</source>
<translation>Spezialisierte Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="615"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="632"/>
<source>D-Infinity Flow Direction Grid</source>
<translation>D-Infinity Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="616"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="633"/>
<source>Supply Grid</source>
<translation>Versorgungsnetz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="617"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="634"/>
<source>Transport Capacity Grid</source>
<translation>Transportkapazitätsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="618"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="635"/>
<source>Outlets Shapefile</source>
<translation>Auslaß-Shapedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="619"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="636"/>
<source>Check for edge contamination</source>
<translation>Kantenverunreinigung prüfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="620"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="637"/>
<source>Transport Limited Accumulation Grid</source>
<translation>Transportbegrenztes Akkumulations Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="621"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="638"/>
<source>Deposition Grid</source>
<translation>Ablagerungs Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="622"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="639"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -4348,62 +4579,62 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DinfTransLimAccum2</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="626"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="643"/>
<source>D-Infinity Transport Limited Accumulation - 2</source>
<translation>D-Infinity transportbegrenzte Akkumulation - 2</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="627"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="644"/>
<source>Specialized Grid Analysis tools</source>
<translation>Spezialisierte Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="628"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="645"/>
<source>D-Infinity Flow Direction Grid</source>
<translation>D-Infinity Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="629"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="646"/>
<source>Supply Grid</source>
<translation>Versorgungsnetz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="630"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="647"/>
<source>Transport Capacity Grid</source>
<translation>Transportkapazitätsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="631"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="648"/>
<source>Input Concentration Grid</source>
<translation>Eingangs Konzentrationsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="632"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="649"/>
<source>Outlets Shapefile</source>
<translation>Auslaß-Shapedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="633"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="650"/>
<source>Check for edge contamination</source>
<translation>Kantenverunreinigung prüfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="634"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="651"/>
<source>Transport Limited Accumulation Grid</source>
<translation>Transportbegrenztes Akkumulations Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="635"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="652"/>
<source>Deposition Grid</source>
<translation>Ablagerungs Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="636"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="653"/>
<source>Output Concentration Grid</source>
<translation>Ausgangs Konzentrationsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="637"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="654"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -4411,62 +4642,62 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DinfTransLimAccum2Multi</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="641"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="658"/>
<source>D-Infinity Transport Limited Accumulation - 2 (multifile)</source>
<translation>D-Infinity transportbegrenzte Akkumulation - 2 (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="642"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="659"/>
<source>Specialized Grid Analysis tools</source>
<translation>Spezialisierte Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="643"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="660"/>
<source>D-Infinity Flow Direction Grid</source>
<translation>D-Infinity Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="644"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="661"/>
<source>Supply Grid</source>
<translation>Versorgungsnetz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="645"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="662"/>
<source>Transport Capacity Grid</source>
<translation>Transportkapazitätsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="646"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="663"/>
<source>Input Concentration Grid</source>
<translation>Eingangs Konzentrationsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="647"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="664"/>
<source>Outlets Shapefile</source>
<translation>Auslaß-Shapedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="648"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="665"/>
<source>Check for edge contamination</source>
<translation>Kantenverunreinigung prüfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="649"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="666"/>
<source>Transport Limited Accumulation Grid</source>
<translation>Transportbegrenztes Akkumulations Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="650"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="667"/>
<source>Deposition Grid</source>
<translation>Ablagerungs Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="651"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="668"/>
<source>Output Concentration Grid</source>
<translation>Ausgangs Konzentrationsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="652"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="669"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -4474,52 +4705,52 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DinfTransLimAccumMulti</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="656"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="673"/>
<source>D-Infinity Transport Limited Accumulation (multifile)</source>
<translation>D-Infinity transportbegrenzte Akkumulation (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="657"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="674"/>
<source>Specialized Grid Analysis tools</source>
<translation>Spezialisierte Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="658"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="675"/>
<source>D-Infinity Flow Direction Grid</source>
<translation>D-Infinity Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="659"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="676"/>
<source>Supply Grid</source>
<translation>Versorgungsnetz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="660"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="677"/>
<source>Transport Capacity Grid</source>
<translation>Transportkapazitätsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="661"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="678"/>
<source>Outlets Shapefile</source>
<translation>Auslaß-Shapedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="662"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="679"/>
<source>Check for edge contamination</source>
<translation>Kantenverunreinigung prüfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="663"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="680"/>
<source>Transport Limited Accumulation Grid</source>
<translation>Transportbegrenztes Akkumulations Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="664"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="681"/>
<source>Deposition Grid</source>
<translation>Ablagerungs Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="665"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="682"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -4527,22 +4758,22 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DirectorySelectorDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="669"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="686"/>
<source>Add</source>
<translation>Hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="670"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="687"/>
<source>Remove</source>
<translation>Entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="671"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="688"/>
<source>Remove all</source>
<translation>Alle entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="672"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="689"/>
<source>Select directory</source>
<translation>Verzeichnis wählen</translation>
</message>
@@ -4550,52 +4781,50 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>Dissolve</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="684"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="699"/>
<source>Geometry exception while dissolving</source>
<translation>Geometrieausnahme während Zerlegung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="677"/>
<source>Dissolve all (do not use field)</source>
- <translation>Alle auflösen (Feld nicht nutzen)</translation>
+ <translation type="obsolete">Alle auflösen (Feld nicht nutzen)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="678"/>
<source>Unique ID field</source>
- <translation>Eindeutiges Schlüsselfeld</translation>
+ <translation type="obsolete">Eindeutiges Schlüsselfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="680"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="697"/>
<source>ValidateGeometry()error: One or more input features have invalid geometry: </source>
<translation>Geometrievalidierungsfehler: Ein oder mehrere Eingabeobjekt haben ungültige Geometrie:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="681"/>
- <source>Skipped feature %i, which has a null geometry</source>
- <translation>Objekt %i mit Null-Geometrie übersprungen</translation>
- </message>
- <message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="682"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="698"/>
<source>ValidateGeometry()error:One or more inputfeatures have invalid geometry: </source>
<translation>GEOS-Validierungsfehler: Ein oder mehrere Eingabeobjekte haben ungültige Geometrien:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="683"/>
- <source>Skipped feature %i. Dissolve resulted in null geometry</source>
- <translation>Objekt %i übersprungen. Auflösung lieferte Null-Geometrie</translation>
- </message>
- <message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="685"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="700"/>
<source>ValidateGeometry() error: One or more inputfeatures have invalid geometry: </source>
<translation>Geometriefehler: Ein oder mehrere Eingabeobjekt haben ungültige Geometrie:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="676"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="693"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="679"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="694"/>
+ <source>Dissolve all (do not use fields)</source>
+ <translation>Alle auflösen (Felder nicht nutzen)</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="695"/>
+ <source>Unique ID fields</source>
+ <translation>Eindeutige Schlüsselfelder</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="696"/>
<source>Dissolved</source>
<translation>Aufgelöst</translation>
</message>
@@ -4603,12 +4832,12 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DlgAddGeometryColumn</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="346"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="370"/>
<source>DB Manager</source>
<translation>DB-Verwaltung</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="347"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="371"/>
<source>field name must not be empty</source>
<translation>Feldname darf nicht leer sein</translation>
</message>
@@ -4617,37 +4846,37 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgAutofill</name>
<message>
<location filename="../python/plugins/processing/ui/DlgAutofill.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="689"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="704"/>
<source>Autofill settings</source>
<translation>Autofülleinstellungen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgAutofill.ui" line="20"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="690"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="705"/>
<source>Autofill mode</source>
<translation>Autofüllmodus</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgAutofill.ui" line="28"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="691"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="706"/>
<source>Do not autofill</source>
<translation>Nicht automatisch füllen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgAutofill.ui" line="33"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="692"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="707"/>
<source>Fill with numbers</source>
<translation>Mit Zahlen füllen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgAutofill.ui" line="38"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="693"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="708"/>
<source>Fill with parameter values</source>
<translation>Mit Parameterwerten füllen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgAutofill.ui" line="49"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="694"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="709"/>
<source>Parameter to use</source>
<translation>Zu benutzender Parameter</translation>
</message>
@@ -4656,13 +4885,13 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgConfig</name>
<message>
<location filename="../python/plugins/processing/ui/DlgConfig.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="698"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="713"/>
<source>Processing options</source>
<translation>Verarbeitungsoptionen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgConfig.ui" line="26"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="699"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="714"/>
<source>Enter setting name to filter list</source>
<translation>Einstellungsname eingeben, um Liste zu filtern</translation>
</message>
@@ -4670,12 +4899,12 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DlgCreateIndex</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="351"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="375"/>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="352"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="376"/>
<source>Please enter some name for the index</source>
<translation>Bitte einen Indexnamen angeben</translation>
</message>
@@ -4683,62 +4912,62 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DlgCreateTable</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="356"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="380"/>
<source>&Create</source>
<translation>&Erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="357"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="381"/>
<source>DB Manager</source>
<translation>DB-Verwaltung</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="358"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="382"/>
<source>no field selected</source>
<translation>Kein Feld gewählt</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="359"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="383"/>
<source>field is at top already</source>
<translation>Feld ist bereits ganz oben</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="360"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="384"/>
<source>No field selected</source>
<translation>Kein Feld gewählt</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="361"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="385"/>
<source>field is at bottom already</source>
<translation>Feld ist bereits ganz unten</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="362"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="386"/>
<source>select schema!</source>
<translation>Schema wählen!</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="363"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="387"/>
<source>enter table name!</source>
<translation>Tabellennamen eingeben!</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="364"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="388"/>
<source>add some fields!</source>
<translation>Felder hinzufügen!</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="365"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="389"/>
<source>set geometry column name</source>
<translation>Geometriespaltennamen angeben</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="366"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="390"/>
<source>Good</source>
<translation>Gut</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="367"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="391"/>
<source>everything went fine</source>
<translation>Alles verlief gut</translation>
</message>
@@ -4746,39 +4975,39 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DlgExportVector</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="371"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="395"/>
<source>Choose where to save the file</source>
<translation>Dateiname zum Speichern wählen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="372"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="396"/>
<source>Export to file</source>
<translation>In Datei exportieren</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="373"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="397"/>
<source>Output file name is required</source>
<translation>Ausgabedateiname ist erforderlich</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="374"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="398"/>
<source>Invalid source srid: must be an integer</source>
<translation>Ungültige Quell-SRID: Muß eine ganze Zahl sein</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="375"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="399"/>
<source>Invalid target srid: must be an integer</source>
<translation>Ungültige Ziel-SRID: Muß eine ganze Zahl sein</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="376"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="400"/>
<source>Error %d
%s</source>
<translation>Fehler:%d
%s</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="377"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="401"/>
<source>Export finished.</source>
<translation>Export abgeschlossen.</translation>
</message>
@@ -4786,17 +5015,17 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DlgFieldProperties</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="381"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="405"/>
<source>DB Manager</source>
<translation>DB-Verwaltung</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="382"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="406"/>
<source>field name must not be empty</source>
<translation>Feldname darf nicht leer sein</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="383"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="407"/>
<source>field type must not be empty</source>
<translation>Feldtyp darf nicht leer sein</translation>
</message>
@@ -4805,7 +5034,7 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgFixedTable</name>
<message>
<location filename="../python/plugins/processing/ui/DlgFixedTable.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="703"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="718"/>
<source>Fixed table</source>
<translation>Feste Tabelle</translation>
</message>
@@ -4814,7 +5043,7 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgGetScriptsAndModels</name>
<message>
<location filename="../python/plugins/processing/ui/DlgGetScriptsAndModels.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="707"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="722"/>
<source>Get scripts and models</source>
<translation>Skripte und Modelle laden</translation>
</message>
@@ -4823,19 +5052,19 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgHelpEdition</name>
<message>
<location filename="../python/plugins/processing/ui/DlgHelpEdition.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="711"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="726"/>
<source>Help editor</source>
<translation>Hilfeeditor</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgHelpEdition.ui" line="43"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="712"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="727"/>
<source>Select element to edit</source>
<translation>Element zur Bearbeitung wählen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgHelpEdition.ui" line="78"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="713"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="728"/>
<source>Element description</source>
<translation>Elementbeschreibung</translation>
</message>
@@ -4844,7 +5073,7 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgHistory</name>
<message>
<location filename="../python/plugins/processing/ui/DlgHistory.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="717"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="732"/>
<source>History</source>
<translation>Historie</translation>
</message>
@@ -4852,44 +5081,44 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DlgImportVector</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="387"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="411"/>
<source>Choose the file to import</source>
<translation>Zu importierende Datei wählen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="388"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="412"/>
<source>Import to database</source>
<translation>In Datenbank importieren</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="389"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="413"/>
<source>Input layer missing or not valid</source>
<translation>Eingabelayer fehlt oder ist ungültig</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="390"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="414"/>
<source>Output table name is required</source>
<translation>Ausgabetabellenname ist erforderlich</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="391"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="415"/>
<source>Invalid source srid: must be an integer</source>
<translation>Ungültige Quell-SRID: Muß eine ganze Zahl sein</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="392"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="416"/>
<source>Invalid target srid: must be an integer</source>
<translation>Ungültige Ziel-SRID: Muß eine ganze Zahl sein</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="393"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="417"/>
<source>Error %d
%s</source>
<translation>Fehler:%d
%s</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="394"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="418"/>
<source>Import was successful.</source>
<translation>Import war erfolgreich.</translation>
</message>
@@ -4898,13 +5127,13 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgModeler</name>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="721"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="736"/>
<source>Processing modeler</source>
<translation>Verarbeitungsmodellierung</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="34"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="722"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="737"/>
<source>Open model</source>
<translation>Modell öffnen</translation>
</message>
@@ -4916,97 +5145,97 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="105"/>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="125"/>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="145"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="723"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="738"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="50"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="725"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="740"/>
<source>Save</source>
<translation>Speichern</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="66"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="727"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="742"/>
<source>Save as...</source>
<translation>Speichern als...</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="89"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="729"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="744"/>
<source>Export as image</source>
<translation>Speichern als Rasterbild</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="102"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="730"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="745"/>
<source>Export as Python script</source>
<translation>Exportiere als Python-Skript</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="122"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="731"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="746"/>
<source>Edit model help</source>
<translation>Modellhilfe bearbeiten</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="142"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="732"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="747"/>
<source>Run model</source>
<translation>Modell ausführen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="190"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="734"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="749"/>
<source>Inputs</source>
<translation>Eingaben</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="218"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="735"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="750"/>
<source>Algorithms</source>
<translation>Algorithmen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="230"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="736"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="751"/>
<source>Enter algorithm name to filter list</source>
<translation>Algorithmenname eingeben, um Liste zu filtern</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="260"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="737"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="752"/>
<source>Enter model name here</source>
<translation>Modellname hier eingeben</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="267"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="738"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="753"/>
<source>Enter group name here</source>
<translation>Gruppenname eingeben</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="40"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="724"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="739"/>
<source>Ctrl+O</source>
<translation>Strg+O</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="56"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="726"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="741"/>
<source>Ctrl+S</source>
<translation>Strg+S</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="72"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="728"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="743"/>
<source>Ctrl+Shift+S</source>
<translation>Strg+Umschalt+S</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgModeler.ui" line="148"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="733"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="748"/>
<source>F5</source>
<translation>F5</translation>
</message>
@@ -5015,7 +5244,7 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgMultipleSelection</name>
<message>
<location filename="../python/plugins/processing/ui/DlgMultipleSelection.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="742"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="757"/>
<source>Multiple selection</source>
<translation>Mehrfachauswahl</translation>
</message>
@@ -5024,19 +5253,19 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgNumberInput</name>
<message>
<location filename="../python/plugins/processing/ui/DlgNumberInput.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="746"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="761"/>
<source>Enter number or expression</source>
<translation>Zahl oder Ausdruck eingeben</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgNumberInput.ui" line="26"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="747"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="762"/>
<source><html><head/><body><p>Enter expression in the text field. Double click on elements in the tree to add their values to the expression.</p></body></html></source>
<translation><html><head/><body><p>Einen Ausdruck in das Textfeld eingeben. Auf Baumelemente doppelklicken, um deren Wert dem Ausdruck hinzuzufügen.</p></body></html></translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgNumberInput.ui" line="36"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="748"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="763"/>
<source><html><head/><body><p><span style=" font-weight:600;">Warning</span>: if expression result is float value, but integer required, result will be rounded to integer.</p></body></html></source>
<translation><html><head/><body><p><span style=" font-weight:600;">Warnung</span>: wenn der Ausdruck eine Fließkommazahl ist, aber eine ganze Zahl gefordert ist, wird das Ergebnis auf eine ganze Zahl gerundet.</p></body></html></translation>
</message>
@@ -5045,19 +5274,19 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgRenderingStyles</name>
<message>
<location filename="../python/plugins/processing/ui/DlgRenderingStyles.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="752"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="767"/>
<source>Dialog</source>
<translation>Dialog</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgRenderingStyles.ui" line="30"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="753"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="768"/>
<source>Output</source>
<translation>Ausgabe</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgRenderingStyles.ui" line="35"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="754"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="769"/>
<source>Style</source>
<translation>Stil</translation>
</message>
@@ -5066,7 +5295,7 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgResults</name>
<message>
<location filename="../python/plugins/processing/ui/DlgResults.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="758"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="773"/>
<source>Results</source>
<translation>Ergebnisse</translation>
</message>
@@ -5075,13 +5304,13 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgScriptEditor</name>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="762"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="777"/>
<source>Script editor</source>
<translation>Skript-Editor</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="56"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="766"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="781"/>
<source>Save</source>
<translation>Speichern</translation>
</message>
@@ -5097,145 +5326,163 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="196"/>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="212"/>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="232"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="764"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="779"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="72"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="768"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="783"/>
<source>Save as...</source>
<translation>Speichern als...</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="95"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="770"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="785"/>
<source>Edit script help</source>
<translation>Skripthilfe bearbeiten</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="115"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="771"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="786"/>
<source>Run algorithm</source>
<translation>Algorithmus ausführen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="138"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="773"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="788"/>
<source>Cut</source>
<translation>Ausschneiden</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="154"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="775"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="790"/>
<source>Copy</source>
<translation>Kopieren</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="170"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="777"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="792"/>
<source>Paste</source>
<translation>Einfügen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="193"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="779"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="794"/>
<source>Undo</source>
<translation>Zurücknehmen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="209"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="781"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="796"/>
<source>Redo</source>
<translation>Wiederholen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="40"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="763"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="778"/>
<source>Open script</source>
<translation>Skript öffnen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="46"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="765"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="780"/>
<source>Ctrl+O, Return</source>
<translation>Strg+O, Eingabe</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="62"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="767"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="782"/>
<source>Ctrl+S</source>
<translation>Strg+S</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="78"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="769"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="784"/>
<source>Ctrl+Shift+S</source>
<translation>Strg+Umschalt+S</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="121"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="772"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="787"/>
<source>F5</source>
<translation>F5</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="144"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="774"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="789"/>
<source>Ctrl+X</source>
<translation>Strg+X</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="160"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="776"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="791"/>
<source>Ctrl+C</source>
<translation>Strg+C</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="176"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="778"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="793"/>
<source>Ctrl+V</source>
<translation>Strg+V</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="199"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="780"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="795"/>
<source>Ctrl+Z</source>
<translation>Strg+Z</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="215"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="782"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="797"/>
<source>Ctrl+Shift+Z</source>
<translation>Strg+Umschalt+Z</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="249"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="783"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="798"/>
<source>A+</source>
<translation>A+</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/DlgScriptEditor.ui" line="259"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="784"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="799"/>
<source>A-</source>
<translation>A-</translation>
</message>
</context>
<context>
+ <name>DlgSqlLayerWindow</name>
+ <message>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="422"/>
+ <source>Column(s) with unique values</source>
+ <translation>Spalte(n) mit eindeutigen Werten</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="423"/>
+ <source>Column with unique values</source>
+ <translation>Spalte mit eindeutigen Werten</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="424"/>
+ <source>%d rows, %.1f seconds</source>
+ <translation>%d Zeilen, %.1f Sekunden</translation>
+ </message>
+</context>
+<context>
<name>DlgSqlWindow</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="398"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="428"/>
<source>Column(s) with unique values</source>
<translation>Spalte(n) mit eindeutigen Werten</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="399"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="429"/>
<source>Column with unique values</source>
<translation>Spalte mit eindeutigen Werten</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="400"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="430"/>
<source>%d rows, %.1f seconds</source>
<translation>%d Zeilen, %.1f Sekunden</translation>
</message>
@@ -5243,52 +5490,52 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DlgTableProperties</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="404"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="434"/>
<source>DB Manager</source>
<translation>DB-Verwaltung</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="405"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="435"/>
<source>nothing selected</source>
<translation>Nichts gewählt</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="406"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="436"/>
<source>Are you sure</source>
<translation>Sind Sie sicher</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="407"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="437"/>
<source>really delete column '%s'?</source>
<translation>Die Spalte %s wirklich löschen?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="408"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="438"/>
<source>really delete constraint '%s'?</source>
<translation>Die Beschränkung %s wirklich löschen?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="409"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="439"/>
<source>The selected table has no geometry</source>
<translation>Die gewählte Tabelle hat keine Geometrie</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="410"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="440"/>
<source>Create?</source>
<translation>Erzeugen?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="411"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="441"/>
<source>Create spatial index for field %s?</source>
<translation>Räumlichen Index für Feld %s anlegen?</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="412"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="442"/>
<source>Nothing selected</source>
<translation>Nichts gewählt</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="413"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="443"/>
<source>really delete index '%s'?</source>
<translation>Den Index %s wirklich löschen?</translation>
</message>
@@ -5297,79 +5544,79 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>DlgVersioning</name>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="14"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="417"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="447"/>
<source>Add versioning support to a table</source>
<translation>Versionierungsunterstützung zur Tabelle hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="22"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="418"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="448"/>
<source>Table is expected to be empty, with a primary key.</source>
<translation>Leere Tabelle mit einem Primärschlüssel erwartet.</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="31"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="419"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="449"/>
<source>Schema</source>
<translation>Schema</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="44"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="420"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="450"/>
<source>Table</source>
<translation>Tabelle</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="75"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="421"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="451"/>
<source>create a view with current content (<TABLE>_current)</source>
<translation>eine Sicht mit dem aktuellen Inhalt erzeugen (<TABELLE>_current)</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="85"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="422"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="452"/>
<source>New columns</source>
<translation>Neue Spalten</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="91"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="423"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="453"/>
<source>Prim. key</source>
<translation>Prim.Schl</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="101"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="424"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="454"/>
<source>id_hist</source>
<translation>id_hist</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="108"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="425"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="455"/>
<source>Start time</source>
<translation>Startzeit</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="118"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="426"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="456"/>
<source>time_start</source>
<translation>time_start</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="125"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="427"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="457"/>
<source>End time</source>
<translation>Endzeit</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="135"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="428"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="458"/>
<source>time_end</source>
<translation>time_end</translation>
</message>
<message>
<location filename="../python/plugins/db_manager/db_plugins/postgis/plugins/versioning/DlgVersioning.ui" line="160"/>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="429"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="459"/>
<source>SQL to be executed:</source>
<translation>Auszuführendes SQL:</translation>
</message>
@@ -5377,67 +5624,67 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DropAnalysis</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="788"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="803"/>
<source>Stream Drop Analysis</source>
<translation>Gewässergefälleanalyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="789"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="804"/>
<source>Stream Network Analysis tools</source>
<translation>Stromnetzwerkanalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="790"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="805"/>
<source>D8 Contributing Area Grid</source>
<translation>D8 beitragende Fläche Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="791"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="806"/>
<source>D8 Flow Direction Grid</source>
<translation>D8 Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="792"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="807"/>
<source>Pit Filled Elevation Grid</source>
<translation>Höhengitter mit gefüllten Löchern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="793"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="808"/>
<source>Accumulated Stream Source Grid</source>
<translation>Kumuliertes Fluss Quellennetz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="794"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="809"/>
<source>Outlets Shapefile</source>
<translation>Auslaß-Shapedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="795"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="810"/>
<source>Minimum Threshold</source>
<translation>Minimum Schwellenwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="796"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="811"/>
<source>Maximum Threshold</source>
<translation>Maximum Schwellenwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="797"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="812"/>
<source>Number of Threshold Values</source>
<translation>Anzahl der Schwellenwerte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="798"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="813"/>
<source>Spacing for Threshold Values</source>
<translation>Abstand für Schwellenwerte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="799"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="814"/>
<source>D-Infinity Drop to Stream Grid</source>
<translation>D-Infinity Sende and Strom Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="800"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="815"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -5445,67 +5692,67 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>DropAnalysisMulti</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="804"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="819"/>
<source>Stream Drop Analysis (multifile)</source>
<translation>Gewässergefälleanalyse (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="805"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="820"/>
<source>Stream Network Analysis tools</source>
<translation>Stromnetzwerkanalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="806"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="821"/>
<source>D8 Contributing Area Grid</source>
<translation>D8 beitragende Fläche Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="807"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="822"/>
<source>D8 Flow Direction Grid</source>
<translation>D8 Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="808"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="823"/>
<source>Pit Filled Elevation Grid</source>
<translation>Höhengitter mit gefüllten Löchern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="809"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="824"/>
<source>Accumulated Stream Source Grid</source>
<translation>Kumuliertes Fluss Quellennetz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="810"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="825"/>
<source>Outlets Shapefile</source>
<translation>Auslaß-Shapedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="811"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="826"/>
<source>Minimum Threshold</source>
<translation>Minimum Schwellenwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="812"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="827"/>
<source>Maximum Threshold</source>
<translation>Maximum Schwellenwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="813"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="828"/>
<source>Number of Threshold Values</source>
<translation>Anzahl der Schwellenwerte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="814"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="829"/>
<source>Spacing for Threshold Values</source>
<translation>Abstand für Schwellenwerte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="815"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="830"/>
<source>D-Infinity Drop to Stream Grid</source>
<translation>D-Infinity Sende and Strom Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="816"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="831"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -5513,7 +5760,7 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>EditModelAction</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="820"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="835"/>
<source>Edit model</source>
<translation>Editiere Modell</translation>
</message>
@@ -5521,7 +5768,7 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>EditScriptAction</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="824"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="839"/>
<source>Edit script</source>
<translation>Editiere Skript</translation>
</message>
@@ -5547,112 +5794,112 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>Eliminate</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="829"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="844"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="830"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="845"/>
<source>Largest area</source>
<translation>Größte Fläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="831"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="846"/>
<source>Smallest Area</source>
<translation>Kleinste Fläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="832"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="847"/>
<source>Largest common boundary</source>
<translation>Größte gemeinsame Grenze</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="833"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="848"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="834"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="849"/>
<source>Use current selection in input layer (works only if called from toolbox)</source>
<translation>Aktuelle Auswahl des Eingabelayers verwenden (funktionert nur aus Werkzeugkasten heraus)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="835"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="850"/>
<source>Selection attribute</source>
<translation>Auswahlattribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="836"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="851"/>
<source>Comparison</source>
<translation>Vergleich</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="837"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="852"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="838"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="853"/>
<source>Merge selection with the neighbouring polygon with the</source>
<translation>Vereinige Auswahl mit dem Nachbarpolygon mit den</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="839"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="854"/>
<source>Cleaned</source>
<translation>Bereinigt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="840"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="855"/>
<source>Cannot convert "%s" to integer</source>
<translation>Kann "%s" nicht in Integer umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="841"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="856"/>
<source>Cannot convert "%s" to float</source>
<translation>Kann "%s" nicht in float umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="842"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="857"/>
<source>Cannot convert "%s" to unicode</source>
<translation>Kann "%s" nicht in unicode umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="843"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="858"/>
<source>Cannot convert "%s" to date with system date format %s</source>
<translation>Kann "%s" nicht in Datum mit Systemdatumsformat %s umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="844"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="859"/>
<source>Cannot convert "%s" to date with format string "%s"</source>
<translation>Kann "%s" nicht in Datum im Format "%s" umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="845"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="860"/>
<source>Enter the date and the date format, e.g. "07.26.2011" "MM.dd.yyyy".</source>
<translation>Bitte Datum und Format eingeben, z.B.: "07.26.2011" "MM.dd.yyyy".</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="846"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="861"/>
<source>"%s" can only be used with string fields</source>
<translation>"%s" kann nur mit Textfeldern verwendet werden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="847"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="862"/>
<source>Error in selection input: %s</source>
<translation>Fehler in der Auswahleingabe: %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="848"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="863"/>
<source>%s: (No selection in input layer "%s")</source>
<translation>%s: (Keine Auswahl in Eingabelayer "%s")</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="849"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="864"/>
<source>Could not replace geometry of feature with id %s</source>
<translation>Konnte Geometrie des Objektes %s nicht ersetzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="828"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="843"/>
<source>Eliminate sliver polygons</source>
<translation>Splitterpolygone beseitigen</translation>
</message>
@@ -5660,27 +5907,27 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>EquivalentNumField</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="853"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="868"/>
<source>Add unique value index field</source>
<translation>Feld mit eindeutigem Klassenindex hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="854"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="869"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="855"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="870"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="856"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="871"/>
<source>Class field</source>
<translation>Klassenfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="857"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="872"/>
<source>Layer with index field</source>
<translation>Layer mit eindeutigem Klassenindex</translation>
</message>
@@ -5688,22 +5935,22 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>ExampleAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="861"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="876"/>
<source>Create copy of layer</source>
<translation>Layerkopie erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="862"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="877"/>
<source>Algorithms for vector layers</source>
<translation>Algorithmen für Vektorlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="863"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="878"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="864"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="879"/>
<source>Output layer with selected features</source>
<translation>Eingabelayer mit gewählten Objekten</translation>
</message>
@@ -5711,62 +5958,62 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>ExecuteSQL</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="868"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="883"/>
<source>Execute SQL</source>
<translation>SQL-Anweisung ausführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="869"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="884"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="870"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="885"/>
<source>Additional input datasources (called input1, .., inputN in the query)</source>
<translation>Zusätzliche Eingabedatenquellen (in der Abfrage input1, .., inputN genannt)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="871"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="886"/>
<source>SQL query</source>
<translation>SQL-Abfrage</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="872"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="887"/>
<source>Unique identifier field</source>
<translation>Eindeutiges Schlüsselfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="873"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="888"/>
<source>Geometry field</source>
<translation>Geometriefeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="874"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="889"/>
<source>Autodetect</source>
<translation>Automatisch feststellen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="875"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="890"/>
<source>No geometry</source>
<translation>Keine Geometrie</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="876"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="891"/>
<source>Geometry type</source>
<translation>Geometrietyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="877"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="892"/>
<source>CRS</source>
<translation>KBS</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="878"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="893"/>
<source>Output</source>
<translation>Ausgabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="879"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="894"/>
<source>Empty SQL. Please enter valid SQL expression and try again.</source>
<translation>Leerer SQL-Ausdruck. Bitte einen gültigen SQL-Ausdruck eingeben und wiederholen.</translation>
</message>
@@ -5774,22 +6021,22 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>Explode</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="884"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="899"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="885"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="900"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="886"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="901"/>
<source>Exploded</source>
<translation>Explodiert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="883"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="898"/>
<source>Explode lines</source>
<translation>Linien sprengen</translation>
</message>
@@ -5797,42 +6044,42 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>ExportGeometryInfo</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="891"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="906"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="892"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="907"/>
<source>Layer CRS</source>
<translation>Layer-KBS</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="893"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="908"/>
<source>Project CRS</source>
<translation>Projekt-KBS</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="894"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="909"/>
<source>Ellipsoidal</source>
<translation>Ellipsenförmig</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="895"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="910"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="896"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="911"/>
<source>Calculate using</source>
<translation>Berechnen mit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="897"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="912"/>
<source>Added geom info</source>
<translation>Geometrieinfo ergänzt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="890"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="905"/>
<source>Export/Add geometry columns</source>
<translation>Geometriespalte exportieren/hinzufügen</translation>
</message>
@@ -5840,27 +6087,27 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>ExtentFromLayer</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="902"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="917"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="903"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="918"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="904"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="919"/>
<source>Calculate extent for each feature separately</source>
<translation>Abmessung für jedes Objekt einzeln berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="905"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="920"/>
<source>Extent</source>
<translation>Umfang</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="901"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="916"/>
<source>Polygon from layer extent</source>
<translation>Polygon aus Layergrenzen</translation>
</message>
@@ -5868,42 +6115,42 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>ExtentSelectionPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="909"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="924"/>
<source>[Leave blank to use min covering extent]</source>
<translation>[Freilassen, um min Abdeckungsumfang zu nutzen]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="910"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="925"/>
<source>Use layer/canvas extent</source>
<translation>Benutze Layer/Leinwand Ausdehnung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="911"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="926"/>
<source>Select extent on canvas</source>
<translation>Wähle Ausdehnung auf Leinwand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="912"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="927"/>
<source>Use min covering extent from input layers</source>
<translation>Benutze minimale Abdeckungsausmasse von Eingangslayern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="913"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="928"/>
<source>Select extent</source>
<translation>Ausdehnung wählen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="914"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="929"/>
<source>Use extent from</source>
<translation>Ausdehnung verwenden aus</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="915"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="930"/>
<source>Warning</source>
<translation>Warnung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="916"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="931"/>
<source>The projection of the chosen layer is not the same as canvas projection! The selected extent might not be what was intended.</source>
<translation>Die Projekt des gewählten Layers entspricht nicht der Kartenprojektion! Die gewählten Grenzen könnte nicht die beabsichtigten sein.</translation>
</message>
@@ -5911,57 +6158,57 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>ExtractByAttribute</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="921"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="936"/>
<source>Vector selection tools</source>
<translation>Vektorauswahlwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="922"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="937"/>
<source>begins with</source>
<translation>Beginnt mit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="923"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="938"/>
<source>contains</source>
<translation>enthält</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="924"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="939"/>
<source>Input Layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="925"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="940"/>
<source>Selection attribute</source>
<translation>Auswahlattribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="926"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="941"/>
<source>Operator</source>
<translation>Operator</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="927"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="942"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="928"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="943"/>
<source>Extracted (attribute)</source>
<translation>Extrahiert (Attribut)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="929"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="944"/>
<source>Operators %s can be used only with string fields.</source>
<translation>Operatoren %s könnte nur in Textfeldern verwendet werden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="930"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="945"/>
<source>Unsupported field type "%s"</source>
<translation>Nicht unterstützter Feldtyp "%s"</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="920"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="935"/>
<source>Extract by attribute</source>
<translation>Nach Attribut extrahieren</translation>
</message>
@@ -5969,37 +6216,37 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>ExtractByLocation</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="936"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="951"/>
<source>Layer to select from</source>
<translation>Auswählen von Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="937"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="952"/>
<source>Additional layer (intersection layer)</source>
<translation>Zusätzliche Layer (Schnittlayer)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="939"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="954"/>
<source>Precision</source>
<translation>Genauigkeit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="940"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="955"/>
<source>Extracted (location)</source>
<translation>Extrahiert (Position)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="934"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="949"/>
<source>Extract by location</source>
<translation>Nach Position extrahieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="935"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="950"/>
<source>Vector selection tools</source>
<translation>Vektorauswahlwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="938"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="953"/>
<source>Geometric predicate</source>
<translation>Geometrisches Prädikat</translation>
</message>
@@ -6007,22 +6254,22 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>ExtractNodes</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="945"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="960"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="946"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="961"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="947"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="962"/>
<source>Nodes</source>
<translation>Knoten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="944"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="959"/>
<source>Extract nodes</source>
<translation>Knoten extrahieren</translation>
</message>
@@ -6030,22 +6277,22 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>ExtractProjection</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="952"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="967"/>
<source>[GDAL] Projections</source>
<translation>[GDAL] Projektionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="953"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="968"/>
<source>Input file</source>
<translation>Eingabedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="954"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="969"/>
<source>Create also .prj file</source>
<translation>Auch .prj-Datei erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="951"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="966"/>
<source>Extract projection</source>
<translation>Projektion extrahieren</translation>
</message>
@@ -6054,144 +6301,144 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<name>FieldsCalculator</name>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="958"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="973"/>
<source>Field calculator</source>
<translation>Feldrechner</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="26"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="959"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="974"/>
<source>Create a new field</source>
<translation>Neues Feld anlegen</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="59"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="960"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="975"/>
<source>Output field name</source>
<translation>Ausgabefeldname</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="72"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="961"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="976"/>
<source>Output field type</source>
<translation>Ausgabefeldtyp</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="85"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="962"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="977"/>
<source>Output field width</source>
<translation>Ausgabefeldbreite</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="95"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="963"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="978"/>
<source>Width of complete output. For example 123,456 means 6 as field width.</source>
<translation>Breite der kompletten Ausgabe. Zum Beispiel bedeutet 123,456 eine Feldbreite von 6.</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="108"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="964"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="979"/>
<source>Precision</source>
<translation>Genauigkeit</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="146"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="965"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="980"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="165"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="966"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="981"/>
<source>Update existing field</source>
<translation>Vorhandenes Feld erneuern</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="195"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="967"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="982"/>
<source>Output file</source>
<translation>Ausgabedatei</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/DlgFieldsCalculator.ui" line="205"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="968"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="983"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="969"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="984"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="970"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="985"/>
<source>Float</source>
<translation>Fließkommazahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="971"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="986"/>
<source>Integer</source>
<translation>Ganze Zahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="972"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="987"/>
<source>String</source>
<translation>Zeichenkette</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="973"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="988"/>
<source>Date</source>
<translation>Datum</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="974"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="989"/>
<source>Result field name</source>
<translation>Ergebnisfeldname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="975"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="990"/>
<source>Field type</source>
<translation>Feldtyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="976"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="991"/>
<source>Field length</source>
<translation>Feldlänge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="977"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="992"/>
<source>Field precision</source>
<translation>Feldgenauigkeit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="978"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="993"/>
<source>Create new field</source>
<translation>Neues Feld erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="979"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="994"/>
<source>Formula</source>
<translation>Formel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="980"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="995"/>
<source>Calculated</source>
<translation>Berechnet</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="981"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="996"/>
<source>Evaluation error: %s</source>
<translation>Auswertungsfehler: %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="982"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="997"/>
<source>An error occurred while evaluating the calculation string:
%s</source>
<translation>Ein Fehler trat bei der Auswertung der Formel auf:
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="983"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="998"/>
<source>Field name is not set. Please enter a field name</source>
<translation>Feldname ist nicht gesetzt. Bitte Feldname eingeben</translation>
</message>
@@ -6199,17 +6446,17 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>FieldsCalculatorDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="987"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1002"/>
<source>[Save to temporary file]</source>
<translation>[In Temporärdatei speichern]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="988"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1003"/>
<source>Save file</source>
<translation>Datei speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="989"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1004"/>
<source>Unable to execute algorithm</source>
<translation>Konnte Anweisung nicht ausführen</translation>
</message>
@@ -6217,44 +6464,44 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>FieldsMapper</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="994"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1009"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="995"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1010"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="996"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1011"/>
<source>Fields mapping</source>
<translation>Feldabbildung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="997"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1012"/>
<source>Refactored</source>
<translation>Faktoriert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="998"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1013"/>
<source>Parser error in expression "{}": {}</source>
<translation>Fehler in Ausdruck "{}": {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="999"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1014"/>
<source>Evaluation error in expression "{}": {}</source>
<translation>Auswertungsfehler bei Ausdruck "{}": {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1000"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1015"/>
<source>An error occurred while evaluating the calculation string:
</source>
<translation>Ein Fehler trat auf bei der Auswertung von:
</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="993"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1008"/>
<source>Refactor fields</source>
<translation>Felder überarbeiten</translation>
</message>
@@ -6262,67 +6509,67 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>FieldsPyculator</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1005"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1020"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1006"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1021"/>
<source>Integer</source>
<translation>Ganze Zahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1007"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1022"/>
<source>Float</source>
<translation>Fließkommazahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1008"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1023"/>
<source>String</source>
<translation>Zeichenkette</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1009"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1024"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1010"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1025"/>
<source>Result field name</source>
<translation>Ergebnisfeldname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1011"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1026"/>
<source>Field type</source>
<translation>Feldtyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1012"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1027"/>
<source>Field length</source>
<translation>Feldlänge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1013"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1028"/>
<source>Field precision</source>
<translation>Feldgenauigkeit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1014"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1029"/>
<source>Global expression</source>
<translation>Globaler Ausdruck</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1015"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1030"/>
<source>Formula</source>
<translation>Formel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1016"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1031"/>
<source>Calculated</source>
<translation>Berechnet</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1017"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1032"/>
<source>FieldPyculator code execute error.Global code block can't be executed!
%s
%s</source>
@@ -6331,7 +6578,7 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1018"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1033"/>
<source>FieldPyculator code execute error.Field code block can't be executed!
%s
%s</source>
@@ -6340,14 +6587,14 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1019"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1034"/>
<source>FieldPyculator code execute error
Field code block does not return '%s1' variable! Please declare this variable in your code!</source>
<translation>FieldPyculator-Code Ausführungsfehler
Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren sie diese Variable im Code!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1004"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1019"/>
<source>Advanced Python field calculator</source>
<translation>Erweiterter Python-Feldrechner</translation>
</message>
@@ -6355,22 +6602,22 @@ Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren
<context>
<name>FileDirectorySelector</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1023"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1038"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1024"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1039"/>
<source>Select directory</source>
<translation>Verzeichnis wählen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1025"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1040"/>
<source>Select file</source>
<translation>Datei wählen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1026"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1041"/>
<source>All files (*.*)</source>
<translation>Alle Dateien (*.*)</translation>
</message>
@@ -6378,12 +6625,12 @@ Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren
<context>
<name>FileSelectionPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1030"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1045"/>
<source>Select folder</source>
<translation>Wähle Ordner</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1031"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1046"/>
<source>Select file</source>
<translation>Datei wählen</translation>
</message>
@@ -6391,32 +6638,32 @@ Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren
<context>
<name>FilterData</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1035"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1050"/>
<source>Filter Data outliers</source>
<translation>Datenausreißer filtern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1036"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1051"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1037"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1052"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1038"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1053"/>
<source>Standard Deviation multiplier</source>
<translation>Standardabweichungsfaktor</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1039"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1054"/>
<source>Window size</source>
<translation>Fenstergröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1040"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1055"/>
<source>Output filtered LAS file</source>
<translation>Gefilterte LAS-Ausgabedatei</translation>
</message>
@@ -6424,27 +6671,27 @@ Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren
<context>
<name>FirstLastReturn</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1044"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1059"/>
<source>First&Last Return</source>
<translation>Erste&letzte Rückgabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1045"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1060"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1046"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1061"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1047"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1062"/>
<source>Use LAS info</source>
<translation>LAS-Info verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1048"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1063"/>
<source>Output layers</source>
<translation>Ausgabelayer</translation>
</message>
@@ -6452,37 +6699,37 @@ Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren
<context>
<name>FixedDistanceBuffer</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1053"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1068"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1054"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1069"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1055"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1070"/>
<source>Distance</source>
<translation>Entfernung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1056"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1071"/>
<source>Segments</source>
<translation>Segmente</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1057"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1072"/>
<source>Dissolve result</source>
<translation>Ergebnis auflösen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1058"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1073"/>
<source>Buffer</source>
<translation>Puffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1052"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1067"/>
<source>Fixed distance buffer</source>
<translation>Puffer festen Abstands</translation>
</message>
@@ -6490,17 +6737,17 @@ Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren
<context>
<name>FixedTableDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1062"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1077"/>
<source>Add row</source>
<translation>Zeile hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1063"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1078"/>
<source>Remove row(s)</source>
<translation>Zeile(n) entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1064"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1079"/>
<source>Remove all</source>
<translation>Alle entfernen</translation>
</message>
@@ -6508,7 +6755,7 @@ Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren
<context>
<name>FixedTablePanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1068"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1083"/>
<source>Fixed table %dx%d</source>
<translation>Fixe Tabelle %dx%d</translation>
</message>
@@ -6523,7 +6770,7 @@ Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren
<location filename="../python/plugins/processing/ui/widgetNumberSelector.ui" line="14"/>
<location filename="../python/plugins/processing/ui/widgetParametersPanel.ui" line="14"/>
<location filename="../python/plugins/processing/ui/widgetRangeSelector.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1086"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1101"/>
<source>Form</source>
<translation>Formular</translation>
</message>
@@ -6537,199 +6784,199 @@ Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren
<location filename="../python/plugins/processing/ui/widgetLayerSelector.ui" line="42"/>
<location filename="../python/plugins/processing/ui/widgetLayerSelector.ui" line="58"/>
<location filename="../python/plugins/processing/ui/widgetNumberSelector.ui" line="42"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1088"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1103"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetBatchPanel.ui" line="39"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1100"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1115"/>
<source>Toggle advanced mode</source>
<translation>Erweiteter Modus umgeschaltet</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetBatchPanel.ui" line="26"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1099"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1114"/>
<source>Add row</source>
<translation>Zeile hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetBatchPanel.ui" line="55"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1101"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1116"/>
<source>Remove row(s)</source>
<translation>Zeile(n) entfernen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetBatchPanel.ui" line="100"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1102"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1117"/>
<source>Open</source>
<translation>Öffnen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetBatchPanel.ui" line="113"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1103"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1118"/>
<source>Save</source>
<translation>Speichern</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetLayerSelector.ui" line="55"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1105"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1120"/>
<source>Iterate over this layer</source>
<translation>Iteriere über diesen Layer</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetNumberSelector.ui" line="39"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1087"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1102"/>
<source>Open number input dialog</source>
<translation>Zahleneingabedialog öffnen</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetParametersPanel.ui" line="44"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1104"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1119"/>
<source>Advanced parameters</source>
<translation>Fortgeschrittene Parameter</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetRangeSelector.ui" line="26"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1097"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1112"/>
<source>Min</source>
<translation>Min</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetRangeSelector.ui" line="65"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1098"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1113"/>
<source>Max</source>
<translation>Max</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="20"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1072"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1087"/>
<source>Fields</source>
<translation>Felder</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="43"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1073"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1088"/>
<source>Add new field</source>
<translation>Neues Feld hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="46"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1074"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1089"/>
<source>add</source>
<translation>hinzufügen</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="53"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1075"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1090"/>
<source>Delete selected field</source>
<translation>Gewähltes Feld löschen</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="56"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1076"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1091"/>
<source>delete</source>
<translation>löschen</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="63"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1077"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1092"/>
<source>Move selected field up</source>
<translation>Gewähltes Feld nach oben</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="66"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1078"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1093"/>
<source>up</source>
<translation>oben</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="73"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1079"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1094"/>
<source>Move selected field down</source>
<translation>Gewähltes Feld nach unten</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="76"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1080"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1095"/>
<source>down</source>
<translation>unten</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="83"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1081"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1096"/>
<source>Reset all fields</source>
<translation>Alle Felder zurücksetzen</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="86"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1082"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1097"/>
<source>reset</source>
<translation>zurücksetzen</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="112"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1083"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1098"/>
<source>Load fields from layer</source>
<translation>Felder aus Layer laden</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="135"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1084"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1099"/>
<source>Load fields from selected layer</source>
<translation>Felder des gewählten Layers laden</translation>
</message>
<message>
<location filename="../python/plugins/processing/algs/qgis/ui/widgetFieldsMapping.ui" line="138"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1085"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1100"/>
<source>Load fields</source>
<translation>Felder laden</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetGeometryPredicateSelector.ui" line="23"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1089"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1104"/>
<source>equals</source>
<translation>entspricht</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetGeometryPredicateSelector.ui" line="30"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1090"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1105"/>
<source>contains</source>
<translation>enthält</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetGeometryPredicateSelector.ui" line="37"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1091"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1106"/>
<source>touches</source>
<translation>berührt</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetGeometryPredicateSelector.ui" line="44"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1092"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1107"/>
<source>intersects</source>
<translation>schneidet sich mit</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetGeometryPredicateSelector.ui" line="51"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1093"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1108"/>
<source>within</source>
<translation>innerhalb</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetGeometryPredicateSelector.ui" line="58"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1094"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1109"/>
<source>overlaps</source>
<translation>überlappt</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetGeometryPredicateSelector.ui" line="65"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1095"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1110"/>
<source>crosses</source>
<translation>kreuzt</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/widgetGeometryPredicateSelector.ui" line="72"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1096"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1111"/>
<source>disjoint</source>
<translation>getrennt</translation>
</message>
@@ -6737,14 +6984,14 @@ Feldcodeblock gibt nicht die '%s1' Variable zurück! Bitte deklarieren
<context>
<name>FusionAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1109"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1124"/>
<source>Fusion folder is not configured.
Please configure it before running Fusion algorithms.</source>
<translation>Fusion Verzeichnis ist nicht konfiguriert.
Bitte konfigurieren bevor Algorithmen daraus verwendet werden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1110"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1125"/>
<source>Additional modifiers</source>
<translation>Zusätzliche Einstellungen</translation>
</message>
@@ -6752,7 +6999,7 @@ Bitte konfigurieren bevor Algorithmen daraus verwendet werden.</translation>
<context>
<name>FusionUtils</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1114"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1129"/>
<source>Fusion execution console output</source>
<translation>Konsolenausgabe der Fusion-Ausführung</translation>
</message>
@@ -6760,7 +7007,7 @@ Bitte konfigurieren bevor Algorithmen daraus verwendet werden.</translation>
<context>
<name>GdalAlgorithmDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1118"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1133"/>
<source>Run as batch process...</source>
<translation>Als Batchprozeß starten...</translation>
</message>
@@ -6768,7 +7015,7 @@ Bitte konfigurieren bevor Algorithmen daraus verwendet werden.</translation>
<context>
<name>GdalOgrAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1122"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1137"/>
<source>GDAL/OGR</source>
<translation>GDAL/OGR</translation>
</message>
@@ -6776,17 +7023,17 @@ Bitte konfigurieren bevor Algorithmen daraus verwendet werden.</translation>
<context>
<name>GdalParametersPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1126"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1141"/>
<source>GDAL/OGR console call</source>
<translation>GDAL/OGR Aufruf</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1127"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1142"/>
<source>[temporary file]</source>
<translation>[temporäre Datei]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1128"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1143"/>
<source>Invalid value for parameter '%s'</source>
<translation>Ungültiger Wert für Parameter '%s'</translation>
</message>
@@ -8871,18 +9118,18 @@ Der 'Grau'-wert (aus GDAL 1.7) ermöglicht Datensätze mit einer Farbt
<context>
<name>GeoAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1132"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1147"/>
<source>Uncaught error while executing algorithm</source>
<translation>Nicht erfasste Fehler bei der Ausführung von Algorithmus</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1133"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1148"/>
<source>
See log for more details</source>
<translation>Die Logdatei enthält mehr Details</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1134"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1149"/>
<source>Converting outputs</source>
<translation>Konvertierung der Ausgabe</translation>
</message>
@@ -8890,57 +9137,57 @@ See log for more details</source>
<context>
<name>GeometryConvert</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1139"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1154"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1140"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1155"/>
<source>Centroids</source>
<translation>Zentroide</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1141"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1156"/>
<source>Nodes</source>
<translation>Knoten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1142"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1157"/>
<source>Linestrings</source>
<translation>Linien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1143"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1158"/>
<source>Multilinestrings</source>
<translation>Multilinien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1144"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1159"/>
<source>Polygons</source>
<translation>Polygone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1145"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1160"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1146"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1161"/>
<source>New geometry type</source>
<translation>Neuer Geometrietyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1147"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1162"/>
<source>Converted</source>
<translation>Umgewandelt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1148"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1163"/>
<source>Cannot convert from %s to %s</source>
<translation>Kann %s nicht in %s umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1138"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1153"/>
<source>Convert geometry type</source>
<translation>Geometrietyp umwandeln</translation>
</message>
@@ -8961,62 +9208,62 @@ See log for more details</source>
<context>
<name>GetScriptsAndModelsDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1154"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1169"/>
<source>Could not connect to scripts/models repository</source>
<translation>Keine Verbindung zum Skript-/Modellrepositorium</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1155"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1170"/>
<source>Network error code: {} on URL: {}</source>
<translation>Netzwerkfehlercode {} bei URL: {}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1156"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1171"/>
<source>Processing</source>
<translation>Verarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1157"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1172"/>
<source>Installed</source>
<translation>Installiert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1158"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1173"/>
<source>Updatable</source>
<translation>Aktualisierbar</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1159"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1174"/>
<source>Not installed</source>
<translation>Nicht installiert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1161"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1176"/>
<source><p><b>Description:</b> %s</p></source>
<translation><p><b>Beschreibung:</b>%s</p></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1162"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1177"/>
<source><p><b>Created by:</b> %s</source>
<translation><p><b>Erstellt von:</b>%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1163"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1178"/>
<source><p><b>Version:</b> %s</source>
<translation><p><b>Version:</b> %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1160"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1175"/>
<source><h2>No detailed description available for this script</h2></source>
<translation><h2>Keine detaillierte Beschreibung für dieses Skript verfügbar</h2></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1153"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1168"/>
<source>Connection problem</source>
<translation>Verbindungsproblem</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1152"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1167"/>
<source><h3> Processing resources manager </h3><p>Check/uncheck algorithms in the tree to select the ones that you want to install or remove</p><p>Algorithms are divided in 3 groups:</p><ul><li><b>Installed:</b> Algorithms already in your system, with the latest version available</li><li><b>Updatable:</b> Algorithms already in your system, but with a newer version available in the server</li> [...]
<translation><h3> Verwaltung der Verarbeitungsmittel</h3><p>Bitte Algorithmen im Baum wählen, die installiert oder entfernt werden sollen</p><p>Algorithmen sind in 3 Gruppen aufgeteilt:</p><ul><li><b>Installierte:</b> Algorithmen, die sich bereits in der letzten verfügbaren Version im System befinden</li><li><b>Aktualisierbare:</b> Algorithmen, die sich bereits auf dem System befinden, aber in akt [...]
</message>
@@ -9030,7 +9277,7 @@ See log for more details</source>
</message>
<message>
<location filename="../src/plugins/globe/globe_plugin.cpp" line="272"/>
- <location filename="../src/plugins/globe/globe_plugin.cpp" line="1091"/>
+ <location filename="../src/plugins/globe/globe_plugin.cpp" line="1093"/>
<source>&Globe</source>
<translation>&Globus</translation>
</message>
@@ -9038,29 +9285,29 @@ See log for more details</source>
<context>
<name>Grass7Algorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1167"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1182"/>
<source>Could not open GRASS GIS 7 algorithm: %s
%s</source>
<translation>Kann GRASS GIS 7-Algorithmus nicht öffnen: %s
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1168"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1183"/>
<source>GRASS GIS 7 region extent</source>
<translation>GRASS GIS 7-Regionsgrenzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1169"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1184"/>
<source>GRASS GIS 7 region cellsize (leave 0 for default)</source>
<translation>GRASS-Regionenzellengröße (0 für um Voreinstellung beizubehalten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1170"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1185"/>
<source>GRASS GIS 7 folder is not configured. Please configure it before running GRASS GIS 7 algorithms.</source>
<translation>GRASS GIS 7-Verzeichnis ist nicht konfiguriert. Bitte vor Ausführung von GRASS GIS 7-Algorithmen konfigurieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1171"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1186"/>
<source>GRASS GIS 7 execution commands</source>
<translation>GRASS GIS 7-Befehlsausführung</translation>
</message>
@@ -9068,34 +9315,34 @@ See log for more details</source>
<context>
<name>Grass7AlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1175"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1190"/>
<source>GRASS7 folder</source>
<translation>GRASS7-Verzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1176"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1191"/>
<source>Log execution commands</source>
<translation>Befehlsausführung protokollieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1177"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1192"/>
<source>Log console output</source>
<translation>Konsolenausgabe protokollieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1178"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1193"/>
<source>Could not open GRASS GIS 7 algorithm: %s</source>
<translation>Konnte GRASS7-Algorithmus nicht öffnen: %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1179"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1194"/>
<source>Could not open GRASS GIS 7 algorithm: %s
%s</source>
<translation>Kann GRASS GIS 7-Algorithmus nicht öffnen: %s
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1180"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1195"/>
<source>GRASS GIS 7 commands</source>
<translation>GRASS GIS 7-Befehle</translation>
</message>
@@ -9103,17 +9350,17 @@ See log for more details</source>
<context>
<name>Grass7Utils</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1184"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1199"/>
<source>GRASS GIS 7 execution console output</source>
<translation>Konsolenausgabe der GRASS GIS 7-Ausführung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1185"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1200"/>
<source>GRASS GIS 7 folder is not configured. Please configure it before running GRASS GIS 7 algorithms.</source>
<translation>GRASS GIS 7-Verzeichnis ist nicht konfiguriert. Bitte vor Ausführung von GRASS GIS 7-Algorithmen konfigurieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1186"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1201"/>
<source>The specified GRASS 7 folder "{}" does not contain a valid set of GRASS 7 modules.
Please, go to the Processing settings dialog, and check that the GRASS 7
folder is correctly configured</source>
@@ -9122,14 +9369,14 @@ Bitte im Processing-Einstellungsdialog überprüfen, dass das GRASS GIS 7-Verzei
richtig konfiguriert ist</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1187"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1202"/>
<source>It seems that GRASS GIS 7 is not correctly installed and configured in your system.
Please install it before running GRASS GIS 7 algorithms.</source>
<translation>GRASS GIS 7 ist anscheinend nicht richtig auf dem System installiert und konfiguriert.
Bitte vor der Ausführung von GRASS GIS 7-Algorithmen installieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1188"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1203"/>
<source>Error while checking GRASS GIS 7 installation. GRASS GIS 7 might not be correctly configured.
</source>
<translation>Fehler bei der Überprüfung der GRASS GIS 7-Installation. GRASS GIS 7 könnte nicht richtig konfiguriert sein.
@@ -9139,1771 +9386,1771 @@ Bitte vor der Ausführung von GRASS GIS 7-Algorithmen installieren.</translation
<context>
<name>GrassAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1192"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1207"/>
<source>Could not open GRASS algorithm: %s.
%s</source>
<translation>Konnte GRASS-Algorithums nicht öffen: %s.
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1193"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1208"/>
<source>GRASS region extent</source>
<translation>GRASS-Regionengrenzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1194"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1209"/>
<source>GRASS region cellsize (leave 0 for default)</source>
<translation>GRASS-Regionenzellengröße (0 für um Voreinstellung beizubehalten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1195"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1210"/>
<source>GRASS folder is not configured.
Please configure it before running GRASS algorithms.</source>
<translation>GRASS-Verzeichnis nicht konfiguriert.
Bitte vor der Ausführung von GRASS-Algorithmen konfigurieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1196"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1211"/>
<source>GRASS execution commands</source>
<translation>GRASS-Befehlsausführung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="185"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="454"/>
<source>v.surf.rst.line - Spatial approximation and topographic analysis using regularized spline with tension.</source>
<translation>v.surf.rst.line - Räumliche Approximation und topographische Analyse mit einer regularisierten Spline-Funktion mit Spannung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="254"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="481"/>
<source>v.clean.advanced - Toolset for cleaning topology of vector map (Advanced).</source>
<translation>v.clean.advanced - Werkzeugsatz für die Bereinigung der Topologie einer Vektorkarte (Fortgeschritten).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="300"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="417"/>
<source>r.slope - Generates raster maps of slope from a elevation raster map.</source>
<translation>r.slope - Erzeugt Rasterkarten mit Hangneigung aus einer Rasterkarte mit Höheninformationen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="134"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="564"/>
<source>r.contour.step - Create vector contours from raster at specified steps</source>
<translation>r.contour.step - Erstellen von Vektorkonturen von Rasterdaten an bestimmten Stufen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="242"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="643"/>
<source>v.buffer.distance - Creates a buffer around features of given type.</source>
<translation>v.buffer.distance - Erzeugt einen Puffer um Objekte mit gegebenen Typ.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="306"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="523"/>
<source>v.surf.bspline.lambda - Bicubic or bilinear spline interpolation with Tykhonov regularization.</source>
<translation>v.surf.bspline.lambda - Bikubische oder bi-lineare Spline-Interpolation mit Tichonow-Regularisierung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="97"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="491"/>
<source>r.cost.full - Creates a raster layer of cumulative cost of moving across a raster layer whose cell values represent cost.</source>
<translation>r.cost.full - Raster aus der kommulierten Kosten für die Bewegung über ein Raster erzeugen, dessen Zellen Kosten repräsentieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="240"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="312"/>
<source>r.lake.coords - Fills lake at given point to given level.</source>
<translation>r.lake.coords - See aus Quellenpunkt einer gegebenen Höhe füllen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="308"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="521"/>
<source>v.to.rast.value - Converts (rasterize) a vector layer into a raster layer.</source>
<translation>v.to.rast.value - Konvertiert (rastert) eine Vektorkarte in eine Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="135"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="385"/>
<source>v.distance.toattr - Finds the nearest element in vector map 'to' for elements in vector map 'from'.</source>
<translation>v.distance.toattr - Findet das nächstgelegene Element der Vektorkarte 'to' für Elemente in der Vektorkarte 'from'.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="272"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="441"/>
<source>r.aspect - Generates raster maps of aspect from a elevation raster map.</source>
<translation>r.slope.apect - Erzeugt Rasterkarten mit Exposition aus einer Rasterkarte mit Höheninformationen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="289"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="571"/>
<source>v.split.length - Split lines to shorter segments by length.</source>
<translation>v.split.length - Trenne Linien zu kürzeren Segmenten nach Länge.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="175"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="365"/>
<source>r.reclass.area.greater - Reclassifies a raster layer, selecting areas larger than a user specified size</source>
<translation>r.reclass.area.greater -Reklassifiziere Rasterkarte durch Auswahl von Flächen größer eines gegeben Werts</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="41"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="526"/>
<source>r.horizon.height - Horizon angle computation from a digital elevation model.</source>
<translation>r.horizon.height - Berechnung des Horizontwinkel auf Grundlage eines digitalen Höhenmodells.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="42"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="431"/>
<source>r.sunmask.datetime - Calculates cast shadow areas from sun position and elevation raster map.</source>
<translation>r.sunmask.datetime - Schattenkarten aus Sonnenposition und Rasterkarten mit Höheninformation berechnen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="100"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="405"/>
<source>r.lake.layer - Fills lake at given point to given level.</source>
<translation>r.lake.layer - See aus Quellenpunkt einer gegebenen Höhe füllen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="62"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="634"/>
<source>r.sunmask.position - Calculates cast shadow areas from sun position and elevation raster map.</source>
<translation>r.sunmask.position - Schattenkarten aus Sonnenposition und Rasterkarten mit Höheninformation berechnen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="176"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="455"/>
<source>r.in.lidar.info - Extract information from LAS file</source>
<translation>r.in.lidar.info - Information aus LAS-Datei extrahieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="218"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="467"/>
<source>r.drain.coordinate - Traces a flow through an elevation model on a raster map.</source>
<translation>r.drain.coordinate - Verfolgt einen Fluss durch ein Höhenmodell auf einer Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="235"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="418"/>
<source>v.transform.pointsfile - Performs an affine transformation on a vector layer, using a support point file.</source>
<translation>v.transform.pointsfile - Führt eine affine Transformation von Vektorkarten mit Hilfe einer Punktdatei durch.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="125"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="337"/>
<source>r.cost.full.raster - Creates a raster layer of cumulative cost of moving across a raster layer whose cell values represent cost.</source>
<translation>r.cost.full.raster - Raster aus der kommulierten Kosten für die Bewegung über ein Raster erzeugen, dessen Zellen Kosten repräsentieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="43"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="384"/>
<source>v.buffer.column - Creates a buffer around features of given type.</source>
<translation>v.buffer.column - Erzeugt einen Puffer um Objekte mit gegebenen Typ.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="198"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="493"/>
<source>Performs bilinear or bicubic spline interpolation with Tykhonov regularization.</source>
<translation>Führt bi-lineare oder bi-kubische oder Spline-Interpolation mit Tichonow-Regularisierung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="352"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="474"/>
<source>Outputs raster map layer values lying along user defined transect line(s).</source>
<translation>Gibt Rasterkartenlayerwerte entlang einer oder mehreren benutzerdefinierten Transektlinien aus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="210"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="442"/>
<source>Calculates solar elevation, solar azimuth, and sun hours.</source>
<translation>Berechnet Sonnenhöhe, -winkel und -stunden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="119"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="309"/>
<source>r.li.shape.ascii - Calculates shape index on a raster map </source>
<translation>r.li.shape.ascii - Berechnet Shapeindex auf einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="305"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="323"/>
<source>Calculates patch number index on a raster map, using a 4 neighbour algorithm.</source>
<translation>Berechnet Patch-Anzahl-Index einer Rasterkarte, unter Verwendung eines 4-Nachbarn-Algorithmus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="37"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="480"/>
<source>r.li.renyi.ascii - Calculates Renyi's diversity index on a raster map</source>
<translation>r.li.renyi.ascii - Berechnet Renyi-Diversitäts-Index einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="311"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="425"/>
<source>r.blend.combine - Blends color components of two raster maps by a given ratio and export into a unique raster.</source>
<translation>r.blend.combine - Farbkomponenten zweier Raster einem Verhältnis anpassen und in eine einziges Raster exportieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="344"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="305"/>
<source>Performs contextual image classification using sequential maximum a posteriori (SMAP) estimation.</source>
<translation>Führt eine kontextbezogene Bildklassifizierung mittels sequentieller Maximum-Aposterori-Schätzung (SMAP) durch</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="88"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="550"/>
<source>Generates spectral signatures for land cover types in an image using a clustering algorithm.</source>
<translation>Generiert Spektralsignaturen für Bodenbedeckungstypen in eimem Bild mittels Häufungsalgorithmus</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="140"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="578"/>
<source>i.eb.hsebal01.coords - Computes sensible heat flux iteration SEBAL 01. Inline coordinates</source>
<translation>i.eb.hsebal01.coords - Berechnet Sensible-Heat-Flux-Iteration. Inline-Koordinaten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="49"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="546"/>
<source>v.to.rast.attribute - Converts (rasterize) a vector layer into a raster layer.</source>
<translation>v.to.rast.attribute - Konvertiert (rastert) eine Vektorkarte in eine Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="303"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="403"/>
<source>Computes biomass growth, precursor of crop yield calculation.</source>
<translation>Berechnet Biomassenzuwachs, Vorläufer von Feldfruchtberechnungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="155"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="624"/>
<source>Rectifies an image by computing a coordinate transformation for each pixel in the image based on the control points. </source>
<translation>Berichtigt ein Bild durch die Berecnung der Koordinatentransformation für jedes Pixel des Bildes nach Kontrollpunkten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="219"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="416"/>
<source>Calculates Optimum-Index-Factor table for spectral bands</source>
<translation>Optimale Indexfaktortabelle für Spektralkanäle berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="292"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="645"/>
<source>Computes potential evapotranspiration calculation with hourly Penman-Monteith.</source>
<translation>Berechnet potentielle Evapotranspiration mit stündlichem Penman-Monteith.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="70"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="371"/>
<source>Identifies segments (objects) from imagery data.</source>
<translation>Identifiziert Segmente (Objekte) aus Bilddaten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="316"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="633"/>
<source>Computes topographic correction of reflectance.</source>
<translation>Berechnet topographische Korrektur der Reflektion.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="39"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="606"/>
<source>Computes evapotranspiration calculation Priestley and Taylor formulation, 1972.</source>
<translation>Berechnet Evapotranspiration mit Priestley und Taylor Formulierung, 1972.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="83"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="594"/>
<source>Calculates different types of vegetation indices.</source>
<translation>Berechnet verschiedene Typen von Vegetationsindizes.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="131"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="505"/>
<source>Generates statistics for i.smap from raster map.</source>
<translation>Generiert Statistik für i.smap aus Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="146"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="414"/>
<source>Computes evaporative fraction (Bastiaanssen, 1995) and root zone soil moisture (Makin, Molden and Bastiaanssen, 2001).</source>
<translation>Berechnet evaporative Bruchteil (Bastiaanssen, 1995) und Bodenfeuchtigkeit der Wurzelzone (Makin, Molden und Bastiaanssen, 2001).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="21"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="363"/>
<source>Actual evapotranspiration for diurnal period (Bastiaanssen, 1995). </source>
<translation>Tatsächliche Evapotranspiration für Tagperiode (Bastiaanssen, 1995).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="76"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="487"/>
<source>r.mask.rast - Creates a MASK for limiting raster operation.</source>
<translation>r.mask.rast - Maske (MASK) erzeugen, um Rasteroperationen zu begrenzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="211"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="468"/>
<source>i.topo.coor.ill - Creates illumination model for topographic correction of reflectance.</source>
<translation>i.topo.coor.ill - Erzeugt Beleuchtungsmodel für topographische Reflektionskorrektur.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="69"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="374"/>
<source>Calculates dominance's diversity index on a raster map</source>
<translation>Berechnet Dominanzdiversitätsindex einer Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="133"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="396"/>
<source>r.walk.points - Creates a raster map showing the anisotropic cumulative cost of moving between different geographic locations on an input raster map whose cell category values represent cost from point vector layers.</source>
<translation>r.walk.points - Rasterkarte aus der kommulierten Kosten für die Bewegung zwischen zwei verschiedenen geographischen Orten auf einer Eingaberasterkarte deren Zellen Kategoriewerte Kosten von Punktvektorlayern repräsentieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="51"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="327"/>
<source>Computes broad band albedo from surface reflectance. </source>
<translation>Berechnet Breitbandalbedo aus Oberflächenreflektion.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="17"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="508"/>
<source>Imports SPOT VGT NDVI data into a raster map.</source>
<translation>Importiert SPOT VGT NDVI Daten in Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="277"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="475"/>
<source>Computes sensible heat flux iteration SEBAL 01.</source>
<translation>Berechnet Sensible-Heat-Flux-Iteration SEBAL 01.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="144"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="354"/>
<source>Performs Landsat TM/ETM+ Automatic Cloud Cover Assessment (ACCA).</source>
<translation>Fürhrt TM/ETM+ automatische Wolkendeckenbewertung (ACCA) durch.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="214"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="528"/>
<source>Performs auto-balancing of colors for RGB images.</source>
<translation>Führt automatische Angleichung der Farben von RGB-Bildern durch.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="34"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="515"/>
<source>Computes evapotranspiration calculation modified or original Hargreaves formulation, 2001.</source>
<translation>Berechnet Evapotranspiration mit modifizierter oder originaler Hargreaves-Formulierung, 2001.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="346"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="614"/>
<source>Principal components analysis (PCA) for image processing.</source>
<translation>Hauptbestandteilsanalyes (PCA) zur Bildverarbeitung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="122"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="359"/>
<source>Calculates top-of-atmosphere radiance or reflectance and temperature for Landsat MSS/TM/ETM+/OLI</source>
<translation>Berechnet Abstrahlung der obersten Atmosphäre oder Reflektionen für Landsat MSS/TM/ETM+/OLI</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="55"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="322"/>
<source>Classifies the cell spectral reflectances in imagery data.</source>
<translation>Klassifiziert die Zellenspektralreflektionen in Bilddaten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="136"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="437"/>
<source>Performs Tasseled Cap (Kauth Thomas) transformation.</source>
<translation>Führt Tasseled Cap (Kauth Thomas)-Transformation durch.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="143"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="617"/>
<source>Computes temporal integration of satellite ET actual (ETa) following the daily ET reference (ETo) from meteorological station(s).</source>
<translation>Ermittelt zeitliche Integration der Satelliten-ET tatsächlichen (ETa) folgend der tägliche ET-Referenz (ETo) von meteorologische(r/en) Station(en).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="159"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="435"/>
<source>Net radiation approximation (Bastiaanssen, 1995).</source>
<translation>Nettostrahlungsnährung (Bastiaanssen, 1995).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="276"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="623"/>
<source>Regroup multiple mono-band rasters into a single multiband raster.</source>
<translation>Mehrere einkanalige Raster in ein einzelnes Multibandraster regruppieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="256"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="534"/>
<source>Image fusion algorithms to sharpen multispectral with high-res panchromatic channels</source>
<translation>Bildvereinigungsalgorithmus um multispektrale mit hochauflösenden-panchromatischen Kanälen zu schärfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="203"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="446"/>
<source>Soil heat flux approximation (Bastiaanssen, 1995).</source>
<translation>Bodenwärmestromnährung (Bastiaanssen, 1995).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="81"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="386"/>
<source>Mosaics several images and extends colormap.</source>
<translation>Fügt mehrere Bilder zusammen und erweitert die Farbabbildung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="318"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="630"/>
<source>Calculates Top of Atmosphere Radiance/Reflectance/Brightness Temperature from ASTER DN.</source>
<translation>Berechnet Abstrahlung der obersten Atmosphäre/Reflektionen/Helligkeitstemperatur aus ASTER DN.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="111"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="537"/>
<source>r.li.simpson.ascii - Calculates Simpson's diversity index on a raster map</source>
<translation>Berechnet Simpsons-Diversitäts-Index einer Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="117"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="428"/>
<source>r.stats.quantile.out - Compute category quantiles using two passes and output statistics</source>
<translation>r.stats.quantile.out - Berechne Kategoriequantile in zwei Durchgängen und Ausgabestatistik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="149"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="560"/>
<source>r.li.pielou.ascii - Calculates Pielou's diversity index on a raster map </source>
<translation>r.li.pielou.ascii - Berechnet Pielou-Diversitäts-Index einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="345"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="607"/>
<source>Calculates mean pixel attribute index on a raster map</source>
<translation>Berechnet den Mittelwert der Attribute (Rasterwerte) -Index einer Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="336"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="401"/>
<source>Calculates multiple linear regression from raster maps.</source>
<translation>Berechnet eine lineare Regression von zwei Rasterkarten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="181"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="303"/>
<source>r.topmodel.topidxstats - Builds a TOPMODEL topographic index statistics file.</source>
<translation>r.topmodel.topidxstats - TOPMODEL topografische Indexstatistikdatei erzeugen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="283"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="587"/>
<source>Allows creation and/or modification of raster map layer support files (metadata).</source>
<translation>Erlaubt die Erzeugung und/oder Modifikation von Rasterkartenlayerunterstützungsdateien (Metadaten).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="329"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="449"/>
<source>r.category.out - Exports category values and labels associated with user-specified raster map layers.</source>
<translation>r.category.out - Mit benutzerdefinierten Rasterkartenlayern verbundene Kategoriewerte und Beschriftungen exportieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="7"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="556"/>
<source>Calculates Shannon's diversity index on a raster map</source>
<translation>Berechnet Shannons-Diversitäts-Index einer Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="57"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="391"/>
<source>r.li.edgedensity.ascii - Calculates edge density index on a raster map, using a 4 neighbour algorithm</source>
<translation>r.li.edgedensity.ascii - Berechnet Kantendichteindex auf einer Rasterkarte mit einem 4-Nachbarn-Algorithmus</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="139"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="553"/>
<source>Raster map calculator. </source>
<translation>Rasterkartenrechner.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="9"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="637"/>
<source>r.walk.coords - Creates a raster map showing the anisotropic cumulative cost of moving between different geographic locations on an input raster map whose cell category values represent cost from a list of coordinates.</source>
<translation>r.walk.coords - Rasterkarte aus der kommulierten Kosten für die Bewegung zwischen zwei verschiedenen geographischen Orten auf einer Eingaberasterkarte deren Zellen Kategoriewerte Kosten aus einer Koordinatenliste repräsentieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="108"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="591"/>
<source>r.li.shannon.ascii - Calculates Shannon's diversity index on a raster map</source>
<translation>Berechnet Shannons-Diversitäts-Index einer Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="202"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="555"/>
<source>Calculates patch density index on a raster map, using a 4 neighbour algorithm</source>
<translation>Berechnet Patch-Anzahl-Index einer Rasterkarte, unter Verwendung eines 4-Nachbarn-Algorithmus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="281"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="588"/>
<source>Calculates mean patch size index on a raster map, using a 4 neighbour algorithm</source>
<translation>Berechnet mitteleren Patch-Größen-Index einer Rasterkarte, unter Verwendung eines 4-Nachbarn-Algorithmus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="82"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="635"/>
<source>Calculates standard deviation of patch area a raster map</source>
<translation>Berechnet den Standardabweichen eines Patchbereiches einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="286"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="502"/>
<source>r.what.coords - Queries raster maps on their category values and category labels on a point.</source>
<translation>r.what.coords - Rasterkarten nach Kategoriewerten und Kategoriebeschriftungen eines Punkt abfragen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="296"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="332"/>
<source>Calculates shape index on a raster map </source>
<translation>Berechnet Shapeindex auf einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="298"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="346"/>
<source>Calculates edge density index on a raster map, using a 4 neighbour algorithm</source>
<translation>Berechnet Kantendichteindex auf einer Rasterkarte mit einem 4-Nachbarn-Algorithmus</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="168"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="466"/>
<source>Creates/modifies the color table associated with a raster map.</source>
<translation>Erzeugt/Ändert die einer Rasterkarte zugeordnete Farbtabelle </translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="77"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="419"/>
<source>r.li.padcv.ascii - Calculates coefficient of variation of patch area on a raster map</source>
<translation>r.li.padcv.ascii - Berechnet Variationskoeffizientien eines Patchbereiches einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="224"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="408"/>
<source>Splits a raster map into tiles</source>
<translation>Rasterkarte in Kacheln aufteilen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="78"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="313"/>
<source>Creates a fractal surface of a given fractal dimension.</source>
<translation>Fraktale Oberfläche einer gegeben Fraktaldimension erzeugen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="132"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="389"/>
<source>r.li.mps.ascii - Calculates mean patch size index on a raster map, using a 4 neighbour algorithm</source>
<translation>r.li.mps.ascii - Berechnet mitteleren Patch-Größen-Index einer Rasterkarte, unter Verwendung eines 4-Nachbarn-Algorithmus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="123"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="489"/>
<source>Generates random surface(s) with spatial dependence.</source>
<translation>Erzeugt zufälltige Oberfläche(n) mit räumlicher Abhängigkeit.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="177"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="609"/>
<source>r.what.points - Queries raster maps on their category values and category labels on a layer of points.</source>
<translation>r.what.points - Rasterkarten nach Kategoriewerten und Kategoriebeschriftungen eines Punktlayers abfragen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="137"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="527"/>
<source>v.surf.rst.cvdev.line - Spatial approximation and topographic analysis using regularized spline with tension.</source>
<translation>v.surf.rst.cvdev.line - Räumliche Approximation und topographische Analyse mit einer regularisierten Spline-Funktion mit Spannung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="161"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="394"/>
<source>Creates a raster map layer showing buffer zones surrounding cells that contain non-NULL category values (low-memory alternative).</source>
<translation>Erzeugt eine Rasterkarte mit Pufferzonen um Zellen, die Nicht-NULL-Wert-Kategoriewerte haben (Alternative für wenig Speicher).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="197"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="597"/>
<source>Calculates contrast weighted edge density index on a raster map</source>
<translation>Berechnet den kontrastgewichteten Kantendichteindex einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="340"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="411"/>
<source>Manages category values and labels associated with user-specified raster map layers.</source>
<translation>Verwaltet mit benutzerdefinierten Rasterkartenlayern verbundene Katagoriewerte und -beschriftungen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="285"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="326"/>
<source>Calculates range of patch area size on a raster map</source>
<translation>Berechnet Reichweite einer Patchbereichsgröße auf einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="228"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="308"/>
<source>Calculates richness index on a raster map</source>
<translation>Berechnet den Richness-Index einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="253"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="477"/>
<source>r.stats.quantile.rast - Compute category quantiles using two passes and output rasters.</source>
<translation>r.stats.quantile.rast - Berechne Kategoriequantile in zwei Durchgängen und Ausgaberaster.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="112"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="362"/>
<source>Calculates Pielou's diversity index on a raster map </source>
<translation>Berechnet Pielou-Diversitäts-Index einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="258"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="432"/>
<source>r.blend.rgb - Blends color components of two raster maps by a given ratio and exports into three rasters.</source>
<translation>r.blend.rgb - Paßt Farbkomponeten zwei Rasterkarten nach einem gegebenen Verhältnis an und exportiert sie in drei Raster.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="29"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="485"/>
<source>Calculates coefficient of variation of patch area on a raster map</source>
<translation>Variationskoeffizienten eines Patchbereiches einer Rasterkarte berechnen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="64"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="613"/>
<source>Generates rate of spread raster maps.</source>
<translation>Erzeugt Rasterkarten mit Grad der Streung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="208"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="529"/>
<source>Calculates Simpson's diversity index on a raster map</source>
<translation>Berechnet Simpsons-Diversitäts-Index einer Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="165"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="376"/>
<source>Makes each output cell value an accumulation function of the values assigned to the corresponding cells in the input raster map layers.</source>
<translation>Jede Ausgabezelle zur Akkumulationsfunktion der den korrespondierenden Zellen zugeordneten Werten des Eingaberasterkartenlayers machen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="199"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="439"/>
<source>Computes USLE R factor, Rainfall erosivity index.</source>
<translation>USLE-R-Faktor berechnen. Niederschlagserosionsindex.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="11"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="383"/>
<source>Interpolates raster maps located (temporal or spatial) in between input raster maps at specific sampling positions.</source>
<translation>Interpoliert Rasterkarten die (zeitlich oder räumlich) zwischen zwei Eingaberasterkarten an bestimmten Abtastpositionen liegen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="291"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="377"/>
<source>Imagery (i.*)</source>
<translation>Bildbearbeitung (i.*)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="147"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="499"/>
<source>r.li.cwed.ascii - Calculates contrast weighted edge density index on a raster map</source>
<translation>r.li.cwed.ascii - Berechnet den kontrastgewichteten Kantendichteindex einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="313"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="380"/>
<source>r.mask.vect - Creates a MASK for limiting raster operation with a vector layer.</source>
<translation>r.mask.vect - MASKe zur Begrenzung der Rasteroperation mit einem Vektorlayer erzeugen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="265"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="314"/>
<source>Creates topographic index layer from elevation raster layer</source>
<translation>Erstellt Karte mit topographischem Index auf Basis eines digitalen Höhenmodells</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="160"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="530"/>
<source>Calculates Renyi's diversity index on a raster map</source>
<translation>Berechnet Renyi-Diversitäts-Index einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="50"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="495"/>
<source>Resamples raster map layers using an analytic kernel.</source>
<translation>Erzeugt eine neue Rasterkarte mit einem analytischen Kern.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="216"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="473"/>
<source>Exports the color table associated with a raster map.</source>
<translation>Exportiert die einer Rasterkarte zugeordnete Farbtabelle.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="339"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="584"/>
<source>Queries colors for a raster map layer. </source>
<translation>Fragt Farben einer Rasterkarte ab.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="18"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="402"/>
<source>Splits a raster map into red, green and blue maps.</source>
<translation>Teilt einer Rasterkarte in rote grüne und blaue Karten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="338"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="642"/>
<source>Computes USLE Soil Erodibility Factor (K).</source>
<translation>Berechnet USLE-Bodenerosionsfaktor (K).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="154"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="589"/>
<source>r.li.dominance.ascii - Calculates dominance's diversity index on a raster map</source>
<translation>r.li.dominance.ascii - Berechnet Dominanzdiversitätsindex einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="231"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="413"/>
<source>Locates the closest points between objects in two raster maps.</source>
<translation>Nächste Punkte zwischen Objekten in zwei Rasterkasten bestimmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="225"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="649"/>
<source>r.li.padsd.ascii - Calculates standard deviation of patch area a raster map</source>
<translation>r.li.padsd.ascii - Berechnet den Standardabweichen eines Patchbereiches einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="23"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="483"/>
<source>r.walk.rast - Creates a raster map showing the anisotropic cumulative cost of moving between different geographic locations on an input raster map whose cell category values represent cost from a raster.</source>
<translation>r.walk.rast - Rasterkarte aus der kommulierten Kosten für die Bewegung zwischen zwei verschiedenen geographischen Orten auf einer Eingaberasterkarte deren Zellen Kategoriewerte Kosten aus einer Rasterkarte repräsentieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="284"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="462"/>
<source>r.li.patchnum.ascii - Calculates patch number index on a raster map, using a 4 neighbour algorithm.</source>
<translation>r.li.patchnum.ascii - Berechnet Patch-Anzahl-Index einer Rasterkarte, unter Verwendung eines 4-Nachbarn-Algorithmus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="151"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="612"/>
<source>r.li.patchdensity.ascii - Calculates patch density index on a raster map, using a 4 neighbour algorithm</source>
<translation>r.li.patchdensity.ascii - Berechnet Patch-Anzahl-Index einer Rasterkarte, unter Verwendung eines 4-Nachbarn-Algorithmus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="73"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="561"/>
<source>Numerical calculation program for transient, confined and unconfined solute transport in two dimensions</source>
<translation>Numerisches Berechnungsprogramm für transienten, beschränkten und unbeschränkte Grundwasserfluß in zwei Dimensionen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="8"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="424"/>
<source>Creates a latitude/longitude raster map.</source>
<translation>Erzeugt eine Breiten-/Längengrad-Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="130"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="407"/>
<source>Simulates TOPMODEL which is a physically based hydrologic model.</source>
<translation>Simuliert TOPMODEL (physikbasiertes hydrologisches Modell)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="354"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="543"/>
<source>Simulates elliptically anisotropic spread.</source>
<translation>Simuliert elliptische antisotropische Streung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="16"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="605"/>
<source>Drapes a color raster over an shaded relief or aspect map. </source>
<translation>Drapiert eine Rasterkarte mit Farbwerten über Schummerungs- oder Expositionskarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="182"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="570"/>
<source>Exports GRASS vector map layers to DXF file format.</source>
<translation>GRASS-Vektor in DXF-Datei exportieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="226"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="406"/>
<source>Generates a raster layer with contiguous areas grown by one cell.</source>
<translation>Erzeugt eine Rasterkarte mit kontinuierlich um eine Zelle gewachsenen Flächen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="40"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="353"/>
<source>Converts a raster layer to a PPM image file at the pixel resolution of the currently defined region.</source>
<translation>Wandelt einen Rasterlayer in eine PPM-Bilddatie in der Auflösung der aktuellen Region.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="196"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="445"/>
<source>Generates random cell values with spatial dependence.</source>
<translation>Erzeugt zufällig Zellwerte mit räumlicher Abhängigkeit.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="170"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="378"/>
<source>Compares bit patterns with a raster map.</source>
<translation>Vergleicht Bitmuster mit Rastern.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="54"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="395"/>
<source>Bilinear interpolation utility for raster map layers.</source>
<translation>Bilineare Interpolationswerkzeug für Rasterkarten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="201"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="344"/>
<source>Stream network extraction</source>
<translation>Stromnetzwerkextraktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="278"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="342"/>
<source>Miscellaneous (m.*)</source>
<translation>Verschiedenes (m.*)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="32"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="608"/>
<source>Create a new vector map layer by combining other vector map layers.</source>
<translation>Erzeugt eine neue Vektorkarte durch Kombination anderer Vektorkarten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="33"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="361"/>
<source>Performs an affine transformation on a vector layer.</source>
<translation>Führt eine affine Transformation von Vektorkarten durch.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="263"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="506"/>
<source>Fills no-data areas in a raster layer using v.surf.rst splines interpolation or v.surf.bspline interpolation</source>
<translation>Leerflächen in Raster nach v.surf.rst oder v.surf.bspline Spline-Interpolation füllen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="233"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="304"/>
<source>Reinterpolates using regularized spline with tension and smoothing.</source>
<translation>Reinterpoliert mit RST und Glättung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="31"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="465"/>
<source>Recursively traces the least cost path backwards to cells from which the cumulative cost was determined.</source>
<translation>Das Modul verfolgt den kürzesten Weg rekursiv zurück zu den Zellen, von denen der kumulative Weg bestimmt wurde.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="87"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="409"/>
<source>Creates parallel line to input vector lines.</source>
<translation>Parallele Linien zu Eingabevektorlinien erzeugen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="312"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="520"/>
<source>Recodes categorical raster maps.</source>
<translation>Kodiert kategorische Rasterkarten um.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="174"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="334"/>
<source>Horizon angle computation from a digital elevation model.</source>
<translation>Berechnung des Horizontwinkel auf Grundlage eines digitalen Höhenmodells.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="200"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="341"/>
<source>r.cost.points - Creates a raster layer of cumulative cost of moving across a raster layer whose cell values represent cost.</source>
<translation>r.rast.points - Raster aus der kommulierten Kosten für die Bewegung über ein Raster erzeugen, dessen Zellen Kosten repräsentieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="47"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="400"/>
<source>Exports GRASS raster map to GRIDATB.FOR map file (TOPMODEL)</source>
<translation>GRASS-Vektor in GRIDATB.FOR Kartendatei (TOPMODEL) speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="158"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="484"/>
<source>r.cost.raster - Creates a raster layer of cumulative cost of moving across a raster layer whose cell values represent cost.</source>
<translation>r.cost.raster - Raster aus der kommulierten Kosten für die Bewegung über ein Raster erzeugen, dessen Zellen Kosten repräsentieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="20"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="551"/>
<source>r.cost.coordinates - Creates a raster layer of cumulative cost of moving across a raster layer whose cell values represent cost.</source>
<translation>r.cost.coordinates - Raster aus der kommulierten Kosten für die Bewegung über ein Raster erzeugen, dessen Zellen Kosten repräsentieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="327"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="566"/>
<source>Finds the average of values in a cover raster layer within areas assigned the same category value in a user-specified base layer.</source>
<translation>Findet den Durchschnitt der Werte in einer Überlagerungskarte innerhalb gleicher Kategorien in einer benutzer-angegebenen Ausgangskarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="95"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="370"/>
<source>Indices for quadrat counts of vector point lists.</source>
<translation>Indizes der Quadrat-Zählmethode aus Vektorpunktliste.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="279"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="545"/>
<source>Detects the object's edges from a LIDAR data set.</source>
<translation>Bestimmt die Kanten eines Objekte aus einem LIDAR-Datensatz.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="243"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="412"/>
<source>Thins non-zero cells that denote linear features in a raster layer.</source>
<translation>Dünne nicht-Null-Zellen aus, die Linieneigenschaften bezeichnen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="67"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="430"/>
<source>Import GetFeature from WFS</source>
<translation>Importiert GetFeature eines WFS</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="268"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="367"/>
<source>Produces a raster layer of uniform random deviates whose range can be expressed by the user.</source>
<translation>Erzeugt eine Rasterkarte mit zufälligen Werten einer Gleichverteilung, deren Spanne vom Benutzer angegeben werden kann.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="274"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="479"/>
<source>Produces the quantization file for a floating-point map.</source>
<translation>Quantisierungsdatei zu Fließkommaraster erzeugen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="30"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="554"/>
<source>Creates a GRASS vector layer of a user-defined grid.</source>
<translation>Erzeugt eine GRASS Vektorkarte mit einem benutzerdefinierten Gitternetz.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="342"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="427"/>
<source>Extracts terrain parameters from a DEM.</source>
<translation>Geländeparameter aus DEM extrahieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="110"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="533"/>
<source>Creates a composite raster layer by using one (or more) layer(s) to fill in areas of "no data" in another map layer.</source>
<translation>Erstellt eine Komposit-Karte, indem bekannte Kategorie-Werte einer (oder mehrerer) Rasterkarte(n) in "NO DATA"-Bereiche einer anderen Rasterkarte gefüllt werden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="106"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="602"/>
<source>Raster (r.*)</source>
<translation>Raster (r.*)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="255"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="316"/>
<source>Spatial approximation and topographic analysis using regularized spline with tension.</source>
<translation>Räumliche Approximation und topographische Analyse mit einer regularisierten Spline-Funktion mit Spannung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="350"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="590"/>
<source>Transforms raster maps from RGB (Red-Green-Blue) color space to HIS (Hue-Intensity-Saturation) color space.</source>
<translation>Rastertransformationfunktion für HIS- (Hue-Intensity-Saturation) in RGB-Farbraum (Rot-Grün-Blau).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="113"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="398"/>
<source>Correction of the v.lidar.growing output. It is the last of the three algorithms for LIDAR filtering.</source>
<translation>Korrektur der v.lidar.growing Ausgabe. Das ist der letzte von 3 Algorithmen um LIDAR zu filtern.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="334"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="547"/>
<source>Generates watershed subbasins raster map.</source>
<translation>Erzeugt Rasterkarte mit Wassereinzugsgebieten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="36"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="627"/>
<source>r.flow.aspect - Construction of flowlines, flowpath lengths, and flowaccumulation (contributing areas) from a raster digital elevation model (DEM).</source>
<translation>r.flow.aspect - Erzeugt Hangkurven (flowlines), Fließlängen und Flussdichte (contributing areas) aus einem angegebenen digitalen Höhenmodell (DEM).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="266"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="574"/>
<source>Outputs a covariance/correlation matrix for user-specified raster layer(s).</source>
<translation>Gibt eine Kovarianz/Korrelations-Matrix für (eine) benutzerdefiniert Rasterkarte(n) aus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="171"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="516"/>
<source>Compute quantiles using two passes.</source>
<translation>Berechne Quantile in zwei Durchgängen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="297"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="522"/>
<source>Vector (v.*)</source>
<translation>Vektor (v.*)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="96"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="457"/>
<source>Classifies attribute data, e.g. for thematic mapping.</source>
<translation>Klassifiziert Attributdaten, z.B. für thematische Karten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="269"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="311"/>
<source>Random location perturbations of GRASS vector points</source>
<translation>Zufällige Positionsstörung von GRASS-Vektorpunkten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="261"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="625"/>
<source>Changes vector category values for an existing vector map according to results of SQL queries or a value in attribute table column.</source>
<translation>Ändert die Kategorien einer existierenden Vektorkarte entsprechend den Ergebnissen der SQL-Abfragen oder der Werte einer Spalte der Attributtabelle.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="102"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="619"/>
<source>Reports statistics for raster layers.</source>
<translation>Gibt statistische Werte für eine Rasterkarte aus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="237"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="336"/>
<source>r.relief.scaling - Creates shaded relief from an elevation layer (DEM).</source>
<translation>r.relief.scaling - Erzeugt eine Schummerungskarte aus einem Höhenmodell (DGM).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="314"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="329"/>
<source>Randomly generate a 2D/3D vector points map.</source>
<translation>Zufällige 2D/3D-Vektorpunktkarte erzeugen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="12"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="321"/>
<source>Generates a raster density map from vector point data using a moving kernel or optionally generates a vector density map on a vector network.</source>
<translation>Erzeugt eine Raster-Dichtekarte aus Vektorpunkten unter Verwendung eines gleitenden Kerns. Optional kann eine Vektor-Dichtekarte basierend auf einem Vektornetzwerk erstellt werden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="221"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="604"/>
<source>Resamples raster layers to a coarser grid using aggregation.</source>
<translation>Erzeugt eine neue Rasterkarte gröberer Auflösung mittels Aggregation.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="127"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="557"/>
<source>Indices for quadrant counts of sites lists.</source>
<translation>Indizes der Quadrat-Zählmethode aus Siteliste.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="109"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="573"/>
<source>Calculates category or object oriented statistics.</source>
<translation>Berechnet Kategorie- oder objektorientierte Statistik.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="138"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="628"/>
<source>Create points along input lines</source>
<translation>Punkte entlang von Eingabelinien erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="317"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="447"/>
<source>Computes minimum spanning tree for the network.</source>
<translation>Berechnet den minimalen Spannbaum eines Netzwerks.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="217"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="331"/>
<source>Computes the shortest path between all pairs of nodes in the network</source>
<translation>Berechnet die kürzesten Pfad zwischen allen Knotenpaaren eines Netzwerkes.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="223"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="572"/>
<source>Computes vertex connectivity between two sets of nodes in the network.</source>
<translation>Berechnet die Stützpunktverbindungen zwischen zwei Knotenmengen im Netzwerk.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="66"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="610"/>
<source>Creates Steiner tree for the network and given terminals</source>
<translation>Erzeugt einen Steinerbaum für das Netzwerk und gegebenen Enden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="236"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="647"/>
<source>v.net.report - Reports lines information of a network</source>
<translation>v.net.report - Berichte zu Kanteninformationen eines Netzwerks</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="169"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="366"/>
<source>Performs visibility graph construction.</source>
<translation>Erstellt Sichtbarkeitsgraphen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="183"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="443"/>
<source>Calculate error matrix and kappa parameter for accuracy assessment of classification result.</source>
<translation>Fehlermatrix und Kappa-Parameter für Genauigkeitsbewertung von Klassifikationsergebnissen berechnen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="14"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="451"/>
<source>Flow computation for massive grids.</source>
<translation>Flußberechnung für massive Raster.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="307"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="335"/>
<source>r.aspect - Generates raster maps of aspect from an elevation raster map.</source>
<translation>r.slope.apect - Erzeugt Rasterkarten mit Exposition aus einer Rasterkarte mit Höheninformationen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="103"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="338"/>
<source>Computes emissivity from NDVI, generic method for sparse land. </source>
<translation>Ermittelt Emissivität aus NDVI, generische Methode für karges Land.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="89"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="452"/>
<source>Calculates univariate statistics from the non-null cells of a raster map.</source>
<translation>Eindimensionale Statistik des Nicht-Null-Zellen eines Rasters berechnen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="259"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="399"/>
<source>Surface interpolation from vector point data by Inverse Distance Squared Weighting.</source>
<translation>Oberflächeninterpolation mit auf Vektorpunkten basierender inverser quadratischer Abstandsgewichtung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="319"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="538"/>
<source>Construction of flowlines, flowpath lengths, and flowaccumulation (contributing areas) from a raster digital elevation model (DEM).</source>
<translation>r.flow.aspect - Erzeugt Hangkurven (flowlines), Fließlängen und Flussdichte (contributing areas) aus einem angegebenen digitalen Höhenmodell (DEM).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="164"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="415"/>
<source>A simple utility for converting bearing and distance measurements to coordinates and vice versa. It assumes a cartesian coordinate system</source>
<translation>Ein einfaches Hilfsprogramm, dass Kurs- und Distanzwert in Koordinaten umrechnet und umgekehrt. Es setzt ein kartesisches Koordinatensystem voraus</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="172"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="514"/>
<source>Surface generation.</source>
<translation>Oberflächenerzeugung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="28"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="482"/>
<source>Generates raster layers of slope, aspect, curvatures and partial derivatives from a elevation raster layer.</source>
<translation>Erzeugt Rasterkarten mit Hangneigung, Exposition, Wölbung und partiellen Ableitungen aus einer Rasterkarte mit Höheninformationen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="207"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="356"/>
<source>Simulates elliptically anisotropic spread on a graphics window and generates a raster map of the cumulative time of spread, given raster maps containing the rates of spread (ROS), the ROS directions and the spread origins.</source>
<translation>Simuliert elliptische anisotrophe Ausbreitung in einem Grafikfenster und erzeugt eine Rasterkarte mit der kumulativen Ausbreitungszeit. Als Ausgangskarten dienen die Ausbreitungsgeschwindigkeit, Ausbreitungsrichtung und der Ursprung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="24"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="507"/>
<source>Tests for normality for points.</source>
<translation>Tests der Normalität auf Vektor-Punkten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="22"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="611"/>
<source>Calculates linear regression from two raster layers : y = a + b*x.</source>
<translation>Berechnet lineare Regression zweier Raster: y = a + b*x.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="101"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="580"/>
<source>Finds the mode of values in a cover layer within areas assigned the same category value in a user-specified base layer.</source>
<translation>Findet den Modalwert der Werte einer Bedeckungskarte innerhalb der Flächen mit gleichen Werten in einer benutzerdefinierten Basiskarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="264"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="375"/>
<source>r.flow.barrier - Construction of flowlines, flowpath lengths, and flowaccumulation (contributing areas) from a raster digital elevation model (DEM).</source>
<translation>r.flow.barrier - Erzeugt Hangkurven (flowlines), Fließlängen und Flussdichte (contributing areas) aus einem angegebenen digitalen Höhenmodell (DEM).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="72"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="568"/>
<source>Reports geometry statistics for vectors.</source>
<translation>Gibt statistische Werte für Geometrie der Vektorobjekte aus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="215"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="438"/>
<source>Bicubic or bilinear spline interpolation with Tykhonov regularization.</source>
<translation>Bikubische oder bi-lineare Spline-Interpolation mit Tichonow-Regularisierung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="232"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="579"/>
<source>Watershed basin creation program.</source>
<translation>Wassereinzugsgebietserzeugungsprogramm.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="246"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="593"/>
<source>Resamples raster map to a finer grid using interpolation.</source>
<translation>Erzeugt eine neue Rasterkarte mit feinerer Auflösung mittels Interpolation.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="341"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="639"/>
<source>Generates red, green and blue raster layers combining hue, intensity and saturation (HIS) values from user-specified input raster layers.</source>
<translation>Erzeugt rot, grün und blaue Rasterkarten durch Kombination des Farbtons, der Intensität und Sättigung (HIS) aus Eingabe-Rasterkarten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="107"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="518"/>
<source>Produces tilings of the source projection for use in the destination region and projection.</source>
<translation>Erzeugt Kacheln der Quellprojektion zur Verwendung in der Zielregion und Projektion.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="188"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="541"/>
<source>r.li.richness.ascii - Calculates richness index on a raster map</source>
<translation>r.li.richness.ascii - Berechet Richness-Index einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="234"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="567"/>
<source>r.li.mpa.ascii - Calculates mean pixel attribute index on a raster map</source>
<translation>r.li.mpa.ascii - Ermittelt mittleren Pixelattributindex einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="310"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="315"/>
<source>Sets color rules based on stddev from a raster map's mean value.</source>
<translation>Setzt Farbregeln basierend auf Standardabweichung des Mittelwerts eines Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="187"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="422"/>
<source>Generate images with textural features from a raster map.</source>
<translation>Bilder mit Texteigenschaften einer Rasterkarte erzeugen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="238"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="382"/>
<source>r.li.padrange.ascii - Calculates range of patch area size on a raster map</source>
<translation>r.li.padrange.ascii - Berechnet Reichweite einer Patchbereichsgröße auf einer Rasterkarte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="280"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="426"/>
<source>Creates a Delaunay triangulation from an input vector map containing points or centroids.</source>
<translation>Erzeugt eine Delaunay-Triangulation auf Basis einer Eingabe-Vektorkarte mit Punkten oder Zentroiden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="241"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="317"/>
<source>Generates three, or four raster map layers showing 1) the base (perpendicular) rate of spread (ROS), 2) the maximum (forward) ROS, 3) the direction of the maximum ROS, and optionally 4) the maximum potential spotting distance.</source>
<translation>Erstellt drei oder vier Rasterkarten, die 1) die Basisrate der (rechtwinkligen) Ausbreitungsgeschwindigkeit, 2) die maximale (Vorwärts-) Geschwindigkeit, 3) die Richtung der größten Ausbreitungsgeschwindigkeit und optional 4) die maximale Entdeckungsentfernung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="184"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="347"/>
<source>Resamples a raster map layer to a finer grid using interpolation.</source>
<translation>Erzeugt eine neue Rasterkarte mit feinerer Auflösung mittels Interpolation.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="262"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="434"/>
<source>Generates area statistics for raster layers.</source>
<translation>Erzeugt Flächenstatistiken für Rasterkarten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="270"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="302"/>
<source>Traces a flow through an elevation model on a raster map.</source>
<translation>Verfolge eine Strömung durch ein Höhenmodell auf einer Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="150"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="559"/>
<source>Finds the median of values in a cover layer within areas assigned the same category value in a user-specified base layer.</source>
<translation>Findet den Median der Werte einer Coverkarte innerhalb der Flächen mit gleichen Werten in einer benutzerdefinierten Basiskarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="315"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="450"/>
<source>Produces a convex hull for a given vector map.</source>
<translation>Erzeugt eine konvexe Hülle für eine Vektorkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="126"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="600"/>
<source>r.random.raster - Create random raster</source>
<translation>r.random.raster - Zufälliges Raster erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="124"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="388"/>
<source>Creates points/segments from input vector lines and positions.</source>
<translation>Punkte/Segmente von Eingabevektorlinien und -positionen bilden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="295"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="460"/>
<source>Samples a raster layer at vector point locations.</source>
<translation>Fragt eine Rasterkarte an den Positionen von Vektorpunkten ab.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="209"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="592"/>
<source>Creates a new map layer whose category values are based upon a reclassification of the categories in an existing raster map layer.</source>
<translation>Neue Karte erzeugen, deren Kategoriewerte auf einer Reklassifikation der Kategorien einer existierenden Rasterkarte basieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="84"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="648"/>
<source>Transforms raster maps from HIS (Hue-Intensity-Saturation) color space to RGB (Red-Green-Blue) color space.</source>
<translation>Rastertransformationfunktion für HIS- (Hue-Intensity-Saturation) in RGB-Farbraum (Rot-Grün-Blau).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="194"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="626"/>
<source>Toolset for cleaning topology of vector map.</source>
<translation>Werkzeugsatz für die Bereinigung der Topologie einer Vektorkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="351"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="496"/>
<source>Calculates univariate statistics for attribute. Variance and standard deviation is calculated only for points if specified.</source>
<translation>Berechnet univariate Statistiken für die Attribute. Die Varianz und Standardabweichung wird nur für Punkte berechnet wenn angefragt.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="178"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="503"/>
<source>Zero-crossing "edge detection" raster function for image processing.</source>
<translation>Nulldurchgangskantendetektionsrasterfunktion für die Bildverarbeitung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="326"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="330"/>
<source>Prints vector map attributes</source>
<translation>Gebe Vektorattribute aus</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="145"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="544"/>
<source>r.contour.level - Create vector contour from raster at specified levels</source>
<translation>r.contour.level - Erstellen von Vektorkonturen von Rasterdaten an bestimmten Ebenen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="10"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="410"/>
<source>v.surf.bspline.sparse - Bicubic or bilinear spline interpolation with Tykhonov regularization.</source>
<translation>v.surf.bspline.sparse - Bikubische oder bi-lineare Spline-Interpolation mit Tichonow-Regularisierung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="190"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="423"/>
<source>r.reclass.area.lesser - Reclassifies a raster layer, selecting areas lower than a user specified size</source>
<translation>r.reclass.area.lesser -Reklassifiziere Rasterkarte durch Auswahl von Flächen kleiner eines gegeben Werts</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="206"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="349"/>
<source>v.split.vert - Split lines to shorter segments by max number of vertices.</source>
<translation>v.split.vert - Trenne Linien zu kürzeren Segmenten nach Stützpunktanzahl.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="56"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="558"/>
<source>Performs raster map matrix filter.</source>
<translation>Führt Matrixfilter auf einer Rasterkarte aus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="153"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="421"/>
<source>Prints terse list of category values found in a raster layer.</source>
<translation>Gibt eine kurze Liste der Kategoriewerte einer Rasterkarte aus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="46"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="548"/>
<source>Overlays two vector maps.</source>
<translation>Überlagert zwei Vektorkarten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="65"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="509"/>
<source>Builds polylines from lines or boundaries.</source>
<translation>Polygone aus Linien oder Umgrenzungen bilden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="330"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="328"/>
<source>Creates Linear Reference System</source>
<translation>Erzeugt ein lineares Bezugssystem</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="195"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="583"/>
<source>Imports geonames.org country files into a GRASS vector points map.</source>
<translation>geonames.org-Länderdatei in eine GRASS-Vektorpunktkarte importieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="44"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="562"/>
<source>Converts vector polygons or points to lines.</source>
<translation>Vektorpolygone oder -pnkte in Linien umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="309"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="350"/>
<source>Converts LAS LiDAR point clouds to a GRASS vector map with libLAS.</source>
<translation>LAS-LiDAR-Punktwolken in eine GRASS-Vektorkarte mit libLAS umwandeln.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="85"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="565"/>
<source>Import ASCII x,y[,z] coordinates as a series of lines.</source>
<translation>ASCII-x,y[,z]-Koordinaten als Linienreihe importieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="320"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="631"/>
<source>Creates points/segments from input lines, linear reference system and positions read from stdin or a file.</source>
<translation>Erzeugt Punkte/Segmente aus Eingabevektorlinien, linearem Bezugssystem und Eingabepositionen aus Standardeingabe oder Datei.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="275"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="372"/>
<source>v.kernel.vector - Generates a vector density map from vector points on a vector network.</source>
<translation>v.kernel.vector - Erzeugt eine Vektordichtekarte aus Vektorpunkten in einem Vektornetzwerk.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="271"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="472"/>
<source>Rectifies a vector by computing a coordinate transformation for each object in the vector based on the control points.</source>
<translation>Berichtigt ein Bild durch die Berechnung der Koordinatentransformation für jedes Objekt im Vektor mittels Kontrollpunkten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="59"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="563"/>
<source>v.kernel.rast - Generates a raster density map from vector points map.</source>
<translation>v.kernel.rast - Erzeugt eine Rasterdichtekarte aus einer Vektorpunktkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="80"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="448"/>
<source>Change the type of geometry elements.</source>
<translation>Typ der Geometrieelemente ändern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="45"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="539"/>
<source>Finds line id and real km+offset for given points in vector map using linear reference system. </source>
<translation>Findet Linienkennung und echten km+Versatz für gegebene Punkte in Vektorkarten mit linearem Referenzsystem.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="93"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="513"/>
<source>v.in.ascii.points - Creates a vector map from an ASCII points file.</source>
<translation>v.in.ascii.points - Erzeugt eine Vektorkarte aus ASCII-Punktdatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="94"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="549"/>
<source>Imports Mapgen or Matlab-ASCII vector maps into GRASS.</source>
<translation>MapGen- oder MatLab-Vektor in GRASS importieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="249"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="433"/>
<source>Exports a vector map as GRASS GIS specific archive file.</source>
<translation>Exportiert eine Vektorkarte als GRASS GIS spezifische Archivdatei.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="252"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="510"/>
<source>Removes outliers from vector point data.</source>
<translation>Entfernt Ausreißer aus einem Punkt-Vektordatensatz.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="324"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="646"/>
<source>Edits a vector map, allows adding, deleting and modifying selected vector features.</source>
<translation>Bearbeitet eine Vektorkarte, erlaubt hinzufügen, löschen und Änderunge von gewählten Vektorobjekten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="74"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="461"/>
<source>Calculate new raster map from a r.mapcalc expression.</source>
<translation>Berechne eine neue Rasterkarte mit einem r.mapcalc-Ausdruck.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="348"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="420"/>
<source>Converts a vector map to VTK ASCII output.</source>
<translation>Wandelt eine Vektorkarte in VTK ASCII um.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="92"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="456"/>
<source>Extrudes flat vector object to 3D with defined height.</source>
<translation>Flaches Vektorobjekt mit definierter Höhe in 3D extrudieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="27"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="525"/>
<source>v.in.ascii.standard - Creates a vector map from an ASCII vector file. </source>
<translation>v.in.ascii.standard - Erzeugt eine Vektorkarte aus einer ASCII Vektordatei. </translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="353"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="552"/>
<source>Performs transformation of 2D vector features to 3D.</source>
<translation>Führt Transformation von 2D-Vektorobjekten zu 3D durch.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="212"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="640"/>
<source>v.build.check - Checks for topological errors.</source>
<translation>v.build.check - Überprüft auf topologische Fehler.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="48"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="494"/>
<source>Creates a raster map from LAS LiDAR points using univariate statistics.</source>
<translation>Erzeugt Rasterkarte aus LAS-LiDAR-Punkten über univariante Statistik.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="13"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="492"/>
<source>Calculates univariate statistics from a raster map based on vector polygons and uploads statistics to new attribute columns.</source>
<translation>Univariante Statistik aus Rasterkarte über Vektorpolygone berechnen und Statistik in neuen Attributspalten ablegen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="248"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="340"/>
<source>Count points in areas and calculate statistics.</source>
<translation>Ermittle Anzahl der Punkte in Bereichen und berechne Statistik.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="118"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="436"/>
<source>Line-of-sight raster analysis program.</source>
<translation>Sichtachsen-Rasteranalysemodul.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="347"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="306"/>
<source>Uploads vector values at positions of vector points to the table.</source>
<translation>Lade Vektorwerte an den Positionen von Vektorpunkten in die Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="19"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="469"/>
<source>Selects vector objects from a vector layer a new layer containing only the selected objects.</source>
<translation>Selektiert Vektorobjekte einer existierenden Vektorkarte und erzeugt eine neue Karte nur mit den selektierten Objekten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="245"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="638"/>
<source>Surface area estimation for rasters.</source>
<translation>Oberflächensschätzungen für Raster.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="35"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="351"/>
<source>Combines red, green and blue raster maps into a single composite raster map.</source>
<translation>Kombiniert rote, grüne und blaue Rasterkarten zu einer zusammengesetzten Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="166"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="621"/>
<source>Converts a raster into a vector layer.</source>
<translation>Raster in Vektorlayer umwandeln.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="205"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="390"/>
<source>Creates a cross product of the category values from multiple raster map layers.</source>
<translation>Kreuzprodukt der Kategoriewerte mehrerer Raster erzeugen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="290"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="577"/>
<source>v.generalize.displacement - Vector based displacement generalization.</source>
<translation>v.generalize.displacement - Vektorbasierte Versatzgeneralisierung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="60"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="585"/>
<source>Converts vector map to 3D by sampling of elevation raster map.</source>
<translation>Wandelt Vektorkarte in 3D durch Abtastung einer Rasterhöhenkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="156"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="478"/>
<source>r.slope - Generates raster maps of slope from an elevation raster map.</source>
<translation>r.slope - Erzeugt Rasterkarten mit Hangneigung aus einer Rasterkarte mit Höheninformationen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="293"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="387"/>
<source>Fills no-data areas in raster maps using spline interpolation.</source>
<translation>Füllt Bereiche mit Leerdaten in Rasterkarten mit Spline-Interpolation.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="323"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="598"/>
<source>Visualization and animation tool for GRASS data.</source>
<translation>Visualisierungs- und Animationswerkzeug für GRASS-Daten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="52"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="629"/>
<source>Construction of slope curves (flowlines), flowpath lengths, and flowline densities (upslope areas) from a raster digital elevation model (DEM).</source>
<translation>Erzeugt Hangkurven (flowlines), Fließlängen und Flussdichte (upslope areas) aus einem angegebenen digitalen Höhenmodell (DEM).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="163"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="381"/>
<source>v.generalize.simplify - Vector based simplification generalization.</source>
<translation>v.generalize.simplify - Vektorbasierte Versatzgeneralisierung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="180"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="512"/>
<source>v.generalize.smooth - Vector based smooth generalization.</source>
<translation>v.generalize.smooth - Vektorbasierte Versatzgeneralisierung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="321"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="333"/>
<source>v.generalize.network - Vector based network generalization.</source>
<translation>v.generalize.network - Vektorbasierte Versatzgeneralisierung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="142"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="358"/>
<source>Canonical components analysis (CCA) program for image processing.</source>
<translation>Kanonische Komponentenanalyseprogramm (CCA) für Bildverarbeitung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="332"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="397"/>
<source>Extracts quality control parameters from MODIS QC layers.</source>
<translation>Extrahiert dies Qualitätskontrollparameter eines MODIS-QC-Layers.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="325"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="596"/>
<source>Generates statistics for i.maxlik from raster map.</source>
<translation>Generiert Statistik für i.maxlik aus Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="75"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="324"/>
<source>Computes the maximum flow between two sets of nodes in the network.</source>
<translation>Berechnet den maximalen Fluß zwischen zwei Knotenmengen im Netzwerk</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="299"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="307"/>
<source>v.net.nodes - Creates points for each network arcs</source>
<translation>v.net.nodes - Erzeugt Punkte für jeden Netzwerkbogen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="162"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="517"/>
<source>v.net.nreport - Reports nodes information of a network</source>
<translation>v.net.nreport - Berichte zu Knoteninformationen eines Netzwerks</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="335"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="486"/>
<source>Creates raster plane layer given dip (inclination), aspect (azimuth) and one point.</source>
<translation>Erzeugt eine Rasterkarte mit einer Ebene mit gegebener Neigung (inclination), Ausrichtung (azimuth) und einem Punkt.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="120"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="586"/>
<source>Computes bridges in the network.</source>
<translation>Berechnet Brücken im Netzwerk</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="79"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="488"/>
<source>Splits network by cost isolines.</source>
<translation>Schnitt durch Netzwerk entlang veranschlagten Isolinien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="129"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="498"/>
<source>Output basic information about a raster layer.</source>
<translation>Gibt grundlegende Informationen über eine Rasterkarte aus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="114"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="569"/>
<source>Dissolves boundaries between adjacent areas sharing a common category number or attribute.</source>
<translation>Löst die Grenzen zwischen anliegenden Gebieten auf die eine gemeinsame Kategorie-Nummer oder Attribut haben.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="222"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="392"/>
<source>Allocates subnets for nearest centers (direction from center)</source>
<translation>Bestimmt Teilnetze für nächste Zentren (vom Zentrum gerichtet)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="68"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="355"/>
<source>Computes shortest distance via the network between the given sets of features.</source>
<translation>Berechnet die kürzesten Abstand zwischen zwei gegebenen Objektmengen im Netzwerk</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="273"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="325"/>
<source>v.net.arcs - Creates arcs from a file of points</source>
<translation>v.net.arcs - Berechnet Bögen aus einer Punktdatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="116"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="463"/>
<source>Finds the nearest element in vector map 'to' for elements in vector map 'from'.</source>
<translation>Findet das nächstgelegene Element der Vektorkarte 'to' für Elemente in der Vektorkarte 'from'.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="61"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="581"/>
<source>Computes strongly and weakly connected components in the network.</source>
<translation>Berechnet stark und schwach verbundene Komponenten eines Netzwerks</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="86"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="429"/>
<source>v.net.articulation - Computes articulation points in the network</source>
<translation>v.net.articulation - Berechnet Artikulationspunkte im Netzwerk</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="302"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="320"/>
<source>Computes degree, centrality, betweeness, closeness and eigenvector centrality measures in the network.</source>
<translation>Berechnet Degree, Centrality, Betweeness, Closeness und Eigenvektor centrality Werte im Netzwerk.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="294"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="576"/>
<source>v.net.connect - Connects points to nearest arcs in a network</source>
<translation>v.net.connect - Verbinde Punkte zu nächsten Bögen in einem Netzwerk</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="220"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="519"/>
<source>Creates a cycle connecting given nodes (Traveling salesman problem)</source>
<translation>Erzeugt eine Rundtour zu gegebenen Punkten (Travelling Salesman)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="250"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="373"/>
<source>Finds shortest path on vector network</source>
<translation>Kürzesten Weg in einem Vektornetzwerk finden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="282"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="444"/>
<source>Creates a raster map layer showing buffer zones surrounding cells that contain non-NULL category values.</source>
<translation>Erzeugt eine Rasterkarte mit Pufferzonen um Zellen, die keine NULL-Wert-Kategorien haben.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="115"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="504"/>
<source>Filters and generates a depressionless elevation layer and a flow direction layer from a given elevation raster layer.</source>
<translation>Depressionsloses Höhenmodell filtern und generieren und eine Fließrichtungskarte auf Basis eines gegebenen Höhenmodells.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="38"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="369"/>
<source>GRASS raster map layer data resampling capability using nearest neighbors.</source>
<translation>GRASS-Rasterlayerdatenneuabtastungsfunktion nach nächstem Nachbarn.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="26"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="582"/>
<source>Creates shaded relief from an elevation layer (DEM).</source>
<translation>Erzeugt eine Schummerungskarte aus einem Höhenmodell (DGM).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="213"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="615"/>
<source>Rescales histogram equalized the range of category values in a raster layer.</source>
<translation>Reskaliert mit Histogrammnormalisierung die Kategoriewerte einer Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="98"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="575"/>
<source>Manages NULL-values of given raster map.</source>
<translation>NULL-Werte eine gegebenen Rasterkarte behandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="343"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="470"/>
<source>Makes each cell category value a function of the category values assigned to the cells around it</source>
<translation>Jede Ausgabezelle zur Funktion der korrespondierenden Zellen des Eingaberasters machen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="193"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="458"/>
<source>Sediment transport and erosion/deposition simulation using path sampling method (SIMWE).</source>
<translation>Sedimenttransport und Erosions/Depositions Simulation unter Verwendung der "path sampling" Methode (SIMWE).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="157"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="318"/>
<source>v.what.rast.points - Uploads raster values at positions of vector points to the table.</source>
<translation>v.what.rast.points - Läd Rasterwerte an gegebenen Position von Vektorpunkten in eine Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="227"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="497"/>
<source>Generates a raster layer of distance to features in input layer.</source>
<translation>Raster aus Objektabständen in Eingabelayer erzeugen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="90"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="345"/>
<source>Sums up the raster cell values.</source>
<translation>Summiert die Rasterzellenwerte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="331"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="595"/>
<source>Raster map matrix filter.</source>
<translation>Rasterkartenmatrixfilter.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="15"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="601"/>
<source>Outputs a raster layer showing the anisotropic cumulative cost of moving based on friction cost.</source>
<translation>Erzeugt eine Rasterkarte, die die anisotrophen kumulierten Kosten der Bewegung auf Basis der Reibungskosten zeigt.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="287"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="524"/>
<source>Tabulates the mutual occurrence (coincidence) of categories for two raster map layers.</source>
<translation>Tabelliere gemeinsames Auftreten (Koinzidenz) der Klassen für zwei Rasterlayer.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="328"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="616"/>
<source>Watershed basin analysis program.</source>
<translation>Wassereinzugsgebietsanalyseprogramm.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="239"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="404"/>
<source>Creates a raster layer of Gaussian deviates.</source>
<translation>Erzeugt eine Raster von Gauss'schen Ableitungen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="63"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="501"/>
<source>v.what.rast.centroids - Uploads raster values at positions of vector centroids to the table.</source>
<translation>v.what.rast.centroids - Lade Rasterwerte an den Position von Vektorzentroiden in die Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="251"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="379"/>
<source>Creates a raster layer and vector point map containing randomly located points.</source>
<translation>Erstellt eine Rasterkarte und eine Vektorkarte, die zufällig angeordnete Punkte enthalten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="25"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="476"/>
<source>Selects features from vector map (A) by features from other vector map (B).</source>
<translation>Selektiert Objekte der Vektorkarte (A) durch Objekte einer anderen Vektorkarte (B).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="179"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="343"/>
<source>Creates a raster map containing concentric rings around a given point.</source>
<translation>Erzeugt eine Rasterkarte, die konzentrische Kreise um einen angegebenen Punkt ziehen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="104"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="641"/>
<source>Recategorizes data in a raster map by grouping cells that form physically discrete areas into unique categories.</source>
<translation>Re-Kategorisiert Daten einer Rasterkarte, indem Zellen physikalisch diskreter Areale zu eindeutigen Kategorie gruppiert werden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="71"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="644"/>
<source>Creates a Voronoi diagram from an input vector layer containing points.</source>
<translation>Erstellt ein Voronoi Diagramm auf Basis einer Vektorkarte mit Punkten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="288"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="339"/>
<source>Flow computation for massive grids (float version).</source>
<translation>Flußberechnung für massive Gitter (Fließkommaversion).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="173"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="364"/>
<source>Flow computation for massive grids (integer version).</source>
<translation>Flußberechnung für massive Gitter (Ganzzahkversion).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="148"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="532"/>
<source>Outputs the raster layer values lying on user-defined line(s).</source>
<translation>Gibt eine Rasterkarte aus, deren Werte entlang einer (oder mehrerer) benutzerdefinierter Linien liegt.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="105"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="500"/>
<source>Export a raster map to a text file as x,y,z values based on cell centers</source>
<translation>Raster in Textdatei als x-,y- und z-Werte der Zellzentren exportieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="267"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="603"/>
<source>Outputs basic information about a user-specified vector map.</source>
<translation>Gibt grundlegende Informationen einer bestimmten Vektorkarte aus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="192"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="310"/>
<source>Randomly partition points into test/train sets.</source>
<translation>Punkte zufällig in Test-/Trainingsdatensätze aufteilen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="229"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="352"/>
<source>Takes vector stream data, transforms it to raster and subtracts depth from the output DEM.</source>
<translation>Nimm Vektordaten, wandle sie in Rasterdaten-und subtrahiere Tiefe aus der Ausgabe DEM.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="337"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="348"/>
<source>Building contour determination and Region Growing algorithm for determining the building inside</source>
<translation>Bestimmung des Gebäudeumriß und Anwendung des 'Region Growing' Verfahrens zu Ermittelung des Gebäudeinneren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="204"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="459"/>
<source>Overland flow hydrologic simulation using path sampling method (SIMWE).</source>
<translation>Hydrologische Simulation des Oberflächenabfluß mittels der "path sampling"-Methode (SIMWE).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="304"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="599"/>
<source>Makes each output cell value a function of the values assigned to the corresponding cells in the input raster layers.</source>
<translation>Jede Ausgabezelle zur Funktion der korrespondierenden Zellen des Eingaberasters machen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="99"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="471"/>
<source>Creates a raster layer of cumulative cost of moving across a raster layer whose cell values represent cost.</source>
<translation>Raster aus der kommulierten Kosten für die Bewegung über ein Raster erzeugen, dessen Zellen Kosten repräsentieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="322"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="542"/>
<source>Rescales the range of category values in a raster layer.</source>
<translation>Reskaliert die Spanne der Kategoriewerte einer Rasterkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="128"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="511"/>
<source>Solar irradiance and irradiation model.</source>
<translation>Solar- und Bestrahlungsmodell.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="152"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="622"/>
<source>Computes the viewshed of a point on an elevation raster map.</source>
<translation>Berechnet den Sichtbarkeitsbereich eines Punkt auf einer Rasterhöhenkarte.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="333"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="535"/>
<source>A simple utility for converting bearing and distance measurements to coordinates and vice versa. It assumes a cartesian coordinate system </source>
<translation>Ein einfaches Hilfsprogramm, dass Kurs- und Distanzwert in Koordinaten umrechnet und umgekehrt. Es setzt ein kartesisches Koordinatensystem voraus </translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="141"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="636"/>
<source>Calculates the volume of data "clumps".</source>
<translation>Berechnet das Volumen Daten-"Klumpen".</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="167"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="453"/>
<source>Inverse Fast Fourier Transform (IFFT) for image processing.</source>
<translation>Inverse schnelle Fourier-Transformation (IFFT) zur Bildverarbeitung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="189"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="440"/>
<source>Vector based generalization.</source>
<translation>Vektorbasierte Generalisierung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="91"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="540"/>
<source>Surface generation program from rasterized contours.</source>
<translation>Oberflächeerzeugung aus Rasterkonturen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="257"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="360"/>
<source>Create random raster</source>
<translation>Zufälliges Raster erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="191"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="368"/>
<source>Converts to POV-Ray format, GRASS x,y,z -> POV-Ray x,z,y</source>
<translation>Wandelt in das POV-Ray-Format, GRASS x,y,z -> POV-Ray x,z,y</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="301"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="632"/>
<source>Surface interpolation utility for raster layers.</source>
<translation>Oberflächeninterpolationswerkzeug für Rasterlayer.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="186"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="393"/>
<source>Visualization(NVIZ)</source>
<translation>Visualisierung (NVIZ)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="121"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="536"/>
<source>Makes each cell value a function of attribute values and stores in an output raster map.</source>
<translation>Jede Zelle zur Funktion von Attributwerten machen und in eine Ausgaberasterkarte speichern.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="247"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="618"/>
<source>Converts files in DXF format to GRASS vector map format.</source>
<translation>Konvertiert Dateien im DXF-Format in das GRASS-Vektorkartenformat.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="230"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="357"/>
<source>Fast Fourier Transform (FFT) for image processing.</source>
<translation>Schnelle Fourier-Transformation (FFT) für Bildverarbeitung.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="349"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="531"/>
<source>Performs atmospheric correction using the 6S algorithm.</source>
<translation>Führt atmospherische Korrektur mit dem 6S-Algorithmus aus.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="53"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="490"/>
<source>Export a raster layer to the Virtual Reality Modeling Language (VRML)</source>
<translation>Raster in Virtual-Reality-Modeling-Language (VRML) exportieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="244"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="620"/>
<source>r.flow.aspect.barrier - Construction of flowlines, flowpath lengths, and flowaccumulation (contributing areas) from a raster digital elevation model (DEM).</source>
<translation>r.flow.aspect.barrier - Erzeugt Hangkurven (flowlines), Fließlängen und Flussdichte (contributing areas) aus einem angegebenen digitalen Höhenmodell (DEM).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="58"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="464"/>
<source>Numerical calculation program for transient, confined and unconfined groundwater flow in two dimensions.</source>
<translation>Numerisches Berechnungsprogramm für transienten, beschränkten und unbeschränkte Grundwasserfluß in zwei Dimensionen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="260"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="319"/>
<source>v.surf.rst.cvdev - Spatial approximation and topographic analysis using regularized spline with tension.</source>
<translation>v.surf.rst.cvdev - Räumliche Approximation und topographische Analyse mit einer regularisierten Spline-Funktion mit Spannung.</translation>
</message>
@@ -10911,32 +11158,32 @@ Bitte vor der Ausführung von GRASS-Algorithmen konfigurieren.</translation>
<context>
<name>GrassAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1200"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1215"/>
<source>GRASS folder</source>
<translation>GRASS-Verzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1201"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1216"/>
<source>Msys folder</source>
<translation>MSYS-Verzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1202"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1217"/>
<source>Log execution commands</source>
<translation>Befehlsausführung protokollieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1203"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1218"/>
<source>Log console output</source>
<translation>Konsolenausgabe protokollieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1204"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1219"/>
<source>Could not open GRASS algorithm: %s</source>
<translation>Kann GRASS-Algorithmus nicht öffnen: %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1205"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1220"/>
<source>GRASS commands</source>
<translation>GRASS-Befehle</translation>
</message>
@@ -10944,26 +11191,26 @@ Bitte vor der Ausführung von GRASS-Algorithmen konfigurieren.</translation>
<context>
<name>GrassUtils</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1209"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1224"/>
<source>GRASS folder is not configured.
Please configure it before running GRASS algorithms.</source>
<translation>GRASS-Verzeichnis nicht richtig konfiguriert.
Bitte vor der Ausführung von GRASS-Algorithmen konfigurieren.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1210"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1225"/>
<source>The specified GRASS folder "{}" does not contain a valid set of GRASS modules. Please, go to the Processing settings dialog, and check that the GRASS folder is correctly configured</source>
<translation>Das angegebene GRASS-Verzeichnis "{}" enthält keine gültige Zusammenstellung von GRASS-Modulen. Bitte in den Processing-Einstellungen das GRASS-Verzeichnis überprüfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1211"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1226"/>
<source>It seems that GRASS is not correctly installed and configured in your system.
Please install it before running GRASS algorithms.</source>
<translation>GRASS scheint nicht richtig installiert oder konfiguriert zu sein.
Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1212"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1227"/>
<source>Error while checking GRASS installation. GRASS might not be correctly configured.
</source>
<translation>Fehler beim Prüfen der GRASS-Installation. GRASS könnte nicht richtig konfiguriert sein.
@@ -10973,72 +11220,72 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>Grid</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1216"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1231"/>
<source>Create grid</source>
<translation>Gitter erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1217"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1232"/>
<source>Vector creation tools</source>
<translation>Vektorerzeugungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1218"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1233"/>
<source>Rectangle (line)</source>
<translation>Rechteck (Linie)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1219"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1234"/>
<source>Rectangle (polygon)</source>
<translation>Rechteck (Polygon)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1220"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1235"/>
<source>Diamond (polygon)</source>
<translation>Raute (Polygon)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1221"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1236"/>
<source>Hexagon (polygon)</source>
<translation>Hexagon (Polygon)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1222"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1237"/>
<source>Grid type</source>
<translation>Gittertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1223"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1238"/>
<source>Grid extent</source>
<translation>Gittergrenze von Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1224"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1239"/>
<source>Horizontal spacing</source>
<translation>Horizontaler Abstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1225"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1240"/>
<source>Vertical spacing</source>
<translation>Vertikaler Abstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1226"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1241"/>
<source>Grid</source>
<translation>Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1227"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1242"/>
<source>Invalid grid spacing: %s/%s</source>
<translation>Ungültiger Gitterabstand: %s/%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1228"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1243"/>
<source>Horizontal spacing is too small for the covered area</source>
<translation>Horizontaler Abstand ist für den abgedeckten Bereich zu klein</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1229"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1244"/>
<source>Vertical spacing is too small for the covered area</source>
<translation>Vertikaler Abstand ist zu klein für abgedeckten Bereich</translation>
</message>
@@ -11046,57 +11293,57 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>GridAverage</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1233"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1248"/>
<source>Grid (Moving average)</source>
<translation>Gitter (Beweglicher Mittelwert)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1234"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1249"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1235"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1250"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1236"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1251"/>
<source>Z field</source>
<translation>Z-Feld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1237"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1252"/>
<source>Radius 1</source>
<translation>Radius 1</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1238"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1253"/>
<source>Radius 2</source>
<translation>Radius 2</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1239"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1254"/>
<source>Min points</source>
<translation>Min. Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1240"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1255"/>
<source>Angle</source>
<translation>Winkel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1241"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1256"/>
<source>Nodata</source>
<translation>Leerwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1242"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1257"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1243"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1258"/>
<source>Interpolated moving average</source>
<translation>Interpolierter beweglicher Mittelwert</translation>
</message>
@@ -11104,62 +11351,62 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>GridDataMetrics</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1247"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1262"/>
<source>Grid (Data metrics)</source>
<translation>Gitter (Datenkriterien)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1248"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1263"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1249"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1264"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1250"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1265"/>
<source>Z field</source>
<translation>Z-Feld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1251"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1266"/>
<source>Metrics</source>
<translation>Kriterien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1252"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1267"/>
<source>Radius 1</source>
<translation>Radius 1</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1253"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1268"/>
<source>Radius 2</source>
<translation>Radius 2</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1254"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1269"/>
<source>Min points</source>
<translation>Min. Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1255"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1270"/>
<source>Angle</source>
<translation>Winkel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1256"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1271"/>
<source>Nodata</source>
<translation>Leerwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1257"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1272"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1258"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1273"/>
<source>Interpolated metrics</source>
<translation>Interpolierte Maße</translation>
</message>
@@ -11167,72 +11414,72 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>GridInvDist</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1262"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1277"/>
<source>Grid (Inverse distance to a power)</source>
<translation>Gitter (Inverse Distanz zu einer Potenz)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1263"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1278"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1264"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1279"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1265"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1280"/>
<source>Z field</source>
<translation>Z-Feld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1266"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1281"/>
<source>Power</source>
<translation>Potenz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1268"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1283"/>
<source>Radius 1</source>
<translation>Radius 1</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1269"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1284"/>
<source>Radius 2</source>
<translation>Radius 2</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1270"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1285"/>
<source>Max points</source>
<translation>Max. Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1271"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1286"/>
<source>Min points</source>
<translation>Min. Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1272"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1287"/>
<source>Angle</source>
<translation>Winkel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1273"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1288"/>
<source>Nodata</source>
<translation>Leerwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1274"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1289"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1275"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1290"/>
<source>Interpolated IDW</source>
<translation>Interpolierte IDW</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1267"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1282"/>
<source>Smoothing</source>
<translation>Glättung</translation>
</message>
@@ -11240,62 +11487,62 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>GridMetrics</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1279"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1294"/>
<source>Grid Metrics</source>
<translation>Datenkriterien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1280"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1295"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1281"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1296"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1282"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1297"/>
<source>Input ground DTM layer</source>
<translation>Eingabe-Boden-DTM-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1283"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1298"/>
<source>Height break</source>
<translation>Höhen Unterbrechung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1284"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1299"/>
<source>Cellsize</source>
<translation>Zellengröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1285"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1300"/>
<source>Output table with grid metrics</source>
<translation>Ausgabetabelle mit Gittermaßen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1286"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1301"/>
<source>OUTPUT CSV INTENSITY</source>
<translation>Ausgabe CSV Intensität</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1287"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1302"/>
<source>Outlier:low,high</source>
<translation>Ausreißer:niedrig,hoch</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1288"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1303"/>
<source>First</source>
<translation>Erster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1289"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1304"/>
<source>Htmin</source>
<translation>Htmin</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1290"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1305"/>
<source>Class (set blank if not used)</source>
<translation>Klasse (leer setzen, wenn nicht verwendet)</translation>
</message>
@@ -11303,52 +11550,52 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>GridNearest</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1294"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1309"/>
<source>Grid (Nearest neighbor)</source>
<translation>Gitter (Nächster Nachbar)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1295"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1310"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1296"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1311"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1297"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1312"/>
<source>Z field</source>
<translation>Z-Feld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1298"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1313"/>
<source>Radius 1</source>
<translation>Radius 1</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1299"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1314"/>
<source>Radius 2</source>
<translation>Radius 2</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1300"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1315"/>
<source>Angle</source>
<translation>Winkel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1301"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1316"/>
<source>Nodata</source>
<translation>Leerwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1302"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1317"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1303"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1318"/>
<source>Interpolated nearest neighbor</source>
<translation>Interpolierter nächster Nachbar</translation>
</message>
@@ -11356,52 +11603,52 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>GridNet</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1307"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1322"/>
<source>Grid Network</source>
<translation>Gitternetzwerk</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1308"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1323"/>
<source>Basic Grid Analysis tools</source>
<translation>Grundlegende Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1309"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1324"/>
<source>D8 Flow Direction Grid</source>
<translation>D8 Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1310"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1325"/>
<source>Outlets Shapefile</source>
<translation>Auslaß-Shapedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1311"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1326"/>
<source>Mask Grid</source>
<translation>Maskengitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1312"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1327"/>
<source>Mask Threshold</source>
<translation>Maskenschwellenwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1313"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1328"/>
<source>Longest Upslope Length Grid</source>
<translation>Längstes Steigungslängen Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1314"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1329"/>
<source>Total Upslope Length Grid</source>
<translation>Gesamt Steigungslängen Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1315"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1330"/>
<source>Strahler Network Order Grid</source>
<translation>Strahler Netzwerk Ordnungs Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1316"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1331"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -11409,52 +11656,52 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>GridNetMulti</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1320"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1335"/>
<source>Grid Network (multifile)</source>
<translation>Gitternetzwerk (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1321"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1336"/>
<source>Basic Grid Analysis tools</source>
<translation>Grundlegende Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1322"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1337"/>
<source>D8 Flow Direction Grid</source>
<translation>D8 Fliessrichtung Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1323"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1338"/>
<source>Outlets Shapefile</source>
<translation>Auslaß-Shapedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1324"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1339"/>
<source>Mask Grid</source>
<translation>Maskengitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1325"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1340"/>
<source>Mask Threshold</source>
<translation>Maskenschwellenwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1326"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1341"/>
<source>Longest Upslope Length Grid</source>
<translation>Längstes Steigungslängen Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1327"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1342"/>
<source>Total Upslope Length Grid</source>
<translation>Gesamt Steigungslängen Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1328"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1343"/>
<source>Strahler Network Order Grid</source>
<translation>Strahler Netzwerk Ordnungs Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1329"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1344"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -11462,72 +11709,72 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>GridSurfaceCreate</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1333"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1348"/>
<source>Grid Surface Create</source>
<translation>Gitteroberfläche erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1334"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1349"/>
<source>Surface</source>
<translation>Oberfläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1335"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1350"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1336"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1351"/>
<source>Cellsize</source>
<translation>Zellengröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1337"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1352"/>
<source>XY Units</source>
<translation>XY-Einheiten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1338"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1353"/>
<source>Z Units</source>
<translation>Z-Einheit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1339"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1354"/>
<source>DTM Output Surface</source>
<translation>DTM-Ausgabeoberfläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1340"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1355"/>
<source>Spike (set blank if not used)</source>
<translation>Impuls (leer lassen, wenn nicht genutzt)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1341"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1356"/>
<source>Median</source>
<translation>Median</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1342"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1357"/>
<source>Smooth</source>
<translation>Glatt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1343"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1358"/>
<source>Slope</source>
<translation>Neigung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1344"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1359"/>
<source>Minimum (set blank if not used)</source>
<translation>Minimum (leer lassen, wenn nicht genutzt)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1345"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1360"/>
<source>Class(es)</source>
<translation>Klasse(n)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1346"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1361"/>
<source>Additional modifiers</source>
<translation>Zusätzliche Einstellungen</translation>
</message>
@@ -11535,42 +11782,42 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>Gridify</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1351"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1366"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1352"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1367"/>
<source>Input Layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1353"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1368"/>
<source>Horizontal spacing</source>
<translation>Horizontaler Abstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1354"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1369"/>
<source>Vertical spacing</source>
<translation>Vertikaler Abstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1355"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1370"/>
<source>Snapped</source>
<translation>Gefangen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1356"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1371"/>
<source>Invalid grid spacing: %s/%s</source>
<translation>Ungültiger Gitterabstand: %s/%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1357"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1372"/>
<source>Failed to gridify feature with FID %s</source>
<translation>Fehler in der Objektvernetzung mit FID %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1350"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1365"/>
<source>Snap points to grid</source>
<translation>Punkte auf Gitter fangen</translation>
</message>
@@ -11578,32 +11825,32 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>GroundFilter</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1361"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1376"/>
<source>Ground Filter</source>
<translation>Bodenfilter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1362"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1377"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1363"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1378"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1364"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1379"/>
<source>Cellsize for intermediate surfaces</source>
<translation>Zellengröße für Zwischenfläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1365"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1380"/>
<source>Output ground LAS file</source>
<translation>LAS-Datei mit Bodenausgabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1366"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1381"/>
<source>Create .dtm surface</source>
<translation>DTM-Ausgabeoberfläche erzeugen</translation>
</message>
@@ -11858,55 +12105,55 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>HelpEditionDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1370"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1385"/>
<source>Cannot open help file: %s</source>
<translation>Die Hilfe-Datei %s konnte nicht geöffnet werden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1371"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1386"/>
<source><h2>Algorithm description</h2>
</source>
<translation><h2>Algorithmus Beschreibung</h2</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1372"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1387"/>
<source><h2>Input parameters</h2>
</source>
<translation><h2>Eingangsparameter</h2></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1373"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1388"/>
<source><h2>Outputs</h2>
</source>
<translation><h2>Ausgabe</h2></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1374"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1389"/>
<source>Algorithm description</source>
<translation>Algorithmus Beschreibung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1375"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1390"/>
<source>Input parameters</source>
<translation>Eingangs Parameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1376"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1391"/>
<source>Outputs</source>
<translation>Ausgaben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1377"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1392"/>
<source>Algorithm created by</source>
<translation>Algorithmus erstellt von</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1378"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1393"/>
<source>Algorithm help written by</source>
<translation>Algorithmus Hilfe Datei geschrieben von</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1379"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1394"/>
<source>Algorithm version</source>
<translation>Alorithmus Version</translation>
</message>
@@ -11914,47 +12161,47 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>HistoryDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1383"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1398"/>
<source>Clear</source>
<translation>Löschen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1385"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1400"/>
<source>Save As...</source>
<translation>Speichern als...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1387"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1402"/>
<source>Confirmation</source>
<translation>Bestätigung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1384"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1399"/>
<source>Clear history</source>
<translation>Historie leeren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1386"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1401"/>
<source>Save history</source>
<translation>Historie speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1388"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1403"/>
<source>Are you sure you want to clear the history?</source>
<translation>Soll die Historie wirklich geleert werden?</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1389"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1404"/>
<source>Save file</source>
<translation>Datei speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1390"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1405"/>
<source>Log files (*.log *.LOG)</source>
<translation>Log Dateien (*.log *.LOG)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1391"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1406"/>
<source>Create test</source>
<translation>Test erzeugen</translation>
</message>
@@ -11983,72 +12230,72 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>HubDistance</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1396"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1411"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1397"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1412"/>
<source>Meters</source>
<translation>Meter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1398"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1413"/>
<source>Feet</source>
<translation>Fuß</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1399"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1414"/>
<source>Miles</source>
<translation>Meilen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1400"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1415"/>
<source>Kilometers</source>
<translation>Kilometer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1401"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1416"/>
<source>Layer units</source>
<translation>Layereinheiten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1402"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1417"/>
<source>Source points layer</source>
<translation>Quellpunktlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1403"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1418"/>
<source>Destination hubs layer</source>
<translation>Zielnabenlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1404"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1419"/>
<source>Hub layer name attribute</source>
<translation>Nabenlayernamenattribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1405"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1420"/>
<source>Output shape type</source>
<translation>Ausgabe-Shape Typ</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1406"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1421"/>
<source>Measurement unit</source>
<translation>Maßeinheit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1407"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1422"/>
<source>Hub distance</source>
<translation>Knotenabstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1408"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1423"/>
<source>Same layer given for both hubs and spokes</source>
<translation>Gleicher Name für Naben- und Speichenlayer gewählt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1395"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1410"/>
<source>Distance to nearest hub</source>
<translation>Abstand zum nächsten Knoten</translation>
</message>
@@ -12056,37 +12303,37 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>HubLines</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1414"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1429"/>
<source>Hub point layer</source>
<translation>Nabenpunktlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1415"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1430"/>
<source>Hub ID field</source>
<translation>Nabenkennungsfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1416"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1431"/>
<source>Spoke point layer</source>
<translation>Speichenpunktlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1417"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1432"/>
<source>Spoke ID field</source>
<translation>Speichenkennungsfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1412"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1427"/>
<source>Hub lines</source>
<translation>Knotenlinien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1413"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1428"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1418"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1433"/>
<source>Same layer given for both hubs and spokes</source>
<translation>Gleicher Name für Naben- und Speichenlayer gewählt</translation>
</message>
@@ -12094,52 +12341,52 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>HypsometricCurves</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1424"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1439"/>
<source>DEM to analyze</source>
<translation>Zu analysierendes DEM</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1425"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1440"/>
<source>Boundary layer</source>
<translation>Begrenzungslayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1426"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1441"/>
<source>Step</source>
<translation>Schrittweite</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1427"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1442"/>
<source>Use % of area instead of absolute value</source>
<translation>Prozentsatz der Fläche statt absolutem Wert verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1422"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1437"/>
<source>Hypsometric curves</source>
<translation>Höhenschichtenkurven</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1423"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1438"/>
<source>Raster tools</source>
<translation>Rasterwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1428"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1443"/>
<source>Feature %d does not intersect raster or entirely located in NODATA area</source>
<translation>Objekt %d schneidet das Raster nicht oder ist komplett im leeren Bereich</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1430"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1445"/>
<source>Area</source>
<translation>Fläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1431"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1446"/>
<source>Elevation</source>
<translation>Geländehöhe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1429"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1444"/>
<source>Feature %d is smaller than raster cell size</source>
<translation>Objekt %d ist kleiner als Rasterzellengröße</translation>
</message>
@@ -12147,42 +12394,42 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>ImageCreate</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1435"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1450"/>
<source>ImageCreate</source>
<translation>ImageCreate</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1436"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1451"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1437"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1452"/>
<source>Input LAS</source>
<translation>LAS-Eingabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1438"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1453"/>
<source>Method to assign color</source>
<translation>Methode zur Farbzuweisung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1440"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1455"/>
<source>Use RGB color model to create the color ramp</source>
<translation>RGB-Farbmodell für die Erzeugung des Farbverlaufs verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1439"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1454"/>
<source>Ground file (used with 'Height' method)</source>
<translation>Grunddatei (mit der 'Höhenmethode' verwendet)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1441"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1456"/>
<source>Pixel size</source>
<translation>Pixelgröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1442"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1457"/>
<source>Output format</source>
<translation>Ausgabeformat</translation>
</message>
@@ -12190,79 +12437,79 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>ImportIntoPostGIS</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1460"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1475"/>
<source>Error importing to PostGIS
%s</source>
<translation>Fehler beim PostGIS-Import
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1447"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1462"/>
<source>Database</source>
<translation>Datenbank</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1448"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1463"/>
<source>Layer to import</source>
<translation>Zu importierender Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1449"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1464"/>
<source>Database (connection name)</source>
<translation>Datenbank (Verbindungsname)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1450"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1465"/>
<source>Schema (schema name)</source>
<translation>Schema (Schemaname)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1451"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1466"/>
<source>Table to import to (leave blank to use layer name)</source>
<translation>Importieren in Tabelle (leer lassen um den Layername zu verwenden)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1452"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1467"/>
<source>Primary key field</source>
<translation>Primärschlüsselfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1453"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1468"/>
<source>Geometry column</source>
<translation>Geometriespalte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1454"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1469"/>
<source>Encoding</source>
<translation>Kodierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1455"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1470"/>
<source>Overwrite</source>
<translation>Überschreiben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1456"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1471"/>
<source>Create spatial index</source>
<translation>Räumlichen Index erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1457"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1472"/>
<source>Convert field names to lowercase</source>
<translation>Feldnamen in Kleinschreibung umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1458"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1473"/>
<source>Drop length constraints on character fields</source>
<translation>Längenbeschränkungen auf Textfeld verwerfen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1459"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1474"/>
<source>Create single-part geometries instead of multi-part</source>
<translation>Einteilige statt mehrteiliger Geometrien erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1446"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1461"/>
<source>Import into PostGIS</source>
<translation>In PostGIS importieren</translation>
</message>
@@ -12270,7 +12517,7 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>InfoViewer</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="433"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="463"/>
<source>DB Manager</source>
<translation>DB-Verwaltung</translation>
</message>
@@ -12278,12 +12525,12 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>InputLayerSelectorPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1464"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1479"/>
<source>Select file</source>
<translation>Datei wählen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1465"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1480"/>
<source>All files (*.*);;</source>
<translation>Alle Dateien (*.*);;</translation>
</message>
@@ -12291,42 +12538,42 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>IntensityImage</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1469"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1484"/>
<source>IntensityImage</source>
<translation>IntensityImage</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1470"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1485"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1471"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1486"/>
<source>Input file</source>
<translation>Eingabedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1472"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1487"/>
<source>Use all returns instead of only first</source>
<translation>Alle Ergebnisse statt nur des ersten verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1473"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1488"/>
<source>Use the lowest return in pixel area to assign the intensity value</source>
<translation>Niedrigstes Ergebnis im Pixelbereich zur Zuweisung des Intensitätswerts verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1474"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1489"/>
<source>Produce a CSV intensity histogram data file</source>
<translation>CSV-Intensitätshistogrammdatendatei erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1475"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1490"/>
<source>Pixel size</source>
<translation>Pixelgröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1476"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1491"/>
<source>Output format</source>
<translation>Ausgabeformat</translation>
</message>
@@ -12334,32 +12581,32 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>Intersection</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1485"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1500"/>
<source>Feature geometry error: One or more output features ignored due to invalid geometry.</source>
<translation>Objektgeometriefehler: Ein oder mehrere Objekte wegen ungültiger Geometrie ignoriert.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1481"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1496"/>
<source>Vector overlay tools</source>
<translation>Vektorlayerüberlagerungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1482"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1497"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1483"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1498"/>
<source>Intersect layer</source>
<translation>Layer schneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1484"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1499"/>
<source>GEOS geoprocessing error: One or more input features have invalid geometry.</source>
<translation>GEOS-Verarbeitungsfehler: Ein oder mehrere Eingabeobjekte haben ungültige Geometrien.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1480"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1495"/>
<source>Intersection</source>
<translation>Verschneidung</translation>
</message>
@@ -12367,37 +12614,37 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>JoinAttributes</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1490"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1505"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1491"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1506"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1492"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1507"/>
<source>Input layer 2</source>
<translation>Eingabelayer 2</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1493"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1508"/>
<source>Table field</source>
<translation>Tabellenspalte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1494"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1509"/>
<source>Table field 2</source>
<translation>Tabellenfeld 2</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1495"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1510"/>
<source>Joined layer</source>
<translation>Zusammengefasster Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1489"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1504"/>
<source>Join attributes table</source>
<translation>Attributtabellen verknüpfen</translation>
</message>
@@ -12421,194 +12668,194 @@ Bitte installieren bevor GRASS-Algorithmen ausgeführt werden.</translation>
<context>
<name>LAStoolsAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1499"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1514"/>
<source>LAStools folder is not configured.
Please configure it before running LAStools algorithms.</source>
<translation>LAStools-Verzeichnis nicht konfiguriert.
Bitte vor der Ausführung von LAStools-Algorithmen einstellen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1500"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1515"/>
<source>verbose</source>
<translation>ausführlich</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1501"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1516"/>
<source>open LAStools GUI</source>
<translation>LAStools-GUI öffnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1502"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1517"/>
<source>number of cores</source>
<translation>Kernanzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1503"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1518"/>
<source>input LAS/LAZ file</source>
<translation>LAS/LAZ-Eingabedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1504"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1519"/>
<source>input directory</source>
<translation>Eingabeverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1505"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1520"/>
<source>input wildcard(s)</source>
<translation>Eingabeplatzhalter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1506"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1521"/>
<source>merge all input files on-the-fly into one</source>
<translation>Alle Eingabedateien spontan in einer zusammenfassen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1507"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1522"/>
<source>horizontal feet</source>
<translation>Fuß horizontal</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1508"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1523"/>
<source>vertical feet</source>
<translation>Fuß vertikal</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1509"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1524"/>
<source>files are flightlines</source>
<translation>Dateien sind Fluglinien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1510"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1525"/>
<source>apply file source ID</source>
<translation>Dateiquellekennung anwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1511"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1526"/>
<source>step size / pixel size</source>
<translation>Schrittweite/Pixelgröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1512"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1527"/>
<source>output LAS/LAZ file</source>
<translation>LAS/LAZ-Ausgabedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1513"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1528"/>
<source>output format</source>
<translation>Ausgabeformat</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1514"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1529"/>
<source>Output raster file</source>
<translation>Ausgaberasterdatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1515"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1530"/>
<source>Output vector file</source>
<translation>Ausgabevektordatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1516"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1531"/>
<source>output directory</source>
<translation>Ausgabeverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1517"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1532"/>
<source>output appendix</source>
<translation>Ausgabe Anhang</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1518"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1533"/>
<source>empty temporary directory</source>
<translation>Leeres Temporärverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1519"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1534"/>
<source>additional command line parameter(s)</source>
<translation>Weitere(r) Kommandozeilenparameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1520"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1535"/>
<source>filter (by return, classification, flags)</source>
<translation>filter (nach Return, Klassifikation, Flag)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1521"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1536"/>
<source>second filter (by return, classification, flags)</source>
<translation>zweiter Filter (nach Return, Klassifikation, Flag)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1522"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1537"/>
<source>third filter (by return, classification, flags)</source>
<translation>dritter Filter (nach Return, Klassifikation, Flag)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1523"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1538"/>
<source>filter (by coordinate, intensity, GPS time, ...)</source>
<translation>Filtern (nach Koordinaten, Intensität, GPS-Zeit, ...)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1524"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1539"/>
<source>value for filter (by coordinate, intensity, GPS time, ...)</source>
<translation>Wert für Filter (nach Koordinate, Intensität, GPS-Zeit, ...)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1525"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1540"/>
<source>second filter (by coordinate, intensity, GPS time, ...)</source>
<translation>Zweiter Filter (nach Koordinate, Intensität, GPS-Zeit, ...)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1526"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1541"/>
<source>value for second filter (by coordinate, intensity, GPS time, ...)</source>
<translation>Wert für zweiten Filter (nach Koordinate, Intensität, GPS-Zeit, ...)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1527"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1542"/>
<source>transform (coordinates)</source>
<translation>Umwandeln (Koordinaten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1528"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1543"/>
<source>value for transform (coordinates)</source>
<translation>Wert für Transformation (Koordinaten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1529"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1544"/>
<source>second transform (coordinates)</source>
<translation>zweite Umwandlung (Koordinaten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1530"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1545"/>
<source>value for second transform (coordinates)</source>
<translation>Wert für zweite Umwandlung (Koordinaten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1531"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1546"/>
<source>transform (intensities, scan angles, GPS times, ...)</source>
<translation>Umwandlung (Intensität, Scanwinkel, GPS-Zeit, ...)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1532"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1547"/>
<source>value for transform (intensities, scan angles, GPS times, ...)</source>
<translation>Wert für Umwandlung (Intensität, Scanwinkel, GPS-Zeit, ...)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1533"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1548"/>
<source>second transform (intensities, scan angles, GPS times, ...)</source>
<translation>Zweite Umwandlung (Intensität, Scanwinkel, GPS-Zeit, ...)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1534"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1549"/>
<source>value for second transform (intensities, scan angles, GPS times, ...)</source>
<translation>Wert für zweite Umwandlung (Intensität, Scanwinkel, GPS-Zeit, ...)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1535"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1550"/>
<source>ignore points with this classification</source>
<translation>Punkte dieser Klasse ignorieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1536"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1551"/>
<source>also ignore points with this classification</source>
<translation>auch Punkte dieser Klasse ignorieren</translation>
</message>
@@ -12616,12 +12863,12 @@ Bitte vor der Ausführung von LAStools-Algorithmen einstellen.</translation>
<context>
<name>LAStoolsUtils</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1540"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1555"/>
<source>LAStools command line</source>
<translation>LAStools Kommandozeile</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1541"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1556"/>
<source>LAStools console output</source>
<translation>LAStools-Konsolenausgabe</translation>
</message>
@@ -12647,42 +12894,42 @@ Bitte vor der Ausführung von LAStools-Algorithmen einstellen.</translation>
<context>
<name>LengthArea</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1545"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1560"/>
<source>Length Area Stream Source</source>
<translation>Länge Fläche Strom Quelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1546"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1561"/>
<source>Stream Network Analysis tools</source>
<translation>Stromnetzwerkanalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1547"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1562"/>
<source>Length Grid</source>
<translation>Längengitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1548"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1563"/>
<source>Contributing Area Grid</source>
<translation>Beitragende Fläche Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1549"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1564"/>
<source>Threshold</source>
<translation>Schwelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1550"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1565"/>
<source>Exponent</source>
<translation>Exponent</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1551"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1566"/>
<source>Stream Source Grid</source>
<translation>Strom Quellennetz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1552"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1567"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -12690,42 +12937,42 @@ Bitte vor der Ausführung von LAStools-Algorithmen einstellen.</translation>
<context>
<name>LengthAreaMulti</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1556"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1571"/>
<source>Length Area Stream Source (multifile)</source>
<translation>Länge Fläche Strom Quelle (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1557"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1572"/>
<source>Stream Network Analysis tools</source>
<translation>Stromnetzwerkanalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1558"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1573"/>
<source>Length Grid</source>
<translation>Längengitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1559"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1574"/>
<source>Contributing Area Grid</source>
<translation>Beitragende Fläche Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1560"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1575"/>
<source>Threshold</source>
<translation>Schwelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1561"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1576"/>
<source>Exponent</source>
<translation>Exponent</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1562"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1577"/>
<source>Stream Source Grid</source>
<translation>Strom Quellennetz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1563"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1578"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -12733,22 +12980,22 @@ Bitte vor der Ausführung von LAStools-Algorithmen einstellen.</translation>
<context>
<name>LidarToolsAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1567"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1582"/>
<source>LAStools folder</source>
<translation>LAStools-Verzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1568"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1583"/>
<source>Fusion folder</source>
<translation>Fusion-Verzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1569"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1584"/>
<source>Wine folder</source>
<translation>Wine-Verzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1570"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1585"/>
<source>Tools for LiDAR data</source>
<translation>Werkzeuge für LiDAR-Daten</translation>
</message>
@@ -12756,37 +13003,37 @@ Bitte vor der Ausführung von LAStools-Algorithmen einstellen.</translation>
<context>
<name>LinesIntersection</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1575"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1590"/>
<source>Vector overlay tools</source>
<translation>Vektorlayerüberlagerungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1576"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1591"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1577"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1592"/>
<source>Intersect layer</source>
<translation>Layer schneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1578"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1593"/>
<source>Input unique ID field</source>
<translation>Eindeutiges Schlüsselfeld der Eingabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1579"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1594"/>
<source>Intersect unique ID field</source>
<translation>Eindeutiges Schlüsselfeld des Schnitts</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1580"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1595"/>
<source>Intersections</source>
<translation>Schnittpunkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1574"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1589"/>
<source>Line intersections</source>
<translation>Linienschnittpunkte</translation>
</message>
@@ -12794,22 +13041,22 @@ Bitte vor der Ausführung von LAStools-Algorithmen einstellen.</translation>
<context>
<name>LinesToPolygons</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1585"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1600"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1586"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1601"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1587"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1602"/>
<source>Polygons from lines</source>
<translation>Polygon aus Linien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1584"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1599"/>
<source>Lines to polygons</source>
<translation>Linien zu Polygonen</translation>
</message>
@@ -12873,7 +13120,7 @@ Bitte vor der Ausführung von LAStools-Algorithmen einstellen.</translation>
</message>
<message>
<location filename="../src/ui/qgisapp.ui" line="243"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1591"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1606"/>
<source>Vect&or</source>
<translation>&Vektor</translation>
</message>
@@ -13367,52 +13614,62 @@ Bitte vor der Ausführung von LAStools-Algorithmen einstellen.</translation>
<translation>Strg+Umschalt+N</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2440"/>
+ <location filename="../src/ui/qgisapp.ui" line="1403"/>
+ <source>F6</source>
+ <translation>F6</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgisapp.ui" line="2285"/>
+ <source>Temporary Scratch Layer...</source>
+ <translation>Temporärlayer...</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgisapp.ui" line="2443"/>
<source>Add Circular String</source>
<translation>Kreisbogen hinzufügen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2455"/>
+ <location filename="../src/ui/qgisapp.ui" line="2458"/>
<source>Add Circular String by Radius</source>
<translation>Kreisbogen über Radius hinzufügen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2487"/>
+ <location filename="../src/ui/qgisapp.ui" line="2490"/>
<source>Diagram Options</source>
<translation>Diagrammoptionen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2490"/>
+ <location filename="../src/ui/qgisapp.ui" line="2493"/>
<source>Layer Diagram Options</source>
<translation>Layerdiagrammoptionen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2499"/>
+ <location filename="../src/ui/qgisapp.ui" line="2502"/>
<source>New GeoPackage Layer...</source>
<translation>Neuer GeoPackage-Layer...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2508"/>
+ <location filename="../src/ui/qgisapp.ui" line="2511"/>
<source>Modify Attributes of Selected Features</source>
<translation>Attribute der gewählten Objekte ändern</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2511"/>
+ <location filename="../src/ui/qgisapp.ui" line="2514"/>
<source>Modify the Attributes of all Selected Features Simultaneously</source>
<translation>Attribute von allen gewählten Objekten gleichzeitig ändern</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2544"/>
+ <location filename="../src/ui/qgisapp.ui" line="2547"/>
<source>Select Features by Value...</source>
<translation>Objekte nach Wert wählen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2547"/>
+ <location filename="../src/ui/qgisapp.ui" line="2550"/>
<source>Select Features By Value</source>
<translation>Objekte nach Wert wählen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2550"/>
+ <location filename="../src/ui/qgisapp.ui" line="2553"/>
<source>F3</source>
<translation>F3</translation>
</message>
@@ -13487,69 +13744,69 @@ Bitte vor der Ausführung von LAStools-Algorithmen einstellen.</translation>
<translation>Strg+Umschalt+W</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1412"/>
+ <location filename="../src/ui/qgisapp.ui" line="1415"/>
<source>Toggle Editing</source>
<translation>Bearbeitungsstatus umschalten</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1415"/>
+ <location filename="../src/ui/qgisapp.ui" line="1418"/>
<source>Toggles the editing state of the current layer</source>
<translation>Bearbeitungsstatus des aktuellen Layers umschalten</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1424"/>
+ <location filename="../src/ui/qgisapp.ui" line="1427"/>
<source>Save for Selected Layer(s)</source>
<translation>Speichern gewählter Layer</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1427"/>
+ <location filename="../src/ui/qgisapp.ui" line="1430"/>
<source>Save edits to current layer, but continue editing</source>
<translation>Speichert Änderungen und bleibt im Bearbeitungsmodus</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1441"/>
<location filename="../src/ui/qgisapp.ui" line="1444"/>
+ <location filename="../src/ui/qgisapp.ui" line="1447"/>
<source>Remove Layer/Group</source>
<translation>Layer/Gruppe löschen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1470"/>
+ <location filename="../src/ui/qgisapp.ui" line="1473"/>
<source>Filter...</source>
<translation>Filter...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1583"/>
+ <location filename="../src/ui/qgisapp.ui" line="1586"/>
<source>Configure Shortcuts...</source>
<translation>Tastenkürzel festlegen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1615"/>
+ <location filename="../src/ui/qgisapp.ui" line="1618"/>
<source>API Documentation</source>
<translation>API-Dokumentation</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1672"/>
<location filename="../src/ui/qgisapp.ui" line="1675"/>
+ <location filename="../src/ui/qgisapp.ui" line="1678"/>
<source>Move Label And Diagram</source>
<translation>Beschriftungen und Diagramm verschieben</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1733"/>
+ <location filename="../src/ui/qgisapp.ui" line="1736"/>
<source>Full Histogram Stretch</source>
<translation>Volle Histogrammstreckung</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1865"/>
+ <location filename="../src/ui/qgisapp.ui" line="1868"/>
<source>Touch Zoom and Pan</source>
<translation>Zoomen und Verschieben durch Berührung</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1934"/>
+ <location filename="../src/ui/qgisapp.ui" line="1937"/>
<source>Pin/Unpin Labels And Diagrams</source>
<translation>Beschriftungen anpinnen/lösen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1937"/>
+ <location filename="../src/ui/qgisapp.ui" line="1940"/>
<source>Pin/Unpin Labels And Diagrams
Click or marquee on label/diagram to pin
Shift unpins, Ctl (Cmd) toggles state
@@ -13560,22 +13817,22 @@ Umschalt löst, Strg (Cmd) schalten um
Funktioniert auf allen änderbaren Layern</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1952"/>
+ <location filename="../src/ui/qgisapp.ui" line="1955"/>
<source>Highlight Pinned Labels And DIagrams</source>
<translation>Angepinnte Beschriftungen und Diagramme hervorheben</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1955"/>
+ <location filename="../src/ui/qgisapp.ui" line="1958"/>
<source>Highlight Pinned Labels And Diagrams</source>
<translation>Angepinnte Beschriftungen und Diagramme hervorheben</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2003"/>
+ <location filename="../src/ui/qgisapp.ui" line="2006"/>
<source>Show/Hide Labels And Diagrams</source>
<translation>Beschriftungen und Diagramme anzeigen/ausblenden</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2006"/>
+ <location filename="../src/ui/qgisapp.ui" line="2009"/>
<source>Show/Hide Labels And Diagrams
Click or marquee on feature to show label and diagram
Shift+click or marquee on label or diagram to hide it
@@ -13586,193 +13843,193 @@ Umschalt+Klick auf Beschriftung/Diagramm auszublenden
Funktioniert auf allen ändernbaren Layern</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2021"/>
<location filename="../src/ui/qgisapp.ui" line="2024"/>
+ <location filename="../src/ui/qgisapp.ui" line="2027"/>
<source>HTML Annotation</source>
<translation>HTML-Beschriftung</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2048"/>
+ <location filename="../src/ui/qgisapp.ui" line="2051"/>
<source>SVG Annotation</source>
<translation>SVG-Anmerkung</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2170"/>
+ <location filename="../src/ui/qgisapp.ui" line="2173"/>
<source>&Download Data...</source>
<translation>&Daten herunterladen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2175"/>
+ <location filename="../src/ui/qgisapp.ui" line="2178"/>
<source>&Import Topology from XML...</source>
<translation>&Topologie aus XML importieren...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2180"/>
+ <location filename="../src/ui/qgisapp.ui" line="2183"/>
<source>&Export Topology to SpatiaLite...</source>
<translation>Topologie nach SpatiaLite &exportieren...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2189"/>
+ <location filename="../src/ui/qgisapp.ui" line="2192"/>
<source>Increase Brightness</source>
<translation>Helligkeit erhöhen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2198"/>
+ <location filename="../src/ui/qgisapp.ui" line="2201"/>
<source>Decrease Brightness</source>
<translation>Helligkeit vermindern</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2207"/>
+ <location filename="../src/ui/qgisapp.ui" line="2210"/>
<source>Increase Contrast</source>
<translation>Kontrast erhöhen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2216"/>
+ <location filename="../src/ui/qgisapp.ui" line="2219"/>
<source>Decrease Contrast</source>
<translation>Kontrast vermindern</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2225"/>
+ <location filename="../src/ui/qgisapp.ui" line="2228"/>
<source>Select By Expression...</source>
<translation>Objekte über Ausdruck wählen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2233"/>
+ <location filename="../src/ui/qgisapp.ui" line="2236"/>
<source>Need Commercial Support?</source>
<translation>Brauchen Sie professionelle Unterstützung?</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2242"/>
+ <location filename="../src/ui/qgisapp.ui" line="2245"/>
<source>Open Field Calculator...</source>
<translation>Feldrechner öffnen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2274"/>
+ <location filename="../src/ui/qgisapp.ui" line="2277"/>
<source>New Vector Layer...</source>
<translation>Neuer Vektorlayer...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2285"/>
+ <location filename="../src/ui/qgisapp.ui" line="2288"/>
<source>Paste features in clipboard into a new temporary scratch layer.</source>
<translation>Objekte in der Zwischenablage als neuen Temporärlayer einfügen.</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2310"/>
+ <location filename="../src/ui/qgisapp.ui" line="2313"/>
<source>Add from Layer Definition File...</source>
<translation>Aus Layerdefinitionsdatei hinzufügen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2315"/>
+ <location filename="../src/ui/qgisapp.ui" line="2318"/>
<source>Save As Layer Definition File...</source>
<translation>Als Layerdefinitionsdatei speichern...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2326"/>
+ <location filename="../src/ui/qgisapp.ui" line="2329"/>
<source>Normal</source>
<translation>Normal</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2329"/>
+ <location filename="../src/ui/qgisapp.ui" line="2332"/>
<source>Normal preview mode</source>
<translation>Normaler Voransichtsmodus</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2337"/>
+ <location filename="../src/ui/qgisapp.ui" line="2340"/>
<source>Simulate Photocopy (Grayscale)</source>
<translation>Fotokopie simulieren (Graustufen)</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2340"/>
+ <location filename="../src/ui/qgisapp.ui" line="2343"/>
<source>Simulate photocopy (grayscale)</source>
<translation>Fotokopie simulieren (Graustufen)</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2348"/>
+ <location filename="../src/ui/qgisapp.ui" line="2351"/>
<source>Simulate Fax (Mono)</source>
<translation>Fax simulieren (Mono)</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2351"/>
+ <location filename="../src/ui/qgisapp.ui" line="2354"/>
<source>Simulate fax (mono)</source>
<translation>Fax simulieren (Mono)</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2359"/>
+ <location filename="../src/ui/qgisapp.ui" line="2362"/>
<source>Simulate Color Blindness (Protanope)</source>
<translation>Farbenblindheit simulieren (Rotblinde)</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2362"/>
+ <location filename="../src/ui/qgisapp.ui" line="2365"/>
<source>Simulate color blindness (protanope)</source>
<translation>Farbenblindheit simulieren (Rotblinde)</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2370"/>
+ <location filename="../src/ui/qgisapp.ui" line="2373"/>
<source>Simulate Color Blindness (Deuteranope)</source>
<translation>Farbenblindheit simulieren (Grünblinde)</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2373"/>
+ <location filename="../src/ui/qgisapp.ui" line="2376"/>
<source>Simulate color blindness (deuteranope)</source>
<translation>Farbenblindheit simulieren (Grünblinde)</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2378"/>
+ <location filename="../src/ui/qgisapp.ui" line="2381"/>
<source>Set Scale Visibility of Layer(s)</source>
<translation>Maßstabsabhängige Sichtbarkeit des/der Layer setzen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2387"/>
+ <location filename="../src/ui/qgisapp.ui" line="2390"/>
<source>Show Selected Layers</source>
<translation>Zeige gewählte Layer</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2396"/>
+ <location filename="../src/ui/qgisapp.ui" line="2399"/>
<source>Hide Selected Layers</source>
<translation>Ausblenden von gewählten Layern</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2420"/>
+ <location filename="../src/ui/qgisapp.ui" line="2423"/>
<source>Statistical Summary</source>
<translation>Statistische Zusammenfassung</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2423"/>
+ <location filename="../src/ui/qgisapp.ui" line="2426"/>
<source>Show statistical summary</source>
<translation>Statistische Zusammenfassung anzeigen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2428"/>
+ <location filename="../src/ui/qgisapp.ui" line="2431"/>
<source>Align Rasters...</source>
<translation>Raster ausrichten...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2443"/>
+ <location filename="../src/ui/qgisapp.ui" line="2446"/>
<source>Add circular string</source>
<translation>Kreisbogen hinzufügen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2458"/>
+ <location filename="../src/ui/qgisapp.ui" line="2461"/>
<source>Add circular string by radius</source>
<translation>Kreisbogen über Radius hinzufügen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2463"/>
+ <location filename="../src/ui/qgisapp.ui" line="2466"/>
<source>Report an issue</source>
<translation>Ein Problem melden</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2475"/>
+ <location filename="../src/ui/qgisapp.ui" line="2478"/>
<source>Enable Tracing</source>
<translation>Spurverfolgung einschalten</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2478"/>
+ <location filename="../src/ui/qgisapp.ui" line="2481"/>
<source>T</source>
<translation>T</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1447"/>
+ <location filename="../src/ui/qgisapp.ui" line="1450"/>
<source>Ctrl+D</source>
<translation>Strg+D</translation>
</message>
@@ -13787,82 +14044,82 @@ Funktioniert auf allen ändernbaren Layern</translation>
<translation>Rasterrechner ...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1452"/>
+ <location filename="../src/ui/qgisapp.ui" line="1455"/>
<source>Set CRS of Layer(s)</source>
<translation>KBS von Layer(n) setzen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1455"/>
+ <location filename="../src/ui/qgisapp.ui" line="1458"/>
<source>Ctrl+Shift+C</source>
<translation>Strg+Umschalt+C</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1460"/>
+ <location filename="../src/ui/qgisapp.ui" line="1463"/>
<source>Set Project CRS from Layer</source>
<translation>Layer-KBS dem Projekt zuweisen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1482"/>
+ <location filename="../src/ui/qgisapp.ui" line="1485"/>
<source>Add to Overview</source>
<translation>Zur Übersicht hinzufügen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1491"/>
+ <location filename="../src/ui/qgisapp.ui" line="1494"/>
<source>Add All to Overview</source>
<translation>Alle zur Übersicht hinzufügen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1500"/>
+ <location filename="../src/ui/qgisapp.ui" line="1503"/>
<source>Remove All from Overview</source>
<translation>Alle aus Übersicht entfernen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1509"/>
+ <location filename="../src/ui/qgisapp.ui" line="1512"/>
<source>Show All Layers</source>
<translation>Alle Layer anzeigen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1512"/>
+ <location filename="../src/ui/qgisapp.ui" line="1515"/>
<source>Ctrl+Shift+U</source>
<translation>Strg+Umschalt+U</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1521"/>
+ <location filename="../src/ui/qgisapp.ui" line="1524"/>
<source>Hide All Layers</source>
<translation>Alle Layer ausblenden</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1524"/>
+ <location filename="../src/ui/qgisapp.ui" line="1527"/>
<source>Ctrl+Shift+H</source>
<translation>Strg+Umschalt+H</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1533"/>
+ <location filename="../src/ui/qgisapp.ui" line="1536"/>
<source>Manage and Install Plugins...</source>
<translation>Erweiterungen verwalten und installieren...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2245"/>
+ <location filename="../src/ui/qgisapp.ui" line="2248"/>
<source>Open Field Calculator</source>
<translation>Feldrechner öffnen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2254"/>
+ <location filename="../src/ui/qgisapp.ui" line="2257"/>
<source>Add Delimited Text Layer...</source>
<translation>Textdatei als Layer importieren...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2257"/>
+ <location filename="../src/ui/qgisapp.ui" line="2260"/>
<source>Add Delimited Text Layer</source>
<translation>Textdatei als Layer importieren</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2277"/>
+ <location filename="../src/ui/qgisapp.ui" line="2280"/>
<source>Paste features in clipboard into a new OGR vector layer.</source>
<translation>Objekte in der Zwischenablage als neuen OGR-Vektorlayer einfügen.</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1538"/>
+ <location filename="../src/ui/qgisapp.ui" line="1541"/>
<source>Toggle Full Screen Mode</source>
<translation>Auf Vollbildmodus schalten</translation>
</message>
@@ -13914,347 +14171,347 @@ Funktioniert auf allen ändernbaren Layern</translation>
<translation>Strg+Umschalt+2</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1473"/>
+ <location filename="../src/ui/qgisapp.ui" line="1476"/>
<source>Ctrl+F</source>
<translation>Strg+F</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1541"/>
+ <location filename="../src/ui/qgisapp.ui" line="1544"/>
<source>F11</source>
<translation>F11</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1553"/>
+ <location filename="../src/ui/qgisapp.ui" line="1556"/>
<source>Ctrl+Shift+P</source>
<translation>Strg+Umschalt+P</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1574"/>
+ <location filename="../src/ui/qgisapp.ui" line="1577"/>
<source>Custom CRS...</source>
<translation>Benutzerkoordinatenbezugssystem...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1595"/>
+ <location filename="../src/ui/qgisapp.ui" line="1598"/>
<source>Local Histogram Stretch</source>
<translation>Lokale Histogrammstreckung</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1598"/>
+ <location filename="../src/ui/qgisapp.ui" line="1601"/>
<source>Stretch histogram of active raster to view extents</source>
<translation>Strecke das Histogram des aktiven Rasters um Ausdehnung zu zeigen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1607"/>
+ <location filename="../src/ui/qgisapp.ui" line="1610"/>
<source>Help Contents</source>
<translation>Hilfe-Übersicht</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1610"/>
+ <location filename="../src/ui/qgisapp.ui" line="1613"/>
<source>F1</source>
<translation>F1</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1624"/>
+ <location filename="../src/ui/qgisapp.ui" line="1627"/>
<source>QGIS Home Page</source>
<translation>QGIS-Homepage</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1627"/>
+ <location filename="../src/ui/qgisapp.ui" line="1630"/>
<source>Ctrl+H</source>
<translation>Strg+H</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1636"/>
+ <location filename="../src/ui/qgisapp.ui" line="1639"/>
<source>Check QGIS Version</source>
<translation>QGIS-Version überprüfen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1639"/>
+ <location filename="../src/ui/qgisapp.ui" line="1642"/>
<source>Check if your QGIS version is up to date (requires internet access)</source>
<translation>Aktualität Ihrer QGIS-Version überprüfen (erfordert Internetzugang)</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1648"/>
+ <location filename="../src/ui/qgisapp.ui" line="1651"/>
<source>About</source>
<translation>Über</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1660"/>
+ <location filename="../src/ui/qgisapp.ui" line="1663"/>
<source>QGIS Sponsors</source>
<translation>QGIS-Sponsoren</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1687"/>
+ <location filename="../src/ui/qgisapp.ui" line="1690"/>
<source>Rotate Label</source>
<translation>Beschriftung drehen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1690"/>
+ <location filename="../src/ui/qgisapp.ui" line="1693"/>
<source>Rotate Label
Ctl (Cmd) increments by 15 deg.</source>
<translation>Beschriftung drehen
Strg (Cmd) erhöht um 15 Grad.</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1703"/>
+ <location filename="../src/ui/qgisapp.ui" line="1706"/>
<source>Change Label</source>
<translation>Beschriftung verändern</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1712"/>
+ <location filename="../src/ui/qgisapp.ui" line="1715"/>
<source>Style Manager...</source>
<translation>Stilverwaltung...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1721"/>
+ <location filename="../src/ui/qgisapp.ui" line="1724"/>
<source>Python Console</source>
<translation>Python-Konsole</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1736"/>
+ <location filename="../src/ui/qgisapp.ui" line="1739"/>
<source>Stretch Histogram to Full Dataset</source>
<translation>Histogramm auf den ganzen Datensatz strecken</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1759"/>
+ <location filename="../src/ui/qgisapp.ui" line="1762"/>
<source>Customization...</source>
<translation>Anpassungen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1767"/>
+ <location filename="../src/ui/qgisapp.ui" line="1770"/>
<source>This is here just to avoid shortcut conflicts, the shortcut is caught in QgsCustomization</source>
<translation>Dies ist nur hier um widersprüchliche Kürzel zu vermeiden, das Kürzel wird in QgsCustomization abgefangen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1770"/>
+ <location filename="../src/ui/qgisapp.ui" line="1773"/>
<source>Ctrl+M</source>
<translation>Strg+M</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1775"/>
+ <location filename="../src/ui/qgisapp.ui" line="1778"/>
<source>Embed Layers and Groups...</source>
<translation>Eingebettete Layer und Gruppen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1778"/>
+ <location filename="../src/ui/qgisapp.ui" line="1781"/>
<source>Embed layers and groups from other project files</source>
<translation>Eingebettete Layer und Gruppe aus anderen Projektdateien</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1787"/>
+ <location filename="../src/ui/qgisapp.ui" line="1790"/>
<source>&Copyright Label</source>
<translation>&Urheberrechtshinweis</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1790"/>
+ <location filename="../src/ui/qgisapp.ui" line="1793"/>
<source>Creates a copyright label that is displayed on the map canvas.</source>
<translation>Erzeugt einen Urheberrechtshinweis auf dem Kartenbild.</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1799"/>
+ <location filename="../src/ui/qgisapp.ui" line="1802"/>
<source>&North Arrow</source>
<translation>&Nordpfeil</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1802"/>
+ <location filename="../src/ui/qgisapp.ui" line="1805"/>
<source>"Creates a north arrow that is displayed on the map canvas"</source>
<translation>"Erzeugt einen Nordpfeil und stellt ihn in der Karte dar"</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1811"/>
+ <location filename="../src/ui/qgisapp.ui" line="1814"/>
<source>&Scale Bar</source>
<translation>&Maßstab</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1814"/>
- <location filename="../src/ui/qgisapp.ui" line="1922"/>
+ <location filename="../src/ui/qgisapp.ui" line="1817"/>
+ <location filename="../src/ui/qgisapp.ui" line="1925"/>
<source>Creates a scale bar that is displayed on the map canvas</source>
<translation>Erzeugt eine Maßstabsleiste, die im Kartenbild angezeigt wird</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1823"/>
+ <location filename="../src/ui/qgisapp.ui" line="1826"/>
<source>Add WFS Layer...</source>
<translation>WFS-Layer hinzufügen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1826"/>
+ <location filename="../src/ui/qgisapp.ui" line="1829"/>
<source>Add WFS Layer</source>
<translation>WFS-Layer hinzufügen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1838"/>
+ <location filename="../src/ui/qgisapp.ui" line="1841"/>
<source>Feature Action</source>
<translation>Objektaktion</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1841"/>
+ <location filename="../src/ui/qgisapp.ui" line="1844"/>
<source>Run Feature Action</source>
<translation>Objektaktion ausführen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1850"/>
<location filename="../src/ui/qgisapp.ui" line="1853"/>
+ <location filename="../src/ui/qgisapp.ui" line="1856"/>
<source>Pan Map to Selection</source>
<translation>Karte zu gewählten Objekten verschieben</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1868"/>
+ <location filename="../src/ui/qgisapp.ui" line="1871"/>
<source>Touch zoom and pan</source>
<translation>Zoomen und Verschieben durch Berührung</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1880"/>
+ <location filename="../src/ui/qgisapp.ui" line="1883"/>
<source>Offset Curve</source>
<translation>Linie versetzen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1889"/>
+ <location filename="../src/ui/qgisapp.ui" line="1892"/>
<source>Copy style</source>
<translation>Stil kopieren</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1898"/>
+ <location filename="../src/ui/qgisapp.ui" line="1901"/>
<source>Paste style</source>
<translation>Stil einfügen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1907"/>
+ <location filename="../src/ui/qgisapp.ui" line="1910"/>
<source>Add WCS Layer...</source>
<translation>WCS-Layer hinzufügen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1916"/>
+ <location filename="../src/ui/qgisapp.ui" line="1919"/>
<source>&Grid</source>
<translation>&Gitter</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1919"/>
+ <location filename="../src/ui/qgisapp.ui" line="1922"/>
<source>Grid</source>
<translation>Gitter</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1964"/>
<location filename="../src/ui/qgisapp.ui" line="1967"/>
+ <location filename="../src/ui/qgisapp.ui" line="1970"/>
<source>New Blank Project</source>
<translation>Neues leeres Projekt</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1976"/>
+ <location filename="../src/ui/qgisapp.ui" line="1979"/>
<source>Local Cumulative Cut Stretch</source>
<translation>Lokale kommulative Schnittstreckung</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1979"/>
+ <location filename="../src/ui/qgisapp.ui" line="1982"/>
<source>Local cumulative cut stretch using current extent, default limits and estimated values.</source>
<translation>Lokale kommulative Schnittstreckung mit aktueller Ausdehnung, Vorgabegrenzen und geschätzten Werten.</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1988"/>
+ <location filename="../src/ui/qgisapp.ui" line="1991"/>
<source>Full Dataset Cumulative Cut Stretch</source>
<translation>Kommulative Schnittstreckung über Gesamtdatensatz</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1991"/>
+ <location filename="../src/ui/qgisapp.ui" line="1994"/>
<source>Cumulative cut stretch using full dataset extent, default limits and estimated values.</source>
<translation>Kommulative Schnittstreckung über gesamten Datensatzausdehnung, Vorgabegrenzen und geschätzten Werten.</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2033"/>
<location filename="../src/ui/qgisapp.ui" line="2036"/>
+ <location filename="../src/ui/qgisapp.ui" line="2039"/>
<source>Duplicate Layer(s)</source>
<translation>Layer duplizieren</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2057"/>
<location filename="../src/ui/qgisapp.ui" line="2060"/>
+ <location filename="../src/ui/qgisapp.ui" line="2063"/>
<source>Save for All Layers</source>
<translation>Alle Layer speichern</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2072"/>
<location filename="../src/ui/qgisapp.ui" line="2075"/>
+ <location filename="../src/ui/qgisapp.ui" line="2078"/>
<source>Rollback for All Layers</source>
<translation>Alle Layeränderungen verwerfen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2087"/>
<location filename="../src/ui/qgisapp.ui" line="2090"/>
+ <location filename="../src/ui/qgisapp.ui" line="2093"/>
<source>Cancel for All Layers</source>
<translation>Abbruch für alle Layer</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2102"/>
<location filename="../src/ui/qgisapp.ui" line="2105"/>
+ <location filename="../src/ui/qgisapp.ui" line="2108"/>
<source>Rollback for Selected Layer(s)</source>
<translation>Verwerfen für gewählte Layer</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2117"/>
<location filename="../src/ui/qgisapp.ui" line="2120"/>
+ <location filename="../src/ui/qgisapp.ui" line="2123"/>
<source>Current Edits</source>
<translation>Aktuelle Änderungen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2132"/>
<location filename="../src/ui/qgisapp.ui" line="2135"/>
+ <location filename="../src/ui/qgisapp.ui" line="2138"/>
<source>Cancel for Selected Layer(s)</source>
<translation>Abbruch für gewählte Layer</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2147"/>
<location filename="../src/ui/qgisapp.ui" line="2150"/>
+ <location filename="../src/ui/qgisapp.ui" line="2153"/>
<source>Save Layer Edits</source>
<translation>Layeränderungen speichern</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2162"/>
<location filename="../src/ui/qgisapp.ui" line="2165"/>
+ <location filename="../src/ui/qgisapp.ui" line="2168"/>
<source>Rotate Feature(s)</source>
<translation>Objekt(e) drehen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2228"/>
+ <location filename="../src/ui/qgisapp.ui" line="2231"/>
<source>Select features using an expression</source>
<translation>Objekte über Ausdruck wählen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2266"/>
+ <location filename="../src/ui/qgisapp.ui" line="2269"/>
<source>Add/Edit Virtual Layer...</source>
<translation>Virtuellen Layer hinzufügen/bearbeiten...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2269"/>
+ <location filename="../src/ui/qgisapp.ui" line="2272"/>
<source>Add/Edit Virtual Layer</source>
<translation>Virtuellen Layer hinzufügen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2290"/>
+ <location filename="../src/ui/qgisapp.ui" line="2293"/>
<source>DXF Export...</source>
<translation>DXF-Export...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2302"/>
<location filename="../src/ui/qgisapp.ui" line="2305"/>
+ <location filename="../src/ui/qgisapp.ui" line="2308"/>
<source>Fill Ring</source>
<translation>Ring füllen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2520"/>
+ <location filename="../src/ui/qgisapp.ui" line="2523"/>
<source>Add Arc&GIS MapServer Layer...</source>
<translation>ArcGIS-MapServer-Layer hinzufügen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2523"/>
+ <location filename="../src/ui/qgisapp.ui" line="2526"/>
<source>Add ArcGIS MapServer Layer</source>
<translation>ArcGIS-MapServer-Layer hinzufügen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2532"/>
+ <location filename="../src/ui/qgisapp.ui" line="2535"/>
<source>Add Ar&cGIS FeatureServer Layer...</source>
<translation>Ar&cGIS-FeatureServer-Layer hinzufügen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2535"/>
+ <location filename="../src/ui/qgisapp.ui" line="2538"/>
<source>Add ArcGIS FeatureServer Layer</source>
<translation>ArcGIS-FeatureServer-Layer hinzufügen</translation>
</message>
@@ -14304,38 +14561,37 @@ Strg (Cmd) erhöht um 15 Grad.</translation>
<translation>&Attributtabelle öffnen</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1432"/>
+ <location filename="../src/ui/qgisapp.ui" line="1435"/>
<source>&Save As...</source>
<translation>&Speichern unter...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1465"/>
+ <location filename="../src/ui/qgisapp.ui" line="1468"/>
<source>&Properties...</source>
<translation>Eigenschaften (&P)...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1550"/>
+ <location filename="../src/ui/qgisapp.ui" line="1553"/>
<source>&Project Properties...</source>
<translation>&Projekteigenschaften...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1562"/>
+ <location filename="../src/ui/qgisapp.ui" line="1565"/>
<source>&Options...</source>
<translation>&Optionen...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="1724"/>
+ <location filename="../src/ui/qgisapp.ui" line="1727"/>
<source>Ctrl+Alt+P</source>
<translation>Strg+Alt+P</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2282"/>
- <location filename="../src/ui/qgisapp.ui" line="2405"/>
+ <location filename="../src/ui/qgisapp.ui" line="2408"/>
<source>New Temporary Scratch Layer...</source>
<translation>Neuer Temporärlayer...</translation>
</message>
<message>
- <location filename="../src/ui/qgisapp.ui" line="2408"/>
+ <location filename="../src/ui/qgisapp.ui" line="2411"/>
<source>New temporary scratch layer</source>
<translation>Neuen Temporärlayer anlegen</translation>
</message>
@@ -14414,37 +14670,37 @@ Strg (Cmd) erhöht um 15 Grad.</translation>
<context>
<name>MeanAndStdDevPlot</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1596"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1611"/>
<source>Graphics</source>
<translation>Grafik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1597"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1612"/>
<source>Input table</source>
<translation>Tabelle eingeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1598"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1613"/>
<source>Category name field</source>
<translation>Kategorienamesfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1599"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1614"/>
<source>Mean field</source>
<translation>Durchschnittswert Feld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1600"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1615"/>
<source>StdDev field</source>
<translation>Standardabweichung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1601"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1616"/>
<source>Plot</source>
<translation>Plot</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1595"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1610"/>
<source>Mean and standard deviation plot</source>
<translation>Mittel- und Standardabweichungsplott</translation>
</message>
@@ -14452,32 +14708,32 @@ Strg (Cmd) erhöht um 15 Grad.</translation>
<context>
<name>MeanCoords</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1606"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1621"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1607"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1622"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1608"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1623"/>
<source>Weight field</source>
<translation>Gewichtungsfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1609"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1624"/>
<source>Unique ID field</source>
<translation>Eindeutiges Schlüsselfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1610"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1625"/>
<source>Mean coordinates</source>
<translation>Mittlere Koordinaten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1605"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1620"/>
<source>Mean coordinate(s)</source>
<translation>Mittlere Koordinate(n)</translation>
</message>
@@ -14485,37 +14741,37 @@ Strg (Cmd) erhöht um 15 Grad.</translation>
<context>
<name>Merge</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1615"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1630"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1616"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1631"/>
<source>Layers to merge</source>
<translation>Zusammenzuführende Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1618"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1633"/>
<source>All layers must have same geometry type!</source>
- <translation>Alle Layer müssen den gleichen Geometrietyp haben</translation>
+ <translation>Alle Layer müssen den gleichen Geometrietyp haben!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1619"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1634"/>
<source>{} field in layer {} has different data type than in other layers.</source>
<translation>Feld {} im Layer {} hat einen anderen Datentyp als in anderen Layern.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1620"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1635"/>
<source>Attribute type mismatch</source>
<translation>Attributtyp nicht passend</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1617"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1632"/>
<source>Merged</source>
<translation>Zusammengeführt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1614"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1629"/>
<source>Merge vector layers</source>
<translation>Vektorlayer zusammenführen</translation>
</message>
@@ -14523,35 +14779,63 @@ Strg (Cmd) erhöht um 15 Grad.</translation>
<context>
<name>MergeData</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1624"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1639"/>
<source>Merge LAS Files</source>
<translation>LAS-Dateien zusammenführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1625"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1640"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1626"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1641"/>
<source>Input LAS files</source>
<translation>LAS-Eingabedateien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1627"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1642"/>
<source>Output merged LAS file</source>
<translation>Zusammengefasste LAS-Ausgabedatei</translation>
</message>
</context>
<context>
+ <name>MergeLines</name>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1646"/>
+ <source>Merge lines</source>
+ <translation>Zeilen zusammenführen</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1647"/>
+ <source>Vector geometry tools</source>
+ <translation>Vektorgeometriewerkzeuge</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1648"/>
+ <source>Input layer</source>
+ <translation>Eingabelayer</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1649"/>
+ <source>Merged</source>
+ <translation>Zusammengeführt</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1650"/>
+ <source>Error merging lines</source>
+ <translation>Fehler beim Linienzusammenführen</translation>
+ </message>
+</context>
+<context>
<name>MessageBarProgress</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1631"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1654"/>
<source>Executing algorithm <i>{0}</i></source>
<translation>Führe Algorithmus aus <i>{0}</i></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1632"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1655"/>
<source>Problem executing algorithm</source>
<translation>Problem bei Algorithmus-Ausführung</translation>
</message>
@@ -15001,54 +15285,54 @@ Strg (Cmd) erhöht um 15 Grad.</translation>
<context>
<name>ModelerAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1636"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1659"/>
<source>Model</source>
<translation>Modell</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1637"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1660"/>
<source>Warning</source>
<translation>Warnung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1638"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1661"/>
<source>Parameter %s in algorithm %s in the model is run with default value! Edit the model to make sure that this is correct.</source>
<translation>Parameter %s in Algorithmus %s im Modell wird mit Vorgabewert ausgeführt! Bitte Modell bearbeiten, um sicherzustellen, dass dies richtig ist.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1639"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1662"/>
<source>Wrong value %s for %s %s</source>
<translation>Falscher Wert %s für %s %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1640"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1663"/>
<source>Prepare algorithm: %s</source>
<translation>Bereite Algorithmus vor: %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1641"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1664"/>
<source>Running %s [%i/%i]</source>
<translation>Verarbeite %s [%i/%i]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1642"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1665"/>
<source>OK. Execution took %0.3f ms (%i outputs).</source>
<translation>OK. Ausführung dauerte %0.3f ms (%i Ausgaben).</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1643"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1666"/>
<source>Failed</source>
<translation>Fehlgeschlagen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1644"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1667"/>
<source>Error executing algorithm %s
%s</source>
<translation>Fehler in Algorithmusausführung %s
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1645"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1668"/>
<source>Model processed ok. Executed %i algorithms total</source>
<translation>Modellverarbeitung OK. Ausgeführte Anzahl der Algorithmen: %i</translation>
</message>
@@ -15056,22 +15340,22 @@ Strg (Cmd) erhöht um 15 Grad.</translation>
<context>
<name>ModelerAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1649"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1672"/>
<source>Models folder</source>
<translation>Modellverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1650"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1673"/>
<source>Models</source>
<translation>Modelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1651"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1674"/>
<source>Could not load model %s</source>
<translation>Konnte Modell %s nicht laden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1652"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1675"/>
<source>Could not load model %s
%s</source>
<translation>Konnte Modell nicht laden %s
@@ -15081,153 +15365,153 @@ Strg (Cmd) erhöht um 15 Grad.</translation>
<context>
<name>ModelerDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1656"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1679"/>
<source>Search...</source>
<translation>Suchen...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1657"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1680"/>
<source>[Enter model name here]</source>
<translation>[Modellname]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1658"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1681"/>
<source>[Enter group name here]</source>
<translation>[Gruppenname]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1661"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1684"/>
<source>Empty model</source>
<translation>Leeres Modell</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1663"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1686"/>
<source>Save Model As Image</source>
<translation>Modell als Bild speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1664"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1687"/>
<source>PNG files (*.png *.PNG)</source>
<translation>PNG-Dateien (*.png *.PNG)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1665"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1688"/>
<source>Save Model As Python Script</source>
<translation>Modell als Pythonskript speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1666"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1689"/>
<source>Python files (*.py *.PY)</source>
<translation>Python-Dateien (*.py *.PY)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1667"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1690"/>
<source>Model exported</source>
<translation>Modell exportiert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1668"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1691"/>
<source>Model was correctly exported.</source>
<translation>Modell wurde korrekt exportiert.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1669"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1692"/>
<source>Warning</source>
<translation>Warnung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1670"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1693"/>
<source>Please enter group and model names before saving</source>
<translation>Bitte Gruppen- und Modellnamen vor dem Speichern angeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1671"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1694"/>
<source>Save Model</source>
<translation>Modell speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1672"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1695"/>
<source>Processing models (*.model)</source>
<translation>Verarbeitungsmodelle (*.model)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1673"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1696"/>
<source>I/O error</source>
<translation>E/A-Fehler</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1674"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1697"/>
<source>Unable to save edits. Reason:
%s</source>
<translation>Änderung konnten nicht gespeichert werden. Grund:
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1675"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1698"/>
<source>Can't save model</source>
<translation>Konnte Modell nicht speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1680"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1703"/>
<source>Processing models (*.model *.MODEL)</source>
<translation>Auswertungsmodelle (*.model *.MODEL)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1681"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1704"/>
<source>Could not load model %s
%s</source>
<translation>Konnte Modell %s nicht laden
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1683"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1706"/>
<source>The selected model could not be loaded.
See the log for more information.</source>
<translation>Das gewählte Modell konnte nicht geladen werden.
Mehr Informationen.im Protokoll.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1662"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1685"/>
<source>Model doesn't contains any algorithms and/or parameters and can't be executed</source>
<translation>Model beinhaltet keine Algorithmen und/oder Parameter und kann deshalb nicht ausgeführt werden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1676"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1699"/>
<source>This model can't be saved in its original location (probably you do not have permission to do it). Please, use the 'Save as...' option.</source>
<translation>Dieses Modell kann nicht an seiner ursprünglichen Stelle gespeichert werden (wahrscheinlich haben Sie keine Berechtigung dazu). Bitte 'Speichern als...' verwenden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1677"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1700"/>
<source>Model saved</source>
<translation>Modell gespeichert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1678"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1701"/>
<source>Model was correctly saved.</source>
<translation>Modell wurde korrekt gespeichert.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1679"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1702"/>
<source>Open Model</source>
<translation>Modell öffnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1682"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1705"/>
<source>Could not open model</source>
<translation>Konnte Modell nicht öffnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1684"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1707"/>
<source>Parameters</source>
<translation>Parameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1659"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1682"/>
<source>Unsaved changes</source>
<translation>Ungesicherte Änderungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1660"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1683"/>
<source>There are unsaved changes in model. Continue?</source>
<translation>Ungesicherte Änderung am Modell. Fortfahren?</translation>
</message>
@@ -15235,7 +15519,7 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>ModelerOnlyAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1688"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1711"/>
<source>Modeler-only tools</source>
<translation>Nur-Modellierungswerkzeuge</translation>
</message>
@@ -15243,157 +15527,157 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>ModelerParameterDefinitionDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1692"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1715"/>
<source>Parameter definition</source>
<translation>Parameter Definitionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1693"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1716"/>
<source>Parameter name</source>
<translation>Parameter Namen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1694"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1717"/>
<source>Checked</source>
<translation>Überprüft</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1695"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1718"/>
<source>Parent layer</source>
<translation>Übergeordneter Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1717"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1740"/>
<source>Required</source>
<translation>Erforderlich</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1718"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1741"/>
<source>Yes</source>
<translation>Ja</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1719"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1742"/>
<source>No</source>
<translation>Nein</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1700"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1723"/>
<source>Shape type</source>
<translation>Shape Typ</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1696"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1719"/>
<source>Allowed data type</source>
<translation>Erlaubter Datentyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1697"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1720"/>
<source>Any</source>
<translation>Jeder</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1698"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1721"/>
<source>Number</source>
<translation>Number</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1699"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1722"/>
<source>String</source>
<translation>Zeichenkette</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1701"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1724"/>
<source>Point</source>
<translation>Punkt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1702"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1725"/>
<source>Line</source>
<translation>Linie</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1703"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1726"/>
<source>Polygon</source>
<translation>Polygon</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1704"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1727"/>
<source>Data type</source>
<translation>Daten Typ</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1705"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1728"/>
<source>Vector (any)</source>
<translation>Vector (jeder)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1706"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1729"/>
<source>Vector (point)</source>
<translation>Vector (Punkt)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1707"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1730"/>
<source>Vector (line)</source>
<translation>Vektor (Linie)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1708"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1731"/>
<source>Vector (polygon)</source>
<translation>Vektor (Polygon)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1709"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1732"/>
<source>Raster</source>
<translation>Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1710"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1733"/>
<source>Table</source>
<translation>Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1711"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1734"/>
<source>Min/Max values</source>
<translation>Min/Max Werte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1712"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1735"/>
<source>Default value</source>
<translation>Vorgabewert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1713"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1736"/>
<source>0</source>
<translation>0</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1714"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1737"/>
<source>Type</source>
<translation>Typ</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1715"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1738"/>
<source>File</source>
<translation>Datei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1716"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1739"/>
<source>Folder</source>
<translation>Ordner</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1720"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1743"/>
<source>Unable to define parameter</source>
<translation>Nicht in der Lage Parameter zu definieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1721"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1744"/>
<source>Invalid parameter name</source>
<translation>Ungültiger Parameter Name</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1722"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1745"/>
<source>Wrong or missing parameter values</source>
<translation>Falsche oder fehlende Parameterwerte</translation>
</message>
@@ -15401,57 +15685,57 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>ModelerParametersDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1726"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1749"/>
<source>Description</source>
<translation>Beschreibung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1727"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1750"/>
<source>Show advanced parameters</source>
<translation>Zeige erweiterte Parameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1728"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1751"/>
<source>(xmin, xmax, ymin, ymax)</source>
<translation> (xmin, xmax, ymin, ymax)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1729"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1752"/>
<source>(x, y)</source>
<translation>(x, y)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1730"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1753"/>
<source>Parent algorithms</source>
<translation>Übergeordneter Algorithmus</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1731"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1754"/>
<source>Parameters</source>
<translation>Parameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1732"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1755"/>
<source><p>Downloading algorithm help... Please wait.</p></source>
<translation><p>Algorithmenhilfe wird heruntergeladen... Bitte warten.</p></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1733"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1756"/>
<source><h2>No help available for this algorithm</h2></source>
<translation><h2>Keine Hilfe für diesen Algorithmus verfügbar.</h2></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1734"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1757"/>
<source><h2>No help available for this algorithm</h2><p>{}</p></source>
<translation><h2>Keine Hilfe für diesen Algorithmus verfügbar.</h2><p>{}</p></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1735"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1758"/>
<source>Hide advanced parameters</source>
<translation>Verstecke erweiterte Parameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1736"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1759"/>
<source>'%s' from algorithm '%s'</source>
<translation>'%s' von Algorithmus '%s'</translation>
</message>
@@ -15459,7 +15743,7 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>MultilineTextPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1740"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1763"/>
<source>[Use text below]</source>
<translation>[Benutze Text unterhalb]</translation>
</message>
@@ -15467,22 +15751,22 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>MultipartToSingleparts</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1745"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1768"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1746"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1769"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1747"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1770"/>
<source>Single parts</source>
<translation>Einzelteile</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1744"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1767"/>
<source>Multipart to singleparts</source>
<translation>Mehr- zu einteilig</translation>
</message>
@@ -15490,7 +15774,7 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>MultipleDirectorySelector</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1751"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1774"/>
<source>...</source>
<translation>...</translation>
</message>
@@ -15498,27 +15782,27 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>MultipleFileInputDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1759"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1782"/>
<source>All files (*.*)</source>
<translation>Alle Dateien (*.*)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1755"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1778"/>
<source>Add file</source>
<translation>Datei hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1756"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1779"/>
<source>Remove file(s)</source>
<translation>Datei(en) entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1757"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1780"/>
<source>Remove all</source>
<translation>Alle entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1758"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1781"/>
<source>Select file(s)</source>
<translation>Datei(en) wählen</translation>
</message>
@@ -15526,17 +15810,17 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>MultipleInputDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1763"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1786"/>
<source>Select all</source>
<translation>Alle wählen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1764"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1787"/>
<source>Clear selection</source>
<translation>Auswahl aufheben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1765"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1788"/>
<source>Toggle selection</source>
<translation>Auswahl umschalten</translation>
</message>
@@ -15544,12 +15828,12 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>MultipleInputPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1769"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1792"/>
<source>0 elements selected</source>
<translation>0 Elemente ausgewählt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1770"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1793"/>
<source>%d elements selected</source>
<translation>%d Elemente ausgewählt</translation>
</message>
@@ -15557,47 +15841,47 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>NearestNeighbourAnalysis</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1775"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1798"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1776"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1799"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1777"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1800"/>
<source>Nearest neighbour</source>
<translation>Nächster Nachbar</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1778"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1801"/>
<source>Observed mean distance</source>
<translation>Beobachtete mittlere Distanz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1779"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1802"/>
<source>Expected mean distance</source>
<translation>Erwartete mittlere Distanz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1780"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1803"/>
<source>Nearest neighbour index</source>
<translation>Nächster Nachbar Index</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1781"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1804"/>
<source>Number of points</source>
<translation>Anzahl von Punkten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1782"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1805"/>
<source>Z-Score</source>
<translation>Z-Wertung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1774"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1797"/>
<source>Nearest neighbour analysis</source>
<translation>Nächster Nachbaranalyse</translation>
</message>
@@ -15646,7 +15930,7 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>NewPreconfiguredAlgorithmAction</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1786"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1809"/>
<source>Create preconfigured algorithm</source>
<translation>Vorkonfigurierten Algorithmus anlegen</translation>
</message>
@@ -15654,7 +15938,7 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>NotSupportedDbType</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="437"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="467"/>
<source>%s is not supported yet</source>
<translation>%s ist noch nicht unterstützt</translation>
</message>
@@ -15662,87 +15946,87 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>NumberInputDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1790"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1813"/>
<source>[Enter your formula here]</source>
<translation>[Formel hier eingeben]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1791"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1814"/>
<source>Values from data layers extents</source>
<translation>Werte aus den Layerausmaßen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1792"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1815"/>
<source>Min X</source>
<translation>Min X</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1793"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1816"/>
<source>Max X</source>
<translation>Max X</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1794"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1817"/>
<source>Min Y</source>
<translation>Min Y</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1795"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1818"/>
<source>Max Y</source>
<translation>Max Y</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1796"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1819"/>
<source>Cellsize</source>
<translation>Zellengröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1797"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1820"/>
<source>Values from raster layers statistics</source>
<translation>Werte aus Rasterlayerstatistik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1798"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1821"/>
<source>Mean</source>
<translation>Durchschnitt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1799"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1822"/>
<source>Std. deviation</source>
<translation>Std.-abweichung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1800"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1823"/>
<source>Max value</source>
<translation>Max. Wert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1801"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1824"/>
<source>Min value</source>
<translation>Min. Wert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1802"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1825"/>
<source>Values from QGIS map canvas</source>
<translation>Werte aus QGIS-Kartefenster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1803"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1826"/>
<source>Current extent</source>
<translation>Aktuelle Ausmaße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1804"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1827"/>
<source>Full extent of all layers in map canvas</source>
<translation>Volles Ausmaß aller Layer der Karte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1805"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1828"/>
<source>Wrong expression</source>
<translation>Falscher Ausdruck</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1806"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1829"/>
<source>The expression entered is not correct</source>
<translation>Der eingegebene Ausdruck ist ungültig</translation>
</message>
@@ -15750,7 +16034,7 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>NumberInputPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1810"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1833"/>
<source>Expression based input</source>
<translation>Ausdrucksbasierte Eingabe</translation>
</message>
@@ -15758,19 +16042,19 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>OTBAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1814"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1837"/>
<source>Could not open OTB algorithm: %s
%s</source>
<translation>Kann OTB-Algorithmus nicht öffnen: %s
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1815"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1838"/>
<source>OTB execution command</source>
<translation>OTB-Befehlsausführung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1816"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1839"/>
<source>Adapter for %s not found</source>
<translation>Adapter für %s nicht gefunden</translation>
</message>
@@ -15778,49 +16062,49 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>OTBAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1821"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1844"/>
<source>Problem with OTB installation: OTB was not found or is not correctly installed</source>
<translation>Problem mit OTB-Installation: OTB wurde nicht gefunden oder ist nicht richtig installiert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1822"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1845"/>
<source>Problem with OTB installation: installed OTB version (%s) is not supported</source>
<translation>Problem mit OTB-Installation: Installierte OTB-Version (%s) wird nicht unterstützt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1823"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1846"/>
<source>Could not open OTB algorithm: %s</source>
<translation>Konnte OTB-Algorithmus nicht öffnen: %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1824"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1847"/>
<source>Could not open OTB algorithm: %s
%s</source>
<translation>Kann OTB-Algorithmus nicht öffnen: %s
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1825"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1848"/>
<source>OTB command line tools folder</source>
<translation>OTB Kommandozeilen Werkzeuge Ordner</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1826"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1849"/>
<source>OTB applications folder</source>
<translation>OTB Anwendungsordner</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1827"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1850"/>
<source>SRTM tiles folder</source>
<translation>SRTM Kachel Ordner</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1828"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1851"/>
<source>Geoid file</source>
<translation>Geoid Datei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1820"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1843"/>
<source>Orfeo Toolbox (Image analysis)</source>
<translation>Orfeo Toolbox (Bildanalyse)</translation>
</message>
@@ -15828,32 +16112,32 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>Ogr2Ogr</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1833"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1856"/>
<source>[OGR] Conversion</source>
<translation>[OGR] Konvertierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1834"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1857"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1835"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1858"/>
<source>Destination Format</source>
<translation>Zielformat</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1836"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1859"/>
<source>Creation options</source>
<translation>Erzeugungsoptionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1837"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1860"/>
<source>Converted</source>
<translation>Umgewandelt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1832"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1855"/>
<source>Convert format</source>
<translation>Format konvertieren</translation>
</message>
@@ -15861,52 +16145,52 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>Ogr2OgrBuffer</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1842"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1865"/>
<source>[OGR] Geoprocessing</source>
<translation>[OGR] Geoverarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1843"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1866"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1844"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1867"/>
<source>Geometry column name ("geometry" for Shapefiles, may be different for other formats)</source>
<translation>Geometriespaltenname ("geometry" bei Shapedateien, kann bei anderen Formaten abweichen)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1845"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1868"/>
<source>Buffer distance</source>
<translation>Pufferabstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1846"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1869"/>
<source>Dissolve all results</source>
<translation>Alle Ergebnisse auflösen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1847"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1870"/>
<source>Dissolve by attribute</source>
<translation>Nach Attribute auflösen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1848"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1871"/>
<source>Output as singlepart geometries (only used when dissolving by attribute)</source>
<translation>Als einteilige Geometrien ausgaben (wird nur verwendet, wenn nach Attribute aufgelöst wird)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1849"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1872"/>
<source>Additional creation options (see ogr2ogr manual)</source>
<translation>Zusätzliche Erzeugungsoptionen (siehe ogr2ogr-Handbuch)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1850"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1873"/>
<source>Buffer</source>
<translation>Puffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1841"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1864"/>
<source>Buffer vectors</source>
<translation>Vektoren puffern</translation>
</message>
@@ -15914,32 +16198,32 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>Ogr2OgrClip</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1855"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1878"/>
<source>[OGR] Geoprocessing</source>
<translation>[OGR] Geoverarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1856"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1879"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1857"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1880"/>
<source>Clip layer</source>
<translation>Layer zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1858"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1881"/>
<source>Additional creation options</source>
<translation>Zusätzliche Erzeugungsoptionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1859"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1882"/>
<source>Clipped (polygon)</source>
<translation>Abgeschnitten (Polygon)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1854"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1877"/>
<source>Clip vectors by polygon</source>
<translation>Vektoren durch Polygon zuschneiden</translation>
</message>
@@ -15947,32 +16231,32 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>Ogr2OgrClipExtent</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1864"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1887"/>
<source>[OGR] Geoprocessing</source>
<translation>[OGR] Geoverarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1865"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1888"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1866"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1889"/>
<source>Clip extent</source>
<translation>Grenzen zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1867"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1890"/>
<source>Additional creation options</source>
<translation>Zusätzliche Erzeugungsoptionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1868"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1891"/>
<source>Clipped (extent)</source>
<translation>Abgeschnitten (Grenze)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1863"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1886"/>
<source>Clip vectors by extent</source>
<translation>Vektoren auf Ausmaße zuschneiden</translation>
</message>
@@ -15980,67 +16264,67 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>Ogr2OgrDissolve</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1873"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1896"/>
<source>[OGR] Geoprocessing</source>
<translation>[OGR] Geoverarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1874"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1897"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1875"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1898"/>
<source>Geometry column name ("geometry" for Shapefiles, may be different for other formats)</source>
<translation>Geometriespaltename ("geometry" für Shapedatei, kann bei anderen Formaten abweichen)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1876"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1899"/>
<source>Dissolve field</source>
<translation>Auflösungsfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1877"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1900"/>
<source>Output as multipart geometries</source>
<translation>Ausgabe als mehrteilige Geometrien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1878"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1901"/>
<source>Keep input attributes</source>
<translation>Eingabeattribute beibehalten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1879"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1902"/>
<source>Count dissolved features</source>
<translation>Aufgelöste Objekte zählen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1880"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1903"/>
<source>Compute area and perimeter of dissolved features</source>
<translation>Fläche und Umfang der aufgelösten Objekte berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1881"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1904"/>
<source>Compute min/max/sum/mean for the following numeric attribute</source>
<translation>Min/Max/Summe/Durchschnitt der folgenden nummerischen Attribute berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1882"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1905"/>
<source>Numeric attribute to compute dissolved features stats</source>
<translation>Nummerische Attribute um Statistik zu ausgelösten Objekten zu berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1883"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1906"/>
<source>Additional creation options (see ogr2ogr manual)</source>
<translation>Zusätzliche Erzeugungsoptionen (siehe ogr2ogr-Handbuch)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1884"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1907"/>
<source>Dissolved</source>
<translation>Aufgelöst</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1872"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1895"/>
<source>Dissolve polygons</source>
<translation>Polygone auflösen</translation>
</message>
@@ -16048,62 +16332,62 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>Ogr2OgrOneSideBuffer</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1889"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1912"/>
<source>[OGR] Geoprocessing</source>
<translation>[OGR] Geoverarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1890"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1913"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1891"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1914"/>
<source>Operation</source>
<translation>Operation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1892"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1915"/>
<source>Geometry column name ("geometry" for Shapefiles, may be different for other formats)</source>
<translation>Geometriespaltename ("geometry" für Shapedatei, kann bei anderen Formaten abweichen)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1893"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1916"/>
<source>Buffer distance</source>
<translation>Pufferabstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1894"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1917"/>
<source>Buffer side</source>
<translation>Pufferseite</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1895"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1918"/>
<source>Dissolve all results</source>
<translation>Alle Ergebnisse auflösen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1896"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1919"/>
<source>Dissolve by attribute</source>
<translation>Nach Attribute auflösen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1897"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1920"/>
<source>Output as singlepart geometries (only used when dissolving by attribute)</source>
<translation>Als einteilige Geometrien ausgaben (wird nur verwendet, wenn nach Attribute aufgelöst wird)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1898"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1921"/>
<source>Additional creation options (see ogr2ogr manual)</source>
<translation>Zusätzliche Erzeugungsoptionen (siehe ogr2ogr-Handbuch)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1899"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1922"/>
<source>Single sided buffer</source>
<translation>Doppelseitiger Puffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1888"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1911"/>
<source>Single sided buffers (and offset lines) for lines</source>
<translation>Einseitige Puffer (und Versatzlinien) für Linien</translation>
</message>
@@ -16111,37 +16395,37 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>Ogr2OgrPointsOnLines</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1904"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1927"/>
<source>[OGR] Geoprocessing</source>
<translation>[OGR] Geoverarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1905"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1928"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1906"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1929"/>
<source>Geometry column name ("geometry" for Shapefiles, may be different for other formats)</source>
<translation>Geometriespaltename ("geometry" für Shapedatei, kann bei anderen Formaten abweichen)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1907"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1930"/>
<source>Distance from line start represented as fraction of line length</source>
<translation>Abstand vom Linienanfang als Bruchteil der Linienlänge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1908"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1931"/>
<source>Additional creation options (see ogr2ogr manual)</source>
<translation>Zusätzliche Erzeugungsoptionen (siehe ogr2ogr-Handbuch)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1909"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1932"/>
<source>Points along lines</source>
<translation>Punkte entlang Linien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1903"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1926"/>
<source>Create points along lines</source>
<translation>Punkte entlang von Linien erzeugen</translation>
</message>
@@ -16149,92 +16433,92 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>Ogr2OgrTableToPostGisList</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1915"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1938"/>
<source>Database (connection name)</source>
<translation>Datenbank (Verbindungsname)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1916"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1939"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1917"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1940"/>
<source>Shape encoding</source>
<translation>Shapekodierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1918"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1941"/>
<source>Schema name</source>
<translation>Schemaname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1919"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1942"/>
<source>Table name, leave blank to use input name</source>
<translation>Tabellenname, leer lassen um Eingabenamen zu verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1920"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1943"/>
<source>Primary key</source>
<translation>Primärschlüssel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1921"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1944"/>
<source>Primary key (existing field, used if the above option is left empty)</source>
<translation>Primärschlüssel (vorhandene Feld, wird genutzt, wenn obige Option leergelassen wird)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1923"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1946"/>
<source>Group N features per transaction (Default: 20000)</source>
<translation>n Objekte je Transaktion gruppieren (Voreinstellung: 20000)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1924"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1947"/>
<source>Overwrite existing table</source>
<translation>Vorhandene Tabelle überschreiben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1925"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1948"/>
<source>Append to existing table</source>
<translation>An vorhandene Tabelle anhängen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1926"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1949"/>
<source>Append and add new fields to existing table</source>
<translation>Anhängen und neue Felder zu vorhandener Tabelle hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1927"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1950"/>
<source>Do not launder columns/table names</source>
<translation>Spalten/Tabellennamen nicht bereinigen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1928"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1951"/>
<source>Continue after a failure, skipping the failed record</source>
<translation>Nach Fehler fortsetzen und fehlerhaften Datensatz überspringen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1929"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1952"/>
<source>Keep width and precision of input attributes</source>
<translation>Breite und Genauigkeit der Eingabeattribute beibehalten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1930"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1953"/>
<source>Additional creation options</source>
<translation>Zusätzliche Erzeugungsoptionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1913"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1936"/>
<source>Import layer/table as geometryless table into PostgreSQL database</source>
<translation>Layer/Tabelle als geometrielose Tabelle in PostgreSQL importieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1914"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1937"/>
<source>[OGR] Miscellaneous</source>
<translation>[OGR] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1922"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1945"/>
<source>Select features using a SQL "WHERE" statement (Ex: column='value')</source>
<translation>Objekte mit SQL "Where"-Klausel auswählen (Bsp: column='value')</translation>
</message>
@@ -16242,172 +16526,172 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>Ogr2OgrToPostGis</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1936"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1959"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1937"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1960"/>
<source>Shape encoding</source>
<translation>Shapekodierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1938"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1961"/>
<source>Output geometry type</source>
<translation>Ausgabegeometrietyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1942"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1965"/>
<source>Host</source>
<translation>Host</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1943"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1966"/>
<source>Port</source>
<translation>Port</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1944"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1967"/>
<source>Username</source>
<translation>Benutzername</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1945"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1968"/>
<source>Database name</source>
<translation>Datenbankname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1946"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1969"/>
<source>Password</source>
<translation>Passwort</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1947"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1970"/>
<source>Schema name</source>
<translation>Schemaname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1948"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1971"/>
<source>Table name, leave blank to use input name</source>
<translation>Tabellenname, leer lassen um Eingabenamen zu verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1951"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1974"/>
<source>Geometry column name</source>
<translation>Geometriespalte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1952"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1975"/>
<source>Vector dimensions</source>
<translation>Vektordimensionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1953"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1976"/>
<source>Distance tolerance for simplification</source>
<translation>Abstandstoleranz für Vereinfachung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1954"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1977"/>
<source>Maximum distance between 2 nodes (densification)</source>
<translation>Maximaler Abstand zwischen zwei Knoten (Verdichtung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1955"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1978"/>
<source>Select features by extent (defined in input layer CRS)</source>
<translation>Wähle Objekte nach Ausdehnung (definiert in Eingabelayer KBS)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1956"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1979"/>
<source>Clip the input layer using the above (rectangle) extent</source>
<translation>Eingabelayer auf obige (rechteckigen) Grenzen zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1958"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1981"/>
<source>Group N features per transaction (Default: 20000)</source>
<translation>n Objekte je Transaktion gruppieren (Voreinstellung: 20000)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1959"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1982"/>
<source>Overwrite existing table</source>
<translation>Vorhandene Tabelle überschreiben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1960"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1983"/>
<source>Append to existing table</source>
<translation>An vorhandene Tabelle anhängen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1961"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1984"/>
<source>Append and add new fields to existing table</source>
<translation>Anhängen und neue Felder zu vorhandener Tabelle hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1962"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1985"/>
<source>Do not launder columns/table names</source>
<translation>Spalten/Tabellennamen nicht bereinigen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1963"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1986"/>
<source>Do not create spatial index</source>
<translation>Keinen räumlichen Index erstellen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1964"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1987"/>
<source>Continue after a failure, skipping the failed feature</source>
<translation>Nach Fehler fortsetzen und fehlerhaftes Objekt überspringen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1967"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1990"/>
<source>Additional creation options</source>
<translation>Zusätzliche Erzeugungsoptionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1934"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1957"/>
<source>Import Vector into PostGIS database (new connection)</source>
<translation>Vektor in PostGIS-Datenbank importieren (neue Verbindung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1935"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1958"/>
<source>[OGR] Miscellaneous</source>
<translation>[OGR] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1939"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1962"/>
<source>Assign an output CRS</source>
<translation>Ein Ausgabe-KBS zuweisen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1940"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1963"/>
<source>Reproject to this CRS on output </source>
<translation>Bei Ausgabe auf dieses KBS reprojizieren </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1941"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1964"/>
<source>Override source CRS</source>
<translation>Quell-KBS überschreiben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1949"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1972"/>
<source>Primary key (new field)</source>
<translation>Primärschlüssel (neues Feld)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1950"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1973"/>
<source>Primary key (existing field, used if the above option is left empty)</source>
<translation>Primärschlüssel (vorhandenes Feld, wird verwendet, wenn obige Option leer gelassen wird)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1965"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1988"/>
<source>Promote to Multipart</source>
<translation>In Mehrteilige umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1966"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1989"/>
<source>Keep width and precision of input attributes</source>
<translation>Breite und Genauigkeit der Eingabeattribute beibehalten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1957"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1980"/>
<source>Select features using a SQL "WHERE" statement (Ex: column='value')</source>
<translation>Objekte mit SQL "Where"-Klausel auswählen (Bsp: column='value')</translation>
</message>
@@ -16415,152 +16699,152 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>Ogr2OgrToPostGisList</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1973"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1996"/>
<source>Database (connection name)</source>
<translation>Datenbank (Verbindungsname)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1974"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1997"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1975"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1998"/>
<source>Shape encoding</source>
<translation>Shapekodierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1976"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1999"/>
<source>Output geometry type</source>
<translation>Ausgabegeometrietyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1980"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2003"/>
<source>Schema name</source>
<translation>Schemaname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1981"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2004"/>
<source>Table name, leave blank to use input name</source>
<translation>Tabellenname, leer lassen um Eingabenamen zu verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1984"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2007"/>
<source>Geometry column name</source>
<translation>Geometriespalte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1985"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2008"/>
<source>Vector dimensions</source>
<translation>Vektordimensionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1986"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2009"/>
<source>Distance tolerance for simplification</source>
<translation>Abstandstoleranz für Vereinfachung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1987"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2010"/>
<source>Maximum distance between 2 nodes (densification)</source>
<translation>Maximaler Abstand zwischen zwei Knoten (Verdichtung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1988"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2011"/>
<source>Select features by extent (defined in input layer CRS)</source>
<translation>Wähle Objekte nach Ausdehnung (definiert in Eingabelayer KBS)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1989"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2012"/>
<source>Clip the input layer using the above (rectangle) extent</source>
<translation>Eingabelayer auf obige (rechteckigen) Grenzen zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1991"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2014"/>
<source>Group N features per transaction (Default: 20000)</source>
<translation>n Objekte je Transaktion gruppieren (Voreinstellung: 20000)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1992"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2015"/>
<source>Overwrite existing table</source>
<translation>Vorhandene Tabelle überschreiben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1993"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2016"/>
<source>Append to existing table</source>
<translation>An vorhandene Tabelle anhängen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1994"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2017"/>
<source>Append and add new fields to existing table</source>
<translation>Anhängen und neue Felder zu vorhandener Tabelle hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1995"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2018"/>
<source>Do not launder columns/table names</source>
<translation>Spalten/Tabellennamen nicht bereinigen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1996"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2019"/>
<source>Do not create spatial index</source>
<translation>Keinen räumlichen Index erstellen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1997"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2020"/>
<source>Continue after a failure, skipping the failed feature</source>
<translation>Nach Fehler fortsetzen und fehlerhaftes Objekt überspringen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2000"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2023"/>
<source>Additional creation options</source>
<translation>Zusätzliche Erzeugungsoptionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1971"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1994"/>
<source>Import Vector into PostGIS database (available connections)</source>
<translation>Vektor in PostGIS-Datenbank importieren (vorhandene Verbindungen)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1972"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="1995"/>
<source>[OGR] Miscellaneous</source>
<translation>[OGR] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1977"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2000"/>
<source>Assign an output CRS</source>
<translation>Ein Ausgabe-KBS zuweisen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1978"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2001"/>
<source>Reproject to this CRS on output </source>
<translation>Bei Ausgabe auf dieses KBS reprojizieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1979"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2002"/>
<source>Override source CRS</source>
<translation>Quell-CRS überschreiben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1982"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2005"/>
<source>Primary key (new field)</source>
<translation>Primärschlüssel (Neues Feld)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1983"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2006"/>
<source>Primary key (existing field, used if the above option is left empty)</source>
<translation>Primärschlüssel (vorhandene Feld, wird genutzt, wenn obige Option leergelassen wird)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1998"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2021"/>
<source>Promote to Multipart</source>
<translation>In mehrteilige umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1999"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2022"/>
<source>Keep width and precision of input attributes</source>
<translation>Breite und Genauigkeit der Eingabeattribute beibehalten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="1990"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2013"/>
<source>Select features using a SQL "WHERE" statement (Ex: column='value')</source>
<translation>Objekte mit SQL "Where"-Klausel auswählen (Bsp: column='value')</translation>
</message>
@@ -16568,27 +16852,27 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>OgrInfo</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2005"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2028"/>
<source>[OGR] Miscellaneous</source>
<translation>[OGR] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2006"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2029"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2007"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2030"/>
<source>Summary output only</source>
<translation>Nur Zusammenfassung ausgeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2008"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2031"/>
<source>Layer information</source>
<translation>Layerinformation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2004"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2027"/>
<source>Information</source>
<translation>Information</translation>
</message>
@@ -16596,37 +16880,37 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>OgrSql</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2012"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2035"/>
<source>Execute SQL</source>
<translation>SQL-Anweisung ausführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2013"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2036"/>
<source>[OGR] Miscellaneous</source>
<translation>[OGR] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2014"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2037"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2015"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2038"/>
<source>SQL</source>
<translation>SQL</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2016"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2039"/>
<source>Dialect</source>
<translation>Dialekt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2017"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2040"/>
<source>SQL result</source>
<translation>SQL-Ergebnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2018"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2041"/>
<source>Empty SQL. Please enter valid SQL expression and try again.</source>
<translation>Leerer SQL-Ausdruck. Bitte einen gültigen SQL-Ausdruck eingeben und wiederholen.</translation>
</message>
@@ -16634,12 +16918,12 @@ Mehr Informationen.im Protokoll.</translation>
<context>
<name>OpenViewerAction</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2022"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2045"/>
<source>Unable to open viewer</source>
<translation>Konnte Anzeige nicht öffnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2023"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2046"/>
<source>The current Fusion folder does not contain the viewer executable.
Please check the configuration in the Processing settings dialog.</source>
<translation>Das aktuelle Fusion-Verzeichnis enthält das Anzeigeprogramm nicht.
@@ -16687,7 +16971,7 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>OracleDBPlugin</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="441"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="471"/>
<source>There is no defined database connection "{}".</source>
<translation>Keine Datenbankverbindung "{}" definiert.</translation>
</message>
@@ -16718,37 +17002,37 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>OrientedMinimumBoundingBox</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2027"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2050"/>
<source>Oriented minimum bounding box</source>
<translation>Minimaler gerichteter Umgrenzungsrahmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2028"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2051"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2029"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2052"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2030"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2053"/>
<source>Calculate OMBB for each feature separately</source>
<translation>Minimaler gerichteter Umgrenzungsrahmen für jedes Objekt einzeln berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2031"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2054"/>
<source>Oriented_MBBox</source>
<translation>Minimale orientierte Umrandungsgrenze</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2032"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2055"/>
<source>Can't calculate an OMBB for each point, it's a point. The number of points must be greater than 2</source>
<translation>Kann MOUG für jeden Punkt nicht berechnen. es ist ein Punkt. Die Anzahl der Punkt muß größer als 2 sein</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2033"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2056"/>
<source>Can't calculate an OMBB for feature {0}.</source>
<translation>Kann MOUG für Objekt {0} nicht bestimmen.</translation>
</message>
@@ -16756,12 +17040,12 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>OutputFile</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2037"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2060"/>
<source>All files(*.*)</source>
<translation>Alle Dateien (*.*)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2038"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2061"/>
<source>%s files(*.%s)</source>
<translation>%s Dateien(*.%s)</translation>
</message>
@@ -16769,7 +17053,7 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>OutputHTML</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2042"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2065"/>
<source>HTML files(*.html)</source>
<translation>HTML Dateien (*.html)</translation>
</message>
@@ -16777,7 +17061,7 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>OutputRaster</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2046"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2069"/>
<source>%s files (*.%s)</source>
<translation>%s Dateien (*.%s)</translation>
</message>
@@ -16785,57 +17069,66 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>OutputSelectionPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2050"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2073"/>
<source>[Save to temporary file]</source>
<translation>[In temporärer Datei speichern]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2051"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2074"/>
+ <source>[Create temporary layer]</source>
+ <translation>[Temporärlayer erzeugen]</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2075"/>
+ <source>Create temporary layer</source>
+ <translation>Temporärlayer erzeugen</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2076"/>
<source>Save to a temporary file</source>
<translation>In temporärer Datei speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2052"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2077"/>
<source>Save to file...</source>
<translation>In Datei speichern...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2053"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2078"/>
<source>Use expression...</source>
<translation>Ausdruck verwenden...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2054"/>
<source>Save to memory layer</source>
- <translation>In Memory-Layer speichern</translation>
+ <translation type="obsolete">In Memory-Layer speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2055"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2079"/>
<source>Save to Spatialite table...</source>
<translation>In Spatialite-Tabelle speichern...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2056"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2080"/>
<source>Save to PostGIS table...</source>
<translation>In PostGIS-Tabelle speichern...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2057"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2081"/>
<source>Expression based output</source>
<translation>Ausdrucksbasierte Ausgabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2058"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2082"/>
<source>Save Spatialite</source>
<translation>Speichere Spatialite</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2059"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2083"/>
<source>Save file</source>
<translation>Datei speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2060"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2084"/>
<source>Select directory</source>
<translation>Verzeichnis wählen</translation>
</message>
@@ -16843,7 +17136,7 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>OutputVector</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2064"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2088"/>
<source>%s files (*.%s)</source>
<translation>%s Dateien (*.%s)</translation>
</message>
@@ -16851,35 +17144,35 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PGDatabase</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="445"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="475"/>
<source>&Table</source>
<translation>&Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="446"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="476"/>
<source>Run &Vacuum Analyze</source>
<translation>&VACUUM ANALYZE ausführen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="447"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="477"/>
<source>Run &Refresh Materialized View</source>
<translation>Materialisierte Sicht aktualisie&ren</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="448"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="478"/>
<source>Select a table for vacuum analyze.</source>
<translation>Auszuräumende und zu analysierende Tabelle wählen.</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="449"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="479"/>
<source>Select a materialized view for refresh.</source>
- <translation>Materialisierte Sicht zur Aktualisierung wählen</translation>
+ <translation>Materialisierte Sicht zur Aktualisierung wählen.</translation>
</message>
</context>
<context>
<name>PGTable</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="453"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="483"/>
<source>Table rule</source>
<translation>Tabellenregel</translation>
</message>
@@ -16887,12 +17180,12 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>ParameterMultipleInput</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2068"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2092"/>
<source>All files (*.*)</source>
<translation>Alle Dateien (*.*)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2069"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2093"/>
<source>%s files(*.%s)</source>
<translation>%s Dateien (*.%s)</translation>
</message>
@@ -16900,7 +17193,7 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>ParameterRaster</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2073"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2097"/>
<source>%s files(*.%s)</source>
<translation>%s Dateien (*.%s)</translation>
</message>
@@ -16908,7 +17201,7 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>ParameterTable</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2077"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2101"/>
<source>%s files(*.%s)</source>
<translation>%s Dateien (*.%s)</translation>
</message>
@@ -16916,7 +17209,7 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>ParameterVector</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2081"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2105"/>
<source>%s files(*.%s)</source>
<translation>%s Dateien (*.%s)</translation>
</message>
@@ -16924,37 +17217,37 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>ParametersPanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2085"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2109"/>
<source>[Not selected]</source>
<translation>[nicht gewählt]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2087"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2111"/>
<source> (x, y)</source>
<translation> (x, y)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2088"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2112"/>
<source> [optional]</source>
<translation> [optional]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2089"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2113"/>
<source>Iterate over this layer</source>
<translation>Iteriere über diesen Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2090"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2114"/>
<source>Open output file after running algorithm</source>
<translation>Öffne Ausgabedatei nach erfolgreicher Ausführung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2091"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2115"/>
<source>[not set]</source>
<translation>[nicht gesetzt]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2086"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2110"/>
<source> (xmin, xmax, ymin, ymax)</source>
<translation> (xmin, xmax, ymin, ymax)</translation>
</message>
@@ -16962,42 +17255,42 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PeukerDouglas</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2095"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2119"/>
<source>Peuker Douglas</source>
<translation>Peuker-Douglas</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2096"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2120"/>
<source>Stream Network Analysis tools</source>
<translation>Stromnetzwerkanalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2097"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2121"/>
<source>Elevation Grid</source>
<translation>Höhen Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2098"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2122"/>
<source>Center Smoothing Weight</source>
<translation>Glättungsgewichtung Mitte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2099"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2123"/>
<source>Side Smoothing Weight</source>
<translation>Seitenglättungsgewichtung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2100"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2124"/>
<source>Diagonal Smoothing Weight</source>
<translation>Diagonale Glättungsgewichtung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2101"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2125"/>
<source>Stream Source Grid</source>
<translation>Strom Quellennetz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2102"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2126"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -17005,42 +17298,42 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PeukerDouglasMulti</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2106"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2130"/>
<source>Peuker Douglas (multifile)</source>
<translation>Peuker-Douglas (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2107"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2131"/>
<source>Stream Network Analysis tools</source>
<translation>Stromnetzwerkanalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2108"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2132"/>
<source>Elevation Grid</source>
<translation>Höhen Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2109"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2133"/>
<source>Center Smoothing Weight</source>
<translation>Glättungsgewichtung Mitte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2110"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2134"/>
<source>Side Smoothing Weight</source>
<translation>Seitenglättungsgewichtung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2111"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2135"/>
<source>Diagonal Smoothing Weight</source>
<translation>Diagonale Glättungsgewichtung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2112"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2136"/>
<source>Stream Source Grid</source>
<translation>Strom Quellennetz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2113"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2137"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -17048,90 +17341,118 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PointDistance</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2118"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2142"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2119"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2143"/>
<source>Linear (N*k x 3) distance matrix</source>
<translation>Lineare (N*k x 3) Distanzmatrix</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2120"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2144"/>
<source>Standard (N x T) distance matrix</source>
<translation>Standard (N x T) Distanzmatrix</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2121"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2145"/>
<source>Summary distance matrix (mean, std. dev., min, max)</source>
<translation>Zusammenfassende Distanzmatrix (mtl, std.abw., min, max.)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2122"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2146"/>
<source>Input point layer</source>
<translation>Eingabepunktlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2123"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2147"/>
<source>Input unique ID field</source>
<translation>Eindeutiges Schlüsselfeld der Eingabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2124"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2148"/>
<source>Target point layer</source>
<translation>Zielpunktlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2125"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2149"/>
<source>Target unique ID field</source>
<translation>Eindeutiges Schlüsselfeld des Ziels</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2126"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2150"/>
<source>Output matrix type</source>
<translation>Typ der Ausgabematrix</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2127"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2151"/>
<source>Use only the nearest (k) target points</source>
<translation>Nur (k) nächste Zielpunkte verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2117"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2141"/>
<source>Distance matrix</source>
<translation>Distanzmatrix</translation>
</message>
</context>
<context>
+ <name>PointOnSurface</name>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2155"/>
+ <source>Point on surface</source>
+ <translation>Punkt auf Oberfläche</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2156"/>
+ <source>Vector geometry tools</source>
+ <translation>Vektorgeometriewerkzeuge</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2157"/>
+ <source>Input layer</source>
+ <translation>Eingabelayer</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2158"/>
+ <source>Point</source>
+ <translation>Punkt</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2159"/>
+ <source>Error calculating point on surface</source>
+ <translation>Fehler bei Berechnung des Punkts auf Oberfläche</translation>
+ </message>
+</context>
+<context>
<name>PointsDisplacement</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2132"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2164"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2133"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2165"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2134"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2166"/>
<source>Displacement distance</source>
<translation>Verlagerungsdistanz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2135"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2167"/>
<source>Horizontal distribution for two point case</source>
<translation>Horizontale Verteilung für Zweipunktefall</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2136"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2168"/>
<source>Displaced</source>
<translation>Versetzt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2131"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2163"/>
<source>Points displacement</source>
<translation>Punktversatz</translation>
</message>
@@ -17139,27 +17460,27 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PointsFromLines</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2141"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2173"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2142"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2174"/>
<source>Raster layer</source>
<translation>Rasterlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2143"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2175"/>
<source>Vector layer</source>
<translation>Vektorlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2144"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2176"/>
<source>Points along line</source>
<translation>Punkte entlang Linie</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2140"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2172"/>
<source>Generate points (pixel centroids) along line</source>
<translation>Punkte (Pixelzentren) entlang einer Linie erzeugen</translation>
</message>
@@ -17167,27 +17488,27 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PointsFromPolygons</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2149"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2181"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2150"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2182"/>
<source>Raster layer</source>
<translation>Rasterlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2151"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2183"/>
<source>Vector layer</source>
<translation>Vektorlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2152"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2184"/>
<source>Points from polygons</source>
<translation>Punkte aus Polygonen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2148"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2180"/>
<source>Generate points (pixel centroids) inside polygons</source>
<translation>Punkte (Pixelzentren) in Polygonen erzeugen</translation>
</message>
@@ -17195,32 +17516,32 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PointsInPolygon</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2157"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2189"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2158"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2190"/>
<source>Polygons</source>
<translation>Polygone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2159"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2191"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2160"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2192"/>
<source>Count field name</source>
<translation>Zählfeldname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2161"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2193"/>
<source>Count</source>
<translation>Anzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2156"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2188"/>
<source>Count points in polygon</source>
<translation>Punkte in Polygon zählen</translation>
</message>
@@ -17228,37 +17549,37 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PointsInPolygonUnique</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2166"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2198"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2167"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2199"/>
<source>Polygons</source>
<translation>Polygone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2168"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2200"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2169"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2201"/>
<source>Class field</source>
<translation>Klassenfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2170"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2202"/>
<source>Count field name</source>
<translation>Zählfeldname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2171"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2203"/>
<source>Unique count</source>
<translation>Eindeutige Anzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2165"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2197"/>
<source>Count unique points in polygon</source>
<translation>Eindeutige Punkte in Polygon zählen</translation>
</message>
@@ -17266,37 +17587,37 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PointsInPolygonWeighted</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2176"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2208"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2177"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2209"/>
<source>Polygons</source>
<translation>Polygone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2178"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2210"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2179"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2211"/>
<source>Weight field</source>
<translation>Gewichtungsfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2180"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2212"/>
<source>Count field name</source>
<translation>Zählfeldname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2181"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2213"/>
<source>Weighted count</source>
<translation>Gewichtete Anzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2175"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2207"/>
<source>Count points in polygon(weighted)</source>
<translation>Punkte in Polygon zählen (gewichtet)</translation>
</message>
@@ -17304,37 +17625,37 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PointsLayerFromTable</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2186"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2218"/>
<source>Vector creation tools</source>
<translation>Vektorerzeugungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2187"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2219"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2188"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2220"/>
<source>X field</source>
<translation>X-Feld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2189"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2221"/>
<source>Y field</source>
<translation>Y-Feld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2190"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2222"/>
<source>Target CRS</source>
<translation>Ziel KBS</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2191"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2223"/>
<source>Points from table</source>
<translation>Punkte aus Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2185"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2217"/>
<source>Points layer from table</source>
<translation>Punktlayer aus Tabelle</translation>
</message>
@@ -17342,42 +17663,42 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PointsToPaths</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2196"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2228"/>
<source>Vector creation tools</source>
<translation>Vektorerzeugungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2197"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2229"/>
<source>Input point layer</source>
<translation>Eingabepunktlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2198"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2230"/>
<source>Group field</source>
<translation>Gruppierungsfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2199"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2231"/>
<source>Order field</source>
<translation>Sortierungsfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2200"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2232"/>
<source>Date format (if order field is DateTime)</source>
<translation>Datumsformat (wenn Sortierungsfeld DateTime ist)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2201"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2233"/>
<source>Paths</source>
<translation>Pfade</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2202"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2234"/>
<source>Directory</source>
<translation>Verzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2195"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2227"/>
<source>Points to path</source>
<translation>Punkte zu Weg</translation>
</message>
@@ -17385,27 +17706,27 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PolarPlot</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2207"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2239"/>
<source>Graphics</source>
<translation>Grafik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2208"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2240"/>
<source>Input table</source>
<translation>Tabelle eingeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2209"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2241"/>
<source>Category name field</source>
<translation>Kategorienamesfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2210"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2242"/>
<source>Value field</source>
<translation>Wertfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2206"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2238"/>
<source>Polar plot</source>
<translation>Polarplot</translation>
</message>
@@ -17413,42 +17734,42 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PolyClipData</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2217"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2249"/>
<source>Mask layer</source>
<translation>Maskenlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2216"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2248"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2214"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2246"/>
<source>Poly Clip Data</source>
<translation>Poly-Daten zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2215"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2247"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2218"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2250"/>
<source>Output clipped LAS file</source>
<translation>Zugeschnittene LAS-Datei ausgeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2219"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2251"/>
<source>Use Shape attribute</source>
<translation>Shapeattribut nutzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2220"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2252"/>
<source>Shape field index</source>
<translation>Shapefeldindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2221"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2253"/>
<source>Shape value</source>
<translation>Shapewert</translation>
</message>
@@ -17456,52 +17777,52 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>Polygonize</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2231"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2263"/>
<source>Processing lines...</source>
<translation>Verarbeite Linien...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2232"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2264"/>
<source>Noding lines...</source>
<translation>Bestimme Knoten in Linien...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2233"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2265"/>
<source>Polygonizing...</source>
<translation>Polygonisiert...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2234"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2266"/>
<source>No polygons were created!</source>
<translation>Es wurden keine Polygone erzeugt!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2226"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2258"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2227"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2259"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2228"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2260"/>
<source>Keep table structure of line layer</source>
<translation>Tabellenstruktur des Linienlayers beibehalten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2229"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2261"/>
<source>Create geometry columns</source>
<translation>Geometriespalten erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2230"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2262"/>
<source>Polygons from lines</source>
<translation>Polygone aus Linien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2225"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2257"/>
<source>Polygonize</source>
<translation>Polygonbildung</translation>
</message>
@@ -17509,22 +17830,22 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PolygonsToLines</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2239"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2271"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2240"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2272"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2241"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2273"/>
<source>Lines from polygons</source>
<translation>Linien aus Polygonen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2238"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2270"/>
<source>Polygons to lines</source>
<translation>Polygone zu Linien</translation>
</message>
@@ -17532,24 +17853,24 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PostGISExecuteSQL</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2248"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2280"/>
<source>Error executing SQL:
%s</source>
<translation>Fehler bei SQL-Ausführung:
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2246"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2278"/>
<source>Database</source>
<translation>Datenbank</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2247"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2279"/>
<source>SQL query</source>
<translation>SQL-Abfrage</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2245"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2277"/>
<source>PostGIS execute SQL</source>
<translation>PostGIS-SQL-Ausführen</translation>
</message>
@@ -17557,7 +17878,7 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PostGisDBPlugin</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="457"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="487"/>
<source>There is no defined database connection "%s".</source>
<translation>Keine Datenbankverbindung "%s" definiert.</translation>
</message>
@@ -17565,7 +17886,7 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>Postprocessing</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2252"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2284"/>
<source>Loading resulting layers</source>
<translation>Lade Ergebnis Layer</translation>
</message>
@@ -17573,22 +17894,22 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PreconfiguredAlgorithmDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2256"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2288"/>
<source>OK</source>
<translation>OK</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2257"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2289"/>
<source>Unable to execute algorithm</source>
<translation>Konnte Algorithmus nicht ausführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2258"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2290"/>
<source><b>Missing parameter value: %s</b></source>
<translation><b>Fehlender Parameterwert: %s</b></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2259"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2291"/>
<source>Wrong or missing parameter values</source>
<translation>Falsche oder fehlende Parameterwerte</translation>
</message>
@@ -17596,7 +17917,7 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>PreconfiguredAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2263"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2295"/>
<source>Preconfigured algorithms</source>
<translation>Vorkonfigurierte Algorithmen</translation>
</message>
@@ -17617,75 +17938,75 @@ Bitte die Processing-Einstellung überprüfen.</translation>
<context>
<name>Processing</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2267"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2299"/>
<source>Could not load provider: %s
%s</source>
<translation>Konnte Datenanbieter nicht laden: %s
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2268"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2300"/>
<source>Error: Algorithm {0} not found
</source>
<translation>Fehler: Algorithmus {0} nicht gefunden
</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2269"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2301"/>
<source>Processing</source>
<translation>Verarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2270"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2302"/>
<source>Error: Wrong parameter value {0} for parameter {1}.</source>
<translation>Fehler: Falscher Wert {0} für Parameter {1}.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2271"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2303"/>
<source>Error in %s. Wrong parameter value %s for parameter %s.</source>
<translation>Fehler in %s. Falscher Parameterwert %s für Parameter %s.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2272"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2304"/>
<source>Error: Missing parameter value for parameter {0}.</source>
<translation>Fehler: Fehlender Wert für Parameter {0}.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2273"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2305"/>
<source>Error in %s. Missing parameter value for parameter %s.</source>
<translation>Fehler in %s. Fehlender Parameterwert for Parameter %s.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2274"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2306"/>
<source>Error: Wrong number of parameters</source>
<translation>Fehler: Falsche Parameteranzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2275"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2307"/>
<source>Error: Wrong parameter value: </source>
<translation>Fehler: Falscher Parameterwert:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2276"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2308"/>
<source>Error: Wrong output value: </source>
<translation>Fehler: Falscher Ausgabewert:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2277"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2309"/>
<source>Unable to execute algorithm
{0}</source>
<translation>Kann Algorithmus nicht ausführen
{0}</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2278"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2310"/>
<source>Warning: Not all input layers use the same CRS.
This can cause unexpected results.</source>
<translation>Warnung: Nicht alle Eingabelayer verwenden das gleiche KBS.
Dies kann zu unerwarteten Ergebnissen führen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2279"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2311"/>
<source>There were errors executing the algorithm.</source>
<translation>Fehler bei der Ausführung des Algorithmus.</translation>
</message>
@@ -17694,37 +18015,37 @@ Dies kann zu unerwarteten Ergebnissen führen.</translation>
<translation type="obsolete">Vekt&or</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2280"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2312"/>
<source>&Analysis Tools</source>
<translation>&Analyse-Werkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2281"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2313"/>
<source>&Research Tools</source>
<translation>&Forschungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2282"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2314"/>
<source>&Geoprocessing Tools</source>
<translation>&Geoverarbeitungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2283"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2315"/>
<source>G&eometry Tools</source>
<translation>G&eometrie-Werkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2284"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2316"/>
<source>&Data Management Tools</source>
<translation>&Datenmanagement-Werkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2285"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2317"/>
<source>Missing dependency</source>
<translation>Fehlende Abhängigkeit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2286"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2318"/>
<source><h3>Missing dependency. This algorithm cannot be run :-( </h3>
%s</source>
<translation><h3>Fehlende Abhängigkeiten. Dieser Algorithmus kann nicht ausgeführt werden :-( </h3>
@@ -17734,97 +18055,102 @@ Dies kann zu unerwarteten Ergebnissen führen.</translation>
<context>
<name>ProcessingConfig</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2290"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2322"/>
<source>General</source>
<translation>Allgemein</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2291"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2323"/>
<source>Show extra info in Log panel</source>
<translation>Zeige Extrainformation im Log Panel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2292"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2324"/>
<source>Keep dialog open after running an algorithm</source>
<translation>Behalte Dialog nach Abschluss des Algorithmus offen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2293"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2325"/>
<source>Use only selected features</source>
<translation>Nur gewählte Objekte nutzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2294"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2326"/>
<source>Use filename as layer name</source>
<translation>Benutze Dateinamen als Layernamen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2295"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2327"/>
<source>Show recently executed algorithms</source>
<translation>Zeige zuletzt ausgeführte Algorithmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2296"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2328"/>
<source>Show tooltip when there are disabled providers</source>
<translation>Tooltip anzeigen, wenn es abgeschaltete Anbieter gibt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2297"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2329"/>
<source>Output folder</source>
<translation>Ausgabeverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2298"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2330"/>
<source>Show layer CRS definition in selection boxes</source>
<translation>Zeige Layer Koordinatensystem in Auswahlboxen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2299"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2331"/>
<source>Warn before executing if layer CRS's do not match</source>
<translation>Zeige Warnung wenn Layer Koordinatensysteme nicht übereinstimmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2300"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2332"/>
+ <source>Warn before executing if extent CRS might not match layers CRS</source>
+ <translation>Vor Ausführung warnen, wenn Grenz-KBS nicht mit den Layer-KBS übereinstimmen könnte</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2333"/>
<source>Style for raster layers</source>
<translation>Stil für Rasterlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2301"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2334"/>
<source>Style for point layers</source>
<translation>Stil für Punktlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2302"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2335"/>
<source>Style for line layers</source>
<translation>Stil für Linienlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2303"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2336"/>
<source>Style for polygon layers</source>
<translation>Stil für Polygonlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2304"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2337"/>
<source>Pre-execution script</source>
<translation>Skript zur Ausführung vor dem Run</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2305"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2338"/>
<source>Post-execution script</source>
<translation>Skript zur Ausführung nach dem Run</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2306"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2339"/>
<source>Recent algs</source>
<translation>Kürzliche verwendete Algorithmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2307"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2340"/>
<source>Default output vector layer extension</source>
<translation>Erweiterungsvoreingestellung für Vektorlayerausgaben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2308"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2341"/>
<source>Default output raster layer extension</source>
<translation>Erweiterungsvoreingestellung für Rasterlayerausgaben</translation>
</message>
@@ -17832,7 +18158,7 @@ Dies kann zu unerwarteten Ergebnissen führen.</translation>
<context>
<name>ProcessingLog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2312"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2345"/>
<source>Processing</source>
<translation>Verarbeitung</translation>
</message>
@@ -17840,106 +18166,110 @@ Dies kann zu unerwarteten Ergebnissen führen.</translation>
<context>
<name>ProcessingPlugin</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2316"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2349"/>
<source>Pro&cessing</source>
<translation>&Verarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2317"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2350"/>
<source>&Toolbox</source>
<translation>&Werkzeugkiste</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2318"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2351"/>
<source>Graphical &Modeler...</source>
<translation>Grafische &Modellierung...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2319"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2352"/>
<source>&History...</source>
<translation>&Historie...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2320"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2353"/>
<source>&Options...</source>
<translation>&Optionen...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2321"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2354"/>
<source>&Results Viewer...</source>
<translation>&Ergebnisanzeige...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2322"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2355"/>
<source>&Commander</source>
<translation>&Commander</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2323"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2356"/>
+ <source>Ctrl+Alt+D</source>
+ <translation>Strg+Alt+D</translation>
+ </message>
+ <message>
<source>Ctrl+Alt+M</source>
- <translation>Strg+Alt+M</translation>
+ <translation type="obsolete">Strg+Alt+M</translation>
</message>
</context>
<context>
<name>ProcessingToolbox</name>
<message>
<location filename="../python/plugins/processing/ui/ProcessingToolbox.ui" line="14"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2327"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2360"/>
<source>Processing Toolbox</source>
<translation>Verarbeitungswerkzeuge</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/ProcessingToolbox.ui" line="27"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2328"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2361"/>
<source>Enter algorithm name to filter list</source>
<translation>Algorithmenname eingeben, um Liste zu filtern</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/ProcessingToolbox.ui" line="61"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2329"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2362"/>
<source>There are disabled providers that contain algorithms including your text string. Click <a href="view">to view them.</a></source>
- <translation>Es gibt deaktivierte Anbieter, die passende Algorithmen enthalten (siehe <a href="view">Anzeige</a>).</translation>
+ <translation>Es gibt deaktivierte Anbieter, die passende Algorithmen enthalten (siehe <a href="view">Anzeige</a>)</translation>
</message>
<message>
<location filename="../python/plugins/processing/ui/ProcessingToolbox.ui" line="84"/>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2330"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2363"/>
<source><html><head/><body><p>You can add more algorithms to the toolbox, <a href="enable"><span style=" text-decoration: underline; color:#0000ff;">enable additional providers.</span></a> <a href="close"><span style=" text-decoration: underline; color:#0000ff;">[close]</span></a></p></body></html></source>
<translation><html><head/><body><p>Durch <a href="enable"><span style=" text-decoration: underline; color:#0000ff;">Einschalten weiterer Anbieter</span> können der Werkzeugleiste mehr Algorithmen hinzugefügt werden.</a> <a href="close"><span style=" text-decoration: underline; color:#0000ff;">[schließen]</span></a></p></body>< [...]
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2331"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2364"/>
<source>Search...</source>
<translation>Suchen...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2332"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2365"/>
<source>Execute</source>
<translation>Ausführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2333"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2366"/>
<source>Execute as batch process</source>
<translation>Als Stapelprozeß ausführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2334"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2367"/>
<source>Edit rendering styles for outputs</source>
<translation>Darstellungsstile zur Ausgabe bearbeiten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2335"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2368"/>
<source>Error executing algorithm</source>
<translation>Fehler bei Algorithmenausführung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2336"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2369"/>
<source><h3>This algorithm cannot be run :-( </h3>
%s</source>
<translation><h3>Dieser Algorithmus kann nicht ausgeführt werden run :-( </h3>
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2337"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2370"/>
<source>Recently used algorithms</source>
<translation>Zuletzt verwendete Algorithmen</translation>
</message>
@@ -17997,7 +18327,7 @@ Dies kann zu unerwarteten Ergebnissen führen.</translation>
<translation>Stacktrace</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2341"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2374"/>
<location filename="../python/python-i18n.cpp" line="30"/>
<source>View message log</source>
<translation>Protokoll anzeigen</translation>
@@ -18472,7 +18802,7 @@ QGIS-API ist über iface zu benutzen. Geben Sie help(iface) ein, um mehr Informa
<context>
<name>QGISAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2345"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2378"/>
<source>QGIS geoalgorithms</source>
<translation>QGIS-Geo-Algorithmen</translation>
</message>
@@ -18626,27 +18956,27 @@ QGIS-API ist über iface zu benutzen. Geben Sie help(iface) ein, um mehr Informa
<translation>Schätze Normalenableitungen...</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11889"/>
+ <location filename="../src/app/qgisapp.cpp" line="11906"/>
<source>minidump written to %1</source>
<translation>Minidump in %1 geschrieben</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11893"/>
+ <location filename="../src/app/qgisapp.cpp" line="11910"/>
<source>writing of minidump to %1 failed (%2)</source>
<translation>Speichern des Minidumps in %1 gescheitert (%2)</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11900"/>
+ <location filename="../src/app/qgisapp.cpp" line="11917"/>
<source>creation of minidump to %1 failed (%2)</source>
<translation>Erzeugung des Minidump in %1 gescheitert (%2)</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11903"/>
+ <location filename="../src/app/qgisapp.cpp" line="11920"/>
<source>Crash dumped</source>
<translation>Absturz abgebildet</translation>
</message>
<message>
- <location filename="../src/app/main.cpp" line="766"/>
+ <location filename="../src/app/main.cpp" line="785"/>
<source>QGIS starting in non-interactive mode not supported.
You are seeing this message most likely because you have no DISPLAY environment variable set.
</source>
@@ -18793,7 +19123,7 @@ Fehler(%2): %3</translation>
<message>
<location filename="../src/core/qgscoordinatereferencesystem.cpp" line="1400"/>
<location filename="../src/core/qgscoordinatereferencesystem.cpp" line="1509"/>
- <location filename="../src/core/qgsvectorlayerrenderer.cpp" line="216"/>
+ <location filename="../src/core/qgsvectorlayerrenderer.cpp" line="214"/>
<source>CRS</source>
<translation>KBS</translation>
</message>
@@ -18804,7 +19134,7 @@ Fehler(%2): %3</translation>
<location filename="../src/core/qgsdistancearea.cpp" line="237"/>
<location filename="../src/providers/grass/qgsgrassgislib.cpp" line="231"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="3341"/>
- <location filename="../src/server/qgssldconfigparser.cpp" line="1696"/>
+ <location filename="../src/server/qgssldconfigparser.cpp" line="1705"/>
<source>Generated CRS</source>
<comment>A CRS automatically generated from layer info get this prefix for description</comment>
<translation>Erzeugtes KBS</translation>
@@ -19002,164 +19332,164 @@ Fehler(%2): %3</translation>
<translation> nm²</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="197"/>
+ <location filename="../src/core/qgsexpression.cpp" line="199"/>
<source>Cannot convert '%1' to double</source>
<translation>Kann '%1' nicht in Fließkommazahl umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="213"/>
+ <location filename="../src/core/qgsexpression.cpp" line="215"/>
<source>Cannot convert '%1' to int</source>
<translation>Kann '%1' nicht in Ganzzahl umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="233"/>
+ <location filename="../src/core/qgsexpression.cpp" line="235"/>
<source>Cannot convert '%1' to DateTime</source>
<translation>Kann '%1' nicht in DateTime umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="247"/>
+ <location filename="../src/core/qgsexpression.cpp" line="249"/>
<source>Cannot convert '%1' to Date</source>
<translation>Kann '%1' nicht in Datum umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="261"/>
+ <location filename="../src/core/qgsexpression.cpp" line="263"/>
<source>Cannot convert '%1' to Time</source>
<translation>Kann '%1' nicht in Zeit umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="278"/>
+ <location filename="../src/core/qgsexpression.cpp" line="280"/>
<source>Cannot convert '%1' to Interval</source>
<translation>Kann '%1' nicht in Interval umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="358"/>
+ <location filename="../src/core/qgsexpression.cpp" line="360"/>
<source>Cannot convert '%1' to boolean</source>
<translation>Kann '%1' nicht in Wahrheitswert umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="502"/>
- <location filename="../src/core/qgsexpression.cpp" line="535"/>
+ <location filename="../src/core/qgsexpression.cpp" line="504"/>
+ <location filename="../src/core/qgsexpression.cpp" line="537"/>
<source>Domain max must be greater than domain min</source>
<translation>Bereichsmaxium muß größe als Minimum sein</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="540"/>
+ <location filename="../src/core/qgsexpression.cpp" line="542"/>
<source>Exponent must be greater than 0</source>
<translation>Exponent muß größer als 0 sein</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="606"/>
+ <location filename="../src/core/qgsexpression.cpp" line="608"/>
<source>Cannot find layer with name or ID '%1'</source>
<translation>Kann Layer mit Name oder ID '%1' nicht finden</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="619"/>
- <location filename="../src/core/qgsexpression.cpp" line="728"/>
+ <location filename="../src/core/qgsexpression.cpp" line="621"/>
+ <location filename="../src/core/qgsexpression.cpp" line="730"/>
<source>No such aggregate '%1'</source>
<translation>Kein Aggregat '%1'</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="665"/>
- <location filename="../src/core/qgsexpression.cpp" line="767"/>
- <location filename="../src/core/qgsexpression.cpp" line="851"/>
+ <location filename="../src/core/qgsexpression.cpp" line="667"/>
+ <location filename="../src/core/qgsexpression.cpp" line="769"/>
+ <location filename="../src/core/qgsexpression.cpp" line="853"/>
<source>Could not calculate aggregate for: %1</source>
<translation>Konnte Aggregat nicht berechnen für: %1</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="679"/>
- <location filename="../src/core/qgsexpression.cpp" line="688"/>
+ <location filename="../src/core/qgsexpression.cpp" line="681"/>
+ <location filename="../src/core/qgsexpression.cpp" line="690"/>
<source>Cannot use relation aggregate function in this context</source>
<translation>Beziehungsaggregatfunktion nicht in diesem Zusammenhang verwendbar</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="708"/>
+ <location filename="../src/core/qgsexpression.cpp" line="710"/>
<source>Cannot find relation with id '%1'</source>
<translation>Relation mit ID '%1' nicht gefunden</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="782"/>
- <location filename="../src/core/qgsexpression.cpp" line="791"/>
+ <location filename="../src/core/qgsexpression.cpp" line="784"/>
+ <location filename="../src/core/qgsexpression.cpp" line="793"/>
<source>Cannot use aggregate function in this context</source>
<translation>Aggregatfunktion nicht in diesem Zusammenhang verwendbar</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="1187"/>
- <location filename="../src/core/qgsexpression.cpp" line="1201"/>
- <location filename="../src/core/qgsexpression.cpp" line="1215"/>
+ <location filename="../src/core/qgsexpression.cpp" line="1189"/>
+ <location filename="../src/core/qgsexpression.cpp" line="1203"/>
+ <location filename="../src/core/qgsexpression.cpp" line="1217"/>
<source>Invalid regular expression '%1': %2</source>
<translation>Ungültiger regulärer Ausdruck '%1': %2</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="1679"/>
+ <location filename="../src/core/qgsexpression.cpp" line="1681"/>
<source>Point index is out of range</source>
<translation>Punktindex außerhalb des Bereichs</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="1831"/>
+ <location filename="../src/core/qgsexpression.cpp" line="1861"/>
<source>Function make_point requires 2-4 arguments</source>
<translation>Funktion make_point braucht 2-4 Argumente</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="1892"/>
+ <location filename="../src/core/qgsexpression.cpp" line="1922"/>
<source>Function make_polygon requires an argument</source>
<translation>Funktion make_polygon erfordert ein Argument</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="1932"/>
+ <location filename="../src/core/qgsexpression.cpp" line="1962"/>
<source>Index is out of range</source>
<translation>Index außerhalb des Bereichs</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="2403"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2433"/>
<source>Function `azimuth` requires exactly two parameters. %1 given.</source>
<translation>Funktion `azimuth` erfordert genau zwei Parameter. %1 angegeben.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="2415"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2445"/>
<source>Function `azimuth` requires two points as arguments.</source>
<translation>Funktion `azimuth` erfordert zwei Punkte als Argumente.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="2624"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2700"/>
<source>Number of places must be positive</source>
<translation>Anzahl der Stellen muß positiv sein</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="2645"/>
- <location filename="../src/core/qgsexpression.cpp" line="2717"/>
- <location filename="../src/core/qgsexpression.cpp" line="2757"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2721"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2793"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2833"/>
<source>Cannot convert '%1:%2:%3' to color</source>
<translation>Kann %1:%2:%3 nicht in Farbe umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="2684"/>
- <location filename="../src/core/qgsexpression.cpp" line="2738"/>
- <location filename="../src/core/qgsexpression.cpp" line="2778"/>
- <location filename="../src/core/qgsexpression.cpp" line="2799"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2760"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2814"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2854"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2875"/>
<source>Cannot convert '%1:%2:%3:%4' to color</source>
<translation>Kann %1:%2:%3:%4 nicht in Farbe umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="2696"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2772"/>
<source>"%1" is not a valid color ramp</source>
<translation>"%1" ist kein gültiger Farbverlauf</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="2822"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2898"/>
<source>Cannot convert '%1:%2:%3:%4:%5' to color</source>
<translation>Kann '%1:%2:%3:%4:%5' nicht in Farbe umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="2833"/>
- <location filename="../src/core/qgsexpression.cpp" line="2876"/>
- <location filename="../src/core/qgsexpression.cpp" line="2923"/>
- <location filename="../src/core/qgsexpression.cpp" line="2937"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2909"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2952"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2999"/>
+ <location filename="../src/core/qgsexpression.cpp" line="3013"/>
<source>Cannot convert '%1' to color</source>
<translation>Kann '%1:%2:%3:%4:%5' nicht in Farbe umwandeln</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="2867"/>
- <location filename="../src/core/qgsexpression.cpp" line="2912"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2943"/>
+ <location filename="../src/core/qgsexpression.cpp" line="2988"/>
<source>Unknown color component '%1'</source>
<translation>Unbekannter Farbteil '%1'</translation>
</message>
@@ -19167,18 +19497,18 @@ Fehler(%2): %3</translation>
<location filename="../src/core/geometry/qgsgeos.cpp" line="37"/>
<location filename="../src/core/geometry/qgsgeos.cpp" line="44"/>
<location filename="../src/core/geometry/qgsgeos.cpp" line="857"/>
- <location filename="../src/core/geometry/qgsgeos.cpp" line="1964"/>
- <location filename="../src/core/geometry/qgsgeos.cpp" line="2201"/>
- <location filename="../src/core/pal/feature.cpp" line="1425"/>
- <location filename="../src/core/pal/feature.cpp" line="1444"/>
- <location filename="../src/core/pal/feature.cpp" line="1474"/>
- <location filename="../src/core/pal/feature.cpp" line="1516"/>
+ <location filename="../src/core/geometry/qgsgeos.cpp" line="2013"/>
+ <location filename="../src/core/geometry/qgsgeos.cpp" line="2250"/>
+ <location filename="../src/core/pal/feature.cpp" line="1623"/>
+ <location filename="../src/core/pal/feature.cpp" line="1642"/>
+ <location filename="../src/core/pal/feature.cpp" line="1672"/>
+ <location filename="../src/core/pal/feature.cpp" line="1714"/>
<location filename="../src/core/pal/geomfunction.cpp" line="366"/>
- <location filename="../src/core/pal/labelposition.cpp" line="264"/>
- <location filename="../src/core/pal/labelposition.cpp" line="503"/>
- <location filename="../src/core/pal/labelposition.cpp" line="533"/>
- <location filename="../src/core/pal/labelposition.cpp" line="566"/>
- <location filename="../src/core/pal/labelposition.cpp" line="623"/>
+ <location filename="../src/core/pal/labelposition.cpp" line="247"/>
+ <location filename="../src/core/pal/labelposition.cpp" line="486"/>
+ <location filename="../src/core/pal/labelposition.cpp" line="516"/>
+ <location filename="../src/core/pal/labelposition.cpp" line="549"/>
+ <location filename="../src/core/pal/labelposition.cpp" line="606"/>
<location filename="../src/core/pal/pointset.cpp" line="284"/>
<location filename="../src/core/pal/pointset.cpp" line="764"/>
<location filename="../src/core/pal/pointset.cpp" line="806"/>
@@ -19192,18 +19522,18 @@ Fehler(%2): %3</translation>
<location filename="../src/core/geometry/qgsgeos.cpp" line="857"/>
<location filename="../src/core/geometry/qgsgeos.cpp" line="1523"/>
<location filename="../src/core/geometry/qgsgeos.cpp" line="1583"/>
- <location filename="../src/core/geometry/qgsgeos.cpp" line="1964"/>
- <location filename="../src/core/geometry/qgsgeos.cpp" line="2201"/>
- <location filename="../src/core/pal/feature.cpp" line="1425"/>
- <location filename="../src/core/pal/feature.cpp" line="1444"/>
- <location filename="../src/core/pal/feature.cpp" line="1474"/>
- <location filename="../src/core/pal/feature.cpp" line="1516"/>
+ <location filename="../src/core/geometry/qgsgeos.cpp" line="2013"/>
+ <location filename="../src/core/geometry/qgsgeos.cpp" line="2250"/>
+ <location filename="../src/core/pal/feature.cpp" line="1623"/>
+ <location filename="../src/core/pal/feature.cpp" line="1642"/>
+ <location filename="../src/core/pal/feature.cpp" line="1672"/>
+ <location filename="../src/core/pal/feature.cpp" line="1714"/>
<location filename="../src/core/pal/geomfunction.cpp" line="366"/>
- <location filename="../src/core/pal/labelposition.cpp" line="264"/>
- <location filename="../src/core/pal/labelposition.cpp" line="503"/>
- <location filename="../src/core/pal/labelposition.cpp" line="533"/>
- <location filename="../src/core/pal/labelposition.cpp" line="566"/>
- <location filename="../src/core/pal/labelposition.cpp" line="623"/>
+ <location filename="../src/core/pal/labelposition.cpp" line="247"/>
+ <location filename="../src/core/pal/labelposition.cpp" line="486"/>
+ <location filename="../src/core/pal/labelposition.cpp" line="516"/>
+ <location filename="../src/core/pal/labelposition.cpp" line="549"/>
+ <location filename="../src/core/pal/labelposition.cpp" line="606"/>
<location filename="../src/core/pal/pointset.cpp" line="284"/>
<location filename="../src/core/pal/pointset.cpp" line="764"/>
<location filename="../src/core/pal/pointset.cpp" line="806"/>
@@ -19251,64 +19581,64 @@ Fehler(%2): %3</translation>
</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="158"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="178"/>
<source>segments %1 and %2 of line %3 intersect at %4</source>
<translation>Segmente %1 und %2 der Linie %3 schneiden sich bei %4</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="173"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="193"/>
<source>ring %1 of polygon %2 not in exterior ring</source>
<translation>Ring %1 des Polygons %2 nicht innerhalb des äußeren Rings</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="209"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="229"/>
<source>GEOS error:could not produce geometry for GEOS (check log window)</source>
<translation>GEOS-Fehler: Konnte Geometrie nicht für GEOS erzeugen (Protokollfenster prüfen)</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="226"/>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="234"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="246"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="254"/>
<source>GEOS error:%1</source>
<translation>GEOS-Fehler:%1</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="290"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="310"/>
<source>polygon %1 has no rings</source>
<translation>Polygon %1 hat keine Ringe</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="302"/>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="307"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="322"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="327"/>
<source>polygon %1 inside polygon %2</source>
<translation>Polygon %1 liegt im Polygon %2</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="321"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="341"/>
<source>Unknown geometry type</source>
<translation>Unbekannter Geometrietyp</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="322"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="342"/>
<source>Unknown geometry type %1</source>
<translation>Unbekannter Geometrietyp %1</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="331"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="351"/>
<source>Geometry validation was aborted.</source>
<translation>Geometrieprüfung wurde abgebrochen.</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="335"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="355"/>
<source>Geometry has %1 errors.</source>
<translation>Geometrie hat %1 Fehler.</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="340"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="360"/>
<source>Geometry is valid.</source>
<translation>Geometrie ist gültig.</translation>
</message>
<message>
- <location filename="../src/core/qgsgeometryvalidator.cpp" line="368"/>
+ <location filename="../src/core/qgsgeometryvalidator.cpp" line="388"/>
<source>invalid line</source>
<translation>Ungültige Linie</translation>
</message>
@@ -19383,12 +19713,12 @@ Fehler(%2): %3</translation>
<translation>Keine Datenanbieter</translation>
</message>
<message>
- <location filename="../src/core/qgsproviderregistry.cpp" line="299"/>
+ <location filename="../src/core/qgsproviderregistry.cpp" line="296"/>
<source>No data provider plugins are available. No vector layers can be loaded</source>
<translation>Keine Datenanbietererweiterungen verfügbar. Es können keine Vektorlayer geladen werden</translation>
</message>
<message>
- <location filename="../src/core/qgsproviderregistry.cpp" line="397"/>
+ <location filename="../src/core/qgsproviderregistry.cpp" line="394"/>
<source>Unable to instantiate the data provider plugin %1</source>
<translation>Konnte den Datenanbieter %1 nicht vorbereiten</translation>
</message>
@@ -19418,7 +19748,7 @@ Fehler(%2): %3</translation>
</message>
<message>
<location filename="../src/core/auth/qgsauthmethodregistry.cpp" line="291"/>
- <location filename="../src/core/qgsproviderregistry.cpp" line="383"/>
+ <location filename="../src/core/qgsproviderregistry.cpp" line="380"/>
<source>Failed to load %1: %2</source>
<translation>Konnte %1 nicht laden: %2</translation>
</message>
@@ -19475,15 +19805,15 @@ Fehler(%2): %3</translation>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="2031"/>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="2047"/>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="2080"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="67"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1985"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2492"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2509"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2557"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2583"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2652"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2658"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2676"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="74"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2000"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2507"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2524"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2572"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2598"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2667"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2673"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2691"/>
<source>OGR</source>
<translation>OGR</translation>
</message>
@@ -19542,18 +19872,18 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="629"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1997"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2012"/>
<source>Arc/Info ASCII Coverage</source>
<translation>Arc/Info ASCII Coverage</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="694"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2002"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2017"/>
<source>Atlas BNA</source>
<translation>Atlas BNA</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2007"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2022"/>
<source>Comma Separated Value</source>
<translation>Komma-separierte Werte [CSV]</translation>
</message>
@@ -19564,8 +19894,8 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="839"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2039"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2041"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2054"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2056"/>
<source>FMEObjects Gateway</source>
<translation>FMEObjects Gateway</translation>
</message>
@@ -19651,7 +19981,7 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="866"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2047"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2062"/>
<source>GeoJSON</source>
<translation>GeoJSON</translation>
</message>
@@ -19707,7 +20037,7 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="961"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2052"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2067"/>
<source>GeoRSS</source>
<translation>GeoRSS</translation>
</message>
@@ -19758,7 +20088,7 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1051"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2057"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2072"/>
<source>Geography Markup Language [GML]</source>
<translation>Geography Markup Language [GML]</translation>
</message>
@@ -19789,7 +20119,7 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1110"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2062"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2077"/>
<source>Generic Mapping Tools [GMT]</source>
<translation>Generic Mapping Tools [GMT]</translation>
</message>
@@ -19825,19 +20155,19 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1173"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2067"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2082"/>
<source>GPS eXchange Format [GPX]</source>
<translation>GPS-Austauschformat [GPX]</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1189"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2085"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2100"/>
<source>INTERLIS 1</source>
<translation>INTERLIS 1</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1204"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2090"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2105"/>
<source>INTERLIS 2</source>
<translation>INTERLIS 2</translation>
</message>
@@ -19858,7 +20188,7 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1239"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2099"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2114"/>
<source>Keyhole Markup Language [KML]</source>
<translation>Keyhole Markup Language [KML]</translation>
</message>
@@ -19924,7 +20254,7 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1344"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2109"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2124"/>
<source>Microstation DGN</source>
<translation>Microstation DGN</translation>
</message>
@@ -19965,13 +20295,13 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1416"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2142"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2157"/>
<source>S-57 Base file</source>
<translation>S-57 Base-Datei</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1431"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2148"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2163"/>
<source>Spatial Data Transfer Standard [SDTS]</source>
<translation>Spatial Data Transfer Standard [SDTS]</translation>
</message>
@@ -20062,7 +20392,7 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1614"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2194"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2209"/>
<source>AutoCAD DXF</source>
<translation>AutoCAD DXF</translation>
</message>
@@ -20078,7 +20408,7 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1647"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2189"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2204"/>
<source>Geoconcept</source>
<translation>Geoconcept</translation>
</message>
@@ -20099,7 +20429,7 @@ Nur %1 von %2 Objekten geschrieben.</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1678"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2020"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2035"/>
<source>ESRI FileGDB</source>
<translation>ESRI-FileGDB</translation>
</message>
@@ -20120,23 +20450,23 @@ Nur %1 von %2 Objekten geschrieben.</translation>
<translation>Transformation fehlgeschlagen, Schreiben gestoppt. (Ausnahme %1)</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4197"/>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4218"/>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4243"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4310"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4331"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4356"/>
<location filename="../src/core/qgsvectorlayerimport.cpp" line="66"/>
<source>Unable to load %1 provider</source>
<translation>Kann Datenanbieter %1 nicht laden</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4205"/>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4226"/>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4251"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4318"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4339"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4364"/>
<location filename="../src/core/qgsvectorlayerimport.cpp" line="75"/>
<source>Provider %1 has no %2 method</source>
<translation>Datenanbieter %1 hat keine Methode %2</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4300"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4413"/>
<source>Loaded from Provider</source>
<translation>Aus Datenanbieter geladen</translation>
</message>
@@ -20487,10 +20817,10 @@ Nur %1 von %2 Objekten geschrieben.</translation>
<message>
<location filename="../src/plugins/evis/idtool/eviseventidtool.cpp" line="77"/>
<location filename="../src/plugins/evis/idtool/eviseventidtool.cpp" line="82"/>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="693"/>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="760"/>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="791"/>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="802"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="699"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="766"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="797"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="808"/>
<location filename="../src/providers/grass/qgsgrass.cpp" line="2919"/>
<source>Warning</source>
<translation>Warnung</translation>
@@ -20789,78 +21119,78 @@ Nur %1 von %2 Objekten geschrieben.</translation>
<translation>Eine Erweiterung, um Anzahl, Summen und Mittel von Rastern zu jedem Polygon eines Vektorlayers zu berechnen</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="694"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="700"/>
<source>Cannot open GDAL MEM dataset %1: %2</source>
<translation>Konnte GDAL-MEM-Datensatz %1 nicht öffnen: %2</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="761"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="767"/>
<source>Cannot GDALCreateGenImgProjTransformer: </source>
<translation>GDALCreateGenImgProjTransformer-Fehler: </translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="792"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="798"/>
<source>Cannot inittialize GDALWarpOperation : </source>
<translation>GDALWarpOperation-Initialisierungsfehler: </translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="803"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="809"/>
<source>Cannot ChunkAndWarpImage: %1</source>
<translation>ChungAndWarpImage-Fehler: %1</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="2196"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2317"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="2202"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2332"/>
<source>GDAL/OGR VSIFileHandler</source>
<translation>GDAL/OGR-VSI-Dateihandler</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="2247"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="2253"/>
<source>This raster file has no bands and is invalid as a raster layer.</source>
<translation>Diese Rasterdatei hat keine Kanäle und ist als Rasterlayer ungültig.</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="2580"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="2586"/>
<source>Cannot get GDAL raster band: %1</source>
<translation>Konnte GDAL-Rasterkanal nicht bestimmen: %1</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3040"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3046"/>
<source>Nearest Neighbour</source>
<translation>Nächster Nachbar</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3041"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3047"/>
<source>Average</source>
<translation>Mittel</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3042"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3048"/>
<source>Gauss</source>
<translation>Gauß</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3043"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3049"/>
<source>Cubic</source>
<translation>Kubisch</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3045"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3051"/>
<source>Cubic Spline</source>
<translation>Kubisches Spline</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3046"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3052"/>
<source>Lanczos</source>
<translation>Lanczos</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3048"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3054"/>
<source>Mode</source>
<translation>Modus</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3049"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="3055"/>
<source>None</source>
<translation>Keine</translation>
</message>
@@ -21001,300 +21331,300 @@ stderr: %4</translation>
<message>
<location filename="../src/providers/db2/qgsdb2provider.cpp" line="1452"/>
<location filename="../src/providers/mssql/qgsmssqlprovider.cpp" line="1883"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2924"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3710"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2938"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3755"/>
<source>Unsupported type for field %1</source>
<translation>Nicht unterstützter Typ für Feld %1</translation>
</message>
<message>
<location filename="../src/providers/mssql/qgsmssqlprovider.cpp" line="1897"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2943"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3730"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2957"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3775"/>
<source>Creation of fields failed</source>
<translation>Erzeugung der Felder gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="67"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="74"/>
<source>OGR[%1] error %2: %3</source>
<translation>OGR[%1] Fehler %2: %3</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="239"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="251"/>
<source>Unable to create the datasource. %1 exists and overwrite flag is false.</source>
<translation>Konnte die Datenquelle nicht erzeugen. %1 bereits vorhanden und Überschreiben ist aus.</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1985"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2000"/>
<source>Unable to get driver %1</source>
<translation>Konnte Treiber %1 nicht laden</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1993"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2008"/>
<source>Arc/Info Binary Coverage</source>
<translation>Arc/Info-Binär-Coverage</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2010"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2025"/>
<source>DODS</source>
<translation>DODS</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2014"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2029"/>
<source>CouchDB</source>
<translation>CouchDB</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2134"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2149"/>
<source>OpenFileGDB</source>
<translation>OpenFileGDB</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2024"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2026"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2039"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2041"/>
<source>ESRI Personal GeoDatabase</source>
<translation>ESRI-Personal-GeoDatabase</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2032"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2047"/>
<source>ESRI ArcSDE</source>
<translation>ESRI-ArcSDE</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2036"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2051"/>
<source>ESRI Shapefiles</source>
<translation>ESRI-Shapedateien</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1094"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2072"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2087"/>
<source>GeoPackage</source>
<translation>GeoPackage</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2077"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2092"/>
<source>Grass Vector</source>
<translation>GRASS-Vektor</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2081"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2096"/>
<source>Informix DataBlade</source>
<translation>Informix-DataBlade</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2095"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2110"/>
<source>Ingres</source>
<translation>Ingres</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2104"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2119"/>
<source>Mapinfo File</source>
<translation>Mapinfo-Datei</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2114"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2129"/>
<source>MySQL</source>
<translation>MySQL</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2118"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2133"/>
<source>MSSQL</source>
<translation>MSSQL</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2122"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2137"/>
<source>Oracle Spatial</source>
<translation>Oracle Spatial</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2126"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2141"/>
<source>ODBC</source>
<translation>ODBC</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2130"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2145"/>
<source>OGDI Vectors</source>
<translation>OGDI-Vektoren</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2138"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2153"/>
<source>PostgreSQL</source>
<translation>PostgreSQL</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2154"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2169"/>
<source>Systematic Organization of Spatial Information [SOSI]</source>
<translation>Systematic Organization of Spatial Information [SOSI]</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2159"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2174"/>
<source>SQLite/SpatiaLite</source>
<translation>SQLite/SpatiaLite</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2164"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2179"/>
<source>Storage and eXchange Format</source>
<translation>Storage and eXchange Format</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2169"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2184"/>
<source>UK. NTF2</source>
<translation>UK. NTF2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2173"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2188"/>
<source>U.S. Census TIGER/Line</source>
<translation>U.S. Census TIGER/Line</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2177"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2192"/>
<source>VRT - Virtual Datasource</source>
<translation>VRT - Virtuelle Datenquellen</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2183"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2198"/>
<source>X-Plane/Flightgear</source>
<translation>X-Plane/Flightgear</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1730"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2199"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2214"/>
<source>Open Document Spreadsheet</source>
<translation>Open-Dokument-Tabelle</translation>
</message>
<message>
<location filename="../src/core/qgsvectorfilewriter.cpp" line="1704"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2204"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2219"/>
<source>MS Office Open XML spreadsheet</source>
<translation>MS-Office-Open-XML-Tabelle</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2209"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2224"/>
<source>MS Excel format</source>
<translation>MS-Excel-Format</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2214"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2229"/>
<source>EDIGEO</source>
<translation>EDIGEO</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2219"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2234"/>
<source>NAS - ALKIS</source>
<translation>NAS - ALKIS</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2224"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2239"/>
<source>WAsP</source>
<translation>WAsP</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2229"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2244"/>
<source>PCI Geomatics Database File</source>
<translation>PCI Geomatics-Datenbankdatei</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2234"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2249"/>
<source>GPSTrackMaker</source>
<translation>GPSTrackMaker</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2239"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2254"/>
<source>Czech Cadastral Exchange Data Format</source>
<translation>Tschechische Katasteraustauschdatenformat</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2244"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2259"/>
<source>OpenStreetMap</source>
<translation>OpenStreetMap</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2249"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2264"/>
<source>Special Use Airspace Format</source>
<translation>Special Use Airspace-Format</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2254"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2269"/>
<source>OpenAir Special Use Airspace Format</source>
<translation>OpenAir Special Use Airspace-Format</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2259"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2274"/>
<source>Planetary Data Systems TABLE</source>
<translation>Planetary Data Systems TABLE</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2264"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2279"/>
<source>Hydrographic Transfer Format</source>
<translation>Hydrographisches Transfer-Format</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2269"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2284"/>
<source>Scalable Vector Graphics</source>
<translation>Skalierbare Vektorgrafik</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2274"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2289"/>
<source>Arc/Info Generate</source>
<translation>Arc/Info Generate</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2279"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2294"/>
<source>Geospatial PDF</source>
<translation>Geospatial-PDF</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2284"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2299"/>
<source>SEG-Y</source>
<translation>SEG-Y</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2289"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2304"/>
<source>SEG-P1</source>
<translation>SEG-P1</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2290"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2305"/>
<source>UKOOA P1/90</source>
<translation>UKOOA P1/90</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="2202"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2324"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="2208"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2339"/>
<source>All files</source>
<translation>Alle Dateien</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2492"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2507"/>
<source>Duplicate field (10 significant characters): %1</source>
<translation>Doppeltes Feld (10 signifikante Zeichen): %1</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2509"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2524"/>
<source>Creating the data source %1 failed: %2</source>
<translation>Erzeugung der Datenquelle %1 gescheitert: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2557"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2572"/>
<source>Unknown vector type of %1</source>
<translation>Unbekannter Vektortyp %1</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2583"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2598"/>
<source>Creation of OGR data source %1 failed: %2</source>
<translation>Erzeugung der OGR-Datenquelle %1 gescheitert: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2652"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2667"/>
<source>field %1 with unsupported type %2 skipped</source>
<translation>Feld %1 wegen nicht unterstütztem Typ %2 übersprungen</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2658"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2673"/>
<source>creation of field %1 failed</source>
<translation>Erzeugung des Feld %1 gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2676"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2691"/>
<source>Couldn't create file %1.qpj</source>
<translation>Konnte Datei %1.qpj nicht erzeugen</translation>
</message>
@@ -21315,13 +21645,13 @@ Fehler:%2</translation>
<translation>Oracle</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2613"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3103"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3503"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3888"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3954"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3985"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4131"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2627"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3117"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3523"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3933"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3999"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4030"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4176"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="135"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="5195"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="5269"/>
@@ -21332,135 +21662,135 @@ Fehler:%2</translation>
<translation>Verbindung zur Datenbank schlug fehl</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2625"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2639"/>
<source>No owner name found</source>
<translation>Kein Besitzername gefunden</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2812"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3647"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2826"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3676"/>
<source>Creation of data source %1 failed:
%2</source>
<translation>Erzeugung der Datenquelle %1 gescheitert:
%2</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2846"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3665"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2860"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3694"/>
<source>Loading of the layer %1 failed</source>
<translation>Laden des Layers %1 gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2888"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2902"/>
<source>Field name clash found (%1 not remappable)</source>
<translation>Feldnamenkonflikt gefunden (%1 nicht abbildbar)</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3109"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3123"/>
<source>%1 not owner of the table %2.</source>
<translation>%1 nicht Besitzer der Tabelle %2.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3125"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3139"/>
<source>Unable to determine number of geometry columns of layer %1.%2:
%3</source>
<translation>Konnte die Geometriespaltenanzahl des Layer %1.%2 nicht feststellen:
%3</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3158"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3172"/>
<source>Unable to delete layer %1.%2:
%3</source>
<translation>Konnte Layer %1.%2 nicht löschen:
%3</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3168"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3182"/>
<source>Unable to clean metadata %1.%2:
%3</source>
<translation>Konnte Metadaten %1.%2 nicht löschen:
%3</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3247"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3422"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3476"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3543"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3261"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3436"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3490"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3557"/>
<source>Could not connect to database</source>
<translation>Verbindung zur Datenbank gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3254"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3268"/>
<source>Unable to check layer style existence [%1]</source>
<translation>Konnte nicht prüfen, ob Layerstil vorhanden ist [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3278"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3292"/>
<source>Unable to create layer style table [%1]</source>
<translation>Konnte Layerstiltabelle nicht erzeugen [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3302"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3316"/>
<source>Unable to check style existence [%1]</source>
<translation>Konnte nicht prüfen, ob Stil existiert [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3431"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3445"/>
<source>Unable to find layer style table [%1]</source>
<translation>Konnte Layerstiltabelle nicht finden [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3489"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3503"/>
<source>Layer style table does not exist [%1]</source>
<translation>Layerstiltabelle nicht vorhanden [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3551"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3565"/>
<source>Could not load layer style table [%1]</source>
<translation>Konnte Layerstiltabelle nicht laden [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3354"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3368"/>
<source>Cannot fetch new layer style id.</source>
<translation>Konnte Layerstilkennung nicht laden.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3361"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3375"/>
<source>Could not prepare insert/update [%1]</source>
<translation>Konnte INSERT/UPDATE nicht vorbereiten [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3382"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3396"/>
<source>Could not execute insert/update [%1]</source>
<translation>Konnte INSERT/UPDATE nicht ausführen [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3403"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3417"/>
<source>Could not reset default status [%1]</source>
<translation>Konnte Vorgabestatus nicht zurücksetzen [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3449"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3463"/>
<source>Could not retrieve style [%1]</source>
<translation>Konnte Stil nicht laden [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3453"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3467"/>
<source>Style not found</source>
<translation>Stil nicht gefunden</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3485"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3499"/>
<source>Could not verify existence of layer style table [%1]</source>
<translation>Konnte Existenz der Layerstiltabelle nicht überprüfen [%1]</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3499"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3513"/>
<source>No style for layer found</source>
<translation>Kein Stil zum Layer gefunden</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3555"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3569"/>
<source>No styles found in layer table [%1]</source>
<translation>Keine Stile in der Layertabelle gefunden [%1]</translation>
</message>
@@ -21491,22 +21821,22 @@ Datenbankfehler: %2</translation>
<translation>Unendliches Filterrechteck angegeben</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3903"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3931"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3948"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3976"/>
<source>Unable to delete layer %1:
%2</source>
<translation>Konnte Ebene %1 nicht löschen:
%2</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3965"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4010"/>
<source>Unable to delete schema %1:
%2</source>
<translation>Konnte Schema %1 nicht löschen:
%2</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4009"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4054"/>
<source>Unable to save layer style. It's not possible to create the destination table on the database. Maybe this is due to table permissions (user=%1). Please contact your database admin</source>
<translation>Kann den Layerstil nicht speicher. Es ist nicht möglich die Zieltabelle in der Datenbank anzulegen. Dies kann mit den Tabellenberechtigungen (Benutzer=%1) zusammenhängen. Wenden Sie sich bitte an den Datenbankadministrator</translation>
</message>
@@ -21517,24 +21847,24 @@ Datenbankfehler: %2</translation>
</message>
<message>
<location filename="../src/providers/mssql/qgsmssqlprovider.cpp" line="2074"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3308"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4063"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3322"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4108"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="5378"/>
<source>Save style in database</source>
<translation>Stil in Datenbank speichern</translation>
</message>
<message>
<location filename="../src/providers/mssql/qgsmssqlprovider.cpp" line="2075"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3309"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4064"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3323"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4109"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="5379"/>
<source>A style named "%1" already exists in the database for this layer. Do you want to overwrite it?</source>
<translation>Ein Stil "%1" für diesen Layer ist bereits in der Datenbank vorhanden. Soll er überschrieben werden?</translation>
</message>
<message>
<location filename="../src/providers/mssql/qgsmssqlprovider.cpp" line="2079"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3313"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4068"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3327"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4113"/>
<source>Operation aborted. No changes were made in the database</source>
<translation>Vorgang abgebrochen. Es wurden keine Datenbankänderungen vorgenommen</translation>
</message>
@@ -21549,20 +21879,20 @@ Datenbankfehler: %2</translation>
<translation>Keine Stile in der Datenbank oder es konnte keine Verbindung dazu aufgenommen werden.</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4116"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4161"/>
<source>Unable to save layer style. It's not possible to insert a new record into the style table. Maybe this is due to table permissions (user=%1). Please contact your database administrator.</source>
<translation>Kann den Layerstil nicht speicher. Es ist nicht möglich Datensätze in die Stiltabelle einzufügen. Dies kann mit den Tabellenberechtigungen (Benutzer=%1) zusammenhängen. Wenden Sie sich bitte an den Datenbankadministrator.</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4170"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4239"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4215"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4284"/>
<source>Connection to database failed using username: %1</source>
<translation>Verbindung zur Datenbank mit Benutzername %1 fehlgeschlagen</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4188"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4214"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4255"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4233"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4259"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4300"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="5286"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="5370"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="5430"/>
@@ -21575,24 +21905,24 @@ Datenbankfehler: %2</translation>
<translation>Fehler bei Abfrageausführung: %1</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4189"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4234"/>
<source>Error executing the select query for related styles. The query was logged</source>
<translation>Fehler beim Abfragen von zusammenhängenden Stilen. Die Abfragen wurde protokolliert</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4215"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4260"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="5586"/>
<source>Error executing the select query for unrelated styles. The query was logged</source>
<translation>Fehler beim Abfragen von unzusammenhängenden Stilen. Die Abfragen wurde protokolliert</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4256"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4301"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="5636"/>
<source>Error executing the select query. The query was logged</source>
<translation>Fehler bei Abfrage. Die Abfrage wurde protokolliert</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4251"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="4296"/>
<location filename="../src/providers/spatialite/qgsspatialiteprovider.cpp" line="5631"/>
<source>Consistency error in table '%1'. Style id should be unique</source>
<translation>Konsistenzfehler in Tabelle '%1'. Stilkennung sollte eindeutig sein</translation>
@@ -21690,71 +22020,71 @@ SQL: %1</translation>
<translation>Fehler beim Laden des Stils. Die Abfrage wurde protokolliert</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="91"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="98"/>
<source>The extra plugin path '%1' does not exist!</source>
<translation>Der zusätzliche Erweiterungspfad '%1' ist nicht vorhanden!</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="119"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="126"/>
<source>Couldn't load SIP module.</source>
<translation>Das SIP-Modul konnte nicht geladen werden.</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="119"/>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="130"/>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="138"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="126"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="137"/>
<location filename="../src/python/qgspythonutilsimpl.cpp" line="145"/>
<location filename="../src/python/qgspythonutilsimpl.cpp" line="152"/>
<location filename="../src/python/qgspythonutilsimpl.cpp" line="159"/>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="203"/>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="243"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="166"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="210"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="250"/>
<source>Python support will be disabled.</source>
<translation>Die Python-Unterstützung wird abgeschaltet.</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="130"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="137"/>
<source>Couldn't set SIP API versions.</source>
<translation>Konnte SIP-API-Version nicht setzen.</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="138"/>
<location filename="../src/python/qgspythonutilsimpl.cpp" line="145"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="152"/>
<source>Couldn't load PyQt.</source>
<translation>Konnte PyQt nicht laden.</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="152"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="159"/>
<source>Couldn't load PyQGIS.</source>
<translation>PyQGIS konnte nicht geladen werden.</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="159"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="166"/>
<source>Couldn't load QGIS utils.</source>
<translation>Konnte QGIS-Utils nicht öffnen.</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="318"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="325"/>
<source>An error occurred during execution of following code:</source>
<translation>Fehler bei der Ausführung folgenden Codes:</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="329"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="336"/>
<source>Python version:</source>
<translation>Python-Version:</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="330"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="337"/>
<source>QGIS version:</source>
<translation>QGIS-Version:</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="331"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="338"/>
<source>Python path:</source>
<translation>Python-Pfad:</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="90"/>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="336"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="97"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="343"/>
<source>Python error</source>
<translation>Python-Fehler</translation>
</message>
@@ -21894,7 +22224,7 @@ SQL: %1</translation>
<translation>Stil in DB speichern (%1)</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1278"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1280"/>
<source>Could not save symbology because:
%1</source>
<translation>Konnte Darstellung nicht speichern, weil:
@@ -21952,68 +22282,68 @@ SQL: %1</translation>
<translation>Objektkennung</translation>
</message>
<message>
- <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="620"/>
+ <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="622"/>
<source>linear</source>
<translation>Linear</translation>
</message>
<message>
- <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="624"/>
+ <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="626"/>
<source>radial</source>
<translation>Radial</translation>
</message>
<message>
- <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="628"/>
+ <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="630"/>
<source>conical</source>
<translation>Konisch</translation>
</message>
<message>
- <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="642"/>
+ <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="644"/>
<source>feature</source>
<translation>Objekt</translation>
</message>
<message>
- <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="646"/>
+ <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="648"/>
<source>viewport</source>
<translation>Ansichtsfenster</translation>
</message>
<message>
- <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="660"/>
+ <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="662"/>
<source>pad</source>
<translation>auffüllen</translation>
</message>
<message>
- <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="664"/>
+ <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="666"/>
<source>repeat</source>
<translation>Wiederholen</translation>
</message>
<message>
- <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="668"/>
+ <location filename="../src/core/symbology-ng/qgsfillsymbollayerv2.cpp" line="670"/>
<source>reflect</source>
<translation>Reflektieren</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayerrenderer.cpp" line="128"/>
+ <location filename="../src/core/qgsvectorlayerrenderer.cpp" line="126"/>
<source>No renderer for drawing.</source>
<translation>Darstellung zum Zeichnen nicht definiert.</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayerrenderer.cpp" line="216"/>
+ <location filename="../src/core/qgsvectorlayerrenderer.cpp" line="214"/>
<source>Simplify transform error caught: %1</source>
<translation>Transformationsfehler bei Vereinfachung abgefangen: %1</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="149"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="180"/>
<source>empty capabilities document</source>
<translation>Leeres Capabilities-Dokument</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="238"/>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="262"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="269"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="293"/>
<source>Dom Exception</source>
<translation>DOM-Ausnahme</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="240"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="271"/>
<source>Could not get WMS capabilities: %1 at line %2 column %3
This is probably due to an incorrect WMS Server URL.
Response was:
@@ -22026,7 +22356,7 @@ Antwort war:
%4</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="264"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="295"/>
<source>Could not get WMS capabilities in the expected format (DTD): no %1 or %2 found.
This might be due to an incorrect WMS Server URL.
Tag:%3
@@ -22039,12 +22369,12 @@ Antwort war:
%4</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1482"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1516"/>
<source>Generated default style</source>
<translation>Erzeugte Vorgabestile</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1483"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1517"/>
<source>Style was missing in capabilities</source>
<translation>Stil fehlte in den Capabilities</translation>
</message>
@@ -22079,12 +22409,12 @@ Antwort war:
<translation>Rasterbildfüllung</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="243"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="250"/>
<source>Couldn't load PyQGIS Server.</source>
<translation>Kann PyQGIS Server nicht laden.</translation>
</message>
<message>
- <location filename="../src/python/qgspythonutilsimpl.cpp" line="203"/>
+ <location filename="../src/python/qgspythonutilsimpl.cpp" line="210"/>
<source>Couldn't load qgis.user.</source>
<translation>Kann qgis.user nicht laden.</translation>
</message>
@@ -22287,17 +22617,17 @@ Antwort war:
<translation>Kann %1 nicht nach %2 umbenennen</translation>
</message>
<message>
- <location filename="../src/core/qgscolorscheme.h" line="188"/>
+ <location filename="../src/core/qgscolorscheme.h" line="196"/>
<source>Recent colors</source>
<translation>Kürzlich verwendete Farben</translation>
</message>
<message>
- <location filename="../src/core/qgscolorscheme.h" line="217"/>
+ <location filename="../src/core/qgscolorscheme.h" line="225"/>
<source>Standard colors</source>
<translation>Standardfarben</translation>
</message>
<message>
- <location filename="../src/core/qgscolorscheme.h" line="244"/>
+ <location filename="../src/core/qgscolorscheme.h" line="252"/>
<source>Project colors</source>
<translation>Projektfarben</translation>
</message>
@@ -23180,216 +23510,221 @@ Only available when the layer uses a categorized symbol renderer.</source>
Nur verfügbar wenn der Layer klassifiziert dargestellt wird.</translation>
</message>
<message>
- <location filename="../src/core/qgsgml.cpp" line="438"/>
+ <location filename="../src/core/qgsgml.cpp" line="452"/>
<source>Error: %1 on line %2, column %3</source>
<translation>Fehler: %1 in Zeile %2, Spalte %3</translation>
</message>
<message>
- <location filename="../src/core/qgsgml.cpp" line="124"/>
- <location filename="../src/core/qgsgml.cpp" line="171"/>
- <location filename="../src/core/qgsgml.cpp" line="427"/>
+ <location filename="../src/core/qgsgml.cpp" line="138"/>
+ <location filename="../src/core/qgsgml.cpp" line="185"/>
+ <location filename="../src/core/qgsgml.cpp" line="441"/>
<source>WFS</source>
<translation>WFS</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1736"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="1740"/>
<source>unable to convert '%1' element to a valid expression: it is not supported yet or it has invalid arguments</source>
<translation>Kann Element '%1' nicht in einen gültigen Ausdruck umwandeln: Es wird nicht unterstützt oder hat ungültige Argumente</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1751"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="1755"/>
<source>'%1' binary operator not supported.</source>
<translation>Binärer Operator '%1' nicht unterstützt.</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1760"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="1769"/>
<source>invalid left operand for '%1' binary operator</source>
<translation>Ungültiger linker Operand für den binären Operator '%1'</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1770"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="1779"/>
<source>invalid right operand for '%1' binary operator</source>
<translation>Ungültiger rechter Operand für den binären Operator '%1'</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1781"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="1848"/>
<source>only one operand for '%1' binary operator</source>
<translation>Nur ein Operand für den binären Operator '%1'</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1817"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="1884"/>
<source>No OGC Geometry found</source>
<translation>Keine OGC-Geometrie gefunden</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1840"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="1907"/>
<source>invalid operand for '%1' unary operator</source>
<translation>Ungültiger Operand für unären Operator '%1'</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1852"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="1919"/>
<source>ogc:Function expected, got %1</source>
<translation>ogc:Function erwartet, %1 gefunden</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1891"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="1958"/>
<source>ogc:Literal expected, got %1</source>
<translation>ogc:Literal erwartet, %1 gefunden</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1913"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="1980"/>
<source>'%1' is an invalid or not supported content for ogc:Literal</source>
<translation>'%1' ist ein ungültiger oder nicht unterstützter Inhalt für ogc:Literal</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="1958"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2025"/>
<source>ogc:PropertyName expected, got %1</source>
<translation>ogc:PropertyName erwartet, %1 gefunden</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2011"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2078"/>
<source>missing some required sub-elements in ogc:PropertyIsBetween</source>
<translation>Einige erforderliche Unterelemente in ogc:PropertyIsBetween fehlen</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2145"/>
- <location filename="../src/core/qgsogcutils.cpp" line="2569"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2191"/>
+ <source>Node type not supported in expression translation: %1</source>
+ <translation>Ausdrucksübersetzung unterstützt diesen Knotentyp nicht: %1</translation>
+ </message>
+ <message>
+ <location filename="../src/core/qgsogcutils.cpp" line="2257"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2681"/>
<source>Node type not supported: %1</source>
<translation>Knotentyp nicht unterstützt: %1</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2172"/>
- <location filename="../src/core/qgsogcutils.cpp" line="2596"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2284"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2708"/>
<source>This use of unary operator not implemented yet</source>
<translation>Diese Verwendung eines unären Operators ist noch nicht implementiert.</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2182"/>
- <location filename="../src/core/qgsogcutils.cpp" line="2606"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2294"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2718"/>
<source>Unary operator %1 not implemented yet</source>
<translation>Unärer Operator %1 noch nicht implementiert</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2236"/>
- <location filename="../src/core/qgsogcutils.cpp" line="2678"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2348"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2792"/>
<source>Binary operator %1 not implemented yet</source>
<translation>Binärer Operator %1 noch nicht implementiert</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2278"/>
- <location filename="../src/core/qgsogcutils.cpp" line="2723"/>
- <location filename="../src/core/qgsogcutils.cpp" line="3149"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2390"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2837"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3263"/>
<source>Literal type not supported: %1</source>
<translation>Literaler Typ nicht unterstützt: %1</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2420"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2532"/>
<source><BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('...'))</source>
<translation><BBOX> wird derzeit nur in Form bbox($geometry, geomFromWKT('...')) unterstützt</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2437"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2549"/>
<source>Unable to translate spatial operator: at least one must refer to geometry.</source>
<translation>Kann räumlichen Operator nicht übersetzen: mindestens einer muß sich auf Geometrie beziehen.</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2446"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2558"/>
<source>spatial operator: the other operator must be a geometry constructor function</source>
<translation>Räumlicher Operator: der andere Operator muß eine Geometrie erzeugen</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2457"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2569"/>
<source>geom_from_wkt: argument must be string literal</source>
<translation>geom_from_wkt: das Argument muß eine Zeichenkette sein</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2472"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2584"/>
<source>geom_from_gml: argument must be string literal</source>
<translation>geom_from_gml: das Argument muß eine Zeichenkette sein</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2480"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2592"/>
<source>geom_from_gml: unable to parse XML</source>
<translation>geom_from_gml: kann XML nicht interpretieren</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2489"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2601"/>
<source>spatial operator: unknown geometry constructor function</source>
<translation>Räumlicher Operator: unbekannte Geometrieerzeugungsfunktion</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2505"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2617"/>
<source>Special columns/constants are not supported.</source>
<translation>Spezielle Spalten/Konstanten nicht unterstützt.</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2867"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="2981"/>
<source>%1: Last argument must be string or integer literal</source>
<translation>%1: Letztes Argument muß Zeichenkette oder Zahl sein</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2912"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3026"/>
<source>Function %1 should have 1 or 2 arguments</source>
<translation>Funktion %1 sollte 1 oder 2 Argumente haben</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2919"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3033"/>
<source>%1: First argument must be string literal</source>
<translation>%1: Erstes Argument muß eine Zeichenkette sein</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2938"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3052"/>
<source>%1: invalid WKT</source>
<translation>%1: ungültiges WKT</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2951"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3065"/>
<source>Function %1 should have 4 or 5 arguments</source>
<translation>Funktion %1 sollte 4 oder 5 Argumente haben</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2962"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3076"/>
<source>%1: Argument %2 must be numeric literal</source>
<translation>%1: Argument %1 muss eine Zahl sein</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="2975"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3089"/>
<source>%1 Argument %2 must be numeric literal</source>
<translation>%1 Argument %1 muß nummerisch sein</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="3008"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3122"/>
<source>Function %1 should have 1 argument</source>
<translation>Funktion %1 sollte ein Argument haben</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="3015"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3129"/>
<source>%1: Argument must be string literal</source>
<translation>%1: Argument muß Zeichenkette sein</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="3023"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3137"/>
<source>ST_GeomFromGML: unable to parse XML</source>
<translation>ST_GeomFromGML: kann XML nicht interpretieren</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="3039"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3153"/>
<source>Function %1 should have 2 arguments</source>
<translation>Funktion %1 sollte zwei Argumente haben</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="3079"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3193"/>
<source>Function %1 should have 3 arguments</source>
<translation>Funktion %1 sollte 3 Argumente haben</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="3111"/>
- <location filename="../src/core/qgsogcutils.cpp" line="3117"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3225"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3231"/>
<source>Function %1 3rd argument should be a numeric value or a string made of a numeric value followed by a string</source>
<translation>Das dritte Argument der Funktion %1 sollte ein numerischer Wert oder eine Zeichenkette bestehend aus einem numerischen Wert gefolgt von einer Zeichenkette sein</translation>
</message>
<message>
- <location filename="../src/core/qgsogcutils.cpp" line="3235"/>
+ <location filename="../src/core/qgsogcutils.cpp" line="3349"/>
<source>Joins are only supported with WFS 2.0</source>
<translation>Verknüpfungen werden nur mit WFS 2.0 unterstützt</translation>
</message>
@@ -23496,7 +23831,7 @@ Nur verfügbar wenn der Layer klassifiziert dargestellt wird.</translation>
<translation>Auf Voreinstellungen zurücksetzen</translation>
</message>
<message>
- <location filename="../src/app/qgslayerstylingwidget.cpp" line="511"/>
+ <location filename="../src/app/qgslayerstylingwidget.cpp" line="522"/>
<source>Style Manager</source>
<translation>Stilverwaltung</translation>
</message>
@@ -23777,10 +24112,10 @@ Nur verfügbar wenn der Layer klassifiziert dargestellt wird.</translation>
</message>
<message>
<location filename="../src/app/qgisapp.cpp" line="1757"/>
- <location filename="../src/app/qgisapp.cpp" line="6039"/>
- <location filename="../src/app/qgisapp.cpp" line="7859"/>
- <location filename="../src/app/qgisapp.cpp" line="7939"/>
- <location filename="../src/app/qgisapp.cpp" line="10921"/>
+ <location filename="../src/app/qgisapp.cpp" line="6041"/>
+ <location filename="../src/app/qgisapp.cpp" line="7876"/>
+ <location filename="../src/app/qgisapp.cpp" line="7956"/>
+ <location filename="../src/app/qgisapp.cpp" line="10938"/>
<source>Error</source>
<translation>Fehler</translation>
</message>
@@ -23810,13 +24145,13 @@ Bitte nehmen Sie Kontakt zu den Entwicklern auf.</translation>
</message>
<message>
<location filename="../src/app/qgisapp.cpp" line="1876"/>
- <location filename="../src/app/qgisapp.cpp" line="11781"/>
+ <location filename="../src/app/qgisapp.cpp" line="11798"/>
<source>Panels</source>
<translation>Bedienfelder</translation>
</message>
<message>
<location filename="../src/app/qgisapp.cpp" line="1878"/>
- <location filename="../src/app/qgisapp.cpp" line="11792"/>
+ <location filename="../src/app/qgisapp.cpp" line="11809"/>
<source>Toolbars</source>
<translation>Werkzeugkästen</translation>
</message>
@@ -24043,68 +24378,68 @@ Bitte nehmen Sie Kontakt zu den Entwicklern auf.</translation>
<translation>QGIS-Dateien</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5871"/>
+ <location filename="../src/app/qgisapp.cpp" line="5873"/>
<source>Diagram Properties</source>
<translation>Diagrammeigenschaften</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5879"/>
+ <location filename="../src/app/qgisapp.cpp" line="5881"/>
<source>Layer diagram properties</source>
<translation>Layerdiagrammeigenschaften</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7031"/>
- <location filename="../src/app/qgisapp.cpp" line="7070"/>
+ <location filename="../src/app/qgisapp.cpp" line="7033"/>
+ <location filename="../src/app/qgisapp.cpp" line="7072"/>
<source>An error occurred during the merge operation</source>
<translation>Beim Zusammenführen trat ein Fehler auf</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7499"/>
+ <location filename="../src/app/qgisapp.cpp" line="7516"/>
<source>New temporary scratch layer name</source>
<translation>Name des neuen Temporärlayer</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7596"/>
+ <location filename="../src/app/qgisapp.cpp" line="7613"/>
<source>Cannot create new layer.</source>
<translation>Kann neuen Layer nicht erzeugen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7663"/>
+ <location filename="../src/app/qgisapp.cpp" line="7680"/>
<source>Cannot copy style</source>
<translation>Kann Stil nicht kopieren</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7693"/>
+ <location filename="../src/app/qgisapp.cpp" line="7710"/>
<source>Cannot parse style</source>
<translation>Kann Stil nicht interpretieren</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7708"/>
+ <location filename="../src/app/qgisapp.cpp" line="7725"/>
<source>Cannot paste style</source>
<translation>Kann Stil nicht einfügen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8131"/>
+ <location filename="../src/app/qgisapp.cpp" line="8148"/>
<source>Filter on joined fields</source>
<translation>Filter auf verknüpften Feldern</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8266"/>
+ <location filename="../src/app/qgisapp.cpp" line="8283"/>
<source>No legend entries selected</source>
<translation>Keine Einträge der Legende gewählt</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8267"/>
+ <location filename="../src/app/qgisapp.cpp" line="8284"/>
<source>Select the layers and groups you want to remove in the legend.</source>
<translation>Zu löschende Layer oder Gruppen in der Legende wählen.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8275"/>
+ <location filename="../src/app/qgisapp.cpp" line="8292"/>
<source>Remove layers and groups</source>
<translation>Layer und Gruppen löschen</translation>
</message>
<message numerus="yes">
- <location filename="../src/app/qgisapp.cpp" line="8275"/>
+ <location filename="../src/app/qgisapp.cpp" line="8292"/>
<source>Remove %n legend entries?</source>
<comment>number of legend items to remove</comment>
<translation>
@@ -24113,7 +24448,7 @@ Bitte nehmen Sie Kontakt zu den Entwicklern auf.</translation>
</translation>
</message>
<message numerus="yes">
- <location filename="../src/app/qgisapp.cpp" line="8287"/>
+ <location filename="../src/app/qgisapp.cpp" line="8304"/>
<source>%n legend entries removed.</source>
<comment>number of removed legend entries</comment>
<translation>
@@ -24122,27 +24457,27 @@ Bitte nehmen Sie Kontakt zu den Entwicklern auf.</translation>
</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8394"/>
+ <location filename="../src/app/qgisapp.cpp" line="8411"/>
<source>%1 (%2 type unsupported)</source>
<translation>%1 (Typ %2 nicht unterstützt)</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8428"/>
+ <location filename="../src/app/qgisapp.cpp" line="8445"/>
<source>Cannot copy style to duplicated layer.</source>
<translation>Kann Stil nicht in kopierten Layer anwenden.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="9095"/>
+ <location filename="../src/app/qgisapp.cpp" line="9112"/>
<source>https://qgis.org/en/site/getinvolved/development/bugreporting.html</source>
<translation>https://qgis.org/de/site/getinvolved/development/bugreporting.html</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="9400"/>
+ <location filename="../src/app/qgisapp.cpp" line="9417"/>
<source>Do you want to save the current project? %1</source>
<translation>Wollen Sie das aktuelle Projekt speichern? %1</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="10901"/>
+ <location filename="../src/app/qgisapp.cpp" line="10918"/>
<source>Invalid Layer</source>
<translation>Ungültiger Layer</translation>
</message>
@@ -24268,7 +24603,7 @@ Bitte nehmen Sie Kontakt zu den Entwicklern auf.</translation>
</message>
<message>
<location filename="../src/app/qgisapp.cpp" line="4702"/>
- <location filename="../src/app/qgisapp.cpp" line="5964"/>
+ <location filename="../src/app/qgisapp.cpp" line="5966"/>
<source>Abort...</source>
<translation>Abbrechen...</translation>
</message>
@@ -24330,37 +24665,37 @@ Bitte nehmen Sie Kontakt zu den Entwicklern auf.</translation>
<translation>Name für zu speichernden QGIS-Projektdatei wählen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5214"/>
+ <location filename="../src/app/qgisapp.cpp" line="5216"/>
<source>Unable to load %1</source>
<translation>%1 kann nicht geladen werden</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5336"/>
+ <location filename="../src/app/qgisapp.cpp" line="5338"/>
<source>Choose a file name to save the map image as</source>
<translation>Name für Datei zum Speichern des Kartenabbilds wählen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5341"/>
+ <location filename="../src/app/qgisapp.cpp" line="5343"/>
<source>Saved map image to %1</source>
<translation>Kartenabbild als %1 gespeichert</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5746"/>
+ <location filename="../src/app/qgisapp.cpp" line="5748"/>
<source>Default system font substituted.</source>
<translation>Durch voreingestellten Systemfont ersetzt.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5765"/>
+ <location filename="../src/app/qgisapp.cpp" line="5767"/>
<source>Labeling</source>
<translation>Beschriftung</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5766"/>
+ <location filename="../src/app/qgisapp.cpp" line="5768"/>
<source>Font for layer <b><u>%1</u></b> was not found (<i>%2</i>). %3</source>
<translation>Schriftart <i>%2</i> für Layer <b><u>%1</u></b> nicht gefunden. %3</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5757"/>
+ <location filename="../src/app/qgisapp.cpp" line="5759"/>
<source>Open labeling dialog</source>
<translation>Beschriftungseinstelllungen öffnen</translation>
</message>
@@ -24583,158 +24918,158 @@ geöffnet werden?</translation>
<translation>Die Projektdatei ist schreibgeschützt.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5088"/>
+ <location filename="../src/app/qgisapp.cpp" line="5090"/>
<source>DXF export completed</source>
<translation>DXF-Export abgeschlossen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5092"/>
+ <location filename="../src/app/qgisapp.cpp" line="5094"/>
<source>DXF export failed</source>
<translation>DXF-Export fehlgeschlagen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5611"/>
+ <location filename="../src/app/qgisapp.cpp" line="5613"/>
<source>No action selected</source>
<translation>Keine Aktion gewählt</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5627"/>
<location filename="../src/app/qgisapp.cpp" line="5629"/>
- <location filename="../src/app/qgisapp.cpp" line="5645"/>
+ <location filename="../src/app/qgisapp.cpp" line="5631"/>
+ <location filename="../src/app/qgisapp.cpp" line="5647"/>
<source>Run feature action<br><b>%1</b></source>
<translation>Objektaktion ausführen<br><b>%1</b></translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5777"/>
- <location filename="../src/app/qgisapp.cpp" line="5798"/>
+ <location filename="../src/app/qgisapp.cpp" line="5779"/>
+ <location filename="../src/app/qgisapp.cpp" line="5800"/>
<source>Commit errors</source>
<translation>Fehler beim Festschreiben</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5778"/>
- <location filename="../src/app/qgisapp.cpp" line="5799"/>
+ <location filename="../src/app/qgisapp.cpp" line="5780"/>
+ <location filename="../src/app/qgisapp.cpp" line="5801"/>
<source>Could not commit changes to layer %1</source>
<translation>Konnte Änderungen am Layer %1 nicht festschreiben</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5780"/>
+ <location filename="../src/app/qgisapp.cpp" line="5782"/>
<source>Errors: %1
</source>
<translation>Fehler: %1</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5787"/>
+ <location filename="../src/app/qgisapp.cpp" line="5789"/>
<source>Show more</source>
<translation>Mehr zeigen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5872"/>
+ <location filename="../src/app/qgisapp.cpp" line="5874"/>
<source>Please select a vector layer first</source>
<translation>Bitte wählen zur zuvor einen Layer</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5966"/>
+ <location filename="../src/app/qgisapp.cpp" line="5968"/>
<source>Reading raster</source>
<translation>Lade Raster</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5967"/>
+ <location filename="../src/app/qgisapp.cpp" line="5969"/>
<source>Saving raster</source>
<translation>Speichere Raster</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6040"/>
+ <location filename="../src/app/qgisapp.cpp" line="6042"/>
<source>Cannot write raster error code: %1</source>
<translation>Rasterschreibfehlercode: %1</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6059"/>
- <location filename="../src/app/qgisapp.cpp" line="6249"/>
+ <location filename="../src/app/qgisapp.cpp" line="6061"/>
+ <location filename="../src/app/qgisapp.cpp" line="6251"/>
<source>Saving done</source>
<translation>Speichern abgeschlossen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6060"/>
+ <location filename="../src/app/qgisapp.cpp" line="6062"/>
<source>Export to raster file has been completed</source>
<translation>Rasterdateiexport abgeschlossen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6250"/>
+ <location filename="../src/app/qgisapp.cpp" line="6252"/>
<source>Export to vector file has been completed</source>
<translation>Export in Vektordatei ist abgeschlossen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6256"/>
+ <location filename="../src/app/qgisapp.cpp" line="6258"/>
<source>Save error</source>
<translation>Fehler beim Speichern</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6257"/>
+ <location filename="../src/app/qgisapp.cpp" line="6259"/>
<source>Export to vector file failed.
Error: %1</source>
<translation>Export in Vektordatei schlug fehl.
Fehler: %1</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6320"/>
- <location filename="../src/app/qgisapp.cpp" line="8971"/>
- <location filename="../src/app/qgisapp.cpp" line="8980"/>
- <location filename="../src/app/qgisapp.cpp" line="9041"/>
- <location filename="../src/app/qgisapp.cpp" line="9050"/>
+ <location filename="../src/app/qgisapp.cpp" line="6322"/>
+ <location filename="../src/app/qgisapp.cpp" line="8988"/>
+ <location filename="../src/app/qgisapp.cpp" line="8997"/>
+ <location filename="../src/app/qgisapp.cpp" line="9058"/>
+ <location filename="../src/app/qgisapp.cpp" line="9067"/>
<source>No Layer Selected</source>
<translation>Keinen Layer ausgewählt</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6321"/>
+ <location filename="../src/app/qgisapp.cpp" line="6323"/>
<source>To delete features, you must select a vector layer in the legend</source>
<translation>Zum Löschen von Objekte zu muss ein Vektorlayer in der Legende gewählt werden</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6329"/>
+ <location filename="../src/app/qgisapp.cpp" line="6331"/>
<source>No Vector Layer Selected</source>
<translation>Es wurde kein Vektorlayer gewählt</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6330"/>
+ <location filename="../src/app/qgisapp.cpp" line="6332"/>
<source>Deleting features only works on vector layers</source>
<translation>Löschen von Objekten ist nur von Vektorlayern möglich</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6337"/>
+ <location filename="../src/app/qgisapp.cpp" line="6339"/>
<source>Provider does not support deletion</source>
<translation>Datenanbieter unterstützt keine Löschoperationen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6338"/>
+ <location filename="../src/app/qgisapp.cpp" line="6340"/>
<source>Data provider does not support deleting features</source>
<translation>Der Datenanbieter hat nicht die Möglichkeit Objekte zu löschen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6345"/>
- <location filename="../src/app/qgisapp.cpp" line="6851"/>
- <location filename="../src/app/qgisapp.cpp" line="6860"/>
- <location filename="../src/app/qgisapp.cpp" line="6961"/>
- <location filename="../src/app/qgisapp.cpp" line="7002"/>
+ <location filename="../src/app/qgisapp.cpp" line="6347"/>
+ <location filename="../src/app/qgisapp.cpp" line="6853"/>
+ <location filename="../src/app/qgisapp.cpp" line="6862"/>
+ <location filename="../src/app/qgisapp.cpp" line="6963"/>
+ <location filename="../src/app/qgisapp.cpp" line="7004"/>
<source>Layer not editable</source>
<translation>Der Layer kann nicht bearbeitet werden</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6346"/>
+ <location filename="../src/app/qgisapp.cpp" line="6348"/>
<source>The current layer is not editable. Choose 'Start editing' in the digitizing toolbar.</source>
<translation>Der aktuelle Layer kann nicht bearbeitet werden. Bitte 'Bearbeitungsstatus umschalten' aus der Digitalisierwerkzeugleiste wählen.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6355"/>
+ <location filename="../src/app/qgisapp.cpp" line="6357"/>
<source>No Features Selected</source>
<translation>Keine Objekte gewählt</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6361"/>
+ <location filename="../src/app/qgisapp.cpp" line="6363"/>
<source>Delete features</source>
<translation>Objekte löschen</translation>
</message>
<message numerus="yes">
- <location filename="../src/app/qgisapp.cpp" line="6361"/>
+ <location filename="../src/app/qgisapp.cpp" line="6363"/>
<source>Delete %n feature(s)?</source>
<comment>number of features to delete</comment>
<translation>
@@ -24743,22 +25078,22 @@ Fehler: %1</translation>
</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6366"/>
+ <location filename="../src/app/qgisapp.cpp" line="6368"/>
<source>Features deleted</source>
<translation>Objekt gelöscht</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6370"/>
+ <location filename="../src/app/qgisapp.cpp" line="6372"/>
<source>Problem deleting features</source>
<translation>Problem beim Löschen der Objekte</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6371"/>
+ <location filename="../src/app/qgisapp.cpp" line="6373"/>
<source>A problem occurred during deletion of %1 feature(s)</source>
<translation>Ein Problem trat bei der Löschung von %1 Objekt(en) auf</translation>
</message>
<message numerus="yes">
- <location filename="../src/app/qgisapp.cpp" line="6376"/>
+ <location filename="../src/app/qgisapp.cpp" line="6378"/>
<source>%n feature(s) deleted.</source>
<comment>number of features deleted</comment>
<translation>
@@ -24767,227 +25102,227 @@ Fehler: %1</translation>
</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6422"/>
+ <location filename="../src/app/qgisapp.cpp" line="6424"/>
<source>Merging features...</source>
<translation>Objekte werden verschmolzen...</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6422"/>
+ <location filename="../src/app/qgisapp.cpp" line="6424"/>
<source>Abort</source>
<translation>Abbrechen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6475"/>
+ <location filename="../src/app/qgisapp.cpp" line="6477"/>
<source>Create unique print composer title</source>
<translation>Eindeutigen Druckzusammenstellungstitel erzeugen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6478"/>
+ <location filename="../src/app/qgisapp.cpp" line="6480"/>
<source>(title generated if left empty)</source>
<translation>(Leergelassene Titel werden generiert)</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6492"/>
+ <location filename="../src/app/qgisapp.cpp" line="6494"/>
<source>Composer title</source>
<translation>Titel der Druckzusammenstellung</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6507"/>
+ <location filename="../src/app/qgisapp.cpp" line="6509"/>
<source>Title can not be empty!</source>
<translation>Titel kann nicht leer sein!</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6517"/>
+ <location filename="../src/app/qgisapp.cpp" line="6519"/>
<source>Title already exists!</source>
<translation>Titel bereits vorhanden!</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6536"/>
- <location filename="../src/app/qgisapp.cpp" line="6635"/>
+ <location filename="../src/app/qgisapp.cpp" line="6538"/>
+ <location filename="../src/app/qgisapp.cpp" line="6637"/>
<source>Composer %1</source>
<translation>Druckzusammenstellung %1</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6593"/>
+ <location filename="../src/app/qgisapp.cpp" line="6595"/>
<source> copy</source>
<translation> Kopie</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6629"/>
+ <location filename="../src/app/qgisapp.cpp" line="6631"/>
<source>Loading composer %1</source>
<translation>Lade Zusammenstellung %1</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6841"/>
- <location filename="../src/app/qgisapp.cpp" line="6943"/>
- <location filename="../src/app/qgisapp.cpp" line="6985"/>
+ <location filename="../src/app/qgisapp.cpp" line="6843"/>
+ <location filename="../src/app/qgisapp.cpp" line="6945"/>
+ <location filename="../src/app/qgisapp.cpp" line="6987"/>
<source>No active layer</source>
<translation>Kein aktiver Layer</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6842"/>
+ <location filename="../src/app/qgisapp.cpp" line="6844"/>
<source>No active layer found. Please select a layer in the layer list</source>
<translation>Keinen aktiven Layer gefunden. Bitte einen Layer aus der Liste wählen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6872"/>
- <location filename="../src/app/qgisapp.cpp" line="7014"/>
- <location filename="../src/app/qgisapp.cpp" line="7050"/>
+ <location filename="../src/app/qgisapp.cpp" line="6874"/>
+ <location filename="../src/app/qgisapp.cpp" line="7016"/>
+ <location filename="../src/app/qgisapp.cpp" line="7052"/>
<source>Not enough features selected</source>
<translation>Nicht genug Objekte gewählt</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6873"/>
- <location filename="../src/app/qgisapp.cpp" line="7015"/>
- <location filename="../src/app/qgisapp.cpp" line="7051"/>
+ <location filename="../src/app/qgisapp.cpp" line="6875"/>
+ <location filename="../src/app/qgisapp.cpp" line="7017"/>
+ <location filename="../src/app/qgisapp.cpp" line="7053"/>
<source>The merge tool requires at least two selected features</source>
<translation>Das Verschmelzungswerkzeug erfordert mindestens zwei gewählte Objekte</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6890"/>
+ <location filename="../src/app/qgisapp.cpp" line="6892"/>
<source>Merged feature attributes</source>
<translation>Objektattribute vereinen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6916"/>
- <location filename="../src/app/qgisapp.cpp" line="7095"/>
+ <location filename="../src/app/qgisapp.cpp" line="6918"/>
+ <location filename="../src/app/qgisapp.cpp" line="7097"/>
<source>Invalid result</source>
<translation>Ungültiges Ergebnis</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6917"/>
- <location filename="../src/app/qgisapp.cpp" line="7096"/>
+ <location filename="../src/app/qgisapp.cpp" line="6919"/>
+ <location filename="../src/app/qgisapp.cpp" line="7098"/>
<source>Could not store value '%1' in field of type %2</source>
<translation>Konnte Wert '%1' nicht im Feld des Typs %2 speichern</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6962"/>
+ <location filename="../src/app/qgisapp.cpp" line="6964"/>
<source>Modifying features can only be done for layers in editing mode.</source>
<translation>Objektänderungen können nur im Bearbeitungsmodus vorgenommen werden.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7030"/>
- <location filename="../src/app/qgisapp.cpp" line="7069"/>
+ <location filename="../src/app/qgisapp.cpp" line="7032"/>
+ <location filename="../src/app/qgisapp.cpp" line="7071"/>
<source>Merge failed</source>
<translation>Zusammenführung fehlgeschlagen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7077"/>
+ <location filename="../src/app/qgisapp.cpp" line="7079"/>
<source>Merged features</source>
<translation>Objekte verschmelzen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7217"/>
- <location filename="../src/app/qgisapp.cpp" line="7242"/>
- <location filename="../src/app/qgisapp.cpp" line="7267"/>
- <location filename="../src/app/qgisapp.cpp" line="7285"/>
+ <location filename="../src/app/qgisapp.cpp" line="7219"/>
+ <location filename="../src/app/qgisapp.cpp" line="7244"/>
+ <location filename="../src/app/qgisapp.cpp" line="7269"/>
+ <location filename="../src/app/qgisapp.cpp" line="7287"/>
<source>No active vector layer</source>
<translation>Kein aktiver Vektorlayer</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7218"/>
+ <location filename="../src/app/qgisapp.cpp" line="7220"/>
<source>To invert selection, choose a vector layer in the legend</source>
<translation>Um die Objektauswahl umzukehren einen Vektorlayer in der Legende wählen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7243"/>
+ <location filename="../src/app/qgisapp.cpp" line="7245"/>
<source>To select all, choose a vector layer in the legend</source>
<translation>Um alle Objekte zu wählen einen Vektorlayer in der Legende wählen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7268"/>
- <location filename="../src/app/qgisapp.cpp" line="7286"/>
+ <location filename="../src/app/qgisapp.cpp" line="7270"/>
+ <location filename="../src/app/qgisapp.cpp" line="7288"/>
<source>To select features, choose a vector layer in the legend</source>
<translation>Um Objekte zu wählen einen Vektorlayer in der Legende wählen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7333"/>
+ <location filename="../src/app/qgisapp.cpp" line="7335"/>
<source>Features cut</source>
<translation>Objekte ausgeschnitten</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7359"/>
+ <location filename="../src/app/qgisapp.cpp" line="7361"/>
<source>Features pasted</source>
<translation>Objekte eingefügt</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7457"/>
- <location filename="../src/app/qgisapp.cpp" line="7464"/>
- <location filename="../src/app/qgisapp.cpp" line="7470"/>
- <location filename="../src/app/qgisapp.cpp" line="7575"/>
- <location filename="../src/app/qgisapp.cpp" line="7582"/>
- <location filename="../src/app/qgisapp.cpp" line="7595"/>
- <location filename="../src/app/qgisapp.cpp" line="7610"/>
+ <location filename="../src/app/qgisapp.cpp" line="7474"/>
+ <location filename="../src/app/qgisapp.cpp" line="7481"/>
+ <location filename="../src/app/qgisapp.cpp" line="7487"/>
+ <location filename="../src/app/qgisapp.cpp" line="7592"/>
+ <location filename="../src/app/qgisapp.cpp" line="7599"/>
+ <location filename="../src/app/qgisapp.cpp" line="7612"/>
+ <location filename="../src/app/qgisapp.cpp" line="7627"/>
<source>Paste features</source>
<translation>Objekte einfügen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7458"/>
+ <location filename="../src/app/qgisapp.cpp" line="7475"/>
<source>no features could be successfully pasted.</source>
<translation>Es wurden keine Objekte erfolgreich eingefügt.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7465"/>
+ <location filename="../src/app/qgisapp.cpp" line="7482"/>
<source>%1 features were successfully pasted.</source>
<translation>%1 Objekte wurden erfolgreich eingefügt.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7471"/>
+ <location filename="../src/app/qgisapp.cpp" line="7488"/>
<source>%1 of %2 features could be successfully pasted.</source>
<translation>%1 von %2 Objekte konnte erfolgreich eingefügt werden.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7498"/>
+ <location filename="../src/app/qgisapp.cpp" line="7515"/>
<source>Pasted</source>
<translation>Eingefügt</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7500"/>
+ <location filename="../src/app/qgisapp.cpp" line="7517"/>
<source>Layer name</source>
<translation>Layername</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7576"/>
+ <location filename="../src/app/qgisapp.cpp" line="7593"/>
<source>No features in clipboard.</source>
<translation>Keine Objekte in der Zwischenablage.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7583"/>
+ <location filename="../src/app/qgisapp.cpp" line="7600"/>
<source>Multiple geometry types found, features with geometry different from %1 will be created without geometry.</source>
<translation>Mehrere Geometriearten gefunden, Objekte mit einer anderen Geometrieart als %1 werden ohne Geometrie erzeugt.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7611"/>
+ <location filename="../src/app/qgisapp.cpp" line="7628"/>
<source>Cannot create field %1 (%2,%3)</source>
<translation>Konnte Feld %1 (%2,%3) nicht anlegen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7802"/>
+ <location filename="../src/app/qgisapp.cpp" line="7819"/>
<source>Start editing failed</source>
<translation>Bearbeitungsbeginn schlug fehl</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7803"/>
+ <location filename="../src/app/qgisapp.cpp" line="7820"/>
<source>Provider cannot be opened for editing</source>
<translation>Datenanbieter kann nicht zum Bearbeiten geöffnet werden</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7828"/>
+ <location filename="../src/app/qgisapp.cpp" line="7845"/>
<source>Stop editing</source>
<translation>Bearbeitung beenden</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7829"/>
+ <location filename="../src/app/qgisapp.cpp" line="7846"/>
<source>Do you want to save the changes to layer %1?</source>
<translation>Sollen die Änderungen am Layer %1 gespeichert werden?</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7860"/>
+ <location filename="../src/app/qgisapp.cpp" line="7877"/>
<source>Problems during roll back</source>
<translation>Probleme beim Zurücknehmen der Änderungen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7940"/>
+ <location filename="../src/app/qgisapp.cpp" line="7957"/>
<source>Could not %1 changes to layer %2
Errors: %3
@@ -24998,220 +25333,220 @@ Fehler: %3
</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7941"/>
+ <location filename="../src/app/qgisapp.cpp" line="7958"/>
<source>rollback</source>
<translation>verworfen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7941"/>
+ <location filename="../src/app/qgisapp.cpp" line="7958"/>
<source>cancel</source>
<translation>abgebrochen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7971"/>
+ <location filename="../src/app/qgisapp.cpp" line="7988"/>
<source>Save</source>
<translation>Speichern</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7971"/>
- <location filename="../src/app/qgisapp.cpp" line="7997"/>
- <location filename="../src/app/qgisapp.cpp" line="8023"/>
+ <location filename="../src/app/qgisapp.cpp" line="7988"/>
+ <location filename="../src/app/qgisapp.cpp" line="8014"/>
+ <location filename="../src/app/qgisapp.cpp" line="8040"/>
<source>all</source>
<translation>Alle</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="7997"/>
+ <location filename="../src/app/qgisapp.cpp" line="8014"/>
<source>Rollback</source>
<translation>Verwerfen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8023"/>
+ <location filename="../src/app/qgisapp.cpp" line="8040"/>
<source>Cancel</source>
<translation>Abbrechen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8039"/>
+ <location filename="../src/app/qgisapp.cpp" line="8056"/>
<source>Current edits</source>
<translation>Aktuelle Änderungen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8040"/>
+ <location filename="../src/app/qgisapp.cpp" line="8057"/>
<source>%1 current changes for %2 layer(s)?</source>
<translation>Aktuelle Änderungen für %2 Layer %1?</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8132"/>
+ <location filename="../src/app/qgisapp.cpp" line="8149"/>
<source>You are about to set a subset filter on a layer that has joined fields. Joined fields cannot be filtered, unless you convert the layer to a virtual layer first. Would you like to create a virtual layer out of this layer first?</source>
<translation>Es soll eine Filter auf einen Layer mit verknüpften Feldern gesetzt werden. Verknüpfte Felder können nur gefiltert werden, wenn sie zuvor in einen virtuellen Layer umgewandelt werden. Soll aus diesem Layer ein virtueller Layer erzeugt werden?</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8314"/>
+ <location filename="../src/app/qgisapp.cpp" line="8331"/>
<source>copy</source>
<translation>Kopie</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8318"/>
+ <location filename="../src/app/qgisapp.cpp" line="8335"/>
<source>Plugin layer</source>
<translation>Erweiterungslayer</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8330"/>
+ <location filename="../src/app/qgisapp.cpp" line="8347"/>
<source>Memory layer</source>
<translation>Speicherlayer</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8382"/>
- <location filename="../src/app/qgisapp.cpp" line="8393"/>
+ <location filename="../src/app/qgisapp.cpp" line="8399"/>
+ <location filename="../src/app/qgisapp.cpp" line="8410"/>
<source>Duplicate layer: </source>
<translation>Layerduplizierung:</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8383"/>
+ <location filename="../src/app/qgisapp.cpp" line="8400"/>
<source>%1 (duplication resulted in invalid layer)</source>
<translation>%1 (Kopieren führt zu ungültigem Layer)</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8453"/>
+ <location filename="../src/app/qgisapp.cpp" line="8470"/>
<source>Set scale visibility for selected layers</source>
<translation>Maßstabsabhängige Sichtbarkeit der gewählten Layer setzen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8771"/>
+ <location filename="../src/app/qgisapp.cpp" line="8788"/>
<source>Couldn't load Python support library: %1</source>
<translation>Konnte Python-Unterstützungsbibliothek nicht laden: %1</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8782"/>
+ <location filename="../src/app/qgisapp.cpp" line="8799"/>
<source>Couldn't resolve python support library's instance() symbol.</source>
<translation>Konnte Symbol instance() nicht in Python-Unterstützungsbibliothek finden.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8800"/>
+ <location filename="../src/app/qgisapp.cpp" line="8817"/>
<source>Python support ENABLED :-) </source>
<translation>Python-Unterstützung aktiviert :-) </translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8826"/>
+ <location filename="../src/app/qgisapp.cpp" line="8843"/>
<source>There is a new version of QGIS available</source>
<translation>Eine neue Version von QGIS ist verfügbar</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8830"/>
+ <location filename="../src/app/qgisapp.cpp" line="8847"/>
<source>You are running a development version of QGIS</source>
<translation>Sie verwenden eine Entwicklungsversion von QGIS</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8834"/>
+ <location filename="../src/app/qgisapp.cpp" line="8851"/>
<source>You are running the current version of QGIS</source>
<translation>Sie verwenden die aktuelle Version von QGIS</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8841"/>
- <location filename="../src/app/qgisapp.cpp" line="8847"/>
+ <location filename="../src/app/qgisapp.cpp" line="8858"/>
+ <location filename="../src/app/qgisapp.cpp" line="8864"/>
<source>QGIS Version Information</source>
<translation>QGIS-Versionsinformationen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8847"/>
+ <location filename="../src/app/qgisapp.cpp" line="8864"/>
<source>Unable to get current version information from server</source>
<translation>Kann Informationen zu aktuellen Version nicht vom Server holen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="8972"/>
- <location filename="../src/app/qgisapp.cpp" line="8981"/>
+ <location filename="../src/app/qgisapp.cpp" line="8989"/>
+ <location filename="../src/app/qgisapp.cpp" line="8998"/>
<source>To perform a full histogram stretch, you need to have a raster layer selected.</source>
<translation>Um eine volle Histogrammstreckung durchzuführen, muß ein Rasterlayer gewählt sein.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="9042"/>
- <location filename="../src/app/qgisapp.cpp" line="9051"/>
+ <location filename="../src/app/qgisapp.cpp" line="9059"/>
+ <location filename="../src/app/qgisapp.cpp" line="9068"/>
<source>To change brightness or contrast, you need to have a raster layer selected.</source>
<translation>Um Helligkeit oder Kontrast zu ändern, muß ein Rasterlayer gewählt sein.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="9077"/>
+ <location filename="../src/app/qgisapp.cpp" line="9094"/>
<source>en</source>
<comment>documentation language</comment>
<translation>de</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="9099"/>
+ <location filename="../src/app/qgisapp.cpp" line="9116"/>
<source>https://qgis.org/en/site/forusers/commercial_support.html</source>
<translation>https://qgis.org/de/site/forusers/commercial_support.html</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="9237"/>
- <location filename="../src/app/qgisapp.cpp" line="9280"/>
+ <location filename="../src/app/qgisapp.cpp" line="9254"/>
+ <location filename="../src/app/qgisapp.cpp" line="9297"/>
<source>Layer is not valid</source>
<translation>Layer ist ungültig</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="10022"/>
+ <location filename="../src/app/qgisapp.cpp" line="10039"/>
<source>Current CRS: %1 (OTF enabled)</source>
<translation>Aktuelles KBS: %1 (SRP aktiv)</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="10028"/>
+ <location filename="../src/app/qgisapp.cpp" line="10045"/>
<source>Current CRS: %1 (OTF disabled)</source>
<translation>Aktuelles KBS: %1 (SRP aus)</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11837"/>
+ <location filename="../src/app/qgisapp.cpp" line="11854"/>
<source>Layer %1</source>
<translation>Layer %1</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="9236"/>
+ <location filename="../src/app/qgisapp.cpp" line="9253"/>
<source>The layer %1 is not a valid layer and can not be added to the map</source>
<translation>Der Layer %1 ist ungültig und kann der Karte nicht hinzugefügt werden</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6852"/>
- <location filename="../src/app/qgisapp.cpp" line="6954"/>
- <location filename="../src/app/qgisapp.cpp" line="6995"/>
+ <location filename="../src/app/qgisapp.cpp" line="6854"/>
+ <location filename="../src/app/qgisapp.cpp" line="6956"/>
+ <location filename="../src/app/qgisapp.cpp" line="6997"/>
<source>The merge features tool only works on vector layers.</source>
<translation>Das Verschmeldungswerkzeug funktioniert nur mit Vektorlayern.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6861"/>
- <location filename="../src/app/qgisapp.cpp" line="7003"/>
+ <location filename="../src/app/qgisapp.cpp" line="6863"/>
+ <location filename="../src/app/qgisapp.cpp" line="7005"/>
<source>Merging features can only be done for layers in editing mode.</source>
<translation>Verschmelzung von Objekten kann nur auf Layern im Bearbeitungsmodus erfolgen.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6944"/>
- <location filename="../src/app/qgisapp.cpp" line="6986"/>
+ <location filename="../src/app/qgisapp.cpp" line="6946"/>
+ <location filename="../src/app/qgisapp.cpp" line="6988"/>
<source>Please select a layer in the layer list</source>
<translation>Einen Layer in der Liste wählen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6953"/>
- <location filename="../src/app/qgisapp.cpp" line="6994"/>
+ <location filename="../src/app/qgisapp.cpp" line="6955"/>
+ <location filename="../src/app/qgisapp.cpp" line="6996"/>
<source>Invalid layer</source>
<translation>Ungültiger Layer</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="9279"/>
+ <location filename="../src/app/qgisapp.cpp" line="9296"/>
<source>The layer is not a valid layer and can not be added to the map</source>
<translation>Der Layer ist ungültig und kann daher nicht zum Kartenfenster hinzugefügt werden</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="9375"/>
+ <location filename="../src/app/qgisapp.cpp" line="9392"/>
<source>Project has layer(s) in edit mode with unsaved edits, which will NOT be saved!</source>
<translation>Projekt hat Layer im Bearbeitungsmodus mit nicht gespeicherten Bearbeitungen, die NICHT gespeichert werden!</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="9399"/>
+ <location filename="../src/app/qgisapp.cpp" line="9416"/>
<source>Save?</source>
<translation>Speichern?</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="10240"/>
+ <location filename="../src/app/qgisapp.cpp" line="10257"/>
<source>Maptips require an active layer</source>
<translation>Kartentipps erfordern einen aktuellen Layer</translation>
</message>
<message numerus="yes">
- <location filename="../src/app/qgisapp.cpp" line="10307"/>
+ <location filename="../src/app/qgisapp.cpp" line="10324"/>
<source>%n feature(s) selected on layer %1.</source>
<comment>number of selected features</comment>
<translation>
@@ -25220,77 +25555,77 @@ Fehler: %3
</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="10814"/>
+ <location filename="../src/app/qgisapp.cpp" line="10831"/>
<source>Open a GDAL Supported Raster Data Source</source>
<translation>Öffnen einer GDAL-Rasterdatenquelle</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="10919"/>
+ <location filename="../src/app/qgisapp.cpp" line="10936"/>
<source>Error adding valid layer to map canvas</source>
<translation>Fehler beim Hinzufügen eines gültigen Layers zur Karte</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="10920"/>
+ <location filename="../src/app/qgisapp.cpp" line="10937"/>
<source>Raster layer</source>
<translation>Raster-Layer</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11046"/>
+ <location filename="../src/app/qgisapp.cpp" line="11063"/>
<source>%1 is not a supported raster data source</source>
<translation>%1 ist keine unterstützte Rasterdatenquelle</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11050"/>
+ <location filename="../src/app/qgisapp.cpp" line="11067"/>
<source>Unsupported Data Source</source>
<translation>Nicht unterstütztes Datenformat</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11107"/>
+ <location filename="../src/app/qgisapp.cpp" line="11124"/>
<source>Exit QGIS</source>
<translation>QGIS beenden</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11108"/>
+ <location filename="../src/app/qgisapp.cpp" line="11125"/>
<source>Do you really want to quit QGIS?</source>
<translation>Soll QGIS wirklich beendet werden?</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11211"/>
+ <location filename="../src/app/qgisapp.cpp" line="11228"/>
<source>This project file was saved by an older version of QGIS. When saving this project file, QGIS will update it to the latest version, possibly rendering it useless for older versions of QGIS.</source>
<translation>Dieses Projekt wurde mit einer älteren Version von QGIS gespeichert. Erneutes Speichern der Projektdatei bringt die Datei auf den aktuellen Stand, verursacht u.U. das es mit älteren Versionen von QGIS nicht mehr verwendet werden kann.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11215"/>
+ <location filename="../src/app/qgisapp.cpp" line="11232"/>
<source>Project file is older</source>
<translation>Projektdatei ist älter</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11626"/>
+ <location filename="../src/app/qgisapp.cpp" line="11643"/>
<source> Please check the <a href="#messageLog">message log</a> for further info.</source>
<translation> Bitte untersuchen Sie das <a href="#messageLog">Protokoll</a> auf weitere Informationen.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11625"/>
+ <location filename="../src/app/qgisapp.cpp" line="11642"/>
<source>A network request timed out, any data received is likely incomplete.</source>
<translation>Zeitüberschreitung bei Netzwerkanfrage, empfangene Daten wahrscheinlich nicht vollständig.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11397"/>
+ <location filename="../src/app/qgisapp.cpp" line="11414"/>
<source>Warning</source>
<translation>Warnung</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11398"/>
+ <location filename="../src/app/qgisapp.cpp" line="11415"/>
<source>This layer doesn't have a properties dialog.</source>
<translation>Dieser Layer hat keine Eigenschaftendialog.</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11455"/>
+ <location filename="../src/app/qgisapp.cpp" line="11472"/>
<source>Authentication required</source>
<translation>Authentifikation erforderlich</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="11510"/>
+ <location filename="../src/app/qgisapp.cpp" line="11527"/>
<source>Proxy authentication required</source>
<translation>Proxy-Authentifikation erforderlich</translation>
</message>
@@ -25303,12 +25638,12 @@ Fehler: %3
</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5134"/>
+ <location filename="../src/app/qgisapp.cpp" line="5136"/>
<source>Failed to run Python script:</source>
<translation>Konnte Python-Skript nicht ausführen:</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6356"/>
+ <location filename="../src/app/qgisapp.cpp" line="6358"/>
<source>The current layer has no selected features</source>
<translation>Der aktuelle Layer hat keine gewählten Objekte</translation>
</message>
@@ -25324,7 +25659,7 @@ Fehler: %3
<translation>Zeigt die aktuelle Karte im einen Winkel in Grad im Uhrzeigersinn gedreht an. Der Winkel kann auch eingegeben werden</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="10020"/>
+ <location filename="../src/app/qgisapp.cpp" line="10037"/>
<source>%1 (OTF)</source>
<translation>%1 (SRP)</translation>
</message>
@@ -25335,12 +25670,12 @@ Fehler: %3
<translation>Meldungen</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="5105"/>
+ <location filename="../src/app/qgisapp.cpp" line="5107"/>
<source>Error loading layer definition</source>
<translation>Fehler beim Laden der Layerdefinition</translation>
</message>
<message>
- <location filename="../src/app/qgisapp.cpp" line="6093"/>
+ <location filename="../src/app/qgisapp.cpp" line="6095"/>
<source>Error saving layer definintion file</source>
<translation>Fehler beim Speichern der Layerdefinitionsdatei</translation>
</message>
@@ -26375,7 +26710,7 @@ p, li { white-space: pre-wrap; }
<message>
<location filename="../src/app/qgsapplayertreeviewmenuprovider.cpp" line="124"/>
<source>Zoom to &Visible Scale</source>
- <translation>Auf sichtbaren Maßstab zoomen</translation>
+ <translation>Auf sichtbaren Maßstab &zoomen</translation>
</message>
<message>
<location filename="../src/app/qgsapplayertreeviewmenuprovider.cpp" line="130"/>
@@ -26486,7 +26821,7 @@ p, li { white-space: pre-wrap; }
<translation>qgis-icon-60x60_xmas.png</translation>
</message>
<message>
- <location filename="../src/core/qgsapplication.cpp" line="900"/>
+ <location filename="../src/core/qgsapplication.cpp" line="912"/>
<source>Application state:
QGIS_PREFIX_PATH env var: %1
Prefix: %2
@@ -26513,7 +26848,7 @@ Auth-DB-Pfad: %10
</translation>
</message>
<message>
- <location filename="../src/core/qgsapplication.cpp" line="918"/>
+ <location filename="../src/core/qgsapplication.cpp" line="930"/>
<source>
</source>
<comment>match indentation of application state</comment>
@@ -26521,24 +26856,24 @@ Auth-DB-Pfad: %10
</translation>
</message>
<message>
- <location filename="../src/core/qgsapplication.cpp" line="1263"/>
+ <location filename="../src/core/qgsapplication.cpp" line="1275"/>
<source>[ERROR] Can not make qgis.db private copy</source>
<translation>[FEHLER] Kann private Kopie von qgis.db nicht anlegen</translation>
</message>
<message>
- <location filename="../src/core/qgsapplication.cpp" line="1276"/>
+ <location filename="../src/core/qgsapplication.cpp" line="1288"/>
<source>Could not open qgis.db</source>
<translation>Konnte qgis.db nicht öffnen</translation>
</message>
<message>
- <location filename="../src/core/qgsapplication.cpp" line="1306"/>
+ <location filename="../src/core/qgsapplication.cpp" line="1318"/>
<source>Migration of private qgis.db failed.
%1</source>
<translation>Migration der Benutzer qgis.db schlug fehl.
%1</translation>
</message>
<message>
- <location filename="../src/core/qgsapplication.cpp" line="1341"/>
+ <location filename="../src/core/qgsapplication.cpp" line="1353"/>
<source>Update of view in private qgis.db failed.
%1</source>
<translation>Aktualisierung der Sicht in privater qgis.db gescheitert.
@@ -27194,82 +27529,82 @@ Ausdruckfehler:
<translation>Nicht angewandte Mehrfachänderungen: <a href="#apply">anwenden</a> oder <a href="#reset">zurücksetzen</a>.</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="802"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="810"/>
<source>Invalid fields</source>
<translation>Ungültige Felder</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="902"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="919"/>
<source>Description: </source>
<translation>Beschreibung:</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="903"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="920"/>
<source>Raw expression: </source>
<translation>Rohausdruck:</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="903"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="920"/>
<source>Constraint: </source>
<translation>Einschränkung:</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1289"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1320"/>
<source>&Reset form</source>
<translation>Formular &zurücksetzen</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1296"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1327"/>
<source>&Select features</source>
<translation>&Objekte wählen</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1300"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1331"/>
<source>Select features</source>
<translation>Objekt wählen</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1303"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1334"/>
<source>Add to current selection</source>
<translation>Zu aktuellen Auswahl hinzufügen</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1306"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1337"/>
<source>Filter current selection</source>
<translation>Mit aktueller Auswahl filtern</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1309"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1340"/>
<source>Remove from current selection</source>
<translation>Aus aktueller Auswahl entfernen</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1318"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1349"/>
<source>Filter features</source>
<translation>Objekt filtern</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1323"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1354"/>
<source>Filter within ("AND")</source>
<translation>Filter innerhalb ("AND")</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1326"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1357"/>
<source>Extend filter ("OR")</source>
<translation>Filter erweitern ("OR")</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1334"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1365"/>
<source>Close</source>
<translation>Schließen</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1460"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1491"/>
<source>The python init function (<code>%1</code>) does not accept three arguments as expected!<br>Please check the function name in the <b>Fields</b> tab of the layer properties.</source>
<translation>Die Python-Init-Funktion (<code>%1</code>) akzeptiert wider Erwarten keine drei Argumente!<br>Bitte den Funktionsnamen im Reiter <b>Felder</b> in den Layereigenschaften überprüfen.</translation>
</message>
<message>
- <location filename="../src/gui/qgsattributeform.cpp" line="1476"/>
+ <location filename="../src/gui/qgsattributeform.cpp" line="1507"/>
<source>The python init function (<code>%1</code>) could not be found!<br>Please check the function name in the <b>Fields</b> tab of the layer properties.</source>
<translation>Die Python-Init-Funktion (<code>%1</code>) wurde nicht gefunden!<br>Bitte den Funktionsnamen im Reiter <b>Felder</b> der Layereigenschaften überprüfen.</translation>
</message>
@@ -27827,12 +28162,12 @@ Ausdruckfehler:
<context>
<name>QgsAttributeTableModel</name>
<message>
- <location filename="../src/gui/attributetable/qgsattributetablemodel.cpp" line="553"/>
+ <location filename="../src/gui/attributetable/qgsattributetablemodel.cpp" line="548"/>
<source>extra column</source>
<translation>Zusätzliche Spalte</translation>
</message>
<message>
- <location filename="../src/gui/attributetable/qgsattributetablemodel.cpp" line="561"/>
+ <location filename="../src/gui/attributetable/qgsattributetablemodel.cpp" line="556"/>
<source>Feature ID: %1</source>
<translation>Objektkennung: %1</translation>
</message>
@@ -27853,27 +28188,47 @@ Ausdruckfehler:
<translation>Bearbeitungselement bearbeiten</translation>
</message>
<message>
- <location filename="../src/ui/qgsattributetypeedit.ui" line="20"/>
+ <location filename="../src/ui/qgsattributetypeedit.ui" line="23"/>
+ <source>Constraints</source>
+ <translation>Restriktionen</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgsattributetypeedit.ui" line="77"/>
<source>Editable</source>
<translation>Änderbar</translation>
</message>
<message>
- <location filename="../src/ui/qgsattributetypeedit.ui" line="30"/>
+ <location filename="../src/ui/qgsattributetypeedit.ui" line="87"/>
+ <source>Defaults</source>
+ <translation>Vorgaben</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgsattributetypeedit.ui" line="93"/>
+ <source>Default value</source>
+ <translation>Vorgabewert</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgsattributetypeedit.ui" line="100"/>
+ <source>Preview</source>
+ <translation>Vorschau</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgsattributetypeedit.ui" line="124"/>
<source>Label on top</source>
<translation>Beschriftung darüber</translation>
</message>
<message>
- <location filename="../src/ui/qgsattributetypeedit.ui" line="56"/>
+ <location filename="../src/ui/qgsattributetypeedit.ui" line="29"/>
<source>Not null</source>
<translation>Nicht Null</translation>
</message>
<message>
- <location filename="../src/ui/qgsattributetypeedit.ui" line="68"/>
+ <location filename="../src/ui/qgsattributetypeedit.ui" line="41"/>
<source>Constraint</source>
<translation>Einschränkung</translation>
</message>
<message>
- <location filename="../src/ui/qgsattributetypeedit.ui" line="85"/>
+ <location filename="../src/ui/qgsattributetypeedit.ui" line="62"/>
<source>Constraint description</source>
<translation>Einschränkungsbeschreibung</translation>
</message>
@@ -27984,7 +28339,7 @@ Operation kann nicht zurückgenommen werden!</translation>
<message>
<location filename="../src/gui/auth/qgsauthauthoritieseditor.cpp" line="526"/>
<source>Certificate could not found in database for id %1:</source>
- <translation>Zertifikat für %1 wurde nicht in der Datenbank gefunden</translation>
+ <translation>Zertifikat für %1 wurde nicht in der Datenbank gefunden:</translation>
</message>
<message>
<location filename="../src/gui/auth/qgsauthauthoritieseditor.cpp" line="533"/>
@@ -29174,7 +29529,7 @@ Autoritäten/Aussteller: %1%2</translation>
<message>
<location filename="../src/core/auth/qgsauthmanager.cpp" line="152"/>
<source>No authentication method plugins found</source>
- <translation>Keine Erweiterungen mit Authentifizierungsmethoden verfügbar.</translation>
+ <translation>Keine Erweiterungen mit Authentifizierungsmethoden verfügbar</translation>
</message>
<message>
<location filename="../src/core/auth/qgsauthmanager.cpp" line="159"/>
@@ -29190,7 +29545,7 @@ Autoritäten/Aussteller: %1%2</translation>
<location filename="../src/core/auth/qgsauthmanager.cpp" line="186"/>
<location filename="../src/core/auth/qgsauthmanager.cpp" line="1297"/>
<source>Auth db is not readable or writable by user</source>
- <translation>Auth-DB ist nicht durch Benutzer les- oder schreibbar.</translation>
+ <translation>Auth-DB ist nicht durch Benutzer les- oder schreibbar</translation>
</message>
<message>
<location filename="../src/core/auth/qgsauthmanager.cpp" line="273"/>
@@ -29384,7 +29739,7 @@ Autoritäten/Aussteller: %1%2</translation>
<message>
<location filename="../src/core/auth/qgsauthmanager.cpp" line="1949"/>
<source>Authentication database contains duplicate SSL cert custom configs for host:port: %1</source>
- <translation>Authentifizierungdatenbank enthält doppelte SSL-Zertifikatsbenutzerkonfigurationen for host:port, id: %1, %2</translation>
+ <translation>Authentifizierungdatenbank enthält doppelte SSL-Zertifikatsbenutzerkonfigurationen for host:port: %1</translation>
</message>
<message>
<location filename="../src/core/auth/qgsauthmanager.cpp" line="2288"/>
@@ -29855,7 +30210,7 @@ Operation kann nicht zurückgenommen werden!</translation>
<message>
<location filename="../src/ui/auth/qgsauthsslerrorsdialog.ui" line="231"/>
<source>WARNING: Only save SSL configurations when necessary.</source>
- <translation>WARNUNG: Nur SSL-Konfiguration speichern wenn nötig</translation>
+ <translation>WARNUNG: Nur SSL-Konfiguration speichern wenn nötig.</translation>
</message>
</context>
<context>
@@ -30025,7 +30380,7 @@ Operation kann nicht zurückgenommen werden!</translation>
<message>
<location filename="../src/gui/auth/qgsauthtrustedcasdialog.cpp" line="90"/>
<source>Serial #</source>
- <translation>Seriennr.</translation>
+ <translation>Seriennr. </translation>
</message>
<message>
<location filename="../src/gui/auth/qgsauthtrustedcasdialog.cpp" line="91"/>
@@ -31058,32 +31413,32 @@ Sollen die vorhandenen Klassen vor der Klassifizierung gelöscht werden?</transl
<translation>Keine Farbe</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorbuttonv2.cpp" line="422"/>
+ <location filename="../src/gui/qgscolorbuttonv2.cpp" line="450"/>
<source>Clear color</source>
<translation>Farbe leeren</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorbuttonv2.cpp" line="431"/>
+ <location filename="../src/gui/qgscolorbuttonv2.cpp" line="459"/>
<source>Default color</source>
<translation>Vorgabefarbe</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorbuttonv2.cpp" line="471"/>
+ <location filename="../src/gui/qgscolorbuttonv2.cpp" line="499"/>
<source>Copy color</source>
<translation>Farbe kopieren</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorbuttonv2.cpp" line="475"/>
+ <location filename="../src/gui/qgscolorbuttonv2.cpp" line="503"/>
<source>Paste color</source>
<translation>Farbe einfügen</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorbuttonv2.cpp" line="494"/>
+ <location filename="../src/gui/qgscolorbuttonv2.cpp" line="522"/>
<source>Pick color</source>
<translation>Farbe abgreifen</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorbuttonv2.cpp" line="498"/>
+ <location filename="../src/gui/qgscolorbuttonv2.cpp" line="526"/>
<source>Choose color...</source>
<translation>Farbe auswählen...</translation>
</message>
@@ -31237,12 +31592,12 @@ Sollen die vorhandenen Klassen vor der Klassifizierung gelöscht werden?</transl
<context>
<name>QgsColorSchemeModel</name>
<message>
- <location filename="../src/gui/qgscolorschemelist.cpp" line="393"/>
+ <location filename="../src/gui/qgscolorschemelist.cpp" line="398"/>
<source>Color</source>
<translation>Farbe</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorschemelist.cpp" line="395"/>
+ <location filename="../src/gui/qgscolorschemelist.cpp" line="400"/>
<source>Label</source>
<translation>Beschriftung</translation>
</message>
@@ -31250,8 +31605,8 @@ Sollen die vorhandenen Klassen vor der Klassifizierung gelöscht werden?</transl
<context>
<name>QgsColorSliderWidget</name>
<message>
- <location filename="../src/gui/qgscolorwidgets.cpp" line="1288"/>
- <location filename="../src/gui/qgscolorwidgets.cpp" line="1315"/>
+ <location filename="../src/gui/qgscolorwidgets.cpp" line="1309"/>
+ <location filename="../src/gui/qgscolorwidgets.cpp" line="1336"/>
<source>%</source>
<translation>%</translation>
</message>
@@ -31259,7 +31614,7 @@ Sollen die vorhandenen Klassen vor der Klassifizierung gelöscht werden?</transl
<context>
<name>QgsColorSwatchDelegate</name>
<message>
- <location filename="../src/gui/qgscolorschemelist.cpp" line="697"/>
+ <location filename="../src/gui/qgscolorschemelist.cpp" line="702"/>
<source>Select color</source>
<translation>Farbe wählen</translation>
</message>
@@ -31275,32 +31630,32 @@ Sollen die vorhandenen Klassen vor der Klassifizierung gelöscht werden?</transl
<context>
<name>QgsColorTextWidget</name>
<message>
- <location filename="../src/gui/qgscolorwidgets.cpp" line="1460"/>
+ <location filename="../src/gui/qgscolorwidgets.cpp" line="1481"/>
<source>rgb( %1, %2, %3 )</source>
<translation>rgb(%1, %2, %3 )</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorwidgets.cpp" line="1463"/>
+ <location filename="../src/gui/qgscolorwidgets.cpp" line="1484"/>
<source>rgba( %1, %2, %3, %4 )</source>
<translation>rgba(%1, %2, %3, %4 )</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorwidgets.cpp" line="1499"/>
+ <location filename="../src/gui/qgscolorwidgets.cpp" line="1520"/>
<source>#RRGGBB</source>
<translation>#RRGGBB</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorwidgets.cpp" line="1501"/>
+ <location filename="../src/gui/qgscolorwidgets.cpp" line="1522"/>
<source>#RRGGBBAA</source>
<translation>#RRGGBBAA</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorwidgets.cpp" line="1503"/>
+ <location filename="../src/gui/qgscolorwidgets.cpp" line="1524"/>
<source>rgb( r, g, b )</source>
<translation>rgb( r, g, b )</translation>
</message>
<message>
- <location filename="../src/gui/qgscolorwidgets.cpp" line="1505"/>
+ <location filename="../src/gui/qgscolorwidgets.cpp" line="1526"/>
<source>rgba( r, g, b, a )</source>
<translation>rgba( r, g, b, a )</translation>
</message>
@@ -36182,32 +36537,32 @@ Bitte versuchen Sie eine niedrigere Auflösung oder ein kleineres Papierformat</
<context>
<name>QgsComposerMouseHandles</name>
<message>
- <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="607"/>
+ <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="612"/>
<source>Change item position</source>
<translation>Elementposition ändern</translation>
</message>
<message>
- <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="632"/>
+ <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="637"/>
<source>Change item size</source>
<translation>Elementgröße ändern</translation>
</message>
<message>
- <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="698"/>
+ <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="703"/>
<source>%1 items selected</source>
<translation>%1 Elemente gewählt</translation>
</message>
<message>
- <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="703"/>
+ <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="708"/>
<source>1 item selected</source>
<translation>1 Element gewählt</translation>
</message>
<message>
- <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="842"/>
+ <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="847"/>
<source>dx: %1 mm dy: %2 mm</source>
<translation>dx %1 mm dy: %2 mm</translation>
</message>
<message>
- <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="1097"/>
+ <location filename="../src/core/composer/qgscomposermousehandles.cpp" line="1102"/>
<source>width: %1 mm height: %2 mm</source>
<translation>Breite: %1 mm Höhe: %2 mm</translation>
</message>
@@ -38092,7 +38447,7 @@ Bitte versuchen Sie eine niedrigere Auflösung oder ein kleineres Papierformat</
<message>
<location filename="../src/ui/composer/qgscompositionwidgetbase.ui" line="500"/>
<source>Specifies the map which is used to georeference composer exports</source>
- <translation>Gibt die Karte an, die zur Georeferenzierung von Zusammenstellungsexporten verwendet wird.</translation>
+ <translation>Gibt die Karte an, die zur Georeferenzierung von Zusammenstellungsexporten verwendet wird</translation>
</message>
<message>
<location filename="../src/ui/composer/qgscompositionwidgetbase.ui" line="603"/>
@@ -38190,83 +38545,83 @@ Bitte versuchen Sie eine niedrigere Auflösung oder ein kleineres Papierformat</
<context>
<name>QgsCompoundColorWidget</name>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="256"/>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="298"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="268"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="310"/>
<source>Select palette file</source>
<translation>Palettendatei wählen</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="267"/>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="276"/>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="309"/>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="322"/>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="329"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="279"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="288"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="321"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="334"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="341"/>
<source>Invalid file</source>
<translation>Ungültige Datei</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="267"/>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="309"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="279"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="321"/>
<source>Error, file does not exist or is not readable</source>
<translation>Fehler, Datei nicht vorhanden oder nicht lesbar</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="276"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="288"/>
<source>Error, no colors found in palette file</source>
<translation>Fehler, keine Farben in der Palettendatei gefunden</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="322"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="334"/>
<source>Palette file is not readable</source>
<translation>Palettendatei ist nicht lesbar</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="329"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="341"/>
<source>No colors found in palette file</source>
<translation>Keine Farbe in Palettendatei gefunden</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="362"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="374"/>
<source>Remove Color Palette</source>
<translation>Aktuelle Farbpalette entfernen</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="363"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="375"/>
<source>Are you sure you want to remove %1?</source>
<translation>Wollen Sie %1 wirklich löschen?</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="387"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="399"/>
<source>Create New Palette</source>
<translation>Neue Palette anlegen</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="387"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="399"/>
<source>Enter a name for the new palette:</source>
<translation>Name für neue Palette eingeben:</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="388"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="400"/>
<source>New palette</source>
<translation>Neue Palette</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="402"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="414"/>
<source>new_palette</source>
<translation>neue_palette</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="440"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="452"/>
<source>Palette file</source>
<translation>Palettendatei</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="460"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="472"/>
<source>Error exporting</source>
<translation>Fehler beim Export</translation>
</message>
<message>
- <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="460"/>
+ <location filename="../src/gui/qgscompoundcolorwidget.cpp" line="472"/>
<source>Error writing palette file</source>
<translation>Fehler beim Schreiben der Palettendatei</translation>
</message>
@@ -38274,170 +38629,175 @@ Bitte versuchen Sie eine niedrigere Auflösung oder ein kleineres Papierformat</
<context>
<name>QgsCompoundColorWidgetBase</name>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="45"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="283"/>
<source>H</source>
<translation>H</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="66"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="304"/>
<source>S</source>
<translation>S</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="87"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="325"/>
<source>V</source>
<translation>V</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="108"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="346"/>
<source>R</source>
<translation>R</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="129"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="367"/>
<source>G</source>
<translation>G</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="150"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="388"/>
<source>B</source>
<translation>B</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="164"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="402"/>
<source>Opacity</source>
<translation>Deckkraft</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="178"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="416"/>
<source>HTML notation</source>
<translation>HTML-Notation</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="533"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="51"/>
<source>Color ramp</source>
<translation>Farbverlauf</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="553"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="71"/>
<source>Color wheel</source>
<translation>Farbkreis</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="570"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="88"/>
<source>Color swatches</source>
<translation>Farbproben</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="587"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="105"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="652"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="170"/>
<source>Color picker</source>
<translation>Farbwahl</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="660"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="178"/>
<source>Sample average radius</source>
<translation>Auswahldurchschnittradius</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="667"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="185"/>
<source> px</source>
<translation> px</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="682"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="200"/>
<source>Sample color</source>
<translation>Beispielfarbe</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="689"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="207"/>
<source><i>Press space to sample a color from under the mouse cursor</i></source>
<translation><i>Drücken der Leertaste aktiviert bzw. deaktiviert Farbauswahl per Mauszeiger</i></translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="755"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="447"/>
<source>Current</source>
<translation>Aktuell</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="765"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="457"/>
<source>Old</source>
<translation>Alt</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="848"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="854"/>
<source>Import Colors...</source>
<translation>Farben importieren...</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="851"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="857"/>
<source>Import colors from file</source>
<translation>Farben aus Datei importieren</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="856"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="862"/>
<source>Export Colors...</source>
<translation>Farben exportieren...</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="859"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="865"/>
<source>Export colors to file</source>
<translation>Farben in Datei speichern</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="864"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="870"/>
<source>Paste Colors</source>
<translation>Farben einfügen</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="867"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="873"/>
<source>Paste colors from clipboard</source>
<translation>Farben aus Zwischenablage einfügen</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="872"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="878"/>
<source>Import Palette...</source>
<translation>Palette importieren...</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="875"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="881"/>
<source>Import palette from file</source>
<translation>Palette aus Datei importieren</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="880"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="886"/>
<source>Remove Palette</source>
<translation>Palette entfernen</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="883"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="889"/>
<source>Remove current palette</source>
<translation>Aktuelle Palette entfernen</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="888"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="894"/>
<source>New Palette...</source>
<translation>Neue Palette...</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="891"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="897"/>
<source>Create a new palette</source>
<translation>Neue Palette anlegen</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="896"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="902"/>
<source>Copy Colors</source>
<translation>Farben kopieren</translation>
</message>
<message>
- <location filename="../src/ui/qgscompoundcolorwidget.ui" line="899"/>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="905"/>
<source>Copy selected colors</source>
<translation>Gewählte Farben kopieren</translation>
</message>
+ <message>
+ <location filename="../src/ui/qgscompoundcolorwidget.ui" line="913"/>
+ <source>Show in Color Buttons</source>
+ <translation>Farbknöpfe anzeigen</translation>
+ </message>
</context>
<context>
<name>QgsConfigureShortcutsDialog</name>
@@ -38820,7 +39180,7 @@ und aktuelle Datei ist [%3]</translation>
<message>
<location filename="../src/ui/qgscredentialdialog.ui" line="182"/>
<source>Saved for session, until app is quit.</source>
- <translation>Für Sitzung gespeichert bis Anwendung beendet wird</translation>
+ <translation>Für Sitzung gespeichert bis Anwendung beendet wird.</translation>
</message>
<message>
<location filename="../src/ui/qgscredentialdialog.ui" line="192"/>
@@ -38861,7 +39221,7 @@ und aktuelle Datei ist [%3]</translation>
<message>
<location filename="../src/gui/qgscredentialdialog.cpp" line="142"/>
<source>Password attempts: %1</source>
- <translation>Paßwortversuche: #</translation>
+ <translation>Paßwortversuche: %1</translation>
</message>
</context>
<context>
@@ -41659,42 +42019,42 @@ nicht angezeigt</translation>
<translation>Transparenter Umriß</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="117"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="120"/>
<source>Around Point</source>
<translation>Um Punkt</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="118"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="121"/>
<source>Over Point</source>
<translation>Über Punkt</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="122"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="125"/>
<source>Around Line</source>
<translation>Um Linie</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="123"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="126"/>
<source>Over Line</source>
<translation>Über Linie</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="127"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="130"/>
<source>Around Centroid</source>
<translation>Um Zentroid</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="128"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="131"/>
<source>Over Centroid</source>
<translation>Über Zentroid</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="129"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="132"/>
<source>Perimeter</source>
<translation>Umfang</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="130"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="133"/>
<source>Inside Polygon</source>
<translation>In Polygon</translation>
</message>
@@ -41719,105 +42079,105 @@ nicht angezeigt</translation>
<translation>Histogramm</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="138"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="141"/>
<source>Height</source>
<translation>Höhe</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="139"/>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="204"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="142"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="207"/>
<source>x-height</source>
<translation>X-Höhe</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="141"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="144"/>
<source>Area</source>
<translation>Fläche</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="142"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="145"/>
<source>Diameter</source>
<translation>Durchmesser</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="144"/>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="145"/>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="152"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="147"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="148"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="155"/>
<source>None</source>
<translation>Keine</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="147"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="150"/>
<source>Top</source>
<translation>Oben</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="148"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="151"/>
<source>Right</source>
<translation>Rechts</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="149"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="152"/>
<source>Bottom</source>
<translation>Unten</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="150"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="153"/>
<source>Left</source>
<translation>Links</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="413"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="416"/>
<source>Unknown diagram type.</source>
<translation>Unbekannter Diagrammtyp.</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="414"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="417"/>
<source>The diagram type '%1' is unknown. A default type is selected for you.</source>
<translation>Der Diagrammtyp '%1' ist unbekannt. Ein vordefinierter Typ wurde gewählt.</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="467"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="470"/>
<source>Bar length: Scale linearly, so that the following value matches the specified bar length:</source>
<translation>Balkenlängen: Linear skalieren, sodaß der folgende Wert der angegeben Balkenlänge entspricht:</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="468"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="471"/>
<source>Bar length</source>
<translation>Balkenlänge</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="477"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="480"/>
<source>Size</source>
<translation>Größe</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="476"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="479"/>
<source>Scale linearly between 0 and the following attribute value / diagram size:</source>
<translation>Linear zwischen 0 und dem folgenden Attribut- / der Diagrammgröße skalieren:</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="634"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="657"/>
<source>Diagrams: No attributes added.</source>
<translation>Diagramme: Keine Attribute hinzugefügt.</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="678"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="701"/>
<source>Interpolation value</source>
<translation>Interpolationswert</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="679"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="702"/>
<source>You did not specify an interpolation value. A default value of %1 has been set.</source>
<translation>Sie haben keinen Interpolationswert angegeben. Ein Vorgabewert %1 wurde gesetzt.</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="852"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="868"/>
<source>Expression based attribute</source>
<translation>Ausdrucksbasiertes Attribut</translation>
</message>
<message>
- <location filename="../src/app/qgsdiagramproperties.cpp" line="635"/>
+ <location filename="../src/app/qgsdiagramproperties.cpp" line="658"/>
<source>You did not add any attributes to this diagram layer. Please specify the attributes to visualize on the diagrams or disable diagrams.</source>
<translation>Die haben keine Attribute zu diesem Diagrammlayer hinzugefügt. Bitte anzuzeigende Attribute festlegen oder Diagramme abschalten.</translation>
</message>
@@ -42273,47 +42633,47 @@ Parser-Fehler:
<translation>&Sortieren...</translation>
</message>
<message>
- <location filename="../src/gui/attributetable/qgsdualview.cpp" line="558"/>
+ <location filename="../src/gui/attributetable/qgsdualview.cpp" line="556"/>
<source>Set column width</source>
<translation>Spaltenbreite setzen</translation>
</message>
<message>
- <location filename="../src/gui/attributetable/qgsdualview.cpp" line="558"/>
+ <location filename="../src/gui/attributetable/qgsdualview.cpp" line="556"/>
<source>Enter column width</source>
<translation>Spaltenbreite eingeben</translation>
</message>
<message>
- <location filename="../src/gui/attributetable/qgsdualview.cpp" line="586"/>
+ <location filename="../src/gui/attributetable/qgsdualview.cpp" line="583"/>
<source>Configure attribute table sort order</source>
<translation>Attributsortierreihenfolge einstellen</translation>
</message>
<message>
- <location filename="../src/gui/attributetable/qgsdualview.cpp" line="594"/>
+ <location filename="../src/gui/attributetable/qgsdualview.cpp" line="591"/>
<source>Defined sort order in attribute table</source>
<translation>Definierte Sortierreihenfolge in Attributtabelle</translation>
</message>
<message>
- <location filename="../src/gui/attributetable/qgsdualview.cpp" line="613"/>
+ <location filename="../src/gui/attributetable/qgsdualview.cpp" line="610"/>
<source>Sort ascending</source>
<translation>Absteigend sortieren</translation>
</message>
<message>
- <location filename="../src/gui/attributetable/qgsdualview.cpp" line="732"/>
+ <location filename="../src/gui/attributetable/qgsdualview.cpp" line="729"/>
<source>Loading features...</source>
<translation>Lade Objekte...</translation>
</message>
<message>
- <location filename="../src/gui/attributetable/qgsdualview.cpp" line="732"/>
+ <location filename="../src/gui/attributetable/qgsdualview.cpp" line="729"/>
<source>Abort</source>
<translation>Abbrechen</translation>
</message>
<message>
- <location filename="../src/gui/attributetable/qgsdualview.cpp" line="733"/>
+ <location filename="../src/gui/attributetable/qgsdualview.cpp" line="730"/>
<source>Attribute table</source>
<translation>Attributtabelle</translation>
</message>
<message>
- <location filename="../src/gui/attributetable/qgsdualview.cpp" line="739"/>
+ <location filename="../src/gui/attributetable/qgsdualview.cpp" line="736"/>
<source>%1 features loaded.</source>
<translation>%1 Objekte geladen.</translation>
</message>
@@ -42352,12 +42712,17 @@ Parser-Fehler:
<context>
<name>QgsDxfExportDialog</name>
<message>
- <location filename="../src/app/qgsdxfexportdialog.cpp" line="560"/>
+ <location filename="../src/app/qgsdxfexportdialog.cpp" line="470"/>
+ <source>Select the coordinate reference system for the dxf file. The data points will be transformed from the layer coordinate reference system.</source>
+ <translation>Koordinatenbezugssystem für die DXF-Datei wählen. Die Datenpunkte werden vom Koordinatenbezugssystem des Layers transformiert.</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgsdxfexportdialog.cpp" line="573"/>
<source>Export as DXF</source>
<translation>Als DXF exportieren</translation>
</message>
<message>
- <location filename="../src/app/qgsdxfexportdialog.cpp" line="560"/>
+ <location filename="../src/app/qgsdxfexportdialog.cpp" line="573"/>
<source>DXF files *.dxf *.DXF</source>
<translation>DXF-Dateien *.dxf *.DXF</translation>
</message>
@@ -42370,37 +42735,37 @@ Parser-Fehler:
<translation>DXF-Export</translation>
</message>
<message>
- <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="73"/>
+ <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="53"/>
<source>Symbology mode</source>
<translation>Darstellungsmodus</translation>
</message>
<message>
- <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="80"/>
+ <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="60"/>
<source>Symbology scale</source>
<translation>Darstellungsmaßstab</translation>
</message>
<message>
- <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="47"/>
+ <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="27"/>
<source>Save as</source>
<translation>Speichern als</translation>
</message>
<message>
- <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="30"/>
+ <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="20"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
- <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="55"/>
+ <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="35"/>
<source>No symbology</source>
<translation>Keine Darstellung</translation>
</message>
<message>
- <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="60"/>
+ <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="40"/>
<source>Feature symbology</source>
<translation>Objektdarstellung</translation>
</message>
<message>
- <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="65"/>
+ <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="45"/>
<source>Symbol layer symbology</source>
<translation>Symbollayerdarstellung</translation>
</message>
@@ -42434,6 +42799,11 @@ Parser-Fehler:
<source>Use layer title as name if set</source>
<translation>Layertitel als Namen verwenden, wenn vorhanden</translation>
</message>
+ <message>
+ <location filename="../src/ui/qgsdxfexportdialogbase.ui" line="162"/>
+ <source>CRS</source>
+ <translation>KBS</translation>
+ </message>
</context>
<context>
<name>QgsEditorWidgetRegistry</name>
@@ -42568,12 +42938,12 @@ Parser-Fehler:
<context>
<name>QgsEffectStackCompactWidget</name>
<message>
- <location filename="../src/gui/effects/qgseffectstackpropertieswidget.cpp" line="395"/>
+ <location filename="../src/gui/effects/qgseffectstackpropertieswidget.cpp" line="405"/>
<source>Draw effects</source>
<translation>Zeicheneffekte</translation>
</message>
<message>
- <location filename="../src/gui/effects/qgseffectstackpropertieswidget.cpp" line="400"/>
+ <location filename="../src/gui/effects/qgseffectstackpropertieswidget.cpp" line="410"/>
<source>Customise effects</source>
<translation>Effekte einstellen</translation>
</message>
@@ -42581,7 +42951,7 @@ Parser-Fehler:
<context>
<name>QgsEffectStackPropertiesDialog</name>
<message>
- <location filename="../src/gui/effects/qgseffectstackpropertieswidget.cpp" line="359"/>
+ <location filename="../src/gui/effects/qgseffectstackpropertieswidget.cpp" line="369"/>
<source>Effect Properties</source>
<translation>Effekteigenschaften</translation>
</message>
@@ -42589,7 +42959,7 @@ Parser-Fehler:
<context>
<name>QgsEffectStackPropertiesWidget</name>
<message>
- <location filename="../src/gui/effects/qgseffectstackpropertieswidget.cpp" line="137"/>
+ <location filename="../src/gui/effects/qgseffectstackpropertieswidget.cpp" line="147"/>
<source>Effects Properties</source>
<translation>Effekteigenschaften</translation>
</message>
@@ -42809,198 +43179,197 @@ p, li { white-space: pre-wrap; }
<context>
<name>QgsExpression</name>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="3693"/>
- <location filename="../src/core/qgsexpression.cpp" line="3705"/>
- <location filename="../src/core/qgsexpression.cpp" line="3744"/>
- <location filename="../src/core/qgsexpression.cpp" line="3756"/>
+ <location filename="../src/core/qgsexpression.cpp" line="3812"/>
+ <location filename="../src/core/qgsexpression.cpp" line="3824"/>
+ <location filename="../src/core/qgsexpression.cpp" line="3863"/>
+ <location filename="../src/core/qgsexpression.cpp" line="3875"/>
<source>No root node! Parsing failed?</source>
<translation>Kein Wurzelknoten! Parsen gescheitert?</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="3788"/>
<source>(no root)</source>
- <translation>(Keine Wurzel)</translation>
+ <translation type="obsolete">(Keine Wurzel)</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="3985"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4104"/>
<source>Unary minus only for numeric values.</source>
<translation>Negatives Vorzeichen nur für nummerische Werte.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4057"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4176"/>
<source>Can't preform /, *, or % on DateTime and Interval</source>
<translation>Kann /, * or % nicht auf Daten oder Intervallen ausführen</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4657"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4800"/>
<source>[unsupported type;%1; value:%2]</source>
<translation>[nicht unterstützter Typ;%1; Wert:%2]</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4708"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4851"/>
<source>Column '%1' not found</source>
<translation>Spalte '%1' nicht gefunden</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4824"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4967"/>
<source>function help for %1 missing</source>
<translation>Funktionshilfe für %1 fehlt</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4829"/>
- <location filename="../src/core/qgsexpression.cpp" line="4849"/>
- <location filename="../src/core/qgsexpression.cpp" line="4865"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4972"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4992"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5008"/>
<source>group</source>
<translation>Gruppe</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4839"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4982"/>
<source>%1 %2</source>
<translation>%1 %2</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4850"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4993"/>
<source>Syntax</source>
<translation>Syntax</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4852"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4995"/>
<source>operator</source>
<translation>Operator</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4869"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5012"/>
<source>function</source>
<translation>Funktion</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4898"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5041"/>
<source>Arguments</source>
<translation>Argumente</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4913"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5056"/>
<source>Examples</source>
<translation>Beispiele</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4930"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5073"/>
<source>Notes</source>
<translation>Hinweise</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5034"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5177"/>
<source>General</source>
<translation>Allgemein</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5035"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5178"/>
<source>Operators</source>
<translation>Operatoren</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5036"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5179"/>
<source>Conditionals</source>
<translation>Bedingungen</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5037"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5180"/>
<source>Fields and Values</source>
<translation>Felder und Werte</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5038"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5181"/>
<source>Math</source>
<translation>Mathematik</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5039"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5182"/>
<source>Conversions</source>
<translation>Umwandlungen</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5040"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5183"/>
<source>Date and Time</source>
<translation>Datum und Zeit</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5041"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5184"/>
<source>String</source>
<translation>Zeichenketten</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5042"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5185"/>
<source>Color</source>
<translation>Farbe</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5043"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5186"/>
<source>Geometry</source>
<translation>Geometrie</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5044"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5187"/>
<source>Record</source>
<translation>Datensatz</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5045"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5188"/>
<source>Variables</source>
<translation>Variablen</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5046"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5189"/>
<source>Fuzzy Matching</source>
<translation>Unscharfer Vergleich</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5047"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5190"/>
<source>Recent (%1)</source>
<translation>Letztes (%1)</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5063"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5206"/>
<source><i><empty geometry></i></source>
<translation><i><leere Geometrie></i></translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5065"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5208"/>
<source><i><geometry: %1></i></source>
<translation><i><Geometrie: %1></i></translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5071"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5214"/>
<source><i><feature: %1></i></source>
<translation><i><Objekt: %1></i></translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5077"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5220"/>
<source><i><interval: %1 days></i></source>
<translation><i><Intervall: %1 Tage></i></translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5082"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5225"/>
<source><i><date: %1></i></source>
<translation><i><date: %1></i></translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5087"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5230"/>
<source><i><time: %1></i></source>
<translation><i><time: %1></i></translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5092"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5235"/>
<source><i><datetime: %1></i></source>
<translation><i><datetime: %1></i></translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5099"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5242"/>
<source>'%1...'</source>
<translation>'%1...'</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4849"/>
- <location filename="../src/core/qgsexpression.cpp" line="4865"/>
+ <location filename="../src/core/qgsexpression.cpp" line="4992"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5008"/>
<source>expression</source>
<translation>Ausdruck</translation>
</message>
@@ -43364,7 +43733,7 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<source>pattern to find</source>
- <translation>Zu suchendes Muster</translation>
+ <translation type="obsolete">Zu suchendes Muster</translation>
</message>
<message>
<source>'A' ILIKE 'A'</source>
@@ -43388,11 +43757,11 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<source>'ABC' ILIKE '%b%'</source>
- <translation>'ABC' ILIKE '%b%'</translation>
+ <translation type="obsolete">'ABC' ILIKE '%b%'</translation>
</message>
<message>
<source>'ABC' ILIKE '%B%'</source>
- <translation>'ABC' ILIKE '%B%'</translation>
+ <translation type="obsolete">'ABC' ILIKE '%B%'</translation>
</message>
<message>
<source>Returns 1 if value is found within a list of values.</source>
@@ -43488,7 +43857,7 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<source>pattern to compare value with</source>
- <translation>Mit Wert zu vergleichendes Muster</translation>
+ <translation type="obsolete">Mit Wert zu vergleichendes Muster</translation>
</message>
<message>
<source>'A' LIKE 'A'</source>
@@ -43508,7 +43877,7 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<source>'ABC' LIKE '%B%'</source>
- <translation>'ABC' LIKE '%B%'</translation>
+ <translation type="obsolete">'ABC' LIKE '%B%'</translation>
</message>
<message>
<source>This group contains math functions e.g square root, sin and cos</source>
@@ -45442,6 +45811,30 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
<translation>Y-Koordinate des Punkts</translation>
</message>
<message>
+ <source>The regular expression to test against. Backslash characters must be double escaped (eg "\\s" to match a white space character). Non-greedy regular expressions are not supported.</source>
+ <translation>Zu vergleichender regulärer Ausdruck. Rückschrägstrich müssen doppelt ausgenommen werden (z.B. "\\s" paßt auf ein Leerzeichen). Nicht-gierige reguläre Ausdrücke werden nicht unterstützt.</translation>
+ </message>
+ <message>
+ <source>regexp_match('QGIS ROCKS','\\sROCKS')</source>
+ <translation>regexp_match('QGIS ROCKS','\\sROCKS')</translation>
+ </message>
+ <message>
+ <source>The regular expression to replace. Backslash characters must be double escaped (eg "\\s" to match a white space character). Non-greedy regular expressions are not supported.</source>
+ <translation>Zu vergleichender regulärer Ausdruck. Rückschrägstrich müssen doppelt ausgenommen werden (z.B. "\\s" paßt auf ein Leerzeichen). Nicht-gierige reguläre Ausdrücke werden nicht unterstützt.</translation>
+ </message>
+ <message>
+ <source>The string that will replace any matching occurrences of the supplied regular expression. Captured groups can be inserted into the replacement string using \\1, \\2, etc.</source>
+ <translation>Die Zeichenkette, die Treffer des regulären gegebenen Ausdrucks ersetzt. Treffergruppen können in die Zeichenkette mit \1, \2 usw. eingefügt werden.</translation>
+ </message>
+ <message>
+ <source>regexp_replace('QGIS SHOULD ROCK','\\sSHOULD\\s',' DOES ')</source>
+ <translation>regexp_replace('QGIS SHOULD ROCK','\\sSHOULD\\s',' DOES ')</translation>
+ </message>
+ <message>
+ <source>The regular expression to match against. Backslash characters must be double escaped (eg "\\s" to match a white space character). Non-greedy regular expressions are not supported.</source>
+ <translation>Zu vergleichender regulärer Ausdruck. Rückschrägstrich müssen doppelt ausgenommen werden (z.B. "\\s" paßt auf ein Leerzeichen). Nicht-gierige reguläre Ausdrücke werden nicht unterstützt.</translation>
+ </message>
+ <message>
<source>z</source>
<translation>z</translation>
</message>
@@ -45455,19 +45848,83 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>Contains functions which aggregate values over layers and fields.</source>
- <translation>Enthält Funktionen die Werte über Layer und Felder aggregieren.</translation>
+ <translation>Enthält Funktionen die Aggregatwerte über Layer und Felder.</translation>
</message>
<message>
<source>Aggregates</source>
<translation>Aggregate</translation>
</message>
<message>
+ <source>pattern to find, you can use '%' as a wildcard, '_' as a single char and '\' to escape.</source>
+ <translation>Zu suchendes Muster. '%' kann als Platzhalter für ein oder mehrere Zeichen, '_' für ein einzelnes Zeichen und '\' zum Aufheben der Sonderbedeutung eines Zeichens verwendet werden.</translation>
+ </message>
+ <message>
+ <source>'ABC' ILIKE '_b_'</source>
+ <translation>'ABC' ILIKE '_b_'</translation>
+ </message>
+ <message>
+ <source>'ABC' ILIKE '_B_'</source>
+ <translation>'ABC' ILIKE '_B_'</translation>
+ </message>
+ <message>
+ <source>'ABCD' ILIKE '_b_'</source>
+ <translation>'ABCD' ILIKE '_b_'</translation>
+ </message>
+ <message>
+ <source>'ABCD' ILIKE '_B_'</source>
+ <translation>'ABCD' ILIKE '_B_'</translation>
+ </message>
+ <message>
+ <source>'ABCD' ILIKE '_b%'</source>
+ <translation>'ABCD' ILIKE '_b%'</translation>
+ </message>
+ <message>
+ <source>'ABCD' ILIKE '_B%'</source>
+ <translation>'ABCD' ILIKE '_B%'</translation>
+ </message>
+ <message>
+ <source>'ABCD' ILIKE '%b%'</source>
+ <translation>'ABCD' ILIKE '%b%'</translation>
+ </message>
+ <message>
+ <source>'ABCD' ILIKE '%B%'</source>
+ <translation>'ABCD' ILIKE '%B%'</translation>
+ </message>
+ <message>
+ <source>pattern to compare value with, you can use '%' as a wildcard, '_' as a single char and '\' to escape.</source>
+ <translation>Mit dem Wert zu vergleichendes Muster. '%' kann als Platzhalter für ein oder mehrere Zeichen, '_' für ein einzelnes Zeichen und '\' zum Aufheben der Sonderbedeutung eines Zeichens verwendet werden.</translation>
+ </message>
+ <message>
+ <source>'ABC' LIKE '_B_'</source>
+ <translation>'ABC' LIKE '_B_'</translation>
+ </message>
+ <message>
+ <source>'ABCD' LIKE '_B_'</source>
+ <translation>'ABCD' LIKE '_B_'</translation>
+ </message>
+ <message>
+ <source>'ABCD' LIKE '_B%'</source>
+ <translation>'ABCD' LIKE '_B%'</translation>
+ </message>
+ <message>
+ <source>'ABCD' LIKE '%B%'</source>
+ <translation>'ABCD' LIKE '%B%'</translation>
+ </message>
+ <message>
+ <source>'1%' LIKE '1\%'</source>
+ <translation>'1%' LIKE '1\%'</translation>
+ </message>
+ <message>
+ <source>'1_' LIKE '1\%'</source>
+ <translation>'1_' LIKE '1\%'</translation>
+ </message>
+ <message>
<source>Returns an aggregate value calculated using features from another layer.</source>
<translation>Liefert einen mit Objekten eines anderen Layers berechneten Aggregatwert.</translation>
</message>
<message>
<source>aggregate</source>
- <translation>aggregate</translation>
+ <translation>Aggregat</translation>
</message>
<message>
<source>a string corresponding to the aggregate to calculate. Valid options are:<br /><ul><li>count</li><li>count_distinct</li><li>count_missing</li><li>min</li><li>max</li><li>sum</li><li>mean</li><li>median</li><li>stdev</li><li>stdevsample</li><li>range</li><li>minority</li><li>majority</li><li>q1: first q [...]
@@ -45491,7 +45948,7 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>sum of all values from the passengers field in the rail_stations layer</source>
- <translation>Summe aller Werte des Felds passengeers im Layer rail_stations</translation>
+ <translation>Summe aller Werte des Felds passengers im Layer rail_stations</translation>
</message>
<message>
<source>aggregate('rail_stations','sum', "passengers"/7)</source>
@@ -45518,12 +45975,52 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
<translation>Kommagetrennte Liste des Feld name für alle Objekte im Layer rail_stations</translation>
</message>
<message>
+ <source>Returns the bisector angle (average angle) to the geometry for a specified vertex on a linestring geometry. Angles are in degrees clockwise from north.</source>
+ <translation>Liefert die Winkelhalbierende (Durchschnittswinkel) zur Geometrie für einen gegebenen Stützpunkt einer Liniengeometrie (Winkel ab Norden in Grad im Uhrzeigersinn).</translation>
+ </message>
+ <message>
+ <source>angle_at_vertex</source>
+ <translation>angle_at_vertex</translation>
+ </message>
+ <message>
+ <source>a linestring geometry</source>
+ <translation>eine Liniengeometrie</translation>
+ </message>
+ <message>
+ <source>vertex index, starting from 0</source>
+ <translation>Stützpunktindex beginnend mit 0</translation>
+ </message>
+ <message>
+ <source>angle_at_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)</source>
+ <translation>angle_at_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)</translation>
+ </message>
+ <message>
+ <source>45.0</source>
+ <translation>45.0</translation>
+ </message>
+ <message>
<source>Returns the north-based azimuth as the angle in radians measured clockwise from the vertical on point_a to point_b.</source>
<translation>Liefert auf Norden bezogenen Azimuth als Winkel im Bogenmaß im Uhrzeigersinn gemessen von der Vertikalen von punkt_a zu punkt_b.</translation>
</message>
<message>
+ <source>Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the geometry). For instance, a polygon geometry will have a boundary consisting of the linestrings for each ring in the polygon. Some geometry types do not have a defined boundary, eg points or geometry collections, and will return null.</source>
+ <translation>Liefert die topologische Umgrenzung. Z.B. hat eine Polygongeometrie eine Umgrenzung, die aus den Linien eines jeden Rings besteht. Einige Geomtriearten haben keine definierte Umgrenzung, z.B. Punkte oder Geometriesammungen und geben Null zurück.</translation>
+ </message>
+ <message>
+ <source>boundary</source>
+ <translation>boundary</translation>
+ </message>
+ <message>
+ <source>geom_to_wkt(boundary(geom_from_wkt('Polygon((1 1, 0 0, -1 1, 1 1))')))</source>
+ <translation>geom_to_wkt(boundary(geom_from_wkt('Polygon((1 1, 0 0, -1 1, 1 1))')))</translation>
+ </message>
+ <message>
+ <source>'LineString(1 1,0 0,-1 1,1 1)'</source>
+ <translation>'LineString(1 1,0 0,-1 1,1 1)'</translation>
+ </message>
+ <message>
<source>Returns the character associated with a unicode code.</source>
- <translation>Liefert das dem Unicode-Kode zugehörige Zeichen.</translation>
+ <translation>Liefert das zu einem Unicode-Kode gehörende Zeichen.</translation>
</message>
<message>
<source>char</source>
@@ -45531,7 +46028,7 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>a unicode code number</source>
- <translation>Eine Unicode-Kodenummer</translation>
+ <translation>Ein Unicode-Kodezahl</translation>
</message>
<message>
<source>char(81)</source>
@@ -45543,11 +46040,11 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>Returns the all aggregated strings from a field or expression joined by a delimiter.</source>
- <translation>Liefert alle durch ein Trennzeichen verbundene aggregierten Zeichenketten eines Felds oder Ausdruck.</translation>
+ <translation>Liefert alle durch ein Trennzeichen verbundene aggregierten Zeichenketten eines Felds oder Ausdruck</translation>
</message>
<message>
<source>concatenate</source>
- <translation>concatenate</translation>
+ <translation>Verkettung</translation>
</message>
<message>
<source>sub expression of field to aggregate</source>
@@ -45555,7 +46052,7 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>optional expression to use to group aggregate calculations</source>
- <translation>Optionaler für Gruppenaggregierungsberechnungen zu verwendender Ausdruck</translation>
+ <translation>Optionaler für Gruppenaggregierungsberechnungen zu verwendender Ausdruck </translation>
</message>
<message>
<source>optional expression to use to filter features used to calculate aggregate</source>
@@ -45587,7 +46084,7 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>count of stations, grouped by state field</source>
- <translation>Stationen zählen, gruppiert nach Feld state</translation>
+ <translation>Stationen zählen, gruppiert nach Feld Staat</translation>
</message>
<message>
<source>Returns the count of distinct values.</source>
@@ -45619,7 +46116,23 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>count of missing (null) station values, grouped by state field</source>
- <translation>Anzahl der fehlenden Stationswerte (NULL), gruppiert nach Feld state</translation>
+ <translation>Anzahl der fehlenden Stationswerte (NULL), gruppiert nach Feld Staat</translation>
+ </message>
+ <message>
+ <source>Returns the distance along the geometry to a specified vertex.</source>
+ <translation>Liefert die Entfernung vom Anfang entlang der Geometrie für einen gegebenen Stützpunkt.</translation>
+ </message>
+ <message>
+ <source>distance_to_vertex</source>
+ <translation>distance_to_vertex</translation>
+ </message>
+ <message>
+ <source>distance_to_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)</source>
+ <translation>distance_to_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)</translation>
+ </message>
+ <message>
+ <source>10.0</source>
+ <translation>10.0</translation>
</message>
<message>
<source>Returns the calculated inter quartile range from a field or expression.</source>
@@ -45638,8 +46151,96 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
<translation>Interquartilbereich des Werts population, gruppiert nach Feld state</translation>
</message>
<message>
+ <source>Returns the angle parallel to the geometry at a specified distance along a linestring geometry. Angles are in degrees clockwise from north.</source>
+ <translation>Liefert den parallelen Winkel zur Geometrie bei einem bestimmten Punkt entlang einer Liniengeometrie (Winkel von Norden in Grad im Uhrzeigersinn).</translation>
+ </message>
+ <message>
+ <source>line_interpolate_angle</source>
+ <translation>line_interpolate_angle</translation>
+ </message>
+ <message>
+ <source>distance along line to interpolate angle at</source>
+ <translation>Abstand entlang der Linien an dem der Winkel bestimmt werden soll</translation>
+ </message>
+ <message>
+ <source>line_interpolate_angle(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),distance:=5)</source>
+ <translation>line_interpolate_angle(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),distance:=5)</translation>
+ </message>
+ <message>
+ <source>90.0</source>
+ <translation>90.0</translation>
+ </message>
+ <message>
+ <source>Returns the point interpolated by a specified distance along a linestring geometry.</source>
+ <translation>Liefert den Punkt an einem gegebenen Abstand entlang einer Linie.</translation>
+ </message>
+ <message>
+ <source>line_interpolate_point</source>
+ <translation>line_interpolate_point</translation>
+ </message>
+ <message>
+ <source>distance along line to interpolate</source>
+ <translation>Abstand entlang der Linie</translation>
+ </message>
+ <message>
+ <source>geom_to_wkt(line_interpolate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),distance:=5))</source>
+ <translation>geom_to_wkt(line_interpolate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),distance:=5))</translation>
+ </message>
+ <message>
+ <source>'Point (5 0)'</source>
+ <translation>'Point (5 0)'</translation>
+ </message>
+ <message>
+ <source>Returns the distance along a linestring corresponding to the closest position the linestring comes to a specified point geometry.</source>
+ <translation>Liefert den Abstand entlang der Linie der dem nächsten Punkt auf der Linie zu einem gegebenen Punkt entspricht.</translation>
+ </message>
+ <message>
+ <source>line_locate_point</source>
+ <translation>line_locate_point</translation>
+ </message>
+ <message>
+ <source>point geometry to locate closest position on linestring to</source>
+ <translation>Punktgeometrie zu dem der nächste Punkt der Linien bestimmt werden soll</translation>
+ </message>
+ <message>
+ <source>line_locate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),point:=geom_from_wkt('Point(5 0)'))</source>
+ <translation>line_locate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),point:=geom_from_wkt('Point(5 0)'))</translation>
+ </message>
+ <message>
+ <source>5.0</source>
+ <translation>5.0</translation>
+ </message>
+ <message>
+ <source>Returns a LineString or MultiLineString geometry, where any connected LineStrings from the input geometry have been merged into a single linestring. This function will return null if passed a geometry which is not a LineString/MultiLineString.</source>
+ <translation>Liefert eine Einzel- oder Mehrfachliniengeometrie in der die verbundenen Linien einer Eingabegeometrie in einzelne Linien zusammengefaßt wurden. Diese Funktion liefert null, wenn die gegebene Geometrie keine Linie ist.</translation>
+ </message>
+ <message>
+ <source>line_merge</source>
+ <translation>line_merge</translation>
+ </message>
+ <message>
+ <source>a LineString/MultiLineString geometry</source>
+ <translation>eine Linie/Multiline</translation>
+ </message>
+ <message>
+ <source>geom_to_wkt(line_merge(geom_from_wkt('MULTILINESTRING((0 0, 1 1),(1 1, 2 2))')))</source>
+ <translation>geom_to_wkt(line_merge(geom_from_wkt('MULTILINESTRING((0 0, 1 1),(1 1, 2 2))')))</translation>
+ </message>
+ <message>
+ <source>'LineString(0 0,1 1,2 2)'</source>
+ <translation>'LineString(0 0,1 1,2 2)'</translation>
+ </message>
+ <message>
+ <source>geom_to_wkt(line_merge(geom_from_wkt('MULTILINESTRING((0 0, 1 1),(11 1, 21 2))')))</source>
+ <translation>geom_to_wkt(line_merge(geom_from_wkt('MULTILINESTRING((0 0, 1 1),(11 1, 21 2))')))</translation>
+ </message>
+ <message>
+ <source>'MultiLineString((0 0, 1 1),(11 1, 21 2)'</source>
+ <translation>'MultiLineString((0 0, 1 1),(11 1, 21 2)'</translation>
+ </message>
+ <message>
<source>Returns the aggregate majority of values (most commonly occurring value) from a field or expression.</source>
- <translation>Liefert den aggregierten Mehrheitswert (am häufigsten auftretender Wert) eines Felds oder Ausdrucks</translation>
+ <translation>Liefert den aggregierten Mehrheitswert (am häufigsten auftretender Wert) eines Felds oder Ausdrucks.</translation>
</message>
<message>
<source>majority</source>
@@ -45763,7 +46364,7 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>maximum length of town_name, grouped by state field</source>
- <translation>Maximale Länge von town_name, gruppiert nach Feld state</translation>
+ <translation>Maximale Länge von town_name, gruppiert nach Feld Staat</translation>
</message>
<message>
<source>Returns the aggregate maximum value from a field or expression.</source>
@@ -45775,15 +46376,15 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>maximum population value, grouped by state field</source>
- <translation>Maximaler Bevölkerungswert, gruppiert nach Feld state</translation>
+ <translation>Maximaler Bevölkerungswert, gruppiert nach Feld Staat</translation>
</message>
<message>
<source>Returns the aggregate mean value from a field or expression.</source>
- <translation>Liefert den aggregierten Mittelwert eines Felds oder Ausdrucks</translation>
+ <translation>Liefert den aggregierten Mittelwert eines Felds oder Ausdrucks.</translation>
</message>
<message>
<source>mean</source>
- <translation>Durchschnitt</translation>
+ <translation>mean</translation>
</message>
<message>
<source>mean("population",group_by:="state")</source>
@@ -45839,7 +46440,7 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>minimum length of town_name, grouped by state field</source>
- <translation>Minimale Länger von town_name, gruppiert nach Feld state</translation>
+ <translation>Minimale Länger von town_name, gruppiert nach Feld Staat</translation>
</message>
<message>
<source>Returns the aggregate minimum value from a field or expression.</source>
@@ -46611,11 +47212,11 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>The regular expression to test against. Backslash characters must be double escaped (eg "\s" to match a white space character). Non-greedy regular expressions are not supported.</source>
- <translation>Zu vergleichender regulärer Ausdruck. Rückschrägstrich müssen doppelt ausgenommen werden (z.B. "\s" paßt auf ein Leerzeichen). Nicht-gierige reguläre Ausdrücke werden nicht unterstützt.</translation>
+ <translation type="obsolete">Zu vergleichender regulärer Ausdruck. Rückschrägstrich müssen doppelt ausgenommen werden (z.B. "\s" paßt auf ein Leerzeichen). Nicht-gierige reguläre Ausdrücke werden nicht unterstützt.</translation>
</message>
<message>
<source>regexp_match('QGIS ROCKS','\sROCKS')</source>
- <translation>regexp_match('QGIS ROCKS','\sROCKS')</translation>
+ <translation type="obsolete">regexp_match('QGIS ROCKS','\sROCKS')</translation>
</message>
<message>
<source>Returns a string with the supplied regular expression replaced.</source>
@@ -46631,15 +47232,15 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>The regular expression to replace. Backslash characters must be double escaped (eg "\s" to match a white space character). Non-greedy regular expressions are not supported.</source>
- <translation>Zu vergleichender regulärer Ausdruck. Rückschrägstrich müssen doppelt ausgenommen werden (z.B. "\s" paßt auf ein Leerzeichen). Nicht-gierige reguläre Ausdrücke werden nicht unterstützt.</translation>
+ <translation type="obsolete">Zu vergleichender regulärer Ausdruck. Rückschrägstrich müssen doppelt ausgenommen werden (z.B. "\s" paßt auf ein Leerzeichen). Nicht-gierige reguläre Ausdrücke werden nicht unterstützt.</translation>
</message>
<message>
<source>The string that will replace any matching occurrences of the supplied regular expression. Captured groups can be inserted into the replacement string using \1, \2, etc.</source>
- <translation>Die Zeichenkette, die Treffer des regulären Ausdrucks ersetzt. Treffergruppen können in die Zeichenkette mit \1, \2 usw. eingefügt werden.</translation>
+ <translation type="obsolete">Die Zeichenkette, die Treffer des regulären Ausdrucks ersetzt. Treffergruppen können in die Zeichenkette mit \1, \2 usw. eingefügt werden.</translation>
</message>
<message>
<source>regexp_replace('QGIS SHOULD ROCK','\sSHOULD\s',' DOES ')</source>
- <translation>regexp_replace('QGIS SHOULD ROCK','\sSHOULD\s',' DOES ')</translation>
+ <translation type="obsolete">regexp_replace('QGIS SHOULD ROCK','\sSHOULD\s',' DOES ')</translation>
</message>
<message>
<source>'QGIS DOES ROCK'</source>
@@ -46659,17 +47260,21 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>The regular expression to match against. Backslash characters must be double escaped (eg "\s" to match a white space character). Non-greedy regular expressions are not supported.</source>
- <translation>Zu vergleichender regulärer Ausdruck. Rückschrägstrich müssen doppelt ausgenommen werden (z.B. "\s" paßt auf ein Leerzeichen). Nicht-gierige reguläre Ausdrücke werden nicht unterstützt.</translation>
+ <translation type="obsolete">Zu vergleichender regulärer Ausdruck. Rückschrägstrich müssen doppelt ausgenommen werden (z.B. "\s" paßt auf ein Leerzeichen). Nicht-gierige reguläre Ausdrücke werden nicht unterstützt.</translation>
</message>
<message>
<source>regexp_substr('abc123','(\d+)')</source>
- <translation>regexp_substr('abc123','(\d+)')</translation>
+ <translation type="obsolete">regexp_substr('abc123','(\d+)')</translation>
</message>
<message>
<source>'123'</source>
<translation>'123'</translation>
</message>
<message>
+ <source>regexp_substr('abc123','(\\d+)')</source>
+ <translation>regexp_substr('abc123','(\\d+)')</translation>
+ </message>
+ <message>
<source>Tests the Dimensional Extended 9 Intersection Model (DE-9IM) representation of the relationship between two geometries.</source>
<translation>Liefert die Dimensional Extended 9 Intersection Model (DE-9IM) Darstellung der Beziehungen zwischen zwei Geometrien.</translation>
</message>
@@ -46735,7 +47340,7 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
</message>
<message>
<source>sum of the passengers field divided by 7 for all matching child features using the 'my_relation' relation</source>
- <translation>Summe von des Feld passengers geteilt durch 7 für alle passenden Kindobjekte über die Beziehung 'my_relation'</translation>
+ <translation>Summe von des Feld passengers geteilt durch 7 für alle passenden Kindobjekte über die Beziehung 'my_relation'</translation>
</message>
<message>
<source>relation_aggregate('my_relation','concatenate', "towns", concatenator:=',')</source>
@@ -48186,32 +48791,32 @@ valign="top"><td>dddd</td><td>der lange lokale Wo
<translation>Letztes (%1)</translation>
</message>
<message>
- <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="581"/>
+ <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="574"/>
<source>Parser Error</source>
<translation>Parsingfehler</translation>
</message>
<message>
- <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="583"/>
+ <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="576"/>
<source>Eval Error</source>
<translation>Auswertungsfehler</translation>
</message>
<message>
- <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="585"/>
+ <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="578"/>
<source>Expression is invalid <a href=more>(more info)</a></source>
<translation>Ausdruck ist ungültig <a href=more>(mehr Information)</a></translation>
</message>
<message>
- <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="661"/>
+ <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="662"/>
<source>More info on expression error</source>
<translation>Mehr Informations zum Ausdrucksfehler</translation>
</message>
<message>
- <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="693"/>
+ <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="694"/>
<source>Load top 10 unique values</source>
<translation>Die ersten zehn eindeutigen Werte laden</translation>
</message>
<message>
- <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="694"/>
+ <location filename="../src/gui/qgsexpressionbuilderwidget.cpp" line="695"/>
<source>Load all unique values</source>
<translation>Alle eindeutigen Werte laden</translation>
</message>
@@ -48407,6 +49012,14 @@ Name des Skripts ändern und speichern, um QGIS das automatische Laden beim Star
</message>
</context>
<context>
+ <name>QgsExpressionLineEdit</name>
+ <message>
+ <location filename="../src/gui/qgsexpressionlineedit.cpp" line="31"/>
+ <source>Expression dialog</source>
+ <translation>Ausdrucksdialog</translation>
+ </message>
+</context>
+<context>
<name>QgsExpressionSelectionDialogBase</name>
<message>
<location filename="../src/ui/qgsexpressionselectiondialogbase.ui" line="14"/>
@@ -48699,7 +49312,7 @@ Name des Skripts ändern und speichern, um QGIS das automatische Laden beim Star
<translation>Webansicht</translation>
</message>
<message>
- <location filename="../src/gui/editorwidgets/qgsexternalresourceconfigdlg.cpp" line="74"/>
+ <location filename="../src/gui/editorwidgets/qgsexternalresourceconfigdlg.cpp" line="88"/>
<source>Select a directory</source>
<translation>Ein Verzeichnis wählen</translation>
</message>
@@ -49019,89 +49632,89 @@ Der Ausdruck ist ungültig (siehe (mehr Information) für Näheres)</translation
<context>
<name>QgsFieldsProperties</name>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="78"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="79"/>
<source>Label</source>
<translation>Beschriftung</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="86"/>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="113"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="87"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="114"/>
<source>Id</source>
<translation>Id</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="87"/>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="114"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="88"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="115"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="88"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="89"/>
<source>Type</source>
<translation>Typ</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="89"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="90"/>
<source>Type name</source>
<translation>Typname</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="90"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="91"/>
<source>Length</source>
<translation>Länge</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="91"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="92"/>
<source>Precision</source>
<translation>Genauigkeit</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="92"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="93"/>
<source>Comment</source>
<translation>Kommentar</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="93"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="94"/>
<source>Edit widget</source>
<translation>Bearbeitungselement</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="96"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="97"/>
<source>Alias</source>
<translation>Alias</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="115"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="116"/>
<source>Layer</source>
<translation>Layer</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="116"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="117"/>
<source>Field</source>
<translation>Feld</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="117"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="118"/>
<source>Cardinality</source>
<translation>Kardinalität</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="123"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="124"/>
<source>Load from external file</source>
<translation>Aus externer Datei laden</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="124"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="125"/>
<source>Provide code in this dialog</source>
<translation>Code in diesem Dialog angeben</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="125"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="126"/>
<source>Load from the environment</source>
<translation>Aus der Umgebung laden</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="208"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="225"/>
<source># -*- coding: utf-8 -*-
"""
QGIS forms can have a Python function that is called when the form is
@@ -49138,167 +49751,167 @@ def my_form_open(dialog, layer, feature):
</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="380"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="397"/>
<source>Many to one relation</source>
<translation>Beziehung mehrere-zu-einem </translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="603"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="622"/>
<source>Added attribute</source>
<translation>Attribut hinzugefügt</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="612"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="631"/>
<source>Failed to add field</source>
<translation>Konnte Feld nicht hinzufügen</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="612"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="631"/>
<source>Failed to add field '%1' of type '%2'. Is the field name unique?</source>
<translation>Konnte Feld '%1' vom Typ '%2' nicht hinzufügen. Ist der Feldname eindeutig?</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="687"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="706"/>
<source>Deleted attributes</source>
<translation>Attribute gelöscht</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="767"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="786"/>
<source>Rename attribute</source>
<translation>Attribut umbenennen</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="775"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="794"/>
<source>Failed to rename field</source>
<translation>Konnte Feld nicht umbenennen</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="775"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="794"/>
<source>Failed to rename field to '%1'. Is the field name unique?</source>
<translation>Konnte Feld nicht in '%1' umbenennen. Ist das Feld eindeutig?</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="825"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="844"/>
<source>Line edit</source>
<translation>Eingabezeile</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="826"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="845"/>
<source>Unique values</source>
<translation>Eindeutige Werte</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="827"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="846"/>
<source>Unique values editable</source>
<translation>Eindeutige Werte (bearbeitbar)</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="828"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="847"/>
<source>Classification</source>
<translation>Klassifikation</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="829"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="848"/>
<source>Value map</source>
<translation>Wertabbildung</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="830"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="849"/>
<source>Edit range</source>
<translation>Eingabezeile mit Bereich</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="831"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="850"/>
<source>Slider range</source>
<translation>Schieberbereich</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="832"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="851"/>
<source>Dial range</source>
<translation>Drehreglerbereich</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="833"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="852"/>
<source>File name</source>
<translation>Dateiname</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="834"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="853"/>
<source>Enumeration</source>
<translation>Aufzählung</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="835"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="854"/>
<source>Immutable</source>
<translation>Unveränderbar</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="836"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="855"/>
<source>Hidden</source>
<translation>Versteckt</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="837"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="856"/>
<source>Checkbox</source>
<translation>Kontrollkästchen</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="838"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="857"/>
<source>Text edit</source>
<translation>Texteditor</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="839"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="858"/>
<source>Calendar</source>
<translation>Kalender</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="840"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="859"/>
<source>Value relation</source>
<translation>Wertbeziehung</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="841"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="860"/>
<source>UUID generator</source>
<translation>UUID-Generator</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="842"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="861"/>
<source>Photo</source>
<translation>Foto</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="843"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="862"/>
<source>Web view</source>
<translation>Webansicht</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="844"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="863"/>
<source>Color</source>
<translation>Farbe</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="845"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="864"/>
<source>Editor Widget</source>
<translation>Bearbeitungselement</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="911"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="936"/>
<source>Select Python file</source>
<translation>Python-Datei wählen</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="911"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="936"/>
<source>Python file</source>
<translation>Python-Datei</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="926"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="951"/>
<source>Select edit form</source>
<translation>Bearbeitungsformular wählen</translation>
</message>
<message>
- <location filename="../src/app/qgsfieldsproperties.cpp" line="926"/>
+ <location filename="../src/app/qgsfieldsproperties.cpp" line="951"/>
<source>UI file</source>
<translation>UI-Dateien</translation>
</message>
@@ -49515,12 +50128,12 @@ Referenz im Funktionsnamen: my_form_open
<context>
<name>QgsFilledMarkerSymbolLayerWidget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="860"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="861"/>
<source>Size Assistant...</source>
<translation>Größenassistent...</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="928"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="929"/>
<source>string </source>
<translation>Zeichenkette </translation>
</message>
@@ -49528,17 +50141,17 @@ Referenz im Funktionsnamen: my_form_open
<context>
<name>QgsFontMarkerSymbolLayerV2Widget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2689"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2702"/>
<source>Select symbol fill color</source>
<translation>Symbolfüllfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2692"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2705"/>
<source>Select symbol outline color</source>
<translation>Symbolumrandungsfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2702"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2715"/>
<source>Size Assistant...</source>
<translation>Größenassistent...</translation>
</message>
@@ -50823,22 +51436,22 @@ Bitte wählen Sie eine gültige Datei.</translation>
<translation>Pixelgröße</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="965"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="971"/>
<source>Band</source>
<translation>Kanal</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="983"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="989"/>
<source>Format not supported</source>
<translation>Format nicht unterstützt</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="1056"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="1062"/>
<source>Cannot read data</source>
<translation>Kann Daten nicht lesen</translation>
</message>
<message>
- <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="2568"/>
+ <location filename="../src/providers/gdal/qgsgdalprovider.cpp" line="2574"/>
<source>Cannot get GDAL raster band: %1</source>
<translation>Konnte GDAL-Rasterkanal nicht bestimmen: %1</translation>
</message>
@@ -50889,7 +51502,7 @@ Bitte wählen Sie eine gültige Datei.</translation>
<message>
<location filename="../src/providers/postgres/qgscolumntypethread.cpp" line="112"/>
<source>Table retrieval stopped.</source>
- <translation>Laden der Tabelle gestoppt</translation>
+ <translation>Laden der Tabelle gestoppt.</translation>
</message>
</context>
<context>
@@ -51291,7 +51904,7 @@ Bitte wählen Sie eine gültige Datei.</translation>
<message>
<location filename="../src/plugins/geometry_checker/ui/qgsgeometrycheckerresulttab.cpp" line="595"/>
<source>The layer has been removed.</source>
- <translation>Der Layer wurde entfernt</translation>
+ <translation>Der Layer wurde entfernt.</translation>
</message>
</context>
<context>
@@ -51424,7 +52037,7 @@ Bitte wählen Sie eine gültige Datei.</translation>
<message>
<location filename="../src/plugins/geometry_checker/ui/qgsgeometrycheckersetuptab.ui" line="453"/>
<source>Topology checks:</source>
- <translation>Topologieprüfung</translation>
+ <translation>Topologieprüfung:</translation>
</message>
<message>
<location filename="../src/plugins/geometry_checker/ui/qgsgeometrycheckersetuptab.ui" line="493"/>
@@ -51504,7 +52117,7 @@ Bitte wählen Sie eine gültige Datei.</translation>
<message>
<location filename="../src/plugins/geometry_checker/ui/qgsgeometrycheckersetuptab.cpp" line="189"/>
<source>The input layer is not allowed to be in editing mode.</source>
- <translation>Der Eingabelayer darf nicht im Bearbeitungsmodus sein</translation>
+ <translation>Der Eingabelayer darf nicht im Bearbeitungsmodus sein.</translation>
</message>
<message>
<location filename="../src/plugins/geometry_checker/ui/qgsgeometrycheckersetuptab.cpp" line="197"/>
@@ -51695,17 +52308,17 @@ Bitte wählen Sie eine gültige Datei.</translation>
<context>
<name>QgsGeometryGeneratorSymbolLayerWidget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="3356"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="3246"/>
<source>Polygon / MultiPolygon</source>
<translation>Polygon / MultiPolygon</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="3357"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="3247"/>
<source>LineString / MultiLineString</source>
<translation>LineString / MultiLineString</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="3358"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="3248"/>
<source>Point / MultiPoint</source>
<translation>Point / MultiPoint</translation>
</message>
@@ -51864,7 +52477,7 @@ Bitte wählen Sie eine gültige Datei.</translation>
<location filename="../src/plugins/geometry_snapper/qgsgeometrysnapper.cpp" line="67"/>
<location filename="../src/plugins/geometry_snapper/qgsgeometrysnapper.cpp" line="93"/>
<source>Failed to read feature %1 of input layer.</source>
- <translation>Konnte Objekt %1 nicht aus Eingabelayer lesen</translation>
+ <translation>Konnte Objekt %1 nicht aus Eingabelayer lesen.</translation>
</message>
</context>
<context>
@@ -53591,25 +54204,31 @@ p, li { white-space: pre-wrap; }
<translation>GML-GetFeature-Netzwerkaktualisierungsanfrage für authcfg %1 gescheitet</translation>
</message>
<message>
- <location filename="../src/core/qgsgml.cpp" line="104"/>
+ <location filename="../src/core/qgsgml.cpp" line="93"/>
+ <source>GML Getfeature network reply update failed for authcfg %1</source>
+ <translation>Aktualisierung der GML-GetFeature-Netzwerkanfrage auf authcfg %1 gescheitet</translation>
+ </message>
+ <message>
+ <location filename="../src/core/qgsgml.cpp" line="118"/>
<source>Loading GML data
%1</source>
<translation>Lade GML-Daten
%1</translation>
</message>
<message>
- <location filename="../src/core/qgsgml.cpp" line="104"/>
+ <location filename="../src/core/qgsgml.cpp" line="118"/>
<source>Abort</source>
<translation>Abbrechen</translation>
</message>
<message>
- <location filename="../src/core/qgsgml.cpp" line="141"/>
+ <location filename="../src/core/qgsgml.cpp" line="155"/>
<source>GML Getfeature network request failed with error: %1</source>
<translation>GML-GetFeature-Netzwerkanfrage scheiterte mit Fehler: %1</translation>
</message>
<message>
<location filename="../src/core/qgsgml.cpp" line="75"/>
- <location filename="../src/core/qgsgml.cpp" line="142"/>
+ <location filename="../src/core/qgsgml.cpp" line="94"/>
+ <location filename="../src/core/qgsgml.cpp" line="156"/>
<source>Network</source>
<translation>Netzwerk</translation>
</message>
@@ -53625,14 +54244,14 @@ p, li { white-space: pre-wrap; }
<context>
<name>QgsGradientFillSymbolLayerV2Widget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1037"/>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1042"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1038"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1043"/>
<source>Select gradient color</source>
<translation>Gradientenfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1040"/>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1045"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1041"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1046"/>
<source>Transparent</source>
<translation>Transparent</translation>
</message>
@@ -53728,6 +54347,11 @@ Use "%1" for the lower bound of the classification, and "%2"
"%1" für die untere Grenze und "%2" für die obere Grenzen angeben.</translation>
</message>
<message>
+ <location filename="../src/ui/qgsgraduatedsymbolrendererv2widget.ui" line="112"/>
+ <source>Precision </source>
+ <translation>Genauigkeit </translation>
+ </message>
+ <message>
<location filename="../src/ui/qgsgraduatedsymbolrendererv2widget.ui" line="347"/>
<source>Mode</source>
<translation>Modus</translation>
@@ -53763,9 +54387,8 @@ Use "%1" for the lower bound of the classification, and "%2"
<translation>Histogramm</translation>
</message>
<message>
- <location filename="../src/ui/qgsgraduatedsymbolrendererv2widget.ui" line="112"/>
<source>Precison </source>
- <translation>Genauigkeit</translation>
+ <translation type="obsolete">Genauigkeit</translation>
</message>
<message>
<location filename="../src/ui/qgsgraduatedsymbolrendererv2widget.ui" line="140"/>
@@ -55722,28 +56345,28 @@ in Zeile %2, Spalte %3</translation>
</message>
<message>
<location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="261"/>
- <location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="309"/>
+ <location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="310"/>
<source>Cannot read raster</source>
<translation>Kann Raster nicht lesen</translation>
</message>
<message>
<location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="273"/>
- <location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="322"/>
+ <location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="323"/>
<source>%1 bytes expected but %2 byte were read from qgis.d.rast</source>
<translation>%1 Bytes erwartet jedoch %2 Bytes von qgis.d.rast gelesen</translation>
</message>
<message>
- <location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="470"/>
+ <location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="471"/>
<source>Format not supported</source>
<translation>Format nicht unterstützt</translation>
</message>
<message>
- <location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="487"/>
+ <location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="488"/>
<source>Cannot read data</source>
<translation>Kann Daten nicht lesen</translation>
</message>
<message>
- <location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="580"/>
+ <location filename="../src/providers/grass/qgsgrassrasterprovider.cpp" line="581"/>
<source>GRASS raster provider</source>
<translation>GRASS-Rasterdatenanbieter</translation>
</message>
@@ -56179,7 +56802,7 @@ in Zeile %2, Spalte %3</translation>
<location filename="../src/ui/qgsgroupwmsdatadialogbase.ui" line="56"/>
<location filename="../src/ui/qgsgroupwmsdatadialogbase.ui" line="59"/>
<source>A name used to identify the group layer. The short name is a text string used for machine-to-machine communication.</source>
- <translation>Name zur Identifikation der Layergruppe. Der Kurzname ist eine Zeichenkette, die für die Kommunikation zwischen Maschinen verwendet wird</translation>
+ <translation>Name zur Identifikation der Layergruppe. Der Kurzname ist eine Zeichenkette, die für die Kommunikation zwischen Maschinen verwendet wird.</translation>
</message>
<message>
<location filename="../src/ui/qgsgroupwmsdatadialogbase.ui" line="66"/>
@@ -56737,179 +57360,179 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<context>
<name>QgsIdentifyResultsDialog</name>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="261"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="264"/>
<source>Identify Results</source>
<translation>Abfrageergebnisse</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="289"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="292"/>
<source>Feature</source>
<translation>Objekt</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="290"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="293"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="306"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="309"/>
<source>Current layer</source>
<translation>Aktueller Layer</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="307"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="310"/>
<source>Top down, stop at first</source>
<translation>Von oben nach unten, beim ersten halten</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="308"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="311"/>
<source>Top down</source>
<translation>Von oben nach unten</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="309"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="312"/>
<source>Layer selection</source>
<translation>Layerauswahl</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="411"/>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="774"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="414"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="787"/>
<source>(Derived)</source>
<translation>(abgeleitet)</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="426"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="429"/>
<source>(Actions)</source>
<translation>(Aktionen)</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="432"/>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="843"/>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="960"/>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1326"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="435"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="856"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="973"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1339"/>
<source>Edit feature form</source>
<translation>Objektformular bearbeiten</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="432"/>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="843"/>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="960"/>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1326"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="435"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="856"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="973"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1339"/>
<source>View feature form</source>
<translation>Objektformular anzeigen</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="315"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="318"/>
<source>Table</source>
<translation>Tabelle</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="314"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="317"/>
<source>Tree</source>
<translation>Baum</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="316"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="319"/>
<source>Graph</source>
<translation>Graph</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="509"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="522"/>
<source>feature id</source>
<translation>Objektkennung</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="712"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="725"/>
<source>Format</source>
<translation>Format</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="761"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="774"/>
<source>No attributes.</source>
<translation>Keine Attribute.</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="966"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="979"/>
<source>Zoom to feature</source>
<translation>Zum Objekt zoomen</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="967"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="980"/>
<source>Copy feature</source>
<translation>Objekt kopieren</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="968"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="981"/>
<source>Toggle feature selection</source>
<translation>Auswahl des Objekts umkehren</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="971"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="984"/>
<source>Copy attribute value</source>
<translation>Attributwert kopieren</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="972"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="985"/>
<source>Copy feature attributes</source>
<translation>Objektattribute kopieren</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="985"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="998"/>
<source>Copy GetFeatureInfo request URL</source>
<translation>GetFeatureInfo-Abfrage-URL kopieren</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="993"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1006"/>
<source>Clear results</source>
<translation>Ergebnisse löschen</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="994"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1007"/>
<source>Clear highlights</source>
<translation>Hervorhebungen löschen</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="995"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1008"/>
<source>Highlight all</source>
<translation>Alle hervorheben</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="996"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1009"/>
<source>Highlight layer</source>
<translation>Layer hervorheben</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="999"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1012"/>
<source>Activate layer</source>
<translation>Layer aktivieren</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1000"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1013"/>
<source>Layer properties...</source>
<translation>Layereigenschaften...</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1003"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1016"/>
<source>Expand all</source>
<translation>Alle ausklappen</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1004"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1017"/>
<source>Collapse all</source>
<translation>Alle einklappen</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1593"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1620"/>
<source>Attributes changed</source>
<translation>Attribute geändert</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1748"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1775"/>
<source>Cannot print</source>
<translation>Drucken nicht möglich</translation>
</message>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1748"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="1775"/>
<source>Cannot print this item</source>
<translation>Kann dieses Element nicht drucken</translation>
</message>
@@ -56917,7 +57540,7 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<context>
<name>QgsIdentifyResultsWebView</name>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="94"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="96"/>
<source>Print</source>
<translation>Drucken</translation>
</message>
@@ -56925,7 +57548,7 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<context>
<name>QgsIdentifyResultsWebViewItem</name>
<message>
- <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="212"/>
+ <location filename="../src/app/qgsidentifyresultsdialog.cpp" line="215"/>
<source>Loading...</source>
<translation>Lade...</translation>
</message>
@@ -57740,248 +58363,273 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<context>
<name>QgsLabelingGui</name>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="92"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="93"/>
<source>% of length</source>
<translation>% der Länge</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="111"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="112"/>
<source>Over the feature's interior</source>
<translation>Über das Objektinnere</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="112"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="113"/>
<source>Over the feature's boundary</source>
<translation>Über die Objektgrenze</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="114"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="115"/>
<source>From point</source>
<translation>Aus Punkt</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="115"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="116"/>
<source>From symbol bounds</source>
<translation>Aus Symbolgrenzen</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="151"/>
- <location filename="../src/app/qgslabelinggui.cpp" line="161"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="153"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="163"/>
<source>Select fill color</source>
<translation>Füllfarbe wählen</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="153"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="155"/>
<source>Select text color</source>
<translation>Textfarbe wählen</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="156"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="158"/>
<source>Select buffer color</source>
<translation>Pufferfarbe wählen</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="159"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="161"/>
<source>Select border color</source>
<translation>Randfarbe wählen</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="163"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="165"/>
<source>Select shadow color</source>
<translation>Schattenfarbe wählen</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="481"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="495"/>
<source>Text</source>
<translation>Text</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="482"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="496"/>
<source>Formatting</source>
<translation>Formatierung</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="483"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="497"/>
<source>Buffer</source>
<translation>Puffer</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="484"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="498"/>
<source>Background</source>
<translation>Hintergrund</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="485"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="499"/>
<source>Shadow</source>
<translation>Schatten</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="486"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="500"/>
<source>Placement</source>
<translation>Platzierung</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="487"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="501"/>
<source>Rendering</source>
<translation>Darstellung</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="764"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="786"/>
<source>%1 not found. Default substituted.</source>
<translation>%1 nicht gefunden. Durch Voreinstellung ersetzt.</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="765"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="787"/>
<source>Chosen font</source>
<translation>Gewählte Schriftart</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1224"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1254"/>
<source>string </source>
<translation>Zeichenkette </translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1230"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1260"/>
<source>[<b>family</b>|<b>family[foundry]</b>],<br>e.g. Helvetica or Helvetica [Cronyx]</source>
<translation>[<b>Familie</b>|<b>Familie[Hersteller]</b>]<br>z.B. Helvetica oder Helvetica [Cronyx]</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1235"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1265"/>
<source>[<b>font style name</b>|<b>Ignore</b>],<br>e.g. Bold Condensed or Light Italic</source>
<translation>[<b>Schriftstilname</b>|<b>Ignorieren</b>],<br>z.B. Fett schmal oder Leicht kursiv</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1279"/>
- <location filename="../src/app/qgslabelinggui.cpp" line="1422"/>
- <location filename="../src/app/qgslabelinggui.cpp" line="1487"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1309"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1452"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1517"/>
<source>double [0.0-10.0]</source>
<translation>Fließkommazahl [0.0 - 10.0]</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1301"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1331"/>
<source>int [0-20]</source>
<translation>Ganze Zahl [0-20]</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1390"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1420"/>
<source>int [0-2000]</source>
<translation>Ganze Zahl [0-2000]</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1402"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1432"/>
<source>int<br></source>
<translation>Ganze Zahl<br></translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1407"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1437"/>
<source>Comma separated list of placements in order of priority<br></source>
<translation>Durch Komma getrennte Liste von Plazierungen in Reihenfolge der Priorität<br></translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1428"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1458"/>
<source>double coord [<b>in,out</b> as 20.0-60.0,20.0-95.0]</source>
<translation>Fließkommakoordinate [<b>in,out</b> als 20.0-60.0,20.0-95.0]</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1435"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1465"/>
<source>In edit mode, layer's relevant labeling map tool is:<br> Defined attribute field -> <i>enabled</i><br> Defined expression -> <i>disabled</i></source>
<translation>Beschriftungswerkzeuge sind im Bearbeitungsmodus:<br> Definiertes Attributfeld → <i>aktiv</i><br> Definierter Ausdruck: → <i>abgeschaltet</i></translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1458"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1488"/>
<source>Value < 0 represents a scale closer than 1:1, e.g. -10 = 10:1<br>Value of 0 disables the specific limit.</source>
<translation>Wert < 0 definiert einen größeren Maßstab als 1:1, z.B. -10 = 10:1<br>Wert = 0 schaltet die betreffende Beschränkung ab.</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1474"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1504"/>
<source>int [1-1000]</source>
<translation>Ganze Zahl [1-1000]</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1476"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1506"/>
<source>int [1-10000]</source>
<translation>Ganze Zahl [1-10000]</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1557"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1587"/>
<source>Text/Buffer sample</source>
<translation>Text-/Pufferbeispiel</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1564"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1594"/>
<source> @ %1 pts (using map units)</source>
<translation> @ %1 Pkt (in Karteneinheiten)</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1577"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1607"/>
<source> @ %1 pts (using map units, BUFFER IN MILLIMETERS)</source>
<translation> @ %1 Pkt (in Karteneinheiten, PUFFER IN MILLIMETERN)</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1597"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1627"/>
<source> (BUFFER NOT SHOWN, in map units)</source>
<translation> (PUFFER NICHT ANGEZEIGT, in Karteneinheiten)</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1742"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1776"/>
<source>No change</source>
<translation>Keine Änderung</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1743"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1777"/>
<source>All uppercase</source>
<translation>Nur Großbuchstaben</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1744"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1778"/>
<source>All lowercase</source>
<translation>Nur Kleinbuchstaben</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1748"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1782"/>
<source>Capitalize first letter</source>
<translation>Erstes Zeichen groß</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1904"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1938"/>
<source>Size%1</source>
<translation>Größe%1</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1904"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="1938"/>
<source> X</source>
<translation> X</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="1975"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="2015"/>
<source>File not found</source>
<translation>Datei nicht gefunden</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="2015"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="2055"/>
<source>Select SVG file</source>
<translation>SVG-Datei wählen</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="601"/>
- <location filename="../src/app/qgslabelinggui.cpp" line="602"/>
- <location filename="../src/app/qgslabelinggui.cpp" line="606"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="2133"/>
+ <source>Left of line</source>
+ <translation>Links der Linie</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgslabelinggui.cpp" line="2134"/>
+ <source>Right of line</source>
+ <translation>Rechts der Linie</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgslabelinggui.cpp" line="2138"/>
+ <source>Above line</source>
+ <translation>Über Linie</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgslabelinggui.cpp" line="2139"/>
+ <source>Below line</source>
+ <translation>Unter Linie</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgslabelinggui.cpp" line="2149"/>
+ <source>Substitutions</source>
+ <translation>Ersetzungen</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgslabelinggui.cpp" line="619"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="620"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="624"/>
<source>Follow label placement</source>
<translation>Beschriftungsplazierung folgen</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="88"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="89"/>
<source>Points</source>
<translation>Punkte</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="88"/>
- <location filename="../src/app/qgslabelinggui.cpp" line="92"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="89"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="93"/>
<source>Map unit</source>
<translation>Karteneinheiten</translation>
</message>
<message>
- <location filename="../src/app/qgslabelinggui.cpp" line="92"/>
+ <location filename="../src/app/qgslabelinggui.cpp" line="93"/>
<source>Millimeter</source>
<translation>Millimeter</translation>
</message>
@@ -57994,1005 +58642,1026 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<translation>Layerbeschriftungseinstellungen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="203"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="695"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="818"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="825"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="832"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="839"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="846"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="925"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="948"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1034"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1079"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1120"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1174"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1216"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1228"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1397"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1414"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1519"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1553"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1625"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1635"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1642"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1689"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1727"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1737"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1826"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1874"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1891"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1959"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2007"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2014"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2164"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2171"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2203"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2210"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2352"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2433"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2462"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2469"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2476"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2502"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2546"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2608"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2625"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2680"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2700"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2743"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2764"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2825"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2845"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2852"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2862"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2908"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2915"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2974"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3042"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3152"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3460"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3467"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3474"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3481"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3488"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3495"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3502"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3509"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3516"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3523"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3949"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4016"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4023"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4085"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4101"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4354"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4451"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4458"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4568"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4619"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4629"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4693"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4791"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4811"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4856"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4900"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4920"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4994"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5095"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5161"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5196"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5226"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5298"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5336"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5377"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5434"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5441"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5768"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5835"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="221"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="740"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="863"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="870"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="877"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="884"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="891"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="979"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="999"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1085"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1130"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1171"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1225"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1267"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1279"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1353"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1489"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1506"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1611"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1654"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1735"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1745"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1752"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1799"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1846"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1856"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1954"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2002"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2019"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2096"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2144"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2151"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2307"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2314"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2346"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2353"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2504"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2585"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2614"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2621"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2628"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2654"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2707"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2766"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2783"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2838"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2858"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2901"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2922"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2983"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3008"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3015"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3025"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3071"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3078"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3137"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3205"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3324"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3629"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3636"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3643"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3650"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3657"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3664"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3671"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3678"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3685"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3692"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4195"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4271"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4278"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4358"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4383"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4645"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4760"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4767"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4886"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4946"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4956"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5029"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5127"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5147"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5192"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5245"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5265"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5339"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5449"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5515"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5550"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5580"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5652"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5690"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5731"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5797"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5804"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6167"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6243"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="141"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="184"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="159"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="202"/>
<source>Lorem Ipsum</source>
<translation>Lorom Ipsum</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="181"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="199"/>
<source>Sample text</source>
<translation>Beispieltext</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="200"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="218"/>
<source>Reset sample text</source>
<translation>Beispieltext zurücksetzen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="242"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="260"/>
<source>Size for sample text in map units</source>
<translation>Größe des Beispieltexts in Karteneinheiten</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="295"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="313"/>
<source>Sample background color</source>
<translation>Beispielhintergrundfarbe</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1566"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1667"/>
<source>Line direction symbol</source>
<translation>Linienrichtungssymbol</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1819"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1947"/>
<source>Formatted numbers</source>
<translation>Zahlenformatierung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1854"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1982"/>
<source>Decimal places </source>
<translation>Dezimalstellen </translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1884"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2012"/>
<source>Show plus sign</source>
<translation>Plus-Vorzeichen anzeigen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1369"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1461"/>
<source>Multiple lines</source>
<translation>Mehrzeilig</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5857"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6274"/>
<source>Minimise placing labels</source>
<translation>Beschriftungsplazierung minimieren</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5911"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6337"/>
<source>Label with</source>
<translation>Beschriften mit</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="63"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="81"/>
<source>Text/Buffer Sample</source>
<translation>Text/Puffer Beispiel</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="479"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1293"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3337"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="506"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1376"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3509"/>
<source>Text</source>
<translation>Text</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="491"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="494"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1330"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="518"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="521"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1422"/>
<source>Formatting</source>
<translation>Formatierung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="527"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="530"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3539"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="554"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="557"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3708"/>
<source>Shadow</source>
<translation>Schatten</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="551"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="554"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5028"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="578"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="581"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5382"/>
<source>Rendering</source>
<translation>Darstellung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="660"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="705"/>
<source>letter</source>
<translation>Buchstabe</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="955"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1006"/>
<source>Spacing</source>
<translation>Zwischenräume</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="984"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2157"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2799"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3378"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1035"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2300"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2957"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3550"/>
<source>Blend mode</source>
<translation>Mischmodi</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="999"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1050"/>
<source>word</source>
<translation>Wort</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1066"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1117"/>
<source>Underlined text</source>
<translation>Unterstrichener Text</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1160"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1211"/>
<source>Bold text
(data defined only, overrides Style)</source>
<translation>Fetter Text
(nur datendefiniert, überschreibt Stil)</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1164"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1215"/>
<source>B</source>
<translation>F</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1202"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1253"/>
<source>Italic text
(data defined only, overrides Style)</source>
<translation>Kursiver Text
(nur datendefiniert, überschreibt Stil)</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1206"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1257"/>
<source>I</source>
<translation>K</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1264"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1324"/>
<source>Font is missing.</source>
<translation>Font fehlt.</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1427"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1337"/>
+ <source>If enabled, the label text will automatically be modified using a preset list of substitutes</source>
+ <translation>Wenn aktiv wird die Beschriftung automatisch mit einer vorgegebenen Liste von Ersetzungen behandelt</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1340"/>
+ <source>Apply label text substitutes</source>
+ <translation>Beschriftungsersetzungen anwenden</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1350"/>
+ <source>Configure substitutes</source>
+ <translation>Ersetzungen einstellen</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1519"/>
<source>Wrap on character</source>
<translation>Bei Zeichen umbrechen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1440"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1532"/>
<source>Line height</source>
<translation>Linienhöhe</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1456"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1548"/>
<source>Line height spacing for multi-line text</source>
<translation>Zeilenhöhe bei mehrzeiligem Text</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1459"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1551"/>
<source> line</source>
<translation> Zeile</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1484"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4847"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1576"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5183"/>
<source>Alignment</source>
<translation>Ausrichtung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1494"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1586"/>
<source>Paragraph style alignment of multi-line text</source>
<translation>Absatzstilausrichtung mehrzeiligen Texts</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1501"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1655"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1593"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1765"/>
<source>Left</source>
<translation>Links</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1506"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1598"/>
<source>Center</source>
<translation>Zentriert</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1511"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1662"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1603"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1772"/>
<source>Right</source>
<translation>Rechts</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3649"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3845"/>
<source>Labels are placed in an equal radius circle around point features.</source>
<translation>Beschriftungen werden auf einem Kreis um das Punktobjekt plaziert</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3662"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3858"/>
<source>Labels are placed at a fixed offset from the point.</source>
<translation>Beschriftungen werden mit einem festen Abstand um den Punkt plaziert.</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3672"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3868"/>
<source>Uses cartographically 'ideal' placements, prioritising label placement with best visual relationship with the point feature</source>
<translation>Kartographisch 'ideale' Plazierung verwenden (bevorzugt mit der besten visuellen Beziehung zum Punktobjekt)</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3675"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3871"/>
<source>Cartographic</source>
<translation>Kartographisch</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3814"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4009"/>
+ <source>Using perimeter (curved)</source>
+ <translation>Umfang verwenden (Kurve)</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4042"/>
<source>Allowed label placement for lines. At least one position must be selected.</source>
<translation>Erlaubte Beschriftungsplazierung für Linien. Mindestens eine Position muß gewählt sein.</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3835"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4072"/>
<source>Allowed positions</source>
<translation>Erlaubte Positionen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3956"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4202"/>
<source>Force point inside polygon</source>
<translation>Punkt innerhalb des Polygons erzwingen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4063"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4327"/>
<source>Distance offset from</source>
<translation>Abstand aus</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4392"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4692"/>
<source>Position priority</source>
<translation>Positionspriorität</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4593"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4920"/>
<source>Repeat</source>
<translation>Wiederholen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4606"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4933"/>
<source>No repeat</source>
<translation>Keine Wiederholung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5357"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5711"/>
<source>Label z-index</source>
<translation>Z-Index der Beschriftung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5364"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5718"/>
<source>Controls how labels are drawn on top of each other. Labels with a higher z-index are drawn above labels with a lower z-index.</source>
<translation>Steuert wie Beschriftungen übereinander gezeichnet werden. Beschriftungen mit einem größeren Z-Index werden über Beschriftungen mit niederigeren gezeichnet.</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5724"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6123"/>
<source>Only draw labels which fit completely within feature</source>
<translation>Nur Beschriftungen zeichnen, die ganz in ein Objekt passen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5750"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6149"/>
<source>Obstacles</source>
<translation>Hindernisse</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5761"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6160"/>
<source>Discourage labels from covering features</source>
<translation>Möglichst keine Objekte durch Beschriftungen verdecken</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5796"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6204"/>
<source>Low weight</source>
<translation>Kleines Gewicht</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5803"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6211"/>
<source>Controls how likely labels are to cover features in this layer</source>
<translation>Steuert wie wahrscheinlich Beschriftungen Objekte dieses Layers verdecken</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5828"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6236"/>
<source>High weight</source>
<translation>Hohes Gewicht</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="482"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="509"/>
<source>Text style</source>
<translation>Textstil</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="808"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="853"/>
<source>Available typeface styles</source>
<translation>Verfügbare Schriftartstile</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1069"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1120"/>
<source>U</source>
<translation>U</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1107"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1158"/>
<source>Strikeout text</source>
<translation>Durchgestrichener Text</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1110"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1161"/>
<source>S</source>
<translation>S</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="735"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="780"/>
<source>Style</source>
<translation>Stil</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="767"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2150"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2556"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3408"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="812"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2293"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2717"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3580"/>
<source>Transparency</source>
<translation>Transparenz</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="899"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2134"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2596"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3362"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3448"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="953"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2277"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2754"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3534"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3617"/>
<source> %</source>
<translation> %</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="757"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="802"/>
<source>Capitalization style of text</source>
<translation>Großschreibungstil des Texts</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="673"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1012"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="718"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1063"/>
<source>Space in pixels or map units, relative to size unit choice</source>
<translation>Abstand in Pixel oder Karteneinheiten relativ zur Größeneinheitenwahl</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="918"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="972"/>
<source>Type case</source>
<translation>Schriftart Groß-/Kleinschreibung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="780"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="825"/>
<source>Font</source>
<translation>Schriftart</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="938"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2037"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3398"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="992"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2174"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3570"/>
<source>Color</source>
<translation>Farbe</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1241"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2223"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1292"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2366"/>
<source>Size</source>
<translation>Größe</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="503"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="506"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2258"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2708"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3342"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="530"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="533"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2401"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2866"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3514"/>
<source>Buffer</source>
<translation>Puffer</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5311"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5665"/>
<source>Labels will not show if larger than this on screen</source>
<translation>Größere Beschriftungen werden nicht angezeigt</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5276"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5314"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5630"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5668"/>
<source> px</source>
<translation> px</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4758"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5500"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5094"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5863"/>
<source>Data defined</source>
<translation>Datendefiniert</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4784"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5120"/>
<source>X</source>
<translation>X</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4804"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5140"/>
<source>Y</source>
<translation>Y</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4840"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5176"/>
<source>Coordinate</source>
<translation>Koordinate</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4869"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5205"/>
<source>Preserve data rotation values</source>
<translation>Datenrotationswerte erhalten</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4893"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5238"/>
<source>horizontal</source>
<translation>horizontal</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4913"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5258"/>
<source>vertical</source>
<translation>vertikal</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5062"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5416"/>
<source>Label options</source>
<translation>Beschriftungsoptionen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5142"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5174"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5496"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5528"/>
<source>Value < 0 represents a scale closer than 1:1, e.g. -10 = 10:1.<br>Value of 0 disables the specific limit.</source>
<translation>Wert < 0 definiert einen größeren Maßstab als 1:1, z.B. -10 = 10:1<br>Wert = 0 schaltet die betreffende Beschränkung ab.</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5177"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5317"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5531"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5671"/>
<source>Maximum </source>
<translation>Maximum </translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5219"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5573"/>
<source>Pixel size-based visibility (labels in map units)</source>
<translation>Sichtbarkeit nach Pixelgröße (Beschriftung in Karteneinheiten)</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5273"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5627"/>
<source>Labels will not show if smaller than this on screen</source>
<translation>Kleinere Beschriftungen werden nicht angezeigt</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5145"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5279"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5499"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5633"/>
<source>Minimum </source>
<translation>Minimum </translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1711"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1830"/>
<source><</source>
<translation><</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5088"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5442"/>
<source>Scale-based visibility</source>
<translation>Maßstabsabhängige Darstellung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1609"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1719"/>
<source>></source>
<translation>></translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="539"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="542"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1675"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3578"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="566"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="569"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1785"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3756"/>
<source>Placement</source>
<translation>Platzierung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1756"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1884"/>
<source>left/right</source>
<translation>links/rechts</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1772"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1900"/>
<source>above</source>
<translation>über</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1779"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1907"/>
<source>below</source>
<translation>unter</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1682"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="1792"/>
<source>Reverse direction</source>
<translation>Rückwärts</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4946"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5291"/>
<source>Priority</source>
<translation>Priorität</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4961"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5306"/>
<source>Low</source>
<translation>Niedrig</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4987"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5332"/>
<source>High</source>
<translation>Hoch</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3652"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3848"/>
<source>Around point</source>
<translation>Um Punkt</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3665"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3861"/>
<source>Offset from point</source>
<translation>Abstand vom Punkt</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3721"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3926"/>
<source>Parallel</source>
<translation>Parallel</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3708"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3913"/>
<source>Curved</source>
<translation>Gebogen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="1972"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2109"/>
<source>Draw text buffer</source>
<translation>Textpuffer zeichnen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2236"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2379"/>
<source>Color buffer's fill</source>
<translation>Pufferfüllung einfärben</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2345"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2497"/>
<source>Draw background</source>
<translation>Hintergrund zeichnen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2518"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2679"/>
<source>Size X</source>
<translation>Größe X</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2525"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2686"/>
<source>Size type</source>
<translation>Größenart</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2539"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2700"/>
<source>Size Y</source>
<translation>Größe Y</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2673"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2831"/>
<source>Fill color</source>
<translation>Füllfarbe</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2693"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2851"/>
<source>Border color</source>
<translation>Randfarbe</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3145"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3317"/>
<source>Draw drop shadow</source>
<translation>Schattenwurf zeichnen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3216"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3388"/>
<source>Blur radius</source>
<translation>Radius verschmieren</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3229"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3401"/>
<source>Blur only alpha pixels</source>
<translation>Nur transparente Pixel verschmieren</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3261"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3433"/>
<source>Label's rotation is ignored</source>
<translation>Beschriftungsdrehung wird ignoriert</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3264"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3436"/>
<source>Use global shadow</source>
<translation>Globalen Schatten verwenden</translation>
</message>
<message utf8="true">
- <location filename="../src/ui/qgslabelingguibase.ui" line="3307"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4555"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3479"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4873"/>
<source>˚</source>
<translation>°</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3332"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3504"/>
<source>Lowest label component</source>
<translation>Niedrigste Beschriftungskomponente</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3355"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3527"/>
<source>Draw under</source>
<translation>Zeichnen unter</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3731"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3936"/>
<source>Horizontal</source>
<translation>Horizontal</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3751"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3953"/>
<source>Offset from centroid</source>
<translation>Abstand vom Zentrum</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3767"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3976"/>
<source>Around centroid</source>
<translation>Um Zentrum</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3774"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3963"/>
<source>Horizontal (slow)</source>
<translation>Horizontal (langsam)</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3781"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3983"/>
<source>Free (slow)</source>
<translation>Frei (langsam)</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3794"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3996"/>
<source>Using perimeter</source>
<translation>Nach Umfang</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3926"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4172"/>
<source>visible polygon</source>
<translation>sichtbarem Polygon</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3942"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4188"/>
<source>whole polygon</source>
<translation>ganzem Polygon</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2426"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4536"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4833"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2578"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4854"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5169"/>
<source>Rotation</source>
<translation>Drehung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3850"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4087"/>
<source>Above line</source>
<translation>Über Linie</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3866"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4103"/>
<source>On line</source>
<translation>Auf Linie</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3873"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4110"/>
<source>Below line</source>
<translation>Unter Linie</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3882"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4119"/>
<source>Line orientation dependent position</source>
<translation>Linienrichtungsabhängige Position</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3910"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4156"/>
<source>Centroid</source>
<translation>Zentroid</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4124"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4144"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4164"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4184"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4204"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4224"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4244"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4264"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4406"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4426"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4446"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4466"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4486"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4506"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4526"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4546"/>
<source>abc</source>
<translation>abc</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4293"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4575"/>
<source>Quadrant</source>
<translation>Quadrant</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4006"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4261"/>
<source>Distance</source>
<translation>Entfernung</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4706"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5042"/>
<source>outside</source>
<translation>außen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4670"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5006"/>
<source>inside</source>
<translation>innen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4735"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5071"/>
<source>Maximum angle between curved characters</source>
<translation>Größter Winkel zwischen Zeichen auf Kurven</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2047"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2654"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2184"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2812"/>
<source>Pen join style</source>
<translation>Stiftübergangsstil</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3385"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3557"/>
<source>Offset</source>
<translation>Versatz</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3209"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3381"/>
<source>Scale</source>
<translation>Maßstab </translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="515"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="518"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3061"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="3347"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="542"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="545"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3224"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3519"/>
<source>Background</source>
<translation>Hintergrund</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2750"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2908"/>
<source>Load symbol parameters</source>
<translation>Symbolparameter laden</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2713"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2817"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2871"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2975"/>
<source>Fixed</source>
<translation>Fest</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2981"/>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4499"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3144"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="4808"/>
<source>Offset X,Y</source>
<translation>X,Y Versatz</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2931"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3094"/>
<source>Rectangle</source>
<translation>Rechteck</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2936"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3099"/>
<source>Square</source>
<translation>Quadratisch</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2941"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3104"/>
<source>Ellipse</source>
<translation>Ellipse</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2946"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3109"/>
<source>Circle</source>
<translation>Kreis</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2951"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3114"/>
<source>SVG</source>
<translation>SVG</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2532"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2693"/>
<source>Shape</source>
<translation>Form</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2807"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2965"/>
<source>Sync with label</source>
<translation>Mit Beschriftung abgleichen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2812"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2970"/>
<source>Offset of label</source>
<translation>Beschriftungsversatz</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2377"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2529"/>
<source>Radius X,Y</source>
<translation>X-,Y-Radius</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2757"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="2915"/>
<source>Border width</source>
<translation>Randbreite</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="2899"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="3062"/>
<source>symbol units</source>
<translation>Symboleinheiten</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5606"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5978"/>
<source>Merge connected lines to avoid duplicate labels</source>
<translation>Anschließende Linien verbinden, um doppelte Beschriftungen zu vermeiden</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5599"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5971"/>
<source>Label every part of multi-part features</source>
<translation>Alle Teile mehrteiliger Objekte beschriften</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5584"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5956"/>
<source>Feature options</source>
<translation>Objektoptionen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5702"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6092"/>
<source>Suppress labeling of features smaller than</source>
<translation>Objekte nicht beschriften, wenn kürzer als</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5695"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6085"/>
<source> mm</source>
<translation> mm</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5399"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5753"/>
<source>Show all labels for this layer (including colliding labels)</source>
<translation>Alle Beschriftungen auf diesem Layer anzeigen (einschließlich kollidierender)</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5571"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5943"/>
<source>Show upside-down labels</source>
<translation>Kopfstehende Beschriftungen anzeigen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5532"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5904"/>
<source>never</source>
<translation>nie</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5548"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5920"/>
<source>when rotation defined</source>
<translation>bei definiertem Winkel</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5519"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5891"/>
<source>always</source>
<translation>immer</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5660"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6041"/>
<source>Limit number of features to be labeled to</source>
<translation>Obergrenze der zu beschriftenden Objekte</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5641"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="6022"/>
<source>Number of features sent to labeling engine, though not all may be labeled</source>
<translation>Anzahl der Objekte, die die Beschriftung durchlaufen, aber evtl. nicht beschriftet werden</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="4863"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5199"/>
<source>Uncheck to write labeling engine derived rotation on pin and NULL on unpin</source>
<translation>Abhaken, um den berechneten Winkel der Beschriftungsfunktion beim Anpinnen und NULL beim Lösen zu speichern</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5454"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5817"/>
<source>Always show</source>
<translation>Immer anzeigen</translation>
</message>
<message>
- <location filename="../src/ui/qgslabelingguibase.ui" line="5470"/>
+ <location filename="../src/ui/qgslabelingguibase.ui" line="5833"/>
<source>Show label</source>
<translation>Beschriftung anzeigen</translation>
</message>
@@ -59112,28 +59781,28 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<context>
<name>QgsLayerStylingWidget</name>
<message>
- <location filename="../src/app/qgslayerstylingwidget.cpp" line="156"/>
- <location filename="../src/app/qgslayerstylingwidget.cpp" line="167"/>
+ <location filename="../src/app/qgslayerstylingwidget.cpp" line="157"/>
+ <location filename="../src/app/qgslayerstylingwidget.cpp" line="168"/>
<source>Symbology</source>
<translation>Darstellung</translation>
</message>
<message>
- <location filename="../src/app/qgslayerstylingwidget.cpp" line="160"/>
+ <location filename="../src/app/qgslayerstylingwidget.cpp" line="161"/>
<source>Labels</source>
<translation>Beschriftungen</translation>
</message>
<message>
- <location filename="../src/app/qgslayerstylingwidget.cpp" line="170"/>
+ <location filename="../src/app/qgslayerstylingwidget.cpp" line="171"/>
<source>Transparency</source>
<translation>Transparenz</translation>
</message>
<message>
- <location filename="../src/app/qgslayerstylingwidget.cpp" line="176"/>
+ <location filename="../src/app/qgslayerstylingwidget.cpp" line="180"/>
<source>Histogram</source>
<translation>Histogramm</translation>
</message>
<message>
- <location filename="../src/app/qgslayerstylingwidget.cpp" line="192"/>
+ <location filename="../src/app/qgslayerstylingwidget.cpp" line="197"/>
<source>History</source>
<translation>Protokoll</translation>
</message>
@@ -59501,38 +60170,38 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<translation>Karte</translation>
</message>
<message>
- <location filename="../src/gui/qgsmapcanvas.cpp" line="758"/>
- <location filename="../src/gui/qgsmapcanvas.cpp" line="778"/>
+ <location filename="../src/gui/qgsmapcanvas.cpp" line="764"/>
+ <location filename="../src/gui/qgsmapcanvas.cpp" line="784"/>
<source>Rendering</source>
<translation>Darstellung</translation>
</message>
<message>
- <location filename="../src/gui/qgsmapcanvas.cpp" line="777"/>
+ <location filename="../src/gui/qgsmapcanvas.cpp" line="783"/>
<source>Canvas refresh: %1 ms</source>
<translation>Kartenaktualisierung: %1 ms</translation>
</message>
<message>
- <location filename="../src/gui/qgsmapcanvas.cpp" line="1176"/>
+ <location filename="../src/gui/qgsmapcanvas.cpp" line="1182"/>
<source>Feature does not have a geometry</source>
<translation>Objekt hat keine Geometrie</translation>
</message>
<message>
- <location filename="../src/gui/qgsmapcanvas.cpp" line="1180"/>
+ <location filename="../src/gui/qgsmapcanvas.cpp" line="1186"/>
<source>Feature geometry is empty</source>
<translation>Objektgeometrie ist leer</translation>
</message>
<message>
- <location filename="../src/gui/qgsmapcanvas.cpp" line="1184"/>
+ <location filename="../src/gui/qgsmapcanvas.cpp" line="1190"/>
<source>Zoom to feature id failed</source>
<translation>Zoom auf Objektkennung gescheitert</translation>
</message>
<message>
- <location filename="../src/gui/qgsmapcanvas.cpp" line="1219"/>
+ <location filename="../src/gui/qgsmapcanvas.cpp" line="1225"/>
<source>Cannot pan to selected feature(s)</source>
<translation>Kann Karte nicht zu gewählten Objekten bewegen</translation>
</message>
<message>
- <location filename="../src/gui/qgsmapcanvas.cpp" line="1219"/>
+ <location filename="../src/gui/qgsmapcanvas.cpp" line="1225"/>
<source>Geometry is NULL</source>
<translation>Geometry ist NULL</translation>
</message>
@@ -59597,103 +60266,103 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<context>
<name>QgsMapLayer</name>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="389"/>
- <location filename="../src/core/qgsmaplayer.cpp" line="1022"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="391"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1024"/>
<source>Specify CRS for layer %1</source>
<translation>KBS für Layer %1 angeben</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1165"/>
- <location filename="../src/core/qgsmaplayer.cpp" line="1181"/>
- <location filename="../src/core/qgsmaplayer.cpp" line="1575"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1167"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1183"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1582"/>
<source>%1 at line %2 column %3</source>
<translation>%1 in Zeile %2, Spalte %3</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1197"/>
- <location filename="../src/core/qgsmaplayer.cpp" line="1611"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1199"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1618"/>
<source>Loading style file %1 failed because:
%2</source>
<translation>Stildatei %1 konnte nicht geladen werden, weil:
%2</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1478"/>
- <location filename="../src/core/qgsmaplayer.cpp" line="1485"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1479"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1492"/>
<source>Could not save symbology because:
%1</source>
<translation>Konnte Darstellung nicht speichern, weil:
%1</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1348"/>
- <location filename="../src/core/qgsmaplayer.cpp" line="1535"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1350"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1542"/>
<source>The directory containing your dataset needs to be writable!</source>
<translation>Der Ordner mit den Daten muss beschreibbar sein!</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1186"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1188"/>
<source>Style not found in database</source>
<translation>Stil nicht in der Datenbank gefunden</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1229"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1231"/>
<source>Cannot apply style to layer with a different geometry type</source>
<translation>Kann Stil nicht auf Layer mit anderem Geometrietyp anwenden</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1362"/>
- <location filename="../src/core/qgsmaplayer.cpp" line="1549"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1364"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1556"/>
<source>Created default style file as %1</source>
<translation>Vorgabestildatei als %1 gespeichert</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1367"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1369"/>
<source>ERROR: Failed to created default style file as %1. Check file permissions and retry.</source>
<translation>FEHLER: Konnte die Datei %1 für den voreingestellten Stil nicht erzeugen. Bitte überprüfen Sie die Zugriffsrechte vor einem erneuten Versuch.</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1383"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1385"/>
<source>User database could not be opened.</source>
<translation>Benutzerdatenbank konnte nicht geöffnet werden.</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1398"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1400"/>
<source>The style table could not be created.</source>
<translation>Die Stiltabelle konnte nicht angelegt werden.</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1413"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1415"/>
<source>The style %1 was saved to database</source>
<translation>Der Stil %1 wurde in der Datenbank gespeichert</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1430"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1432"/>
<source>The style %1 was updated in the database.</source>
<translation>Der Stil %1 wurde in der Datenbank aktualisiert.</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1435"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1437"/>
<source>The style %1 could not be updated in the database.</source>
<translation>Der Stil %1 konnte nicht in der Datenbank aktualisiert werden.</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1441"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1443"/>
<source>The style %1 could not be inserted into database.</source>
<translation>Der Stil %1 konnte nicht in der Datenbank gespeichert werden.</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1554"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1561"/>
<source>ERROR: Failed to created SLD style file as %1. Check file permissions and retry.</source>
<translation>FEHLER: Konnte SLD-Stildatei %1 nicht erstellen. Prüfen Sie bitte die Berechtigungen und wiederholen Sie den Versuch.</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1580"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1587"/>
<source>Unable to open file %1</source>
<translation>Konnte Datei %1 nicht öffnen</translation>
</message>
<message>
- <location filename="../src/core/qgsmaplayer.cpp" line="1208"/>
+ <location filename="../src/core/qgsmaplayer.cpp" line="1210"/>
<source>Root <qgis> element could not be found</source>
<translation>Wurzelelement <qgis> nicht gefunden</translation>
</message>
@@ -59878,18 +60547,18 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<translation>Es gab ein Problem bei der Transformation der Layerausmaße. Layer übersprungen.</translation>
</message>
<message>
- <location filename="../src/core/qgsmaprendererjob.cpp" line="280"/>
+ <location filename="../src/core/qgsmaprendererjob.cpp" line="285"/>
<source>Insufficient memory for image %1x%2</source>
<translation>Speicher reicht für Bild %1x%2 nicht aus</translation>
</message>
<message>
- <location filename="../src/core/qgsmaprendererjob.cpp" line="387"/>
+ <location filename="../src/core/qgsmaprendererjob.cpp" line="394"/>
<source>%1 ms: %2</source>
<translation>%1 ms: %2</translation>
</message>
<message>
- <location filename="../src/core/qgsmaprendererjob.cpp" line="387"/>
- <location filename="../src/core/qgsmaprendererjob.cpp" line="389"/>
+ <location filename="../src/core/qgsmaprendererjob.cpp" line="394"/>
+ <location filename="../src/core/qgsmaprendererjob.cpp" line="396"/>
<source>Rendering</source>
<translation>Darstellung</translation>
</message>
@@ -60373,7 +61042,7 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<context>
<name>QgsMapToolNodeTool</name>
<message>
- <location filename="../src/app/nodetool/qgsmaptoolnodetool.cpp" line="231"/>
+ <location filename="../src/app/nodetool/qgsmaptoolnodetool.cpp" line="232"/>
<source>Could not snap to a feature in the current layer.</source>
<translation>Konnte nicht auf eine Objekt des aktuellen Layers fangen.</translation>
</message>
@@ -60488,7 +61157,7 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<message>
<location filename="../src/app/qgsmaptoolreshape.cpp" line="120"/>
<source>The feature cannot be reshaped because the resulting geometry is empty</source>
- <translation>Das Objekt kann nicht umgeformt werden, weil die Ergebnisgeometrie leer ist.</translation>
+ <translation>Das Objekt kann nicht umgeformt werden, weil die Ergebnisgeometrie leer ist</translation>
</message>
</context>
<context>
@@ -60766,7 +61435,7 @@ Die könnte auf ein Netzwerkproblem oder ein Problem des WMS-Server hindeuten.</
<context>
<name>QgsMarkerLineSymbolLayerV2Widget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1687"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1688"/>
<source>string </source>
<translation>Zeichenkette </translation>
</message>
@@ -60848,91 +61517,91 @@ and re-encrypted using new password</source>
<translation>&Konfiguration</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="271"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="286"/>
<source>The calculations are based on:</source>
<translation>Die Berechnungen basieren auf:</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="293"/>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="367"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="308"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="382"/>
<source>Project CRS transformation is turned off.</source>
<translation>KBS-Transformation im Projekt deaktiviert.</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="368"/>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="386"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="383"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="401"/>
<source>Distance is calculated in %1, based on project CRS (%2).</source>
<translation>Abstand wird auf Basis des Projekt-KBS (%2) in %1 berechnet.</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="296"/>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="370"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="311"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="385"/>
<source>Ellipsoidal calculation is not possible with CRS transformation disabled.</source>
<translation>Ellipsoide Berechnung ist ohne KBS-Transformation nicht möglich.</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="340"/>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="414"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="355"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="429"/>
<source>The value is converted from %1 to %2.</source>
<translation>Der Wert wird von %1 in %2 umgewandelt.</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="297"/>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="371"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="312"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="386"/>
<source>Measure (OTF off)</source>
<translation>Maß (SRP aus)</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="282"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="297"/>
<source>Both project CRS (%1) and measured area are in degrees, so area is calculated using cartesian calculations in square degrees.</source>
<translation>Sowohl Projekt-KBS (%1) und Flächenenmessung sind in Grad, daher werden Flächen mit kartesische Berechnungen in Quadratgrad berechnet.</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="294"/>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="312"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="309"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="327"/>
<source>Area is calculated in %1, based on project CRS (%2).</source>
<translation>Flächen werden in %1 berechnet auf Basis des Projekt-KBS (%2).</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="304"/>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="378"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="319"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="393"/>
<source>Project CRS transformation is turned on and ellipsoidal calculation is selected.</source>
<translation>Projekt-KBS-Transformation aktiv und ellipsoide Berechnung gewählt.</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="305"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="320"/>
<source>The coordinates are transformed to the chosen ellipsoid (%1), and the area is calculated in %2.</source>
<translation>Die Koordinaten werden auf den gewählten Ellipsoiden (%1) transformiert und die Fläche in %2 berechnet.</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="311"/>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="385"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="326"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="400"/>
<source>Project CRS transformation is turned on but ellipsoidal calculation is not selected.</source>
<translation>Projekt-KBS-Transformation aktiv, aber ellipsoide Berechnung ist nicht gewählt.</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="315"/>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="389"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="330"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="404"/>
<source>Measure (OTF on)</source>
<translation>Maß (SRP an)</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="356"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="371"/>
<source>Both project CRS (%1) and measured length are in degrees, so distance is calculated using cartesian calculations in degrees.</source>
<translation>Sowohl Projekt-KBS (%1) und gemessene Längen sind in Grad, Abstände werden durch kartesische Berechnungen in Grad berechnet.</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="379"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="394"/>
<source>The coordinates are transformed to the chosen ellipsoid (%1), and the distance is calculated in %2.</source>
<translation>Die Koordinaten werden auf den gewählten Ellipsoiden (%1) transformiert und die Abstände in %2 berechnet.</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="436"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="451"/>
<source>Segments [%1]</source>
<translation>Segmente [%1]</translation>
</message>
<message>
- <location filename="../src/app/qgsmeasuredialog.cpp" line="504"/>
+ <location filename="../src/app/qgsmeasuredialog.cpp" line="519"/>
<source>map units</source>
<translation>Karteneinheiten</translation>
</message>
@@ -61827,12 +62496,12 @@ verbesserung</translation>
<context>
<name>QgsNetworkAccessManager</name>
<message>
- <location filename="../src/core/qgsnetworkaccessmanager.cpp" line="238"/>
+ <location filename="../src/core/qgsnetworkaccessmanager.cpp" line="242"/>
<source>Network request %1 timed out</source>
<translation>Netzwerkanfrage %1 dauerte zu lange</translation>
</message>
<message>
- <location filename="../src/core/qgsnetworkaccessmanager.cpp" line="238"/>
+ <location filename="../src/core/qgsnetworkaccessmanager.cpp" line="242"/>
<source>Network</source>
<translation>Netzwerk</translation>
</message>
@@ -62842,8 +63511,7 @@ Ausführliche Fehlerinformation:
<message>
<location filename="../src/ui/qgsnewspatialitelayerdialogbase.ui" line="252"/>
<source>Create an autoincrementing primary key</source>
- <translation>automatisch inkrementierenden
-Primärschlüssel erzeugen</translation>
+ <translation>automatisch inkrementierenden Primärschlüssel erzeugen</translation>
</message>
<message>
<location filename="../src/ui/qgsnewspatialitelayerdialogbase.ui" line="262"/>
@@ -63722,46 +64390,46 @@ Immer Netzwerk: immer aus dem Netzwerk laden und nicht prüfen, ob im Cache ein
<translation>Konnte die SpatiaLite-Datenbank nicht öffnen</translation>
</message>
<message>
- <location filename="../src/core/qgsofflineediting.cpp" line="384"/>
+ <location filename="../src/core/qgsofflineediting.cpp" line="382"/>
<source>Unable to initialize SpatialMetadata:
</source>
<translation>Konnten räumliche Metadaten nicht initialisieren:
</translation>
</message>
<message>
- <location filename="../src/core/qgsofflineediting.cpp" line="418"/>
+ <location filename="../src/core/qgsofflineediting.cpp" line="416"/>
<source>Could not create a new database
</source>
<translation>Konnte neue Datenbank nicht anlegen
</translation>
</message>
<message>
- <location filename="../src/core/qgsofflineediting.cpp" line="428"/>
+ <location filename="../src/core/qgsofflineediting.cpp" line="426"/>
<source>Unable to activate FOREIGN_KEY constraints</source>
<translation>Konnten FOREIGN_KEY-Einschränkung nicht aktivieren</translation>
</message>
<message>
- <location filename="../src/core/qgsofflineediting.cpp" line="551"/>
+ <location filename="../src/core/qgsofflineediting.cpp" line="549"/>
<source>QGIS wkbType %1 not supported</source>
<translation>QGIS WKB-Typ %1 nicht unterstützt</translation>
</message>
<message>
- <location filename="../src/core/qgsofflineediting.cpp" line="690"/>
+ <location filename="../src/core/qgsofflineediting.cpp" line="704"/>
<source>Feature cannot be copied to the offline layer, please check if the online layer '%1' is still accessible.</source>
<translation>Objekt kann nicht in Offline-Layer kopiert werden. Bitte prüfen, ob der Online-Layer '%1' noch erreichbar ist.</translation>
</message>
<message>
- <location filename="../src/core/qgsofflineediting.cpp" line="936"/>
+ <location filename="../src/core/qgsofflineediting.cpp" line="953"/>
<source>Offline Editing Plugin</source>
<translation>Offline-Bearbeitungserweiterung</translation>
</message>
<message>
- <location filename="../src/core/qgsofflineediting.cpp" line="950"/>
+ <location filename="../src/core/qgsofflineediting.cpp" line="967"/>
<source>Could not open the spatialite logging database</source>
<translation>Konnte die SpatiaLite-Protokolldatenbank nicht öffnen</translation>
</message>
<message>
- <location filename="../src/core/qgsofflineediting.cpp" line="516"/>
+ <location filename="../src/core/qgsofflineediting.cpp" line="514"/>
<source>%1: Unknown data type %2. Not using type affinity for the field.</source>
<translation>%1: Unbekannter Datentyp %2. Typenangabe wird nicht für Feld verwendet.</translation>
</message>
@@ -63845,32 +64513,32 @@ Immer Netzwerk: immer aus dem Netzwerk laden und nicht prüfen, ob im Cache ein
<context>
<name>QgsOfflineEditingPluginGui</name>
<message>
- <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="113"/>
+ <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="118"/>
<source>Select target database for offline data</source>
<translation>Zieldatenbank für Offline-Daten wählen</translation>
</message>
<message>
- <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="115"/>
+ <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="120"/>
<source>SpatiaLite DB</source>
<translation>SpatiaLite DB</translation>
</message>
<message>
- <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="116"/>
+ <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="121"/>
<source>All files</source>
<translation>Alle Dateien</translation>
</message>
<message>
- <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="135"/>
+ <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="140"/>
<source>Offline Editing Plugin</source>
<translation>Offline-Bearbeitungserweiterung</translation>
</message>
<message>
- <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="136"/>
+ <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="141"/>
<source>Converting to offline project.</source>
<translation>Konvertiere zu Offline-Projekt.</translation>
</message>
<message>
- <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="137"/>
+ <location filename="../src/plugins/offline_editing/offline_editing_plugin_gui.cpp" line="142"/>
<source>Offline database file '%1' exists. Overwrite?</source>
<translation>Offline-Datenbankdatei '%1' vorhanden. Überschreiben?</translation>
</message>
@@ -63907,6 +64575,11 @@ Immer Netzwerk: immer aus dem Netzwerk laden und nicht prüfen, ob im Cache ein
<source>Deselect all</source>
<translation>Alle abwählen</translation>
</message>
+ <message>
+ <location filename="../src/plugins/offline_editing/offline_editing_plugin_guibase.ui" line="98"/>
+ <source>Only synchronize selected features if a selection is present</source>
+ <translation>Nur gewählte Objekte synchronisieren (wenn vorhanden)</translation>
+ </message>
</context>
<context>
<name>QgsOfflineEditingProgressDialog</name>
@@ -63951,240 +64624,241 @@ Immer Netzwerk: immer aus dem Netzwerk laden und nicht prüfen, ob im Cache ein
<context>
<name>QgsOgrProvider</name>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3202"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3354"/>
<source>Data source is invalid, no layer found (%1)</source>
<translation>Datenquelle ungültig, kein Layer gefunden (%1)</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="158"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="177"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="185"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1206"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1884"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3197"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3202"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3207"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3312"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3330"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3345"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="170"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="189"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="197"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1221"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1899"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3349"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3354"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3359"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3476"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3494"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3509"/>
<source>OGR</source>
<translation>OGR</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3197"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3207"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3349"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3359"/>
<source>Data source is invalid (%1)</source>
<translation>Datenquelle ungültig (%1)</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="365"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="377"/>
<source>Whole number (integer)</source>
<translation>Ganzzahl (integer)</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="367"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="379"/>
<source>Whole number (integer 64 bit)</source>
<translation>Ganzzahl (integer 64bit)</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="369"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="381"/>
<source>Decimal number (real)</source>
<translation>Dezimalzahl (real)</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="370"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="382"/>
<source>Text (string)</source>
<translation>Text (string)</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="371"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="383"/>
<source>Date</source>
<translation>Datum</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="378"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="390"/>
<source>Time</source>
<translation>Zeit</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="379"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="391"/>
<source>Date & Time</source>
<translation>Datum & Zeit</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="419"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="162"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="434"/>
<source>OGR[%1] error %2: %3</source>
<translation>OGR[%1] Fehler %2: %3</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="647"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="662"/>
<source>Unknown</source>
<translation>Unbekannt</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1097"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1112"/>
<source>OGR error creating wkb for feature %1: %2</source>
<translation>OGR-Fehler beim erzeugen des WKB für Objekt %1: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1206"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1221"/>
<source>type %1 for attribute %2 not found</source>
<translation>Typ %1 des Attribut %2 nicht gefunden</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1214"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1229"/>
<source>OGR error creating feature %1: %2</source>
<translation>OGR-Fehler beim Erzeugen des Objekts %1: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1320"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1335"/>
<source>type %1 for field %2 not found</source>
<translation>Typ %1 des Feld %2 nicht gefunden</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1334"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1349"/>
<source>OGR error creating field %1: %2</source>
<translation>OGR-Fehler bei Erzeugung des Felds %1: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1369"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1384"/>
<source>Cannot delete feature id column</source>
<translation>Kann Objektkennungsspalte nicht löschen</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1380"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1395"/>
<source>OGR error deleting field %1: %2</source>
<translation>OGR-Fehler beim Löschen des Felds %1: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1388"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1403"/>
<source>Deleting fields is not supported prior to GDAL 1.9.0</source>
<translation>GDAL 1.9.0 unterstützt das Löschen von Feldern nicht vor 1.9.0</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1406"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1423"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1421"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1438"/>
<source>Invalid attribute index</source>
<translation>Ungültiger Attributindex</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1413"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1428"/>
<source>Error renaming field %1: name '%2' already exists</source>
<translation>Fehler beim Umbenennen des Felds %1: name '%2' bereits vorhanden</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1433"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1448"/>
<source>OGR error renaming field %1: %2</source>
<translation>OGR-Fehler beim Umbenennen des Felds %1: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1442"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1457"/>
<source>Renaming fields is not supported prior to GDAL 1.9.0</source>
<translation>Umbenennen von Feldern wird vor GDAL 1.9.0 nicht unterstützt</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1466"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1594"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1734"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1481"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1609"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1749"/>
<source>OGR error on feature %1: id too large</source>
<translation>OGR-Fehler bei Objekt %1: ID zu groß</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1477"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1492"/>
<source>Feature %1 for attribute update not found.</source>
<translation>Objekt %1 zur Attributaktualisierung nicht gefunden.</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1492"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1507"/>
<source>Changing feature id of feature %1 is not allowed.</source>
<translation>Änderung der Objektkennung des Objekts %1 ist nicht erlaubt.</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1505"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1520"/>
<source>Field %1 of feature %2 doesn't exist.</source>
<translation>Feld %1 des Objekts %2 nicht vorhanden.</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1561"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1576"/>
<source>Type %1 of attribute %2 of feature %3 unknown.</source>
<translation>Typ %1 des Attributs %2 des Objekte %3 unbekannt.</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1569"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1647"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1584"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1662"/>
<source>OGR error setting feature %1: %2</source>
<translation>OGR-Fehler beim Setzen des Objekts %1: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1577"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="2981"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1592"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3115"/>
<source>OGR error syncing to disk: %1</source>
<translation>OGR-Fehler beim Syncen auf Festplatte: %1</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1601"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1616"/>
<source>OGR error changing geometry: feature %1 not found</source>
<translation>OGR-Fehler beim Ändern der Geometrie: Objekt %1 nicht gefunden</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1616"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1631"/>
<source>OGR error creating geometry for feature %1: %2</source>
<translation>OGR-Fehler bei Geometrieerzeugung für Objekt %1: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1625"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1640"/>
<source>OGR error in feature %1: geometry is null</source>
<translation>OGR-Fehler bei Objekt %1: Geometrie ist leer</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1636"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1651"/>
<source>OGR error setting geometry of feature %1: %2</source>
<translation>OGR-Fehler beim Setzen der Geometrie des Objekts %1: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3290"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3454"/>
<source>Cannot reopen datasource %1</source>
<translation>Kann Datenquelle %1 nicht neu öffnen</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3312"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3313"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3476"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3477"/>
<source>Cannot reopen datasource %1 in update mode</source>
<translation>Kann Datenquelle %1 nicht im Aktualisierungsmodus neu öffnen</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3330"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3494"/>
<source>Unbalanced call to leaveUpdateMode() w.r.t. enterUpdateMode()</source>
<translation>Aufrufe von leaveUpdateMode() und enterUpdateMode() passen nicht zusammen</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3345"/>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3346"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3509"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="3510"/>
<source>Cannot reopen datasource %1 in read-only mode</source>
<translation>Kann Datenquelle %1 nicht im schreibgeschützten Modus neu öffnen</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="158"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="170"/>
<source>Possible corruption after REPACK detected. %1 still exists. This may point to a permission or locking problem of the original DBF.</source>
<translation>Möglicher Fehler nach REPACK entdeckt. %1 ist noch vorhanden. Dies könnte auf ein Berechtigungs- oder Dateisperrenproblem der DBF hindeuten.</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="177"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="189"/>
<source>Original layer could not be reopened.</source>
<translation>Ursprünglicher Layer konnte nicht erneut geöffnet werden.</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="185"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="197"/>
<source>Original datasource could not be reopened.</source>
<translation>Ursprüngliche Datenquelle konnte nicht erneut geöffnet werden.</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1740"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1755"/>
<source>OGR error deleting feature %1: %2</source>
<translation>OGR-Fehler beim Löschen des Objekts %1: %2</translation>
</message>
<message>
- <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1884"/>
+ <location filename="../src/providers/ogr/qgsogrprovider.cpp" line="1899"/>
<source>Shapefiles without attribute are considered read-only.</source>
<translation>Shapedateien ohne Attribute werden als schreibgeschützt betrachtet.</translation>
</message>
@@ -66946,23 +67620,23 @@ Fehler:%2
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1625"/>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1694"/>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1701"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1841"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2057"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2232"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2264"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2299"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2307"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2327"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2335"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2459"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2481"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2509"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2522"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2806"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2818"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2827"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2986"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2995"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1855"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2071"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2246"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2278"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2313"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2321"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2341"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2349"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2473"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2495"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2523"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2536"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2820"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2832"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2841"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3000"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3009"/>
<source>Oracle</source>
<translation>Oracle</translation>
</message>
@@ -67087,8 +67761,8 @@ SQL: %2</translation>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1583"/>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1663"/>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1727"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2021"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2673"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2035"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2687"/>
<source>Could not start transaction</source>
<translation>Transaktion konnte nicht gestartet werden</translation>
</message>
@@ -67118,9 +67792,9 @@ SQL: %2</translation>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1549"/>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1610"/>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1686"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1833"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2049"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2806"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1847"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2063"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2820"/>
<source>Could not commit transaction</source>
<translation>Transaktion konnte nicht festgeschrieben werden</translation>
</message>
@@ -67135,9 +67809,9 @@ SQL: %2</translation>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1556"/>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1618"/>
<location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1694"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1841"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2057"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2818"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1855"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2071"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2832"/>
<source>Could not rollback transaction</source>
<translation>Transaktion konnte nicht zurückgerollt werden</translation>
</message>
@@ -67204,36 +67878,36 @@ SQL: %2</translation>
<translation>Oracle-Fehler beim Umbenennen von Attributen: %1</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1807"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2042"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1821"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2056"/>
<source>Update of feature %1 failed</source>
<translation>Aktualisierung des Objekte %1 gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1838"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1852"/>
<source>Oracle error while changing attributes: %1</source>
<translation>Oracle-Fehler beim Attributändern: %1</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1786"/>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2031"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="1791"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2045"/>
<source>Could not prepare update statement.</source>
<translation>Konnte Aktualisierungsanweisung nicht vorbereiten.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2054"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2068"/>
<source>Oracle error while changing geometry values: %1</source>
<translation>Oracle-Fehler beim Geometrieändern: %1</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2232"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2246"/>
<source>Could not retrieve extents: %1
SQL: %2</source>
<translation>Konnte Ausmaße nicht bestimmen: %1
SQL: %2</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2262"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2276"/>
<source>Could not execute query.
The error message from the database was:
%1.
@@ -67244,7 +67918,7 @@ Die Datenbankfehlermeldung war:
SQL: %2</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2296"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2310"/>
<source>Could not retrieve SRID of %1.
The error message from the database was:
%2.
@@ -67255,7 +67929,7 @@ Die Datenbankfehlermeldung war:
SQL: %3</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2304"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2318"/>
<source>Could not determine SRID of %1.
The error message from the database was:
%2.
@@ -67266,14 +67940,14 @@ Die Datenbankfehlermeldung war:
SQL: %3</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2325"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2339"/>
<source>%1 has no valid geometry types.
SQL: %2</source>
<translation>%1 hat keine gültigen Geometrietypen.
SQL: %2</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2332"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2346"/>
<source>Could not determine geometry type of %1.
The error message from the database was:
%2.
@@ -67284,22 +67958,22 @@ Die Datenbankfehlermeldung war:
SQL: %3</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2369"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2383"/>
<source>Geometry type and srid for empty column %1 of %2 undefined.</source>
<translation>Geometrietyp und SRID für leere Spalte %1 in %2 undefiniert.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2396"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2410"/>
<source>Feature type or srid for %1 of %2 could not be determined or was not requested.</source>
<translation>Objekttyp oder SRID für %1 aus %2 konnte nicht festgestellt werden oder wurde nicht verlangt.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2424"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2438"/>
<source>Editing and adding disabled for 2D+ layer (%1; %2)</source>
<translation>Ändern und Hinzufügen auf 2D+-Layern abgeschaltet (%1; %2)</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2454"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2468"/>
<source>Could not update metadata for %1.%2.
SQL:%3
Error: %4</source>
@@ -67308,7 +67982,7 @@ SQL:%3
Fehler: %4</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2476"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2490"/>
<source>Could not insert metadata for %1.%2.
SQL:%3
Error: %4</source>
@@ -67317,7 +67991,7 @@ SQL: %3
Fehler: %4</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2506"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2520"/>
<source>Creation spatial index failed.
SQL:%1
Error: %2</source>
@@ -67326,7 +68000,7 @@ SQL:%1
FehleR:%2</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2519"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2533"/>
<source>Rebuild of spatial index failed.
SQL:%1
Error: %2</source>
@@ -67335,52 +68009,52 @@ SQL:%1
Fehler:%2</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2681"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2695"/>
<source>Could not determine table existence.</source>
<translation>Konnte Tabellenexistenz nicht feststellen.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2693"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2707"/>
<source>Table %1 could not be dropped.</source>
<translation>Tabelle %1 konnte nicht gelöscht werden.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2698"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2712"/>
<source>Table %1 already exists.</source>
<translation>Tabelle %1 bereits vorhanden.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2717"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2731"/>
<source>Table creation failed.</source>
<translation>Tabellenerzeugung gescheitert.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2748"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2762"/>
<source>Could not lookup authid %1:%2</source>
<translation>Konnte AuthId %1:%2 nicht finden</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2764"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2778"/>
<source>Could not lookup WKT.</source>
<translation>Konnte WKT nicht finden.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2775"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2789"/>
<source>Could not determine new srid.</source>
<translation>Konnte freie SRID nicht feststellen.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2790"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2804"/>
<source>CRS not found and could not be created.</source>
<translation>KBS nicht gefunden und konnte auch nicht erzeugt werden.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2801"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2815"/>
<source>Could not insert metadata.</source>
<translation>Konnte Metadaten nicht einfügen.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2825"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2839"/>
<source>Drop created table %1 failed.
SQL:%2
Error: %3</source>
@@ -67389,12 +68063,12 @@ SQL:%2
Fehler: %3</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2986"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3000"/>
<source>Oracle SRID %1 not found.</source>
<translation>Oracle SRID %1 nicht gefunden.</translation>
</message>
<message>
- <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="2991"/>
+ <location filename="../src/providers/oracle/qgsoracleprovider.cpp" line="3005"/>
<source>Lookup of Oracle SRID %1 failed.
SQL:%2
Error:%3</source>
@@ -70069,12 +70743,12 @@ Ergebnis: %3 (%4)</translation>
<location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1318"/>
<location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1341"/>
<location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1364"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1437"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1458"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1463"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1468"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1755"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3022"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1454"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1475"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1480"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1485"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1772"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3039"/>
<source>PostGIS</source>
<translation>PostGIS</translation>
</message>
@@ -70245,22 +70919,22 @@ SQL: %2</translation>
<translation>Eindeutige Spalte '%1' hat keine NOT NULL-Einschränkung.</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1437"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1454"/>
<source>Key field '%1' for view/query not found.</source>
<translation>Schlüsselfeld '%1' der Sicht/Abfrage nicht gefunden.</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1458"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1475"/>
<source>Primary key field '%1' for view/query not unique.</source>
<translation>Primärschlüsselfeld '%1' der Sicht/Abfrage ist nicht eindeutig.</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1463"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1480"/>
<source>Keys for view/query undefined.</source>
<translation>Schlüssel für Sicht/Abfrage undefiniert.</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1468"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1485"/>
<source>No key field for view/query given.</source>
<translation>Kein Schlüsselfeld für Sicht/Abfrage gegeben.</translation>
</message>
@@ -70275,93 +70949,93 @@ SQL: %2</translation>
<translation>Ignoriere Schlüsselkandidat wegen NULL-Werten oder Vererbung</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1751"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="1768"/>
<source>Could not find topology of layer %1.%2.%3</source>
<translation>Konnte Topologie des Layers %1.%2.%3 nicht finden</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2104"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2121"/>
<source>PostGIS error while adding features: %1</source>
<translation>PostGIS-Fehler beim Attributhinzufügen: %1</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2163"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2180"/>
<source>PostGIS error while deleting features: %1</source>
<translation>PostGIS-Fehler beim Objektlöschen: %1</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2235"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2252"/>
<source>PostGIS error while adding attributes: %1</source>
<translation>PostGIS-Fehler beim Attributhinzufügen: %1</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2290"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2307"/>
<source>PostGIS error while deleting attributes: %1</source>
<translation>PostGIS-Fehler beim Attributlöschen: %1</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2315"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2332"/>
<source>Invalid attribute index: %1</source>
<translation>Ungültiger Attributindex: %1</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2321"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2338"/>
<source>Error renaming field %1: name '%2' already exists</source>
<translation>Fehler beim Umbenennen des Felds %1: name '%2' bereits vorhanden</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2350"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2367"/>
<source>PostGIS error while renaming attributes: %1</source>
<translation>PostGIS-Fehler beim Attributumbenennen: %1</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2462"/>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2812"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2479"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2829"/>
<source>PostGIS error while changing attributes: %1</source>
<translation>PostGIS-Fehler beim Attributändern: %1</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2662"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="2679"/>
<source>PostGIS error while changing geometry values: %1</source>
<translation>PostGIS-Fehler beim Geometrieändern: %1</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3022"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3039"/>
<source>result of extents query invalid: %1</source>
<translation>Ergebnis der Ausmaßabfrage ungültig: %1</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3335"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3352"/>
<source>Geometry type and srid for empty column %1 of %2 undefined.</source>
<translation>Geometrietyp und SRID für leere Spalte %1 in %2 undefiniert.</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3364"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3381"/>
<source>Feature type or srid for %1 of %2 could not be determined or was not requested.</source>
<translation>Objekttyp oder SRID für %1 aus %2 konnte nicht festgestellt werden und wurde nicht festgelegt.</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3389"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3406"/>
<source>Editing and adding disabled for 2D+ layer (%1; %2)</source>
<translation>Ändern und Hinzufügen auf 2D+-Layern abgeschaltet (%1; %2)</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3778"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3823"/>
<source>PostgreSQL version: unknown</source>
<translation>PostgreSQL-Version: unbekannt</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3779"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3824"/>
<source>unknown</source>
<translation>unbekannt</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3799"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3844"/>
<source>PostgreSQL not connected</source>
<translation>PostgreSQL nicht verbunden</translation>
</message>
<message>
- <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3802"/>
+ <location filename="../src/providers/postgres/qgspostgresprovider.cpp" line="3847"/>
<source>PostgreSQL/PostGIS provider
%1
PostGIS %2</source>
@@ -70378,52 +71052,52 @@ PostGIS %2</translation>
<context>
<name>QgsProject</name>
<message>
- <location filename="../src/core/qgsproject.cpp" line="635"/>
+ <location filename="../src/core/qgsproject.cpp" line="645"/>
<source>Loading layer %1</source>
<translation>Lade Layer %1</translation>
</message>
<message>
- <location filename="../src/core/qgsproject.cpp" line="746"/>
+ <location filename="../src/core/qgsproject.cpp" line="756"/>
<source>Unable to open %1</source>
<translation>Konnte %1 nicht öffnen</translation>
</message>
<message>
- <location filename="../src/core/qgsproject.cpp" line="759"/>
+ <location filename="../src/core/qgsproject.cpp" line="769"/>
<source>Project File Read Error</source>
<translation>Projektlesefehler</translation>
</message>
<message>
- <location filename="../src/core/qgsproject.cpp" line="760"/>
+ <location filename="../src/core/qgsproject.cpp" line="770"/>
<source>%1 at line %2 column %3</source>
<translation>%1 in Zeile %2, Spalte %3</translation>
</message>
<message>
- <location filename="../src/core/qgsproject.cpp" line="763"/>
+ <location filename="../src/core/qgsproject.cpp" line="773"/>
<source>Project file read error: %1 at line %2 column %3</source>
<translation>Projektdateifehler: %1 in Zeile %2, Spalte %3</translation>
</message>
<message>
- <location filename="../src/core/qgsproject.cpp" line="770"/>
+ <location filename="../src/core/qgsproject.cpp" line="780"/>
<source>%1 for file %2</source>
<translation>%1 in Datei %2</translation>
</message>
<message>
- <location filename="../src/core/qgsproject.cpp" line="1154"/>
+ <location filename="../src/core/qgsproject.cpp" line="1164"/>
<source>Unable to create backup file %1</source>
<translation>Kann Sicherung %1 nicht anlegen</translation>
</message>
<message>
- <location filename="../src/core/qgsproject.cpp" line="1168"/>
+ <location filename="../src/core/qgsproject.cpp" line="1178"/>
<source>Unable to save to file %1</source>
<translation>Konnte nicht in Datei %1 speichern</translation>
</message>
<message>
- <location filename="../src/core/qgsproject.cpp" line="1028"/>
+ <location filename="../src/core/qgsproject.cpp" line="1038"/>
<source>%1 is not writable. Please adjust permissions (if possible) and try again.</source>
<translation>%1 ist nicht beschreibbar. Bitte passen Sie die Zugriffsrechte (wenn möglich) und versuchen Sie es erneut.</translation>
</message>
<message>
- <location filename="../src/core/qgsproject.cpp" line="1198"/>
+ <location filename="../src/core/qgsproject.cpp" line="1208"/>
<source>Unable to save to file %1. Your project may be corrupted on disk. Try clearing some space on the volume and check file permissions before pressing save again.</source>
<translation>Konnte nicht in Datei %1 speichern. Das Projekt könnten auf der Festplatte defekt sein. Bitte machen sie etwas Platz auf der Festplatte frei und überprüfen Sie die Zugriffsrechte bevor Sie es erneut versuchen.</translation>
</message>
@@ -70521,13 +71195,13 @@ Choose ignore to continue loading without the missing layers. Choose cancel to r
<translation>Raster</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1028"/>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1371"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1031"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1375"/>
<source>Coordinate System Restriction</source>
<translation>Koordinatensystemeinschränkung</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1028"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1031"/>
<source>No coordinate systems selected. Disabling restriction.</source>
<translation>Kein Koordinatensystem gewählt. Einschränkung aufgehoben.</translation>
</message>
@@ -70754,197 +71428,197 @@ Choose ignore to continue loading without the missing layers. Choose cancel to r
<translation>Andere Einschränkungen</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1283"/>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1290"/>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1296"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1287"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1294"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1300"/>
<source>Map units (%1)</source>
<translation>Karteneinheiten (%1)</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1371"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1375"/>
<source>CRS %1 was already selected</source>
<translation>KBS %1 war bereits gewählt</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1391"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1395"/>
<source>Coordinate System Restrictions</source>
<translation>Koordinatensystemeinschränkung</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1392"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1396"/>
<source>The current selection of coordinate systems will be lost.
Proceed?</source>
<translation>Die aktuelle Koordinatensystemauswahl wird verloren gehen.
Fortfahren?</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1425"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1429"/>
<source>Select print composer</source>
<translation>Druckzusammenstellung wählen</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1425"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1429"/>
<source>Composer Title</source>
<translation>Titel der Druckzusammenstellung</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1447"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1451"/>
<source>Select restricted layers and groups</source>
<translation>Eingeschränkte Layer und Gruppen wählen</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1536"/>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1585"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1540"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1589"/>
<source>Start checking QGIS Server</source>
<translation>QGIS-Serverprüfung starten</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1546"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1550"/>
<source>Use short name for "%1"</source>
<translation>Kurzname für "%1" verwenden</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1555"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1559"/>
<source>Some layers and groups have the same name or short name</source>
<translation>Einige Layer und Gruppen haben den gleichen Namen oder Kurznamen</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1556"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1560"/>
<source>Duplicate names:</source>
<translation>Doppelte Namen:</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1562"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1566"/>
<source>All names and short names of layer and group are unique</source>
<translation>Alle Layer- und -kurznamen und Gruppen sind eindeutig</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1567"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1571"/>
<source>Some layer short names have to be updated:</source>
<translation>Einige Layerkurznamen wurden aktualisiert:</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1572"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1576"/>
<source>All layer short names are well formed</source>
<translation>Alle Layerkurznamen sind richtig</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1577"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1581"/>
<source>Some layer encodings are not set:</source>
<translation>Einige Layerkodierungen sind nicht gesetzt:</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1582"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1586"/>
<source>All layer encodings are set</source>
<translation>Alle Layerkodierungen sind gesetzt</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1592"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1596"/>
<source>Enter scale</source>
<translation>Maßstab eingeben</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1593"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1597"/>
<source>Scale denominator</source>
<translation>Maßstabsnenner</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1614"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1618"/>
<source>Load scales</source>
<translation>Maßstäbe laden</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1615"/>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1637"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1619"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1641"/>
<source>XML files (*.xml *.XML)</source>
<translation>XML-Dateien (*.xml *.XML)</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1636"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1640"/>
<source>Save scales</source>
<translation>Maßstäbe speichern</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1788"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1792"/>
<source>Select a valid symbol</source>
<translation>Ein gültiges Symbol wählen</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1794"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1798"/>
<source>Invalid symbol : </source>
<translation>Ungültiges Symbil : </translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1851"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1855"/>
<source>Update layer "%1" encoding</source>
<translation>Aktualisiere Kodierung des Layers "%1"</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1875"/>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1979"/>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1980"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1879"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1983"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1984"/>
<source>Parameters:</source>
<translation>Parameter:</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1979"/>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1980"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1983"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1984"/>
<source>Select %1 from pull-down menu to adjust radii</source>
<translation>%1 aus Menü wählen, um die Radien einzustellen</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="1991"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="1995"/>
<source>Can only use ellipsoidal calculations when CRS transformation is enabled</source>
<translation>Ellipsoide Berechnungen nur bei eingeschalteter KBS-Transformation möglich</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2025"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2029"/>
<source>Select Color</source>
<translation>Farbe wählen</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2039"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2043"/>
<source>Select palette file</source>
<translation>Palettendatei wählen</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2050"/>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2059"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2054"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2063"/>
<source>Invalid file</source>
<translation>Ungültige Datei</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2050"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2054"/>
<source>Error, file does not exist or is not readable</source>
<translation>Fehler, Datei nicht vorhanden oder nicht lesbar</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2059"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2063"/>
<source>Error, no colors found in palette file</source>
<translation>Fehler, keine Farben in der Palettendatei gefunden</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2068"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2072"/>
<source>Palette file</source>
<translation>Palettendatei</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2088"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2092"/>
<source>Error exporting</source>
<translation>Fehler beim Export</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2088"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2092"/>
<source>Error writing palette file</source>
<translation>Fehler beim Schreiben der Palettendatei</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2133"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2137"/>
<source>Invalid scale</source>
<translation>Ungültiger Maßstab</translation>
</message>
<message>
- <location filename="../src/app/qgsprojectproperties.cpp" line="2133"/>
+ <location filename="../src/app/qgsprojectproperties.cpp" line="2137"/>
<source>The text you entered is not a valid scale.</source>
<translation>Der eingegebene Text ist kein gültiger Maßstab</translation>
</message>
@@ -70957,709 +71631,714 @@ Fortfahren?</translation>
<translation>Projekteigenschaften</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="94"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="97"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="85"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="88"/>
<source>General</source>
<translation>Allgemein</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="273"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="246"/>
<source>General settings</source>
<translation>Allgemeine Einstellungen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="375"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="348"/>
<source>Project title</source>
<translation>Projekttitel</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="451"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="424"/>
<source>Descriptive project name</source>
<translation>Beschreibender Projektname</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="454"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="427"/>
<source>Default project title</source>
<translation>Projekttitelvorgabe</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="290"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="263"/>
<source>Selection color</source>
<translation>Auswahlfarbe</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="325"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="298"/>
<source>Background color</source>
<translation>Hintergrundfarbe</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="412"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="385"/>
<source>absolute</source>
<translation>Absolut</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="417"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="390"/>
<source>relative</source>
<translation>Relativ</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="431"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="404"/>
<source>Save paths</source>
<translation>Pfade speichern</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="514"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="487"/>
<source>Semi-minor</source>
<translation>Nebenachse</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="491"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="464"/>
<source>Semi-major</source>
<translation>Hauptachse</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="106"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="97"/>
<source>CRS</source>
<translation>KBS</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="109"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="100"/>
<source>Coordinate Reference System</source>
<translation>Koordinatenbezugssystem</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="118"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="109"/>
<source>Identify layers</source>
<translation>Layer abfragen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="130"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="133"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="121"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="124"/>
<source>Default styles</source>
<translation>Vorgabestile</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="142"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="133"/>
<source>OWS server</source>
<translation>OWS-Server</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="184"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="175"/>
<source>Variables</source>
<translation>Variablen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="441"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="414"/>
<source>Checking this setting avoids visible edge artifacts when rendering this project as separate map tiles. Rendering performance will be degraded.</source>
<translation>Anhaken diese Einstellung vermeidet sichtbare Kanteneffekte bei der Darstellung dieses Projektes in einzelnen Kartenkacheln. Die Darstellungsgeschwindigkeit wird davon beeinträchtigt.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="444"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="417"/>
<source>Avoid artifacts when project is rendered as map tiles (degrades performance)</source>
<translation>Artefakte bei der Darstellung von Kartenkacheln vermeiden (beeinträchtigt Geschwindigkeit)</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="480"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="453"/>
<source>Ellipsoid
(for distance calculations)</source>
<translation>Ellipsoid
(für Abstandsberechnungen)</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="549"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="522"/>
<source>Precision</source>
<translation>Genauigkeit</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="572"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="545"/>
<source>Automatic</source>
<translation>Automatisch</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1584"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1521"/>
<source>Position</source>
<translation>Position</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1614"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1551"/>
<source>Short name</source>
<translation>Kurzname</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2223"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2289"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2167"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2233"/>
<source>Deselect all</source>
<translation>Alle abwählen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2326"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2270"/>
<source>Test configuration</source>
<translation>Testkonfiguration</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2334"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2278"/>
<source>Launch</source>
<translation>Starten</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2483"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2409"/>
<source>When enabled, layers from the same database connection will be put into a transaction group. Their edit state will be synchronized and changes to these layers will be sent to the provider immediately. Only supported on postgres provider.</source>
<translation>Wenn aktiv werden Layer aus der gleichen Datenbankvebindung in eine Transaktionsgruppe gelegt. Ihre Bearbeitungszustand wird synchronisiert und Änderungen an diesen Layer werden direkt zur Datenanbieter geschickt. Nur mit dem PostgreSQL-Anbieter unterstützt.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2486"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2412"/>
<source>Automatically create transaction groups where possible</source>
<translation>Wenn möglich automatisch Transaktionsgruppen erstellen </translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2493"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2419"/>
<source>When enabled, default values will be evaluated as early as possible. This will fill default values in the add feature form already and not only create them on commit. Only supported for postgres provider.</source>
<translation>Wenn aktiv werden Vorgabewerte so früh wie möglich ausgewertet. Die füllt die Vorgabewert direkt im Objektformular aus und nicht erst beim Festschreiben. Nur mit dem PostgreSQL-Anbieter unterstützt.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2496"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2422"/>
<source>Evaluate default values on provider side</source>
<translation>Vorgabewerte auf Anbieterseite auswerten</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2507"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2433"/>
<source>Expression Variables</source>
<translation>Ausdrucksvariablen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="585"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="558"/>
<source>Manual</source>
<translation>Manuell</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="592"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="565"/>
<source>The number of decimal places for the manual option</source>
<translation>Setzt die Anzahl Dezimalstellen für die manuelle Option</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="605"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="578"/>
<source>decimal places</source>
<translation>Dezimalstellen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="624"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="597"/>
<source>Project scales</source>
<translation>Projektmaßstäbe</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="644"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="655"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="666"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="677"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="914"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="967"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1056"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1103"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="617"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="628"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="639"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="650"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="860"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="913"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1002"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1049"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="121"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="112"/>
<source>Identifiable layers</source>
<translation>Abfragbare Layer</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="828"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="783"/>
<source>Project layers</source>
<translation>Projektlayer</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="838"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2190"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2276"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="793"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2134"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2220"/>
<source>Layer</source>
<translation>Layer</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="843"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="798"/>
<source>Type</source>
<translation>Typ</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="848"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="803"/>
<source>Identifiable</source>
<translation>Abfragbar</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1046"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="992"/>
<source>Marker</source>
<translation>Markierung</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="925"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="871"/>
<source>Line</source>
<translation>Linie</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="902"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="848"/>
<source>Default symbols</source>
<translation>Vorlagesymbole</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1067"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1013"/>
<source>Fill</source>
<translation>Füllung</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1007"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="953"/>
<source>Color Ramp</source>
<translation>Farbverlauf</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1128"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1074"/>
<source>Transparency</source>
<translation>Transparenz</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1163"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1109"/>
<source> %</source>
<translation> %</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1200"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1146"/>
<source>Style Manager</source>
<translation>Stilverwaltung</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1117"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1063"/>
<source>Options</source>
<translation>Optionen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="166"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="157"/>
<source>Relations</source>
<translation>Beziehungen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="388"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="361"/>
<source>Project file</source>
<translation>Projektdatei</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1188"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1134"/>
<source>Assign random colors to symbols</source>
<translation>Den Symbolen zufällige Farben zuordnen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1222"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1168"/>
<source>Project colors</source>
<translation>Projektfarben</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1228"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1174"/>
<source>Copy colors</source>
<translation>Farben kopieren</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1255"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1201"/>
<source>Add color</source>
<translation>Farbe hinzufügen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1269"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1215"/>
<source>Paste colors</source>
<translation>Farben einfügen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1283"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1229"/>
<source>Remove color</source>
<translation>Farbe entfernen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1375"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1312"/>
<source>Service capabilities</source>
<translation>Diensteigenschaften</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1406"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1409"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1343"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1346"/>
<source>The web site URL of the service provider.</source>
<translation>Die Website-URL des Dienstanbieters.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1423"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1360"/>
<source>Person</source>
<translation>Person</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1396"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1333"/>
<source>Title</source>
<translation>Titel</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1540"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1477"/>
<source>Organization</source>
<translation>Organisation</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1416"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1353"/>
<source>Online resource</source>
<translation>Online-Quelle</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1453"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1390"/>
<source>E-Mail</source>
<translation>E-Mail</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1470"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1407"/>
<source>Phone</source>
<translation>Telefon</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1490"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1427"/>
<source>Abstract</source>
<translation>Zusammenfassung</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1557"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1494"/>
<source>Fees</source>
<translation>Gebühren</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1550"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1487"/>
<source>Access constraints</source>
<translation>Zugriffsbeschränkungen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1523"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1460"/>
<source>Keyword list</source>
<translation>Schlüsselwortliste</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1624"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1561"/>
<source>WMS capabilities</source>
<translation>WMS-Capabilities</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1941"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1878"/>
<source>Add geometry to feature response</source>
<translation>Geometrie der Objektantwort beifügen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1651"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1588"/>
<source>Min. X</source>
<translation>Min. X</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1668"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1605"/>
<source>Min. Y</source>
<translation>Min. Y</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1685"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1622"/>
<source>Max. X</source>
<translation>Max. X</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1702"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1639"/>
<source>Max. Y</source>
<translation>Max. Y</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1719"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1656"/>
<source>Use Current Canvas Extent</source>
<translation>Aktuelle Anzeigegrenzen übernehmen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1889"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1826"/>
<source>Used</source>
<translation>Benutzte</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1742"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1679"/>
<source>Exclude composers</source>
<translation>Druckzusammenstellungen ausschließen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2260"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2204"/>
<source>WCS capabilities</source>
<translation>WCS-Capabilities</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1801"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1738"/>
<source>Exclude layers</source>
<translation>Layer ausschließen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1916"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1853"/>
<source>Quality for JPEG images ( 10 : smaller image - 100 : best quality )</source>
<translation>Qualität für JPEG-Bilder ( 10 : kleineres Bilder - 100 : beste Qualität )</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1907"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1844"/>
<source>Use layer ids as names</source>
<translation>Layer-IDs als Namen verwenden</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="145"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="136"/>
<source>WMS/WFS Server Configuration</source>
<translation>WMS/WFS-Serverkonfiguration</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="175"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="166"/>
<source>Data Sources</source>
<translation>Datenquellen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="471"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="444"/>
<source>Measurements</source>
<translation>Messungen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="498"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="471"/>
<source>Units for distance measurement</source>
<translation>Einheit für Abstandsmessung</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="521"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="494"/>
<source>Units for area measurement</source>
<translation>Einheiten für Flächenmessung</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="540"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="513"/>
<source>Coordinate display</source>
<translation>Koordinatenanzeige</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="556"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="529"/>
<source>Display coordinates using</source>
<translation>Koordinatenanzeige in</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="569"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="542"/>
<source>Automatically sets the number of decimal places to use when displaying coordinates</source>
<translation>Setzt die Anzahl von Nachkommastellen für die Koordinatenanzeige automatisch</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="582"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="555"/>
<source>Manually set the number of decimal places to use when displaying coordinates</source>
<translation>Setzt die Anzahl von Nachkommastellen zur Koordinatenanzeige manuell</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="763"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="727"/>
<source>Enable 'on the fly' CRS transformation (OTF)</source>
<translation>Spontanreprojektion aktivieren (SRP)</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="853"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="808"/>
<source>Read Only</source>
<translation>Schreibgeschützt</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1300"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1246"/>
<source>Import colors</source>
<translation>Farben importieren</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1314"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1260"/>
<source>Export colors</source>
<translation>Farben exportieren</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1433"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1436"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1370"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1373"/>
<source>The contact person e-mail for the service.</source>
<translation>Die E-Mail-Adresses der Kontaktperson des Dienstes.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1443"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1446"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1380"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1383"/>
<source>The contact person name for the service.</source>
<translation>Der Name der Kontaktperson des Dienstes.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1460"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1463"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1397"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1400"/>
<source>The name of the service provider.</source>
<translation>Der Name des Dienstanbieters.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1480"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1483"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1417"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1420"/>
<source>The title should be brief yet descriptive enough to identify this service.</source>
<translation>Der Titel sollte den Dienst kurz aber prägnant identifizieren.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1500"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1503"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1437"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1440"/>
<source>The contact person phone for the service.</source>
<translation>Die Telefonnummer der Kontaktperson des Dienstes.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1510"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1447"/>
<source>The abstract is a descriptive narrative providing more information about the service.</source>
<translation>Die Zusammenfassung ist ein beschreibender Text, der mehr Informationen zum Dienst bietet.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1530"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1533"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1467"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1470"/>
<source>List of keywords separated by comma to help catalog searching.</source>
<translation>Liste der durch Komma getrennten Schlüsselworte zur Katalogsuche.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1564"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1501"/>
<source>Fees applied to the service.</source>
<translation>Gebühren des Dienstes.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1574"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1511"/>
<source>Access constraints applied to the service.</source>
<translation>Zugriffsbeschränkungen des Dienstes.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1591"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1528"/>
<source>The contact person position for the service.</source>
<translation>Die Position der Kontaktperson des Dienstes.</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1604"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1607"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1541"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1544"/>
<source>A name used to identify the root layer. The short name is a text string used for machine-to-machine communication.</source>
<translation>Name zur Identifikation des Wurzellayers. Der Kurzname ist eine Zeichenkette, die für die Kommunikation zwischen Maschinen verwendet wird</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1997"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1934"/>
<source>GetFeatureInfo geometry precision (decimal places)</source>
<translation>GetFeatureInfo-Geometriegenauigkeit (Dezimalstellen)</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2033"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1970"/>
<source>INSPIRE (European directive)</source>
<translation>INSPIRE (Europäische Richtlinie)</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2055"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1992"/>
<source>Service language</source>
<translation>Dienstsprache</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2062"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1999"/>
<source>Scenario 2 - INSPIRE related fields using embedded service metadata:</source>
<translation>Szenario 2 - INSPIRE bezogene Felder verwenden eingebettete Dienstmetadaten:</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2084"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2021"/>
<source>Metadata date</source>
<translation>Metadaten-Datum</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2101"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2038"/>
<source>Last revision date</source>
<translation>Letztes Bearbeitungsdatum:</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2111"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2048"/>
<source>Scenario 1 - INSPIRE related fields using referenced external service metadata</source>
<translation>Szenario 1 - INSPIRE bezogenen Felder beziehen sich auf externen Dienstmetadaten</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2126"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2063"/>
<source>Metadata URL</source>
<translation>Metadaten-URL</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2134"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2071"/>
<source>application/vnd.iso.19139+xml</source>
<translation>application/vnd.iso.19139+xml</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2139"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2076"/>
<source>application/vnd.ogc.csw.GetRecordByIdResponse_xml</source>
<translation>application/vnd.ogc.csw.GetRecordByIdResponse_xml</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2144"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2081"/>
<source>application/vnd.ogc.csw_xml</source>
<translation>application/vnd.ogc.csw_xml</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2152"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2089"/>
<source>URL mime/type</source>
<translation>URL mime/type</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2174"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2102"/>
+ <source>Segmentize feature info geometry</source>
+ <translation>Objektinformationsgeometrie segmentieren</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2118"/>
<source>WFS capabilities (also influences DXF export)</source>
<translation>WFS-Eigenschaften (beeinflußt auch DXF-Ausgabe)</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2195"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2281"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2139"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2225"/>
<source>Published</source>
<translation>Veröffentlich</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2200"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2144"/>
<source>Geometry precision (decimal places)</source>
<translation>Geometriegenauigkeit (Dezimalstellen)</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2205"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2149"/>
<source>Update</source>
<translation>Aktualisieren</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2210"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2154"/>
<source>Insert</source>
<translation>Einfügen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2215"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2159"/>
<source>Delete</source>
<translation>Löschen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2230"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2296"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2174"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2240"/>
<source>Select all</source>
<translation>Alle wählen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="154"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="157"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="145"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="148"/>
<source>Macros</source>
<translation>Makros</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2021"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2239"/>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2305"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1958"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2183"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2249"/>
<source>Advertised URL</source>
<translation>Angezeigte URL</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1950"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1887"/>
<source>Width</source>
<translation>Breite</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1979"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1916"/>
<source>Height</source>
<translation>Höhe</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1986"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1923"/>
<source>Maximums for GetMap request</source>
<translation>Maxima für GetMap-Abfragen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1633"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1570"/>
<source>Advertised extent</source>
<translation>Angezeigte Ausmasse</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1860"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="1797"/>
<source>CRS restrictions</source>
<translation>KBS-Beschränkungen</translation>
</message>
<message>
- <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2441"/>
+ <location filename="../src/ui/qgsprojectpropertiesbase.ui" line="2376"/>
<source>Python macros</source>
<translation>Python-Makros</translation>
</message>
@@ -72336,27 +73015,27 @@ p, li { white-space: pre-wrap; }
<context>
<name>QgsRasterDataProvider</name>
<message>
- <location filename="../src/core/raster/qgsrasterdataprovider.cpp" line="287"/>
+ <location filename="../src/core/raster/qgsrasterdataprovider.cpp" line="292"/>
<source>Format not supported</source>
<translation>Format nicht unterstützt</translation>
</message>
<message>
- <location filename="../src/core/raster/qgsrasterdataprovider.cpp" line="471"/>
+ <location filename="../src/core/raster/qgsrasterdataprovider.cpp" line="476"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../src/core/raster/qgsrasterdataprovider.cpp" line="473"/>
+ <location filename="../src/core/raster/qgsrasterdataprovider.cpp" line="478"/>
<source>Text</source>
<translation>Text</translation>
</message>
<message>
- <location filename="../src/core/raster/qgsrasterdataprovider.cpp" line="475"/>
+ <location filename="../src/core/raster/qgsrasterdataprovider.cpp" line="480"/>
<source>Html</source>
<translation>Html</translation>
</message>
<message>
- <location filename="../src/core/raster/qgsrasterdataprovider.cpp" line="477"/>
+ <location filename="../src/core/raster/qgsrasterdataprovider.cpp" line="482"/>
<source>Feature</source>
<translation>Objekt</translation>
</message>
@@ -72364,7 +73043,7 @@ p, li { white-space: pre-wrap; }
<context>
<name>QgsRasterFillSymbolLayerWidget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="3059"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="3072"/>
<source>Select image file</source>
<translation>Bilddatei wählen</translation>
</message>
@@ -72733,7 +73412,7 @@ Auf Hilfeknopf klicken um die gültigen Erzeugungsoptionen diese Formats zu erfa
<translation>Datenquellen entfernen</translation>
</message>
<message>
- <location filename="../src/core/raster/qgsrasterinterface.h" line="102"/>
+ <location filename="../src/core/raster/qgsrasterinterface.h" line="143"/>
<source>Band</source>
<translation>Kanal</translation>
</message>
@@ -72753,7 +73432,7 @@ Auf Hilfeknopf klicken um die gültigen Erzeugungsoptionen diese Formats zu erfa
<translation>QgsRasterLayer erzeugt</translation>
</message>
<message>
- <location filename="../src/core/raster/qgsrasterlayer.cpp" line="1513"/>
+ <location filename="../src/core/raster/qgsrasterlayer.cpp" line="1515"/>
<source>Raster</source>
<translation>Raster</translation>
</message>
@@ -72928,7 +73607,7 @@ Auf Hilfeknopf klicken um die gültigen Erzeugungsoptionen diese Formats zu erfa
<translation>Datenanbieter ist ungültig (Anbieter %1, URI: %2</translation>
</message>
<message>
- <location filename="../src/core/raster/qgsrasterlayer.cpp" line="1513"/>
+ <location filename="../src/core/raster/qgsrasterlayer.cpp" line="1515"/>
<source><maplayer> not found.</source>
<translation><maplayer> nicht gefunden.</translation>
</message>
@@ -74109,12 +74788,12 @@ standard deviation ×</source>
<context>
<name>QgsRasterProjector</name>
<message>
- <location filename="../src/core/raster/qgsrasterprojector.cpp" line="871"/>
+ <location filename="../src/core/raster/qgsrasterprojector.cpp" line="827"/>
<source>Approximate</source>
<translation>Annähern</translation>
</message>
<message>
- <location filename="../src/core/raster/qgsrasterprojector.cpp" line="873"/>
+ <location filename="../src/core/raster/qgsrasterprojector.cpp" line="829"/>
<source>Exact</source>
<translation>Genau</translation>
</message>
@@ -74556,7 +75235,7 @@ standard deviation ×</source>
</message>
<message>
<location filename="../src/ui/raster/qgsrastertransparencywidget.ui" line="111"/>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="79"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="82"/>
<source>None</source>
<translation>Keine</translation>
</message>
@@ -74626,64 +75305,64 @@ standard deviation ×</source>
<translation>Nicht gesetzt</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="115"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="118"/>
<source>not defined</source>
<translation>undefiniert</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="238"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="241"/>
<source>Save file</source>
<translation>Datei speichern</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="238"/>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="288"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="241"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="291"/>
<source>Textfile</source>
<translation>Textdatei</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="250"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="253"/>
<source>QGIS Generated Transparent Pixel Value Export File</source>
<translation>QGIS-erzeugte Export-Datei für transparente Pixelwerte</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="253"/>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="560"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="256"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="563"/>
<source>Red</source>
<translation>Rot</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="253"/>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="561"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="256"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="564"/>
<source>Green</source>
<translation>Grün</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="253"/>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="562"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="256"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="565"/>
<source>Blue</source>
<translation>Blau</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="253"/>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="264"/>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="563"/>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="584"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="256"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="267"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="566"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="587"/>
<source>Percent Transparent</source>
<translation>Prozent Transparenz</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="264"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="267"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="276"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="279"/>
<source>Write access denied</source>
<translation>Schreibzugriff verweigert</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="276"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="279"/>
<source>Write access denied. Adjust the file permissions and try again.
</source>
@@ -74691,17 +75370,17 @@ standard deviation ×</source>
</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="288"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="291"/>
<source>Open file</source>
<translation>Datei öffnen</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="367"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="370"/>
<source>Import Error</source>
<translation>Importfehler</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="367"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="370"/>
<source>The following lines contained errors
%1</source>
@@ -74710,12 +75389,12 @@ standard deviation ×</source>
%1</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="372"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="375"/>
<source>Read access denied</source>
<translation>Lesezugriff verweigert</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="372"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="375"/>
<source>Read access denied. Adjust the file permissions and try again.
</source>
@@ -74723,22 +75402,22 @@ standard deviation ×</source>
</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="575"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="578"/>
<source>Gray</source>
<translation>Grau</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="579"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="582"/>
<source>Indexed Value</source>
<translation>Indizierter Wert</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="582"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="585"/>
<source>From</source>
<translation>Von</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="583"/>
+ <location filename="../src/gui/raster/qgsrastertransparencywidget.cpp" line="586"/>
<source>To</source>
<translation>Nach</translation>
</message>
@@ -74881,70 +75560,70 @@ standard deviation ×</source>
<context>
<name>QgsRelationEditorWidget</name>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="49"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="50"/>
<source>Toggle editing</source>
<translation>Bearbeitungsstatus umschalten</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="52"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="53"/>
<source>Toggle editing mode for child layer</source>
<translation>Bearbeitungsmodus der Kindlayer umschalten</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="57"/>
<location filename="../src/gui/qgsrelationeditorwidget.cpp" line="58"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="59"/>
<source>Save child layer edits</source>
<translation>Kindlayeränderungen speichern</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="64"/>
<location filename="../src/gui/qgsrelationeditorwidget.cpp" line="65"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="66"/>
<source>Add child feature</source>
<translation>Kindobjekt hinzufügen</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="71"/>
<location filename="../src/gui/qgsrelationeditorwidget.cpp" line="72"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="73"/>
<source>Delete child feature</source>
<translation>Kindobjekt löschen</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="78"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="79"/>
<source>Link existing features</source>
<translation>Vorhandene Objekte verknüpfen</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="79"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="80"/>
<source>Link existing child features</source>
<translation>Vorhandene Kindobjekte verknüpfen</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="85"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="86"/>
<source>Unlink feature</source>
<translation>Objektverknüpfung lösen</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="86"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="87"/>
<source>Unlink child feature</source>
<translation>Kindobjektverknüpfung lösen</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="93"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="94"/>
<source>Form view</source>
<translation>Formularansicht</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="94"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="95"/>
<source>Switch to form view</source>
<translation>Auf Formularansicht umschalten</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="101"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="102"/>
<source>Table view</source>
<translation>Tabellenansicht</translation>
</message>
<message>
- <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="102"/>
+ <location filename="../src/gui/qgsrelationeditorwidget.cpp" line="103"/>
<source>Switch to table view</source>
<translation>Auf Tabellenansicht umschalten</translation>
</message>
@@ -75053,12 +75732,12 @@ standard deviation ×</source>
<translation>%1 (keine Auswahl)</translation>
</message>
<message>
- <location filename="../src/gui/editorwidgets/qgsrelationreferencewidget.cpp" line="692"/>
+ <location filename="../src/gui/editorwidgets/qgsrelationreferencewidget.cpp" line="689"/>
<source>Relation %1 for %2.</source>
- <translation>Beziehung %1 für %2</translation>
+ <translation>Beziehung %1 für %2.</translation>
</message>
<message>
- <location filename="../src/gui/editorwidgets/qgsrelationreferencewidget.cpp" line="693"/>
+ <location filename="../src/gui/editorwidgets/qgsrelationreferencewidget.cpp" line="690"/>
<source>Identify a feature of %1 to be associated. Press <ESC> to cancel.</source>
<translation>Zuzuordnendes Obekt auf %1 wählen. <ESC> bricht ab. </translation>
</message>
@@ -75081,24 +75760,24 @@ standard deviation ×</source>
</message>
<message>
<location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="62"/>
- <location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="157"/>
+ <location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="158"/>
<source>Bilinear</source>
<translation>Bilinear</translation>
</message>
<message>
<location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="63"/>
- <location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="161"/>
+ <location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="162"/>
<source>Cubic</source>
<translation>Kubisch</translation>
</message>
<message>
<location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="65"/>
- <location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="171"/>
+ <location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="172"/>
<source>Average</source>
<translation>Mittel</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="218"/>
+ <location filename="../src/gui/raster/qgsrendererrasterpropertieswidget.cpp" line="219"/>
<source>Select color</source>
<translation>Farbe wählen</translation>
</message>
@@ -75241,7 +75920,7 @@ standard deviation ×</source>
</message>
<message>
<location filename="../src/ui/qgsrendererrulepropsdialogbase.ui" line="35"/>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="780"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="785"/>
<source>Filter</source>
<translation>Filter</translation>
</message>
@@ -75271,24 +75950,24 @@ standard deviation ×</source>
<translation>Symbol</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="736"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="742"/>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="736"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="742"/>
<source>Filter expression parsing error:
</source>
<translation>Filterausdrucksfehler:
</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="757"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="763"/>
<source>Evaluation error</source>
<translation>Auswertungsfehler</translation>
</message>
<message numerus="yes">
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="780"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="785"/>
<source>Filter returned %n feature(s)</source>
<comment>number of filtered features</comment>
<translation>
@@ -75541,52 +76220,52 @@ standard deviation ×</source>
<context>
<name>QgsRuleBasedRendererV2Model</name>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="862"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="867"/>
<source>(no filter)</source>
<translation>(kein Filter)</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="889"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="894"/>
<source><li><nobr>%1 features also in rule %2</nobr></li></source>
<translation><li><nobr>%1 Objekte auch in Regel %2</nobr></li></translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="954"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="959"/>
<source>Label</source>
<translation>Beschriftung</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="954"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="959"/>
<source>Rule</source>
<translation>Regel</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="954"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="959"/>
<source>Min. scale</source>
<translation>Min. Maßstab</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="954"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="959"/>
<source>Count</source>
<translation>Anzahl</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="954"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="959"/>
<source>Duplicate count</source>
<translation>Doppelte</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="954"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="959"/>
<source>Max. scale</source>
<translation>Max. Maßstab</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="961"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="966"/>
<source>Number of features in this rule.</source>
<translation>Anzahl der Objekte in dieser Regel.</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="965"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="970"/>
<source>Number of features in this rule which are also present in other rule(s).</source>
<translation>Anzahl von Objekten in dieser Regel, die auch in anderen Regeln vorkommen.</translation>
</message>
@@ -75659,43 +76338,43 @@ standard deviation ×</source>
<translation>Alle Kategorien in Regeln</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="269"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="268"/>
<source>Add ranges to rules</source>
<translation>Alle Bereiche zu Regeln</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="285"/>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="291"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="283"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="289"/>
<source>Scale refinement</source>
<translation>Eine Regel für Maßstäbe präzisieren</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="285"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="283"/>
<source>Parent rule %1 must have a symbol for this operation.</source>
<translation>Für diese Operation muß die Elterregel %1 ein Symbol haben.</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="292"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="290"/>
<source>Please enter scale denominators at which will split the rule, separate them by commas (e.g. 1000,5000):</source>
<translation>Bitte geben Sie einen Maßstabsnenner an bei dem die Regel aufgeteilt werden soll. Trennen Sie sie durch Kommata (z.B. 1000,5000):</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="304"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="302"/>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="304"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="302"/>
<source>"%1" is not valid scale denominator, ignoring it.</source>
<translation>"%1" wird als ungültiger Nenner ignoriert.</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="542"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="546"/>
<source>Calculating feature count.</source>
<translation>Objektanzahl wird berechnet.</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="542"/>
+ <location filename="../src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp" line="546"/>
<source>Abort</source>
<translation>Abbrechen</translation>
</message>
@@ -75870,7 +76549,7 @@ standard deviation ×</source>
<message>
<location filename="../src/gui/qgssqlcomposerdialog.cpp" line="217"/>
<source>An error occurred during evaluation of the SQL statement</source>
- <translation>Ein Fehler trat bei der Auswertung der SQL-Anweisung auf.</translation>
+ <translation>Ein Fehler trat bei der Auswertung der SQL-Anweisung auf</translation>
</message>
<message>
<location filename="../src/gui/qgssqlcomposerdialog.cpp" line="218"/>
@@ -76007,7 +76686,7 @@ und nur die Geometriespalte des Haupttypname kann als die Geometriespalte des Er
<message>
<location filename="../src/core/qgssqlstatement.cpp" line="240"/>
<source>Table %1 is referenced by column %2, but not selected in FROM / JOIN.</source>
- <translation>Spalte %2 bezieht sich auf Tabelle %1, die aber nicht in FROM / JOIN gewählt wird</translation>
+ <translation>Spalte %2 bezieht sich auf Tabelle %1, die aber nicht in FROM / JOIN gewählt wird.</translation>
</message>
<message>
<location filename="../src/core/qgssqlstatement.cpp" line="461"/>
@@ -76018,27 +76697,27 @@ und nur die Geometriespalte des Haupttypname kann als die Geometriespalte des Er
<context>
<name>QgsSVGFillSymbolLayerWidget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2236"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2243"/>
<source>SVG file</source>
<translation>SVG-Datei</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2169"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2176"/>
<source>Select fill color</source>
<translation>Füllfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2171"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2178"/>
<source>Select border color</source>
<translation>Randfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2236"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2243"/>
<source>Select SVG texture file</source>
<translation>SVG-Texturdatei wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2236"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2243"/>
<source>All files</source>
<translation>Alle Dateien</translation>
</message>
@@ -76388,19 +77067,19 @@ und nur die Geometriespalte des Haupttypname kann als die Geometriespalte des Er
<context>
<name>QgsShapeburstFillSymbolLayerV2Widget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1372"/>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1377"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1373"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1378"/>
<source>Select gradient color</source>
<translation>Gradientenfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1375"/>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1380"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1376"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1381"/>
<source>Transparent</source>
<translation>Transparent</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1487"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1488"/>
<source>Integer between 0 and 18</source>
<translation>Ganze Zahl zwischen 0 und 18</translation>
</message>
@@ -76408,22 +77087,22 @@ und nur die Geometriespalte des Haupttypname kann als die Geometriespalte des Er
<context>
<name>QgsSimpleFillSymbolLayerV2Widget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="705"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="706"/>
<source>Select fill color</source>
<translation>Füllfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="708"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="709"/>
<source>Transparent fill</source>
<translation>Transparente Füllung</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="710"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="711"/>
<source>Select border color</source>
<translation>Randfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="713"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="714"/>
<source>Transparent border</source>
<translation>Transparenter Rand</translation>
</message>
@@ -76431,12 +77110,12 @@ und nur die Geometriespalte des Haupttypname kann als die Geometriespalte des Er
<context>
<name>QgsSimpleLineSymbolLayerV2Widget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="180"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="181"/>
<source>Select line color</source>
<translation>Lienienfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="195"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="196"/>
<source>Width Assistant...</source>
<translation>Breitenassistent...</translation>
</message>
@@ -76444,32 +77123,32 @@ und nur die Geometriespalte des Haupttypname kann als die Geometriespalte des Er
<context>
<name>QgsSimpleMarkerSymbolLayerV2Widget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="425"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="426"/>
<source>Select fill color</source>
<translation>Füllfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="428"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="429"/>
<source>Transparent fill</source>
<translation>Transparente Füllung</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="430"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="431"/>
<source>Select border color</source>
<translation>Randfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="433"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="434"/>
<source>Transparent border</source>
<translation>Transparenter Rand</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="442"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="443"/>
<source>Size Assistant...</source>
<translation>Größenassistent...</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="544"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="545"/>
<source>string </source>
<translation>Zeichenkette </translation>
</message>
@@ -76575,33 +77254,33 @@ verbesserung</translation>
<translation>Quantile</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="596"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="605"/>
<source>Load Color Map</source>
<translation>QGIS-Farbabbildung laden</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="596"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="605"/>
<source>The color map for band %1 has no entries</source>
<translation>Die Farbabbildung für den Kanal %1 hat keine Einträge</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="608"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="617"/>
<source>Open file</source>
<translation>Datei öffnen</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="608"/>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="695"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="617"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="704"/>
<source>Textfile (*.txt)</source>
<translation>Textdatei (*.txt)</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="681"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="690"/>
<source>Import Error</source>
<translation>Importfehler</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="681"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="690"/>
<source>The following lines contained errors
</source>
@@ -76609,12 +77288,12 @@ verbesserung</translation>
</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="686"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="695"/>
<source>Read access denied</source>
<translation>Lesezugriff verweigert</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="686"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="695"/>
<source>Read access denied. Adjust the file permissions and try again.
</source>
@@ -76622,22 +77301,22 @@ verbesserung</translation>
</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="695"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="704"/>
<source>Save file</source>
<translation>Datei speichern</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="707"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="716"/>
<source>QGIS Generated Color Map Export File</source>
<translation>QGIS-Farbabbildungsexportdatei</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="753"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="762"/>
<source>Write access denied</source>
<translation>Schreibzugriff verweigert</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="753"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="762"/>
<source>Write access denied. Adjust the file permissions and try again.
</source>
@@ -76645,32 +77324,32 @@ verbesserung</translation>
</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="860"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="869"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="861"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="870"/>
<source>Value for color stop</source>
<translation>Wert für Farbstopp</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="864"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="873"/>
<source>Value <=</source>
<translation>Wert <=</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="865"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="874"/>
<source>Maximum value for class</source>
<translation>Maximalwert für Klasse</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="868"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="877"/>
<source>Value =</source>
<translation>Wert =</translation>
</message>
<message>
- <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="869"/>
+ <location filename="../src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp" line="878"/>
<source>Value for color</source>
<translation>Wert für Farbe</translation>
</message>
@@ -76790,7 +77469,7 @@ einheitssuffix</translation>
<message>
<location filename="../src/ui/qgssinglebandpseudocolorrendererwidgetbase.ui" line="209"/>
<source>If checked, any pixels with a value out of range will not be rendered</source>
- <translation>Wenn angehakt werden Pixel außerhalb des Bereichs nicht dargestellt.</translation>
+ <translation>Wenn angehakt werden Pixel außerhalb des Bereichs nicht dargestellt</translation>
</message>
<message>
<location filename="../src/ui/qgssinglebandpseudocolorrendererwidgetbase.ui" line="111"/>
@@ -77526,8 +78205,7 @@ aber führt danach zu größerer Geschwindigkeit.</translation>
<location filename="../src/providers/spatialite/qgsspatialitesourceselect.cpp" line="300"/>
<source>A connection with the same name already exists,
please provide a new name:</source>
- <translation>Eine Verbindung mit dem gleichen Namen ist bereits vorhanden,
-bitte einen neuen Namen angeben:</translation>
+ <translation>Eine Verbindung mit gleichem Namen ist bereits vorhanden. Bitte einen neuen Namen angeben:</translation>
</message>
<message>
<location filename="../src/providers/spatialite/qgsspatialitesourceselect.cpp" line="366"/>
@@ -77593,7 +78271,7 @@ bitte einen neuen Namen angeben:</translation>
<source>Failure getting table metadata ... is this really a SpatialLite database? %1
%2</source>
- <translation>Fehler bei der Metadatentabelleabfrage ... ist dies wirklich eine SpatiaLite-Datenbank? %1
+ <translation>Konnte Metadaten nicht bestimmen ... ist dies wirklich eine SpatiaLite-Datenbank? %1
%2</translation>
</message>
@@ -78917,6 +79595,112 @@ Es gab ein Problem mit Ihrer Symboldatenbank.</translation>
</message>
</context>
<context>
+ <name>QgsSubstitutionListDialog</name>
+ <message>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="211"/>
+ <source>Substitutions</source>
+ <translation>Ersetzungen</translation>
+ </message>
+</context>
+<context>
+ <name>QgsSubstitutionListWidget</name>
+ <message>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="89"/>
+ <source>Save substitutions</source>
+ <translation>Ersetzungen speichern</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="90"/>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="126"/>
+ <source>XML files (*.xml *.XML)</source>
+ <translation>XML-Dateien (*.xml *.XML)</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="112"/>
+ <source>Export substitutions</source>
+ <translation>Ersetzungen exportieren</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="113"/>
+ <source>Cannot write file %1:
+%2.</source>
+ <translation>Datei %1 kann nicht geschrieben werden:
+%2.</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="125"/>
+ <source>Load substitutions</source>
+ <translation>Ersetzungen laden</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="135"/>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="149"/>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="162"/>
+ <source>Import substitutions</source>
+ <translation>Ersetzungen importieren</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="136"/>
+ <source>Cannot read file %1:
+%2.</source>
+ <translation>Datei %1 kann nicht gelesen werden:
+%2.</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="150"/>
+ <source>Parse error at line %1, column %2:
+%3</source>
+ <translation>Fehler in Zeile %1, Spalte %2:
+%3</translation>
+ </message>
+ <message>
+ <location filename="../src/app/qgssubstitutionlistwidget.cpp" line="163"/>
+ <source>The selected file in not an substitutions list.</source>
+ <translation>Die gewählte Datei ist keine Ersetzungsliste.</translation>
+ </message>
+</context>
+<context>
+ <name>QgsSubstitutionListWidgetBase</name>
+ <message>
+ <location filename="../src/ui/qgssubstitutionlistwidgetbase.ui" line="14"/>
+ <source>Form</source>
+ <translation>Formular</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgssubstitutionlistwidgetbase.ui" line="36"/>
+ <source>Text</source>
+ <translation>Text</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgssubstitutionlistwidgetbase.ui" line="41"/>
+ <source>Substitution</source>
+ <translation>Ersetzung</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgssubstitutionlistwidgetbase.ui" line="46"/>
+ <source>Case Sensitive</source>
+ <translation>Groß-/Kleinschreibung beachten</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgssubstitutionlistwidgetbase.ui" line="51"/>
+ <source>Whole Word</source>
+ <translation>Ganzes Wort</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgssubstitutionlistwidgetbase.ui" line="54"/>
+ <source>If checked, only whole word matches are replaced</source>
+ <translation>Wenn aktiv werden nur ganze Worte ersetzt</translation>
+ </message>
+ <message>
+ <location filename="../src/ui/qgssubstitutionlistwidgetbase.ui" line="64"/>
+ <location filename="../src/ui/qgssubstitutionlistwidgetbase.ui" line="75"/>
+ <location filename="../src/ui/qgssubstitutionlistwidgetbase.ui" line="86"/>
+ <location filename="../src/ui/qgssubstitutionlistwidgetbase.ui" line="97"/>
+ <source>...</source>
+ <translation>...</translation>
+ </message>
+</context>
+<context>
<name>QgsSvgAnnotationDialog</name>
<message>
<location filename="../src/app/qgssvgannotationdialog.cpp" line="29"/>
@@ -79019,27 +79803,27 @@ Es gab ein Problem mit Ihrer Symboldatenbank.</translation>
<context>
<name>QgsSvgMarkerSymbolLayerV2Widget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1786"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1787"/>
<source>Select fill color</source>
<translation>Füllfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1789"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1790"/>
<source>Select border color</source>
<translation>Randfarbe wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1808"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="1809"/>
<source>Size Assistant...</source>
<translation>Größenassistent...</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2034"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2041"/>
<source>Select SVG file</source>
<translation>SVG-Datei wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2036"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="2043"/>
<source>SVG files</source>
<translation>SVG-Dateien</translation>
</message>
@@ -79047,12 +79831,12 @@ Es gab ein Problem mit Ihrer Symboldatenbank.</translation>
<context>
<name>QgsSvgSelectorGroupsModel</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssvgselectorwidget.cpp" line="120"/>
+ <location filename="../src/gui/symbology-ng/qgssvgselectorwidget.cpp" line="317"/>
<source>App Symbols</source>
<translation>Anw.-symbole</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssvgselectorwidget.cpp" line="124"/>
+ <location filename="../src/gui/symbology-ng/qgssvgselectorwidget.cpp" line="321"/>
<source>User Symbols</source>
<translation>Ben.-symbole</translation>
</message>
@@ -79060,17 +79844,17 @@ Es gab ein Problem mit Ihrer Symboldatenbank.</translation>
<context>
<name>QgsSvgSelectorWidget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssvgselectorwidget.cpp" line="273"/>
+ <location filename="../src/gui/symbology-ng/qgssvgselectorwidget.cpp" line="483"/>
<source>Select SVG file</source>
<translation>SVG-Datei wählen</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssvgselectorwidget.cpp" line="275"/>
+ <location filename="../src/gui/symbology-ng/qgssvgselectorwidget.cpp" line="485"/>
<source>SVG files</source>
<translation>SVG-Dateien</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssvgselectorwidget.cpp" line="298"/>
+ <location filename="../src/gui/symbology-ng/qgssvgselectorwidget.cpp" line="508"/>
<source>File not found</source>
<translation>Datei nicht gefunden</translation>
</message>
@@ -79078,17 +79862,17 @@ Es gab ein Problem mit Ihrer Symboldatenbank.</translation>
<context>
<name>QgsSymbolLayerV2Widget</name>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="151"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="152"/>
<source>Size</source>
<translation>Größe</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="158"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="159"/>
<source>area</source>
<translation>Fläche</translation>
</message>
<message>
- <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="161"/>
+ <location filename="../src/gui/symbology-ng/qgssymbollayerv2widget.cpp" line="162"/>
<source>diameter</source>
<translation>Durchmesser</translation>
</message>
@@ -79492,7 +80276,7 @@ Es gab ein Problem mit Ihrer Symboldatenbank.</translation>
<message>
<location filename="../src/app/qgstipfactory.cpp" line="67"/>
<source>Both used to be correct, but we recently decided to just use 'QGIS'. For articles we suggest you write 'QGIS is ....'</source>
- <translation>Beide Bezeichnungen waren richtig, es wurde aber kürzlich beschlossen nur noch 'QGIS' zu verwenden. In Artikeln sollte man nur noch 'QGIS ist...' verwenden.</translation>
+ <translation>Beide Bezeichnungen waren richtig, es wurde aber kürzlich beschlossen nur noch 'QGIS' zu verwenden. In Artikeln sollte man nur noch 'QGIS ist...' verwenden</translation>
</message>
<message>
<location filename="../src/app/qgstipfactory.cpp" line="30"/>
@@ -79997,17 +80781,17 @@ p, li { white-space: pre-wrap; }
<context>
<name>QgsValueMapConfigDlg</name>
<message>
- <location filename="../src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp" line="164"/>
+ <location filename="../src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp" line="167"/>
<source>Select a file</source>
<translation>Datei wählen</translation>
</message>
<message>
- <location filename="../src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp" line="173"/>
+ <location filename="../src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp" line="176"/>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
- <location filename="../src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp" line="174"/>
+ <location filename="../src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp" line="177"/>
<source>Could not open file %1
Error was:%2</source>
<translation>Konnte Datei %1 nicht öffnen
@@ -80063,7 +80847,7 @@ Fehler war:%2</translation>
<context>
<name>QgsValueRelationConfigDlg</name>
<message>
- <location filename="../src/gui/editorwidgets/qgsvaluerelationconfigdlg.cpp" line="72"/>
+ <location filename="../src/gui/editorwidgets/qgsvaluerelationconfigdlg.cpp" line="81"/>
<source>Edit filter expression</source>
<translation>Filterausdruck bearbeiten</translation>
</message>
@@ -80425,136 +81209,136 @@ Fehler war:%2</translation>
<translation>QGIS</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="2508"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="2583"/>
<source>ERROR: no provider</source>
<translation>FEHLER: kein Datenanbieter</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="2514"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="2589"/>
<source>ERROR: layer not editable</source>
<translation>FEHLER: Layer ist nicht veränderbar</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="2531"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="2606"/>
<source>Commit errors:
%1</source>
<translation>Commit-Fehler:
%1</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3844"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4011"/>
<source>General</source>
<translation>Allgemein</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3850"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4017"/>
<source>Layer comment</source>
<translation>Layerkommentar</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3857"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4024"/>
<source>Storage type of this layer</source>
<translation>Speichertyp dieses Layers</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3865"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4032"/>
<source>Description of this provider</source>
<translation>Beschreibung dieses Datenanbieter</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3872"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4039"/>
<source>Source for this layer</source>
<translation>Quelle dieses Layers</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3890"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4057"/>
<source>Geometry type of the features in this layer</source>
<translation>Geometrietyp der Objekte dieses Layers</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3897"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4064"/>
<source>Primary key attributes</source>
<translation>Primärschlüsselattribute</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3908"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4075"/>
<source>The number of features in this layer</source>
<translation>Anzahl der Objekte dieses Layers</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3922"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4089"/>
<source>Extents</source>
<translation>Ausdehnung</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3926"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4093"/>
<source>In layer spatial reference system units</source>
<translation>In Bezugssystemeinheiten des Layers</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3992"/>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4027"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4159"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4194"/>
<source>In project spatial reference system units</source>
<translation>In Bezugssystemeinheiten des Projekts</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4005"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4172"/>
<source>Layer Spatial Reference System</source>
<translation>Räumliches Bezugssystem des Layers</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4016"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4183"/>
<source>Project (Output) Spatial Reference System</source>
<translation>Räumliches Bezugssystem des Projekts (Ausgabe)</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4038"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4205"/>
<source>Attribute field info</source>
<translation>Attributfeldinformationen</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3975"/>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3994"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4142"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4161"/>
<source>xMin,yMin %1,%2 : xMax,yMax %3,%4</source>
<translation>xMin,yMin %1;%2 : xMax,yMax %3;%4</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3913"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4080"/>
<source>Capabilities of this layer</source>
<translation>Funktionalität dieses Layers</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="3980"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4147"/>
<source>unknown extent</source>
<translation>Unbekannte Ausmaße</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4029"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4196"/>
<source>(Invalid transformation of layer extents)</source>
<translation>(Transformation der Layerausdehnung ungültig)</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4044"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4211"/>
<source>Field</source>
<translation>Feld</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4047"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4214"/>
<source>Type</source>
<translation>Typ</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4050"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4217"/>
<source>Length</source>
<translation>Länge</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4053"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4220"/>
<source>Precision</source>
<translation>Genauigkeit</translation>
</message>
<message>
- <location filename="../src/core/qgsvectorlayer.cpp" line="4056"/>
+ <location filename="../src/core/qgsvectorlayer.cpp" line="4223"/>
<source>Comment</source>
<translation>Kommentar</translation>
</message>
@@ -80562,18 +81346,18 @@ Fehler war:%2</translation>
<context>
<name>QgsVectorLayerAndAttributeModel</name>
<message>
- <location filename="../src/app/qgsdxfexportdialog.cpp" line="143"/>
+ <location filename="../src/app/qgsdxfexportdialog.cpp" line="145"/>
<source>Layer</source>
<translation>Layer</translation>
</message>
<message>
- <location filename="../src/app/qgsdxfexportdialog.cpp" line="145"/>
+ <location filename="../src/app/qgsdxfexportdialog.cpp" line="147"/>
<source>Output layer attribute</source>
<translation>Ausgabelayerattribut</translation>
</message>
<message>
- <location filename="../src/app/qgsdxfexportdialog.cpp" line="150"/>
- <location filename="../src/app/qgsdxfexportdialog.cpp" line="227"/>
+ <location filename="../src/app/qgsdxfexportdialog.cpp" line="152"/>
+ <location filename="../src/app/qgsdxfexportdialog.cpp" line="229"/>
<source>Attribute containing the name of the destination layer in the DXF output.</source>
<translation>Attribut, das den Namen des Ziellayers in der DXF-Ausgabe enthält.</translation>
</message>
@@ -80621,8 +81405,8 @@ Fehler war:%2</translation>
<source>SUCCESS: %n attribute(s) renamed.</source>
<comment>renamed attributes count</comment>
<translation>
- <numerusform>SUCCESS: Ein Attribute unbenannt.</numerusform>
- <numerusform>ERFOLG: %n Attribute umbenannt</numerusform>
+ <numerusform>ERFOLG: Ein Attribut umbenannt.</numerusform>
+ <numerusform>ERFOLG: %n Attribute umbenannt.</numerusform>
</translation>
</message>
<message numerus="yes">
@@ -80630,8 +81414,8 @@ Fehler war:%2</translation>
<source>ERROR: %n attribute(s) not renamed</source>
<comment>not renamed attributes count</comment>
<translation>
- <numerusform>FEHLER: Ein Attribut nicht umbenannt.</numerusform>
- <numerusform>FEHLER: %n Attribute nicht umbenannt.</numerusform>
+ <numerusform>FEHLER: Ein Attribut nicht umbenannt</numerusform>
+ <numerusform>FEHLER: %n Attribute nicht umbenannt</numerusform>
</translation>
</message>
<message>
@@ -81734,8 +82518,12 @@ Insbesondere können virtuellen Layern mit eingebetteten Layern in eine QLR-Date
<translation>Abfrage</translation>
</message>
<message>
- <location filename="../src/providers/virtual/qgsvirtuallayersourceselectbase.ui" line="168"/>
<source><html><head/><body><p>This is the SQL query editor. You can edit here an SQL query refering to any existing vector layers or embedded layers.</p><p>Virtual layers rely on SQLite and Spatialite. Any functions from SQLite or Spatialite can then be used in the query. To add or access geometries of a table, you can use "tablename.geometry", regardless of original geometry column's name.</p><p><span style=" [...]
+ <translation type="obsolete"><html><head/><body><p>Die ist die SQL-Abfragebearbeitung.</p><p>Virtuelle Layers basieren auf SQLite und Spatialite. Jede Funktion von SQLite oder Spatialite kann in der Abfrage verwendet werden.</p><p><span style=" font-weight:600;">Besondere Hinweise:</span></p><p>Weil die automatische Feststellung der Datentypen jeder Spalte einer Abfrage nicht immer möglich ist, könn [...]
+ </message>
+ <message>
+ <location filename="../src/providers/virtual/qgsvirtuallayersourceselectbase.ui" line="168"/>
+ <source><html><head/><body><p>This is the SQL query editor. You can edit here an SQL query referring to any existing vector layers or embedded layers.</p><p>Virtual layers rely on SQLite and Spatialite. Any functions from SQLite or Spatialite can then be used in the query. To add or access geometries of a table, you can use "tablename.geometry", regardless of original geometry column's name.</p><p><span style=" [...]
<translation><html><head/><body><p>Die ist die SQL-Abfragebearbeitung.</p><p>Virtuelle Layers basieren auf SQLite und Spatialite. Jede Funktion von SQLite oder Spatialite kann in der Abfrage verwendet werden.</p><p><span style=" font-weight:600;">Besondere Hinweise:</span></p><p>Weil die automatische Feststellung der Datentypen jeder Spalte einer Abfrage nicht immer möglich ist, können spezielle Kom [...]
</message>
<message>
@@ -81912,17 +82700,17 @@ Insbesondere können virtuellen Layern mit eingebetteten Layern in eine QLR-Date
<context>
<name>QgsWFSConnectionItem</name>
<message>
- <location filename="../src/providers/wfs/qgswfsdataitems.cpp" line="91"/>
+ <location filename="../src/providers/wfs/qgswfsdataitems.cpp" line="93"/>
<source>Edit...</source>
<translation>Bearbeiten...</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsdataitems.cpp" line="95"/>
+ <location filename="../src/providers/wfs/qgswfsdataitems.cpp" line="97"/>
<source>Delete</source>
<translation>Löschen</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsdataitems.cpp" line="105"/>
+ <location filename="../src/providers/wfs/qgswfsdataitems.cpp" line="107"/>
<source>Modify WFS connection</source>
<translation>WFS-Verbindung ändern</translation>
</message>
@@ -81953,29 +82741,29 @@ Insbesondere können virtuellen Layern mit eingebetteten Layern in eine QLR-Date
<translation>QGIS</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="457"/>
+ <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="462"/>
<source>Error when parsing GetFeature response</source>
<translation>Fehler beim Interpretieren der GetFeature-Antwort</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="458"/>
- <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="484"/>
- <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="642"/>
+ <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="463"/>
+ <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="489"/>
+ <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="647"/>
<source>WFS</source>
<translation>WFS</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="483"/>
+ <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="488"/>
<source>Server generated an exception in GetFeature response</source>
<translation>Server erzeugte eine Ausnahme in der GetFeature-Antwort</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="642"/>
+ <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="647"/>
<source>Retrying request %1: %2/%3</source>
<translation>Wiederhole Anfrage %1: %2/%3</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="704"/>
+ <location filename="../src/providers/wfs/qgswfsfeatureiterator.cpp" line="709"/>
<source>Download of features failed: %1</source>
<translation>Herunterladen von Objekt schlug fehl: %1</translation>
</message>
@@ -82019,8 +82807,8 @@ Insbesondere können virtuellen Layern mit eingebetteten Layern in eine QLR-Date
<location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1109"/>
<location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1121"/>
<location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1130"/>
- <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1440"/>
- <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1515"/>
+ <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1449"/>
+ <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1524"/>
<source>WFS</source>
<translation>WFS</translation>
</message>
@@ -82147,42 +82935,42 @@ Insbesondere können virtuellen Layern mit eingebetteten Layern in eine QLR-Date
<translation>Kann Attributelemente nicht finden</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1439"/>
+ <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1448"/>
<source>GetCapabilities failed for url %1: %2</source>
<translation>GetCapabilities für URL %1 gescheitert: %2</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1514"/>
+ <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1523"/>
<source>Could not find typename %1 in capabilities for url %2</source>
<translation>Konnte Namen des Typs %1 in Diensteigenschaften der URL %2 nicht finden</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1549"/>
+ <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1558"/>
<source>empty response</source>
<translation>Leere Antwort</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1555"/>
+ <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1564"/>
<source>WFS service exception:%1</source>
<translation>WFS-Dienstausnahme: %1</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1561"/>
+ <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1570"/>
<source>unsuccessful service response: %1</source>
<translation>Nichterfolgreiche Dienstantwort: %1</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1568"/>
+ <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1577"/>
<source>WFS exception report (code=%1 text=%2)</source>
<translation>WFS-Ausnahmenbereicht (Code=%1 Text=%2)</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1569"/>
+ <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1578"/>
<source>missing</source>
<translation>fehlt</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1575"/>
+ <location filename="../src/providers/wfs/qgswfsprovider.cpp" line="1584"/>
<source>unhandled response: %1</source>
<translation>nicht behandelte Antwort: %1</translation>
</message>
@@ -82191,31 +82979,34 @@ Insbesondere können virtuellen Layern mit eingebetteten Layern in eine QLR-Date
<name>QgsWFSRequest</name>
<message>
<location filename="../src/providers/wfs/qgswfsrequest.cpp" line="108"/>
- <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="157"/>
- <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="223"/>
- <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="234"/>
- <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="291"/>
- <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="299"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="123"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="164"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="174"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="237"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="248"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="265"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="314"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="322"/>
<source>WFS</source>
<translation>WFS</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="185"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="199"/>
<source>%1 of %2 bytes downloaded.</source>
<translation>%1 von %2 Bytes heruntergeladen.</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="222"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="236"/>
<source>Redirect loop detected: %1</source>
<translation>Umleitungszyklus festgestellt: %1</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="289"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="312"/>
<source>empty response: %1</source>
<translation>Leere Antwort: %1</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="317"/>
+ <location filename="../src/providers/wfs/qgswfsrequest.cpp" line="340"/>
<source>network request update failed for authentication config</source>
<translation>Aktualisierung der Netzwerkanfragen für Authentifikationskonfiguration gescheitert</translation>
</message>
@@ -82223,12 +83014,12 @@ Insbesondere können virtuellen Layern mit eingebetteten Layern in eine QLR-Date
<context>
<name>QgsWFSRootItem</name>
<message>
- <location filename="../src/providers/wfs/qgswfsdataitems.cpp" line="156"/>
+ <location filename="../src/providers/wfs/qgswfsdataitems.cpp" line="158"/>
<source>New Connection...</source>
<translation>Neue Verbindung...</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfsdataitems.cpp" line="178"/>
+ <location filename="../src/providers/wfs/qgswfsdataitems.cpp" line="180"/>
<source>Create a new WFS connection</source>
<translation>Neue WFS-Verbindung anlegen</translation>
</message>
@@ -82286,7 +83077,7 @@ Neuladen des Layers mit F5 könnte helfen</translation>
<message>
<location filename="../src/providers/wfs/qgswfsshareddata.cpp" line="1016"/>
<source>Layer extent reported by the server is not correct. You may need to zoom on layer and then zoom out to see all features</source>
- <translation>Vom Server gemeldete Layerausmaße sind nicht richtig. Ggf. muß erneut zum Layer gezoomt und dann herausgezoomt werden, um alle Objekte zu sehen.</translation>
+ <translation>Vom Server gemeldete Layerausmaße sind nicht richtig. Ggf. muß erneut zum Layer gezoomt und dann herausgezoomt werden, um alle Objekte zu sehen</translation>
</message>
<message>
<location filename="../src/providers/wfs/qgswfsshareddata.cpp" line="1065"/>
@@ -82380,22 +83171,22 @@ Neuladen des Layers mit F5 könnte helfen</translation>
<translation>Löschen bestätigen</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfssourceselect.cpp" line="521"/>
+ <location filename="../src/providers/wfs/qgswfssourceselect.cpp" line="523"/>
<source>Server exception</source>
<translation>Serverausnahme</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfssourceselect.cpp" line="521"/>
+ <location filename="../src/providers/wfs/qgswfssourceselect.cpp" line="523"/>
<source>DescribeFeatureType failed</source>
<translation>DescribeFeatureType gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfssourceselect.cpp" line="736"/>
+ <location filename="../src/providers/wfs/qgswfssourceselect.cpp" line="738"/>
<source>Load connections</source>
<translation>Verbindungen laden</translation>
</message>
<message>
- <location filename="../src/providers/wfs/qgswfssourceselect.cpp" line="737"/>
+ <location filename="../src/providers/wfs/qgswfssourceselect.cpp" line="739"/>
<source>XML files (*.xml *XML)</source>
<translation>XML-Dateien (*.xml *.XML)</translation>
</message>
@@ -82500,27 +83291,27 @@ Neuladen des Layers mit F5 könnte helfen</translation>
<context>
<name>QgsWMSConnectionItem</name>
<message>
- <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="63"/>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="67"/>
<source>Failed to parse WMS URI</source>
<translation>Unverständliche WMS-URI</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="71"/>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="75"/>
<source>Failed to download capabilities</source>
<translation>Eigenschaften-Abfrage gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="78"/>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="82"/>
<source>Failed to parse capabilities</source>
<translation>Unverständliche Eigenschaften</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="202"/>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="221"/>
<source>Edit...</source>
<translation>Bearbeiten...</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="206"/>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="225"/>
<source>Delete</source>
<translation>Löschen</translation>
</message>
@@ -82528,7 +83319,7 @@ Neuladen des Layers mit F5 könnte helfen</translation>
<context>
<name>QgsWMSRootItem</name>
<message>
- <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="384"/>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="403"/>
<source>New Connection...</source>
<translation>Neue Verbindung...</translation>
</message>
@@ -82923,73 +83714,83 @@ Neuladen des Layers mit F5 könnte helfen</translation>
<context>
<name>QgsWcsCapabilities</name>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="174"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="182"/>
<source>empty capabilities document</source>
<translation>Leeres Capabilities-Dokument</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="274"/>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="338"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="282"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="346"/>
<source>
Tried URL: %1</source>
<translation>
Versuchte URL: %1</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="355"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="363"/>
<source>Capabilities request redirected.</source>
<translation>Eigenschaften-Abfrage umgeleitet.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="382"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="399"/>
<source>empty of capabilities: %1</source>
<translation>Eigenschaften leer: %1</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="403"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="429"/>
<source>Download of capabilities failed: %1</source>
<translation>Eigenschaften-Abfrage gescheitert: %1</translation>
</message>
<message>
<location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="152"/>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="362"/>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="404"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="166"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="370"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="385"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="420"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="430"/>
<source>WCS</source>
<translation>WCS</translation>
</message>
<message>
<location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="151"/>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="361"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="369"/>
<source>Download of capabilities failed: network request update failed for authentication config</source>
<translation>Laden der Eigenschaften gescheitert: Netzwerkaktualisierungsanfrage für Authentikationskonfiguration gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="416"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="165"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="384"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="419"/>
+ <source>Download of capabilities failed: network reply update failed for authentication config</source>
+ <translation>Laden der Eigenschaften gescheitert: Aktualisierung der Authentikationskonfiguration der Netzwerkanfrage gescheitert</translation>
+ </message>
+ <message>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="442"/>
<source>%1 of %2 bytes of capabilities downloaded.</source>
<translation>%1 von %2 Bytes der Eigenschaften heruntergeladen.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="454"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="480"/>
<source>Exception</source>
<translation>Ausnahme</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="456"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="482"/>
<source>Could not get WCS capabilities: %1</source>
<translation>Konnte WCS-Fähigkeiten nicht erfragen: %1</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="460"/>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="739"/>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="766"/>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="921"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="486"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="765"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="792"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="947"/>
<source>Dom Exception</source>
<translation>DOM-Ausnahme</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="462"/>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="768"/>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="923"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="488"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="794"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="949"/>
<source>Could not get WCS capabilities in the expected format (DTD): no %1 found.
This might be due to an incorrect WCS Server URL.
Tag:%3
@@ -83002,17 +83803,17 @@ Antwort war:
%4</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="478"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="504"/>
<source>Version not supported</source>
<translation>Version nicht unterstützt</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="480"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="506"/>
<source>WCS server version %1 is not supported by QGIS (supported versions: 1.0.0, 1.1.0, 1.1.2)</source>
<translation>WCS-Serverversion %1 wird nicht von QGIS unterstützt (unterstützte Versionen: 1.0.0, 1.1.0, 1.1.2)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="741"/>
+ <location filename="../src/providers/wcs/qgswcscapabilities.cpp" line="767"/>
<source>Could not get WCS capabilities: %1 at line %2 column %3
This is probably due to an incorrect WCS Server URL.
Response was:
@@ -83028,84 +83829,94 @@ Antwort war:
<context>
<name>QgsWcsDownloadHandler</name>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1726"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1757"/>
<source>Map request error (Status: %1; Reason phrase: %2; URL:%3)</source>
<translation>Kartenabfrage-Fehler (Status: %1; Grund:%2; URL: %3)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1672"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1710"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1729"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1767"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1785"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1795"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1805"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1822"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1828"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1848"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1887"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1891"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1682"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1694"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1732"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1741"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1760"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1798"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1816"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1826"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1836"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1853"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1859"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1879"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1917"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1930"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1934"/>
<source>WCS</source>
<translation>WCS</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1671"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1709"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1681"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1731"/>
<source>Network request update failed for authentication config</source>
<translation>Netzwerkaktualisierung der Authentifikationskonfiguration gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1758"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1693"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1740"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1916"/>
+ <source>Network reply update failed for authentication config</source>
+ <translation>Aktualisierung der Netzwerkanfragen für Authentifikationskonfiguration gescheitert</translation>
+ </message>
+ <message>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1789"/>
<source>Map request error:<br>Title: %1<br>Error: %2<br>URL: <a href='%3'>%3</a>)</source>
<translation>Kartenabfrage-Fehler:<br>Titel: %1<br>Fehler:%2<br>URL: <a href='%3'>%3</a>)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1764"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1795"/>
<source>Map request error (Status: %1; Response: %2; URL:%3)</source>
<translation>Kartenabfrage-Fehler (Status: %1; Antwort:%2; URL: %3)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1785"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1816"/>
<source>Cannot parse multipart response: %1</source>
<translation>Unverständliche mehrteilige Antwort: %1</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1795"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1826"/>
<source>Expected 2 parts, %1 received</source>
<translation>%1 statt zwei Teile empfangen</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1805"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1836"/>
<source>More than 2 parts (%1) received</source>
<translation>Mehr als 2 Teile (%1) empfangen</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1820"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1851"/>
<source>Map request error (Title:%1; Error:%2; URL: %3)</source>
<translation>Kartenabfrage-Fehler (Titel: %1; Fehler:%2; URL: %3)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1826"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1857"/>
<source>Map request error (Response: %1; URL:%2)</source>
<translation>Kartenabfrage-Fehler (Antwort:%1; URL: %2)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1848"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1879"/>
<source>Content-Transfer-Encoding %1 not supported</source>
<translation>Content-Transfer-Encoding %1 nicht unterstützt</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1887"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1930"/>
<source>Map request failed [error:%1 url:%2]</source>
<translation>Kartenabfrage-Fehler [Fehler:%1; URL: %2]</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1891"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1934"/>
<source>Not logging more than 100 request errors.</source>
<translation>Nicht mehr als 100 Abfragefehler werden protokolliert.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1905"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1949"/>
<source>%1 of %2 bytes of map downloaded.</source>
<translation>%1 von %2 Bytes der Karte heruntergeladen.</translation>
</message>
@@ -83133,53 +83944,53 @@ Antwort war:
<translation>Konnte Testdatensatz nicht laden.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="563"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="562"/>
<source>Received coverage has wrong extent %1 (expected %2)</source>
<translation>Empfangene Coverage hat falsche Ausdehnung %1 (erwartet %2)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="563"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="625"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="789"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="811"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="821"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1046"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1186"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="562"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="624"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="788"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="810"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="820"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1045"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1185"/>
<source>WCS</source>
<translation>WCS</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="582"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="581"/>
<source>Rotating raster</source>
<translation>Raster wird gedreht</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="625"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="624"/>
<source>Received coverage has wrong size %1 x %2 (expected %3 x %4)</source>
<translation>Empfangene Coverage hat die falsche Größe %1 x %2 (erwartet %3 x %4)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="781"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="780"/>
<source>Getting map via WCS.</source>
<translation>Lade Karte über WCS.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="789"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="788"/>
<source>No data received</source>
<translation>Keine Daten empfangen</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="811"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="810"/>
<source>Cannot create memory file</source>
<translation>Konnte Speicherdatei nicht erzeugen</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="947"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="946"/>
<source>Dom Exception</source>
<translation>DOM-Ausnahme</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="948"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="947"/>
<source>Could not get WCS Service Exception at %1 at line %2 column %3
Response was:
@@ -83192,143 +84003,143 @@ Antwort war:
%4</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="986"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="985"/>
<source>Service Exception</source>
<translation>Dienstausnahme</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="995"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="994"/>
<source>Request contains a format not offered by the server.</source>
<translation>Anfrage enthält ein Format, dass der Server nicht anbietet.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="996"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="995"/>
<source>Request is for a Coverage not offered by the service instance.</source>
<translation>Angefragte Coverage wird von Serverinstanz nicht angeboten.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="997"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="996"/>
<source>Value of (optional) UpdateSequence parameter in GetCapabilities request is equal to current value of service metadata update sequence number.</source>
<translation>Wert des (optionalen) Aktualisierungssequenenzzählers der GetCapabilities-Anfrage entspricht dem aktuellen Wert des Aktualisierungssequenzzähler in den Dienstmetadaten.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="998"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="997"/>
<source>Value of (optional) UpdateSequence parameter in GetCapabilities request is greater than current value of service metadata update sequence number.</source>
<translation>Wert des (optionalen) Aktualisierungssequenenzzählers der GetCapabilities-Anfrage ist größer als der aktuelle Wert des Aktualisierungssequenzzähler in den Dienstmetadaten.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1000"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="999"/>
<source>Request does not include a parameter value, and the server instance did not declare a default value for that dimension.</source>
<translation>Anfrage enthält keinen Parameterwert, und die Serverinstanz selbst definiert auch keine Vorgabe dafür.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1001"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1000"/>
<source>Request contains an invalid parameter value.</source>
<translation>Anfrage enthält einen ungültigen Parameterwert.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1003"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1002"/>
<source>No other exceptionCode specified by this service and server applies to this exception.</source>
<translation>Kein anderer Ausnahmecode des Dienstes und Servers trifft auf diese Ausnahme zu.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1004"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1003"/>
<source>Operation request contains an output CRS that can not be used within the output format.</source>
<translation>Operationsanfrage enthält ein Ausgabe-KBS, das nicht mit dem Ausgabeformat verwendet werden kann.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1005"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1004"/>
<source>Operation request specifies to "store" the result, but not enough storage is available to do this.</source>
<translation>Operationsanfrage gibt das "Speichern" des Ergebnisses vor, aber es ist nicht genügend Speicher dafür verfügbar.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1032"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1031"/>
<source>(No error code was reported)</source>
<translation>(Kein Fehlercode zurückgegeben)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1040"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1039"/>
<source>(Unknown error code)</source>
<translation>(Unbekannter Fehlercode)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1043"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1042"/>
<source>The WCS vendor also reported: </source>
<translation>Der WCS-Betreiber meldete folgendes: </translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1046"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1045"/>
<source>composed error message '%1'.</source>
<translation>Zusammengestellte Fehlermeldung '%1'.</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1186"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1185"/>
<source>Cannot verify coverage full extent: %1</source>
<translation>Konnte Grenze der Coverage nicht überprüfen: %1</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1217"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1298"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1216"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1297"/>
<source>Property</source>
<translation>Eigenschaft</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1220"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1301"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1219"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1300"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1223"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1222"/>
<source>Name (identifier)</source>
<translation>Name (Kennung)</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1224"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1305"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1223"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1304"/>
<source>Title</source>
<translation>Titel</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1225"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1306"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1224"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1305"/>
<source>Abstract</source>
<translation>Zusammenfassung</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1228"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1227"/>
<source>Fixed Width</source>
<translation>Feste Breite</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1229"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1228"/>
<source>Fixed Height</source>
<translation>Feste Höhe</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1230"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1229"/>
<source>Native CRS</source>
<translation>Natives KBS</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1231"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1230"/>
<source>Native Bounding Box</source>
<translation>Native Ausdehnung</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1234"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1233"/>
<source>WGS 84 Bounding Box</source>
<translation>WGS84-Ausdehnung</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1242"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1247"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1241"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1246"/>
<source>Available in CRS</source>
<translation>Verfügbar in KBS</translation>
</message>
<message numerus="yes">
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1247"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1257"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1246"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1256"/>
<source>(and %n more)</source>
<comment>crs</comment>
<translation>
@@ -83337,89 +84148,89 @@ Antwort war:
</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1252"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1257"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1251"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1256"/>
<source>Available in format</source>
<translation>Verfügbar im Format</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1275"/>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1328"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1274"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1327"/>
<source>Coverages</source>
<translation>Coverages</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1281"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1280"/>
<source>Cache Stats</source>
<translation>Cache-Statistik</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1289"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1288"/>
<source>Server Properties</source>
<translation>Server-Eigenschaften</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1309"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1308"/>
<source>Keywords</source>
<translation>Schlüsselworte</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1310"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1309"/>
<source>Online Resource</source>
<translation>Online-Quelle</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1311"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1310"/>
<source>Contact Person</source>
<translation>Kontaktperson</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1315"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1314"/>
<source>Fees</source>
<translation>Gebühren</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1316"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1315"/>
<source>Access Constraints</source>
<translation>Zugriffsbeschränkungen</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1317"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1316"/>
<source>Image Formats</source>
<translation>Bildformate</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1318"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1317"/>
<source>GetCapabilitiesUrl</source>
<translation>GetCapabilities-URL</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1320"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1319"/>
<source>Get Coverage Url</source>
<translation>GetCoverage-URL</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1320"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1319"/>
<source> <font color="red">(advertised but ignored)</font></source>
<translation> <font color="red">(gemeldet, aber ignoriert)</font></translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1342"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1341"/>
<source>And %1 more coverages</source>
<translation>Und %1 weitere Coverages</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1369"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1368"/>
<source>Format not supported</source>
<translation>Format nicht unterstützt</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1490"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1489"/>
<source>Read data error</source>
<translation>Datenlesefehler</translation>
</message>
<message>
- <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1517"/>
+ <location filename="../src/providers/wcs/qgswcsprovider.cpp" line="1516"/>
<source>RasterIO error: </source>
<translation>Raster-E/A-Fehler: </translation>
</message>
@@ -83427,18 +84238,18 @@ Antwort war:
<context>
<name>QgsWebPage</name>
<message>
- <location filename="../src/core/qgswebpage.h" line="237"/>
+ <location filename="../src/core/qgswebpage.h" line="239"/>
<source>Line %1: %2</source>
<translation>Zeile %1: %2</translation>
</message>
<message>
- <location filename="../src/core/qgswebpage.h" line="237"/>
<location filename="../src/core/qgswebpage.h" line="239"/>
+ <location filename="../src/core/qgswebpage.h" line="241"/>
<source>Javascript</source>
<translation>Javascript</translation>
</message>
<message>
- <location filename="../src/core/qgswebpage.h" line="239"/>
+ <location filename="../src/core/qgswebpage.h" line="241"/>
<source>%1 (line %2): %3</source>
<translation>%1 (Zeile %2): %3</translation>
</message>
@@ -83486,7 +84297,7 @@ Antwort war:
<translation>...</translation>
</message>
<message>
- <location filename="../src/gui/editorwidgets/qgswebviewwidgetwrapper.cpp" line="177"/>
+ <location filename="../src/gui/editorwidgets/qgswebviewwidgetwrapper.cpp" line="178"/>
<source>Select a file</source>
<translation>Datei wählen</translation>
</message>
@@ -83507,41 +84318,49 @@ Antwort war:
<context>
<name>QgsWmsCapabilitiesDownload</name>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1945"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1989"/>
<source>%1 of %2 bytes of capabilities downloaded.</source>
<translation>%1 von %2 Bytes der Eigenschaften heruntergeladen.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1960"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2004"/>
<source>Capabilities request redirected.</source>
<translation>Eigenschaften-Abfrage umgeleitet.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1966"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2010"/>
<source>Redirect loop detected: %1</source>
<translation>Umleitungszyklus festgestellt: %1</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1916"/>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1967"/>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1977"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1952"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1964"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2011"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2021"/>
<location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2040"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2096"/>
<source>WMS</source>
<translation>WMS</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1915"/>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1976"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1951"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2020"/>
<source>Download of capabilities failed: network request update failed for authentication config</source>
<translation>Laden der Eigenschaften gescheitert: Netzwerkaktualisierungsanfrage für Authentikationskonfiguration gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2033"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="1963"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2039"/>
+ <source>Download of capabilities failed: network reply update failed for authentication config</source>
+ <translation>Laden der Eigenschaften gescheitert: Aktualisierung der Authentikationskonfiguration der Netzwerkanfrage gescheitert</translation>
+ </message>
+ <message>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2089"/>
<source>empty of capabilities: %1</source>
<translation>Eigenschaften leer: %1</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2039"/>
+ <location filename="../src/providers/wms/qgswmscapabilities.cpp" line="2095"/>
<source>Download of capabilities failed: %1</source>
<translation>Eigenschaften-Abfrage gescheitert: %1</translation>
</message>
@@ -83549,47 +84368,47 @@ Antwort war:
<context>
<name>QgsWmsImageDownloadHandler</name>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3267"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3577"/>
<source>Map request error (Status: %1; Reason phrase: %2; URL:%3)</source>
<translation>Kartenabfrage-Fehler (Status: %1; Grund:%2; URL: %3)</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3270"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3292"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3301"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3309"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3331"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3335"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3580"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3602"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3611"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3619"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3644"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3648"/>
<source>WMS</source>
<translation>WMS</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3291"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3601"/>
<source>Returned image is flawed [Content-Type:%1; URL:%2]</source>
<translation>Geladenes Bild ist defekt [Content-Type:%1; URL: %2]</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3299"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3609"/>
<source>Map request error (Title:%1; Error:%2; URL: %3)</source>
<translation>Kartenabfrage-Fehler (Titel: %1; Fehler:%2; URL: %3)</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3305"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3615"/>
<source>Map request error (Status: %1; Response: %2; Content-Type: %3; URL:%4)</source>
<translation>Kartenabfrage-Fehler (Status: %1; Antwort:%2; Content-Type: %3; URL: %4)</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3331"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3644"/>
<source>Map request failed [error:%1 url:%2]</source>
<translation>Kartenabfrage-Fehler [Fehler:%1; URL: %2]</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3335"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3648"/>
<source>Not logging more than 100 request errors.</source>
<translation>Nicht mehr als 100 Abfragefehler werden protokolliert.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3349"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3663"/>
<source>%1 of %2 bytes of map downloaded.</source>
<translation>%1 von %2 Bytes der Karte heruntergeladen.</translation>
</message>
@@ -83597,29 +84416,29 @@ Antwort war:
<context>
<name>QgsWmsLegendDownloadHandler</name>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3722"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="4083"/>
<source>Redirect loop detected: %1</source>
<translation>Umleitungszyklus festgestellt: %1</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3723"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="4084"/>
<source>WMS</source>
<translation>WMS</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3794"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="4156"/>
<source>GetLegendGraphic request error</source>
<translation>GetLegendGraphic-Abfragefehler</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3796"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="4158"/>
<source>Status: %1
Reason phrase: %2</source>
<translation>Status: %1
Grund: %2</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3804"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="4166"/>
<source>Returned legend image is flawed [URL: %1]</source>
<translation>Geladenes Legendenbild ist defekt [URL: %1]</translation>
</message>
@@ -83627,61 +84446,61 @@ Grund: %2</translation>
<context>
<name>QgsWmsProvider</name>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="110"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="122"/>
<source>Cannot parse URI</source>
<translation>Konnte URI nicht parsen</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="137"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="161"/>
<source>Cannot calculate extent</source>
<translation>Konnte Ausdehnung nicht berechnen</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="130"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="154"/>
<source>Cannot set CRS</source>
<translation>Konnte KBS nicht setzen</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="299"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="316"/>
<source>Number of layers and styles don't match</source>
<translation>Anzahl von Layern und Stilen stimmt nicht überein</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="299"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="873"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="882"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2431"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2846"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="316"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="876"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="885"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2728"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3145"/>
<source>WMS</source>
<translation>WMS</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="388"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="405"/>
<source>Number of tile layers must be one</source>
<translation>Anzahl der Kachellayer muss eins sein</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="395"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="412"/>
<source>Tile layer not found</source>
<translation>Kachellayer nicht gefunden</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="456"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="473"/>
<source>Tile layer or tile matrix set not found</source>
<translation>Kachellayer oder Kachelmatrixsatz nicht gefunden</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="581"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="628"/>
<source>Getting map via WMS.</source>
<translation>Lade Karte über WMS.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="847"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="748"/>
<source>Getting tiles.</source>
<translation>Lade Kacheln.</translation>
</message>
<message numerus="yes">
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="855"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="858"/>
<source>%n tile requests in background</source>
<comment>tile request count</comment>
<translation>
@@ -83690,7 +84509,7 @@ Grund: %2</translation>
</translation>
</message>
<message numerus="yes">
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="856"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="859"/>
<source>, %n cache hits</source>
<comment>tile cache hits</comment>
<translation>
@@ -83699,7 +84518,7 @@ Grund: %2</translation>
</translation>
</message>
<message numerus="yes">
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="857"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="860"/>
<source>, %n cache misses.</source>
<comment>tile cache missed</comment>
<translation>
@@ -83708,7 +84527,7 @@ Grund: %2</translation>
</translation>
</message>
<message numerus="yes">
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="858"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="861"/>
<source>, %n errors.</source>
<comment>errors</comment>
<translation>
@@ -83717,205 +84536,205 @@ Grund: %2</translation>
</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="873"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="876"/>
<source>image is NULL</source>
<translation>Bild ist NULL</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="882"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="885"/>
<source>unexpected image size</source>
<translation>Unerwartete Bildgröße</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1053"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1346"/>
<source>Dom Exception</source>
<translation>DOM-Ausnahme</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1107"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1400"/>
<source>Service Exception</source>
<translation>Dienstausnahme</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1112"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1405"/>
<source>Request contains a format not offered by the server.</source>
<translation>Anfrage enthält ein Format, dass der Server nicht anbietet.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1116"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1409"/>
<source>Request contains a CRS not offered by the server for one or more of the Layers in the request.</source>
<translation>Anfrage verlangt ein CRS für einen oder mehrere Layer, die der Server nicht anbietet.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1120"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1413"/>
<source>Request contains a SRS not offered by the server for one or more of the Layers in the request.</source>
<translation>Anfrage enthält ein SRS für einen oder mehrere Layer, die der Server nicht anbietet.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1124"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1417"/>
<source>GetMap request is for a Layer not offered by the server, or GetFeatureInfo request is for a Layer not shown on the map.</source>
<translation>GetMap-Anfrage für einen Layer, den der Server nicht anbietet oder GetFeature-Anfrage für einen Layer, der nicht auf der Karte angezeigt wird.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1129"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1422"/>
<source>Request is for a Layer in a Style not offered by the server.</source>
<translation>Anfrage für einen Layer in einem Stil, den der Server nicht anbietet.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1133"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1426"/>
<source>GetFeatureInfo request is applied to a Layer which is not declared queryable.</source>
<translation>GetFeatureInfo-Anfrage wird auf einen Layer bezogen, der nicht als abfragbar deklariert ist.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1137"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1430"/>
<source>GetFeatureInfo request contains invalid X or Y value.</source>
<translation>GetFeatureInfo-Anfrage enthält einen ungültigen X- oder Y-Wert.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1141"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1434"/>
<source>Value of (optional) UpdateSequence parameter in GetCapabilities request is equal to current value of service metadata update sequence number.</source>
<translation>Wert des (optionalen) Aktualisierungssequenenzzählers der GetCapabilities-Anfrage entspricht dem aktuellen Wert des Aktualisierungssequenzzähler in den Dienstmetadaten.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1146"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1439"/>
<source>Value of (optional) UpdateSequence parameter in GetCapabilities request is greater than current value of service metadata update sequence number.</source>
<translation>Wert des (optionalen) Aktualisierungssequenenzzählers der GetCapabilities-Anfrage ist größer als der aktuelle Wert des Aktualisierungssequenzzähler in den Dienstmetadaten.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1151"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1444"/>
<source>Request does not include a sample dimension value, and the server did not declare a default value for that dimension.</source>
<translation>Anfrage enthält keinen beispielhaften Dimensionswert, und der Server selbst definiert auch keinen.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1156"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1449"/>
<source>Request contains an invalid sample dimension value.</source>
<translation>Anfrage enthält einen ungültigen beispielhaften Dimensionswert.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1160"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1453"/>
<source>Request is for an optional operation that is not supported by the server.</source>
<translation>Anfrage ist für eine optionale Operation, die der Server nicht unterstützt.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1164"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1457"/>
<source>(No error code was reported)</source>
<translation>(Kein Fehlercode zurückgegeben)</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1168"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1461"/>
<source>(Unknown error code)</source>
<translation>(Unbekannter Fehlercode)</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1171"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1464"/>
<source>The WMS vendor also reported: </source>
<translation>Der WMS-Betreiber meldete folgendes: </translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1370"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1580"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1839"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2031"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1663"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1873"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2136"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2328"/>
<source>Property</source>
<translation>Eigenschaft</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1373"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1583"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1842"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2034"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1666"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1876"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2139"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2331"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1378"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1492"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1671"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1785"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1386"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1679"/>
<source>Visibility</source>
<translation>Sichtbarkeit</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1389"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1682"/>
<source>Visible</source>
<translation>Sichtbar</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1389"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1682"/>
<source>Hidden</source>
<translation>Versteckt</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1394"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1500"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1596"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1687"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1793"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1889"/>
<source>Title</source>
<translation>Titel</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1402"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1508"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1604"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1695"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1801"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1897"/>
<source>Abstract</source>
<translation>Zusammenfassung</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1410"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1703"/>
<source>Can Identify</source>
<translation>Kann abgefragt werden</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1413"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1421"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1429"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1849"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1706"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1714"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1722"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2146"/>
<source>Yes</source>
<translation>Ja</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1413"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1421"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1429"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1849"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1706"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1714"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1722"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2146"/>
<source>No</source>
<translation>Nein</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1418"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1711"/>
<source>Can be Transparent</source>
<translation>Kann transparent sein</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1426"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1719"/>
<source>Can Zoom In</source>
<translation>Kann herangezoomt werden</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1434"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1727"/>
<source>Cascade Count</source>
<translation>Kaskadiere Anzahl</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1442"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1735"/>
<source>Fixed Width</source>
<translation>Feste Breite</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1450"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1743"/>
<source>Fixed Height</source>
<translation>Feste Höhe</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1460"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1470"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1753"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1763"/>
<source>Available in CRS</source>
<translation>Verfügbar in KBS</translation>
</message>
<message numerus="yes">
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1473"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1766"/>
<source>(and %n more)</source>
<comment>crs</comment>
<translation>
@@ -83924,95 +84743,95 @@ Grund: %2</translation>
</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1483"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1776"/>
<source>Available in style</source>
<translation>Verfügbar im Stil</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1518"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1811"/>
<source>LegendURLs</source>
<translation>LegendenURLs</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1571"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1864"/>
<source>Server Properties</source>
<translation>Server-Eigenschaften</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1551"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1769"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1844"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2062"/>
<source>Selected Layers</source>
<translation>Gewählte Layer</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1553"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1786"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1846"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2079"/>
<source>Other Layers</source>
<translation>Andere Layer</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1559"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1852"/>
<source>Tile Layer Properties</source>
<translation>Kachellayer-Eigenschaften</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1563"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1856"/>
<source>Cache Stats</source>
<translation>Cache-Statistik</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1588"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1881"/>
<source>WMS Version</source>
<translation>WMS-Version</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1612"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1905"/>
<source>Keywords</source>
<translation>Schlüsselworte</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1620"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1913"/>
<source>Online Resource</source>
<translation>Online-Quelle</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1628"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1921"/>
<source>Contact Person</source>
<translation>Kontaktperson</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1640"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1933"/>
<source>Fees</source>
<translation>Gebühren</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1648"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1941"/>
<source>Access Constraints</source>
<translation>Zugriffsbeschränkungen</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1738"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2031"/>
<source>Image Formats</source>
<translation>Bildformate</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1728"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1746"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2021"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2039"/>
<source>Identify Formats</source>
<translation>Abfrageformate</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1754"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2047"/>
<source>Layer Count</source>
<translation>Layeranzahl</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1686"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1979"/>
<source>Tile Layer Count</source>
<translation>Kachellayeranzahl</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1054"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1347"/>
<source>Could not get WMS Service Exception: %1 at line %2 column %3
Response was:
@@ -84025,278 +84844,283 @@ Antwort war:
%4</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1656"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1949"/>
<source>GetCapabilitiesUrl</source>
<translation>GetCapabilities-URL</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1663"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1956"/>
<source>GetMapUrl</source>
<translation>GetMap-URL</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1666"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1673"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1680"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1959"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1966"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1973"/>
<source> <font color="red">(advertised but ignored)</font></source>
<translation> <font color="red">(gemeldet, aber ignoriert)</font></translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1670"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1963"/>
<source>GetFeatureInfoUrl</source>
<translation>GetFeatureInfoUrl</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1677"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1970"/>
<source>GetLegendGraphic</source>
<translation>GetLegendGraphic</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1693"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1986"/>
<source>GetTileUrl</source>
<translation>GetTileUrl</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1702"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1995"/>
<source>Tile templates</source>
<translation>Kachelvorlagen</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1714"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2007"/>
<source>FeatureInfo templates</source>
<translation>FeatureInfo-Vorlagen</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1802"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2095"/>
<source>Tileset Properties</source>
<translation>Tileset-Eigenschaften</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1813"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2106"/>
<source>Identifier</source>
<translation>Kennung</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1815"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2108"/>
<source>Tile mode</source>
<translation>Kachelmodus</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1824"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2117"/>
<source>WMTS</source>
<translation>WMTS</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1828"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2121"/>
<source>WMS-C</source>
<translation>WMS-C</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1832"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2125"/>
+ <source>XYZ</source>
+ <translation>XYZ</translation>
+ </message>
+ <message>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2129"/>
<source>Invalid tile mode</source>
<translation>Ungültiger Kachelmodus</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1846"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2143"/>
<source>Selected</source>
<translation>Ausgewählt</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1855"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2152"/>
<source>Available Styles</source>
<translation>Verfügbare Stile</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1868"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1873"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2165"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2170"/>
<source>CRS</source>
<translation>KBS</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1876"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2173"/>
<source>Bounding Box</source>
<translation>Ausdehnung</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1889"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2186"/>
<source>Available Tilesets</source>
<translation>Verfügbare Kachelsätze</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1925"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2222"/>
<source>Selected tile matrix set </source>
<translation>Gewählter Kachelmatrixsatz </translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1927"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2224"/>
<source>Scale</source>
<translation>Maßstab</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1928"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2225"/>
<source>Tile size [px]</source>
<translation>Kachengröße [px]</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1929"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2226"/>
<source>Tile size [mu]</source>
<translation>Kachengröße [KE]</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1930"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2227"/>
<source>Matrix size</source>
<translation>Matrixgröße</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1931"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2228"/>
<source>Matrix extent [mu]</source>
<translation>Matrixgrenzen [KE]</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1932"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2229"/>
<source>Bounds</source>
<translation>Grenzen</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1933"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2230"/>
<source>Width</source>
<translation>Breite</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1934"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2231"/>
<source>Height</source>
<translation>Höhe</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1935"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2232"/>
<source>Top</source>
<translation>Oben</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1936"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2233"/>
<source>Left</source>
<translation>Links</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1937"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2234"/>
<source>Bottom</source>
<translation>Unten</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1938"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2235"/>
<source>Right</source>
<translation>Rechts</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1968"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1994"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2265"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2291"/>
<source>%n missing row(s)</source>
<translation>%n fehlende Zeilen</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1969"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2266"/>
<source>Layer's upper bound: %1</source>
<translation>Obere Begrenzung des Layers: %1</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1981"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2007"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2278"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2304"/>
<source>%n missing column(s)</source>
<translation>%n fehlende Spalten</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1982"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2279"/>
<source>Layer's left bound: %1</source>
<translation>Linke Begrenzung des Layers: %1</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="1995"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2292"/>
<source>Layer's lower bound: %1</source>
<translation>Untere Begrenzung des Layers: %1</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2008"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2305"/>
<source>Layer's right bound: %1</source>
<translation>Rechte Begrenzung des Layers: %1</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2025"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2322"/>
<source>Cache stats</source>
<translation>Cache-Statistik</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2038"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2335"/>
<source>Hits</source>
<translation>Treffer</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2044"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2341"/>
<source>Misses</source>
<translation>Fehlgriffe</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2050"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2347"/>
<source>Errors</source>
<translation>Fehler</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2073"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2370"/>
<source>Format not supported</source>
<translation>Format nicht unterstützt</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2093"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2390"/>
<source>Context not fully specified (extent was defined but width and/or height was not).</source>
<translation>Kontext nicht vollständig angegeben (Ausmaß wurde definiert, aber Breite und Höhe nicht).</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2429"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2726"/>
<source>Get feature info request error (Title:%1; Error:%2; URL: %3)</source>
<translation>Abfrageanfragefehler (Titel:%1; Fehler: %2; URL: %3)</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2551"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2848"/>
<source>GML schema is not valid</source>
<translation>GML-Schema ist ungültig</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2557"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2854"/>
<source>GML is not valid</source>
<translation>GML ist ungültig</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2571"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2646"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2868"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2943"/>
<source>Cannot identify</source>
<translation>Abfrage gescheitert</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2647"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2944"/>
<source>Result parsing failed. %1 feature types were guessed from gml (%2) but no features were parsed.</source>
<translation>Ergebnisüberprüfung fehlgeschlagen. %1 Objekttypen wurden aus dem gml (%2) geraten aber keine Objekte wurden analysiert.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2804"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3102"/>
<source>identify request redirected.</source>
<translation>Identify-Anfrage umgeleitet.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2820"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3119"/>
<source>Map getfeatureinfo error %1: %2</source>
<translation>GetFeatureInfo-Fehler %1: %2</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2829"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3128"/>
<source>Cannot parse getfeatureinfo: %1</source>
<translation>Konnte GetFeatureInfo nicht interpretieren: %1</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="2844"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3143"/>
<source>Map getfeatureinfo error: %1 [%2]</source>
<translation>GetFeatureInfo-Fehler %1 [%2]</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3179"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3476"/>
<source>%1 of %2 bytes of GetLegendGraphic downloaded.</source>
<translation>%1 von %2 Bytes der Legendengrafik heruntergeladen.</translation>
</message>
@@ -84304,44 +85128,44 @@ Antwort war:
<context>
<name>QgsWmsTiledImageDownloadHandler</name>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3486"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3825"/>
<source>Tile request error</source>
<translation>Tile-Anfragefehler</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3486"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3825"/>
<source>Status: %1
Reason phrase: %2</source>
<translation>Status: %1
Grund: %2</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3506"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3845"/>
<source>Tile request error (Title:%1; Error:%2; URL: %3)</source>
<translation>Kachelabfrage-Fehler (Titel: %1; Fehler: %2; URL: %3)</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3508"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3516"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3569"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3617"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3635"/>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3644"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3847"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3855"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3913"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3978"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3996"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="4005"/>
<source>WMS</source>
<translation>WMS</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3512"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3851"/>
<source>Tile request error (Status:%1; Content-Type:%2; Length:%3; URL: %4)</source>
<translation>Kachelabfrage-Fehler (Status: %1; Content-Typ: %2; Länge: %3; URL: %4)</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3568"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3912"/>
<source>Returned image is flawed [Content-Type:%1; URL: %2]</source>
<translation>Geladenes Bild ist defekt [Content-Type:%1; URL: %2]</translation>
</message>
<message numerus="yes">
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3602"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3953"/>
<source>%n tile requests in background</source>
<comment>tile request count</comment>
<translation>
@@ -84350,7 +85174,7 @@ Grund: %2</translation>
</translation>
</message>
<message numerus="yes">
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3603"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3954"/>
<source>, %n cache hits</source>
<comment>tile cache hits</comment>
<translation>
@@ -84359,7 +85183,7 @@ Grund: %2</translation>
</translation>
</message>
<message numerus="yes">
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3604"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3955"/>
<source>, %n cache misses.</source>
<comment>tile cache missed</comment>
<translation>
@@ -84368,7 +85192,7 @@ Grund: %2</translation>
</translation>
</message>
<message numerus="yes">
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3605"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3956"/>
<source>, %n errors.</source>
<comment>errors</comment>
<translation>
@@ -84377,17 +85201,17 @@ Grund: %2</translation>
</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3617"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3978"/>
<source>Not logging more than 100 request errors.</source>
<translation>Nicht mehr als 100 Abfragefehler werden protokolliert.</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3634"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3995"/>
<source>Tile request max retry error. Failed %1 requests for tile %2 of tileRequest %3 (url: %4)</source>
<translation>Maximale Wiederholungen erreicht. %1 Abfragen der Kachel %2 der Kachelabfrage %3 (url: %4)</translation>
</message>
<message>
- <location filename="../src/providers/wms/qgswmsprovider.cpp" line="3643"/>
+ <location filename="../src/providers/wms/qgswmsprovider.cpp" line="4004"/>
<source>repeat tileRequest %1 tile %2(retry %3)</source>
<translation>Wiederhole Kachelabfrage %1, Kachel %2 (Wiederholung %3)</translation>
</message>
@@ -84422,6 +85246,38 @@ Grund: %2</translation>
</message>
</context>
<context>
+ <name>QgsXyzLayerItem</name>
+ <message>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="540"/>
+ <source>Delete</source>
+ <translation>Löschen</translation>
+ </message>
+</context>
+<context>
+ <name>QgsXyzTileRootItem</name>
+ <message>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="501"/>
+ <source>New Connection...</source>
+ <translation>Neue Verbindung...</translation>
+ </message>
+ <message>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="508"/>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="513"/>
+ <source>New XYZ tile layer</source>
+ <translation>Neuer XYZ-Kachellayer</translation>
+ </message>
+ <message>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="509"/>
+ <source>Please enter XYZ tile layer URL. {x}, {y}, {z} will be replaced by actual tile coordinates.</source>
+ <translation>Bitte XYZ-Kachellayer URL eingeben. {x}, {y}, {z} werden durch die tatsächliche Kachelkoordinaten ersetzt.</translation>
+ </message>
+ <message>
+ <location filename="../src/providers/wms/qgswmsdataitems.cpp" line="514"/>
+ <source>Please enter name of the tile layer:</source>
+ <translation>Bitte Name des Kachellayers angeben:</translation>
+ </message>
+</context>
+<context>
<name>QgsZonalStatisticsDialog</name>
<message>
<location filename="../src/plugins/zonal_statistics/qgszonalstatisticsdialog.cpp" line="32"/>
@@ -84555,41 +85411,41 @@ Grund: %2</translation>
<context>
<name>RAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2349"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2382"/>
<source>[Unnamed algorithm]</source>
<translation>[Unbenannte Algorithmen]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2350"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2383"/>
<source>User R scripts</source>
<translation>R-Benutzerskripte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2351"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2384"/>
<source>Could not load R script: %s.
Problem with line %s</source>
<translation>Konnte R-Skript nicht laden: %s.
Problem mit Zeile %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2352"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2385"/>
<source>R Console Output</source>
<translation>R-Konsolenausgabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2353"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2386"/>
<source>R folder is not configured.
Please configure it before running R scripts.</source>
<translation>R-Verzeichnis nicht konfiguriert.
Bitte vor der Ausführung von R-Skripten einstellen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2354"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2387"/>
<source>R execution commands</source>
<translation>R-Befehlsausführung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2355"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2388"/>
<source><p>This algorithm requires R to be run. Unfortunately it seems that R is not installed in your system or it is not correctly configured to be used from QGIS</p><p><a href="http://docs.qgis.org/testing/en/docs/user_manual/processing/3rdParty.html">Click here</a> to know more about how to install and configure R to be used with QGIS</p></source>
<translation><p>Dieser Algorithmus erfordert die Ausführung von R. Leider scheint R nicht richtig für die Verwendung in QGIS installiert oder konfiguriert zu sein</p><p><a href="http://docs.qgis.org/testing/en/docs/user_manual/processing/3rdParty.html">Hier klicken</a> um mehr zur Installation und Konfiguration von R für QGIS zu erfahren</p></translation>
</message>
@@ -84597,27 +85453,27 @@ Bitte vor der Ausführung von R-Skripten einstellen.</translation>
<context>
<name>RAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2359"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2392"/>
<source>R Scripts folder</source>
<translation>R-Skriptverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2360"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2393"/>
<source>R folder</source>
<translation>R-Verzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2361"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2394"/>
<source>R user library folder</source>
<translation>R-Benutzerbibliotheksverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2362"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2395"/>
<source>Use 64 bit version</source>
<translation>64bit-Version verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2363"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2396"/>
<source>Could not load R script: %s
%s</source>
<translation>Konnte R-Skript nicht laden: %s
@@ -84627,25 +85483,25 @@ Bitte vor der Ausführung von R-Skripten einstellen.</translation>
<context>
<name>RUtils</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2367"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2400"/>
<source>R execution console output</source>
<translation>Konsolenausgabe aus R-Ausführung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2368"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2401"/>
<source><h2>R Output</h2>
</source>
<translation><h2>R-Ausgabe</h2></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2369"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2402"/>
<source>R folder is not configured.
Please configure it before running R scripts.</source>
<translation>R-Verzeichnis nicht konfiguriert.
Bitte vor der Ausführung von R-Skripten einstellen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2370"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2403"/>
<source><p>This algorithm requires R to be run. Unfortunately, it seems that R is not installed in your system, or it is not correctly configured to be used from QGIS</p><p><a href="http://docs.qgis.org/testing/en/docs/user_manual/processing/3rdParty.html">Click here</a> to know more about how to install and configure R to be used with QGIS</p></source>
<translation><p>Dieser Algorithmus erfordert die Ausführung von R. Leider scheint R nicht richtig für die Verwendung in QGIS installiert oder konfiguriert zu sein</p><p><a href="http://docs.qgis.org/testing/en/docs/user_manual/processing/3rdParty.html">Hier klicken</a> um mehr zur Installation und Konfiguration von R für QGIS zu erfahren</p></translation>
</message>
@@ -84653,52 +85509,52 @@ Bitte vor der Ausführung von R-Skripten einstellen.</translation>
<context>
<name>RandomExtract</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2375"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2408"/>
<source>Vector selection tools</source>
<translation>Vektorauswahlwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2376"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2409"/>
<source>Number of selected features</source>
<translation>Anzahl gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2377"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2410"/>
<source>Percentage of selected features</source>
<translation>Prozentsatz gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2378"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2411"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2379"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2412"/>
<source>Method</source>
<translation>Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2380"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2413"/>
<source>Number/percentage of selected features</source>
<translation>Anzahl/Prozentsatz gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2381"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2414"/>
<source>Extracted (random)</source>
<translation>Extrahiert (zufällig)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2382"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2415"/>
<source>Selected number is greater than feature count. Choose a lower value and try again.</source>
<translation>Die gewählte Zahl ist größer als die Objektanzahl. Kleineren Wert wählen und wiederholen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2383"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2416"/>
<source>Percentage can't be greater than 100. Set a different value and try again.</source>
<translation>Prozentsatz kann nicht größer 100 sein. Anderen Wert wählen und wiederholen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2374"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2407"/>
<source>Random extract</source>
<translation>Zufälliger Ausschnitt</translation>
</message>
@@ -84706,57 +85562,57 @@ Bitte vor der Ausführung von R-Skripten einstellen.</translation>
<context>
<name>RandomExtractWithinSubsets</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2388"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2421"/>
<source>Vector selection tools</source>
<translation>Vektorauswahlwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2389"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2422"/>
<source>Number of selected features</source>
<translation>Anzahl gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2390"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2423"/>
<source>Percentage of selected features</source>
<translation>Prozentsatz gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2391"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2424"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2392"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2425"/>
<source>ID field</source>
<translation>Kennungsfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2393"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2426"/>
<source>Method</source>
<translation>Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2394"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2427"/>
<source>Number/percentage of selected features</source>
<translation>Anzahl/Prozentsatz gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2395"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2428"/>
<source>Extracted (random stratified)</source>
<translation>Extrahiert (zufällig geschichtet)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2396"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2429"/>
<source>Selected number is greater that feature count. Choose lesser value and try again.</source>
<translation>Die gewählte Zahl ist größer als die Objektanzahl. Kleineren Wert wählen und wiederholen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2397"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2430"/>
<source>Percentage can't be greater than 100. Set correct value and try again.</source>
<translation>Prozentsatz kann nicht größer 100 sein. Anderen Wert wählen und wiederholen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2387"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2420"/>
<source>Random extract within subsets</source>
<translation>Zufällige Auswahl in Untermengen</translation>
</message>
@@ -84764,38 +85620,38 @@ Bitte vor der Ausführung von R-Skripten einstellen.</translation>
<context>
<name>RandomPointsAlongLines</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2402"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2435"/>
<source>Vector creation tools</source>
<translation>Vektorerzeugungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2403"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2436"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2404"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2437"/>
<source>Number of points</source>
<translation>Anzahl von Punkten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2405"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2438"/>
<source>Minimum distance</source>
<translation>Minimalabstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2406"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2439"/>
<source>Random points</source>
<translation>Zufällige Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2407"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2440"/>
<source>Can not generate requested number of random points. Maximum number of attempts exceeded.</source>
<translation>Kann angeforderte Anzahl von zufälligen Punkte nicht erzeugen.
Maximalzahl der Versuche überschritten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2401"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2434"/>
<source>Random points along line</source>
<translation>Zufällige Punkte entlang einer Linie</translation>
</message>
@@ -84803,38 +85659,38 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RandomPointsExtent</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2412"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2445"/>
<source>Vector creation tools</source>
<translation>Vektorerzeugungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2413"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2446"/>
<source>Input extent</source>
<translation>Eingabeabmessungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2414"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2447"/>
<source>Points number</source>
<translation>Punktanzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2415"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2448"/>
<source>Minimum distance</source>
<translation>Minimalabstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2416"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2449"/>
<source>Random points</source>
<translation>Zufällige Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2417"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2450"/>
<source>Can not generate requested number of random points. Maximum number of attempts exceeded.</source>
<translation>Kann angeforderte Anzahl von zufälligen Punkte nicht erzeugen.
Maximalzahl der Versuche überschritten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2411"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2444"/>
<source>Random points in extent</source>
<translation>Zufällige Punkte in Grenzen</translation>
</message>
@@ -84842,38 +85698,38 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RandomPointsLayer</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2422"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2455"/>
<source>Vector creation tools</source>
<translation>Vektorerzeugungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2423"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2456"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2424"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2457"/>
<source>Points number</source>
<translation>Punktanzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2425"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2458"/>
<source>Minimum distance</source>
<translation>Minimalabstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2426"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2459"/>
<source>Random points</source>
<translation>Zufällige Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2427"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2460"/>
<source>Can not generate requested number of random points. Maximum number of attempts exceeded.</source>
<translation>Kann angeforderte Anzahl von zufälligen Punkte nicht erzeugen.
Maximalzahl der Versuche überschritten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2421"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2454"/>
<source>Random points in layer bounds</source>
<translation>Zufällige Punkte in den Layergrenzen</translation>
</message>
@@ -84881,53 +85737,53 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RandomPointsPolygonsFixed</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2432"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2465"/>
<source>Vector creation tools</source>
<translation>Vektorerzeugungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2433"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2466"/>
<source>Points count</source>
<translation>Punktanzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2434"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2467"/>
<source>Points density</source>
<translation>Punktdichte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2435"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2468"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2436"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2469"/>
<source>Sampling strategy</source>
<translation>Abtaststrategie</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2437"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2470"/>
<source>Number or density of points</source>
<translation>Anzahl der Dichtepunkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2438"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2471"/>
<source>Minimum distance</source>
<translation>Minimalabstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2439"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2472"/>
<source>Random points</source>
<translation>Zufällige Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2440"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2473"/>
<source>Can not generate requested number of random points. Maximum number of attempts exceeded.</source>
<translation>Kann angeforderte Anzahl von zufälligen Punkte nicht erzeugen.
Maximalzahl der Versuche überschritten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2431"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2464"/>
<source>Random points inside polygons (fixed)</source>
<translation>Zufällige Punkte in Polygonen (festgelegt)</translation>
</message>
@@ -84935,53 +85791,53 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RandomPointsPolygonsVariable</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2445"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2478"/>
<source>Vector creation tools</source>
<translation>Vektorerzeugungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2446"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2479"/>
<source>Points count</source>
<translation>Punktanzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2447"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2480"/>
<source>Points density</source>
<translation>Punktdichte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2448"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2481"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2449"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2482"/>
<source>Sampling strategy</source>
<translation>Abtaststrategie</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2450"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2483"/>
<source>Number field</source>
<translation>Nummernfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2451"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2484"/>
<source>Minimum distance</source>
<translation>Minimalabstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2452"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2485"/>
<source>Random points</source>
<translation>Zufällige Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2453"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2486"/>
<source>Can not generate requested number of random points. Maximum number of attempts exceeded.</source>
<translation>Kann angeforderte Anzahl von zufälligen Punkte nicht erzeugen.
Maximalzahl der Versuche überschritten.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2444"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2477"/>
<source>Random points inside polygons (variable)</source>
<translation>Zufällige Punkte in Polygonen (variable)</translation>
</message>
@@ -84989,52 +85845,52 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RandomSelection</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2458"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2491"/>
<source>Vector selection tools</source>
<translation>Vektorauswahlwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2459"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2492"/>
<source>Number of selected features</source>
<translation>Anzahl gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2460"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2493"/>
<source>Percentage of selected features</source>
<translation>Prozentsatz gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2461"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2494"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2462"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2495"/>
<source>Method</source>
<translation>Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2463"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2496"/>
<source>Number/percentage of selected features</source>
<translation>Anzahl/Prozentsatz gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2464"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2497"/>
<source>Selection</source>
<translation>Auswahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2465"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2498"/>
<source>Selected number is greater than feature count. Choose a lower value and try again.</source>
<translation>Die gewählte Zahl ist größer als die Objektanzahl. Kleineren Wert wählen und wiederholen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2466"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2499"/>
<source>Percentage can't be greater than 100. Set a different value and try again.</source>
<translation>Prozentsatz kann nicht größer 100 sein. Anderen Wert wählen und wiederholen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2457"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2490"/>
<source>Random selection</source>
<translation>Zufällige Auswahl</translation>
</message>
@@ -85042,57 +85898,57 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RandomSelectionWithinSubsets</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2471"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2504"/>
<source>Vector selection tools</source>
<translation>Vektorauswahlwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2472"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2505"/>
<source>Number of selected features</source>
<translation>Anzahl gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2473"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2506"/>
<source>Percentage of selected features</source>
<translation>Prozentsatz gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2474"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2507"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2475"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2508"/>
<source>ID Field</source>
<translation>ID Feld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2476"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2509"/>
<source>Method</source>
<translation>Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2477"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2510"/>
<source>Number/percentage of selected features</source>
<translation>Anzahl/Prozentsatz gewählter Objekte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2478"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2511"/>
<source>Selection stratified</source>
<translation>Geschichtete Auswahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2479"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2512"/>
<source>Selected number is greater that feature count. Choose lesser value and try again.</source>
<translation>Die gewählte Zahl ist größer als die Objektanzahl. Kleineren Wert wählen und wiederholen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2480"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2513"/>
<source>Percentage can't be greater than 100. Set a different value and try again.</source>
<translation>Prozentsatz kann nicht größer 100 sein. Anderen Wert wählen und wiederholen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2470"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2503"/>
<source>Random selection within subsets</source>
<translation>Zufällige Auswahl in Untermengen</translation>
</message>
@@ -85100,42 +85956,42 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RasterLayerBoundsAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2484"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2517"/>
<source>Raster layer bounds</source>
<translation>Rasterlayer Grenzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2485"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2518"/>
<source>Modeler-only tools</source>
<translation>Modell Werkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2486"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2519"/>
<source>Layer</source>
<translation>Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2487"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2520"/>
<source>min X</source>
<translation>min X</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2488"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2521"/>
<source>max X</source>
<translation>max X</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2489"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2522"/>
<source>min Y</source>
<translation>min Y</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2490"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2523"/>
<source>max Y</source>
<translation>max Y</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2491"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2524"/>
<source>Extent</source>
<translation>Umfang</translation>
</message>
@@ -85143,32 +85999,32 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RasterLayerHistogram</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2496"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2529"/>
<source>Graphics</source>
<translation>Grafik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2497"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2530"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2498"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2531"/>
<source>Number of bins</source>
<translation>Anzahl von bins</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2499"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2532"/>
<source>Histogram</source>
<translation>Histogramm</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2500"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2533"/>
<source>Table</source>
<translation>Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2495"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2528"/>
<source>Raster layer histogram</source>
<translation>Rasterlayerhistogramm</translation>
</message>
@@ -85176,57 +86032,57 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RasterLayerStatistics</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2505"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2538"/>
<source>Raster tools</source>
<translation>Rasterwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2506"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2539"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2507"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2540"/>
<source>Statistics</source>
<translation>Statistik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2508"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2541"/>
<source>Minimum value</source>
<translation>Minimalwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2509"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2542"/>
<source>Maximum value</source>
<translation>Maximalwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2510"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2543"/>
<source>Sum</source>
<translation>Summe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2511"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2544"/>
<source>Mean value</source>
<translation>Mittelwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2512"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2545"/>
<source>valid cells count</source>
<translation>Anzahl von gültigen Zellen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2513"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2546"/>
<source>No-data cells count</source>
<translation>Anzahl von NoData Zellen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2514"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2547"/>
<source>Standard deviation</source>
<translation>Standardabweichung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2504"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2537"/>
<source>Raster layer statistics</source>
<translation>Rasterlayerstatistik</translation>
</message>
@@ -85243,62 +86099,62 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RectanglesOvalsDiamondsFixed</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2518"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2551"/>
<source>Rectangles, ovals, diamonds (fixed)</source>
<translation>Rechtecke, Ovale, Rauten (fest)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2519"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2552"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2520"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2553"/>
<source>Rectangles</source>
<translation>Rechtecke</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2521"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2554"/>
<source>Diamonds</source>
<translation>Rauten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2522"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2555"/>
<source>Ovals</source>
<translation>Ovale</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2523"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2556"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2524"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2557"/>
<source>Buffer shape</source>
<translation>Formpuffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2525"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2558"/>
<source>Width</source>
<translation>Breite</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2526"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2559"/>
<source>Height</source>
<translation>Höhe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2527"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2560"/>
<source>Rotation</source>
<translation>Drehung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2528"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2561"/>
<source>Number of segments</source>
<translation>Segmentanzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2529"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2562"/>
<source>Output</source>
<translation>Ausgabe</translation>
</message>
@@ -85306,72 +86162,72 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RectanglesOvalsDiamondsVariable</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2533"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2566"/>
<source>Rectangles, ovals, diamonds (variable)</source>
<translation>Rechtecke, Ovale, Rauten (variabel)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2534"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2567"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2535"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2568"/>
<source>Rectangles</source>
<translation>Rechtecke</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2536"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2569"/>
<source>Diamonds</source>
<translation>Rauten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2537"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2570"/>
<source>Ovals</source>
<translation>Ovale</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2538"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2571"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2539"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2572"/>
<source>Buffer shape</source>
<translation>Formpuffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2540"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2573"/>
<source>Width field</source>
<translation>Breitenfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2541"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2574"/>
<source>Height field</source>
<translation>Höhenfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2542"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2575"/>
<source>Rotation field</source>
<translation>Drehungsfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2543"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2576"/>
<source>Number of segments</source>
<translation>Segmentanzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2544"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2577"/>
<source>Output</source>
<translation>Ausgabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2545"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2578"/>
<source>Feature {} has empty width, height or angle. Skipping...</source>
<translation>Überspringe Objekt {} mit leerer Breite, Höhe oder Winkel...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2546"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2579"/>
<source>Feature {} has empty width or height. Skipping...</source>
<translation>Objekt {} mit leerer Breite oder Höhe übersprungen...</translation>
</message>
@@ -85379,37 +86235,37 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RegularPoints</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2551"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2584"/>
<source>Vector creation tools</source>
<translation>Vektorerzeugungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2552"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2585"/>
<source>Input extent</source>
<translation>Eingabeabmessungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2553"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2586"/>
<source>Point spacing/count</source>
<translation>Punktabstände/-anzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2554"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2587"/>
<source>Initial inset from corner (LH side)</source>
<translation>Anfängliche Einsatz von Ecke (linke Seite)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2555"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2588"/>
<source>Apply random offset to point spacing</source>
<translation>Zufälligen Versatz auf Punktabstand anwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2556"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2589"/>
<source>Use point spacing</source>
<translation>Benutze Punktabstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2550"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2583"/>
<source>Regular points</source>
<translation>Regelmäßige Punkte</translation>
</message>
@@ -85417,12 +86273,12 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>RenderingStyleFilePanel</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2560"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2593"/>
<source>Select style file</source>
<translation>Wähle Stildatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2561"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2594"/>
<source>QGIS Layer Style File (*.qml *.QML)</source>
<translation>QGIS Layerstildatei (*.qml *.QML)</translation>
</message>
@@ -85430,27 +86286,27 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>ReprojectLayer</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2566"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2599"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2567"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2600"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2568"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2601"/>
<source>Target CRS</source>
<translation>Ziel KBS</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2569"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2602"/>
<source>Reprojected</source>
<translation>Reprojiiziert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2565"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2598"/>
<source>Reproject layer</source>
<translation>Layer reprojizieren</translation>
</message>
@@ -85458,27 +86314,27 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>ReverseLineDirection</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2573"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2606"/>
<source>Reverse line direction</source>
<translation>Linienrichtung umgekehren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2574"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2607"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2575"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2608"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2576"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2609"/>
<source>Reversed</source>
<translation>Umgekehrt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2577"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2610"/>
<source>Error reversing line</source>
<translation>Fehler bei Linienumkehrung</translation>
</message>
@@ -85693,59 +86549,59 @@ Maximalzahl der Versuche überschritten.</translation>
<translation>Hilfe</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="243"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="237"/>
<source>Point not selected</source>
<translation>Punkt nicht gewählt</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="243"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="237"/>
<source>First, select start and stop points.</source>
<translation>Zuerst Start- und Endpunkte wählen.</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="255"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="249"/>
<source>Plugin isn't configured</source>
<translation>Erweiterung is nicht konfiguriert</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="255"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="249"/>
<source>Plugin isn't configured! Please go to the Vector menu, Road Graph, Settings option to configure it.</source>
<translation>Erweiterung ist nicht konfiguriert. Bitte unter Vektor/Straßengraph/Einstellungen konfigurieren.</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="276"/>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="281"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="270"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="275"/>
<source>Tie point failed</source>
<translation>Punktzuordnung fehlgeschlagen</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="276"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="270"/>
<source>Start point doesn't tie to the road!</source>
<translation>Startpunkt konnte keiner Straße zugeordnet werden!</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="281"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="275"/>
<source>Stop point doesn't tie to the road!</source>
<translation>Endpunkt konnte keiner Straße zugeordnet werden!</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="291"/>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="308"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="285"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="302"/>
<source>Cannot calculate path</source>
<translation>Kann Weg nicht berechnen</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="309"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="303"/>
<source>The created graph is empty. Please check your input data.</source>
<translation>Der erzeugte Graph ist leer. Bitte prüfen die Eingabe prüfen.</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="325"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="319"/>
<source>Path not found</source>
<translation>Pfad nicht gefunden</translation>
</message>
<message>
- <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="292"/>
+ <location filename="../src/plugins/roadgraph/shortestpathwidget.cpp" line="286"/>
<source>Could not find start vertex. Please check your input data.</source>
<translation>Konnte Startstützpunkt nicht finden. Bitte Eingabedaten überprüfen.</translation>
</message>
@@ -85772,1307 +86628,1307 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>SAGAAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="435"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="242"/>
<source>Slope Length</source>
<translation>Hanglänge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="574"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="252"/>
<source>Shapes Buffer (Attribute distance)|Shapes Buffer</source>
<translation>Shapepuffer (Attributabstand)|Shapepuffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="575"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="166"/>
<source>Representativeness|Representativeness (Grid)</source>
<translation>Repräsentativität|Repräsentativität (Raster)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="516"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="16"/>
<source>Gaussian Filter</source>
<translation>Gauss'scher Filter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="463"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="246"/>
<source>Flow Accumulation (Top-Down)</source>
<translation>Flußdichte (Oben-Unten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="522"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="232"/>
<source>Convex Hull</source>
<translation>Konvexe Hülle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="361"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="86"/>
<source>Flow Accumulation (Recursive)</source>
<translation>Flußdichte (Rekursiv)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="446"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="101"/>
<source>Polygon Centroids</source>
<translation>Polygonschwerpunkt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="409"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="173"/>
<source>Flow Accumulation (Flow Tracing)</source>
<translation>Flußdichte (Flußverfolgung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="547"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="213"/>
<source>Point Statistics for Polygons</source>
<translation>Polygon-Punktstatistik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="416"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="107"/>
<source>Grid Values to Points (randomly)</source>
<translation>Gitterwerte zu Punkten (zufällig)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="576"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="143"/>
<source>Clip Points with Polygons</source>
<translation>Punkte auf Polygon zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="495"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="112"/>
<source>Gradient Vectors from Direction and Length</source>
<translation>Gradientenvektor aus Richtung und Länge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="461"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="161"/>
<source>Grid Statistics for Polygons</source>
<translation>Gitterstatistik für Polygone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="603"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="176"/>
<source>Layer of extreme value</source>
<translation>Extrema-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="549"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="174"/>
<source>Create Graticule</source>
<translation>Gradnetz erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="430"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="102"/>
<source>Difference</source>
<translation>Differenz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="531"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="26"/>
<source>Clip Grid with Polygon</source>
<translation>Punkte auf Polygon zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="442"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="192"/>
<source>Crop to Data</source>
<translation>Auf Daten zuschneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="405"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="168"/>
<source>Close Gaps</source>
<translation>Lücken schließen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="431"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="267"/>
<source>Polygon Clipping</source>
<translation>Polygonclipping</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="473"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="152"/>
<source>Multiresolution Index of Valley Bottom Flatness (MRVBF)</source>
<translation>Mehrauflösung-Talbodenebenheitsindex (MRVBF)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="600"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="218"/>
<source>Flatten Polygon Layer</source>
<translation>Polygonlayer glätten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="401"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="235"/>
<source>Shared Polygon Edges</source>
<translation>Gemeinsame Polygonkanten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="481"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="83"/>
<source>Add Point Attributes to Polygons</source>
<translation>Punktattribute zu Polygonen hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="514"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="207"/>
<source>Polygon Self-Intersection</source>
<translation>Polygonselbstüberschneidungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="440"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="35"/>
<source>Gradient Vectors from Surface</source>
<translation>Gradientenvektor aus Oberfläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="418"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="19"/>
<source>GWR for Multiple Predictor Grids</source>
<translation>GWR für mehrere Vorsagegitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="533"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="212"/>
<source>Multiple Regression Analysis (Points/Grids)</source>
<translation>Mehrfach-Regressionsanalyse (Punkt/Raster)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="546"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="206"/>
<source>Hypsometry</source>
<translation>Hypsometrie</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="462"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="209"/>
<source>Aggregation Index</source>
<translation>Aggregationsindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="492"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="240"/>
<source>Identity</source>
<translation>Identität</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="372"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="219"/>
<source>LS Factor</source>
<translation>LS-Faktor</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="482"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="208"/>
<source>DTM Filter (slope-based)</source>
<translation>DTM-Filter (Hangbasiert)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="571"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="134"/>
<source>Effective Air Flow Heights</source>
<translation>Effektive Luftflußhöhen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="419"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="156"/>
<source>Add Grid Values to Points</source>
<translation>Gitterwerte zu Punkten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="410"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="76"/>
<source>Kernel Density Estimation</source>
<translation>Kerndichtenschätzung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="512"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="109"/>
<source>Grid Cell Index</source>
<translation>Gitterzellenindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="375"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="74"/>
<source>Mass Balance Index</source>
<translation>Gleichgewichtsindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="543"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="11"/>
<source>Transform Shapes</source>
<translation>Shapes transformieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="507"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="68"/>
<source>Regression analysis|Regression Analysis (Points/Grid)</source>
<translation>Regressionanalyse|Regressionsanalyse (Punkte/Raster)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="417"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="34"/>
<source>Polygon Properties</source>
<translation>Polygoneigenschaften</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="521"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="243"/>
<source>Geographically Weighted Multiple Regression</source>
<translation>Geografischgewichtete Mehrfach-Regression</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="505"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="38"/>
<source>GWR for Multiple Predictors (Gridded Model Output)</source>
<translation>GWR für mehrere Vorsagegitter (Gerasterte Modellausgabe)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="398"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="93"/>
<source>Directional Statistics for Single Grid</source>
<translation>Richtungsstatistik für Einzelraster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="530"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="196"/>
<source>Fill Sinks|Fill Sinks (Planchon/Darboux, 2001)</source>
<translation>Senken füllen|Senken füllen (Planchon/Darboux, 2001)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="450"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="9"/>
<source>Grids Product</source>
<translation>Rasterprodukte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="458"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="25"/>
<source>Fill Gaps in Records</source>
<translation>Datensatzlücken füllen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="509"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="256"/>
<source>Topographic Correction</source>
<translation>Topographische Korrektur</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="590"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="50"/>
<source>Grid Buffer</source>
<translation>Gitterpuffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="449"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="184"/>
<source>Catchment Area (Flow Tracing)</source>
<translation>Einzugsbereich (Flußverfolgung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="356"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="185"/>
<source>User Defined Filter</source>
<translation>Benutzerdefinierter Filter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="438"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="39"/>
<source>Watershed Segmentation</source>
<translation>Niederschlagssegmentierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="380"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="115"/>
<source>Line Simplification</source>
<translation>Linienvereinfachung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="523"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="203"/>
<source>Convergence Index (Search Radius)</source>
<translation>Konvergenzindex (Suchradius)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="487"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="15"/>
<source>Topographic Wetness Index (TWI)</source>
<translation>Topographischer Niederschlagsindex (TWI)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="468"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="258"/>
<source>Upslope Area|4</source>
<translation>Anstieg Areal4</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="542"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="31"/>
<source>Laplacian Filter</source>
<translation>Laplace-Filter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="384"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="63"/>
<source>Grid Proximity Buffer</source>
<translation>Gitterannährungspuffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="613"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="163"/>
<source>Aggregate Point Observations</source>
<translation>Punktbeobachtung sammeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="420"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="111"/>
<source>Transpose Grids</source>
<translation>Gitter transponieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="506"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="165"/>
<source>Topographic Position Index (TPI)</source>
<translation>Topographische Position (TPI)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="536"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="245"/>
<source>Grid Masking</source>
<translation>Gittermaskierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="563"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="113"/>
<source>Channel Network and Drainage Basins</source>
<translation>Kanalnetzwerk und Drainagebecken</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="365"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="20"/>
<source>Real Surface Area</source>
<translation>Echte Oberfläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="504"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="147"/>
<source>Threshold Buffer</source>
<translation>Schwellenpuffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="573"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="227"/>
<source>Add Grid Values to Shapes</source>
<translation>Gitterwerte zu Shapes hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="452"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="248"/>
<source>QuadTree Structure to Shapes</source>
<translation>Quad-Tree-Struktur zu Shapes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="490"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="155"/>
<source>Analytical Hillshading</source>
<translation>Analytische Schummerung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="609"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="48"/>
<source>Surface Specific Points</source>
<translation>Oberflächen spezifische Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="451"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="262"/>
<source>Transect through polygon shapefile</source>
<translation>Durch Polygonshapedateien schneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="556"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="224"/>
<source>Convert Lines to Polygons</source>
<translation>Linien in Polygone umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="364"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="257"/>
<source>Local Minima and Maxima</source>
<translation>Lokale Minima und Maxima</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="586"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="238"/>
<source>Accumulated Cost (Isotropic)</source>
<translation>Aufgelaufenen Kosten (isotropisch)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="484"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="211"/>
<source>Line Dissolve</source>
<translation>Linien auflösen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="513"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="122"/>
<source>Resampling</source>
<translation>Abtastung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="545"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="124"/>
<source>Fuzzy Union (OR)</source>
<translation>Fuzzy-Vereinigung (ODER)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="423"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="52"/>
<source>Natural Neighbour</source>
<translation>Natürlicher Nachbar</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="360"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="45"/>
<source>Convert Lines to Points</source>
<translation>Linien in Punkten umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="612"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="189"/>
<source>Thin Plate Spline (Global)</source>
<translation>Thin Plate Spline (global)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="589"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="222"/>
<source>Polygon dissolve (by attribute)|Polygon Dissolve</source>
<translation>Polygon auflösen (nach Attribut)|Polygon auflösen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="369"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="90"/>
<source>Stream Power Index</source>
<translation>Stromstärkeindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="529"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="62"/>
<source>Global Moran's I for Grids</source>
<translation>Global Moran I für Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="552"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="43"/>
<source>Polynomial Regression</source>
<translation>Polynominalregression</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="444"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="145"/>
<source>Multiple Regression Analysis (Grid/Grids)</source>
<translation>Mehrfach-Regressionsanalyse (Gitter)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="606"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="96"/>
<source>Nearest Neighbour</source>
<translation>Nächster Nachbar</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="489"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="249"/>
<source>Water Retention Capacity</source>
<translation>Bodenwasserspannungskapazität</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="578"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="234"/>
<source>Gradient Vectors from Directional Components</source>
<translation>Gradientenvektoren aus gerichteten Komponenten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="377"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="79"/>
<source>Majority Filter</source>
<translation>Mehrheitsfilter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="568"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="57"/>
<source>Flow Path Length</source>
<translation>Fließweglänge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="429"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="237"/>
<source>Simple Region Growing</source>
<translation>Einfaches Region-Growing</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="433"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="148"/>
<source>Simulation</source>
<translation>Simulation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="443"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="142"/>
<source>Get Shapes Extents</source>
<translation>Shapeausmaße bestimmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="550"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="144"/>
<source>Union</source>
<translation>Vereinigungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="445"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="78"/>
<source>Fill Sinks XXL (Wang & Liu)</source>
<translation>Senken füllen XXL (Wang & Liu)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="526"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="65"/>
<source>B-Spline Approximation</source>
<translation>B-Spline-Approximation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="359"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="146"/>
<source>Polygon Parts to Separate Polygons</source>
<translation>Polygonteile in Einzelpolygone umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="460"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="226"/>
<source>Points Thinning</source>
<translation>Punkte ausdünnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="454"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="30"/>
<source>Change Date Format</source>
<translation>Datumsformat ändern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="601"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="195"/>
<source>Gradient Vector from Cartesian to Polar Coordinates</source>
<translation>Gradientenvektor aus kartesischen in Polar-Koordinaten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="404"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="61"/>
<source>Fragmentation Classes from Density and Connectivity</source>
<translation>Fragmentierungsklassen aus Dichte und Verbindungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="381"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="33"/>
<source>Ordinary Kriging</source>
<translation>Normales Krigen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="537"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="108"/>
<source>Grid Volume</source>
<translation>Rastervolumen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="367"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="13"/>
<source>Patching</source>
<translation>Zusammenflicken</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="553"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="59"/>
<source>Ordered Weighted Averaging|Ordered Weighted Averaging (OWA)</source>
<translation>Sortiertes gewichtetes Mitteln|Sortiertes gewichtetes Mitteln (OWA)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="587"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="126"/>
<source>Thin Plate Spline (TIN)</source>
<translation>Thin-Plate-Spline (TIN)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="528"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="178"/>
<source>SAGA Wetness Index</source>
<translation>SAGA Feuchtigkeitsindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="434"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="182"/>
<source>Histogram Surface</source>
<translation>Histogramm-Oberfläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="594"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="49"/>
<source>Merge Layers</source>
<translation>Layer zusammenführen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="499"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="202"/>
<source>Grid Skeletonization</source>
<translation>Rasterskelettierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="501"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="175"/>
<source>Catchment Area|Catchment Area (Parallel)</source>
<translation>Einzugsgebiet|Einzugsgebiet (Parallel)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="593"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="157"/>
<source>Geometric Figures</source>
<translation>Geometrische Figuren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="494"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="119"/>
<source>Spatial Point Pattern Analysis</source>
<translation>Räumliche Punktmusteranalyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="580"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="264"/>
<source>Update</source>
<translation>Aktualisieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="581"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="84"/>
<source>Sink Removal</source>
<translation>Ablauf entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="456"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="187"/>
<source>Convert Points to Line(s)</source>
<translation>Punkte in Linien umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="396"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="179"/>
<source>Change Grid Values</source>
<translation>Gitterwert ändern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="541"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="169"/>
<source>Line Properties</source>
<translation>Linieneigenschaften</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="422"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="233"/>
<source>Convert Multipoints to Points</source>
<translation>Multipunkt zu Punkt umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="544"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="97"/>
<source>Cell Balance</source>
<translation>Zellengleichgewicht</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="540"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="138"/>
<source>Fill Sinks (Wang & Liu)</source>
<translation>Senken füllen (Wang & Liu)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="583"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="193"/>
<source>Convert Data Storage Type</source>
<translation>Datenspeichertyp umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="478"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="70"/>
<source>Rank Filter</source>
<translation>Rangfilter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="479"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="159"/>
<source>Change Detection</source>
<translation>Erkennung ändern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="585"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="160"/>
<source>Strahler Order</source>
<translation>Strahler-Reihenfolge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="510"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="56"/>
<source>Inverse Distance Weighted</source>
<translation>gewichtete inverse Distanz (IDW)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="427"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="131"/>
<source>Multilevel B-Spline Interpolation (from Grid)</source>
<translation>Mehrstufen-B-Spline-Interpolation (aus Gitter)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="475"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="72"/>
<source>Geographically Weighted Multiple Regression (Points/Grids)</source>
<translation>Geografischgewichtete Mehrfach-Regression (Punkt/Gitter)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="515"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="172"/>
<source>Fast Region Growing Algorithm</source>
<translation>Schneller Regionswachstumalgorithmus</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="560"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="216"/>
<source>Terrain Ruggedness Index (TRI)</source>
<translation>Oberflächenrauhigkeit (TRI)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="432"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="127"/>
<source>GWR for Single Predictor Grid</source>
<translation>GWR für einzelnes Vorsagegitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="362"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="251"/>
<source>Points Filter</source>
<translation>Punktfilter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="599"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="140"/>
<source>Radius of Variance (Grid)</source>
<translation>Radius der Varianz (Gitter)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="577"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="54"/>
<source>Geographically Weighted Multiple Regression (Points)</source>
<translation>Geografischgewichtete Mehrfach-Regression (Punkte)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="592"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="40"/>
<source>Sink Drainage Route Detection</source>
<translation>Ablaufdrainageweg bestimmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="388"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="58"/>
<source>GWR for Single Predictor (Gridded Model Output)</source>
<translation>GWR für einzelnes Vorsagegitter (Gerasterte Modellausgabe)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="373"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="149"/>
<source>Cubic Spline Approximation</source>
<translation>Kubische Spline-Nährung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="483"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="37"/>
<source>Overland Flow Distance to Channel Network</source>
<translation>Überlandflußabstand zu Kanalnetzwerken</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="559"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="136"/>
<source>Shapes Buffer (Fixed distance)|Shapes Buffer</source>
<translation>Shapepuffer (fester Abstand)|Shapepuffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="534"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="266"/>
<source>Line-Polygon Intersection</source>
<translation>Linien-Polygon-Verschneidung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="511"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="18"/>
<source>Accumulated Cost (Anisotropic)</source>
<translation>Aufgelaufenen Kosten (Anisotropisch)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="579"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="132"/>
<source>Fragmentation (Alternative)</source>
<translation>Fragmentierung (Alternative)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="493"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="260"/>
<source>Principle Components Analysis</source>
<translation>Hauptkomponentenanalyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="368"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="128"/>
<source>Ordinary Kriging (Global)</source>
<translation>Normales Krigen (Global)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="485"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="114"/>
<source>Multi-Band Variation</source>
<translation>Mehrkanalvariation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="403"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="82"/>
<source>Universal Kriging (Global)</source>
<translation>Universeles Krigen (Global)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="471"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="73"/>
<source>Analytical Hierarchy Process</source>
<translation>Analytischer Hierachieprozeß</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="535"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="158"/>
<source>Diurnal Anisotropic Heating</source>
<translation>Anisotrope Erwärmung über Tag</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="595"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="69"/>
<source>Variogram Surface</source>
<translation>Variogramm-Oberfläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="470"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="91"/>
<source>Multi Direction Lee Filter</source>
<translation>Mehrrichtung-Lee-Filter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="363"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="121"/>
<source>Watershed Basins</source>
<translation>Einzugsgebietsbecken</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="447"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="66"/>
<source>Supervised Classification</source>
<translation>Überwachte Klassifizierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="455"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="44"/>
<source>Soil Texture Classification</source>
<translation>Bodentexturklassifizierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="413"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="24"/>
<source>Vectorising Grid Classes</source>
<translation>Vektorisierende Gitter-Klassen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="474"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="231"/>
<source>Modified Quadratic Shepard</source>
<translation>Modifizierte quadratische Shepard-Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="411"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="123"/>
<source>Variogram Cloud</source>
<translation>Variogramm Wolke</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="498"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="221"/>
<source>Vectorising Raster Classes</source>
<translation>Vektorisierene Rasterklassen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="582"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="194"/>
<source>Morphometric Protection Index</source>
<translation>Morphometrischer Schutzindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="374"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="220"/>
<source>Universal Kriging</source>
<translation>Universeles Krigen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="394"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="229"/>
<source>Raster calculator|Grid Calculator</source>
<translation>Rasterrechner|Rasterrechner</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="386"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="28"/>
<source>Grid Orientation</source>
<translation>Gitterrichtung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="421"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="265"/>
<source>Convergence Index</source>
<translation>Konvergenzindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="519"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="17"/>
<source>Shapes to Grid</source>
<translation>Shapes in Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="385"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="171"/>
<source>Land Surface Temperature</source>
<translation>Landoberflächentemperatur</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="436"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="205"/>
<source>Polygon dissolve (all polygons)|Polygon Dissolve</source>
<translation>Polygon auflösen (alle Polygone)|Polygon auflösen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="472"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="263"/>
<source>Flow Width and Specific Catchment Area</source>
<translation>Flußbreite und spezifisches Einzugsgebiet</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="569"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="106"/>
<source>Random Terrain Generation</source>
<translation>Zufälliges Gelände erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="379"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="60"/>
<source>Convert Polygons to Lines</source>
<translation>Polygon in Linien umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="415"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="153"/>
<source>Fuzzy Intersection (AND)</source>
<translation>Fuzzy-Schnittmenge (UND)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="397"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="36"/>
<source>Polygon Shape Indices</source>
<translation>Polygonshapeindizes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="520"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="22"/>
<source>Cluster Analysis for Grids</source>
<translation>Häufungsanalyse für Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="358"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="104"/>
<source>Burn Stream Network into DEM</source>
<translation>Stromnetzwerk in DEM brennen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="370"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="29"/>
<source>Relative Heights and Slope Positions</source>
<translation>Relative Höhen und Hangpositionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="391"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="230"/>
<source>Regression Kriging</source>
<translation>Regressionskrigen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="570"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="210"/>
<source>Simple Kriging</source>
<translation>Einfaches Krigen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="355"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="71"/>
<source>Fuzzify</source>
<translation>Fuzzifizieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="605"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="125"/>
<source>Catchment Area (Recursive)</source>
<translation>Einzugsbereich (Rekursiv)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="502"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="215"/>
<source>Convert Polygon/Line Vertices to Points</source>
<translation>Polygon-/Linienstützpunkte in Punkte umwandeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="538"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="67"/>
<source>Least Cost Paths</source>
<translation>Pfad geringster Kosten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="383"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="197"/>
<source>Split Shapes Layer Randomly</source>
<translation>Shapelayer zufällig aufteilen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="611"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="259"/>
<source>Grid Standardisation</source>
<translation>Gitterstandardisierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="400"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="239"/>
<source>Proximity Grid</source>
<translation>Näheraster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="392"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="129"/>
<source>Contour Lines from Grid</source>
<translation>Umrandungslinien aus Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="598"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="53"/>
<source>Fragmentation (Standard)</source>
<translation>Fragmentierung (Standard)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="500"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="41"/>
<source>Invert Data/No-Data</source>
<translation>Daten/Leerdaten invertieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="406"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="120"/>
<source>Vegetation Index (Slope Based)</source>
<translation>Vegetationsindex (hangbasiert)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="527"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="183"/>
<source>Statistics for Grids</source>
<translation>Statistik für Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="488"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="154"/>
<source>Grids Sum</source>
<translation>Gittersumme</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="508"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="85"/>
<source>Triangulation</source>
<translation>Triangulation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="607"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="228"/>
<source>Grid Values to Points</source>
<translation>Gitterwerte in Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="557"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="247"/>
<source>Add Coordinates to points</source>
<translation>Koordinaten zu Punkten hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="491"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="14"/>
<source>Symmetrical Difference</source>
<translation>Symmetrische Differenz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="555"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="130"/>
<source>Flat Detection</source>
<translation>Flacherkennung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="503"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="186"/>
<source>Aggregate</source>
<translation>Aggregieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="562"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="75"/>
<source>Sky View Factor</source>
<translation>Himmelsichtfaktor</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="467"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="180"/>
<source>Grid Difference</source>
<translation>Gitterdifferenz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="465"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="200"/>
<source>Vertical Distance to Channel Network</source>
<translation>Vertikale Distanz in Kanalnetzwerk</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="389"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="89"/>
<source>Random Field</source>
<translation>Zufälliges Feld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="591"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="170"/>
<source>Simple Filter</source>
<translation>Einfacher Filter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="604"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="47"/>
<source>Minimum Distance Analysis</source>
<translation>Minimumdistanzanalyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="453"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="103"/>
<source>Shrink and Expand</source>
<translation>Verkleinern und Vergrößern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="441"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="42"/>
<source>Cut Shapes Layer</source>
<translation>Shapelayer schneiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="393"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="32"/>
<source>TPI Based Landform Classification</source>
<translation>TPI basierte Landformklassifikation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="548"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="110"/>
<source>Intersect</source>
<translation>Schnittmengen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="378"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="204"/>
<source>Profile from points table|Profile from points</source>
<translation>Profile aus Punkttabelle|Profil aus Punkten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="464"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="8"/>
<source>Downslope Distance Gradient</source>
<translation>Abwärtsabstandsgrendiente</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="564"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="77"/>
<source>Channel Network</source>
<translation>Kanalnetzwerk</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="412"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="105"/>
<source>Pattern Analysis</source>
<translation>Musteranalyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="477"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="150"/>
<source>Fit N Points to shape</source>
<translation>N-Punkte in Shape einpassen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="517"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="255"/>
<source>Remove Duplicate Points</source>
<translation>Doppelte Punkte entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="425"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="254"/>
<source>Reclassify Grid Values</source>
<translation>Gitterwert neuklassifizieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="469"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="261"/>
<source>Geographically Weighted Regression (Points/Grid)</source>
<translation>Geografischgewichtete Regression (Punkt/Gitter)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="476"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="190"/>
<source>Close One Cell Gaps</source>
<translation>Einzellenlücken schließen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="426"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="81"/>
<source>Slope, Aspect, Curvature</source>
<translation>Neigung, Exposition, Wölbung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="561"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="10"/>
<source>Function</source>
<translation>Funktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="439"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="100"/>
<source>GWR for Multiple Predictors</source>
<translation>GWR für mehrere Vorhersagen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="428"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="167"/>
<source>Wind effect|Wind Effect (Windward / Leeward Index)</source>
<translation>Windeffekt|Wind Effekt (Windwärts / Leeindex)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="614"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="55"/>
<source>Close Gaps with Spline</source>
<translation>Lücken mit Spline schließen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="357"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="64"/>
<source>Fill Sinks (QM of ESP)</source>
<translation>Senken füllen (QM von ESP)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="518"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="80"/>
<source>Diversity of Categories</source>
<translation>Kategorienvielfalt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="539"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="117"/>
<source>Create Polygons Graticule|Create Graticule</source>
<translation>Gradnetz als Polygone erzeugen|Gradnetz erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="390"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="94"/>
<source>Change Time Format</source>
<translation>Zeitformat ändern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="566"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="92"/>
<source>Confusion Matrix (Polygons / Grid)</source>
<translation>Wahrheitsmatrix (Polygone / Gitter)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="567"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="241"/>
<source>Successive Flow Routing</source>
<translation>Aufeinanderfolgende Flußlenkung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="437"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="244"/>
<source>Thin Plate Spline (Local)</source>
<translation>Thin Plate Spline (Lokal)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="532"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="164"/>
<source>Multilevel B-Spline Interpolation for Categories</source>
<translation>Mehrstufen-B-Spline-Interpolation für Kategorien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="408"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="51"/>
<source>Diffusive Hillslope Evolution (FTCS)</source>
<translation>Diffusive Hillslope Evolution (FTCS)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="608"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="12"/>
<source>Diffusive Hillslope Evolution (ADI)</source>
<translation>Diffusive Hillslope Evolution (ADI)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="448"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="87"/>
<source>Create Lines Graticule|Create Graticule</source>
<translation>Gradnetz als Linien erzeugen|Gradnetz erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="376"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="137"/>
<source>Flow Accumulation (QM of ESP)</source>
<translation>Flußdichte (QM von ESP)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="610"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="88"/>
<source>Grid Normalisation</source>
<translation>Gitternormalisierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="496"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="191"/>
<source>Thin Plate Spline</source>
<translation>Thin Plate Spline</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="615"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="217"/>
<source>Seed Generation</source>
<translation>Saaterzeugung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="395"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="236"/>
<source>Polygon-Line Intersection</source>
<translation>Polygon-Linien-Verschneidung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="424"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="214"/>
<source>Running Average</source>
<translation>Beweglicher Mittelwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="572"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="199"/>
<source>Cross-Classification and Tabulation</source>
<translation>Kreuzklassifizierung und Tabellierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="466"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="99"/>
<source>Gradient Vector from Polar to Cartesian Coordinates</source>
<translation>Gradientenvektor aus Polar- zu kartesischen Koordinaten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="525"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="151"/>
<source>Metric Conversions</source>
<translation>Metrische Umwandlungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="558"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="201"/>
<source>RGB Composite</source>
<translation>RGB-Composite</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="597"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="23"/>
<source>Edge Contamination</source>
<translation>Kantenverunreinigung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="524"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="135"/>
<source>Curvature Classification</source>
<translation>Wölbungsklassifizierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="402"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="27"/>
<source>Filter Clumps</source>
<translation>Klumpen filtern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="407"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="250"/>
<source>Overland Flow - Kinematic Wave D8</source>
<translation>Überlandfluß - Kinematische Welle D8</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="382"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="95"/>
<source>Profiles from Lines</source>
<translation>Profile aus Linien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="497"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="139"/>
<source>Distance Matrix</source>
<translation>Distanzmatrix</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="371"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="141"/>
<source>Residual analysis|Residual Analysis (Grid)</source>
<translation>Restanalyse|Restanalyse (Raster)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="584"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="253"/>
<source>Zonal Grid Statistics</source>
<translation>Zonengitterstatistik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="399"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="46"/>
<source>Grid Division</source>
<translation>Gitterteilung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="596"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="7"/>
<source>Lake Flood</source>
<translation>Seeflut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="565"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="21"/>
<source>Add Polygon Attributes to Points</source>
<translation>Polygonattribute zu Punkten hinzufügen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="486"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="133"/>
<source>Multilevel B-Spline Interpolation</source>
<translation>Mehrstufen-B-Spline-Interpolation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="366"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="188"/>
<source>Cross Profiles</source>
<translation>Kreuzprofile</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="459"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="225"/>
<source>Polar to Cartesian Coordinates</source>
<translation>Polar- zu kartesischen Koordinaten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="480"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="181"/>
<source>Mosaick raster layers|Mosaicking</source>
<translation>Stitching von Rasterlayern|Stitching</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="457"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="177"/>
<source>Fire Risk Analysis</source>
<translation>Feuerriskikoanalyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="602"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="116"/>
<source>Geographically Weighted Regression</source>
<translation>Geografischgewichtete Regression</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="387"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="223"/>
<source>Separate points by direction</source>
<translation>Punkte nach Richtung aufteilen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="414"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="198"/>
<source>Polygons to Edges and Nodes</source>
<translation>Polygone zu Kanten und Knoten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="551"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="98"/>
<source>Morphological Filter</source>
<translation>Morphologischer Filter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="554"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="118"/>
<source>Vector Ruggedness Measure (VRM)</source>
<translation>Vektorrauhigkeitsmaß (VRM)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="588"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="162"/>
<source>Fast Representativeness</source>
<translation>Schnelle Repräsentativität</translation>
</message>
@@ -87080,17 +87936,17 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>SLDatabase</name>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="461"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="491"/>
<source>Run &Vacuum</source>
<translation>&VACUUM ausführen</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="462"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="492"/>
<source>&Database</source>
<translation>Da&tenbank</translation>
</message>
<message>
- <location filename="../python/plugins/db_manager/python-i18n.cpp" line="463"/>
+ <location filename="../python/plugins/db_manager/python-i18n.cpp" line="493"/>
<source>No database selected or you are not connected to it.</source>
<translation>Keine Datenbank gewählt oder keine Verbindung möglich.</translation>
</message>
@@ -87098,24 +87954,24 @@ Maximalzahl der Versuche überschritten.</translation>
<context>
<name>SagaAlgorithm212</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2581"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2614"/>
<source>Unsupported file format</source>
<translation>Nicht unterstütztes Dateiformat</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2582"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2615"/>
<source>SAGA execution commands</source>
<translation>SAGA-Befehlsausführung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2583"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2616"/>
<source>Input layer %s has more than one band.
Multiband layers are not supported by SAGA</source>
<translation>Eingabelayer %s hat mehr als einen Kanal.
Mehrkanallayer werden von SAGA nicht unterstützt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2584"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2617"/>
<source>Input layers do not have the same grid extent.</source>
<translation>Eingabelayer haben nicht die gleichen Gitterabmessungen.</translation>
</message>
@@ -87123,12 +87979,12 @@ Mehrkanallayer werden von SAGA nicht unterstützt</translation>
<context>
<name>SagaAlgorithm213</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2588"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2621"/>
<source>Unsupported file format</source>
<translation>Nicht unterstütztes Dateiformat</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2589"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2622"/>
<source>SAGA execution commands</source>
<translation>SAGA-Befehlsausführung</translation>
</message>
@@ -87136,47 +87992,47 @@ Mehrkanallayer werden von SAGA nicht unterstützt</translation>
<context>
<name>SagaAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2593"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2626"/>
<source>SAGA folder</source>
<translation>SAGA-Verzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2594"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2627"/>
<source>Enable SAGA Import/Export optimizations</source>
<translation>SAGA-Im-/Exportoptimierungen einschalten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2595"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2628"/>
<source>Log execution commands</source>
<translation>Befehlsausführung protokollieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2596"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2629"/>
<source>Log console output</source>
<translation>Konsolenausgabe protokollieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2597"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2630"/>
<source>Activate</source>
<translation>Aktivieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2598"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2631"/>
<source>Problem with SAGA installation: SAGA was not found or is not correctly installed</source>
<translation>Problem mit SAGA-Installation: SAGA wurde nicht gefunden oder ist nicht richtig installiert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2599"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2632"/>
<source>Problem with SAGA installation: installed SAGA version (%s) is not supported</source>
<translation>Problem mit SAGA-Installation: Installierte SAGA-Version (%s) ist nicht unterstützt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2600"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2633"/>
<source>Could not open SAGA algorithm: %s</source>
<translation>Konnte SAGA-Algorithmus nicht öffnen: %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2601"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2634"/>
<source>Could not open SAGA algorithm: %s
%s</source>
<translation>Konnte SAGA-Algorithmus nicht öffnen: %s
@@ -87186,7 +88042,7 @@ Mehrkanallayer werden von SAGA nicht unterstützt</translation>
<context>
<name>SagaUtils</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2605"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2638"/>
<source>SAGA execution console output</source>
<translation>Konsolenausgabe der SAGA-Ausführung</translation>
</message>
@@ -87194,22 +88050,22 @@ Mehrkanallayer werden von SAGA nicht unterstützt</translation>
<context>
<name>SaveSelectedFeatures</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2610"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2643"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2611"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2644"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2612"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2645"/>
<source>Selection</source>
<translation>Auswahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2609"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2642"/>
<source>Save selected features</source>
<translation>Gewählte Objekt speichern</translation>
</message>
@@ -87217,36 +88073,36 @@ Mehrkanallayer werden von SAGA nicht unterstützt</translation>
<context>
<name>ScriptAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2616"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2649"/>
<source>User scripts</source>
<translation>Benutzer Skripte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2617"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2650"/>
<source>This script has a syntax errors.
Problem with line: %s</source>
<translation>Diese Skript hat Syntaxfehler.
Problem in Zeile: %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2618"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2651"/>
<source>[Test scripts]</source>
<translation>[Test Skripte]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2619"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2652"/>
<source>[Unnamed algorithm]</source>
<translation>[Unbenannte Algorithmen]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2620"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2653"/>
<source>Could not load script: %s.
Problem with line "%s"</source>
<translation>Konnte Skript nicht laden: %s
Problem in Zeile: "%s"</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2621"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2654"/>
<source>Could not load script: %s.
Problem with line %d</source>
<translation>Konnte Skript nicht laden: %s.
@@ -87256,12 +88112,12 @@ Fehler in Zeile %d</translation>
<context>
<name>ScriptAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2625"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2658"/>
<source>Scripts folder</source>
<translation>Skript Verzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2626"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2659"/>
<source>Scripts</source>
<translation>Skripte</translation>
</message>
@@ -87269,39 +88125,44 @@ Fehler in Zeile %d</translation>
<context>
<name>ScriptEditorDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2632"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2665"/>
<source>Python scripts (*.py)</source>
<translation>Python-Skripte (*.py)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2633"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2666"/>
<source>Processing R script (*.rsx)</source>
<translation>Verarbeitete R-Skript (*.rsx)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2634"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2667"/>
+ <source>Open script</source>
+ <translation>Skript öffnen</translation>
+ </message>
+ <message>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2668"/>
<source>Save script</source>
<translation>Skript speichern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2635"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2669"/>
<source>I/O error</source>
<translation>E/A-Fehler</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2636"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2670"/>
<source>Unable to save edits. Reason:
%s</source>
<translation>Änderung konnten nicht gespeichert werden. Grund:
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2630"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2663"/>
<source>Unsaved changes</source>
<translation>Ungesicherte Änderungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2631"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2664"/>
<source>There are unsaved changes in script. Continue?</source>
<translation>Es gibt ungesicherte Skriptänderungen. Fortfahren?</translation>
</message>
@@ -87357,57 +88218,57 @@ Fehler in Zeile %d</translation>
<context>
<name>SelectByAttribute</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2641"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2675"/>
<source>Vector selection tools</source>
<translation>Vektorauswahlwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2642"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2676"/>
<source>begins with </source>
<translation>Beginnt mit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2643"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2677"/>
<source>contains</source>
<translation>enthält</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2644"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2678"/>
<source>Input Layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2645"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2679"/>
<source>Selection attribute</source>
<translation>Auswahlattribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2646"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2680"/>
<source>Operator</source>
<translation>Operator</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2647"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2681"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2648"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2682"/>
<source>Selected (attribute)</source>
<translation>Auswahl (Attribut)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2649"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2683"/>
<source>Operators %s can be used only with string fields.</source>
<translation>Operatoren %s könnte nur in Textfeldern verwendet werden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2650"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2684"/>
<source>Unsupported field type "%s"</source>
<translation>Nicht unterstützter Feldtyp "%s"</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2640"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2674"/>
<source>Select by attribute</source>
<translation>Nach Attribut wählen</translation>
</message>
@@ -87415,42 +88276,42 @@ Fehler in Zeile %d</translation>
<context>
<name>SelectByAttributeSum</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2655"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2689"/>
<source>Vector selection tools</source>
<translation>Vektorauswahlwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2656"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2690"/>
<source>Input Layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2657"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2691"/>
<source>Selection attribute</source>
<translation>Auswahlattribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2658"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2692"/>
<source>Value</source>
<translation>Wert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2659"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2693"/>
<source>Selected (attribute sum)</source>
<translation>Auswahl (Attributsumme)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2660"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2694"/>
<source>There is no selection in the input layer. Select one feature and try again.</source>
<translation>Im Eingabelayer ist nichts ausgewählt. Bitte ein Objekt wählen und nocheinmal versuchen.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2661"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2695"/>
<source>No adjacent features found.</source>
<translation>Keine benachbarten Objekte gefunden.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2654"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2688"/>
<source>Select by attribute sum</source>
<translation>Nach Attributsumme wählen</translation>
</message>
@@ -87458,52 +88319,52 @@ Fehler in Zeile %d</translation>
<context>
<name>SelectByExpression</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2666"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2700"/>
<source>Vector selection tools</source>
<translation>Vektorauswahlwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2667"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2701"/>
<source>creating new selection</source>
<translation>Neue Auswahl wird erstellt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2668"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2702"/>
<source>adding to current selection</source>
<translation>Füge zur aktuellen Auswahl hinzu</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2669"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2703"/>
<source>removing from current selection</source>
<translation>Entferne aus aktueller Auswahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2670"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2704"/>
<source>selecting within current selection</source>
<translation>innerhalb der aktuellen Auswahl wählen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2671"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2705"/>
<source>Input Layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2672"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2706"/>
<source>Expression</source>
<translation>Ausdruck</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2673"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2707"/>
<source>Modify current selection by</source>
<translation>Vorhandene Auswaähl ändern durch</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2674"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2708"/>
<source>Selected (expression)</source>
<translation>Auswahl (Ausdruck)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2665"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2699"/>
<source>Select by expression</source>
<translation>Nach Ausdruck wählen</translation>
</message>
@@ -87511,57 +88372,57 @@ Fehler in Zeile %d</translation>
<context>
<name>SelectByLocation</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2679"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2713"/>
<source>Vector selection tools</source>
<translation>Vektorauswahlwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2680"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2714"/>
<source>creating new selection</source>
<translation>Neue Auswahl erstellen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2681"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2715"/>
<source>adding to current selection</source>
<translation>Füge zur aktuellen Auswahl hinzu</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2682"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2716"/>
<source>removing from current selection</source>
<translation>Entferne aus aktueller Auswahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2683"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2717"/>
<source>Layer to select from</source>
<translation>Layer von dem gewählt wird</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2684"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2718"/>
<source>Additional layer (intersection layer)</source>
<translation>Zusätzliche Layer (Schnittlayer)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2685"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2719"/>
<source>Geometric predicate</source>
<translation>Geometrisches Prädikat</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2686"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2720"/>
<source>Precision</source>
<translation>Genauigkeit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2687"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2721"/>
<source>Modify current selection by</source>
<translation>Aktuelle Auswahl ändern mit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2688"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2722"/>
<source>Selected (location)</source>
<translation>Auswahl (Position)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2678"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2712"/>
<source>Select by location</source>
<translation>Nach Position selektieren</translation>
</message>
@@ -87622,27 +88483,27 @@ Fehler in Zeile %d</translation>
<context>
<name>SetRasterStyle</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2693"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2727"/>
<source>Raster general tools</source>
<translation>Allgemeine Rasterwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2694"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2728"/>
<source>Raster layer</source>
<translation>Rasterlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2695"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2729"/>
<source>Style file</source>
<translation>Stildatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2696"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2730"/>
<source>Styled</source>
<translation>Gestaltet</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2692"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2726"/>
<source>Set style for raster layer</source>
<translation>Setze Stil für Rasterlayer</translation>
</message>
@@ -87650,27 +88511,27 @@ Fehler in Zeile %d</translation>
<context>
<name>SetVectorStyle</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2701"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2735"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2702"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2736"/>
<source>Vector layer</source>
<translation>Vektorlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2703"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2737"/>
<source>Style file</source>
<translation>Stildatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2704"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2738"/>
<source>Styled</source>
<translation>Gestaltet</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2700"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2734"/>
<source>Set style for vector layer</source>
<translation>Setze Stil für Vektorlayer</translation>
</message>
@@ -87678,14 +88539,14 @@ Fehler in Zeile %d</translation>
<context>
<name>Setting</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2708"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2742"/>
<source>Wrong parameter value:
%s</source>
<translation>Falscher Parameterwert:
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2709"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2743"/>
<source>Specified path does not exist:
%s</source>
<translation>Angegebener Pfad existiert nicht:
@@ -87967,7 +88828,7 @@ Fehler in Zeile %d</translation>
<context>
<name>ShowTestDialog</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2713"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2747"/>
<source>Unit test</source>
<translation>Unit-Test</translation>
</message>
@@ -87975,32 +88836,32 @@ Fehler in Zeile %d</translation>
<context>
<name>SimplifyGeometries</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2718"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2752"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2719"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2753"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2720"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2754"/>
<source>Tolerance</source>
<translation>Toleranz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2721"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2755"/>
<source>Simplified</source>
<translation>Vereinfacht</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2722"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2756"/>
<source>Simplify: Input geometries have been simplified from %s to %s points</source>
<translation>Vereinfachen: Eingabegeometrien wurden von %s auf %s Punkte vereinfacht</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2717"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2751"/>
<source>Simplify geometries</source>
<translation>Geometrien vereinfachen</translation>
</message>
@@ -88041,32 +88902,36 @@ Fehler in Zeile %d</translation>
<context>
<name>SinglePartsToMultiparts</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2727"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2761"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2728"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2762"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2729"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2763"/>
<source>Unique ID field</source>
<translation>Eindeutiges Schlüsselfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2730"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2764"/>
<source>Multipart</source>
<translation>Mehrteilig</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2731"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2765"/>
+ <source>At least two features must have same attribute value! Please choose another field...</source>
+ <translation>Mindest zwei Objekt müssen den gleichen Attributwert haben! Bitte ein anderes Feld wählen...</translation>
+ </message>
+ <message>
<source>Invalid unique ID field</source>
- <translation>Ungültiges eindeutiges Kennungsfeld</translation>
+ <translation type="obsolete">Ungültiges eindeutiges Kennungsfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2726"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2760"/>
<source>Singleparts to multipart</source>
<translation>Ein- zu mehrteilig</translation>
</message>
@@ -88113,42 +88978,42 @@ Fehler in Zeile %d</translation>
<context>
<name>SlopeArea</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2735"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2769"/>
<source>Slope Area Combination</source>
<translation>Neigungsflächenkombination</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2736"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2770"/>
<source>Stream Network Analysis tools</source>
<translation>Stromnetzwerkanalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2737"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2771"/>
<source>Slope Grid</source>
<translation>Neigungsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2738"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2772"/>
<source>Contributing Area Grid</source>
<translation>Beitragende Fläche Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2739"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2773"/>
<source>Slope Exponent</source>
<translation>Neigungs Exponent</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2740"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2774"/>
<source>Area Exponent</source>
<translation>Flächen Exponent</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2741"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2775"/>
<source>Slope Area Grid</source>
<translation>Neigungsflächen Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2742"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2776"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -88156,42 +89021,42 @@ Fehler in Zeile %d</translation>
<context>
<name>SlopeAreaMulti</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2746"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2780"/>
<source>Slope Area Combination (multifile)</source>
<translation>Neigungsflächenkombination (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2747"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2781"/>
<source>Stream Network Analysis tools</source>
<translation>Stromnetzwerkanalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2748"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2782"/>
<source>Slope Grid</source>
<translation>Neigungsgitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2749"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2783"/>
<source>Contributing Area Grid</source>
<translation>Beitragende Fläche Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2750"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2784"/>
<source>Slope Exponent</source>
<translation>Neigungs Exponent</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2751"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2785"/>
<source>Area Exponent</source>
<translation>Flächen Exponent</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2752"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2786"/>
<source>Slope Area Grid</source>
<translation>Neigungsflächen Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2753"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2787"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -88199,37 +89064,37 @@ Fehler in Zeile %d</translation>
<context>
<name>Smooth</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2757"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2791"/>
<source>Smooth geometry</source>
<translation>Geometrieglättung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2758"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2792"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2759"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2793"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2760"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2794"/>
<source>Iterations</source>
<translation>Wiederholungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2761"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2795"/>
<source>Offset</source>
<translation>Versatz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2762"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2796"/>
<source>Smoothed</source>
<translation>Geglättet</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2763"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2797"/>
<source>Error smoothing geometry</source>
<translation>Fehler bei Geometrieglättung</translation>
</message>
@@ -88237,32 +89102,32 @@ Fehler in Zeile %d</translation>
<context>
<name>SpatialIndex</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2767"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2801"/>
<source>Create spatial index</source>
<translation>Räumlichen Index erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2768"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2802"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2769"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2803"/>
<source>Input Layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2770"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2804"/>
<source>Indexed layer</source>
<translation>Indizierter Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2771"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2805"/>
<source>Can not create spatial index</source>
<translation>Kann räumlichen Index nicht erstellen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2772"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2806"/>
<source>Layer's data provider does not support spatial indexes</source>
<translation>Der Datenanbieter dieses Layers unterstützt das Erzeugen von räumlichen Indizes nicht</translation>
</message>
@@ -88270,72 +89135,72 @@ Fehler in Zeile %d</translation>
<context>
<name>SpatialJoin</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2777"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2811"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2778"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2812"/>
<source>Take attributes of the first located feature</source>
<translation>Attribute des ersten bestimmten Objekts verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2779"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2813"/>
<source>Take summary of intersecting features</source>
<translation>Zusammenfassung der schneidenden Objekte erstellen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2780"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2814"/>
<source>Only keep matching records</source>
<translation>Nur passende Datensätze erhalten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2781"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2815"/>
<source>Keep all records (including non-matching target records)</source>
<translation>Alle Datensätze erhalten (einschließlich nicht zutreffender Zieldatensätzen)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2782"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2816"/>
<source>Target vector layer</source>
<translation>Zielvektorlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2783"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2817"/>
<source>Join vector layer</source>
<translation>Verknüpfter Vektorlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2784"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2818"/>
<source>Geometric predicate</source>
<translation>Geometrische Prädikat</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2785"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2819"/>
<source>Precision</source>
<translation>Genauigkeit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2786"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2820"/>
<source>Attribute summary</source>
<translation>Attributzusammenfassung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2787"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2821"/>
<source>Statistics for summary (comma separated)</source>
<translation>Statistik zur Zusammenfassung (kommasepariert)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2788"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2822"/>
<source>Joined table</source>
<translation>Verknüpfte Tabelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2789"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2823"/>
<source>Joined layer</source>
<translation>Zusammengefasster Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2776"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2810"/>
<source>Join attributes by location</source>
<translation>Attribute nach Position zusammenfügen</translation>
</message>
@@ -88343,32 +89208,32 @@ Fehler in Zeile %d</translation>
<context>
<name>SplitLinesWithLines</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2794"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2828"/>
<source>Vector overlay tools</source>
<translation>Vektorlayerüberlagerungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2795"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2829"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2796"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2830"/>
<source>Split layer</source>
<translation>Layer aufteilen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2797"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2831"/>
<source>Splitted</source>
<translation>Geteilt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2798"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2832"/>
<source>Geometry exception while splitting</source>
<translation>Geometrieausnahme während Aufteilung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2793"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2827"/>
<source>Split lines with lines</source>
<translation>Linien with Linien teilen</translation>
</message>
@@ -88376,32 +89241,32 @@ Fehler in Zeile %d</translation>
<context>
<name>SplitRGBBands</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2802"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2836"/>
<source>Split RGB bands</source>
<translation>RGB-Kanäle trennen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2803"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2837"/>
<source>Image tools</source>
<translation>Bildwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2804"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2838"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2805"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2839"/>
<source>Output R band layer</source>
<translation>R-Ausgabekanallayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2806"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2840"/>
<source>Output G band layer</source>
<translation>G-Ausgabekanallayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2807"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2841"/>
<source>Output B band layer</source>
<translation>B-Ausgabekanallayer</translation>
</message>
@@ -88437,32 +89302,32 @@ Fehler in Zeile %d</translation>
<context>
<name>StatisticsByCategories</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2812"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2846"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2813"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2847"/>
<source>Input vector layer</source>
<translation>Eingabevektorlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2814"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2848"/>
<source>Field to calculate statistics on</source>
<translation>Feld für Statistikberechnung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2815"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2849"/>
<source>Field with categories</source>
<translation>Feld mit Kategorien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2816"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2850"/>
<source>Statistics by category</source>
<translation>Statistik nach Kategorie</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2811"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2845"/>
<source>Statistics by categories</source>
<translation>Statistik nach Kategorien</translation>
</message>
@@ -88470,37 +89335,37 @@ Fehler in Zeile %d</translation>
<context>
<name>SumLines</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2821"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2855"/>
<source>Vector analysis tools</source>
<translation>Vektoranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2822"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2856"/>
<source>Lines</source>
<translation>Linien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2823"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2857"/>
<source>Polygons</source>
<translation>Polygone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2824"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2858"/>
<source>Lines length field name</source>
<translation>Linienlängenfeldname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2825"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2859"/>
<source>Lines count field name</source>
<translation>Linienzählfeldname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2826"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2860"/>
<source>Line length</source>
<translation>Linienlänge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2820"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2854"/>
<source>Sum line lengths</source>
<translation>Linienlängen summieren</translation>
</message>
@@ -88601,33 +89466,33 @@ Fehler in Zeile %d</translation>
<context>
<name>SymmetricalDifference</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2831"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2865"/>
<source>Vector overlay tools</source>
<translation>Vektorlayerüberlagerungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2832"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2866"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2833"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2867"/>
<source>Difference layer</source>
<translation>Differenzlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2834"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2868"/>
<source>GEOS geoprocessing error: One or more input features have invalid geometry.</source>
<translation>GEOS-Verarbeitungsfehler: Ein oder mehrere Eingabeobjekte haben ungültige Geometrien.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2835"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2869"/>
<source>Feature geometry error: One or more output features ignored due to invalid geometry.</source>
<translation>
Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometrie wurden ignoriert.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2830"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2864"/>
<source>Symmetrical difference</source>
<translation>Symmetrische Differenz</translation>
</message>
@@ -88635,222 +89500,222 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>TAUDEMAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="633"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="655"/>
<source>Basic Grid Analysis tools</source>
<translation>Grundlegende Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="621"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="662"/>
<source>D-Infinity Avalanche Runout (multifile)</source>
<translation>D-Unendlich Lawinenauslauf (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="634"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="668"/>
<source>Move Outlets To Streams</source>
<translation>Abläufe zu Strömem verschieben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="644"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="671"/>
<source>D8 Flow Directions (multifile)</source>
<translation>D8 Flußrichtungen (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="627"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="685"/>
<source>Topographic Wetness Index</source>
<translation>Topographischer Niederschlagsindex (TWI)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="648"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="690"/>
<source>Stream Network Analysis tools</source>
<translation>Stromnetzwerkanalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="629"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="680"/>
<source>Move Outlets To Streams (multifile)</source>
<translation>Abläufe zu Strömem verschieben (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="658"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="675"/>
<source>Stream Reach and Watershed</source>
<translation>Flußausdehnung und Wasserscheiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="649"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="663"/>
<source>D-Infinity Reverse Accumulation</source>
<translation>D-Unendlich umgekehrte Akkumulation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="643"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="681"/>
<source>Slope Over Area Ratio</source>
<translation>Gefälle-über-Flächenverhältnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="645"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="676"/>
<source>Select GT Threshold (multifile)</source>
<translation>GT-Schwelle wählen (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="641"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="678"/>
<source>D-Infinity Contributing Area (multifile)</source>
<translation>D8 beitragende Fläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="657"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="669"/>
<source>D-Infinity Concentration Limited Accumulation (multifile)</source>
<translation>D-Infinity konzentrationsbegrenzte Akkumulation (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="652"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="693"/>
<source>D8 Distance To Streams</source>
<translation>D8 Abstand zu Strömen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="653"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="684"/>
<source>D-Infinity Decaying Accumulation</source>
<translation>D-Unendlich abnehmende Akkumulation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="636"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="689"/>
<source>D-Infinity Flow Directions (multifile)</source>
<translation>D-Unendlich Flußrichtungen (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="651"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="657"/>
<source>Select GT Threshold</source>
<translation>GT-Schwelle wählen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="628"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="682"/>
<source>D8 Contributing Area</source>
<translation>D8 beitragende Fläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="618"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="674"/>
<source>Stream Reach and Watershed (multifile)</source>
<translation>Flußausdehnung und Wasserscheiden (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="617"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="653"/>
<source>Gage Watershed - 2 (multifile)</source>
<translation>Einzugsgebiet messen - 2 (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="637"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="659"/>
<source>Specialized Grid Analysis tools</source>
<translation>Spezialisierte Gitteranalysewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="616"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="673"/>
<source>D-Infinity Concentration Limited Accumulation</source>
<translation>D-Unendlich konzentrationsbegrenzte Akkumulation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="619"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="661"/>
<source>D-Infinity Flow Directions</source>
<translation>D-Infinity Fließrichtungen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="631"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="664"/>
<source>Gage Watershed - 2</source>
<translation>Einzugsgebiet messen - 2</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="639"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="667"/>
<source>D-Infinity Contributing Area</source>
<translation>D-Unendlich beitragende Fläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="659"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="687"/>
<source>Slope Over Area Ratio (multifile)</source>
<translation>Gefälle-über-Flächenverhältnis (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="647"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="683"/>
<source>D8 Extreme Upslope Value (multifile)</source>
<translation>D8 Extremer Aufwärtswert (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="623"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="686"/>
<source>D-Infinity Reverse Accumulation (multifile)</source>
<translation>D-Unendlich umgekehrte Akkumulation (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="622"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="654"/>
<source>Pit Remove</source>
<translation>Löcher entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="656"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="660"/>
<source>Gage Watershed</source>
<translation>Einzugsgebiet messen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="642"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="650"/>
<source>Stream Definition By Threshold</source>
<translation>Stromdefinition nach Schwelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="650"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="656"/>
<source>D8 Extreme Upslope Value</source>
<translation>D8 Extremer Aufwärtswert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="625"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="688"/>
<source>Slope Average Down</source>
<translation>Gemitteltes Gefälle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="638"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="665"/>
<source>D8 Contributing Area (multifile)</source>
<translation>D8 beitragende Fläche (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="655"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="679"/>
<source>D8 Distance To Streams (multifile)</source>
<translation>D8 Abstand zu Strömen (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="626"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="672"/>
<source>Gage Watershed (multifile)</source>
<translation>Einzugsgebiet messen (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="632"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="677"/>
<source>D-Infinity Avalanche Runout</source>
<translation>D-Unendlich Lawinenauslauf</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="620"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="658"/>
<source>Slope Average Down (multifile)</source>
<translation>Gemitteltes Gefälle (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="640"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="691"/>
<source>Pit Remove (multifile)</source>
<translation>Löcher entfernen (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="646"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="666"/>
<source>D-Infinity Upslope Dependence (multifile)</source>
<translation>D-Unendlich Auswärtsabhängigkeit (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="630"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="670"/>
<source>D-Infinity Upslope Dependence</source>
<translation>D-Unendlich Aufwärtsabhängigkeit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="654"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="652"/>
<source>Topographic Wetness Index (multifile)</source>
<translation>Topographischer Niederschlagsindex (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="624"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="651"/>
<source>Stream Definition By Threshold (multifile)</source>
<translation>Stromdefinition nach Schwelle (Mehrdatei)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/processing-i18n.cpp" line="635"/>
+ <location filename="../python/plugins/processing/processing-i18n.cpp" line="692"/>
<source>D8 Flow Directions</source>
<translation>D8 Flußrichtungen</translation>
</message>
@@ -88858,14 +89723,14 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>TauDEMAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2839"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2873"/>
<source>Could not load TauDEM algorithm: %s
%s</source>
<translation>Konnte TauDEM-Algorithmus nicht laden: %s
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2840"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2874"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -88873,47 +89738,47 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>TauDEMAlgorithmProvider</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2845"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2879"/>
<source>TauDEM command line tools folder</source>
<translation>Verzeichnis der TauDEM-Kommandozeilenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2849"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2883"/>
<source>MPICH2/OpenMPI bin directory</source>
<translation>MPICH2/OpenMPI-Programmverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2850"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2884"/>
<source>Number of MPI parallel processes to use</source>
<translation>Anzahl zu verwendender paralleler MPI-Prozesse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2851"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2885"/>
<source>Could not open TauDEM algorithm: %s</source>
<translation>Konnte TauDEM-Algorithmus nicht öffnen: %s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2844"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2878"/>
<source>TauDEM (hydrologic analysis)</source>
<translation>TauDEM (hydrologische Analyse)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2846"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2880"/>
<source>TauDEM multifile command line tools folder</source>
<translation>TauDEM-Mehrdateibefehlszeilenwerkzeugverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2847"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2881"/>
<source>Enable singlefile TauDEM tools</source>
<translation>TauDEM-Einzeldateibefehlswerkzeuge aktivieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2848"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2882"/>
<source>Enable multifile TauDEM tools</source>
<translation>TauDEM-Mehrdateienbefehlswerkzeuge aktivieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2852"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2886"/>
<source>Could not open TauDEM algorithm %s:
%s</source>
<translation>Konnte TauDEM-Algorithmus %s nicht öffnen:
@@ -88923,14 +89788,14 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>TauDEMMultifileAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2856"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2890"/>
<source>Could not load TauDEM algorithm: %s
%s</source>
<translation>Konnte TauDEM-Algorithmus nicht laden: %s
%s</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2857"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2891"/>
<source>Wrong number of MPI processes used. Please set correct number before running TauDEM algorithms.</source>
<translation>Falsche Anzahl von MPI-Prozessen verwendet. Bitte vor der Ausführung von TauDEM-Algorithmen korrekte Anzahl einstellen.</translation>
</message>
@@ -88938,12 +89803,12 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>TauDEMUtils</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2861"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2895"/>
<source>TauDEM execution console output</source>
<translation>Konsolenausgabe der TauDEM-Ausführung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2862"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2896"/>
<source>TauDEM command:</source>
<translation>TauDEM-Befehl:</translation>
</message>
@@ -88951,27 +89816,27 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>TextToFloat</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2867"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2901"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2868"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2902"/>
<source>Input Layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2869"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2903"/>
<source>Text attribute to convert to float</source>
<translation>In Fließkomma umzuwandelndes Textattribut </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2870"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2904"/>
<source>Float from text</source>
<translation>Fließkomma aus Text</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2866"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2900"/>
<source>Text to float</source>
<translation>Text zu Fließkomma</translation>
</message>
@@ -88979,47 +89844,47 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>TinSurfaceCreate</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2874"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2908"/>
<source>Tin Surface Create</source>
<translation>TIN-Oberflächenerzeugung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2875"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2909"/>
<source>Surface</source>
<translation>Oberfläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2876"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2910"/>
<source>Input LAS layer</source>
<translation>Eingabe-LAS-Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2877"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2911"/>
<source>Cellsize</source>
<translation>Zellengröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2878"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2912"/>
<source>XY Units</source>
<translation>XY-Einheiten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2879"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2913"/>
<source>Z Units</source>
<translation>Z-Einheit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2880"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2914"/>
<source>.dtm output surface</source>
<translation>DTM-Ausgabeoberfläche</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2882"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2916"/>
<source>Select specific return</source>
<translation>Bestimmtes Ergebnis wählen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2881"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2915"/>
<source>Class</source>
<translation>Klasse</translation>
</message>
@@ -89041,7 +89906,7 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>TreeProviderItem</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2886"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2920"/>
<source> [{0} geoalgorithms]</source>
<translation> [{0} Geo-Algorithmen]</translation>
</message>
@@ -89049,33 +89914,33 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>Union</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2891"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2925"/>
<source>Vector overlay tools</source>
<translation>Vektorlayerüberlagerungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2892"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2926"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2893"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2927"/>
<source>Input layer 2</source>
<translation>Eingabelayer 2</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2894"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2928"/>
<source>Feature geometry error: One or more output features ignored due to invalid geometry.</source>
<translation>
Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometrie wurden ignoriert.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2895"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2929"/>
<source>GEOS geoprocessing error: One or more input features have invalid geometry.</source>
<translation>GEOS-Verarbeitungsfehler: Ein oder mehrere Eingabeobjekte haben ungültige Geometrien.</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2890"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2924"/>
<source>Union</source>
<translation>Vereinigungen</translation>
</message>
@@ -89083,42 +89948,42 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>UniqueValues</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2900"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2934"/>
<source>Vector table tools</source>
<translation>Vektortabellenwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2901"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2935"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2902"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2936"/>
<source>Target field</source>
<translation>Zielfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2903"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2937"/>
<source>Unique values</source>
<translation>Eindeutige Werte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2904"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2938"/>
<source>Total unique values</source>
<translation>Gesamtzahl eindeutiger Werte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2905"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2939"/>
<source><p>Total unique values: </source>
<translation><p>Gesamte eindeutige Werte:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2906"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2940"/>
<source><p>Unique values:</p></source>
<translation><p>Eindeutige Werte:</p></translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2899"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2933"/>
<source>List unique values</source>
<translation>Eindeutige Werte auflisten</translation>
</message>
@@ -89139,37 +90004,37 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>VariableDistanceBuffer</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2911"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2945"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2912"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2946"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2913"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2947"/>
<source>Distance field</source>
<translation>Distanzfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2914"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2948"/>
<source>Segments</source>
<translation>Segmente</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2915"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2949"/>
<source>Dissolve result</source>
<translation>Ergebnis auflösen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2916"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2950"/>
<source>Buffer</source>
<translation>Puffer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2910"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2944"/>
<source>Variable distance buffer</source>
<translation>Puffer variabler Distanz</translation>
</message>
@@ -89190,47 +90055,47 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>VectorGrid</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2921"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2955"/>
<source>Vector creation tools</source>
<translation>Vektorerzeugungswerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2922"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2956"/>
<source>Output grid as polygons</source>
<translation>Gitter als Polygone ausgeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2923"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2957"/>
<source>Output grid as lines</source>
<translation>Gitter als Linien ausgeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2924"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2958"/>
<source>Grid extent</source>
<translation>Gittergrenze von Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2925"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2959"/>
<source>X spacing</source>
<translation>X-Abstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2926"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2960"/>
<source>Y spacing</source>
<translation>Y-Abstand</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2927"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2961"/>
<source>Grid type</source>
<translation>Gittertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2928"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2962"/>
<source>Grid</source>
<translation>Gitter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2920"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2954"/>
<source>Vector grid</source>
<translation>Vektorraster</translation>
</message>
@@ -89238,42 +90103,42 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>VectorLayerBoundsAlgorithm</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2932"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2966"/>
<source>Vector layer bounds</source>
<translation>Vektorlayer Grenzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2933"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2967"/>
<source>Modeler-only tools</source>
<translation>Modell Werkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2934"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2968"/>
<source>Layer</source>
<translation>Layer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2935"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2969"/>
<source>min X</source>
<translation>min X</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2936"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2970"/>
<source>max X</source>
<translation>max X</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2937"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2971"/>
<source>min Y</source>
<translation>min Y</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2938"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2972"/>
<source>max Y</source>
<translation>max Y</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2939"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2973"/>
<source>Extent</source>
<translation>Umfang</translation>
</message>
@@ -89281,32 +90146,32 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>VectorLayerHistogram</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2944"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2978"/>
<source>Graphics</source>
<translation>Grafik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2945"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2979"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2946"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2980"/>
<source>Attribute</source>
<translation>Attribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2947"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2981"/>
<source>number of bins</source>
<translation>Anzahl von bins</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2948"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2982"/>
<source>Histogram</source>
<translation>Histogramm</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2943"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2977"/>
<source>Vector layer histogram</source>
<translation>Vektorlayerhistogramm</translation>
</message>
@@ -89314,32 +90179,32 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>VectorLayerScatterplot</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2953"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2987"/>
<source>Graphics</source>
<translation>Grafik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2954"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2988"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2955"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2989"/>
<source>X attribute</source>
<translation>X-Attribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2956"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2990"/>
<source>Y attribute</source>
<translation>Y-Attribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2957"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2991"/>
<source>Scatterplot</source>
<translation>Streudiagramm</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2952"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2986"/>
<source>Vector layer scatterplot</source>
<translation>Vektorlayerstreuungsplott</translation>
</message>
@@ -89347,27 +90212,27 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>VectorSplit</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2962"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2996"/>
<source>Vector general tools</source>
<translation>Allgemeine Vektorwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2963"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2997"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2964"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2998"/>
<source>Unique ID field</source>
<translation>Eindeutiges Schlüsselfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2965"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2999"/>
<source>Output directory</source>
<translation>Ausgabeverzeichniss</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2961"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="2995"/>
<source>Split vector layer</source>
<translation>Vektorlayer teilen</translation>
</message>
@@ -89375,27 +90240,27 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>VoronoiPolygons</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2971"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3005"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2972"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3006"/>
<source>Buffer region</source>
<translation>Region puffern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2969"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3003"/>
<source>Voronoi polygons</source>
<translation>Voronoipolygone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2970"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3004"/>
<source>Vector geometry tools</source>
<translation>Vektorgeometriewerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2973"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3007"/>
<source>Input file should contain at least 3 points. Choose another file and try again.</source>
<translation>Eingabedatei sollte mindestens 3 Punkte enthalten. Eine andere Datei wählen und nochmal versuchen.</translation>
</message>
@@ -90288,7 +91153,7 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<location filename="../src/ui/symbollayer/widget_svgfill.ui" line="231"/>
<location filename="../src/ui/symbollayer/widget_svgfill.ui" line="238"/>
<location filename="../src/ui/symbollayer/widget_svgfill.ui" line="245"/>
- <location filename="../src/ui/symbollayer/widget_svgfill.ui" line="302"/>
+ <location filename="../src/ui/symbollayer/widget_svgfill.ui" line="317"/>
<source>...</source>
<translation>...</translation>
</message>
@@ -90955,42 +91820,42 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>ZonalStatistics</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2978"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3012"/>
<source>Raster tools</source>
<translation>Rasterwerkzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2979"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3013"/>
<source>Raster layer</source>
<translation>Rasterlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2980"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3014"/>
<source>Raster band</source>
<translation>Rasterkanal</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2981"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3015"/>
<source>Vector layer containing zones</source>
<translation>Zonenvektorlayer </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2982"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3016"/>
<source>Output column prefix</source>
<translation>Ausgabespaltenpräfix</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2983"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3017"/>
<source>Load whole raster in memory</source>
<translation>Ganzes Raster in Speicher laden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2984"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3018"/>
<source>Zonal statistics</source>
<translation>Zonenstatistik</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2977"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3011"/>
<source>Zonal Statistics</source>
<translation>Räumliche Statistik</translation>
</message>
@@ -91011,151 +91876,151 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>alg</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3005"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3039"/>
<source>You need to set either inline data positions or an input data positions file!</source>
<translation>Es muß entweder interne Datenpositionen oder eine Eingabedatei für Positionen geben!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3006"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3040"/>
<source>You need to set either sampling data positions or an output sampling data positions file!</source>
<translation>Es müssen entweder Abtastdatenpositionen oder eine Ausgabedatei für Abtastdatenpositionen angeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3007"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3041"/>
<source>You need to set input and output data positions parameters!</source>
<translation>Es mpssen Eingabe- und Ausgabedatenpositionsparameter angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2998"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3032"/>
<source>You need to set either a brighten percentage or a NULL color!</source>
<translation>Es must entweder der Aufhellungsprozentsatz oder eine NULL-Farbe angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3012"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3046"/>
<source>You need to set at least source/sink_where or source/sink_cats parameters for each set!</source>
<translation>Es muß zumindest der source/sink_where oder source/sink_cats Parameter für jeden Satz gesetzt sein!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2996"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3030"/>
<source>You need to set either inline configuration or a configuration file!</source>
<translation>Es muss entweder eine direkte Konfiguration oder eine Konfigurationsdatei angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2997"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3031"/>
<source>Your configuration needs to be a "moving window" configuration!</source>
<translation>Die Konfiguration muss eine "gleitende Fenster"-Konfiguration sein!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3016"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3050"/>
<source>Your configuration needs to be a non "moving window" configuration!</source>
<translation>Die Konfiguration muss eine nicht-"gleitende Fenster"-Konfiguration sein!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2994"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3028"/>
<source>You need to set either start coordinates OR a start points vector layer!</source>
<translation>Es müssen entweder Startkoordinaten oder ein Startpunktvektorlayer angeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2995"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3029"/>
<source>-c, -a, -n parameters are mutually exclusive!</source>
<translation>-c, -a, -n Parameter schließen sich gegenseitig aus!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3003"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3037"/>
<source>You can't use original Hargreaves flag and precipitation parameter together!</source>
<translation>Die originale Hargreaves-Einstellung und der Fällungsparameter schließen sich aus!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3004"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3038"/>
<source>If you don't use original Hargreaves flag, you must set the precipitation raster parameter!</source>
<translation>Wenn die orginale Hargreaves-Einstellung nicht verwendet wird, muß ein Fällungsrasterparameter angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2990"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3024"/>
<source>You need to set either a segment rules file or write directly the rules!</source>
<translation>Die Segmentregeln müssen direkt oder als Datei angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3013"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3047"/>
<source>Upload parameters should be a list of elements taken in the following values:
'cat', 'dist', 'to_x', 'to_y', 'to_along', 'to_angle', 'to_attr'</source>
<translation>Hochladeparameter sollten eine Elementliste mit folgenden Werten sein:
'cat', 'dist', 'to_x', 'to_y', 'to_along', 'to_angle', 'to_attr'</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3014"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3048"/>
<source>The number of columns and the number of upload parameters should be equal!</source>
<translation>Die Anzahl der Spalten und die Anzahl der Hochladeparameter sollte gleich sein!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2993"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3027"/>
<source>You need to set at least 'setnull' or 'null' parameters for this algorithm!</source>
<translation>Für diesen Algorithmus muß zumindest der Parameter 'setnull' oder 'null' gesetzt sein!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3008"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3042"/>
<source>You need to set either inline expression or a rules file!</source>
<translation>Es muss ein direkter Ausdruck oder eine Regeldatei angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3000"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3034"/>
<source>You need to set either a rules file or write directly the rules!</source>
<translation>Die Regeln müssen direkt oder als Datei angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3009"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3043"/>
<source>You need to set either radius or x_radius and y_radius!</source>
<translation>Es muss ein Radius, x_radius oder y_radius angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3010"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3044"/>
<source>You need to set x_radius and y_radius!</source>
<translation>Es muß mindestens x_radius und y_radius gesetzt sein!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3001"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3035"/>
<source>You need to set either rules or a raster from which to copy categories!</source>
<translation>Es müssen Regeln oder ein Raster aus dem die Kategorien kopiert werden angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3011"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3045"/>
<source>You need to set the method list with the following values only: asm, contrast, corr, var, idm, sa, se, sv, entr, dv, de, moc1, moc2!</source>
<translation>Es muss eine Methodenliste ausschließlich aus folgenden Werten angeben werden: asm, contrast, corr, var, idm, sa, se, sv, entr, dv, de, moc1, moc2!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2991"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3025"/>
<source>You need to set either inline rules or a rules file!</source>
<translation>Es müssen direkte Regeln oder eine Regeldatei angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3015"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3049"/>
<source>Feature type for '{}' should be a list of elements taken in the following values:
'point', 'line', 'boundary', 'centroid', 'area'</source>
<translation>Objekttyp für '{}' sollte eine Elementliste mit folgenden Werten sein:
'point', 'line', 'boundary', 'centroid', 'area'</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2989"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3023"/>
<source>You need to set either an input control point file or inline control points!</source>
<translation>Es muss entweder eine Kontrollpunkteingabedatei oder direkt Kontrollpunkte angeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3002"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3036"/>
<source>You need to set either a fixed height value or the height column!</source>
<translation>Es muss entweder eine fester Höhenwert oder eine Höhenspalte angeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2992"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3026"/>
<source>You need to set either an input ASCII file or inline data!</source>
<translation>Es muss eine ASCII Eingabedatei oder Daten angegeben werden!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2999"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3033"/>
<source>You need to set at least setX_where or setX_cats parameters for each set!</source>
<translation>Es muß zumindest die setX_where oder setX_cats Parameter für jeden Satz gesetzt sein!</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="2988"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3022"/>
<source>Fusion</source>
<translation>Fusion</translation>
</message>
@@ -91163,42 +92028,42 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>aspect</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3021"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3055"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3022"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3056"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3023"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3057"/>
<source>Band number</source>
<translation>Kanalnummer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3024"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3058"/>
<source>Compute edges</source>
<translation>Kanten berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3025"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3059"/>
<source>Use Zevenbergen&Thorne formula (instead of the Horn's one)</source>
<translation>Benutze Zevenbergen&Thorne Formel (statt Horn)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3026"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3060"/>
<source>Return trigonometric angle (instead of azimuth)</source>
<translation>Trigonometrischen Winkel (statt Azimut) zurückgeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3027"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3061"/>
<source>Return 0 for flat (instead of -9999)</source>
<translation>0 (statt -9999) für Ebene zurückgeben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3020"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3054"/>
<source>Aspect</source>
<translation>Perspektive</translation>
</message>
@@ -91206,27 +92071,27 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>blast2dem</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3031"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3065"/>
<source>blast2dem</source>
<translation>blast2dem</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3032"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3066"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3033"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3067"/>
<source>Attribute</source>
<translation>Attribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3034"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3068"/>
<source>Product</source>
<translation>Produkt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3035"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3069"/>
<source>Use tile bounding box (after tiling with buffer)</source>
<translation>Benutze Kachel Begrenzungsrahmen (nach Buffer)</translation>
</message>
@@ -91234,27 +92099,27 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>blast2demPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3039"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3073"/>
<source>blast2demPro</source>
<translation>blast2demPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3040"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3074"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3041"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3075"/>
<source>Attribute</source>
<translation>Attribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3042"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3076"/>
<source>Product</source>
<translation>Produkt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3043"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3077"/>
<source>Use tile bounding box (after tiling with buffer)</source>
<translation>Benutze Kachel Begrenzungsrahmen (nach Buffer)</translation>
</message>
@@ -91262,37 +92127,37 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>blast2iso</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3047"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3081"/>
<source>blast2iso</source>
<translation>blast2iso</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3048"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3082"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3049"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3083"/>
<source>smooth underlying TIN</source>
<translation>Zugrundeliegendes TIN glätten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3050"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3084"/>
<source>extract isoline with a spacing of</source>
<translation>Extrahiere Isolinie mit einem Abstand von</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3051"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3085"/>
<source>clean isolines shorter than (0 = do not clean)</source>
<translation>Iso-Linien bereinigen, wenn kürzer als (0 = keine Bereinigung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3052"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3086"/>
<source>simplify segments shorter than (0 = do not simplify)</source>
<translation>Segmente vereinfachen kürzer als (0 = nicht vereinfachen) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3053"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3087"/>
<source>simplify segments pairs with area less than (0 = do not simplify)</source>
<translation>Segmentpaare vereinfachen mit Fläche kleiner als (0 = nicht vereinfachen) </translation>
</message>
@@ -91300,37 +92165,37 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>blast2isoPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3057"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3091"/>
<source>blast2isoPro</source>
<translation>blast2isoPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3058"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3092"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3059"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3093"/>
<source>smooth underlying TIN</source>
<translation>Zugrundeliegendes TIN glätten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3060"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3094"/>
<source>extract isoline with a spacing of</source>
<translation>Extrahiere Isolinie mit einem Abstand von</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3061"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3095"/>
<source>clean isolines shorter than (0 = do not clean)</source>
<translation>Iso-Linien vereinfachen kürzer als (0 = nicht vereinfachen) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3062"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3096"/>
<source>simplify segments shorter than (0 = do not simplify)</source>
<translation>Segmente vereinfachen kürzer als (0 = nicht vereinfachen) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3063"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3097"/>
<source>simplify segments pairs with area less than (0 = do not simplify)</source>
<translation>Segmentpaare vereinfachen mit Fläche kleiner als (0 = nicht vereinfachen) </translation>
</message>
@@ -91338,37 +92203,37 @@ Objektgeometriefehler: Eine oder mehrere Ausgabeobjekte mit ungültiger Geometri
<context>
<name>buildvrt</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3068"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3102"/>
<source>[GDAL] Miscellaneous</source>
<translation>[GDAL] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3069"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3103"/>
<source>Input layers</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3070"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3104"/>
<source>Resolution</source>
<translation>Auflösung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3071"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3105"/>
<source>Layer stack</source>
<translation>Layerstapel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3072"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3106"/>
<source>Allow projection difference</source>
<translation>Unterschiedliche Projektionen zulassen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3073"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3107"/>
<source>Virtual</source>
<translation>Virtuell</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3067"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3101"/>
<source>Build Virtual Raster</source>
<translation>Virtuelles Raster generieren</translation>
</message>
@@ -91565,7 +92430,7 @@ which are described and illustrated on <a href="http://en.wikipedia.org/
<p>Contact the author through aruntheguy at gmail dot com</p>
</source>
- <translation><h1>Heatmap-Erweiterung</h1>
+ <translation type="obsolete"><h1>Heatmap-Erweiterung</h1>
<p>Die Heatmap-Erweiterung erzeugt mit Hilfe von Kerndichteschätzung ein Dichteraster (Heatmap) für einen Punktlayer. Die Dichte wird auf Basis der Punktanzahl an einer Stelle berechnet, je größer die Anzahl der in einer Punkthäufung desto größer der Rasterwert.
<h2>Parameter</h2>
@@ -92015,10 +92880,10 @@ Für eine einfache Suche nach Attribute einer Spalte kann das <label>Suche
<a name="Field">
<h4>Feldrechner</h4>
</a>
-Der Knopf <label>Feldrechner</label> in der Attributtabelle ermöglicht Berechnungen auf mit vorhandenen Attributwerten oder definierten Funktionen. Z.B. kann die Länge oder Fläche von Geometrieobjekten berechnet werden.<br/>
+Der Knopf <label>Feldrechner</label> in der Attributtabelle ermöglicht Berechnungen auf mit vorhandenen Attributwerten oder definierten Funktionen. Z.B. kann die Länge oder Fläche von Geo#metrieobjekten berechnet werden.<br/>
Die Ergebnisse können in eine neue Attributspalte geschrieben oder eine vorhandene Spalte damit überschrieben werden.<br/>
Um den Feldrechner zu öffnen, müssen Sie den Vektorlayer zuvor in den Bearbeitungsmodus versetzen.
-</translation>
+<br></translation>
</message>
<message>
<source><h3>Spatial Bookmarks</h3>
@@ -92100,6 +92965,101 @@ Um ein Lesezeichen im Dialog zu löschen, klicken Sie auf <label>Löschen&
</translation>
</message>
<message>
+ <source><h3>Heatmap Plugin Help</h3>
+<p>The Heatmap plugin uses Kernel Density Estimation to create a density (heatmap)
+raster of an input point vector layer. The density is calculated based on the
+number of points in a location, with larger numbers of clustered points resulting
+in larger values. Heatmaps allow easy identification of "hotspots" and
+clustering of points.</p>
+
+<h2>Dialog Parameters</h2>
+
+<h3>Input point layer</h3>
+<p>The input is always a vector layer of point type. All the point vector layers that are currently loaded in the canvas are shown in the drop-down list. Click the dropdown button and select the desired layer.</p>
+
+<h3>Output raster</h3>
+<p>The output raster location and filename can be set by clicking the <label>...</label> button next to the output raster textbox.<br/>
+<b>Note:</b> The file format is automatically added depending upon the output format selected, if not explicitly given.</p>
+
+<h3>Output format</h3>
+<p>All the file creation supporting GDAL formats are available in the drop down list. Click and select the required output format for your file.<br/>
+<b>Note:</b> GeoTiff and ERDAS Imagine .img formats are recommended. Some formats make the application crash. Kindly stick to the recommended formats until the crash issue is resolved or use other formats if you know GDAL supports it completely.</p>
+
+<h3>Radius (bandwidth)</h3>
+<p>Used to specify the heatmap search radius (or kernel bandwidth) in meters or map units. The radius specifies the distance around a point at which the influence
+ of the point will be felt. Larger values result in greater smoothing, but smaller values may show finer details and variation in point density.</p>
+
+<h3>Advanced Options</h3>
+
+<h4>Rows and Columns</h4>
+<p>Used to change the dimensions of the output raster file. These values are also linked to the <b>Cell size X</b> and <b>Cell size Y</b> values.
+Increasing the number of rows or columns will decrease the cell size and increase the file size of the output file. The values in Rows and Columns
+are also linked, so doubling the number of rows will automatically double the number of columns and the cell sizes will also be halved. The geographical area of the output raster will remain the same!</p>
+
+<h4>Cell size X and Y</h4>
+<p>Control the geographic size of each pixel in the output raster. Changing these values will also change the number of Rows and Columns in the output
+ raster.</p>
+
+<h4>Kernel shape</h4>
+<p>The kernel shape controls the rate at which the influence of a point decreases as the distance from the point increases. Different kernels decay at
+different rates, so a triweight kernel gives features greater weight for distances closer to the point than the Epanechnikov kernel does. Consequently,
+triweight results in "sharper" hotspots, and Epanechnikov results in "smoother" hotspots. A number of standard kernel functions are available in QGIS,
+which are described and illustrated on <a href="http://en.wikipedia.org/wiki/Kernel_(statistics)#Kernel_functions_in_common_use">Wikipedia</a>.</p>
+
+<h4>Decay ratio</h4>
+<p>For triangular kernels, the decay ratio defines amount of influence that applies to the outermost pixels in the buffer radius. A value of 0 reflects a standard triangular kernel, where the influences drops to zero as the distance from the pixel to the point approaches the specified radius. In contrast, a value of 1 indicates that no falloff occurs as the distance from the point increases.</p>
+
+<h4>Use radius from field</h4>
+<p>Optionally, the value in a specified field can be used to control the kernel radius for each point in the input layer.</p>
+
+<h4>Use weight from field</h4>
+<p>Optionally, a attribute containing weights for points can be used to weight some points in the input layer more than others.</p>
+
+<h2>Further Details</h2>
+<p>Contact the author through aruntheguy at gmail dot com</p>
+
+</source>
+ <translation><h1>Heatmap-Erweiterung</h1>
+<p>Die Heatmap-Erweiterung erzeugt mit Hilfe von Kerndichteschätzung ein Dichteraster (Heatmap) für einen Punktlayer. Die Dichte wird auf Basis der Punktanzahl an einer Stelle berechnet, je größer die Anzahl der in einer Punkthäufung desto größer der Rasterwert.
+
+<h2>Parameter</h2>
+
+<h3>Eingabepunktlayer</h3>
+<p>Die Eingabe ist jeweils ein Punktlayer. In die Liste werden alle derzeit in die Karte geladenen Punktlayer übernommen. Klicken Sie auf den Pfeil neben der Liste und wählen Sie den gewünschten Layer.</p>
+
+<h3>Ausgaberaster</h3>
+<p>Der Dateiname für das Ausgaberaster kann durch Klick auf <label>...</label> neben dem Eingabefeld gewählt werden.<br/>
+<b>Hinweis:</b> Wenn nicht explizit angegeben, wird die Dateiendung abhängig vom gewählten Ausgabeformat automatisch ergänzt,</p>
+
+<h3>Ausgabeformat</h3>
+<p>Alle Formate deren Erzeugung GDAL unterstützt sind in der Liste verfügbar. Wählen Sie das gewünschte Ausgabeformat Ihrer Datei.<br/>
+<b>Hinweis:</b> Die Formate GeoTiff und ERDAS Imagine .img werden empfohlen. Einige Formate können die Anwendung zum Absturz bringen. Bleiben Sie bitte bei den empfohlenen Formate bis die Absturzursache beseitig ist oder wählen Sie ein anderes Format, wenn Sie wissen, dass GDAL es voll unterstützt.</p>
+
+<h3>Heatmap Punktattribute</h3>
+<h4>Radius (Bandbreite)</h4>
+<p>Der Pufferradius gibt den Abstand um einen Punkt herum an, in dem die Wirkung des Punktes spürbar ist. Große Werte führen zu größer Glättung, aber kleinere Werte können genauere Resultate ergeben.<br/>
+<b>Hinweise:</b> Der Wert ist immer ganzzahlig.</p>
+
+<h4>Kernform</h4>
+<p>Der Kernform-Parameter bestimmt die Rate in der der Einfluß eines Punktes mit
+zunehmenden Abstand zum Punkt verfällt. Es sind mehrere Standardkernfunktionen
+verfügbar, welche im <a href="http://en.wikipedia.org/wiki/Kernel_(statistics)#Kernel_functions_in_common_use">englischen
+Wikipedia</a> näher beschrieben sind.<p>
+
+<h4>Radius aus Feld nutzen</h4>
+<p>Wahlweise kann auch ein Attribut angegeben werden, das die Kernradien für die einzelnen Punkte des Eingabelayers festlegt.</p>
+
+<h4>Gewicht aus Feld nutzen</h4>
+<p>Wahlweise kann auch ein Attribut mit Punktgewichten zur stärkeren Gewichtung einiger Punkte des Eingabelayers verwendet werden.</p>
+
+<h4>Verfallrate</h4>
+<p>Für dreieckige Kerne gibt die Verfallrate gibt den Betrag des Einfluß der äußersten Pixel des Pufferradius an. Ein Wert von 0 definiert einen dreieckigen Standardkern, bei dem der Einfluß auf Null sinkt, wenn die Entfernung des Pixels sich dem definierten Radius nähert. Im Gegensatz dazu definiert ein Wert von 1, dass kein Verfall bei zunehmendem Abstand stattfindet.</p>
+
+<h2>Weitere Einzelheiten</h2>
+<p>Sie können über aruntheguy at gmail dot com mit dem Autor Kontakt aufnehmen.</p>
+</translation>
+ </message>
+ <message>
<source><h3>Print Composer</h3>
<p>
@@ -92596,7 +93556,7 @@ The following options can be added
</source>
<translation><h3>Getrennter Textlayer</h3>
-Läd und zeigt getrennten Text an.
+Läd und zeigt getrennten Text ans
<p>
<a href="#re">Überblick</a><br/>
<a href="#creating">Erzeugung eines getrennten Textlayers</a><br/>
@@ -92689,7 +93649,7 @@ Es ist sicherer eine explizite Kodierung anzugeben, wenn das QGIS-Projekt portie
<li>Räumlichen Index nutzen. Einen räumlichen Index erzeugen, der die Anzeige- und räumliche Auswahlgeschwindigkeit verbessert.
Diese Option kann für Dateien sinnvoll sein, deren Größe einige MB übersteigt.</li>
<li>Untermengen-Index nutzen. Einen Index erzeugen, wenn eine Untermenge verwendet wird (entweder durch die Angabe eines Filters in den Layereigenschaftendialog oder implizite Untermenge, wenn nicht alle Geometrien gültig sind). Der Index wird nur erzeugt, wenn eine Untermenge definiert ist.</li>
-<li>Datei überwachen. Wenn dies eingestellt ist, überwacht QGIS die Datei auf Änderungen durch Anwendungen und läd sie neu, wenn es geändert wird. Die Karte wird nicht neugezeichnet bis der Benutzer sie aktualisiert, aber Indizes und Ausmaße werden neugeladen. Diese Option sollte gewählt werden, wenn Indizes benutzt werden und es wahrscheinlich ist, dass anderen Anwendungen die Datei ändern.</li>
+<li>Datei überwachen. Wenn dies eingestellt ist, überwacht QGIS die Datei auf Änderungen durch Anwendungen und läd sie neue, wenn es geändert wird. Die Karte wird nicht neugezeichnet bis der Benutzer sie aktualisiert, aber Indizes und Ausmaße werden neugeladen. Diese Option sollte gewählt werden, wenn Indizes benutzt werden und es wahrscheinlich ist, dass anderen Anwendungen die Datei ändern.</li>
</ul>
<h4><a name="csv">Wie Trenn-, Anführungs- und Ausnahmezeichen verwendet werden</a></h4>
@@ -92824,7 +93784,6 @@ Die folgenden Optionen können verwendet werden
<li><tt>watchFile=(yes|no)</tt> legt fest, dass der Datenanbieter das Dateisystem auf Dateiänderungen überwachen soll.</li>
<li><tt>quiet=(yes|no)</tt> legt fest, ob Fehler beim Laden des Layers in einem Dialog angezeigt werden sollen (in jedem Fall werden sie in QGIS-Protokoll geschrieben). Voreingestellt ist no. Diese Option ist in der Oberfläche nicht verfügbar</li>
</ul>
-
</translation>
</message>
<message>
@@ -93433,6 +94392,46 @@ To filter a layer before adding it to the map, double click on its name or use &
<li>Ticking <label>Search options</label> enables additional options for searching in different column types and using 2 search modes: <label>Wildcard</label> or <label>RegExp</label>.
</ul>
</source>
+ <translatorcomment><h3>Oracle-Tabelle hinzufügen</h3>
+In diesem Dialog können Sie Oracle-Layern (Tabellen mit Geometriespalten) zur Karte hinzufügen.
+<p>
+<a href="#connect">Verbindungen</a><br/>
+<a href="#add">Layer hinzufügen</a><br/>
+<a href="#filter">Layer filtern</a><br/>
+<a href="#search">Suchoptionen</a><br/>
+
+<a name="connect">
+<h4>Verbindungen</h4>
+</a>
+<ul>
+<li>Wählen Sie eine Verbindung aus der Liste und klicken Sie auf <label>Verbinden</label>.
+<li>Wenn es keine Verbindung gibt, klicken Sie auf <label>Neu</label>, um eine Verbindung anzulegen.
+<li>Um eine Verbindung zu verändern, klicken Sie auf <label>Bearbeiten</label>.
+</ul>
+<a name="add">
+<h4>Layer hinzufügen</h4>
+</a>
+Um einen Layer hinzuzufügen:
+<ol>
+<li>Wählen Sie die gewünschte Verbindung aus der Liste,
+<li>klicken Sie auf <label>Verbinden</label>,
+<li>suchen Sie den Layer, den Sie der Liste hinzufügen wollen und klicken Sie ihn an um ihn auszuwählen,
+<li>Sie können zusätzliche Layer wählen indem Sie die Strg-Taste gedrückt halten,
+<li>klicken Sie auf <label>Hinzufügen</label> um den/die Layer der Karte hinzuzufügen.
+</ol>
+<a name="filter">
+<h4>Layer filtern</h4>
+</a>
+Um Layer vor dem Hinzufügen zu Filtern klicken Sie doppelt auf deren Namen oder benutzen den Knopf <label>Abfrage erstellen</label>. Daraufhin öffnet sich der Abfrageeditor, in dem Sie SQL-Anweisungen zum Filtern der Datensätze festlegen können.
+
+<a name="#search">
+<h4>Optionen</h4>
+</a>
+<li><label>Aus Tabelle ohne Geometry anzeigen</label> gibt an, dass auch Tabellen ohne Geometre angezeigt werden sollen.
+<li><label>Dialog geöffnet halten</label> gibt an dass der Dialog nach dem Hinzufügen von Tabellen nicht geschlossen werden soll.
+<li>Anhaken von <label>Suchoptionen</label> schaltet zusätzliche Suchoptionen nach verschiedenen Spaltentypen und zwei Suchmodi zu: <label>Platzhalter</label> oder <label>RegAusdr</label>.
+</ul>
+</translatorcomment>
<translation><h3>Oracle-Tabelle hinzufügen</h3>
In diesem Dialog können Sie Oracle-Layern (Tabellen mit Geometriespalten) zur Karte hinzufügen.
<p>
@@ -93583,8 +94582,8 @@ To filter a layer before adding it to the map, double click on its name or use &
<li>Ticking <label>Search options</label> enables additional options for searching in different column types and using 2 search modes: <label>Wildcard</label> or <label>RegExp</label>.
</ul>
</source>
- <translation><h3>PostGIS-Tabelle hinzufügen</h3>
-In diesem Dialog können Sie PostgreSQL/PostGIS-Layern (Tabellen mit Geometriespalten) zur Karte hinzufügen.
+ <translation><h3>Oracle-Tabelle hinzufügen</h3>
+In diesem Dialog können Sie Oracle-Layern (Tabellen mit Geometriespalten) zur Karte hinzufügen.
<p>
<a href="#connect">Verbindungen</a><br/>
<a href="#add">Layer hinzufügen</a><br/>
@@ -95163,37 +96162,37 @@ Die folgenden Optionen können verwendet werden
<context>
<name>contour</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3077"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3111"/>
<source>Contour</source>
<translation>Kontur</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3078"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3112"/>
<source>[GDAL] Extraction</source>
<translation>[GDAL] Extraktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3079"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3113"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3080"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3114"/>
<source>Interval between contour lines</source>
<translation>Intervall zwischen Konturlinien</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3081"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3115"/>
<source>Attribute name (if not set, no elevation attribute is attached)</source>
<translation>Attributname (wenn nicht angegeben, wird kein Höhenattribut zugefügt)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3082"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3116"/>
<source>Additional creation parameters</source>
<translation>Weitere Erzeugungsparameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3083"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3117"/>
<source>Contours</source>
<translation>Konturen</translation>
</message>
@@ -96065,17 +97064,17 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>expressions</name>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="3076"/>
+ <location filename="../src/core/qgsexpression.cpp" line="3160"/>
<source>Vector</source>
<translation>Vektor</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="3078"/>
+ <location filename="../src/core/qgsexpression.cpp" line="3162"/>
<source>Raster</source>
<translation>Raster</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="3080"/>
+ <location filename="../src/core/qgsexpression.cpp" line="3164"/>
<source>Plugin</source>
<translation>Plugin</translation>
</message>
@@ -96083,47 +97082,47 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>fillnodata</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3088"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3122"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3089"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3123"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3090"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3124"/>
<source>Search distance</source>
<translation>Suchdistanz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3091"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3125"/>
<source>Smooth iterations</source>
<translation>Glättungsiterationen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3092"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3126"/>
<source>Band to operate on</source>
<translation>Zu bearbeitender Kanal</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3093"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3127"/>
<source>Validity mask</source>
<translation>Gültigkeitsmaske</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3094"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3128"/>
<source>Do not use default validity mask</source>
<translation>Voreingestellte Gültigkeitsmaske nicht verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3095"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3129"/>
<source>Filled</source>
<translation>Gefüllt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3087"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3121"/>
<source>Fill nodata</source>
<translation>"Leerwert" füllen</translation>
</message>
@@ -96131,37 +97130,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>flightlinesToCHM</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3099"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3133"/>
<source>flightlinesToCHM</source>
<translation>flightlinesToCHM</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3100"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3134"/>
<source>LAStools Pipelines</source>
<translation>LAS-Tools Pipelines</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3101"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3135"/>
<source>tile size (side length of square tile)</source>
<translation>Kachelgröße (Seitenlänge der Quadrate) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3102"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3136"/>
<source>buffer around each tile (avoids edge artifacts)</source>
<translation>Buffer um einzelne Kacheln (vermeidet Randartefakte)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3103"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3137"/>
<source>terrain type</source>
<translation>Geländetyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3104"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3138"/>
<source>laser beam width (diameter of laser footprint)</source>
<translation>Laserstrahlbreite (Laserabdrucksdurchmesser)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3105"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3139"/>
<source>tile base name (using 'sydney' creates sydney_274000_4714000...)</source>
<translation>Kachelbasisname ('sydney' erzeugt sydney_274000_4714000...)</translation>
</message>
@@ -96169,32 +97168,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>flightlinesToDTMandDSM</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3109"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3143"/>
<source>flightlinesToDTMandDSM</source>
<translation>flightlinesToDTMandDSM</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3110"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3144"/>
<source>LAStools Pipelines</source>
<translation>LAS-Tools Pipelines</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3111"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3145"/>
<source>tile size (side length of square tile)</source>
<translation>Kachelgröße (Seitenlänge der Quadrate) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3112"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3146"/>
<source>buffer around each tile (avoids edge artifacts)</source>
<translation>Buffer um einzelne Kacheln (vermeidet Randartefakte)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3113"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3147"/>
<source>terrain type</source>
<translation>Geländetyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3114"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3148"/>
<source>tile base name (using 'sydney' creates sydney_274000_4714000...)</source>
<translation>Kachelbasisname ('sydney' erzeugt sydney_274000_4714000...)</translation>
</message>
@@ -96202,32 +97201,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>flightlinesToSingleCHMpitFree</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3118"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3152"/>
<source>flightlinesToSingleCHMpitFree</source>
<translation>flightlinesToSingleCHMpitFree</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3119"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3153"/>
<source>LAStools Pipelines</source>
<translation>LAS-Tools Pipelines</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3120"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3154"/>
<source>tile size (side length of square tile)</source>
<translation>Kachelgröße (Seitenlänge der Quadrate) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3121"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3155"/>
<source>buffer around each tile (avoids edge artifacts)</source>
<translation>Buffer um einzelne Kacheln (vermeidet Randartefakte)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3122"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3156"/>
<source>terrain type</source>
<translation>Geländetyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3123"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3157"/>
<source>laser beam width (diameter of laser footprint)</source>
<translation>Laserstrahlbreite (Laserabdrucksdurchmesser)</translation>
</message>
@@ -96235,92 +97234,92 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>gdal2tiles</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3127"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3161"/>
<source>gdal2tiles</source>
<translation>gdal2tiles</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3128"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3162"/>
<source>[GDAL] Miscellaneous</source>
<translation>[GDAL] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3129"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3163"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3130"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3164"/>
<source>Tile cutting profile</source>
<translation>Kachelschneideprofil</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3131"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3165"/>
<source>Resampling method</source>
<translation>Abtastmethode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3132"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3166"/>
<source>The spatial reference system used for the source input data</source>
<translation>Das räumliche Bezugssystem der Eingabedaten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3133"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3167"/>
<source>Zoom levels to render</source>
<translation>Darzustellende Zoomstufen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3134"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3168"/>
<source>Resume mode, generate only missing files</source>
<translation>Wiederaufnahmemodus, nur fehlende Dateien erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3135"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3169"/>
<source>NODATA transparency value to assign to the input data</source>
<translation>Den Eingabedaten zuzuweisender Leer-Transparenzwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3136"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3170"/>
<source>Generate KML for Google Earth - default for "geodetic" profile and "raster" in EPSG:4326</source>
<translation>KML für Google-Earth erzeugen - voreingestellt auf "geodätisches" Profil und "Raster" in EPSG:4326</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3137"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3171"/>
<source>Avoid automatic generation of KML files for EPSG:4326</source>
<translation>Automatische Erzeugung von KML-Dateien für EPSG:4326 vermeiden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3138"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3172"/>
<source>URL address where the generated tiles are going to be published</source>
<translation>URL unter der die generierten Kacheln veröffentlich werden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3139"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3173"/>
<source>Web viewer to generate</source>
<translation>Zu erzeugende Webanzeige</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3140"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3174"/>
<source>Title of the map</source>
<translation>Kartentitel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3141"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3175"/>
<source>Copyright for the map</source>
<translation>Urheberrecht der Karte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3142"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3176"/>
<source>Google Maps API key from http://code.google.com/apis/maps/signup.html</source>
<translation>Google-Maps-API-Schlüssel von http://code.google.com/apis/maps/signup.html</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3143"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3177"/>
<source>Bing Maps API key from https://www.bingmapsportal.com/</source>
<translation>Bing-Maps-API-Schlüssel von https://www.bingmapsportal.com/</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3144"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3178"/>
<source>The directory where the tile result is created</source>
<translation>Verzeichnis in dem die Ergebniskacheln erzeugt werden sollen</translation>
</message>
@@ -96328,27 +97327,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>gdal2xyz</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3149"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3183"/>
<source>[GDAL] Conversion</source>
<translation>[GDAL] Konvertierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3150"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3184"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3151"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3185"/>
<source>Band number</source>
<translation>Kanalnummer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3152"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3186"/>
<source>xyz</source>
<translation>xyz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3148"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3182"/>
<source>gdal2xyz</source>
<translation>gdal2xyz</translation>
</message>
@@ -96356,42 +97355,42 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>gdaladdo</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3157"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3191"/>
<source>[GDAL] Miscellaneous</source>
<translation>[GDAL] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3158"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3192"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3159"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3193"/>
<source>Overview levels</source>
<translation>Übersichtsebenen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3160"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3194"/>
<source>Remove all existing overviews</source>
<translation>Alle Übersichten entfernen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3161"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3195"/>
<source>Resampling method</source>
<translation>Abtastmethode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3162"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3196"/>
<source>Overview format</source>
<translation>Übersichtsformat</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3163"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3197"/>
<source>Pyramidized</source>
<translation>Ausgabe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3156"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3190"/>
<source>Build overviews (pyramids)</source>
<translation>Übersichten erzeugen (Pyramiden)</translation>
</message>
@@ -96399,97 +97398,97 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>gdalcalc</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3168"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3202"/>
<source>[GDAL] Miscellaneous</source>
<translation>[GDAL] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3169"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3203"/>
<source>Input layer A</source>
<translation>Eingabelayer A</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3170"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3204"/>
<source>Number of raster band for raster A</source>
<translation>Kanalnummer für Raster A</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3171"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3205"/>
<source>Input layer B</source>
<translation>Eingabelayer B</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3172"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3206"/>
<source>Number of raster band for raster B</source>
<translation>Kanalnummer für Raster B</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3173"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3207"/>
<source>Input layer C</source>
<translation>Eingabelayer C</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3174"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3208"/>
<source>Number of raster band for raster C</source>
<translation>Kanalnummer für Raster C</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3175"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3209"/>
<source>Input layer D</source>
<translation>Eingabelayer D</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3176"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3210"/>
<source>Number of raster band for raster D</source>
<translation>Kanalnummer für Raster D</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3177"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3211"/>
<source>Input layer E</source>
<translation>Eingabelayer E</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3178"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3212"/>
<source>Number of raster band for raster E</source>
<translation>Kanalnummer für Raster E</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3179"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3213"/>
<source>Input layer F</source>
<translation>Eingabelayer F</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3180"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3214"/>
<source>Number of raster band for raster F</source>
<translation>Kanalnummer für Raster F</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3181"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3215"/>
<source>Calculation in gdalnumeric syntax using +-/* or any numpy array functions (i.e. logical_and())</source>
<translation>Berechnung in Syntax von gdalnumeric mit +-/* oder anderen Numpy-Feldfunktionen (z.B. logical_end()) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3182"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3216"/>
<source>Set output nodata value</source>
<translation>Ausgabeleerwert festlegen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3183"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3217"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3184"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3218"/>
<source>Additional creation parameters</source>
<translation>Zusaätzliche Erzeugungsparameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3185"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3219"/>
<source>Calculated</source>
<translation>Berechnet</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3167"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3201"/>
<source>Raster calculator</source>
<translation>Rasterrechner</translation>
</message>
@@ -96497,32 +97496,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>gdaltindex</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3190"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3224"/>
<source>[GDAL] Miscellaneous</source>
<translation>[GDAL] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3191"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3225"/>
<source>Input layers</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3192"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3226"/>
<source>Tile index field</source>
<translation>Kachelindexfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3193"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3227"/>
<source>Skip files with different projection reference</source>
<translation>Dateien mit anderer Projektion überspringen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3194"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3228"/>
<source>Tile index</source>
<translation>Kachelindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3189"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3223"/>
<source>Tile Index</source>
<translation>Kachelindex</translation>
</message>
@@ -99108,52 +100107,52 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>hillshade</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3199"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3233"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3200"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3234"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3201"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3235"/>
<source>Band number</source>
<translation>Kanalnummer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3202"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3236"/>
<source>Compute edges</source>
<translation>Kanten berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3203"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3237"/>
<source>Use Zevenbergen&Thorne formula (instead of the Horn's one)</source>
<translation>Benutze Zevenbergen&Thorne Formel (statt Horn)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3204"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3238"/>
<source>Z factor (vertical exaggeration)</source>
<translation>Z-Faktor (Vertikale Überhöhung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3205"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3239"/>
<source>Scale (ratio of vert. units to horiz.)</source>
<translation>Skalierung (Verh. von vert. zu horz. Einheiten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3206"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3240"/>
<source>Azimuth of the light</source>
<translation>Azimut des Lichts</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3207"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3241"/>
<source>Altitude of the light</source>
<translation>Höhe des Lichts</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3198"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3232"/>
<source>Hillshade</source>
<translation>Schummerung</translation>
</message>
@@ -99161,37 +100160,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>hugeFileClassify</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3211"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3245"/>
<source>hugeFileClassify</source>
<translation>hugeFileClassify</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3212"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3246"/>
<source>LAStools Pipelines</source>
<translation>LAS-Tools Pipelines</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3213"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3247"/>
<source>tile size (side length of square tile)</source>
<translation>Kachelgröße (Seitenlänge der Quadrate) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3214"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3248"/>
<source>buffer around each tile (avoids edge artifacts)</source>
<translation>Buffer um einzelne Kacheln (vermeidet Randartefakte)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3215"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3249"/>
<source>airborne LiDAR</source>
<translation>Luft-LiDAR</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3216"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3250"/>
<source>terrain type</source>
<translation>Geländetyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3217"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3251"/>
<source>preprocessing</source>
<translation>Vorverarbeitung</translation>
</message>
@@ -99199,37 +100198,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>hugeFileGroundClassify</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3221"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3255"/>
<source>hugeFileGroundClassify</source>
<translation>hugeFileGroundClassify</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3222"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3256"/>
<source>LAStools Pipelines</source>
<translation>LAS-Tools Pipelines</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3223"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3257"/>
<source>tile size (side length of square tile)</source>
<translation>Kachelgröße (Seitenlänge der Quadrate) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3224"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3258"/>
<source>buffer around each tile (avoids edge artifacts)</source>
<translation>Buffer um einzelne Kacheln (vermeidet Randartefakte)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3225"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3259"/>
<source>airborne LiDAR</source>
<translation>Luft-LiDAR</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3226"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3260"/>
<source>terrain type</source>
<translation>Geländetyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3227"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3261"/>
<source>preprocessing</source>
<translation>Vorverarbeitung</translation>
</message>
@@ -99237,37 +100236,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>hugeFileNormalize</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3231"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3265"/>
<source>hugeFileNormalize</source>
<translation>hugeFileNormalize</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3232"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3266"/>
<source>LAStools Pipelines</source>
<translation>LAS-Tools Pipelines</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3233"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3267"/>
<source>tile size (side length of square tile)</source>
<translation>Kachelgröße (Seitenlänge der Quadrate) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3234"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3268"/>
<source>buffer around each tile (avoids edge artifacts)</source>
<translation>Buffer um einzelne Kacheln (vermeidet Randartefakte)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3235"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3269"/>
<source>airborne LiDAR</source>
<translation>Luft-LiDAR</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3236"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3270"/>
<source>terrain type</source>
<translation>Geländetyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3237"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3271"/>
<source>preprocessing</source>
<translation>Vorverarbeitung</translation>
</message>
@@ -99275,32 +100274,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>information</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3242"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3276"/>
<source>[GDAL] Miscellaneous</source>
<translation>[GDAL] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3243"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3277"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3244"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3278"/>
<source>Suppress GCP info</source>
<translation>Paßpunktinformation unterdrücken</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3245"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3279"/>
<source>Suppress metadata info</source>
<translation>Metadateninfo unterdrücken</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3246"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3280"/>
<source>Layer information</source>
<translation>Layerinformation</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3241"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3275"/>
<source>Information</source>
<translation>Information</translation>
</message>
@@ -99308,27 +100307,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2dem</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3250"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3284"/>
<source>las2dem</source>
<translation>las2dem</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3251"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3285"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3252"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3286"/>
<source>Attribute</source>
<translation>Attribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3253"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3287"/>
<source>Product</source>
<translation>Produkt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3254"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3288"/>
<source>use tile bounding box (after tiling with buffer)</source>
<translation>Benutze Kachel Begrenzungsrahmen (nach Buffer)</translation>
</message>
@@ -99336,27 +100335,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2demPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3258"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3292"/>
<source>las2demPro</source>
<translation>las2demPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3259"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3293"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3260"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3294"/>
<source>attribute (what to interpolate)</source>
<translation>Attribute (zu Interpolieren)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3261"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3295"/>
<source>product (how to output per pixel)</source>
<translation>Produkt (Pixelausgabe)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3262"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3296"/>
<source>use tile bounding box (after tiling with buffer)</source>
<translation>Benutze Kachel Begrenzungsrahmen (nach Buffer)</translation>
</message>
@@ -99364,37 +100363,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2iso</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3266"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3300"/>
<source>las2iso</source>
<translation>las2iso</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3267"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3301"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3268"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3302"/>
<source>smooth underlying TIN</source>
<translation>Zugrundeliegendes TIN glätten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3269"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3303"/>
<source>extract isoline with a spacing of</source>
<translation>Extrahiere Isolinie mit einem Abstand von</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3270"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3304"/>
<source>clean isolines shorter than (0 = do not clean)</source>
<translation>Segmente vereinfachen kürzer als (0 = nicht vereinfachen) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3271"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3305"/>
<source>simplify segments shorter than (0 = do not simplify)</source>
<translation>Segmente vereinfachen kürzer als (0 = nicht vereinfachen) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3272"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3306"/>
<source>simplify segments pairs with area less than (0 = do not simplify)</source>
<translation>Segmentpaare vereinfachen mit Fläche kleiner als (0 = nicht vereinfachen) </translation>
</message>
@@ -99402,12 +100401,12 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2lasPro_filter</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3276"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3310"/>
<source>las2lasPro_filter</source>
<translation>las2lasPro_filter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3277"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3311"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
@@ -99415,42 +100414,42 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2lasPro_project</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3281"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3315"/>
<source>las2lasPro_project</source>
<translation>las2lasPro_project</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3282"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3316"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3283"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3317"/>
<source>source projection</source>
<translation>Quellprojektion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3284"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3318"/>
<source>source utm zone</source>
<translation>Quell-UTM-Zone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3285"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3319"/>
<source>source state plane code</source>
<translation>US-Koodinatensystemkennung Quelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3286"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3320"/>
<source>target projection</source>
<translation>Zielprojektion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3287"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3321"/>
<source>target utm zone</source>
<translation>Ziel-UTM-Zone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3288"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3322"/>
<source>target state plane code</source>
<translation>US-Koodinatensystemkennung Ziel</translation>
</message>
@@ -99458,22 +100457,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2lasPro_transform</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3292"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3326"/>
<source>las2lasPro_transform</source>
<translation>las2lasPro_transform</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3293"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3327"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3294"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3328"/>
<source>operations (first 8 need an argument)</source>
<translation>Operationen (die ersten 8 brauchen ein Argument)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3295"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3329"/>
<source>argument for operation</source>
<translation>Argument für Operation</translation>
</message>
@@ -99481,12 +100480,12 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2las_filter</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3299"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3333"/>
<source>las2las_filter</source>
<translation>las2las_filter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3300"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3334"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
@@ -99494,42 +100493,42 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2las_project</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3304"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3338"/>
<source>las2las_project</source>
<translation>las2las_project</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3305"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3339"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3306"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3340"/>
<source>source projection</source>
<translation>Quellprojektion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3307"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3341"/>
<source>source utm zone</source>
<translation>Quell-UTM-Zone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3308"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3342"/>
<source>source state plane code</source>
<translation>US-Koodinatensystemkennung Quelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3309"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3343"/>
<source>target projection</source>
<translation>Zielprojektion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3310"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3344"/>
<source>target utm zone</source>
<translation>Ziel-UTM-Zone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3311"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3345"/>
<source>target state plane code</source>
<translation>US-Koodinatensystemkennung Ziel</translation>
</message>
@@ -99537,22 +100536,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2las_transform</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3315"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3349"/>
<source>las2las_transform</source>
<translation>las2las_transform</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3316"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3350"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3317"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3351"/>
<source>operations (first 8 need an argument)</source>
<translation>Operationen (die ersten 8 brauchen ein Argument)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3318"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3352"/>
<source>argument for operation</source>
<translation>Argument für Operation</translation>
</message>
@@ -99560,27 +100559,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2shp</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3322"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3356"/>
<source>las2shp</source>
<translation>las2shp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3323"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3357"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3324"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3358"/>
<source>use PointZ instead of MultiPointZ</source>
<translation>PointZ statt MultiPointZ nutzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3325"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3359"/>
<source>number of points per record</source>
<translation>Anzahl der Punkte je Datensatz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3326"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3360"/>
<source>Output SHP file</source>
<translation>Ausgabeshapedatei</translation>
</message>
@@ -99588,12 +100587,12 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2tin</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3330"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3364"/>
<source>las2tin</source>
<translation>las2tin</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3331"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3365"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
@@ -99601,22 +100600,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2txt</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3335"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3369"/>
<source>las2txt</source>
<translation>las2txt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3336"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3370"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3337"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3371"/>
<source>parse string</source>
<translation>Analysiere Text</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3338"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3372"/>
<source>Output ASCII file</source>
<translation>ASCII-Ausgabedatei</translation>
</message>
@@ -99624,17 +100623,17 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>las2txtPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3342"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3376"/>
<source>las2txtPro</source>
<translation>las2txtPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3343"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3377"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3344"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3378"/>
<source>parse string</source>
<translation>Analysiere Text</translation>
</message>
@@ -99642,32 +100641,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasboundary</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3348"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3382"/>
<source>lasboundary</source>
<translation>lasboundary</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3349"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3383"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3350"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3384"/>
<source>compute boundary based on</source>
<translation>berechne Grenzen basierend auf</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3351"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3385"/>
<source>concavity</source>
<translation>Wölbung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3352"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3386"/>
<source>interior holes</source>
<translation>Innere Löcher</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3353"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3387"/>
<source>disjoint polygon</source>
<translation>getrenntes Polygon</translation>
</message>
@@ -99675,32 +100674,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasboundaryPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3357"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3391"/>
<source>lasboundaryPro</source>
<translation>lasboundaryPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3358"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3392"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3359"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3393"/>
<source>compute boundary based on</source>
<translation>berechne Grenzen basierend auf</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3360"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3394"/>
<source>concavity</source>
<translation>Wölbung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3361"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3395"/>
<source>interior holes</source>
<translation>Innere Löcher</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3362"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3396"/>
<source>disjoint polygon</source>
<translation>getrenntes Polygon</translation>
</message>
@@ -99708,47 +100707,47 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lascanopy</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3366"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3400"/>
<source>lascanopy</source>
<translation>lascanopy</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3367"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3401"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3368"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3402"/>
<source>square plot size</source>
<translation>Quadratische Plottgröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3369"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3403"/>
<source>height cutoff / breast height</source>
<translation>abgeschnittene Höhe / Brusthöhe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3370"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3404"/>
<source>create</source>
<translation>erzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3371"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3405"/>
<source>count rasters (e.g. 2.0 5.0 10.0 20.0)</source>
<translation>Rasteranzahl (z.B. 2.0 5.0 10.0 20.0)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3372"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3406"/>
<source>density rasters (e.g. 2.0 5.0 10.0 20.0)</source>
<translation>Dichteraster (z.B. 2.0 5.0 10.0 20.0)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3373"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3407"/>
<source>use tile bounding box (after tiling with buffer)</source>
<translation>Benutze Kachel Begrenzungsrahmen (nach Buffer)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3374"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3408"/>
<source>input file is single plot</source>
<translation>Eingabedatei ist ein einzelner Plott</translation>
</message>
@@ -99756,47 +100755,47 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lascanopyPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3378"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3412"/>
<source>lascanopyPro</source>
<translation>lascanopyPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3379"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3413"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3380"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3414"/>
<source>square plot size</source>
<translation>Quadratische Plattgröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3381"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3415"/>
<source>height cutoff / breast height</source>
<translation>abgeschnittene Höhe / Brusthöhe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3382"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3416"/>
<source>create</source>
<translation>erzeuge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3383"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3417"/>
<source>count rasters (e.g. 2.0 5.0 10.0 20.0)</source>
<translation>Rasteranzahl (z.B. 2.0 5.0 10.0 20.0)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3384"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3418"/>
<source>density rasters (e.g. 2.0 5.0 10.0 20.0)</source>
<translation>Dichteraster (z.B. 2.0 5.0 10.0 20.0)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3385"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3419"/>
<source>use tile bounding box (after tiling with buffer)</source>
<translation>Benutze Kachel Begrenzungsrahmen (nach Buffer)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3386"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3420"/>
<source>input file is single plot</source>
<translation>Eingabedatei ist einzelner Plott</translation>
</message>
@@ -99804,12 +100803,12 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasclassify</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3390"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3424"/>
<source>lasclassify</source>
<translation>lasclassify</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3391"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3425"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
@@ -99817,12 +100816,12 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasclassifyPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3395"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3429"/>
<source>lasclassifyPro</source>
<translation>lasclassifyPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3396"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3430"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
@@ -99830,32 +100829,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasclip</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3400"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3434"/>
<source>lasclip</source>
<translation>lasclip</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3401"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3435"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3402"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3436"/>
<source>Input polygon(s)</source>
<translation>Eingabepolygon(e)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3403"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3437"/>
<source>interior</source>
<translation>Innenbereich</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3404"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3438"/>
<source>what to do with points</source>
<translation>Was mit Punkten zu tun ist</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3405"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3439"/>
<source>classify as</source>
<translation>klassifiziere als</translation>
</message>
@@ -99863,17 +100862,17 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lascolor</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3409"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3443"/>
<source>lascolor</source>
<translation>lascolor</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3410"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3444"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3411"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3445"/>
<source>Input ortho</source>
<translation>Eingabe Ortho</translation>
</message>
@@ -99881,32 +100880,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lascontrol</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3415"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3449"/>
<source>lascontrol</source>
<translation>lascontrol</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3416"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3450"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3417"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3451"/>
<source>ASCII text file of control points</source>
<translation>ASCII-Textdatei mit Kontrollpunkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3418"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3452"/>
<source>parse string marking which columns are xyz (use 's' for skip)</source>
<translation>Zeichenkettenmarkierung für xyz-Spalten ('s' zum Überspringen)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3419"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3453"/>
<source>which points to use for elevation checks</source>
<translation>Zur Höhenkontrolle zu verwendene Punkte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3420"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3454"/>
<source>adjust z elevation by translating away the average error</source>
<translation>Z-Höhe durch Herausrechnen des durchschnittlichen Fehlers anpassen</translation>
</message>
@@ -99914,27 +100913,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasdiff</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3424"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3458"/>
<source>lasdiff</source>
<translation>lasdiff</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3425"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3459"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3426"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3460"/>
<source>other input LAS/LAZ file</source>
<translation>weitere LAS/LAZ-Eingabedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3427"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3461"/>
<source>stop reporting difference after this many points</source>
<translation>Bericht über Unterschiede nach folgender Punktanzahl einstellen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3428"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3462"/>
<source>create elevation difference file (if points are in the same order)</source>
<translation>Höhenunterschiedsdatei erzeugen (wenn die Pukte die gleiche Reihenfolge haben)</translation>
</message>
@@ -99942,32 +100941,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasduplicate</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3432"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3466"/>
<source>lasduplicate</source>
<translation>lasduplicate</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3433"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3467"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3434"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3468"/>
<source>keep duplicate with lowest z coordinate</source>
<translation>Duplikat mit niedrigster Z-Koordinate halten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3435"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3469"/>
<source>only remove duplicates in x y and z</source>
<translation>entferne nur Duplikate in x y und z</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3436"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3470"/>
<source>mark surviving duplicate as single return</source>
<translation>Markiere überlebendes Duplikat als Single Return</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3437"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3471"/>
<source>record removed duplicates to LAS/LAZ file</source>
<translation>Speichere entfernte Duplikate in die LAS/LAZ Datei</translation>
</message>
@@ -99975,32 +100974,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasduplicatePro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3441"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3475"/>
<source>lasduplicatePro</source>
<translation>lasduplicatePro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3442"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3476"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3443"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3477"/>
<source>keep duplicate with lowest z coordinate</source>
<translation>Duplikat mit niedrigster Z-Koordinate halten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3444"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3478"/>
<source>only remove duplicates in x y and z</source>
<translation>entferne nur Duplikate in x y und z</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3445"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3479"/>
<source>mark surviving duplicate as single return</source>
<translation>Markiere überlebendes Duplikat als Single Return</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3446"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3480"/>
<source>record removed duplicates</source>
<translation>Gelöschte Duplikate aufzeichnen</translation>
</message>
@@ -100008,27 +101007,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasgrid</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3450"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3484"/>
<source>lasgrid</source>
<translation>lasgrid</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3451"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3485"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3452"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3486"/>
<source>Attribute</source>
<translation>Attribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3453"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3487"/>
<source>Method</source>
<translation>Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3454"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3488"/>
<source>use tile bounding box (after tiling with buffer)</source>
<translation>Benutze Kachel Begrenzungsrahmen (nach Buffer)</translation>
</message>
@@ -100036,27 +101035,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasgridPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3458"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3492"/>
<source>lasgridPro</source>
<translation>lasgridPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3459"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3493"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3460"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3494"/>
<source>Attribute</source>
<translation>Attribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3461"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3495"/>
<source>Method</source>
<translation>Methode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3462"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3496"/>
<source>use tile bounding box (after tiling with buffer)</source>
<translation>Benutze Kachel Begrenzungsrahmen (nach Buffer)</translation>
</message>
@@ -100064,32 +101063,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasground</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3466"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3500"/>
<source>lasground</source>
<translation>lasground</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3467"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3501"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3468"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3502"/>
<source>no triangle bulging during TIN refinement</source>
<translation>keine Dreieckswölbung während TIN Verfeinerung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3469"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3503"/>
<source>classify flightlines separately (needs point source IDs populated)</source>
<translation>Fluglinien getrennt klassifizieren (Punktquellenkennungen müssen gefüllt sein) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3470"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3504"/>
<source>terrain type</source>
<translation>Geländetyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3471"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3505"/>
<source>preprocessing</source>
<translation>Vorbereitung</translation>
</message>
@@ -100097,27 +101096,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasgroundPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3475"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3509"/>
<source>lasgroundPro</source>
<translation>lasgroundPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3476"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3510"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3477"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3511"/>
<source>no triangle bulging during TIN refinement</source>
<translation>keine Dreieckswölbung während TIN Verfeinerung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3478"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3512"/>
<source>terrain type</source>
<translation>Geländetyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3479"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3513"/>
<source>preprocessing</source>
<translation>Vorverarbeitung</translation>
</message>
@@ -100125,47 +101124,47 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasgroundPro_new</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3483"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3517"/>
<source>lasgroundPro_new</source>
<translation>lasgroundPro_new</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3484"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3518"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3485"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3519"/>
<source>terrain type</source>
<translation>Geländetyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3486"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3520"/>
<source>preprocessing</source>
<translation>Vorverarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3487"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3521"/>
<source>step (for 'custom' terrain only)</source>
<translation>Schrittweite (nur für 'Benutzergelände')</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3488"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3522"/>
<source>bulge (for 'custom' terrain only)</source>
<translation>Ausbuchtung (nur für 'Benutzergelände)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3489"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3523"/>
<source>spike (for 'custom' terrain only)</source>
<translation>Spitze (nur für 'Benutzergelände')</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3490"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3524"/>
<source>down spike (for 'custom' terrain only)</source>
<translation>Tiefpunkt (nur für 'Benutzergelände')</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3491"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3525"/>
<source>offset (for 'custom' terrain only)</source>
<translation>Versatz (nur für 'Benutzergelände')</translation>
</message>
@@ -100173,47 +101172,47 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasground_new</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3495"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3529"/>
<source>lasground_new</source>
<translation>lasground_new</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3496"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3530"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3497"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3531"/>
<source>terrain type</source>
<translation>Geländetyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3498"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3532"/>
<source>preprocessing</source>
<translation>Vorverarbeitung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3499"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3533"/>
<source>step (for 'custom' terrain only)</source>
<translation>Schrittweite (nur für 'Benutzergelände')</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3500"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3534"/>
<source>bulge (for 'custom' terrain only)</source>
<translation>Ausbuchtung (nur für 'Benutzergelände)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3501"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3535"/>
<source>spike (for 'custom' terrain only)</source>
<translation>Spitze (nur für 'Benutzergelände')</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3502"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3536"/>
<source>down spike (for 'custom' terrain only)</source>
<translation>Tiefpunkt (nur für 'Benutzergelände')</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3503"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3537"/>
<source>offset (for 'custom' terrain only)</source>
<translation>Versatz (nur für 'Benutzergelände')</translation>
</message>
@@ -100221,37 +101220,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasheight</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3507"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3541"/>
<source>lasheight</source>
<translation>lasheight</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3508"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3542"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3509"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3543"/>
<source>replace z</source>
<translation>Z ersetzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3510"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3544"/>
<source>drop above</source>
<translation>ausscheiden über</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3511"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3545"/>
<source>drop above height</source>
<translation>ausscheiden über Höhe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3512"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3546"/>
<source>drop below</source>
<translation>ausscheiden unter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3513"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3547"/>
<source>drop below height</source>
<translation>ausscheiden über Höhe</translation>
</message>
@@ -100259,37 +101258,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasheightPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3517"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3551"/>
<source>lasheightPro</source>
<translation>lasheightPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3518"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3552"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3519"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3553"/>
<source>replace z</source>
<translation>Z ersetzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3520"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3554"/>
<source>drop above</source>
<translation>ausscheiden über</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3521"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3555"/>
<source>drop above height</source>
<translation>ausscheiden über Höhe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3522"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3556"/>
<source>drop below</source>
<translation>ausscheiden unter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3523"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3557"/>
<source>drop below height</source>
<translation>ausscheiden unter Höhe</translation>
</message>
@@ -100297,57 +101296,57 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasheightPro_classify</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3527"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3561"/>
<source>lasheightPro_classify</source>
<translation>lasheightPro_classify</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3528"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3562"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3529"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3563"/>
<source>replace z</source>
<translation>Z ersetzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3530"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3564"/>
<source>classify below height as</source>
<translation>Unterhöhen klassifizieren als</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3531"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3565"/>
<source>below height</source>
<translation>Unterhöhe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3532"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3566"/>
<source>classify between height as</source>
<translation>Zwischenhöhen klassifieren als</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3533"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3567"/>
<source>between height ... </source>
<translation>Zwischenhöhe ...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3534"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3568"/>
<source>... and height</source>
<translation>... und Höhe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3535"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3569"/>
<source>between height ...</source>
<translation>zwischen Höhe ...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3536"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3570"/>
<source>classify above</source>
<translation>Überklassifierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3537"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3571"/>
<source>classify above height</source>
<translation>Überhöhe klassifizieren</translation>
</message>
@@ -100355,57 +101354,57 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasheight_classify</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3541"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3575"/>
<source>lasheight_classify</source>
<translation>lasheight_classify</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3542"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3576"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3543"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3577"/>
<source>replace z</source>
<translation>Z ersetzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3544"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3578"/>
<source>classify below height as</source>
<translation>Unterhöhen klassifizieren als</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3545"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3579"/>
<source>below height</source>
<translation>Unterhöhe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3546"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3580"/>
<source>classify between height as</source>
<translation>Zwischenhöhen klassifieren als</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3547"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3581"/>
<source>between height ... </source>
<translation>zwischen Höhe ...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3548"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3582"/>
<source>... and height</source>
<translation>... und Höhe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3549"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3583"/>
<source>between height ...</source>
<translation>zwischen Höhe ...</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3550"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3584"/>
<source>classify above</source>
<translation>darüber klassifizieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3551"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3585"/>
<source>classify above height</source>
<translation>Überhöhe klassifizieren</translation>
</message>
@@ -100413,22 +101412,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasindex</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3555"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3589"/>
<source>lasindex</source>
<translation>lasindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3556"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3590"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3557"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3591"/>
<source>append *.lax file to *.laz file</source>
<translation>LAX-Datei an LAZ-Datei anhängen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3558"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3592"/>
<source>is mobile or terrestrial LiDAR (not airborne)</source>
<translation>ist mobiles oder terrestrisches LIDAR (nicht aus der Luft)</translation>
</message>
@@ -100436,22 +101435,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasindexPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3562"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3596"/>
<source>lasindexPro</source>
<translation>lasindexPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3563"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3597"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3564"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3598"/>
<source>append *.lax file to *.laz file</source>
<translation>LAX-Datei an LAZ-Datei anhängen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3565"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3599"/>
<source>is mobile or terrestrial LiDAR (not airborne)</source>
<translation>ist mobiles oder terrestrisches LIDAR (nicht aus der Luft)</translation>
</message>
@@ -100459,42 +101458,42 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasinfo</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3569"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3603"/>
<source>lasinfo</source>
<translation>lasinfo</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3570"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3604"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3571"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3605"/>
<source>compute density</source>
<translation>Dichte berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3572"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3606"/>
<source>repair bounding box</source>
<translation>repariere Begrenzungsrahmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3573"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3607"/>
<source>repair counters</source>
<translation>Zähler reparieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3574"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3608"/>
<source>histogram</source>
<translation>Histogramm</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3575"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3609"/>
<source>bin size</source>
<translation>bin Größe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3576"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3610"/>
<source>Output ASCII file</source>
<translation>ASCII-Ausgabedatei</translation>
</message>
@@ -100502,37 +101501,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasinfoPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3580"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3614"/>
<source>lasinfoPro</source>
<translation>lasinfoPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3581"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3615"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3582"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3616"/>
<source>compute density</source>
<translation>Dichte berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3583"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3617"/>
<source>repair bounding box</source>
<translation>repariere Begrenzungsrahmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3584"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3618"/>
<source>repair counters</source>
<translation>Zähler reparieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3585"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3619"/>
<source>histogram</source>
<translation>Histogramm</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3586"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3620"/>
<source>bin size</source>
<translation>bin Größe</translation>
</message>
@@ -100540,42 +101539,42 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasmerge</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3590"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3624"/>
<source>lasmerge</source>
<translation>lasmerge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3591"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3625"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3592"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3626"/>
<source>2nd file</source>
<translation>2. Datei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3593"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3627"/>
<source>3rd file</source>
<translation>3. Datei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3594"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3628"/>
<source>4th file</source>
<translation>4. Datei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3595"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3629"/>
<source>5th file</source>
<translation>5. Datei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3596"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3630"/>
<source>6th file</source>
<translation>6. Datei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3597"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3631"/>
<source>7th file</source>
<translation>7. Datei</translation>
</message>
@@ -100583,12 +101582,12 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasmergePro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3601"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3635"/>
<source>lasmergePro</source>
<translation>lasmergePro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3602"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3636"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
@@ -100596,37 +101595,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasnoise</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3606"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3640"/>
<source>lasnoise</source>
<translation>lasnoise</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3607"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3641"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3608"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3642"/>
<source>isolated if surrounding cells have only</source>
<translation>isoliert wenn umgebende Zellen haben nur</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3609"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3643"/>
<source>resolution of isolation grid in xy</source>
<translation>Auflösung des Isolationsgitters in xy</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3610"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3644"/>
<source>resolution of isolation grid in z</source>
<translation>Auflösung des Isolationsgitters in z</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3611"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3645"/>
<source>what to do with isolated points</source>
<translation>was machen mit isolierten Punkten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3612"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3646"/>
<source>classify as</source>
<translation>klassifiziere als</translation>
</message>
@@ -100634,37 +101633,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasnoisePro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3616"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3650"/>
<source>lasnoisePro</source>
<translation>lasnoisePro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3617"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3651"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3618"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3652"/>
<source>isolated if surrounding cells have only</source>
<translation>isoliert wenn umgebende Zellen haben nur</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3619"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3653"/>
<source>resolution of isolation grid in xy</source>
<translation>Auflösung des Isolationsgitters in xy</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3620"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3654"/>
<source>resolution of isolation grid in z</source>
<translation>Auflösung des Isolationsgitters in z</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3621"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3655"/>
<source>what to do with isolated points</source>
<translation>was machen mit isolierten Punkten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3622"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3656"/>
<source>classify as</source>
<translation>klassifiziere als</translation>
</message>
@@ -100672,22 +101671,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasoverage</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3626"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3660"/>
<source>lasoverage</source>
<translation>lasoverage</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3627"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3661"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3628"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3662"/>
<source>size of grid used for scan angle check</source>
<translation>Größe des Gitters zur Scanwinkel Überprüfung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3629"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3663"/>
<source>mode of operation</source>
<translation>Modus der Operation</translation>
</message>
@@ -100695,22 +101694,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasoveragePro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3633"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3667"/>
<source>lasoveragePro</source>
<translation>lasoveragePro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3634"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3668"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3635"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3669"/>
<source>size of grid used for scan angle check</source>
<translation>Größe des Gitters zur Scanwinkel Überprüfung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3636"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3670"/>
<source>mode of operation</source>
<translation>Modus der Operation</translation>
</message>
@@ -100718,37 +101717,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasoverlap</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3640"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3674"/>
<source>lasoverlap</source>
<translation>lasoverlap</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3641"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3675"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3642"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3676"/>
<source>size of grid used for overlap check</source>
<translation>Größe des Rasters das für Überlappungstest benutzt wird</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3643"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3677"/>
<source>attribute to check</source>
<translation>Zu prüfendes Attribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3644"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3678"/>
<source>operation on attribute per cell</source>
<translation>Operation auf Attribut per Zelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3645"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3679"/>
<source>create overlap raster</source>
<translation>erzeuge überlappendes Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3646"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3680"/>
<source>create difference raster</source>
<translation>erzeuge Differenzenraster</translation>
</message>
@@ -100756,37 +101755,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasoverlapPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3650"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3684"/>
<source>lasoverlapPro</source>
<translation>lasoverlapPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3651"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3685"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3652"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3686"/>
<source>size of grid used for overlap check</source>
<translation>Größe des Rasters welches für Überlappungstest benutzt wird</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3653"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3687"/>
<source>attribute to check</source>
<translation>Zu prüfendes Attribut</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3654"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3688"/>
<source>operation on attribute per cell</source>
<translation>Operation auf Attribut per Zelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3655"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3689"/>
<source>create overlap raster</source>
<translation>erzeuge überlappendes Raster</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3656"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3690"/>
<source>create difference raster</source>
<translation>erzeuge Differenzenraster</translation>
</message>
@@ -100794,17 +101793,17 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasprecision</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3660"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3694"/>
<source>lasprecision</source>
<translation>lasprecision</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3661"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3695"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3662"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3696"/>
<source>Output ASCII file</source>
<translation>ASCII-Ausgabedatei</translation>
</message>
@@ -100812,62 +101811,62 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>laspublish</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3666"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3700"/>
<source>laspublish</source>
<translation>laspublish</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3667"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3701"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3668"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3702"/>
<source>type of portal</source>
<translation>Portaltyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3669"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3703"/>
<source>use Eye Dome Lighting (EDL)</source>
<translation>Eye-Dome-Lighting (EDL) verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3670"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3704"/>
<source>show Skybox</source>
<translation>Skybox anzeigen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3671"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3705"/>
<source>default material colors on start-up</source>
<translation>Vorgabematerialfarben beim Start</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3672"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3706"/>
<source>portal output directory</source>
<translation>Portalausgabeverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3673"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3707"/>
<source>copy or move source LiDAR files into portal (only for download portals)</source>
<translation>LiDAR-Quelldateien ins Portal kopieren oder verschieben (nur für Portale zum Herunterladen)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3674"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3708"/>
<source>overwrite existing files</source>
<translation>Vorhandene Dateien überschreiben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3675"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3709"/>
<source>portal HTML page</source>
<translation>Portal-HTML-Seite</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3676"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3710"/>
<source>portal title</source>
<translation>Portal-Titel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3677"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3711"/>
<source>portal description</source>
<translation>Portal-Beschreibung</translation>
</message>
@@ -100875,62 +101874,62 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>laspublishPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3681"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3715"/>
<source>laspublishPro</source>
<translation>laspublishPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3682"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3716"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3683"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3717"/>
<source>type of portal</source>
<translation>Portaltyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3684"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3718"/>
<source>use Eye Dome Lighting (EDL)</source>
<translation>Eye-Dome-Lighting (EDL) verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3685"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3719"/>
<source>show Skybox</source>
<translation>Skybox anzeigen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3686"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3720"/>
<source>default material colors on start-up</source>
<translation>Vorgabematerialfarben beim Start</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3687"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3721"/>
<source>portal output directory</source>
<translation>Portalausgabeverzeichnis</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3688"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3722"/>
<source>copy or move source LiDAR files into portal (only for download portals)</source>
<translation>LiDAR-Quelldateien ins Portal kopieren oder verschieben (nur für Portale zum Herunterladen)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3689"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3723"/>
<source>overwrite existing files</source>
<translation>Vorhandene Dateien überschreiben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3690"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3724"/>
<source>portal HTML page</source>
<translation>Portal-HTML-Seite</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3691"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3725"/>
<source>portal title</source>
<translation>Portal-Titel</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3692"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3726"/>
<source>portal description</source>
<translation>Portal-Beschreibung</translation>
</message>
@@ -100938,17 +101937,17 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasquery</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3696"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3730"/>
<source>lasquery</source>
<translation>lasquery</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3697"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3731"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3698"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3732"/>
<source>area of interest</source>
<translation>Interessensgebiet</translation>
</message>
@@ -100956,22 +101955,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lassort</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3702"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3736"/>
<source>lassort</source>
<translation>lassort</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3703"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3737"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3704"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3738"/>
<source>sort by GPS time</source>
<translation>sortiere nach GPS Zeit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3705"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3739"/>
<source>sort by point source ID</source>
<translation>Nach Punktquellkennung sortieren</translation>
</message>
@@ -100979,22 +101978,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lassortPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3709"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3743"/>
<source>lassortPro</source>
<translation>lassortPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3710"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3744"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3711"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3745"/>
<source>sort by GPS time</source>
<translation>sortiere nach GPS Zeit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3712"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3746"/>
<source>sort by point source ID</source>
<translation>Nach Punktquellkennung sortieren</translation>
</message>
@@ -101002,27 +102001,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lassplit</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3716"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3750"/>
<source>lassplit</source>
<translation>lassplit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3717"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3751"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3718"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3752"/>
<source>number of digits for file names</source>
<translation>Anzahl der Stellen für Dateinamen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3719"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3753"/>
<source>how to split</source>
<translation>Wie zu teilen ist</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3720"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3754"/>
<source>interval or number</source>
<translation>Interval oder Nummer</translation>
</message>
@@ -101030,42 +102029,42 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasthin</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3724"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3758"/>
<source>lasthin</source>
<translation>lasthin</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3725"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3759"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3726"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3760"/>
<source>size of grid used for thinning</source>
<translation>Größe des Gitters zum Ausdünnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3727"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3761"/>
<source>keep particular point per cell</source>
<translation>Bestimmten Punkt je Zelle halten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3728"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3762"/>
<source>vertical threshold or contour intervals (only for 'adaptive' or 'contours' thinning)</source>
<translation>Vertikalereserve oder Konturintervalle (nur für 'adaptive' oder Konturausdünnung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3729"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3763"/>
<source>mark thinned-away points as withheld</source>
<translation>Ausgedünnte Punkte als unterdrückt kennzeichnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3730"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3764"/>
<source>classify surviving points as class</source>
<translation>Verbleibende Punkte als Klasse ansehen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3731"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3765"/>
<source>class</source>
<translation>Klasse</translation>
</message>
@@ -101073,42 +102072,42 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasthinPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3735"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3769"/>
<source>lasthinPro</source>
<translation>lasthinPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3736"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3770"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3737"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3771"/>
<source>size of grid used for thinning</source>
<translation>Gittergröße zum Ausdünnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3738"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3772"/>
<source>keep particular point per cell</source>
<translation>Bestimmten Punkt je Zelle halten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3739"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3773"/>
<source>vertical threshold or contour intervals (only for 'adaptive' or 'contours' thinning)</source>
<translation>Vertikalereserve oder Konturintervalle (nur für 'adaptive' oder Konturausdünnung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3740"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3774"/>
<source>mark thinned-away points as withheld</source>
<translation>Ausgedünnten Punkt als unterdrückt kennzeichnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3741"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3775"/>
<source>classify surviving points as class</source>
<translation>Verbleibende Punkt als Klasse ansehen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3742"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3776"/>
<source>class</source>
<translation>Klasse</translation>
</message>
@@ -101116,32 +102115,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lastile</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3746"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3780"/>
<source>lastile</source>
<translation>lastile</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3747"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3781"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3748"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3782"/>
<source>tile size (side length of square tile)</source>
<translation>Kachelgröße (Seitenlänge der Quadrate) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3749"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3783"/>
<source>buffer around each tile</source>
<translation>Puffer um einzelne Kacheln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3750"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3784"/>
<source>flag buffer points as 'withheld' for easier removal later</source>
<translation>Pufferpunkte zur einfachen späteren Entfernung als 'zurückgehalten' markieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3751"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3785"/>
<source>make tiling reversible (advanced, usually not needed)</source>
<translation>Kachelung umkehrbar machen (fortgeschritten, normalerweise nicht nötig)</translation>
</message>
@@ -101149,37 +102148,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lastilePro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3755"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3789"/>
<source>lastilePro</source>
<translation>lastilePro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3756"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3790"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3757"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3791"/>
<source>tile size (side length of square tile)</source>
<translation>Kachelgröße (Seitenlänge der Quadrate) </translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3758"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3792"/>
<source>buffer around each tile (avoids edge artifacts)</source>
<translation>Buffer um einzelne Kacheln (vermeidet Randartefakte)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3759"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3793"/>
<source>flag buffer points as 'withheld' for easier removal later</source>
<translation>Pufferpunkte zur einfachen späteren Entfernung als 'zurückgehalten' markieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3760"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3794"/>
<source>more than 2000 tiles</source>
<translation>mehr als 2000 Kacheln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3761"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3795"/>
<source>tile base name (using sydney.laz creates sydney_274000_4714000.laz)</source>
<translation>Kachelbasisname ('sydney.laz' erzeugt sydney_274000_4714000.laz)</translation>
</message>
@@ -101187,22 +102186,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasvalidate</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3765"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3799"/>
<source>lasvalidate</source>
<translation>lasvalidate</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3766"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3800"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3767"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3801"/>
<source>save report to '*_LVS.xml'</source>
<translation>Speichert Report unter '*_LVS.xml'</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3768"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3802"/>
<source>Output XML file</source>
<translation>XML-Ausgabedatei</translation>
</message>
@@ -101210,22 +102209,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasvalidatePro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3772"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3806"/>
<source>lasvalidatePro</source>
<translation>lasvalidatePro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3773"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3807"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3774"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3808"/>
<source>generate one '*_LVS.xml' report per file</source>
<translation>erzeugt einen '*_LVS.xml' Report pro Datei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3775"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3809"/>
<source>Output XML file</source>
<translation>XML-Ausgabedatei</translation>
</message>
@@ -101233,27 +102232,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasview</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3779"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3813"/>
<source>lasview</source>
<translation>lasview</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3780"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3814"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3781"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3815"/>
<source>max number of points sampled</source>
<translation>max. Anzahl von erzeugten Punkten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3782"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3816"/>
<source>color by</source>
<translation>Einfärben nach</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3783"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3817"/>
<source>window size (x y) in pixels</source>
<translation>Fenstergröße (x y) in Pixel</translation>
</message>
@@ -101261,27 +102260,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>lasviewPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3787"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3821"/>
<source>lasviewPro</source>
<translation>lasviewPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3788"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3822"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3789"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3823"/>
<source>max number of points sampled</source>
<translation>max. Anzahl von erzeugten Punkten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3790"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3824"/>
<source>color by</source>
<translation>Einfärben nach</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3791"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3825"/>
<source>window size (x y) in pixels</source>
<translation>Fenstergröße (x y) in Pixel</translation>
</message>
@@ -101289,27 +102288,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>laszip</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3795"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3829"/>
<source>laszip</source>
<translation>laszip</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3796"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3830"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3797"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3831"/>
<source>only report size</source>
<translation>Nur Größe berichten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3798"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3832"/>
<source>create spatial indexing file (*.lax)</source>
<translation>Räumlichen Index erzeugen (*.lax)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3799"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3833"/>
<source>append *.lax into *.laz file</source>
<translation>LAX- and LAZ-Datei anhängen</translation>
</message>
@@ -101317,27 +102316,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>laszipPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3803"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3837"/>
<source>laszipPro</source>
<translation>laszipPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3804"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3838"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3805"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3839"/>
<source>only report size</source>
<translation>Nur Größe berichten</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3806"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3840"/>
<source>create spatial indexing file (*.lax)</source>
<translation>Räumlichen Index erzeugen (*.lax)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3807"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3841"/>
<source>append *.lax into *.laz file</source>
<translation>LAX- and LAZ-Datei anhängen</translation>
</message>
@@ -101345,37 +102344,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>merge</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3811"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3845"/>
<source>Merge</source>
<translation>Verschmelzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3812"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3846"/>
<source>[GDAL] Miscellaneous</source>
<translation>[GDAL] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3813"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3847"/>
<source>Input layers</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3814"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3848"/>
<source>Grab pseudocolor table from first layer</source>
<translation>Pseudofarbtabelle aus erstem Bild entnehmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3815"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3849"/>
<source>Place each input file into a separate band</source>
<translation>Jeder Datei einen eigenen Kanal zuordnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3816"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3850"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3817"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3851"/>
<source>Merged</source>
<translation>Zusammengeführt</translation>
</message>
@@ -101383,32 +102382,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>nearblack</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3822"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3856"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3823"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3857"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3824"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3858"/>
<source>How far from black (white)</source>
<translation>Entfernung von Schwarz (oder Weiß)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3825"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3859"/>
<source>Search for nearly white pixels instead of nearly black</source>
<translation>Suche nach fast weißen statt schwarzen Pixeln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3826"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3860"/>
<source>Nearblack</source>
<translation>Fast Schwarz</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3821"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3855"/>
<source>Near black</source>
<translation>Fast schwarz</translation>
</message>
@@ -101416,37 +102415,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>nviz</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3831"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3865"/>
<source>Visualization(NVIZ)</source>
<translation>Visualisierung (NVIZ)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3832"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3866"/>
<source>Raster file(s) for elevation</source>
<translation>Rasterdatei(en) für Höhen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3833"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3867"/>
<source>Vector lines/areas overlay file(s)</source>
<translation>Vektorlinien-/-flächenüberlagerungsdatei(en)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3834"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3868"/>
<source>Raster file(s) for color</source>
<translation>Rasterdatei(en) für Farbe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3835"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3869"/>
<source>GRASS region extent</source>
<translation>GRASS-Regionengrenzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3836"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3870"/>
<source>GRASS region cellsize (leave 0 for default)</source>
<translation>GRASS-Regionenzellengröße (0 für um Voreinstellung beizubehalten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3830"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3864"/>
<source>nviz</source>
<translation>nviz</translation>
</message>
@@ -101454,37 +102453,37 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>nviz7</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3840"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3874"/>
<source>nviz7</source>
<translation>nviz7</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3841"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3875"/>
<source>Visualization(NVIZ)</source>
<translation>Visualisierung (NVIZ)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3842"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3876"/>
<source>Raster file(s) for elevation</source>
<translation>Rasterdatei(en) für Höhen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3843"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3877"/>
<source>Vector lines/areas overlay file(s)</source>
<translation>Vektorlinien-/-flächenüberlagerungsdatei(en)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3844"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3878"/>
<source>Raster file(s) for color</source>
<translation>Rasterdatei(en) für Farbe</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3845"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3879"/>
<source>GRASS region extent</source>
<translation>GRASS-Regionengrenzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3846"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3880"/>
<source>GRASS region cellsize (leave 0 for default)</source>
<translation>GRASS-Regionenzellengröße (0 für um Voreinstellung beizubehalten)</translation>
</message>
@@ -101538,22 +102537,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>pct2rgb</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3851"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3885"/>
<source>[GDAL] Conversion</source>
<translation>[GDAL] Konvertierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3852"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3886"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3853"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3887"/>
<source>Band to convert</source>
<translation>Umzuwandelnder Kanal</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3850"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3884"/>
<source>PCT to RGB</source>
<translation>PCT nach RGB</translation>
</message>
@@ -101561,27 +102560,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>polygonize</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3857"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3891"/>
<source>Polygonize (raster to vector)</source>
<translation>Vektorisieren (Raster nach Vektor)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3858"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3892"/>
<source>[GDAL] Conversion</source>
<translation>[GDAL] Konvertierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3859"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3893"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3860"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3894"/>
<source>Output field name</source>
<translation>Ausgabefeldname</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3861"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3895"/>
<source>Vectorized</source>
<translation>Vektorisiert</translation>
</message>
@@ -101589,52 +102588,52 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>proximity</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3866"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3900"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3867"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3901"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3868"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3902"/>
<source>Values</source>
<translation>Werte</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3869"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3903"/>
<source>Distance units</source>
<translation>Distanzeinheit</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3870"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3904"/>
<source>Max distance (negative value to ignore)</source>
<translation>Maximalabstand (negative Werte werden ignoriert)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3871"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3905"/>
<source>Nodata (negative value to ignore)</source>
<translation>Leerwert (zu ignorierender negativer Wert)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3872"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3906"/>
<source>Fixed buf value (negative value to ignore)</source>
<translation>Fester Pufferwert (negativer Werte werden ignoriert)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3873"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3907"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3874"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3908"/>
<source>Distance</source>
<translation>Entfernung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3865"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3899"/>
<source>Proximity (raster distance)</source>
<translation>Nähe (Rasterabstand)</translation>
</message>
@@ -101642,97 +102641,97 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>rasterize</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3879"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3913"/>
<source>[GDAL] Conversion</source>
<translation>[GDAL] Konvertierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3880"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3914"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3881"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3915"/>
<source>Attribute field</source>
<translation>Attributfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3882"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3916"/>
<source>Set output raster size (ignored if above option is checked)</source>
<translation>Ausgabelayergröße setzen (wird ignoriert, wenn Option oben gewählt ist)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3883"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3917"/>
<source>Horizontal</source>
<translation>Horizontal</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3884"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3918"/>
<source>Vertical</source>
<translation>Vertikal</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3885"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3919"/>
<source>Raster extent</source>
<translation>Rastermaße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3886"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3920"/>
<source>Raster type</source>
<translation>Rastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3887"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3921"/>
<source>Nodata value</source>
<translation>Leerwert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3888"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3922"/>
<source>GeoTIFF options. Compression type:</source>
<translation>GeoTIFF-Optionen. Kompressionstyp:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3889"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3923"/>
<source>Set the JPEG compression level</source>
<translation>JPEG-Kompressionsstufe setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3890"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3924"/>
<source>Set the DEFLATE compression level</source>
<translation>DEFLATE-Kompressionsstufe setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3891"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3925"/>
<source>Set the predictor for LZW or DEFLATE compression</source>
<translation>LZW- oder DEFLATE-Kompressionsvorhersage setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3892"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3926"/>
<source>Create tiled output (only used for the GTiff format)</source>
<translation>Gekachelte Ausgabe (nur bei GTIFF-Format verwendet)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3893"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3927"/>
<source>Control whether the created file is a BigTIFF or a classic TIFF</source>
<translation>Ausgabe als BigTIFF oder klassisches TIFF steuern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3894"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3928"/>
<source>Force the generation of an associated ESRI world file (.tfw)</source>
<translation>Erzeugung der zugehörigen ESRI-Worlddatei (.tfw) erzwingen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3895"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3929"/>
<source>Additional creation parameters</source>
<translation>Zusaätzliche Erzeugungsparameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3896"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3930"/>
<source>Rasterized</source>
<translation>Gerastert</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3878"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3912"/>
<source>Rasterize (vector to raster)</source>
<translation>Rastern (Vektor nach Raster)</translation>
</message>
@@ -101740,27 +102739,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>rasterize_over</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3901"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3935"/>
<source>[GDAL] Conversion</source>
<translation>[GDAL] Konvertierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3902"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3936"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3903"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3937"/>
<source>Attribute field</source>
<translation>Attributfeld</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3904"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3938"/>
<source>Existing raster layer</source>
<translation>Vorhandener Rasterlayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3900"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3934"/>
<source>Rasterize (write over existing raster)</source>
<translation>Rastern (vorhandenes Raster überschreiben)</translation>
</message>
@@ -101768,82 +102767,82 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>retile</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3908"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3942"/>
<source>Retile</source>
<translation>Neukacheln</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3909"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3943"/>
<source>[GDAL] Miscellaneous</source>
<translation>[GDAL] Verschiedenes</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3910"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3944"/>
<source>Input layers</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3911"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3945"/>
<source>Pixel size to be used for the output file (XSIZE YSIZE like 512 512)</source>
<translation>Größe für die Ausgabedateien in Pixel (XSIZE YSIZE wie 512 512)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3912"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3946"/>
<source>Resampling algorithm</source>
<translation>Abtastmethode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3913"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3947"/>
<source>Override source CRS</source>
<translation>Quell-KBS überschreiben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3914"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3948"/>
<source>Number of pyramids levels to build</source>
<translation>Anzahl der zu erzeugenden Pyramidenstufen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3915"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3949"/>
<source>Build only the pyramids</source>
<translation>Nur Pyramiden erzeugen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3916"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3950"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3917"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3951"/>
<source>Output raster format</source>
<translation>Ausgaberasterformat</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3918"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3952"/>
<source>Use a directory for each row</source>
<translation>Ein Verzeichnis je Zeile verwenden</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3919"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3953"/>
<source>Name of the csv file containing the tile(s) georeferencing information</source>
<translation>Name der CSV-Datei, die die Georeferenzierungsinformation der Kacheln enthält</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3920"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3954"/>
<source>Column delimiter used in the CSV file</source>
<translation>Spaltentrennzeichen der CSV-Datei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3921"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3955"/>
<source>name of shape file containing the result tile(s) index</source>
<translation>Name der Shapedatei für den Kachelindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3922"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3956"/>
<source>name of the attribute containing the tile name in the result shape file</source>
<translation>Name für das Attribut des Kachelnamens in der Ergebnis-Shapedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3923"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3957"/>
<source>The directory where the tile result is created</source>
<translation>Verzeichnis in dem die Ergebniskacheln erzeugt werden sollen</translation>
</message>
@@ -101851,22 +102850,22 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>rgb2pct</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3928"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3962"/>
<source>[GDAL] Conversion</source>
<translation>[GDAL] Konvertierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3929"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3963"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3930"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3964"/>
<source>Number of colors</source>
<translation>Farbanzahl</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3927"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3961"/>
<source>RGB to PCT</source>
<translation>RGB nach PCT</translation>
</message>
@@ -101874,27 +102873,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>roughness</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3935"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3969"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3936"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3970"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3937"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3971"/>
<source>Band number</source>
<translation>Kanalnummer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3938"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3972"/>
<source>Compute edges</source>
<translation>Kanten berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3934"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3968"/>
<source>Roughness</source>
<translation>Rauhigkeit</translation>
</message>
@@ -101984,7 +102983,7 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>self.output</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3942"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3976"/>
<source>Spatialite files(*.sqlite)</source>
<translation>Spatialite dateien(*.sqlite)</translation>
</message>
@@ -101992,27 +102991,27 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>shp2las</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3946"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3980"/>
<source>shp2las</source>
<translation>shp2las</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3947"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3981"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3948"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3982"/>
<source>Input SHP file</source>
<translation>Eingabe shp Datei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3949"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3983"/>
<source>resolution of x and y coordinate</source>
<translation>Auflösung der X und Y Koordinate</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3950"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3984"/>
<source>resolution of z coordinate</source>
<translation>Auflösung der Z Koordinate</translation>
</message>
@@ -102020,32 +103019,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>sieve</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3954"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3988"/>
<source>Sieve</source>
<translation>Sieben</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3955"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3989"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3956"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3990"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3957"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3991"/>
<source>Threshold</source>
<translation>Schwelle</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3958"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3992"/>
<source>Pixel connection</source>
<translation>Pixelverbindung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3959"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3993"/>
<source>Sieved</source>
<translation>Gesiebt</translation>
</message>
@@ -102053,42 +103052,42 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>slope</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3964"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3998"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3965"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3999"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3966"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4000"/>
<source>Band number</source>
<translation>Kanalnummer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3967"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4001"/>
<source>Compute edges</source>
<translation>Kanten berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3968"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4002"/>
<source>Use Zevenbergen&Thorne formula (instead of the Horn's one)</source>
<translation>Benutze Zevenbergen&Thorne Formel (statt Horn)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3969"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4003"/>
<source>Slope expressed as percent (instead of degrees)</source>
<translation>Steigung in Prozent (statt Grad)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3970"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4004"/>
<source>Scale (ratio of vert. units to horiz.)</source>
<translation>Skalierung (Verh. von vert. zu horz. Einheiten)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3963"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="3997"/>
<source>Slope</source>
<translation>Neigung</translation>
</message>
@@ -102096,7 +103095,7 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>symbol_angle</name>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5005"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5148"/>
<source>Angle of symbol used to render the feature (valid for marker symbols only).</source>
<translation>Winkel des Symbols zur Objektdarstellung (nur für Markierungssymbole gültig).</translation>
</message>
@@ -102104,7 +103103,7 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>symbol_color</name>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5004"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5147"/>
<source>Color of symbol used to render the feature.</source>
<translation>Farbe des Symbols zur Objektdarstellung.</translation>
</message>
@@ -102308,32 +103307,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>tpi</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3975"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4009"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3976"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4010"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3977"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4011"/>
<source>Band number</source>
<translation>Kanalnummer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3978"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4012"/>
<source>Compute edges</source>
<translation>Kanten berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3979"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4013"/>
<source>Topographic Position Index</source>
<translation>Topographischer Positionsindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3974"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4008"/>
<source>TPI (Topographic Position Index)</source>
<translation>Topographische Position (TPI)</translation>
</message>
@@ -102341,102 +103340,102 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>translate</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3985"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4019"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3986"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4020"/>
<source>Set the size of the output file (In pixels or %)</source>
<translation>Größe der Ausgabedatei setzen (in Pixel oder %)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3987"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4021"/>
<source>Output size is a percentage of input size</source>
<translation>Ausgabegröße in Prozent der Eingabegröße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3989"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4023"/>
<source>Expand</source>
<translation>Ausdehnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3990"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4024"/>
<source>Output projection for output file [leave blank to use input projection]</source>
<translation>Projektion für Ausgabedatei [leer lassen um Eingabeprojektion zu verwenden]</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3991"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4025"/>
<source>Subset based on georeferenced coordinates</source>
<translation>Auf georeferenzierten Koordinaten basierende Untermenge</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3992"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4026"/>
<source>Copy all subdatasets of this file to individual output files</source>
<translation>Alle Unterdatensätze dieser Datei in einzelne Dateien kopieren</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4001"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4035"/>
<source>Additional creation parameters</source>
<translation>Weitere Erzeugungsparameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4002"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4036"/>
<source>Converted</source>
<translation>Umgewandelt</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3993"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4027"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3988"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4022"/>
<source>Nodata value, leave blank to take the nodata value from input</source>
<translation>Leerwert, auf 'none' belassen, um den Leerwert aus der Eingabe zu übernehmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3983"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4017"/>
<source>Translate (convert format)</source>
<translation>Umwandeln (Format konvertieren)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3984"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4018"/>
<source>[GDAL] Conversion</source>
<translation>[GDAL] Konvertierung</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3994"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4028"/>
<source>GeoTIFF options. Compression type:</source>
<translation>GeoTIFF-Optionen. Kompressionstyp:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3995"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4029"/>
<source>Set the JPEG compression level</source>
<translation>JPEG-Kompressionsstufe setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3996"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4030"/>
<source>Set the DEFLATE compression level</source>
<translation>DEFLATE-Kompressionsstufe setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3997"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4031"/>
<source>Set the predictor for LZW or DEFLATE compression</source>
<translation>LZW- oder DEFLATE-Kompressionsvorhersage setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3998"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4032"/>
<source>Create tiled output (only used for the GTiff format)</source>
<translation>Gekachelte Ausgabe (nur bei GTIFF-Format verwendet)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="3999"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4033"/>
<source>Control whether the created file is a BigTIFF or a classic TIFF</source>
<translation>Ausgabe als BigTIFF- oder klassisches TIFF steuern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4000"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4034"/>
<source>Force the generation of an associated ESRI world file (.tfw))</source>
<translation>Erzeugung der zugehörigen ESRI-Worlddatei (.tfw) erzwingen</translation>
</message>
@@ -102444,32 +103443,32 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>tri</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4007"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4041"/>
<source>[GDAL] Analysis</source>
<translation>[GDAL] Analyse</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4008"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4042"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4009"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4043"/>
<source>Band number</source>
<translation>Kanalnummer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4010"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4044"/>
<source>Compute edges</source>
<translation>Kanten berechnen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4011"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4045"/>
<source>Terrain Ruggedness Index</source>
<translation>Geländerauhigkeitsindex</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4006"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4040"/>
<source>TRI (Terrain Ruggedness Index)</source>
<translation>Oberflächenrauhigkeit (TRI)</translation>
</message>
@@ -102477,52 +103476,52 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>txt2las</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4015"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4049"/>
<source>txt2las</source>
<translation>txt2las</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4016"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4050"/>
<source>LAStools</source>
<translation>LAS-Tools</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4017"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4051"/>
<source>Input ASCII file</source>
<translation>ASCII-Eingabedatei</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4018"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4052"/>
<source>parse lines as</source>
<translation>Zeilen interpretieren als</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4019"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4053"/>
<source>skip the first n lines</source>
<translation>Erste n Zeilen überspringen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4020"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4054"/>
<source>resolution of x and y coordinate</source>
<translation>Auflösung der X und Y Koordinate</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4021"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4055"/>
<source>resolution of z coordinate</source>
<translation>Auflösung der Z Koordinate</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4022"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4056"/>
<source>projection</source>
<translation>Projektion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4023"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4057"/>
<source>utm zone</source>
<translation>UTM-Zone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4024"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4058"/>
<source>state plane code</source>
<translation>US-Koodinatensystemkennung</translation>
</message>
@@ -102530,47 +103529,47 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>txt2lasPro</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4028"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4062"/>
<source>txt2lasPro</source>
<translation>txt2lasPro</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4029"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4063"/>
<source>LAStools Production</source>
<translation>LASTools-Produktion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4030"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4064"/>
<source>parse lines as</source>
<translation>Zeilen interpretieren als</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4031"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4065"/>
<source>skip the first n lines</source>
<translation>Erste n Zeile überspringen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4032"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4066"/>
<source>resolution of x and y coordinate</source>
<translation>Auflösung der X und Y Koordinate</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4033"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4067"/>
<source>resolution of z coordinate</source>
<translation>Auflösung der Z Koordinate</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4034"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4068"/>
<source>projection</source>
<translation>Projektion</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4035"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4069"/>
<source>utm zone</source>
<translation>UTM-Zone</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4036"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4070"/>
<source>state plane code</source>
<translation>US-Koodinatensystemkennung</translation>
</message>
@@ -102578,227 +103577,227 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>variable_help</name>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4945"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5088"/>
<source>Current QGIS version string.</source>
<translation>Aktueller QGIS-Versionstext.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4946"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5089"/>
<source>Current QGIS version number.</source>
<translation>Aktuelle QGIS-Versionsnummer.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4947"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5090"/>
<source>Current QGIS release name.</source>
<translation>Aktueller QGIS-Releasename.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4948"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5091"/>
<source>Operating system name, eg 'windows', 'linux' or 'osx'.</source>
<translation>Betriebssystemname, z.B. 'windows', 'linux' oder 'osx'.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4949"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5092"/>
<source>QGIS platform, eg 'desktop' or 'server'.</source>
<translation>QGIS-Plattform, z.B. 'desktop' oder 'server'.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4950"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5093"/>
<source>Current user's operating system account name.</source>
- <translation>Betriebssystemkontoname des aktuellen Benutzers</translation>
+ <translation>Betriebssystemkontoname des aktuellen Benutzers.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4951"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5094"/>
<source>Current user's operating system user name (if available).</source>
- <translation>Benutzername des aktuellen Benutzers (wenn verfügbar)</translation>
+ <translation>Benutzername des aktuellen Benutzers (wenn verfügbar).</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4954"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5097"/>
<source>Title of current project.</source>
<translation>Titel des aktuellen Projekts.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4955"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5098"/>
<source>Full path (including file name) of current project.</source>
<translation>Voller Pfad (mit Dateiname) des aktuellen Projekts.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4956"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5099"/>
<source>Folder for current project.</source>
<translation>Verzeichnis des aktuellen Projekts.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4957"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5100"/>
<source>Filename of current project.</source>
<translation>Dateiname des aktuellen Projekts.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4960"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5103"/>
<source>Name of current layer.</source>
<translation>Aktueller Rastername.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4961"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5104"/>
<source>ID of current layer.</source>
<translation>Kennung des aktuellen Layers.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4964"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5107"/>
<source>Number of pages in composition.</source>
<translation>Seitenanzahl in Zusammenstellung.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4965"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5108"/>
<source>Composition page height in mm.</source>
<translation>Zusammenstellungsseitenhöhe in mm.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4966"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5109"/>
<source>Composition page width in mm.</source>
<translation>Zusammenstellungsseitenbreite in mm.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4967"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5110"/>
<source>Composition resolution (DPI).</source>
<translation>Zusammenstellungsauflösung (DPI).</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4970"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5113"/>
<source>Total number of features in atlas.</source>
<translation>Gesamtanzahl der Objekte in Atlas.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4971"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5114"/>
<source>Current atlas feature number.</source>
<translation>Aktuelle Atlasobjektnummer.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4972"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5115"/>
<source>Current atlas file name.</source>
<translation>Aktueller Atlas-Dateiname.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4973"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5116"/>
<source>Current atlas page name.</source>
<translation>Aktueller Atlas-Seitenname.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4974"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5117"/>
<source>Current atlas feature (as feature object).</source>
<translation>Aktuelles Atlas-Objekt (als Objekt).</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4975"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5118"/>
<source>Current atlas feature ID.</source>
<translation>ID des aktuellen Atlasobjekts.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4976"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5119"/>
<source>Current atlas feature geometry.</source>
<translation>Geometrie des aktuellen Altas-Objekts.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4979"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5122"/>
<source>Composer item user ID (not necessarily unique).</source>
<translation>Benutzerkennung des aktuellen Zusammenstellungselement (nicht notwendigerweise eindeutig).</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4980"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5123"/>
<source>Composer item unique ID.</source>
<translation>Eindeutiger ID des Zusammenstellungselements.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4981"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5124"/>
<source>Left position of composer item (in mm).</source>
<translation>Linke Position des Zusammenstellungselements (in mm).</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4982"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5125"/>
<source>Top position of composer item (in mm).</source>
<translation>Obere Position des Zusammenstellungselements (in mm).</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4983"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5126"/>
<source>Width of composer item (in mm).</source>
<translation>Breite des Zusammenstellungselements (in mm).</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4984"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5127"/>
<source>Height of composer item (in mm).</source>
<translation>Höhe des Zusammenstellungselements (in mm).</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4987"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5130"/>
<source>ID of current map destination. This will be 'canvas' for canvas renders, and the item ID for composer map renders.</source>
<translation>Kennung des aktuellen Kartenziels. 'canvas' für Darstellung in der Karte und Kennung der Zusammenstellung bei Druckzusammenstellungen.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4988"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5131"/>
<source>Current rotation of map.</source>
<translation>Aktuelle Kartendrehung.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4989"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5132"/>
<source>Current scale of map.</source>
<translation>Aktueller Kartenmaßstab.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4990"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5133"/>
<source>Center of map.</source>
<translation>Mittelpunkt der Karte.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4991"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5134"/>
<source>Width of map.</source>
<translation>Breite der Karte.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4992"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5135"/>
<source>Height of map.</source>
<translation>Höhe der Karte.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4994"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5137"/>
<source>Stores the number of the current row.</source>
<translation>Aktuelle Zeilennummer.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4995"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5138"/>
<source>Current grid annotation value.</source>
<translation>Aktueller Gitteranmerkungswert.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4996"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5139"/>
<source>Current grid annotation axis (eg, 'x' for longitude, 'y' for latitude).</source>
<translation>Aktuelle Kartenmerkungsachse (z.B. 'x' für Längengrad und 'y' für Breitengrad).</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="4999"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5142"/>
<source>Number of parts in rendered feature's geometry.</source>
- <translation>Anzahl der Teile der Geometrie des dargestellten Objekts</translation>
+ <translation>Anzahl der Teile der Geometrie des dargestellten Objekts.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5000"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5143"/>
<source>Current geometry part number for feature being rendered.</source>
<translation>Nummer des aktuellen Geometrieteils das dargestellten Objekts.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5001"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5144"/>
<source>Number of points in the rendered geometry's part. It is only meaningful for line geometries and for symbol layers that set this variable.</source>
<translation>Anzahl der Punkte im dargestellten Geometrieteil. Nur für Liniengeometrien sinnvoll oder für Symbollayer die diese Variable setzen.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5002"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5145"/>
<source>Current point number in the rendered geometry's part. It is only meaningful for line geometries and for symbol layers that set this variable.</source>
<translation>Aktuellen Punktnummer des angezeigen Geometrieteils. Nur sinnvoll bei Liniengeometrien oder Symbollayer die diese Variable setzen.</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5017"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5160"/>
<source>not set</source>
<translation>nicht gesetzt</translation>
</message>
<message>
- <location filename="../src/core/qgsexpression.cpp" line="5023"/>
+ <location filename="../src/core/qgsexpression.cpp" line="5166"/>
<source><p>Current value: %1</p></source>
<translation><p>Aktueller Wert: %1</p></translation>
</message>
@@ -102806,102 +103805,102 @@ Base Path (i.e. keep only filename from attribute)</source>
<context>
<name>warp</name>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4042"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4076"/>
<source>Input layer</source>
<translation>Eingabelayer</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4043"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4077"/>
<source>Source SRS</source>
<translation>Quell-KBS</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4044"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4078"/>
<source>Destination SRS</source>
<translation>Ziel-KBS</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4046"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4080"/>
<source>Output file resolution in target georeferenced units (leave 0 for no change)</source>
<translation>Auflösung der Ausgabedatei in georeferenzierten Zieleinheiten (0 bedeutet keine Änderung)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4047"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4081"/>
<source>Resampling method</source>
<translation>Abtastmethode</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4058"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4092"/>
<source>Additional creation parameters</source>
<translation>Weitere Erzeugungsparameter</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4050"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4084"/>
<source>Output raster type</source>
<translation>Ausgaberastertyp</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4040"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4074"/>
<source>Warp (reproject)</source>
<translation>Transformieren (Reprojizieren)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4041"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4075"/>
<source>[GDAL] Projections</source>
<translation>[GDAL] Projektionen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4045"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4079"/>
<source>Nodata value, leave blank to take the nodata value from input</source>
<translation>Leerwert, auf 'none' belassen, um den Leerwert aus der Eingabe zu übernehmen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4048"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4082"/>
<source>Raster extent</source>
<translation>Rastermaße</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4049"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4083"/>
<source>CRS of the raster extent</source>
<translation>KBS der Rastergrenzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4051"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4085"/>
<source>GeoTIFF options. Compression type:</source>
<translation>GeoTIFF-Optionen. Kompressionstyp:</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4052"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4086"/>
<source>Set the JPEG compression level</source>
<translation>JPEG-Kompressionsstufe setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4053"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4087"/>
<source>Set the DEFLATE compression level</source>
<translation>DEFLATE-Kompressionsstufe setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4054"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4088"/>
<source>Set the predictor for LZW or DEFLATE compression</source>
<translation>LZW- oder DEFLATE-Kompressionsvorhersage setzen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4055"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4089"/>
<source>Create tiled output (only used for the GTiff format)</source>
<translation>Gekachelte Ausgabe (nur bei GTIFF-Format verwendet)</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4056"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4090"/>
<source>Control whether the created file is a BigTIFF or a classic TIFF</source>
<translation>Ausgabe als BigTIFF oder klassisches TIFF steuern</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4057"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4091"/>
<source>Force the generation of an associated ESRI world file (.tfw))</source>
<translation>Erzeugung der zugehörigen ESRI-Worlddatei (.tfw) erzwingen</translation>
</message>
<message>
- <location filename="../python/plugins/processing/python-i18n.cpp" line="4059"/>
+ <location filename="../python/plugins/processing/python-i18n.cpp" line="4093"/>
<source>Reprojected</source>
<translation>Reprojiiziert</translation>
</message>
diff --git a/images/images.qrc b/images/images.qrc
index ecf3bb0..448520a 100644
--- a/images/images.qrc
+++ b/images/images.qrc
@@ -90,7 +90,7 @@
<file>themes/default/console/iconSyntaxErrorConsole.png</file>
<file>themes/default/console/iconResetColorConsole.png</file>
<file>themes/default/copyright_label.png</file>
- <file>themes/default/extents.png</file>
+ <file>themes/default/extents.svg</file>
<file>themes/default/favourites.png</file>
<file>themes/default/geographic.png</file>
<file>themes/default/gpsicons/barchart.svg</file>
@@ -99,7 +99,7 @@
<file>themes/default/grass_mapset.png</file>
<file>themes/default/grass_mapset_open.png</file>
<file>themes/default/grass_mapset_search.png</file>
- <file>themes/default/histogram.png</file>
+ <file>themes/default/histogram.svg</file>
<file>themes/default/join_bevel.png</file>
<file>themes/default/join_miter.png</file>
<file>themes/default/join_round.png</file>
@@ -107,13 +107,10 @@
<file>themes/default/locked.svg</file>
<file>themes/default/lockedGray.svg</file>
<file>themes/default/mAction.svg</file>
- <file>themes/default/mActionAdd.png</file>
<file>themes/default/mActionAdd.svg</file>
<file>themes/default/mActionAddLayer.svg</file>
<file>themes/default/mActionAddAllToOverview.svg</file>
- <file>themes/default/mActionAddArrow.png</file>
<file>themes/default/mActionAddArrow.svg</file>
- <file>themes/default/mActionAddBasicShape.png</file>
<file>themes/default/mActionAddBasicShape.svg</file>
<file>themes/default/mActionAddBasicCircle.svg</file>
<file>themes/default/mActionEditNodesItem.svg</file>
@@ -126,9 +123,7 @@
<file>themes/default/mActionAddGroup.png</file>
<file>themes/default/mActionAddGroup.svg</file>
<file>themes/default/mActionAddHtml.svg</file>
- <file>themes/default/mActionAddImage.png</file>
<file>themes/default/mActionAddImage.svg</file>
- <file>themes/default/mActionAddLegend.png</file>
<file>themes/default/mActionAddLegend.svg</file>
<file>themes/default/mActionAddMap.png</file>
<file>themes/default/mActionAddMap.svg</file>
@@ -138,10 +133,8 @@
<file>themes/default/mActionAddOgrLayer.svg</file>
<file>themes/default/mActionAddOracleLayer.svg</file>
<file>themes/default/mActionAddPostgisLayer.svg</file>
- <file>themes/default/mActionAddPart.png</file>
<file>themes/default/mActionAddPart.svg</file>
<file>themes/default/mActionAddRasterLayer.svg</file>
- <file>themes/default/mActionAddRing.png</file>
<file>themes/default/mActionAddRing.svg</file>
<file>themes/default/mActionAddSpatiaLiteLayer.svg</file>
<file>themes/default/mActionAddVertex.png</file>
@@ -150,20 +143,13 @@
<file>themes/default/mActionAddWmsLayer.svg</file>
<file>themes/default/mActionAddDelimitedTextLayer.svg</file>
<file>themes/default/mActionAddVirtualLayer.svg</file>
- <file>themes/default/mActionAlignBottom.png</file>
<file>themes/default/mActionAlignBottom.svg</file>
- <file>themes/default/mActionAlignHCenter.png</file>
<file>themes/default/mActionAlignHCenter.svg</file>
- <file>themes/default/mActionAlignLeft.png</file>
<file>themes/default/mActionAlignLeft.svg</file>
- <file>themes/default/mActionAlignRight.png</file>
<file>themes/default/mActionAlignRight.svg</file>
- <file>themes/default/mActionAlignTop.png</file>
<file>themes/default/mActionAlignTop.svg</file>
- <file>themes/default/mActionAlignVCenter.png</file>
<file>themes/default/mActionAlignVCenter.svg</file>
<file>themes/default/mActionAllEdits.svg</file>
- <file>themes/default/mActionAnnotation.png</file>
<file>themes/default/mActionAnnotation.svg</file>
<file>themes/default/mActionArrowDown.png</file>
<file>themes/default/mActionArrowLeft.png</file>
@@ -174,37 +160,26 @@
<file>themes/default/mActionAtlasNext.svg</file>
<file>themes/default/mActionAtlasPrev.svg</file>
<file>themes/default/mActionAtlasSettings.svg</file>
- <file>themes/default/mActionCalculateField.png</file>
<file>themes/default/mActionCalculateField.svg</file>
<file>themes/default/mActionCancelAllEdits.svg</file>
<file>themes/default/mActionCancelEdits.svg</file>
- <file>themes/default/mActionCaptureLine.png</file>
<file>themes/default/mActionCaptureLine.svg</file>
- <file>themes/default/mActionCapturePoint.png</file>
<file>themes/default/mActionCapturePoint.svg</file>
- <file>themes/default/mActionCapturePolygon.png</file>
<file>themes/default/mActionCapturePolygon.svg</file>
- <file>themes/default/mActionNewTableRow.png</file>
<file>themes/default/mActionNewTableRow.svg</file>
- <file>themes/default/mActionChangeLabelProperties.png</file>
<file>themes/default/mActionChangeLabelProperties.svg</file>
<file>themes/default/mActionCheckQgisVersion.png</file>
- <file>themes/default/mActionCollapseTree.png</file>
<file>themes/default/mActionCollapseTree.svg</file>
<file>themes/default/mActionComposerManager.svg</file>
<file>themes/default/mActionConditionalFormatting.svg</file>
<file>themes/default/mActionContextHelp.png</file>
<file>themes/default/mActionCopySelected.png</file>
- <file>themes/default/mActionCreateMemory.png</file>
<file>themes/default/mActionCreateMemory.svg</file>
<file>themes/default/mActionCustomProjection.svg</file>
<file>themes/default/mActionDecreaseBrightness.svg</file>
<file>themes/default/mActionDecreaseContrast.svg</file>
- <file>themes/default/mActionDeleteAttribute.png</file>
<file>themes/default/mActionDeleteAttribute.svg</file>
- <file>themes/default/mActionDeletePart.png</file>
<file>themes/default/mActionDeletePart.svg</file>
- <file>themes/default/mActionDeleteRing.png</file>
<file>themes/default/mActionDeleteRing.svg</file>
<file>themes/default/mActionDeleteSelected.svg</file>
<file>themes/default/mActionDeleteVertex.png</file>
@@ -212,46 +187,33 @@
<file>themes/default/mActionDraw.svg</file>
<file>themes/default/mActionDuplicateLayer.svg</file>
<file>themes/default/mActionDuplicateComposer.svg</file>
- <file>themes/default/mActionEditCopy.png</file>
<file>themes/default/mActionEditCopy.svg</file>
- <file>themes/default/mActionEditCut.png</file>
<file>themes/default/mActionEditCut.svg</file>
- <file>themes/default/mActionEditPaste.png</file>
<file>themes/default/mActionEditPaste.svg</file>
- <file>themes/default/mActionExpandNewTree.png</file>
<file>themes/default/mActionExpandNewTree.svg</file>
- <file>themes/default/mActionExpandTree.png</file>
<file>themes/default/mActionExpandTree.svg</file>
<file>themes/default/mActionExportMapServer.png</file>
<file>themes/default/mActionFileExit.png</file>
<file>themes/default/mActionFileNew.svg</file>
<file>themes/default/mActionFileOpen.svg</file>
- <file>themes/default/mActionFilePrint.png</file>
<file>themes/default/mActionFilePrint.svg</file>
<file>themes/default/mActionFileSave.svg</file>
<file>themes/default/mActionFileSaveAs.svg</file>
<file>themes/default/mActionFileSmall.png</file>
<file>themes/default/mActionFillRing.svg</file>
- <file>themes/default/mActionFilter.png</file>
<file>themes/default/mActionFilter.svg</file>
<file>themes/default/mActionFilter2.svg</file>
- <file>themes/default/mActionFolder.png</file>
<file>themes/default/mActionFolder.svg</file>
- <file>themes/default/mActionFormAnnotation.png</file>
<file>themes/default/mActionFormAnnotation.svg</file>
<file>themes/default/mActionFromSelectedFeature.png</file>
<file>themes/default/mActionFormView.svg</file>
- <file>themes/default/mActionFullCumulativeCutStretch.png</file>
<file>themes/default/mActionFullCumulativeCutStretch.svg</file>
- <file>themes/default/mActionFullHistogramStretch.png</file>
<file>themes/default/mActionFullHistogramStretch.svg</file>
- <file>themes/default/mActionGroupItems.png</file>
<file>themes/default/mActionGroupItems.svg</file>
<file>themes/default/mActionHelpAbout.png</file>
<file>themes/default/mActionHelpAPI.png</file>
<file>themes/default/mActionHelpContents.svg</file>
<file>themes/default/mActionHelpSponsors.png</file>
- <file>themes/default/mActionHideAllLayers.png</file>
<file>themes/default/mActionHideAllLayers.svg</file>
<file>themes/default/mActionHideSelectedLayers.png</file>
<file>themes/default/mActionHistory.svg</file>
@@ -260,57 +222,36 @@
<file>themes/default/mActionIncreaseBrightness.svg</file>
<file>themes/default/mActionIncreaseContrast.svg</file>
<file>themes/default/mActionInOverview.svg</file>
- <file>themes/default/mActionInvertSelection.png</file>
<file>themes/default/mActionInvertSelection.svg</file>
- <file>themes/default/mActionLabel.png</file>
<file>themes/default/mActionLabel.svg</file>
- <file>themes/default/mActionLabeling.png</file>
<file>themes/default/mActionLabeling.svg</file>
<file>themes/default/mActionDiagramProperties.svg</file>
- <file>themes/default/mActionLocalCumulativeCutStretch.png</file>
<file>themes/default/mActionLocalCumulativeCutStretch.svg</file>
- <file>themes/default/mActionLocalHistogramStretch.png</file>
<file>themes/default/mActionLocalHistogramStretch.svg</file>
- <file>themes/default/mActionLowerItems.png</file>
<file>themes/default/mActionLowerItems.svg</file>
- <file>themes/default/mActionMapTips.png</file>
<file>themes/default/mActionMapTips.svg</file>
- <file>themes/default/mActionMeasure.png</file>
<file>themes/default/mActionMeasure.svg</file>
- <file>themes/default/mActionMeasureAngle.png</file>
<file>themes/default/mActionMeasureAngle.svg</file>
- <file>themes/default/mActionMeasureArea.png</file>
<file>themes/default/mActionMeasureArea.svg</file>
<file>themes/default/mActionMergeFeatureAttributes.svg</file>
- <file>themes/default/mActionMergeFeatures.png</file>
<file>themes/default/mActionMergeFeatures.svg</file>
- <file>themes/default/mActionMoveFeature.png</file>
<file>themes/default/mActionMoveFeature.svg</file>
<file>themes/default/mActionMoveFeatureLine.svg</file>
<file>themes/default/mActionMoveFeaturePoint.svg</file>
- <file>themes/default/mActionMoveItemContent.png</file>
<file>themes/default/mActionMoveItemContent.svg</file>
- <file>themes/default/mActionMoveItemsToBottom.png</file>
<file>themes/default/mActionMoveItemsToBottom.svg</file>
- <file>themes/default/mActionMoveItemsToTop.png</file>
<file>themes/default/mActionMoveItemsToTop.svg</file>
- <file>themes/default/mActionMoveLabel.png</file>
<file>themes/default/mActionMoveLabel.svg</file>
<file>themes/default/mActionMoveVertex.png</file>
- <file>themes/default/mActionNewAttribute.png</file>
<file>themes/default/mActionNewAttribute.svg</file>
- <file>themes/default/mActionNewBookmark.png</file>
<file>themes/default/mActionNewBookmark.svg</file>
<file>themes/default/mActionNewComposer.svg</file>
<file>themes/default/mActionNewFolder.png</file>
<file>themes/default/mActionNewSpatiaLiteLayer.svg</file>
<file>themes/default/mActionNewGeoPackageLayer.svg</file>
<file>themes/default/mActionNewVectorLayer.svg</file>
- <file>themes/default/mActionNodeTool.png</file>
<file>themes/default/mActionNodeTool.svg</file>
- <file>themes/default/mActionOffsetCurve.png</file>
<file>themes/default/mActionOffsetCurve.svg</file>
- <file>themes/default/mActionOpenTable.png</file>
<file>themes/default/mActionOpenTable.svg</file>
<file>themes/default/mActionAddTable.svg</file>
<file>themes/default/mActionOffsetPointSymbols.svg</file>
@@ -319,44 +260,30 @@
<file>themes/default/mActionPanToSelected.svg</file>
<file>themes/default/mActionPinLabels.svg</file>
<file>themes/default/mActionProjectProperties.png</file>
- <file>themes/default/mActionPropertiesWidget.png</file>
<file>themes/default/mActionPropertiesWidget.svg</file>
- <file>themes/default/mActionPropertyItem.png</file>
<file>themes/default/mActionPropertyItem.svg</file>
<file>themes/default/mActionQgisHomePage.png</file>
- <file>themes/default/mActionRaiseItems.png</file>
<file>themes/default/mActionRaiseItems.svg</file>
- <file>themes/default/mActionRedo.png</file>
<file>themes/default/mActionRedo.svg</file>
<file>themes/default/mActionRefresh.png</file>
- <file>themes/default/mActionRemove.png</file>
+ <file>themes/default/mActionRemove.svg</file>
<file>themes/default/mActionRemoveAllFromOverview.svg</file>
<file>themes/default/mActionRemoveLayer.svg</file>
<file>themes/default/mActionRemoveSelectedFeature.png</file>
- <file>themes/default/mActionReshape.png</file>
<file>themes/default/mActionReshape.svg</file>
<file>themes/default/mActionRollbackAllEdits.svg</file>
<file>themes/default/mActionRollbackEdits.svg</file>
- <file>themes/default/mActionRotateFeature.png</file>
<file>themes/default/mActionRotateFeature.svg</file>
- <file>themes/default/mActionRotateLabel.png</file>
<file>themes/default/mActionRotateLabel.svg</file>
- <file>themes/default/mActionRotatePointSymbols.png</file>
<file>themes/default/mActionRotatePointSymbols.svg</file>
<file>themes/default/mActionSaveAllEdits.svg</file>
- <file>themes/default/mActionSaveAsPDF.png</file>
<file>themes/default/mActionSaveAsPDF.svg</file>
- <file>themes/default/mActionSaveAsSVG.png</file>
<file>themes/default/mActionSaveAsSVG.svg</file>
<file>themes/default/mActionSaveEdits.svg</file>
- <file>themes/default/mActionSaveMapAsImage.png</file>
<file>themes/default/mActionSaveMapAsImage.svg</file>
- <file>themes/default/mActionScaleBar.png</file>
<file>themes/default/mActionScaleBar.svg</file>
<file>themes/default/mActionSelect.svg</file>
- <file>themes/default/mActionSelectAll.png</file>
<file>themes/default/mActionSelectAll.svg</file>
- <file>themes/default/mActionSelectedToTop.png</file>
<file>themes/default/mActionSelectedToTop.svg</file>
<file>themes/default/mActionSelectFreehand.svg</file>
<file>themes/default/mActionSelectPan.png</file>
@@ -366,11 +293,8 @@
<file>themes/default/mActionSelectAllTree.svg</file>
<file>themes/default/mActionSetProjection.svg</file>
<file>themes/default/mActionSharing.svg</file>
- <file>themes/default/mActionSharingExport.svg</file>
<file>themes/default/mActionSharingImport.svg</file>
- <file>themes/default/mActionShowAllLayers.png</file>
<file>themes/default/mActionShowAllLayers.svg</file>
- <file>themes/default/mActionShowBookmarks.png</file>
<file>themes/default/mActionShowBookmarks.svg</file>
<file>themes/default/mActionShowHideLabels.svg</file>
<file>themes/default/mActionShowPinnedLabels.svg</file>
@@ -383,19 +307,13 @@
<file>themes/default/mActionSimplify.svg</file>
<file>themes/default/mActionSplitFeatures.svg</file>
<file>themes/default/mActionSplitParts.svg</file>
- <file>themes/default/mActionSum.png</file>
<file>themes/default/mActionSum.svg</file>
- <file>themes/default/mActionTextAnnotation.png</file>
<file>themes/default/mActionTextAnnotation.svg</file>
- <file>themes/default/mActionToggleEditing.png</file>
<file>themes/default/mActionToggleEditing.svg</file>
<file>themes/default/mActionTouch.svg</file>
<file>themes/default/mActionTouch2.png</file>
- <file>themes/default/mActionTracing.png</file>
<file>themes/default/mActionTracing.svg</file>
<file>themes/default/mActionUndo.svg</file>
- <file>themes/default/mActionUndo.png</file>
- <file>themes/default/mActionUngroupItems.png</file>
<file>themes/default/mActionUngroupItems.svg</file>
<file>themes/default/mActionUnselectAttributes.png</file>
<file>themes/default/mActionSvgAnnotation.svg</file>
@@ -417,7 +335,6 @@
<file>themes/default/mIconCertificateTrusted.svg</file>
<file>themes/default/mIconCertificateUntrusted.svg</file>
<file>themes/default/mIconClear.svg</file>
- <file>themes/default/mIconClose.png</file>
<file>themes/default/mIconCollapse.png</file>
<file>themes/default/mIconCollapseSmall.svg</file>
<file>themes/default/mIconColorBox.svg</file>
@@ -425,6 +342,7 @@
<file>themes/default/mIconColorSwatches.svg</file>
<file>themes/default/mIconColorWheel.svg</file>
<file>themes/default/mIconConnect.png</file>
+ <file>themes/default/mIconClose.svg</file>
<file>themes/default/mIconCritical.png</file>
<file>themes/default/mIconDataDefine.svg</file>
<file>themes/default/mIconDataDefineError.svg</file>
@@ -493,13 +411,12 @@
<file>themes/default/mIconSpatialite.svg</file>
<file>themes/default/mIconStopRendering.png</file>
<file>themes/default/mIconSymbology.png</file>
- <file>themes/default/mIconTableLayer.png</file>
+ <file>themes/default/mIconTableLayer.svg</file>
<file>themes/default/mIconTimerContinue.png</file>
<file>themes/default/mIconTimerPause.png</file>
<file>themes/default/mIconTreeView.png</file>
<file>themes/default/mIconUnknownLayerType.png</file>
<file>themes/default/mIconWaitingForLayerType.png</file>
- <file>themes/default/mIconWarn.png</file>
<file>themes/default/mIconWcs.svg</file>
<file>themes/default/mIconWfs.svg</file>
<file>themes/default/mIconWms.svg</file>
@@ -555,12 +472,9 @@
<file>themes/default/propertyicons/symbology.svg</file>
<file>themes/default/propertyicons/system.svg</file>
<file>themes/default/propertyicons/transparency.png</file>
- <file>themes/default/rendererCategorizedSymbol.png</file>
<file>themes/default/rendererCategorizedSymbol.svg</file>
- <file>themes/default/rendererGraduatedSymbol.png</file>
<file>themes/default/rendererGraduatedSymbol.svg</file>
<file>themes/default/rendererNullSymbol.svg</file>
- <file>themes/default/rendererSingleSymbol.png</file>
<file>themes/default/rendererSingleSymbol.svg</file>
<file>themes/default/rendererRuleBasedSymbol.svg</file>
<file>themes/default/rendererPointDisplacementSymbol.svg</file>
@@ -582,20 +496,15 @@
<file>themes/default/styleicons/style-line.png</file>
<file>themes/default/styleicons/style-point.png</file>
<file>themes/default/styleicons/style-polygon.png</file>
- <file>themes/default/symbologyAdd.png</file>
<file>themes/default/symbologyAdd.svg</file>
- <file>themes/default/symbologyDown.png</file>
<file>themes/default/symbologyDown.svg</file>
<file>themes/default/symbologyEdit.png</file>
- <file>themes/default/symbologyRemove.png</file>
<file>themes/default/symbologyRemove.svg</file>
- <file>themes/default/symbologyUp.png</file>
<file>themes/default/symbologyUp.svg</file>
<file>themes/default/sync_views.svg</file>
<file>themes/default/text.png</file>
- <file>themes/default/tracking.png</file>
<file>themes/default/tracking.svg</file>
- <file>themes/default/transformed.png</file>
+ <file>themes/default/transformed.svg</file>
<file>themes/default/transp-background_8x8.png</file>
<file>themes/default/unlocked.svg</file>
<file>themes/default/user.png</file>
@@ -606,7 +515,6 @@
<file>themes/default/relation.svg</file>
<file>themes/default/mActionLink.svg</file>
<file>themes/default/mActionUnlink.svg</file>
- <file>themes/default/mActionRemove.svg</file>
<file>flags/mr.png</file>
<file>flags/bs.png</file>
<file>flags/ca.png</file>
@@ -638,12 +546,9 @@
<file>themes/default/cadtools/parallel.png</file>
<file>themes/default/cadtools/perpendicular.png</file>
<file>themes/default/mIconSuccess.png</file>
- <file>themes/default/mIconClear.png</file>
<file>themes/default/mIconWarning.svg</file>
<file>themes/default/mIconPaintEffects.svg</file>
- <file>themes/default/mActionCircularStringCurvePoint.png</file>
<file>themes/default/mActionCircularStringCurvePoint.svg</file>
- <file>themes/default/mActionCircularStringRadius.png</file>
<file>themes/default/mActionCircularStringRadius.svg</file>
<file>flags/zh.png</file>
<file>icons/qgis-icon-16x16_xmas.png</file>
@@ -665,6 +570,8 @@
<file>themes/default/mActionAddAfsLayer.svg</file>
<file>themes/default/mIconFormSelect.svg</file>
<file>themes/default/mActionMultiEdit.svg</file>
+ <file>themes/default/mIconClearText.svg</file>
+ <file>themes/default/mIconClearTextHover.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
diff --git a/images/splash/splash.png b/images/splash/splash.png
index 826b3e3..10f9964 100644
Binary files a/images/splash/splash.png and b/images/splash/splash.png differ
diff --git a/images/themes/default/extents.png b/images/themes/default/extents.png
deleted file mode 100644
index a64d3f8..0000000
Binary files a/images/themes/default/extents.png and /dev/null differ
diff --git a/images/themes/default/histogram.png b/images/themes/default/histogram.png
deleted file mode 100644
index 5e22752..0000000
Binary files a/images/themes/default/histogram.png and /dev/null differ
diff --git a/images/themes/default/mActionAddBasicShape.png b/images/themes/default/mActionAddBasicShape.png
deleted file mode 100644
index d63e06f..0000000
Binary files a/images/themes/default/mActionAddBasicShape.png and /dev/null differ
diff --git a/images/themes/default/mActionCalculateField.png b/images/themes/default/mActionCalculateField.png
deleted file mode 100644
index f18a061..0000000
Binary files a/images/themes/default/mActionCalculateField.png and /dev/null differ
diff --git a/images/themes/default/mActionCaptureLine.png b/images/themes/default/mActionCaptureLine.png
deleted file mode 100644
index 50c58f0..0000000
Binary files a/images/themes/default/mActionCaptureLine.png and /dev/null differ
diff --git a/images/themes/default/mActionDeleteAttribute.png b/images/themes/default/mActionDeleteAttribute.png
deleted file mode 100644
index e4f03f5..0000000
Binary files a/images/themes/default/mActionDeleteAttribute.png and /dev/null differ
diff --git a/images/themes/default/mActionFilter.png b/images/themes/default/mActionFilter.png
deleted file mode 100644
index ee62d49..0000000
Binary files a/images/themes/default/mActionFilter.png and /dev/null differ
diff --git a/images/themes/default/mActionNewAttribute.png b/images/themes/default/mActionNewAttribute.png
deleted file mode 100644
index 4039201..0000000
Binary files a/images/themes/default/mActionNewAttribute.png and /dev/null differ
diff --git a/images/themes/default/mActionRotateLabel.png b/images/themes/default/mActionRotateLabel.png
deleted file mode 100644
index 8add094..0000000
Binary files a/images/themes/default/mActionRotateLabel.png and /dev/null differ
diff --git a/images/themes/default/mActionToggleEditing.png b/images/themes/default/mActionToggleEditing.png
deleted file mode 100644
index 7b212b5..0000000
Binary files a/images/themes/default/mActionToggleEditing.png and /dev/null differ
diff --git a/images/themes/default/mIconClear.png b/images/themes/default/mIconClear.png
deleted file mode 100644
index e6c8e8b..0000000
Binary files a/images/themes/default/mIconClear.png and /dev/null differ
diff --git a/images/themes/default/mIconClearText.svg b/images/themes/default/mIconClearText.svg
new file mode 100644
index 0000000..9c03ed7
--- /dev/null
+++ b/images/themes/default/mIconClearText.svg
@@ -0,0 +1,72 @@
+<?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"
+ id="svg2"
+ height="16"
+ width="16"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="mIconClearText.svg">
+ <defs
+ id="defs10" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1215"
+ inkscape:window-height="776"
+ id="namedview8"
+ showgrid="true"
+ inkscape:zoom="23.6"
+ inkscape:cx="2.2245763"
+ inkscape:cy="8.3898305"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4138" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <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></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero [...]
+ d="M 4.6303139,3 1,8 4.6303139,13 14,13 14,3 13.824245,3 Z"
+ id="path2999"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0"
+ d="M 5.9226862,10.69629 11.701082,5.2732861"
+ id="path3775" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0"
+ d="M 5.9226862,5.2732861 11.701082,10.69629"
+ id="path3777" />
+</svg>
diff --git a/images/themes/default/mIconClearTextHover.svg b/images/themes/default/mIconClearTextHover.svg
new file mode 100644
index 0000000..c873002
--- /dev/null
+++ b/images/themes/default/mIconClearTextHover.svg
@@ -0,0 +1,72 @@
+<?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"
+ id="svg2"
+ height="16"
+ width="16"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="mIconClearTextHover.svg">
+ <defs
+ id="defs10" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1215"
+ inkscape:window-height="776"
+ id="namedview8"
+ showgrid="true"
+ inkscape:zoom="23.6"
+ inkscape:cx="2.2245763"
+ inkscape:cy="8.3898305"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4138" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <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></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero [...]
+ d="M 4.6303139,3 1,8 4.6303139,13 14,13 14,3 13.824245,3 Z"
+ id="path2999"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0"
+ d="M 5.9226862,10.69629 11.701082,5.2732861"
+ id="path3775" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0"
+ d="M 5.9226862,5.2732861 11.701082,10.69629"
+ id="path3777" />
+</svg>
diff --git a/images/themes/default/mIconClose.png b/images/themes/default/mIconClose.png
deleted file mode 100644
index 514c9d0..0000000
Binary files a/images/themes/default/mIconClose.png and /dev/null differ
diff --git a/images/themes/default/mIconClose.svg b/images/themes/default/mIconClose.svg
new file mode 100644
index 0000000..7fa4f85
--- /dev/null
+++ b/images/themes/default/mIconClose.svg
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<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"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ width="32px"
+ height="32px"
+ viewBox="0 0 32 32"
+ enable-background="new 0 0 32 32"
+ xml:space="preserve"
+ inkscape:version="0.48.2 r9819"
+ sodipodi:docname="mIconClose.svg"><metadata
+ id="metadata3043"><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></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs3041" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1916"
+ inkscape:window-height="1156"
+ id="namedview3039"
+ showgrid="false"
+ inkscape:zoom="26.875"
+ inkscape:cx="16"
+ inkscape:cy="16"
+ inkscape:window-x="4"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="Layer_1" />
+<path
+ opacity="0.75"
+ d="M16,1C7.715,1,1,7.716,1,16c0,8.283,6.715,15,15,15c8.283,0,15-6.717,15-15C31,7.716,24.283,1,16,1z M23.76,20.932c0.781,0.781,0.781,2.047,0,2.828c-0.391,0.391-0.902,0.586-1.414,0.586s-1.023-0.195-1.414-0.586L16,18.828 l-4.931,4.932c-0.39,0.391-0.902,0.586-1.414,0.586S8.631,24.15,8.241,23.76c-0.781-0.781-0.781-2.047,0-2.828L13.172,16 l-4.931-4.931c-0.781-0.781-0.781-2.047,0-2.828c0.78-0.781,2.048-0.781,2.828,0L16,13.172l4.932-4.931 c0.781-0.781,2.047-0.781,2.828,0c0.781,0.781,0.78 [...]
+ id="path3035" />
+<path
+ opacity="0.9"
+ fill="#FFFFFF"
+ d="M18.828,16l4.932-4.931c0.781-0.781,0.781-2.047,0-2.828c-0.781-0.781-2.047-0.781-2.828,0 L16,13.172l-4.931-4.931c-0.78-0.781-2.048-0.781-2.828,0c-0.781,0.781-0.781,2.047,0,2.828L13.172,16l-4.931,4.932 c-0.781,0.781-0.781,2.047,0,2.828c0.39,0.391,0.902,0.586,1.414,0.586s1.024-0.195,1.414-0.586L16,18.828l4.932,4.932 c0.391,0.391,0.902,0.586,1.414,0.586s1.023-0.195,1.414-0.586c0.781-0.781,0.781-2.047,0-2.828L18.828,16z"
+ id="path3037" />
+</svg>
\ No newline at end of file
diff --git a/images/themes/default/mIconWarn.png b/images/themes/default/mIconWarn.png
deleted file mode 100644
index 3eaf954..0000000
Binary files a/images/themes/default/mIconWarn.png and /dev/null differ
diff --git a/images/themes/default/symbologyAdd.png b/images/themes/default/symbologyAdd.png
deleted file mode 100644
index 57f0c34..0000000
Binary files a/images/themes/default/symbologyAdd.png and /dev/null differ
diff --git a/images/themes/default/symbologyDown.png b/images/themes/default/symbologyDown.png
deleted file mode 100644
index 1f4ab81..0000000
Binary files a/images/themes/default/symbologyDown.png and /dev/null differ
diff --git a/images/themes/default/symbologyRemove.png b/images/themes/default/symbologyRemove.png
deleted file mode 100644
index 6ed6095..0000000
Binary files a/images/themes/default/symbologyRemove.png and /dev/null differ
diff --git a/images/themes/default/transformed.png b/images/themes/default/transformed.png
deleted file mode 100644
index 30f853d..0000000
Binary files a/images/themes/default/transformed.png and /dev/null differ
diff --git a/images/themes/default/transformed.svg b/images/themes/default/transformed.svg
new file mode 100644
index 0000000..c2caabc
--- /dev/null
+++ b/images/themes/default/transformed.svg
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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"
+ version="1.0"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ width="32"
+ height="32"
+ sodipodi:docname="transformed.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <g
+ id="g3353"
+ transform="translate(0.88,0.94432)"
+ style="stroke:#cfcfcf;stroke-opacity:1">
+ <rect
+ ry="1.0600001"
+ y="0.56"
+ x="0.47999999"
+ height="28.92"
+ width="30"
+ id="rect3355"
+ style="opacity:0.9264214;fill:#171717;fill-opacity:0;fill-rule:nonzero;stroke:#cfcfcf;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path3357"
+ d="M 0.44,6.04 L 30.44,6.04"
+ style="fill:none;fill-rule:evenodd;stroke:#cfcfcf;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3359"
+ d="M 0.52,15.36 L 30.24,15.4"
+ style="fill:none;fill-rule:evenodd;stroke:#cfcfcf;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3361"
+ d="M 0.64,23.48 L 30.32,23.44"
+ style="fill:none;fill-rule:evenodd;stroke:#cfcfcf;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3363"
+ d="M 6.56,0.6 L 6.56,29.08"
+ style="fill:none;fill-rule:evenodd;stroke:#cfcfcf;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3365"
+ d="M 15.48,0.48 L 15.6,29.12"
+ style="fill:none;fill-rule:evenodd;stroke:#cfcfcf;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3367"
+ d="M 23.56,0.68 L 23.68,29.2"
+ style="fill:none;fill-rule:evenodd;stroke:#cfcfcf;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <metadata
+ id="metadata15">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs13">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective17" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="986"
+ inkscape:window-width="1680"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="25"
+ inkscape:cx="9.06"
+ inkscape:cy="16.15568"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="svg2" />
+<!-- Generator: Xara Xtreme 2.0, SVG Export Plug-In Version: 0.4 --><!-- Generated 2008-08-06 12:16:14 --><!-- not very useful exporter for now... --><!-- entity tag="40" --><!-- entity tag="1" --><!-- entity tag="4114" --><!-- entity tag="4116" --><!-- entity tag="4124" --><!-- entity tag="80" --><!-- entity tag="41" --><!-- entity tag="1" --><!-- entity tag="42" --><!-- entity tag="1" --><!-- entity tag="45" --><!-- entity tag="53" --><!-- entity tag="4031" --><!-- entity tag="43" -->< [...]
+ x="674598"
+ y="1046995"
+ width="375942"
+ height="375108"
+ id="rect4" />
+<!-- entity tag="1" --><!-- entity tag="176" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="0" --><!-- entity tag="104" --><!-- entit [...]
+ x="674599"
+ y="1046736"
+ width="375942"
+ height="375108"
+ id="rect6" />
+<!-- entity tag="1" --><!-- entity tag="176" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="0" --><!-- entity tag="104" --><!-- entit [...]
+ x="674599"
+ y="1046736"
+ width="375942"
+ height="375108"
+ id="rect8" />
+<!-- entity tag="1" --><!-- entity tag="176" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="0" --><!-- entity tag="4050" --><!-- enti [...]
+ x="313420"
+ y="236536"
+ width="375942"
+ height="375108"
+ id="rect10" />
+<!-- entity tag="1" --><!-- entity tag="176" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entity tag="1" --><!-- entity tag="111" --><!-- entity tag="150" --><!-- entity tag="0" --><!-- entity tag="0" --><!-- entity tag="115" --><!-- entit [...]
+ id="g3344"
+ transform="translate(0.16,4e-2)">
+ <rect
+ ry="1.0600001"
+ y="0.56"
+ x="0.47999999"
+ height="28.92"
+ width="30"
+ id="rect3330"
+ style="opacity:0.9264214;fill:#171717;fill-opacity:0;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path3332"
+ d="M 0.44,6.04 L 30.44,6.04"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3334"
+ d="M 0.52,15.36 L 30.24,15.4"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3336"
+ d="M 0.64,23.48 L 30.32,23.44"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3338"
+ d="M 6.56,0.6 L 6.56,29.08"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3340"
+ d="M 15.48,0.48 L 15.6,29.12"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3342"
+ d="M 23.56,0.68 L 23.68,29.2"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/ms-windows/Installer-Files/WelcomeFinishPage.bmp b/ms-windows/Installer-Files/WelcomeFinishPage.bmp
index 2e53d20..b32008e 100644
Binary files a/ms-windows/Installer-Files/WelcomeFinishPage.bmp and b/ms-windows/Installer-Files/WelcomeFinishPage.bmp differ
diff --git a/ms-windows/osgeo4w/creatensis.pl b/ms-windows/osgeo4w/creatensis.pl
index 01bd33b..2856930 100755
--- a/ms-windows/osgeo4w/creatensis.pl
+++ b/ms-windows/osgeo4w/creatensis.pl
@@ -355,6 +355,9 @@ close F;
$version = "$major.$minor.$patch" unless defined $version;
+my($pmajor,$pminor,$ppatch) = $version =~ /^(\d+)\.(\d+)\.(\d+)$/;
+die "Invalid version $version" unless defined $ppatch;
+
unless( defined $binary ) {
if( -f "binary$archpostfix-$version" ) {
open P, "binary$archpostfix-$version";
@@ -440,8 +443,8 @@ $cmd .= " -V$verbose";
$cmd .= " -DVERSION_NAME='$releasename'";
$cmd .= " -DVERSION_NUMBER='$version'";
$cmd .= " -DBINARY_REVISION=$binary";
-$cmd .= sprintf( " -DVERSION_INT='%d%02d%02d%02d'", $major, $minor, $patch, $binary );
-$cmd .= " -DQGIS_BASE='$packagename $releasename'";
+$cmd .= sprintf( " -DVERSION_INT='%d%02d%02d%02d'", $pmajor, $pminor, $ppatch, $binary );
+$cmd .= sprintf( " -DQGIS_BASE='$packagename %d.%d'", $pmajor, $pminor );
$cmd .= " -DINSTALLER_NAME='$packagename-OSGeo4W-$version-$binary-Setup$archpostfix.exe'";
$cmd .= " -DDISPLAYED_NAME='$packagename \'$releasename\' ($version)'";
$cmd .= " -DSHORTNAME='$shortname'";
diff --git a/ms-windows/osgeo4w/package-nightly.cmd b/ms-windows/osgeo4w/package-nightly.cmd
index a9302f1..546e9c6 100644
--- a/ms-windows/osgeo4w/package-nightly.cmd
+++ b/ms-windows/osgeo4w/package-nightly.cmd
@@ -29,7 +29,7 @@ if "%ARCH%"=="" goto usage
if not "%SHA%"=="" set SHA=-%SHA%
if "%SITE%"=="" set SITE=qgis.org
-set BUILDDIR=%CD%\build-nightly-%ARCH%
+set BUILDDIR=%CD%\build-%PACKAGENAME%-%ARCH%
if "%OSGEO4W_ROOT%"=="" (
if "%ARCH%"=="x86" (
diff --git a/ms-windows/osgeo4w/package.cmd b/ms-windows/osgeo4w/package.cmd
index c56f79e..dd3579a 100644
--- a/ms-windows/osgeo4w/package.cmd
+++ b/ms-windows/osgeo4w/package.cmd
@@ -29,7 +29,7 @@ if "%ARCH%"=="" goto usage
if not "%SHA%"=="" set SHA=-%SHA%
if "%SITE%"=="" set SITE=qgis.org
-set BUILDDIR=%CD%\build-%ARCH%
+set BUILDDIR=%CD%\build-%PACKAGENAME%-%ARCH%
if "%OSGEO4W_ROOT%"=="" (
if "%ARCH%"=="x86" (
@@ -341,6 +341,7 @@ tar -C %OSGEO4W_ROOT% -cjf %ARCH%/release/qgis/%PACKAGENAME%-server/%PACKAGENAME
"apps/%PACKAGENAME%/bin/wms_metadata.xml" ^
"apps/%PACKAGENAME%/bin/schemaExtension.xsd" ^
"apps/%PACKAGENAME%/python/qgis/_server.pyd" ^
+ "apps/%PACKAGENAME%/python/qgis/_server.lib" ^
"apps/%PACKAGENAME%/python/qgis/server/" ^
"httpd.d/httpd_%PACKAGENAME%.conf.tmpl" ^
"etc/postinstall/%PACKAGENAME%-server.bat" ^
diff --git a/python/PyQt/PyQt4/Qt.py b/python/PyQt/PyQt4/Qt.py
new file mode 100644
index 0000000..03274e6
--- /dev/null
+++ b/python/PyQt/PyQt4/Qt.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ Qt.py
+ ---------------------
+ Date : September 2016
+ Copyright : (C) 2015 by Marco Bernasocchi
+ Email : marco at opengis dot ch
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Marco Bernasocchi'
+__date__ = 'September 2016'
+__copyright__ = '(C) 2016, Marco Bernasocchi'
+# This will get replaced with a git SHA1 when you do a git archive
+__revision__ = '$Format:%H$'
+
+
+from PyQt4.Qt import *
diff --git a/python/PyQt/PyQt5/Qt.py b/python/PyQt/PyQt5/Qt.py
new file mode 100644
index 0000000..12e8225
--- /dev/null
+++ b/python/PyQt/PyQt5/Qt.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ Qt.py
+ ---------------------
+ Date : September 2016
+ Copyright : (C) 2015 by Marco Bernasocchi
+ Email : marco at opengis dot ch
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Marco Bernasocchi'
+__date__ = 'September 2016'
+__copyright__ = '(C) 2016, Marco Bernasocchi'
+# This will get replaced with a git SHA1 when you do a git archive
+__revision__ = '$Format:%H$'
+
+
+from PyQt5.Qt import *
diff --git a/python/console/console.py b/python/console/console.py
index 5828ef3..4f8dbaf 100644
--- a/python/console/console.py
+++ b/python/console/console.py
@@ -212,7 +212,7 @@ class PythonConsoleWidget(QWidget):
self.cutEditorButton = QAction(self)
self.cutEditorButton.setCheckable(False)
self.cutEditorButton.setEnabled(True)
- self.cutEditorButton.setIcon(QgsApplication.getThemeIcon("mActionEditCut.png"))
+ self.cutEditorButton.setIcon(QgsApplication.getThemeIcon("mActionEditCut.svg"))
self.cutEditorButton.setMenuRole(QAction.PreferencesRole)
self.cutEditorButton.setIconVisibleInMenu(True)
self.cutEditorButton.setToolTip(cutEditorBt)
@@ -222,7 +222,7 @@ class PythonConsoleWidget(QWidget):
self.copyEditorButton = QAction(self)
self.copyEditorButton.setCheckable(False)
self.copyEditorButton.setEnabled(True)
- self.copyEditorButton.setIcon(QgsApplication.getThemeIcon("mActionEditCopy.png"))
+ self.copyEditorButton.setIcon(QgsApplication.getThemeIcon("mActionEditCopy.svg"))
self.copyEditorButton.setMenuRole(QAction.PreferencesRole)
self.copyEditorButton.setIconVisibleInMenu(True)
self.copyEditorButton.setToolTip(copyEditorBt)
@@ -232,7 +232,7 @@ class PythonConsoleWidget(QWidget):
self.pasteEditorButton = QAction(self)
self.pasteEditorButton.setCheckable(False)
self.pasteEditorButton.setEnabled(True)
- self.pasteEditorButton.setIcon(QgsApplication.getThemeIcon("mActionEditPaste.png"))
+ self.pasteEditorButton.setIcon(QgsApplication.getThemeIcon("mActionEditPaste.svg"))
self.pasteEditorButton.setMenuRole(QAction.PreferencesRole)
self.pasteEditorButton.setIconVisibleInMenu(True)
self.pasteEditorButton.setToolTip(pasteEditorBt)
diff --git a/python/console/console_editor.py b/python/console/console_editor.py
index 9e00a5f..53a655e 100644
--- a/python/console/console_editor.py
+++ b/python/console/console_editor.py
@@ -294,9 +294,9 @@ class Editor(QsciScintilla):
iconFind = QgsApplication.getThemeIcon("console/iconSearchEditorConsole.png")
iconSyntaxCk = QgsApplication.getThemeIcon("console/iconSyntaxErrorConsole.png")
iconObjInsp = QgsApplication.getThemeIcon("console/iconClassBrowserConsole.png")
- iconCut = QgsApplication.getThemeIcon("mActionEditCut.png")
- iconCopy = QgsApplication.getThemeIcon("mActionEditCopy.png")
- iconPaste = QgsApplication.getThemeIcon("mActionEditPaste.png")
+ iconCut = QgsApplication.getThemeIcon("mActionEditCut.svg")
+ iconCopy = QgsApplication.getThemeIcon("mActionEditCopy.svg")
+ iconPaste = QgsApplication.getThemeIcon("mActionEditPaste.svg")
menu.addAction(
QCoreApplication.translate("PythonConsole", "Hide Editor"),
self.hideEditor)
@@ -899,7 +899,7 @@ class EditorTabWidget(QTabWidget):
toolTipClose = QCoreApplication.translate("PythonConsole",
"Close")
self.clButton.setToolTip(toolTipClose)
- self.clButton.setIcon(QgsApplication.getThemeIcon("mIconClose.png"))
+ self.clButton.setIcon(QgsApplication.getThemeIcon("/mIconClose.svg"))
self.clButton.setIconSize(QSize(18, 18))
self.clButton.setCursor(Qt.PointingHandCursor)
self.clButton.setStyleSheet('QToolButton:hover{border: none } \
diff --git a/python/core/composer/qgscomposerattributetable.sip b/python/core/composer/qgscomposerattributetable.sip
index d1b1284..d2aadda 100644
--- a/python/core/composer/qgscomposerattributetable.sip
+++ b/python/core/composer/qgscomposerattributetable.sip
@@ -164,7 +164,7 @@ class QgsComposerAttributeTable : QgsComposerTable
void setFeatureFilter( const QString& expression );
/** Returns the attributes fields which are shown by the table.
- * @returns a QSet of integers refering to the attributes in the vector layer. If
+ * @returns a QSet of integers referring to the attributes in the vector layer. If
* result is an empty QSet than all feature attributes will be shown.
* @see setDisplayAttributes
* @deprecated use QgsComposerTable::columns() instead
@@ -172,7 +172,7 @@ class QgsComposerAttributeTable : QgsComposerTable
QSet<int> displayAttributes() const /Deprecated/;
/** Sets the attributes to display in the table.
- * @param attr QSet of integer values refering to the attributes from the vector layer to show.
+ * @param attr QSet of integer values referring to the attributes from the vector layer to show.
* Set to an empty QSet to show all feature attributes.
* @param refresh set to true to force the table to refetch features from its vector layer
* and immediately update the display of the table. This may result in the table changing size
diff --git a/python/core/composer/qgscomposerattributetablev2.sip b/python/core/composer/qgscomposerattributetablev2.sip
index 2d86b51..62628c8 100644
--- a/python/core/composer/qgscomposerattributetablev2.sip
+++ b/python/core/composer/qgscomposerattributetablev2.sip
@@ -231,7 +231,7 @@ class QgsComposerAttributeTableV2 : QgsComposerTableV2
void setFeatureFilter( const QString& expression );
/** Sets the attributes to display in the table.
- * @param attr QSet of integer values refering to the attributes from the vector layer to show.
+ * @param attr QSet of integer values referring to the attributes from the vector layer to show.
* Set to an empty QSet to show all feature attributes.
* @param refresh set to true to force the table to refetch features from its vector layer
* and immediately update the display of the table. This may result in the table changing size
diff --git a/python/core/composer/qgscomposerlegend.sip b/python/core/composer/qgscomposerlegend.sip
index 17d9a0f..7dc9617 100644
--- a/python/core/composer/qgscomposerlegend.sip
+++ b/python/core/composer/qgscomposerlegend.sip
@@ -50,13 +50,13 @@ class QgsComposerLegend : QgsComposerItem
* @param enabled set to false to disable automatic resizing. The legend frame will not
* be expanded to fit legend items, and items may be cropped from display.
* @see resizeToContents()
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
void setResizeToContents( bool enabled );
/** Returns whether the legend should automatically resize to fit its contents.
* @see setResizeToContents()
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
bool resizeToContents() const;
diff --git a/python/core/composer/qgscomposerpicture.sip b/python/core/composer/qgscomposerpicture.sip
index 7c9386e..4c8e33a 100644
--- a/python/core/composer/qgscomposerpicture.sip
+++ b/python/core/composer/qgscomposerpicture.sip
@@ -30,6 +30,13 @@ class QgsComposerPicture: QgsComposerItem
Unknown
};
+ //! Method for syncing rotation to a map's North direction
+ enum NorthMode
+ {
+ GridNorth, /*!< Align to grid north */
+ TrueNorth, /*!< Align to true north */
+ };
+
QgsComposerPicture( QgsComposition *composition /TransferThis/);
~QgsComposerPicture();
@@ -132,6 +139,38 @@ class QgsComposerPicture: QgsComposerItem
*/
bool useRotationMap() const;
+ /**
+ * Returns the mode used to align the picture to a map's North.
+ * @see setNorthMode()
+ * @see northOffset()
+ * @note added in QGIS 2.18
+ */
+ NorthMode northMode() const;
+
+ /**
+ * Sets the mode used to align the picture to a map's North.
+ * @see northMode()
+ * @see setNorthOffset()
+ * @note added in QGIS 2.18
+ */
+ void setNorthMode( NorthMode mode );
+
+ /**
+ * Returns the offset added to the picture's rotation from a map's North.
+ * @see setNorthOffset()
+ * @see northMode()
+ * @note added in QGIS 2.18
+ */
+ double northOffset() const;
+
+ /**
+ * Sets the offset added to the picture's rotation from a map's North.
+ * @see northOffset()
+ * @see setNorthMode()
+ * @note added in QGIS 2.18
+ */
+ void setNorthOffset( double offset );
+
/** Returns the resize mode used for drawing the picture within the composer
* item's frame.
* @returns resize mode of picture
diff --git a/python/core/composer/qgscomposition.sip b/python/core/composer/qgscomposition.sip
index 4fc3b4b..c1c26b2 100644
--- a/python/core/composer/qgscomposition.sip
+++ b/python/core/composer/qgscomposition.sip
@@ -902,7 +902,7 @@ class QgsComposition : QGraphicsScene
void statusMsgChanged( QString message );
/** Emitted whenever the expression variables stored in the composition have been changed.
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
void variablesChanged();
};
diff --git a/python/core/core.sip b/python/core/core.sip
index 3e418b9..577c4c1 100644
--- a/python/core/core.sip
+++ b/python/core/core.sip
@@ -25,6 +25,7 @@
%Include qgsaggregatecalculator.sip
%Include qgsattributeaction.sip
%Include qgsattributetableconfig.sip
+%Include qgsbearingutils.sip
%Include qgsbrowsermodel.sip
%Include qgsclipper.sip
%Include qgscolorscheme.sip
@@ -54,6 +55,7 @@
%Include qgsfeaturefilterprovider.sip
%Include qgsfeatureiterator.sip
%Include qgsfeaturerequest.sip
+%Include qgsfeedback.sip
%Include qgsfield.sip
%Include qgsgeometrysimplifier.sip
%Include qgsgeometryvalidator.sip
@@ -101,6 +103,7 @@
%Include qgsobjectcustomproperties.sip
%Include qgsofflineediting.sip
%Include qgsogcutils.sip
+%Include qgsoptionalexpression.sip
%Include qgsowsconnection.sip
%Include qgspaintenginehack.sip
%Include qgspallabeling.sip
diff --git a/python/core/dxf/qgsdxfexport.sip b/python/core/dxf/qgsdxfexport.sip
index 653b72b..f1f220c 100644
--- a/python/core/dxf/qgsdxfexport.sip
+++ b/python/core/dxf/qgsdxfexport.sip
@@ -73,6 +73,16 @@ class QgsDxfExport
QGis::UnitType mapUnits() const;
/**
+ * Set destination CRS
+ */
+ void setDestinationCrs( long crs );
+
+ /**
+ * Set destination CRS
+ */
+ long destinationCrs();
+
+ /**
* Set symbology export mode
* @param e the mode
*/
@@ -227,8 +237,9 @@ class QgsDxfExport
* @param lineStyleName line type to use
* @param color color to use
* @param width line width to use
+ * @deprecated use QgsPointSequenceV2 variant
*/
- void writePolyline( const QgsPolyline &line, const QString &layer, const QString &lineStyleName, const QColor& color, double width = -1 );
+ void writePolyline( const QgsPolyline &line, const QString &layer, const QString &lineStyleName, const QColor& color, double width = -1 ) /Deprecated/;
/**
* Draw dxf primitives (LWPOLYLINE)
@@ -276,7 +287,8 @@ class QgsDxfExport
void writeSolid( const QString &layer, const QColor& color, const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, const QgsPoint &pt4 ) /Deprecated/;
//! Write line (as a polyline)
- void writeLine( const QgsPoint &pt1, const QgsPoint &pt2, const QString &layer, const QString &lineStyleName, const QColor& color, double width = -1 );
+ //! @deprecated use QgsPointV2 version
+ void writeLine( const QgsPoint &pt1, const QgsPoint &pt2, const QString &layer, const QString &lineStyleName, const QColor& color, double width = -1 ) /Deprecated/;
//! Write line (as a polyline)
//! @note added in 2.15
diff --git a/python/core/geometry/qgsabstractgeometryv2.sip b/python/core/geometry/qgsabstractgeometryv2.sip
index 259f1d4..4f1ffae 100644
--- a/python/core/geometry/qgsabstractgeometryv2.sip
+++ b/python/core/geometry/qgsabstractgeometryv2.sip
@@ -130,6 +130,13 @@ class QgsAbstractGeometryV2
*/
bool isMeasure() const;
+ /** Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the geometry).
+ * For instance, a polygon geometry will have a boundary consisting of the linestrings for each ring in the polygon.
+ * @returns boundary for geometry. May be null for some geometry types.
+ * @note added in QGIS 2.18
+ */
+ virtual QgsAbstractGeometryV2* boundary() const = 0;
+
//import
/** Sets the geometry from a WKB string.
@@ -254,7 +261,7 @@ class QgsAbstractGeometryV2
* @param leftOf returns whether the point lies on the left side of the nearest segment (true if point is to left of segment,
* false if point is to right of segment)
* @param epsilon epsilon for segment snapping
- * @returns squared distance to closest segment
+ * @returns squared distance to closest segment or negative value on error
*/
virtual double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const = 0;
diff --git a/python/core/geometry/qgscurvepolygonv2.sip b/python/core/geometry/qgscurvepolygonv2.sip
index d79d0cf..d6c4ee6 100644
--- a/python/core/geometry/qgscurvepolygonv2.sip
+++ b/python/core/geometry/qgscurvepolygonv2.sip
@@ -29,6 +29,8 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
virtual double area() const;
virtual double perimeter() const;
QgsPolygonV2* surfaceToPolygon() const;
+ virtual QgsAbstractGeometryV2* boundary() const /Factory/;
+
//curve polygon interface
int numInteriorRings() const;
diff --git a/python/core/geometry/qgscurvev2.sip b/python/core/geometry/qgscurvev2.sip
index 740268a..890ec31 100644
--- a/python/core/geometry/qgscurvev2.sip
+++ b/python/core/geometry/qgscurvev2.sip
@@ -75,6 +75,8 @@ class QgsCurveV2: public QgsAbstractGeometryV2
*/
virtual QgsCurveV2* reversed() const = 0 /Factory/;
+ virtual QgsAbstractGeometryV2* boundary() const /Factory/;
+
/** Returns a geometry without curves. Caller takes ownership
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
diff --git a/python/core/geometry/qgsgeometry.sip b/python/core/geometry/qgsgeometry.sip
index 22bf640..c55875c 100644
--- a/python/core/geometry/qgsgeometry.sip
+++ b/python/core/geometry/qgsgeometry.sip
@@ -179,7 +179,7 @@ class QgsGeometry
* @param afterVertex will be set to the vertex index of the next vertex after the closest one. Will be set to -1 if
* not present.
* @param sqrDist will be set to the square distance between the closest vertex and the specified point
- * @returns closest point in geometry
+ * @returns closest point in geometry. If not found (empty geometry), returns null point nad sqrDist is negative.
*/
//TODO QGIS 3.0 - rename beforeVertex to previousVertex, afterVertex to nextVertex
QgsPoint closestVertex( const QgsPoint& point, int& atVertex /Out/, int& beforeVertex /Out/, int& afterVertex /Out/, double& sqrDist /Out/ ) const;
@@ -193,6 +193,15 @@ class QgsGeometry
double distanceToVertex( int vertex ) const;
/**
+ * Returns the bisector angle for this geometry at the specified vertex.
+ * @param vertex vertex index to calculate bisector angle at
+ * @returns bisector angle, in radians clockwise from north
+ * @note added in QGIS 2.18
+ * @see interpolateAngle()
+ */
+ double angleAtVertex( int vertex ) const;
+
+ /**
* Returns the indexes of the vertices before and after the given vertex index.
*
* This function takes into account the following factors:
@@ -473,9 +482,32 @@ class QgsGeometry
/**
* Return interpolated point on line at distance
* @note added in 1.9
+ * @see lineLocatePoint()
*/
QgsGeometry* interpolate( double distance ) /Factory/;
+ /** Returns a distance representing the location along this linestring of the closest point
+ * on this linestring geometry to the specified point. Ie, the returned value indicates
+ * how far along this linestring you need to traverse to get to the closest location
+ * where this linestring comes to the specified point.
+ * @param point point to seek proximity to
+ * @return distance along line, or -1 on error
+ * @note only valid for linestring geometries
+ * @see interpolate()
+ * @note added in QGIS 2.18
+ */
+ double lineLocatePoint( const QgsGeometry& point ) const;
+
+ /** Returns the angle parallel to the linestring or polygon boundary at the specified distance
+ * along the geometry. Angles are in radians, clockwise from north.
+ * If the distance coincides precisely at a node then the average angle from the segment either side
+ * of the node is returned.
+ * @param distance distance along geometry
+ * @note added in QGIS 2.18
+ * @see angleAtVertex()
+ */
+ double interpolateAngle( double distance ) const;
+
/** Returns a geometry representing the points shared by this geometry and other. */
QgsGeometry* intersection( const QgsGeometry* geometry ) const /Factory/;
@@ -485,6 +517,15 @@ class QgsGeometry
*/
QgsGeometry* combine( const QgsGeometry* geometry ) const /Factory/;
+ /** Merges any connected lines in a LineString/MultiLineString geometry and
+ * converts them to single line strings.
+ * @returns a LineString or MultiLineString geometry, with any connected lines
+ * joined. An empty geometry will be returned if the input geometry was not a
+ * MultiLineString geometry.
+ * @note added in QGIS 2.18
+ */
+ QgsGeometry mergeLines() const;
+
/** Returns a geometry representing the points making up this geometry that do not make up other. */
QgsGeometry* difference( const QgsGeometry* geometry ) const /Factory/;
diff --git a/python/core/geometry/qgsgeometrycollectionv2.sip b/python/core/geometry/qgsgeometrycollectionv2.sip
index 306ccb7..2423dcc 100644
--- a/python/core/geometry/qgsgeometrycollectionv2.sip
+++ b/python/core/geometry/qgsgeometrycollectionv2.sip
@@ -30,6 +30,7 @@ class QgsGeometryCollectionV2: public QgsAbstractGeometryV2
virtual int dimension() const;
virtual QString geometryType() const;
virtual void clear();
+ virtual QgsAbstractGeometryV2* boundary() const /Factory/;
/** Adds a geometry and takes ownership. Returns true in case of success.*/
virtual bool addGeometry( QgsAbstractGeometryV2* g /Transfer/ );
diff --git a/python/core/geometry/qgsmulticurvev2.sip b/python/core/geometry/qgsmulticurvev2.sip
index f40774b..bce8521 100644
--- a/python/core/geometry/qgsmulticurvev2.sip
+++ b/python/core/geometry/qgsmulticurvev2.sip
@@ -26,4 +26,6 @@ class QgsMultiCurveV2: public QgsGeometryCollectionV2
* @note added in QGIS 2.14
*/
QgsMultiCurveV2* reversed() const /Factory/;
+
+ virtual QgsAbstractGeometryV2* boundary() const /Factory/;
};
diff --git a/python/core/geometry/qgsmultipointv2.sip b/python/core/geometry/qgsmultipointv2.sip
index 2838451..ff355e6 100644
--- a/python/core/geometry/qgsmultipointv2.sip
+++ b/python/core/geometry/qgsmultipointv2.sip
@@ -20,6 +20,8 @@ class QgsMultiPointV2: public QgsGeometryCollectionV2
/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g );
+ virtual QgsAbstractGeometryV2* boundary() const /Factory/;
+
protected:
virtual bool wktOmitChildType() const;
diff --git a/python/core/geometry/qgsmultipolygonv2.sip b/python/core/geometry/qgsmultipolygonv2.sip
index f5d5ebd..4ce4280 100644
--- a/python/core/geometry/qgsmultipolygonv2.sip
+++ b/python/core/geometry/qgsmultipolygonv2.sip
@@ -24,6 +24,8 @@ class QgsMultiPolygonV2: public QgsMultiSurfaceV2
@return the converted geometry. Caller takes ownership*/
QgsAbstractGeometryV2* toCurveType() const /Factory/;
+ virtual QgsAbstractGeometryV2* boundary() const /Factory/;
+
protected:
virtual bool wktOmitChildType() const;
diff --git a/python/core/geometry/qgsmultisurfacev2.sip b/python/core/geometry/qgsmultisurfacev2.sip
index 2e406d1..7b3d9ff 100644
--- a/python/core/geometry/qgsmultisurfacev2.sip
+++ b/python/core/geometry/qgsmultisurfacev2.sip
@@ -20,6 +20,8 @@ class QgsMultiSurfaceV2: public QgsGeometryCollectionV2
/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g );
+ virtual QgsAbstractGeometryV2* boundary() const /Factory/;
+
/** Returns a geometry without curves. Caller takes ownership*/
QgsAbstractGeometryV2* segmentize() const /Factory/;
};
diff --git a/python/core/geometry/qgspointv2.sip b/python/core/geometry/qgspointv2.sip
index 8dfe47e..b51a748 100644
--- a/python/core/geometry/qgspointv2.sip
+++ b/python/core/geometry/qgspointv2.sip
@@ -157,6 +157,7 @@ class QgsPointV2: public QgsAbstractGeometryV2
bool transformZ = false );
void transform( const QTransform& t );
virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const;
+ virtual QgsAbstractGeometryV2* boundary() const /Factory/;
//low-level editing
virtual bool insertVertex( QgsVertexId position, const QgsPointV2& vertex );
diff --git a/python/core/geometry/qgspolygonv2.sip b/python/core/geometry/qgspolygonv2.sip
index 859cd24..900e089 100644
--- a/python/core/geometry/qgspolygonv2.sip
+++ b/python/core/geometry/qgspolygonv2.sip
@@ -35,4 +35,5 @@ class QgsPolygonV2: public QgsCurvePolygonV2
//overridden to handle LineString25D rings
virtual void setExteriorRing( QgsCurveV2* ring /Transfer/ );
+ virtual QgsAbstractGeometryV2* boundary() const /Factory/;
};
diff --git a/python/core/layertree/qgslayertreemodel.sip b/python/core/layertree/qgslayertreemodel.sip
index da09dd0..de401db 100644
--- a/python/core/layertree/qgslayertreemodel.sip
+++ b/python/core/layertree/qgslayertreemodel.sip
@@ -94,15 +94,21 @@ class QgsLayerTreeModel : QAbstractItemModel
QModelIndex legendNode2index( QgsLayerTreeModelLegendNode* legendNode );
//! Return filtered list of active legend nodes attached to a particular layer node
+ //! (by default it returns also legend node embedded in parent layer node (if any) unless skipNodeEmbeddedInParent is true)
//! @note added in 2.6
+ //! @note skipNodeEmbeddedInParent added in 2.18
//! @see layerOriginalLegendNodes()
- QList<QgsLayerTreeModelLegendNode*> layerLegendNodes( QgsLayerTreeLayer* nodeLayer );
+ QList<QgsLayerTreeModelLegendNode*> layerLegendNodes( QgsLayerTreeLayer* nodeLayer, bool skipNodeEmbeddedInParent = false );
//! Return original (unfiltered) list of legend nodes attached to a particular layer node
//! @note added in 2.14
//! @see layerLegendNodes()
QList<QgsLayerTreeModelLegendNode*> layerOriginalLegendNodes( QgsLayerTreeLayer* nodeLayer );
+ //! Return legend node that may be embbeded in parent (i.e. its icon will be used for layer's icon).
+ //! @note added in 2.18
+ QgsLayerTreeModelLegendNode* legendNodeEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const;
+
/** Searches through the layer tree to find a legend node with a matching layer ID
* and rule key.
* @param layerId map layer ID
@@ -252,8 +258,6 @@ class QgsLayerTreeModel : QAbstractItemModel
QVariant legendNodeData( QgsLayerTreeModelLegendNode* node, int role ) const;
Qt::ItemFlags legendNodeFlags( QgsLayerTreeModelLegendNode* node ) const;
bool legendEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const;
- /** Return legend node that may be embbeded in parent (i.e. its icon will be used for layer's icon). */
- QgsLayerTreeModelLegendNode* legendNodeEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const;
QIcon legendIconEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const;
void legendCleanup();
void legendInvalidateMapBasedData();
diff --git a/python/core/qgsannotation.sip b/python/core/qgsannotation.sip
index 76b661a..a975545 100644
--- a/python/core/qgsannotation.sip
+++ b/python/core/qgsannotation.sip
@@ -1,6 +1,6 @@
/** \ingroup core
* \class QgsAnnotation
- * \note added in QGIS 3.0
+ * \note added in QGIS 2.18
*
* \brief An interface for annotation items which are drawn over a map.
*
diff --git a/python/core/qgsapplication.sip b/python/core/qgsapplication.sip
index be66870..323eeb8 100644
--- a/python/core/qgsapplication.sip
+++ b/python/core/qgsapplication.sip
@@ -385,7 +385,7 @@ static void qtgui_UpdatePyArgv(PyObject *argvlist, int argc, char **argv)
* be called whenever global, application-wide settings are altered to advise listeners
* that they may need to update their state.
* @see settingsChanged()
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
void emitSettingsChanged();
@@ -394,7 +394,7 @@ static void qtgui_UpdatePyArgv(PyObject *argvlist, int argc, char **argv)
// void preNotify( QObject * receiver, QEvent * event, bool * done );
/** Emitted whenever any global, application-wide settings are changed.
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
* @see emitSettingsChanged()
*/
void settingsChanged();
diff --git a/python/core/qgsbearingutils.sip b/python/core/qgsbearingutils.sip
new file mode 100644
index 0000000..078907c
--- /dev/null
+++ b/python/core/qgsbearingutils.sip
@@ -0,0 +1,21 @@
+/**
+ * \class QgsBearingUtils
+ * \ingroup core
+ * Utilities for calculating bearings and directions.
+ * \note Added in version 2.18
+*/
+class QgsBearingUtils
+{
+%TypeHeaderCode
+#include <qgsbearingutils.h>
+%End
+ public:
+
+ /**
+ * Returns the direction to true north from a specified point and for a specified
+ * coordinate reference system. The returned value is in degrees clockwise from
+ * vertical. An exception will be thrown if the bearing could not be calculated.
+ */
+ static double bearingTrueNorth( const QgsCoordinateReferenceSystem& crs,
+ const QgsPoint& point );
+};
diff --git a/python/core/qgscolorscheme.sip b/python/core/qgscolorscheme.sip
index 062e895..7aa6a4d 100644
--- a/python/core/qgscolorscheme.sip
+++ b/python/core/qgscolorscheme.sip
@@ -151,6 +151,8 @@ class QgsUserColorScheme : QgsGplColorScheme
virtual bool isEditable() const;
+ virtual QgsColorScheme::SchemeFlags flags() const;
+
/** Sets the name for the scheme
* @param name new name
*/
@@ -161,6 +163,12 @@ class QgsUserColorScheme : QgsGplColorScheme
*/
bool erase();
+ /** Sets whether a this scheme should be shown in color button menus.
+ * @param show set to true to show in color button menus, or false to hide from menus
+ * @note added in QGIS 2.18
+ */
+ void setShowSchemeInMenu( bool show );
+
protected:
virtual QString gplFilePath();
diff --git a/python/core/qgseditformconfig.sip b/python/core/qgseditformconfig.sip
index acc8f1a..7b40455 100644
--- a/python/core/qgseditformconfig.sip
+++ b/python/core/qgseditformconfig.sip
@@ -15,7 +15,7 @@
* *
***************************************************************************/
-class QgsAttributeEditorElement : QObject
+class QgsAttributeEditorElement : QObject /Abstract/
{
%TypeHeaderCode
#include "qgsvectorlayer.h"
@@ -74,13 +74,28 @@ class QgsAttributeEditorElement : QObject
AttributeEditorType type() const;
/**
- * Is reimplemented in classes inheriting from this to serialize it.
+ * Get the XML Dom element to save this element.
*
* @param doc The QDomDocument which is used to create new XML elements
*
- * @return An DOM element which represents this element
+ * @return A DOM element to serialize this element
*/
- virtual QDomElement toDomElement( QDomDocument& doc ) const = 0;
+ QDomElement toDomElement( QDomDocument& doc ) const;
+
+ /**
+ * Controls if this element should be labeled with a title (field, relation or groupname).
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLabel() const;
+
+ /**
+ * Controls if this element should be labeled with a title (field, relation or groupname).
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLabel(bool showLabel);
+
};
class QgsAttributeEditorContainer : QgsAttributeEditorElement
@@ -149,8 +164,6 @@ class QgsAttributeEditorContainer : QgsAttributeEditorElement
/**
* Change the name of this container
- *
- * @param name
*/
void setName( const QString& name );
@@ -164,6 +177,20 @@ class QgsAttributeEditorContainer : QgsAttributeEditorElement
*/
void setColumnCount( int columnCount );
+ /**
+ * An expression that controls the visibility of this container.
+ *
+ * @note Added in QGIS 2.18
+ */
+ QgsOptionalExpression visibilityExpression() const;
+
+ /**
+ * An expression that controls the visibility of this container.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setVisibilityExpression( const QgsOptionalExpression& visibilityExpression );
+
};
/**
@@ -255,6 +282,32 @@ class QgsAttributeEditorRelation : QgsAttributeEditorElement
* @return true if the relation was found in the relationmanager
*/
bool init( QgsRelationManager *relManager );
+
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLinkButton() const;
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLinkButton( bool showLinkButton );
+
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showUnlinkButton() const;
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowUnlinkButton( bool showUnlinkButton );
};
class QgsEditFormConfig : QObject
diff --git a/python/core/qgsexpression.sip b/python/core/qgsexpression.sip
index 5abce90..295253b 100644
--- a/python/core/qgsexpression.sip
+++ b/python/core/qgsexpression.sip
@@ -12,8 +12,23 @@ class QgsExpression
* loop in which this expression is used.
*/
QgsExpression( const QString& expr );
+ /**
+ * Create an empty expression.
+ *
+ * @note Added in QGIS 2.18
+ */
+ QgsExpression();
+
~QgsExpression();
+ /**
+ * Checks if this expression is valid.
+ * A valid expression could be parsed but does not necessarily evaluate properly.
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool isValid() const;
+
//! Returns true if an error occurred when parsing the input expression
bool hasParserError() const;
//! Returns parser error
@@ -135,6 +150,13 @@ class QgsExpression
double scale();
+ /**
+ * Set the expression string, will reset the whole internal structure.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setExpression( const QString& expression );
+
//! Return the original, unmodified expression string.
//! If there was none supplied because it was constructed by sole
//! API calls, dump() will be used to create one instead.
@@ -354,6 +376,19 @@ class QgsExpression
bool handlesNull = false,
bool isContextual = false );
+ /** Constructor for function which uses unnamed parameters and group list
+ * @note added in QGIS 3.0
+ */
+ Function( const QString& fnname,
+ int params,
+ const QStringList& groups,
+ const QString& helpText = QString(),
+ bool usesGeometry = false,
+ const QStringList& referencedColumns = QStringList(),
+ bool lazyEval = false,
+ bool handlesNull = false,
+ bool isContextual = false );
+
/** Constructor for function which uses named parameter list.
* @note added in QGIS 2.16
*/
@@ -367,6 +402,19 @@ class QgsExpression
bool handlesNull = false,
bool isContextual = false );
+ /** Constructor for function which uses named parameter list and group list.
+ * @note added in QGIS 3.0
+ */
+ Function( const QString& fnname,
+ const QgsExpression::ParameterList& params,
+ const QStringList& groups,
+ const QString& helpText = QString(),
+ bool usesGeometry = false,
+ const QStringList& referencedColumns = QStringList(),
+ bool lazyEval = false,
+ bool handlesNull = false,
+ bool isContextual = false );
+
virtual ~Function();
/** The name of the function. */
@@ -405,8 +453,23 @@ class QgsExpression
*/
bool isContextual() const;
- /** The group the function belongs to. */
+ /** Returns true if the function is deprecated and should not be presented as a valid option
+ * to users in expression builders.
+ * @note added in QGIS 3.0
+ */
+ virtual bool isDeprecated() const;
+
+ /** Returns the first group which the function belongs to.
+ * @note consider using groups() instead, as some functions naturally belong in multiple groups
+ */
QString group() const;
+
+ /** Returns a list of the groups the function belongs to.
+ * @note added in QGIS 3.0
+ * @see group()
+ */
+ QStringList groups() const;
+
/** The help text for the function. */
const QString helptext() const;
diff --git a/python/core/qgsexpressioncontext.sip b/python/core/qgsexpressioncontext.sip
index 57f89a8..79b38f6 100644
--- a/python/core/qgsexpressioncontext.sip
+++ b/python/core/qgsexpressioncontext.sip
@@ -299,7 +299,7 @@ class QgsExpressionContext
/** Returns the index of the first scope with a matching name within the context.
* @param scopeName name of scope to find
* @returns index of scope, or -1 if scope was not found within the context.
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
int indexOfScope( const QString& scopeName ) const;
diff --git a/python/core/qgsexpressionfieldbuffer.sip b/python/core/qgsexpressionfieldbuffer.sip
index dfa3aee..8bceb4a 100644
--- a/python/core/qgsexpressionfieldbuffer.sip
+++ b/python/core/qgsexpressionfieldbuffer.sip
@@ -28,6 +28,16 @@ class QgsExpressionFieldBuffer
void removeExpression( int index );
/**
+ * Renames an expression field at a given index
+ *
+ * @param index The index of the expression to change
+ * @param name New name for field
+ *
+ * @note added in 3.0
+ */
+ void renameExpression( int index, const QString& name );
+
+ /**
* Changes the expression at a given index
*
* @param index The index of the expression to change
diff --git a/python/core/qgsfeedback.sip b/python/core/qgsfeedback.sip
new file mode 100644
index 0000000..7b4d494
--- /dev/null
+++ b/python/core/qgsfeedback.sip
@@ -0,0 +1,43 @@
+
+/** \ingroup core
+ * Base class for feedback objects to be used for cancellation of something running in a worker thread.
+ * The class may be used as is or it may be subclassed for extended functionality
+ * for a particular operation (e.g. report progress or pass some data for preview).
+ *
+ * When cancel() is called, the internal code has two options to check for cancellation state:
+ * - if the worker thread uses an event loop (e.g. for network communication), the code can
+ * make a queued connection to cancelled() signal and handle the cancellation in its slot.
+ * - if the worker thread does not use an event loop, it can poll isCancelled() method regularly
+ * to see if the operation should be cancelled.
+ *
+ * The class is meant to be created and destroyed in the main thread.
+ *
+ * For map rendering, the object may be created in constructor of a QgsMapLayerRenderer
+ * subclass and available with QgsMapLayerRenderer::feedback() method. When a map rendering job
+ * gets cancelled, the cancel() method is called on the feedback object of all layers.
+ *
+ * @note added in QGIS 2.18
+ */
+class QgsFeedback : QObject
+{
+%TypeHeaderCode
+#include <qgsfeedback.h>
+%End
+
+ public:
+ //! Construct a feedback object
+ QgsFeedback( QObject* parent /TransferThis/ = nullptr );
+
+ virtual ~QgsFeedback();
+
+ //! Tells the internal routines that the current operation should be cancelled. This should be run by the main thread
+ void cancel();
+
+ //! Tells whether the operation has been cancelled already
+ bool isCancelled() const;
+
+ signals:
+ //! Internal routines can connect to this signal if they use event loop
+ void cancelled();
+
+};
diff --git a/python/core/qgsfield.sip b/python/core/qgsfield.sip
index a1bd42e..0ffe048 100644
--- a/python/core/qgsfield.sip
+++ b/python/core/qgsfield.sip
@@ -42,9 +42,20 @@ class QgsField
bool operator==( const QgsField& other ) const;
bool operator!=( const QgsField& other ) const;
- //! Gets the name of the field
+ /** Returns the name of the field.
+ * @see setName()
+ * @see displayName()
+ */
QString name() const;
+ /** Returns the name to use when displaying this field. This will be the
+ * field alias if set, otherwise the field name.
+ * @see name()
+ * @see alias()
+ * @note added in QGIS 2.18
+ */
+ QString displayName() const;
+
//! Gets variant type of the field as it will be retrieved from data source
QVariant::Type type() const;
@@ -74,6 +85,14 @@ class QgsField
QString comment() const;
/**
+ * Returns if this field is numeric. Any integer or floating point type
+ * will return true for this.
+ *
+ * @note added in QGIS 2.18
+ */
+ bool isNumeric() const;
+
+ /**
* Set the field name.
* @param name Name of the field
*/
@@ -107,6 +126,36 @@ class QgsField
*/
void setComment( const QString& comment );
+ /** Returns the expression used when calculating the default value for the field.
+ * @returns expression evaluated when calculating default values for field, or an
+ * empty string if no default is set
+ * @note added in QGIS 2.18
+ * @see setDefaultValueExpression()
+ */
+ QString defaultValueExpression() const;
+
+ /** Sets an expression to use when calculating the default value for the field.
+ * @param expression expression to evaluate when calculating default values for field. Pass
+ * an empty expression to clear the default.
+ * @note added in QGIS 2.18
+ * @see defaultValueExpression()
+ */
+ void setDefaultValueExpression( const QString& expression );
+
+ /** Returns the alias for the field (the friendly displayed name of the field ),
+ * or an empty string if there is no alias.
+ * @see setAlias()
+ * @note added in QGIS 2.18
+ */
+ QString alias() const;
+
+ /** Sets the alias for the field (the friendly displayed name of the field ).
+ * @param alias field alias, or empty string to remove an existing alias
+ * @see alias()
+ * @note added in QGIS 2.18
+ */
+ void setAlias( const QString& alias );
+
/** Formats string for display*/
QString displayString( const QVariant& v ) const;
diff --git a/python/core/qgsgeometryvalidator.sip b/python/core/qgsgeometryvalidator.sip
index 4e8c04a..9496a0e 100644
--- a/python/core/qgsgeometryvalidator.sip
+++ b/python/core/qgsgeometryvalidator.sip
@@ -13,7 +13,7 @@ class QgsGeometryValidator : QThread
void stop();
/** Validate geometry and produce a list of geometry errors */
- static void validateGeometry( const QgsGeometry *g, QList<QgsGeometry::Error> &errors );
+ static void validateGeometry( const QgsGeometry *g, QList<QgsGeometry::Error> &errors /Out/ );
signals:
void errorFound( const QgsGeometry::Error& );
diff --git a/python/core/qgsmaplayer.sip b/python/core/qgsmaplayer.sip
index dc083cd..4b20c39 100644
--- a/python/core/qgsmaplayer.sip
+++ b/python/core/qgsmaplayer.sip
@@ -10,10 +10,12 @@ class QgsMapLayer : QObject
%End
%ConvertToSubClassCode
- if (sipCpp->inherits("QgsMapLayer"))
+ QgsMapLayer* layer = qobject_cast<QgsMapLayer*>( sipCpp );
+
+ sipType = 0;
+
+ if ( layer )
{
- sipType = sipType_QgsMapLayer;
- QgsMapLayer* layer = qobject_cast<QgsMapLayer*>(sipCpp);
if (layer->type() == QgsMapLayer::VectorLayer)
{
sipType = sipType_QgsVectorLayer;
@@ -27,11 +29,6 @@ class QgsMapLayer : QObject
sipType = sipType_QgsPluginLayer;
}
}
- else
- {
- sipType = 0;
- }
-
%End
public:
diff --git a/python/core/qgsmaplayerrenderer.sip b/python/core/qgsmaplayerrenderer.sip
index ac45fdd..fea7820 100644
--- a/python/core/qgsmaplayerrenderer.sip
+++ b/python/core/qgsmaplayerrenderer.sip
@@ -12,6 +12,10 @@ class QgsMapLayerRenderer
//! Do the rendering (based on data stored in the class)
virtual bool render() = 0;
+ //! Access to feedback object of the layer renderer (may be null)
+ //! @note added in QGIS 2.18
+ virtual QgsFeedback* feedback() const;
+
//! Return list of errors (problems) that happened during the rendering
QStringList errors() const;
diff --git a/python/core/qgsmapsettings.sip b/python/core/qgsmapsettings.sip
index 6d0d213..9cb0d17 100644
--- a/python/core/qgsmapsettings.sip
+++ b/python/core/qgsmapsettings.sip
@@ -116,7 +116,8 @@ class QgsMapSettings
UseRenderingOptimization, //!< Enable vector simplification and other rendering optimizations
DrawSelection, //!< Whether vector selections should be shown in the rendered map
DrawSymbolBounds, //!< Draw bounds of symbols (for debugging/testing)
- RenderMapTile //!< Draw map such that there are no problems between adjacent tiles
+ RenderMapTile, //!< Draw map such that there are no problems between adjacent tiles
+ RenderPartialOutput, //!< Whether to make extra effort to update map image with partially rendered layers (better for interactive map canvas). Added in QGIS 2.18
};
typedef QFlags<QgsMapSettings::Flag> Flags;
diff --git a/python/core/qgsofflineediting.sip b/python/core/qgsofflineediting.sip
index c749613..6170f65 100644
--- a/python/core/qgsofflineediting.sip
+++ b/python/core/qgsofflineediting.sip
@@ -28,10 +28,10 @@ class QgsOfflineEditing : QObject
* @param offlineDbFile offline db file name
* @param layerIds list of layer names to convert
*/
- bool convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds );
+ bool convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds, bool onlySelected = false );
/** Return true if current project is offline */
- bool isOfflineProject();
+ bool isOfflineProject() const;
/** Synchronize to remote layers */
void synchronize();
diff --git a/python/core/qgsoptionalexpression.sip b/python/core/qgsoptionalexpression.sip
new file mode 100644
index 0000000..f444a3e
--- /dev/null
+++ b/python/core/qgsoptionalexpression.sip
@@ -0,0 +1,112 @@
+/***************************************************************************
+ qgsoptionalexpression.sip - QgsOptionalExpression
+
+ ---------------------
+ begin : 8.9.2016
+ copyright : (C) 2016 by Matthias Kuhn
+ email : matthias at opengis.ch
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/**
+ * An expression with an additional enabled flag.
+ *
+ * This can be used for configuration options where an expression can be enabled
+ * or diabled but when disabled it shouldn't lose it's information for the case
+ * it gets re-enabled later on and a user shouldn't be force to redo the configuration.
+ *
+ * @note Added in QGIS 2.18
+ */
+
+class QgsOptionalExpression
+{
+%TypeHeaderCode
+#include <qgsoptionalexpression.h>
+%End
+ public:
+ /**
+ * Construct a default optional expression.
+ * It will be disabled and with an empty expression.
+ */
+ QgsOptionalExpression();
+
+ /**
+ * Construct an optional expression with the provided expression.
+ * It will be enabled.
+ */
+ QgsOptionalExpression( const QgsExpression& expression );
+
+ /**
+ * Construct an optional expression with the provided expression and enabled state.
+ */
+ QgsOptionalExpression( const QgsExpression& expression, bool enabled );
+
+ /**
+ * Compare this QgsOptionalExpression to another one.
+ *
+ * This will compare the enabled flag and call the == operator
+ * of the contained class.
+ *
+ * @note Added in QGIS 2.18
+ */
+ int operator== ( const QgsOptionalExpression& other ) const;
+%MethodCode
+ sipRes = *sipCpp == *a0;
+%End
+
+ int __bool__() const;
+%MethodCode
+ sipRes = sipCpp->enabled();
+%End
+
+ /**
+ * Check if this optional is enabled
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool enabled() const;
+
+ /**
+ * Set if this optional is enabled
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setEnabled( bool enabled );
+
+ /**
+ * Access the payload data
+ *
+ * @note Added in QGIS 2.18
+ */
+ QgsExpression data() const;
+
+ /**
+ * Set the payload data
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setData( const QgsExpression& data );
+
+ /**
+ * Save the optional expression to the provided QDomElement.
+ *
+ * The caller is responsible to pass an empty QDomElement and to append it to
+ * a parent element.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void writeXml( QDomElement& element );
+
+ /**
+ * Read the optional expression from the provided QDomElement.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void readXml( const QDomElement& element );
+};
diff --git a/python/core/qgspallabeling.sip b/python/core/qgspallabeling.sip
index 0b3f813..488b58b 100644
--- a/python/core/qgspallabeling.sip
+++ b/python/core/qgspallabeling.sip
@@ -103,6 +103,7 @@ class QgsPalLayerSettings
Horizontal, /**< Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only.*/
Free, /**< Arranges candidates scattered throughout a polygon feature. Candidates are rotated to respect the polygon's orientation. Applies to polygon layers only.*/
OrderedPositionsAroundPoint, /**< Candidates are placed in predefined positions around a point. Peference is given to positions with greatest cartographic appeal, eg top right, bottom right, etc. Applies to point layers only.*/
+ PerimeterCurved, /** Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.*/
};
//! Positions for labels when using the QgsPalLabeling::OrderedPositionsAroundPoint placement mode
@@ -387,6 +388,11 @@ class QgsPalLayerSettings
QPainter::CompositionMode blendMode;
QColor previewBkgrdColor;
+ //! Substitution collection for automatic text substitution with labels
+ QgsStringReplacementCollection substitutions;
+ //! True if substitutions should be applied
+ bool useSubstitutions;
+
//-- text formatting
QString wrapChar;
diff --git a/python/core/qgsproject.sip b/python/core/qgsproject.sip
index 7fe8243..dfae60a 100644
--- a/python/core/qgsproject.sip
+++ b/python/core/qgsproject.sip
@@ -391,8 +391,14 @@ class QgsProject : QObject
//! Emitted when the list of layer which are excluded from map identification changes
void nonIdentifiableLayersChanged( QStringList nonIdentifiableLayers );
+ //! Emitted when the file name of the project changes
+ void fileNameChanged();
+
+ //! Emitted when the home path of the project changes
+ void homePathChanged();
+
/** Emitted whenever the expression variables stored in the project have been changed.
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
void variablesChanged();
@@ -410,7 +416,7 @@ class QgsProject : QObject
/** Causes the project to emit the variablesChanged() signal. This should
* be called whenever expression variables related to the project are changed.
* @see variablesChanged()
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
void emitVariablesChanged();
diff --git a/python/core/qgsrendercontext.sip b/python/core/qgsrendercontext.sip
index 3c5818b..16ee120 100644
--- a/python/core/qgsrendercontext.sip
+++ b/python/core/qgsrendercontext.sip
@@ -23,6 +23,7 @@ class QgsRenderContext
DrawSymbolBounds, //!< Draw bounds of symbols (for debugging/testing)
RenderMapTile, //!< Draw map such that there are no problems between adjacent tiles
Antialiasing, //!< Use antialiasing while drawing
+ RenderPartialOutput, //!< Whether to make extra effort to update map image with partially rendered layers (better for interactive map canvas). Added in QGIS 2.18
};
typedef QFlags<QgsRenderContext::Flag> Flags;
diff --git a/python/core/qgsstringutils.sip b/python/core/qgsstringutils.sip
index 7c133c7..4dce51c 100644
--- a/python/core/qgsstringutils.sip
+++ b/python/core/qgsstringutils.sip
@@ -1,3 +1,115 @@
+
+
+/** \ingroup core
+ * \class QgsStringReplacement
+ * \brief A representation of a single string replacement.
+ * \note Added in version 3.0
+ */
+
+class QgsStringReplacement
+{
+%TypeHeaderCode
+#include <qgsstringutils.h>
+%End
+ public:
+
+ /** Constructor for QgsStringReplacement.
+ * @param match string to match
+ * @param replacement string to replace match with
+ * @param caseSensitive set to true for a case sensitive match
+ * @param wholeWordOnly set to true to match complete words only, or false to allow partial word matches
+ */
+ QgsStringReplacement( const QString& match,
+ const QString& replacement,
+ bool caseSensitive = false,
+ bool wholeWordOnly = false );
+
+ //! Returns the string matched by this object
+ QString match() const;
+
+ //! Returns the string to replace matches with
+ QString replacement() const;
+
+ //! Returns true if match is case sensitive
+ bool caseSensitive() const;
+
+ //! Returns true if match only applies to whole words, or false if partial word matches are permitted
+ bool wholeWordOnly() const;
+
+ /** Processes a given input string, applying any valid replacements which should be made.
+ * @param input input string
+ * @returns input string with any matches replaced by replacement string
+ */
+ QString process( const QString& input ) const;
+
+ bool operator==( const QgsStringReplacement& other );
+
+ /** Returns a map of the replacement properties.
+ * @see fromProperties()
+ */
+ QgsStringMap properties() const;
+
+ /** Creates a new QgsStringReplacement from an encoded properties map.
+ * @see properties()
+ */
+ static QgsStringReplacement fromProperties( const QgsStringMap& properties );
+
+};
+
+
+/** \ingroup core
+ * \class QgsStringReplacementCollection
+ * \brief A collection of string replacements (specified using QgsStringReplacement objects).
+ * \note Added in version 3.0
+ */
+
+class QgsStringReplacementCollection
+{
+%TypeHeaderCode
+#include <qgsstringutils.h>
+%End
+ public:
+
+ /** Constructor for QgsStringReplacementCollection
+ * @param replacements initial list of string replacements
+ */
+ QgsStringReplacementCollection( const QList< QgsStringReplacement >& replacements = QList< QgsStringReplacement >() );
+
+ /** Returns the list of string replacements in this collection.
+ * @see setReplacements()
+ */
+ QList< QgsStringReplacement > replacements() const;
+
+ /** Sets the list of string replacements in this collection.
+ * @param replacements list of string replacements to apply. Replacements are applied in the
+ * order they are specified here.
+ * @see replacements()
+ */
+ void setReplacements( const QList< QgsStringReplacement >& replacements );
+
+ /** Processes a given input string, applying any valid replacements which should be made
+ * using QgsStringReplacement objects contained by this collection. Replacements
+ * are made in order of the QgsStringReplacement objects contained in the collection.
+ * @param input input string
+ * @returns input string with any matches replaced by replacement string
+ */
+ QString process( const QString& input ) const;
+
+ /** Writes the collection state to an XML element.
+ * @param elem target DOM element
+ * @param doc DOM document
+ * @see readXml()
+ */
+ void writeXml( QDomElement& elem, QDomDocument& doc ) const;
+
+ /** Reads the collection state from an XML element.
+ * @param elem DOM element
+ * @see writeXml()
+ */
+ void readXml( const QDomElement& elem );
+};
+
+
/** \ingroup core
* \class QgsStringUtils
* \brief Utility functions for working with strings.
@@ -25,7 +137,7 @@ class QgsStringUtils
* @param string input string
* @param capitalization capitalization type to apply
* @return capitalized string
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
static QString capitalize( const QString& string, Capitalization capitalization );
@@ -65,4 +177,13 @@ class QgsStringUtils
* @returns 4 letter Soundex code
*/
static QString soundex( const QString &string );
+
+ /** Returns a string with any URL (eg http(s)/ftp) and mailto: text converted to valid HTML <a ...>
+ * links.
+ * @param string string to insert links into
+ * @param foundLinks if specified, will be set to true if any links were inserted into the string
+ * @returns string with inserted links
+ * @note added in QGIS 2.18
+ */
+ static QString insertLinks( const QString& string, bool* foundLinks = nullptr );
};
diff --git a/python/core/qgsvectorlayer.sip b/python/core/qgsvectorlayer.sip
index d0e983e..0ca55f3 100644
--- a/python/core/qgsvectorlayer.sip
+++ b/python/core/qgsvectorlayer.sip
@@ -191,7 +191,7 @@ class QgsVectorLayer : QgsMapLayer
void setDisplayField( const QString& fldName = "" );
/** Returns the primary display field name used in the identify results dialog */
- const QString displayField() const;
+ QString displayField() const;
/** Set the preview expression, used to create a human readable preview string.
* Used e.g. in the attribute table feature list. Uses { @link QgsExpression }.
@@ -207,7 +207,7 @@ class QgsVectorLayer : QgsMapLayer
*
* @return The expression which will be used to preview features for this layer
*/
- const QString displayExpression();
+ QString displayExpression() const;
/** Returns the data provider */
QgsVectorDataProvider* dataProvider();
@@ -232,6 +232,11 @@ class QgsVectorLayer : QgsMapLayer
@returns true if join was found and successfully removed */
bool removeJoin( const QString& joinLayerId );
+ /**
+ * Acccessor to the join buffer object
+ * @note added 2.14.7
+ */
+ QgsVectorLayerJoinBuffer* joinBuffer();
const QList<QgsVectorJoinInfo> vectorJoins() const;
/**
@@ -1333,6 +1338,42 @@ class QgsVectorLayer : QgsMapLayer
/** Caches joined attributes if required (and not already done) */
void createJoinCaches();
+ /** Returns the calculated default value for the specified field index. The default
+ * value may be taken from a client side default value expression (see setDefaultValueExpression())
+ * or taken from the underlying data provider.
+ * @param index field index
+ * @param feature optional feature to use for default value evaluation. If passed,
+ * then properties from the feature (such as geometry) can be used when calculating
+ * the default value.
+ * @param context optional expression context to evaluate expressions again. If not
+ * specified, a default context will be created
+ * @return calculated default value
+ * @note added in QGIS 2.18
+ * @see setDefaultValueExpression()
+ */
+ QVariant defaultValue( int index, const QgsFeature& feature = QgsFeature(),
+ QgsExpressionContext* context = nullptr ) const;
+
+ /** Sets an expression to use when calculating the default value for a field.
+ * @param index field index
+ * @param expression expression to evaluate when calculating default values for field. Pass
+ * an empty expression to clear the default.
+ * @note added in QGIS 2.18
+ * @see defaultValue()
+ * @see defaultValueExpression()
+ */
+ void setDefaultValueExpression( int index, const QString& expression );
+
+ /** Returns the expression used when calculating the default value for a field.
+ * @param index field index
+ * @returns expression evaluated when calculating default values for field, or an
+ * empty string if no default is set
+ * @note added in QGIS 2.18
+ * @see defaultValue()
+ * @see setDefaultValueExpression()
+ */
+ QString defaultValueExpression( int index ) const;
+
/** Calculates a list of unique values contained within an attribute in the layer. Note that
* in some circumstances when unsaved changes are present for the layer then the returned list
* may contain outdated values (for instance when the attribute value in a saved feature has
diff --git a/python/core/raster/qgsbrightnesscontrastfilter.sip b/python/core/raster/qgsbrightnesscontrastfilter.sip
index 0d74853..da38150 100644
--- a/python/core/raster/qgsbrightnesscontrastfilter.sip
+++ b/python/core/raster/qgsbrightnesscontrastfilter.sip
@@ -15,7 +15,8 @@ class QgsBrightnessContrastFilter : QgsRasterInterface
bool setInput( QgsRasterInterface* input );
- QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height );
+ QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) /Factory/;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;
void setBrightness( int brightness );
int brightness() const;
diff --git a/python/core/raster/qgshillshaderenderer.sip b/python/core/raster/qgshillshaderenderer.sip
index 0ea9b7f..6a7fd85 100644
--- a/python/core/raster/qgshillshaderenderer.sip
+++ b/python/core/raster/qgshillshaderenderer.sip
@@ -32,6 +32,7 @@ class QgsHillshadeRenderer : QgsRasterRenderer
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterInterface* input ) /Factory/;
QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height ) /Factory/;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;
void writeXML( QDomDocument& doc, QDomElement& parentElem ) const;
diff --git a/python/core/raster/qgshuesaturationfilter.sip b/python/core/raster/qgshuesaturationfilter.sip
index a7ccb37..8f85c5f 100644
--- a/python/core/raster/qgshuesaturationfilter.sip
+++ b/python/core/raster/qgshuesaturationfilter.sip
@@ -25,7 +25,8 @@ class QgsHueSaturationFilter : QgsRasterInterface
bool setInput( QgsRasterInterface* input );
- QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height );
+ QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) /Factory/;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;
void setSaturation( int saturation );
int saturation() const;
diff --git a/python/core/raster/qgsmultibandcolorrenderer.sip b/python/core/raster/qgsmultibandcolorrenderer.sip
index dcaea1c..f2492ae 100644
--- a/python/core/raster/qgsmultibandcolorrenderer.sip
+++ b/python/core/raster/qgsmultibandcolorrenderer.sip
@@ -13,6 +13,7 @@ class QgsMultiBandColorRenderer: QgsRasterRenderer
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider ) /Factory/;
QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height ) /Factory/;
+ QgsRasterBlock* block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;
int redBand() const;
void setRedBand( int band );
diff --git a/python/core/raster/qgspalettedrasterrenderer.sip b/python/core/raster/qgspalettedrasterrenderer.sip
index 1b85e57..4672563 100644
--- a/python/core/raster/qgspalettedrasterrenderer.sip
+++ b/python/core/raster/qgspalettedrasterrenderer.sip
@@ -11,6 +11,7 @@ class QgsPalettedRasterRenderer : QgsRasterRenderer
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterInterface* input ) /Factory/;
QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height ) /Factory/;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;
/** Returns number of colors*/
int nColors() const;
diff --git a/python/core/raster/qgsrasterdataprovider.sip b/python/core/raster/qgsrasterdataprovider.sip
index b1c312d..de8741b 100644
--- a/python/core/raster/qgsrasterdataprovider.sip
+++ b/python/core/raster/qgsrasterdataprovider.sip
@@ -103,6 +103,7 @@ class QgsRasterDataProvider : QgsDataProvider, QgsRasterInterface
/** Read block of data using given extent and size. */
virtual QgsRasterBlock *block( int theBandNo, const QgsRectangle &theExtent, int theWidth, int theHeight ) / Factory /;
+ virtual QgsRasterBlock *block2( int theBandNo, const QgsRectangle &theExtent, int theWidth, int theHeight, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;
/** Return true if source band has no data value */
virtual bool srcHasNoDataValue( int bandNo ) const;
@@ -306,7 +307,7 @@ class QgsRasterDataProvider : QgsDataProvider, QgsRasterInterface
/** Read block of data using give extent and size
* @note not available in python bindings
*/
- //virtual void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data );
+ //virtual void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data, QgsRasterBlockFeedback* feedback = nullptr );
/** Returns true if user no data contains value */
bool userNoDataValuesContains( int bandNo, double value ) const;
diff --git a/python/core/raster/qgsrasterdrawer.sip b/python/core/raster/qgsrasterdrawer.sip
index 56ea224..b56158d 100644
--- a/python/core/raster/qgsrasterdrawer.sip
+++ b/python/core/raster/qgsrasterdrawer.sip
@@ -12,10 +12,11 @@ class QgsRasterDrawer
/** Draws raster data.
* @param p destination QPainter
* @param viewPort viewport to render
- * @param theQgsMapToPixel map to pixel convertor
+ * @param theQgsMapToPixel map to pixel converter
* @param ctx render context
+ * @param feedback optional raster feedback object for cancellation/preview. Added in QGIS 2.18.
*/
- void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel, const QgsRenderContext *ctx = nullptr );
+ void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel, const QgsRenderContext *ctx = nullptr, QgsRasterBlockFeedback* feedback = nullptr );
protected:
/** Draws raster part
diff --git a/python/core/raster/qgsrasterinterface.sip b/python/core/raster/qgsrasterinterface.sip
index 5809042..efec4b1 100644
--- a/python/core/raster/qgsrasterinterface.sip
+++ b/python/core/raster/qgsrasterinterface.sip
@@ -1,4 +1,41 @@
+/** \ingroup core
+ * Feedback object tailored for raster block reading.
+ *
+ * @note added in QGIS 2.18
+ */
+class QgsRasterBlockFeedback : QgsFeedback
+{
+%TypeHeaderCode
+#include <qgsrasterinterface.h>
+%End
+
+ public:
+ //! Construct a new raster block feedback object
+ QgsRasterBlockFeedback( QObject* parent = nullptr );
+
+ //! May be emitted by raster data provider to indicate that some partial data are available
+ //! and a new preview image may be produced
+ virtual void onNewData();
+
+ //! Whether the raster provider should return only data that are already available
+ //! without waiting for full result. By default this flag is not enabled.
+ //! @see setPreviewOnly()
+ bool isPreviewOnly() const;
+ //! set flag whether the block request is for preview purposes only
+ //! @see isPreviewOnly()
+ void setPreviewOnly( bool preview );
+
+ //! Whether our painter is drawing to a temporary image used just by this layer
+ //! @see setRenderPartialOutput()
+ bool renderPartialOutput() const;
+ //! Set whether our painter is drawing to a temporary image used just by this layer
+ //! @see renderPartialOutput()
+ void setRenderPartialOutput( bool enable );
+
+};
+
+
/** Base class for processing modules.
*
*/
@@ -132,6 +169,19 @@ class QgsRasterInterface
*/
virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) = 0 /Factory/;
+ /** Read block of data using given extent and size.
+ * Returns pointer to data.
+ * Caller is responsible to free the memory returned.
+ * @param bandNo band number
+ * @param extent extent of block
+ * @param width pixel width of block
+ * @param height pixel height of block
+ * @param feedback optional raster feedback object for cancellation/preview
+ * @note This is extended version of block() method. Default implementation falls back to calling block().
+ * @note Added in QGIS 2.18
+ */
+ virtual QgsRasterBlock *block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;
+
/** Set input.
* Returns true if set correctly, false if cannot use that input */
virtual bool setInput( QgsRasterInterface* input );
@@ -241,5 +291,6 @@ class QgsRasterInterface
int theStats = QgsRasterBandStats::All,
const QgsRectangle & theExtent = QgsRectangle(),
int theBinCount = 0 );
+
};
diff --git a/python/core/raster/qgsrasteriterator.sip b/python/core/raster/qgsrasteriterator.sip
index 6727ae7..8b195e3 100644
--- a/python/core/raster/qgsrasteriterator.sip
+++ b/python/core/raster/qgsrasteriterator.sip
@@ -12,8 +12,9 @@ class QgsRasterIterator
@param nCols number of columns
@param nRows number of rows
@param extent area to read
+ @param feedback optional raster feedback object for cancellation/preview. Added in QGIS 2.18
*/
- void startRasterRead( int bandNumber, int nCols, int nRows, const QgsRectangle& extent );
+ void startRasterRead( int bandNumber, int nCols, int nRows, const QgsRectangle& extent, QgsRasterBlockFeedback* feedback = nullptr );
/** Fetches next part of raster data, caller takes ownership of the block and
caller should delete the block.
diff --git a/python/core/raster/qgsrasternuller.sip b/python/core/raster/qgsrasternuller.sip
index d0e8ccd..b8156d3 100644
--- a/python/core/raster/qgsrasternuller.sip
+++ b/python/core/raster/qgsrasternuller.sip
@@ -20,6 +20,7 @@ class QgsRasterNuller : QgsRasterInterface
QGis::DataType dataType( int bandNo ) const;
QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) / Factory /;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;
void setNoData( int bandNo, const QgsRasterRangeList& noData );
diff --git a/python/core/raster/qgsrasterprojector.sip b/python/core/raster/qgsrasterprojector.sip
index ba7d54d..47bb697 100644
--- a/python/core/raster/qgsrasterprojector.sip
+++ b/python/core/raster/qgsrasterprojector.sip
@@ -1,6 +1,10 @@
-/** Raster projector */
-
+/** \ingroup core
+ * \brief QgsRasterProjector implements approximate projection support for
+ * it calculates grid of points in source CRS for target CRS + extent
+ * which are used to calculate affine transformation matrices.
+ * \class QgsRasterProjector
+ */
class QgsRasterProjector : QgsRasterInterface
{
%TypeHeaderCode
@@ -9,7 +13,7 @@ class QgsRasterProjector : QgsRasterInterface
%End
public:
- /** Precison defines if each pixel is reprojected or approximate reprojection based
+ /** Precision defines if each pixel is reprojected or approximate reprojection based
* on an approximation matrix of reprojected points is used.
*/
enum Precision
@@ -18,11 +22,7 @@ class QgsRasterProjector : QgsRasterInterface
Exact, //!< Exact, precise but slow
};
- /** \brief QgsRasterProjector implements approximate projection support for
- * it calculates grid of points in source CRS for target CRS + extent
- * which are used to calculate affine transformation matrices.
- */
-
+ //! @deprecated since 2.18: use default constructor
QgsRasterProjector( const QgsCoordinateReferenceSystem& theSrcCRS,
const QgsCoordinateReferenceSystem& theDestCRS,
int theSrcDatumTransform,
@@ -31,20 +31,21 @@ class QgsRasterProjector : QgsRasterInterface
int theDestRows, int theDestCols,
double theMaxSrcXRes, double theMaxSrcYRes,
const QgsRectangle& theExtent
- );
-
+ ) /Deprecated/;
+ //! @deprecated since 2.18: use default constructor
QgsRasterProjector( const QgsCoordinateReferenceSystem& theSrcCRS,
const QgsCoordinateReferenceSystem& theDestCRS,
const QgsRectangle& theDestExtent,
int theDestRows, int theDestCols,
double theMaxSrcXRes, double theMaxSrcYRes,
const QgsRectangle& theExtent
- );
+ ) /Deprecated/;
+ //! @deprecated since 2.18: use default constructor
QgsRasterProjector( const QgsCoordinateReferenceSystem& theSrcCRS,
const QgsCoordinateReferenceSystem& theDestCRS,
double theMaxSrcXRes, double theMaxSrcYRes,
const QgsRectangle& theExtent
- );
+ ) /Deprecated/;
QgsRasterProjector();
/** \brief The destructor */
@@ -66,8 +67,8 @@ class QgsRasterProjector : QgsRasterInterface
/** \brief Get destination CRS */
QgsCoordinateReferenceSystem destCrs() const;
- /** \brief set maximum source resolution */
- void setMaxSrcRes( double theMaxSrcXRes, double theMaxSrcYRes );
+ /** @deprecated since 2.18, does nothing */
+ void setMaxSrcRes( double theMaxSrcXRes, double theMaxSrcYRes ) /Deprecated/;
Precision precision() const;
void setPrecision( Precision precision );
@@ -75,6 +76,7 @@ class QgsRasterProjector : QgsRasterInterface
static QString precisionLabel( Precision precision );
QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height ) / Factory /;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;
/** Calculate destination extent and size from source extent and size */
bool destExtentSize( const QgsRectangle& theSrcExtent, int theSrcXSize, int theSrcYSize,
diff --git a/python/core/raster/qgsrasterrenderer.sip b/python/core/raster/qgsrasterrenderer.sip
index 3da8fed..eebcb90 100644
--- a/python/core/raster/qgsrasterrenderer.sip
+++ b/python/core/raster/qgsrasterrenderer.sip
@@ -38,8 +38,6 @@ class QgsRasterRenderer : QgsRasterInterface
virtual bool setInput( QgsRasterInterface* input );
- virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) = 0 / Factory /;
-
bool usesTransparency() const;
void setOpacity( double opacity );
diff --git a/python/core/raster/qgsrasterresamplefilter.sip b/python/core/raster/qgsrasterresamplefilter.sip
index 715d130..f4770fa 100644
--- a/python/core/raster/qgsrasterresamplefilter.sip
+++ b/python/core/raster/qgsrasterresamplefilter.sip
@@ -20,6 +20,7 @@ class QgsRasterResampleFilter : QgsRasterInterface
bool setInput( QgsRasterInterface* input );
QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) /Factory/;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;
/** Set resampler for zoomed in scales. Takes ownership of the object*/
void setZoomedInResampler( QgsRasterResampler* r /Transfer/ );
diff --git a/python/core/raster/qgssinglebandcolordatarenderer.sip b/python/core/raster/qgssinglebandcolordatarenderer.sip
index d55316a..0cd2b2a 100644
--- a/python/core/raster/qgssinglebandcolordatarenderer.sip
+++ b/python/core/raster/qgssinglebandcolordatarenderer.sip
@@ -13,6 +13,7 @@ class QgsSingleBandColorDataRenderer: QgsRasterRenderer
bool setInput( QgsRasterInterface* input );
QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height ) / Factory /;
+ QgsRasterBlock* block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;
void writeXML( QDomDocument& doc, QDomElement& parentElem ) const;
diff --git a/python/core/raster/qgssinglebandgrayrenderer.sip b/python/core/raster/qgssinglebandgrayrenderer.sip
index f92594b..e2a0d26 100644
--- a/python/core/raster/qgssinglebandgrayrenderer.sip
+++ b/python/core/raster/qgssinglebandgrayrenderer.sip
@@ -17,6 +17,7 @@ class QgsSingleBandGrayRenderer: QgsRasterRenderer
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider ) /Factory/;
QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height ) / Factory /;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;
int grayBand() const;
void setGrayBand( int band );
diff --git a/python/core/raster/qgssinglebandpseudocolorrenderer.sip b/python/core/raster/qgssinglebandpseudocolorrenderer.sip
index a1df1e6..d9e009e 100644
--- a/python/core/raster/qgssinglebandpseudocolorrenderer.sip
+++ b/python/core/raster/qgssinglebandpseudocolorrenderer.sip
@@ -12,6 +12,7 @@ class QgsSingleBandPseudoColorRenderer: QgsRasterRenderer
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider ) /Factory/;
QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height ) / Factory /;
+ QgsRasterBlock* block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;
/** Takes ownership of the shader*/
void setShader( QgsRasterShader* shader /Transfer/ );
diff --git a/python/ext-libs/owslib/swe/common.py b/python/ext-libs/owslib/swe/common.py
index ea11064..6904ed8 100644
--- a/python/ext-libs/owslib/swe/common.py
+++ b/python/ext-libs/owslib/swe/common.py
@@ -85,7 +85,7 @@ class AbstractSWE(object):
self.id = testXMLAttribute(element,"id") # string, optional
# Elements
- self.extention = [] # anyType, min=0, max=X
+ self.extension = [] # anyType, min=0, max=X
class AbstractSWEIdentifiable(AbstractSWE):
def __init__(self, element):
diff --git a/python/ext-libs/owslib/wmts.py b/python/ext-libs/owslib/wmts.py
index 2235137..57a61e2 100644
--- a/python/ext-libs/owslib/wmts.py
+++ b/python/ext-libs/owslib/wmts.py
@@ -747,7 +747,7 @@ class ContentMetadata:
@property
def tilematrixsets(self):
- # NB. This attribute has been superseeded by the
+ # NB. This attribute has been superceeded by the
# `tilematrixsetlinks` attribute defined below, but is included
# for now to provide continuity.
warnings.warn("The 'tilematrixsets' attribute has been deprecated"
diff --git a/python/ext-libs/owslib/wps.py b/python/ext-libs/owslib/wps.py
index 3b94234..b9138ec 100644
--- a/python/ext-libs/owslib/wps.py
+++ b/python/ext-libs/owslib/wps.py
@@ -1560,8 +1560,8 @@ class GMLMultiPolygonFeatureCollection(FeatureCollection):
def monitorExecution(execution, sleepSecs=3, download=False, filepath=None):
'''
- Convenience method to monitor the status of a WPS execution till it completes (succesfully or not),
- and write the output to file after a succesfull job completion.
+ Convenience method to monitor the status of a WPS execution till it completes (successfully or not),
+ and write the output to file after a successful job completion.
execution: WPSExecution instance
sleepSecs: number of seconds to sleep in between check status invocations
diff --git a/python/gui/editorwidgets/core/qgseditorconfigwidget.sip b/python/gui/editorwidgets/core/qgseditorconfigwidget.sip
index b580501..d4a4a1b 100644
--- a/python/gui/editorwidgets/core/qgseditorconfigwidget.sip
+++ b/python/gui/editorwidgets/core/qgseditorconfigwidget.sip
@@ -38,5 +38,12 @@ class QgsEditorConfigWidget : QWidget
virtual QgsEditorWidgetConfig config() = 0;
virtual void setConfig( const QgsEditorWidgetConfig& config ) = 0;
+
+ signals:
+
+ /** Emitted when the configuration of the widget is changed.
+ * @note added in QGIS 2.18
+ */
+ void changed();
};
diff --git a/python/gui/editorwidgets/qgsdoublespinbox.sip b/python/gui/editorwidgets/qgsdoublespinbox.sip
index 6fac256..1666a02 100644
--- a/python/gui/editorwidgets/qgsdoublespinbox.sip
+++ b/python/gui/editorwidgets/qgsdoublespinbox.sip
@@ -1,3 +1,9 @@
+/** \ingroup gui
+ * @brief The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
+ * The clear value can be either the minimum or the maiximum value of the spin box or a custom value.
+ * This value can then be handled by a special value text.
+ */
+
class QgsDoubleSpinBox : QDoubleSpinBox
{
%TypeHeaderCode
@@ -5,18 +11,30 @@ class QgsDoubleSpinBox : QDoubleSpinBox
%End
public:
+
+ //! Behaviour when widget is cleared.
enum ClearValueMode
{
- MinimumValue,
- MaximumValue,
- CustomValue
+ MinimumValue, //!< Reset value to minimum()
+ MaximumValue, //!< Reset value to maximum()
+ CustomValue, //!< Reset value to custom value (see setClearValue() )
};
+ /** Constructor for QgsDoubleSpinBox.
+ * @param parent parent widget
+ */
explicit QgsDoubleSpinBox( QWidget *parent /TransferThis/ = 0 );
- //! determines if the widget will show a clear button
- //! @note the clear button will set the widget to its minimum value
+ /** Sets whether the widget will show a clear button. The clear button
+ * allows users to reset the widget to a default or empty state.
+ * @param showClearButton set to true to show the clear button, or false to hide it
+ * @see showClearButton()
+ */
void setShowClearButton( const bool showClearButton );
+
+ /** Returns whether the widget is showing a clear button.
+ * @see setShowClearButton()
+ */
bool showClearButton() const;
/** Sets if the widget will allow entry of simple expressions, which are
@@ -25,6 +43,7 @@ class QgsDoubleSpinBox : QDoubleSpinBox
* @note added in QGIS 2.7
*/
void setExpressionsEnabled( const bool enabled );
+
/** Returns whether the widget will allow entry of simple expressions, which are
* evaluated and then discarded.
* @returns true if spin box allows expression entry
@@ -36,26 +55,29 @@ class QgsDoubleSpinBox : QDoubleSpinBox
virtual void clear();
/**
- * @brief setClearValue defines the clear value as a custom value and will automatically set the clear value mode to CustomValue
+ * Defines the clear value as a custom value and will automatically set the clear value mode to CustomValue.
* @param customValue defines the numerical value used as the clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
+ * @see setClearValue()
*/
void setClearValue( double customValue, const QString& clearValueText = QString() );
+
/**
- * @brief setClearValueMode defines if the clear value should be the minimum or maximum values of the widget or a custom value
+ * Defines if the clear value should be the minimum or maximum values of the widget or a custom value.
* @param mode mode to user for clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
*/
void setClearValueMode( ClearValueMode mode, const QString& clearValueText = QString() );
- //! returns the value used when clear() is called.
+ /** Returns the value used when clear() is called.
+ * @see setClearValue()
+ */
double clearValue() const;
virtual double valueFromText( const QString & text ) const;
virtual QValidator::State validate( QString & input, int & pos ) const;
protected:
- virtual void resizeEvent( QResizeEvent* event );
virtual void changeEvent( QEvent* event );
virtual void paintEvent( QPaintEvent* event );
};
diff --git a/python/gui/editorwidgets/qgsrelationwidgetwrapper.sip b/python/gui/editorwidgets/qgsrelationwidgetwrapper.sip
index 9b67a4d..f2f29b7 100644
--- a/python/gui/editorwidgets/qgsrelationwidgetwrapper.sip
+++ b/python/gui/editorwidgets/qgsrelationwidgetwrapper.sip
@@ -23,6 +23,48 @@ class QgsRelationWidgetWrapper : QgsWidgetWrapper
public:
explicit QgsRelationWidgetWrapper( QgsVectorLayer* vl, const QgsRelation& relation, QWidget* editor = 0, QWidget* parent /TransferThis/ = 0 );
+ /**
+ * Defines if a title lable should be shown for this widget.
+ * Only has an effect after widget() has been called at least once.
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLabel() const;
+
+ /**
+ * Defines if a title lable should be shown for this widget.
+ * Only has an effect after widget() has been called at least once.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLabel( bool showLabel );
+
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLinkButton() const;
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLinkButton( bool showLinkButton );
+
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showUnlinkButton() const;
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowUnlinkButton( bool showUnlinkButton );
+
protected:
QWidget* createWidget( QWidget* parent );
void initWidget( QWidget* editor );
@@ -30,4 +72,10 @@ class QgsRelationWidgetWrapper : QgsWidgetWrapper
public slots:
void setFeature( const QgsFeature& feature );
+
+ /** Sets the visibility of the wrapper's widget.
+ * @param visible set to true to show widget, false to hide widget
+ * @note added in QGIS 2.16
+ */
+ void setVisible( bool visible );
};
diff --git a/python/gui/editorwidgets/qgsspinbox.sip b/python/gui/editorwidgets/qgsspinbox.sip
index 09e8b65..d560641 100644
--- a/python/gui/editorwidgets/qgsspinbox.sip
+++ b/python/gui/editorwidgets/qgsspinbox.sip
@@ -1,3 +1,9 @@
+/** \ingroup gui
+ * @brief The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
+ * The clear value can be either the minimum or the maiximum value of the spin box or a custom value.
+ * This value can then be handled by a special value text.
+ */
+
class QgsSpinBox : QSpinBox
{
%TypeHeaderCode
@@ -5,18 +11,30 @@ class QgsSpinBox : QSpinBox
%End
public:
+
+ //! Behaviour when widget is cleared.
enum ClearValueMode
{
- MinimumValue,
- MaximumValue,
- CustomValue
+ MinimumValue, //!< Reset value to minimum()
+ MaximumValue, //!< Reset value to maximum()
+ CustomValue, //!< Reset value to custom value (see setClearValue() )
};
+ /** Constructor for QgsSpinBox.
+ * @param parent parent widget
+ */
explicit QgsSpinBox( QWidget *parent /TransferThis/ = 0 );
- //! determines if the widget will show a clear button
- //! @note the clear button will set the widget to its minimum value
+ /** Sets whether the widget will show a clear button. The clear button
+ * allows users to reset the widget to a default or empty state.
+ * @param showClearButton set to true to show the clear button, or false to hide it
+ * @see showClearButton()
+ */
void setShowClearButton( const bool showClearButton );
+
+ /** Returns whether the widget is showing a clear button.
+ * @see setShowClearButton()
+ */
bool showClearButton() const;
/** Sets if the widget will allow entry of simple expressions, which are
@@ -25,6 +43,7 @@ class QgsSpinBox : QSpinBox
* @note added in QGIS 2.7
*/
void setExpressionsEnabled( const bool enabled );
+
/** Returns whether the widget will allow entry of simple expressions, which are
* evaluated and then discarded.
* @returns true if spin box allows expression entry
@@ -36,26 +55,30 @@ class QgsSpinBox : QSpinBox
virtual void clear();
/**
- * @brief setClearValue defines the clear value for the widget and will automatically set the clear value mode to CustomValue
+ * Defines the clear value as a custom value and will automatically set the clear value mode to CustomValue.
* @param customValue defines the numerical value used as the clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
+ * @see setClearValue()
*/
void setClearValue( int customValue, const QString& clearValueText = QString() );
+
/**
- * @brief setClearValueMode defines if the clear value should be the minimum or maximum values of the widget or a custom value
+ * Defines if the clear value should be the minimum or maximum values of the widget or a custom value.
* @param mode mode to user for clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
*/
void setClearValueMode( ClearValueMode mode, const QString& clearValueText = QString() );
- //! returns the value used when clear() is called.
+ /** Returns the value used when clear() is called.
+ * @see setClearValue()
+ */
int clearValue() const;
virtual int valueFromText( const QString & text ) const;
virtual QValidator::State validate( QString & input, int & pos ) const;
protected:
- virtual void resizeEvent( QResizeEvent* event );
+
virtual void changeEvent( QEvent* event );
virtual void paintEvent( QPaintEvent* event );
};
diff --git a/python/gui/gui.sip b/python/gui/gui.sip
index a9eac81..eba2b43 100644
--- a/python/gui/gui.sip
+++ b/python/gui/gui.sip
@@ -69,6 +69,7 @@
%Include qgsexpressionbuilderdialog.sip
%Include qgsexpressionbuilderwidget.sip
%Include qgsexpressionhighlighter.sip
+%Include qgsexpressionlineedit.sip
%Include qgsexpressionselectiondialog.sip
%Include qgsextentgroupbox.sip
%Include qgsexternalresourcewidget.sip
@@ -159,6 +160,7 @@
%Include qgssourceselectdialog.sip
%Include qgssublayersdialog.sip
%Include qgssvgannotationitem.sip
+%Include qgstabwidget.sip
%Include qgstablewidgetitem.sip
%Include qgstextannotationitem.sip
%Include qgstrackedvectorlayertools.sip
diff --git a/python/gui/layertree/qgslayertreeview.sip b/python/gui/layertree/qgslayertreeview.sip
index af1f539..636a276 100644
--- a/python/gui/layertree/qgslayertreeview.sip
+++ b/python/gui/layertree/qgslayertreeview.sip
@@ -72,6 +72,14 @@ class QgsLayerTreeView : QTreeView
//! Force refresh of layer symbology. Normally not needed as the changes of layer's renderer are monitored by the model
void refreshLayerSymbology( const QString& layerId );
+ //! Enhancement of QTreeView::expandAll() that also records expanded state in layer tree nodes
+ //! @note added in QGIS 2.18
+ void expandAllNodes();
+
+ //! Enhancement of QTreeView::collapseAll() that also records expanded state in layer tree nodes
+ //! @note added in QGIS 2.18
+ void collapseAllNodes();
+
signals:
//! Emitted when a current layer is changed
void currentLayerChanged( QgsMapLayer* layer );
diff --git a/python/gui/qgscolorschemelist.sip b/python/gui/qgscolorschemelist.sip
index 4161a2d..81b4726 100644
--- a/python/gui/qgscolorschemelist.sip
+++ b/python/gui/qgscolorschemelist.sip
@@ -142,12 +142,19 @@ class QgsColorSchemeList: QTreeView
*/
bool isDirty() const;
+ /** Returns the scheme currently selected in the list.
+ * @note added in QGIS 2.18
+ * @see setScheme()
+ */
+ QgsColorScheme* scheme();
+
public slots:
/** Sets the color scheme to show in the list
* @param scheme QgsColorScheme for colors to show in the list
* @param context context string provided to color scheme
* @param baseColor base color for color scheme
+ * @see scheme()
*/
void setScheme( QgsColorScheme* scheme, const QString &context = QString(), const QColor &baseColor = QColor() );
diff --git a/python/gui/qgscolorwidgets.sip b/python/gui/qgscolorwidgets.sip
index 31a37b5..bc375c0 100644
--- a/python/gui/qgscolorwidgets.sip
+++ b/python/gui/qgscolorwidgets.sip
@@ -373,6 +373,7 @@ class QgsColorRampWidget : QgsColorWidget
protected:
virtual void mouseMoveEvent( QMouseEvent *event );
+ virtual void wheelEvent( QWheelEvent* event );
virtual void mousePressEvent( QMouseEvent *event );
virtual void keyPressEvent( QKeyEvent * event );
};
diff --git a/python/gui/qgscompoundcolorwidget.sip b/python/gui/qgscompoundcolorwidget.sip
index 3fdfb33..19d2b43 100644
--- a/python/gui/qgscompoundcolorwidget.sip
+++ b/python/gui/qgscompoundcolorwidget.sip
@@ -6,7 +6,7 @@
* \note Added in version 2.16
*/
-class QgsCompoundColorWidget : QWidget
+class QgsCompoundColorWidget : QgsPanelWidget
{
%TypeHeaderCode
#include <qgscompoundcolorwidget.h>
@@ -14,11 +14,19 @@ class QgsCompoundColorWidget : QWidget
public:
+ //! Widget layout
+ enum Layout
+ {
+ LayoutDefault, /*!< Use the default (rectangular) layout */
+ LayoutVertical, /*!< Use a narrower, vertically stacked layout */
+ };
+
/** Constructor for QgsCompoundColorWidget
* @param parent parent widget
* @param color initial color for dialog
+ * @param layout widget layout to use
*/
- QgsCompoundColorWidget( QWidget *parent /TransferThis/ = nullptr, const QColor& color = QColor() );
+ QgsCompoundColorWidget( QWidget *parent /TransferThis/ = nullptr, const QColor& color = QColor(), Layout layout = LayoutDefault );
~QgsCompoundColorWidget();
diff --git a/python/gui/qgsexpressionlineedit.sip b/python/gui/qgsexpressionlineedit.sip
new file mode 100644
index 0000000..7b1a697
--- /dev/null
+++ b/python/gui/qgsexpressionlineedit.sip
@@ -0,0 +1,82 @@
+/** \ingroup gui
+ * @class QgsExpressionLineEdit
+ * @brief The QgsExpressionLineEdit widget includes a line edit for entering expressions
+ * together with a button to open the expression creation dialog.
+ *
+ * This widget is designed for use in contexts where no layer fields are available for
+ * use in an expression. In contexts where the expression is directly associated with
+ * a layer and fields can be used, then QgsFieldExpressionWidget is a more appropriate
+ * choice as it gives users direct access to select fields from a drop down list.
+ * @note added in QGIS 2.18
+ */
+
+class QgsExpressionLineEdit : QWidget
+{
+%TypeHeaderCode
+#include "qgsexpressionlineedit.h"
+%End
+
+ public:
+
+ /**
+ * Constructor for QgsExpressionLineEdit.
+ * @param parent parent widget
+ */
+ explicit QgsExpressionLineEdit( QWidget *parent /TransferThis/ = nullptr );
+ /** Sets the title used in the expression builder dialog
+ * @param title dialog title
+ * @see expressionDialogTitle()
+ */
+ void setExpressionDialogTitle( const QString& title );
+
+ /** Returns the title used for the expression dialog.
+ * @see setExpressionDialogTitle()
+ */
+ QString expressionDialogTitle() const;
+
+ /** Sets whether the widget should show a multiline text editor.
+ * @param multiLine set to true to show multiline editor, or false
+ * to show single line editor (the default).
+ */
+ void setMultiLine( bool multiLine );
+
+ /** Set the geometry calculator used in the expression dialog.
+ * @param distanceArea calculator
+ */
+ void setGeomCalculator( const QgsDistanceArea &distanceArea );
+
+ /** Sets a layer associated with the widget. Required in order to get the fields and values
+ * from the layer.
+ * @param layer vector layer
+ */
+ void setLayer( QgsVectorLayer* layer );
+
+ /** Returns the current expression shown in the widget.
+ * @see setExpression()
+ */
+ QString expression() const;
+
+ /**
+ * Returns true if the current expression is valid.
+ * @param expressionError will be set to any generated error message if specified
+ */
+ bool isValidExpression( QString *expressionError /Out/ = nullptr ) const;
+
+ signals:
+
+ /** Emitted when the expression is changed.
+ * @param expression new expression
+ */
+ void expressionChanged( const QString& expression );
+
+ public slots:
+
+ /** Sets the current expression to show in the widget.
+ * @param expression expression string
+ * @see expression()
+ */
+ void setExpression( const QString& expression );
+
+ protected:
+ void changeEvent( QEvent* event );
+};
diff --git a/python/gui/qgsfieldexpressionwidget.sip b/python/gui/qgsfieldexpressionwidget.sip
index 24bfb1e..0cac132 100644
--- a/python/gui/qgsfieldexpressionwidget.sip
+++ b/python/gui/qgsfieldexpressionwidget.sip
@@ -53,6 +53,17 @@ class QgsFieldExpressionWidget : QWidget
*/
QString asExpression() const;
+ /**
+ * Returns the currently selected field or expression. If a field is currently selected, the returned
+ * value will be converted to a valid expression referencing this field (ie enclosing the field name with
+ * appropriate quotations).
+ *
+ * Alias for asExpression()
+ *
+ * @note added in QGIS 2.18
+ */
+ QString expression() const;
+
//! Returns the currently used layer
QgsVectorLayer* layer() const;
@@ -90,6 +101,14 @@ class QgsFieldExpressionWidget : QWidget
//! sets the current field or expression in the widget
void setField( const QString &fieldName );
+ /**
+ * Sets the current expression text and if applicable also the field.
+ * Alias for setField.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setExpression( const QString& expression );
+
protected slots:
//! open the expression dialog to edit the current or add a new expression
void editExpression();
diff --git a/python/gui/qgsfilterlineedit.sip b/python/gui/qgsfilterlineedit.sip
index c387c64..2fdbc2a 100644
--- a/python/gui/qgsfilterlineedit.sip
+++ b/python/gui/qgsfilterlineedit.sip
@@ -1,53 +1,145 @@
-
-/** LineEdit with builtin clear button
- */
+/** \class QgsFilterLineEdit
+ * \ingroup gui
+ * QLineEdit subclass with built in support for clearing the widget's value and
+ * handling custom null value representations.
+ *
+ * When using QgsFilterLineEdit the value(), setValue() and clearValue() methods should be used
+ * instead of QLineEdit's text(), setText() and clear() methods, and the valueChanged()
+ * signal should be used instead of textChanged().
+ **/
class QgsFilterLineEdit : QLineEdit
{
%TypeHeaderCode
#include <qgsfilterlineedit.h>
%End
public:
+
+ //! Behaviour when clearing value of widget
+ enum ClearMode
+ {
+ ClearToNull, //!< Reset value to null
+ ClearToDefault, //!< Reset value to default value (see defaultValue() )
+ };
+
+ /** Constructor for QgsFilterLineEdit.
+ * @param parent parent widget
+ * @param nullValue string for representing null values
+ */
QgsFilterLineEdit( QWidget* parent /TransferThis/ = 0, const QString& nullValue = QString::null );
+ /** Returns true if the widget's clear button is visible.
+ * @see setShowClearButton()
+ * @note added in QGIS 2.18
+ */
+ bool showClearButton() const;
+
+ /** Sets whether the widget's clear button is visible.
+ * @param visible set to false to hide the clear button
+ * @see showClearButton()
+ * @note added in QGIS 2.18
+ */
+ void setShowClearButton( bool visible );
+
+ /** Returns the clear mode for the widget. The clear mode defines the behaviour of the
+ * widget when its value is cleared. This defaults to ClearToNull.
+ * @see setClearMode()
+ * @note added in QGIS 2.18
+ */
+ ClearMode clearMode() const;
+
+ /** Sets the clear mode for the widget. The clear mode defines the behaviour of the
+ * widget when its value is cleared. This defaults to ClearToNull.
+ * @see clearMode()
+ * @note added in QGIS 2.18
+ */
+ void setClearMode( ClearMode mode );
+
+ /** Sets the string representation for null values in the widget. This does not
+ * affect the values returned for null values by value(), rather it only affects
+ * the text that is shown to users when the widget's value is null.
+ * @param nullValue string to show when widget's value is null
+ * @see nullValue()
+ */
void setNullValue( const QString& nullValue );
+ /** Returns the string used for representating null values in the widget.
+ * @see setNullValue()
+ * @see isNull()
+ */
QString nullValue() const;
+ /** Sets the default value for the widget. The default value is a value
+ * which the widget will be reset to if it is cleared and the clearMode()
+ * is equal to ClearToDefault.
+ * @param defaultValue default value
+ * @see defaultValue()
+ * @see clearMode()
+ * @note added in QGIS 2.18
+ */
+ void setDefaultValue( const QString& defaultValue );
+
+ /** Returns the default value for the widget. The default value is a value
+ * which the widget will be reset to if it is cleared and the clearMode()
+ * is equal to ClearToDefault.
+ * @see setDefaultValue()
+ * @see clearMode()
+ * @note added in QGIS 2.18
+ */
+ QString defaultValue() const;
+
/**
- * Sets the current text with NULL support
+ * Sets the current text for the widget with support for handling null values.
*
- * @param value The text to set. If a Null string is provided, the text will match the nullValue.
+ * @param value The text to set. If a null string is provided, the text shown in the
+ * widget will be set to the current nullValue().
+ * @see value()
*/
void setValue( const QString& value );
/**
- * Returns the text of this edit with NULL support
+ * Returns the text of this edit with support for handling null values. If the text
+ * in the widget matches the current nullValue() then the returned value will be
+ * a null string.
*
- * @return Current text (Null string if it matches the nullValue property )
+ * @return Current text (or null string if it matches the nullValue() property )
+ * @see setValue()
*/
QString value() const;
/**
- * Determine if the current text represents Null.
+ * Determine if the current text represents null.
*
- * @return True if the value is Null.
+ * @return True if the widget's value is null.
+ * @see nullValue()
*/
bool isNull() const;
+ public slots:
+
+ /** Clears the widget and resets it to the null value.
+ * @see nullValue()
+ * @note added in QGIS 2.18
+ */
+ virtual void clearValue();
+
signals:
+
+ /** Emitted when the widget is cleared
+ * @see clearValue()
+ */
void cleared();
/**
- * Same as textChanged(const QString& ) but with support for Null values.
+ * Same as textChanged() but with support for null values.
*
- * @param value The current text or Null string if it matches the nullValue property.
+ * @param value The current text or null string if it matches the nullValue() property.
*/
void valueChanged( const QString& value );
protected:
void mousePressEvent( QMouseEvent* e );
+ void mouseMoveEvent( QMouseEvent* e );
void focusInEvent( QFocusEvent* e );
- void resizeEvent( QResizeEvent* e );
- void changeEvent( QEvent* e );
void paintEvent( QPaintEvent* e );
+ void leaveEvent( QEvent* e );
};
diff --git a/python/gui/qgspanelwidget.sip b/python/gui/qgspanelwidget.sip
index 254b773..9f38fe2 100644
--- a/python/gui/qgspanelwidget.sip
+++ b/python/gui/qgspanelwidget.sip
@@ -60,7 +60,7 @@ class QgsPanelWidget : public QWidget
/**
* The the auto delete property on the widget. True by default.
- * When auto delete is enabeld when a panel is removed from the stack
+ * When auto delete is enabled when a panel is removed from the stack
* it will be deleted.
* @param autoDelete Enable or disable auto delete on the panel.
*/
@@ -68,12 +68,20 @@ class QgsPanelWidget : public QWidget
/**
* The the auto delete property on the widget. True by default.
- * When auto delete is enabeld when a panel is removed from the stack
+ * When auto delete is enabled when a panel is removed from the stack
* it will be deleted.
* @returns The auto delete value for the widget.
*/
bool autoDelete();
+ /** Traces through the parents of a widget to find if it is contained within a QgsPanelWidget
+ * widget.
+ * @param widget widget which may be contained within a panel widget
+ * @returns parent panel widget if found, otherwise nullptr
+ * @note added in QGIS 2.18
+ */
+ static QgsPanelWidget* findParentPanel( QWidget* widget );
+
signals:
/**
@@ -81,6 +89,9 @@ class QgsPanelWidget : public QWidget
* @param panel The panel widget that was accepted.
* @note This argument is normally raised with emit panelAccepted(this)
* so that callers can retrive the widget easier in calling code.
+ * @note this is emitted only when this panel is accepted, and is not emitted for
+ * child panels. Eg, if this panel opens a second stacked panel, then this panel
+ * will not emit panelAccepted when the second panel is accepted.
*/
void panelAccepted( QgsPanelWidget* panel );
diff --git a/python/gui/qgsrelationeditorwidget.sip b/python/gui/qgsrelationeditorwidget.sip
index 19a5eaa..1e70f13 100644
--- a/python/gui/qgsrelationeditorwidget.sip
+++ b/python/gui/qgsrelationeditorwidget.sip
@@ -65,4 +65,44 @@ class QgsRelationEditorWidget : QgsCollapsibleGroupBox
* which are currently being edited.
*/
QgsIFeatureSelectionManager* featureSelectionManager();
+
+ /**
+ * Defines if a title label should be shown for this widget.
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLabel() const;
+
+ /**
+ * Defines if a title label should be shown for this widget.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLabel( bool showLabel );
+
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLinkButton() const;
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLinkButton( bool showLinkButton );
+
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showUnlinkButton() const;
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowUnlinkButton( bool showUnlinkButton );
};
diff --git a/python/gui/qgstabwidget.sip b/python/gui/qgstabwidget.sip
new file mode 100644
index 0000000..dde2841
--- /dev/null
+++ b/python/gui/qgstabwidget.sip
@@ -0,0 +1,84 @@
+/***************************************************************************
+ qgstabwidget.sip - QgsTabWidget
+
+ ---------------------
+ begin : 8.9.2016
+ copyright : (C) 2016 by Matthias Kuhn
+ email : matthias at opengis.ch
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/** \ingroup gui
+ * The QgsTabWidget class is the same as the QTabWidget but with additional methods to
+ * temporarily hide/show tabs.
+ *
+ * @note Added in QGIS 2.18
+ */
+class QgsTabWidget : QTabWidget
+{
+%TypeHeaderCode
+#include <qgstabwidget.h>
+%End
+
+ public:
+ /**
+ * Create a new QgsTabWidget with the optionally provided parent.
+ *
+ * @note Added in QGIS 2.18
+ */
+ QgsTabWidget( QWidget *parent = nullptr );
+
+ /**
+ * Hides the tab with the given widget
+ *
+ * @note Added in QGIS 2.18
+ */
+ void hideTab( QWidget* tab );
+
+ /**
+ * Shows the tab with the given widget
+ *
+ * @note Added in QGIS 2.18
+ */
+ void showTab( QWidget* tab );
+
+ /**
+ * Control the visibility for the tab with the given widget.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setTabVisible( QWidget* tab, bool visible );
+
+ /**
+ * Returns the index of the tab with the given widget.
+ * This index is not the same as the one provided to insertTab and removeTab
+ * since these methods are not aware of hidden tabs.
+ *
+ * @note Added in QGIS 2.18
+ */
+ int realTabIndex( QWidget* widget );
+
+ /**
+ * Is called internally whenever a new tab has been inserted.
+ *
+ * Is used to keep track of currently available and visible tabs.
+ *
+ * @note Added in QGIS 2.18
+ */
+ virtual void tabInserted( int index );
+
+ /**
+ * Is called internally whenever a tab has been removed.
+ *
+ * Is used to keep track of currently available and visible tabs.
+ *
+ * @note Added in QGIS 2.18
+ */
+ virtual void tabRemoved( int index );
+};
diff --git a/python/plugins/GdalTools/tools/doBuildVRT.py b/python/plugins/GdalTools/tools/doBuildVRT.py
index d99bfec..a10db1a 100644
--- a/python/plugins/GdalTools/tools/doBuildVRT.py
+++ b/python/plugins/GdalTools/tools/doBuildVRT.py
@@ -78,6 +78,7 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget):
def onClosing(self):
# disconnect from mapCanvas.layerChanged() signal
self.iface.mapCanvas().layersChanged.disconnect(self.onVisibleLayersChanged)
+ self.iface.mapCanvas().layersChanged.disconnect(self.switchLayerMode)
BasePluginWidget.onClosing(self)
def onVisibleLayersChanged(self):
diff --git a/python/plugins/GdalTools/tools/doExtractProj.py b/python/plugins/GdalTools/tools/doExtractProj.py
index e474764..4e1acd7 100644
--- a/python/plugins/GdalTools/tools/doExtractProj.py
+++ b/python/plugins/GdalTools/tools/doExtractProj.py
@@ -23,7 +23,7 @@ __copyright__ = '(C) 2011, Alexander Bruy'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
-from qgis.PyQt.QtCore import Qt, QCoreApplication, QThread, QMutex
+from qgis.PyQt.QtCore import Qt, QCoreApplication, QThread, QMutex, pyqtSignal
from qgis.PyQt.QtWidgets import QDialog, QDialogButtonBox, QApplication, QMessageBox
from qgis.PyQt.QtGui import QCursor
@@ -184,6 +184,10 @@ def extractProjection(filename, createPrj):
class ExtractThread(QThread):
+ fileProcessed = pyqtSignal()
+ processFinished = pyqtSignal()
+ processInterrupted = pyqtSignal()
+
def __init__(self, files, needPrj):
QThread.__init__(self, QThread.currentThread())
self.inFiles = files
@@ -213,7 +217,7 @@ class ExtractThread(QThread):
if not interrupted:
self.processFinished.emit()
else:
- self.processIterrupted.emit()
+ self.processInterrupted.emit()
def stop(self):
self.mutex.lock()
diff --git a/python/plugins/db_manager/db_manager.py b/python/plugins/db_manager/db_manager.py
index cdc2433..5d814f6 100644
--- a/python/plugins/db_manager/db_manager.py
+++ b/python/plugins/db_manager/db_manager.py
@@ -199,6 +199,15 @@ class DBManager(QMainWindow):
self.tabs.setCurrentIndex(index)
query.nameChanged.connect(functools.partial(self.update_query_tab_name, index, dbname))
+ def runSqlLayerWindow(self, layer):
+ from dlg_sql_layer_window import DlgSqlLayerWindow
+ query = DlgSqlLayerWindow(self.iface, layer, self)
+ lname = layer.name()
+ tabname = self.tr("Layer") + u" (%s)" % lname
+ index = self.tabs.addTab(query, tabname)
+ #self.tabs.setTabIcon(index, db.connection().icon())
+ self.tabs.setCurrentIndex(index)
+
def update_query_tab_name(self, index, dbname, queryname):
if not queryname:
queryname = self.tr("Query")
diff --git a/python/plugins/db_manager/db_manager_plugin.py b/python/plugins/db_manager/db_manager_plugin.py
index 3e1cbe6..dca2cbe 100644
--- a/python/plugins/db_manager/db_manager_plugin.py
+++ b/python/plugins/db_manager/db_manager_plugin.py
@@ -24,6 +24,9 @@ from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtWidgets import QAction, QApplication
from qgis.PyQt.QtGui import QIcon
+from qgis.core import QgsMapLayerRegistry, QgsMapLayer, QgsDataSourceURI
+import re
+
from . import resources_rc # NOQA
@@ -48,6 +51,15 @@ class DBManagerPlugin:
else:
self.iface.addPluginToMenu(QApplication.translate("DBManagerPlugin", "DB Manager"), self.action)
+ self.layerAction = QAction(QIcon(":/db_manager/icon"), QApplication.translate("DBManagerPlugin", "Update Sql Layer"),
+ self.iface.mainWindow())
+ self.layerAction.setObjectName("dbManagerUpdateSqlLayer")
+ self.layerAction.triggered.connect(self.onUpdateSqlLayer)
+ self.iface.legendInterface().addLegendLayerAction(self.layerAction, "", "dbManagerUpdateSqlLayer", QgsMapLayer.VectorLayer, False)
+ for l in QgsMapLayerRegistry.instance().mapLayers().values():
+ self.onLayerWasAdded(l)
+ QgsMapLayerRegistry.instance().layerWasAdded.connect(self.onLayerWasAdded)
+
def unload(self):
# Remove the plugin menu item and icon
if hasattr(self.iface, 'removePluginDatabaseMenu'):
@@ -59,9 +71,36 @@ class DBManagerPlugin:
else:
self.iface.removeToolBarIcon(self.action)
+ self.iface.legendInterface().removeLegendLayerAction(self.layerAction)
+ QgsMapLayerRegistry.instance().layerWasAdded.disconnect(self.onLayerWasAdded)
+
if self.dlg is not None:
self.dlg.close()
+ def onLayerWasAdded(self, aMapLayer):
+ if hasattr(aMapLayer, 'dataProvider') and aMapLayer.dataProvider().name() in ['postgres', 'spatialite', 'oracle']:
+ uri = QgsDataSourceURI(aMapLayer.source())
+ if re.search('^\(SELECT .+ FROM .+\)$', uri.table(), re.S):
+ self.iface.legendInterface().addLegendLayerActionForLayer(self.layerAction, aMapLayer)
+ # virtual has QUrl source
+ # url = QUrl(QUrl.fromPercentEncoding(l.source()))
+ # url.queryItemValue('query')
+ # url.queryItemValue('uid')
+ # url.queryItemValue('geometry')
+
+ def onUpdateSqlLayer(self):
+ l = self.iface.legendInterface().currentLayer()
+ if l.dataProvider().name() in ['postgres', 'spatialite', 'oracle']:
+ uri = QgsDataSourceURI(l.source())
+ if re.search('^\(SELECT .+ FROM .+\)$', uri.table(), re.S):
+ self.run()
+ self.dlg.runSqlLayerWindow(l)
+ # virtual has QUrl source
+ # url = QUrl(QUrl.fromPercentEncoding(l.source()))
+ # url.queryItemValue('query')
+ # url.queryItemValue('uid')
+ # url.queryItemValue('geometry')
+
def run(self):
# keep opened only one instance
if self.dlg is None:
diff --git a/python/plugins/db_manager/db_plugins/plugin.py b/python/plugins/db_manager/db_plugins/plugin.py
index 0e4a27a..402c3ab 100644
--- a/python/plugins/db_manager/db_plugins/plugin.py
+++ b/python/plugins/db_manager/db_plugins/plugin.py
@@ -550,6 +550,9 @@ class Database(DbItemObject):
def spatialIndexClause(self, src_table, src_column, dest_table, dest_table_column):
return None
+ def hasLowercaseFieldNamesOption(self):
+ return False
+
class Schema(DbItemObject):
diff --git a/python/plugins/db_manager/db_plugins/postgis/plugin.py b/python/plugins/db_manager/db_plugins/postgis/plugin.py
index fe9f5a5..a758d25 100644
--- a/python/plugins/db_manager/db_plugins/postgis/plugin.py
+++ b/python/plugins/db_manager/db_plugins/postgis/plugin.py
@@ -165,6 +165,9 @@ class PGDatabase(Database):
item.runRefreshMaterializedView()
+ def hasLowercaseFieldNamesOption(self):
+ return True
+
class PGSchema(Schema):
diff --git a/python/plugins/db_manager/db_plugins/spatialite/connector.py b/python/plugins/db_manager/db_plugins/spatialite/connector.py
index c85df0b..0bd73be 100644
--- a/python/plugins/db_manager/db_plugins/spatialite/connector.py
+++ b/python/plugins/db_manager/db_plugins/spatialite/connector.py
@@ -83,7 +83,7 @@ class SpatiaLiteDBConnector(DBConnector):
return self.has_spatial
def _checkRaster(self):
- """ check if it's a rasterite db """
+ """ check if it's a rasterlite db """
self.has_raster = self._checkRasterTables()
return self.has_raster
diff --git a/python/plugins/db_manager/dlg_import_vector.py b/python/plugins/db_manager/dlg_import_vector.py
index 8e9f579..b50341d 100644
--- a/python/plugins/db_manager/dlg_import_vector.py
+++ b/python/plugins/db_manager/dlg_import_vector.py
@@ -76,6 +76,10 @@ class DlgImportVector(QDialog, Ui_Dialog):
self.editPrimaryKey.setText(self.default_pk)
self.editGeomColumn.setText(self.default_geom)
+
+ self.chkLowercaseFieldNames.setEnabled(self.db.hasLowercaseFieldNamesOption())
+ if not self.chkLowercaseFieldNames.isEnabled():
+ self.chkLowercaseFieldNames.setChecked(False)
else:
# set default values
self.checkSupports()
@@ -106,6 +110,10 @@ class DlgImportVector(QDialog, Ui_Dialog):
if not self.chkSpatialIndex.isEnabled():
self.chkSpatialIndex.setChecked(False)
+ self.chkLowercaseFieldNames.setEnabled(self.db.hasLowercaseFieldNamesOption())
+ if not self.chkLowercaseFieldNames.isEnabled():
+ self.chkLowercaseFieldNames.setChecked(False)
+
def populateLayers(self):
self.cboInputLayer.clear()
for index, layer in enumerate(iface.legendInterface().layers()):
@@ -300,13 +308,18 @@ class DlgImportVector(QDialog, Ui_Dialog):
else:
geom = None
+ options = {}
+ if self.chkLowercaseFieldNames.isEnabled() and self.chkLowercaseFieldNames.isChecked():
+ pk = pk.lower()
+ if geom:
+ geom = geom.lower()
+ options['lowercaseFieldNames'] = True
+
# get output params, update output URI
self.outUri.setDataSource(schema, table, geom, "", pk)
uri = self.outUri.uri(False)
providerName = self.db.dbplugin().providerName()
-
- options = {}
if self.chkDropTable.isChecked():
options['overwrite'] = True
diff --git a/python/plugins/db_manager/dlg_sql_layer_window.py b/python/plugins/db_manager/dlg_sql_layer_window.py
new file mode 100644
index 0000000..18c87bb
--- /dev/null
+++ b/python/plugins/db_manager/dlg_sql_layer_window.py
@@ -0,0 +1,530 @@
+# -*- coding: utf-8 -*-
+
+"""
+/***************************************************************************
+Name : DB Manager
+Description : Database manager plugin for QGIS
+Date : May 23, 2011
+copyright : (C) 2011 by Giuseppe Sucameli
+email : brush.tyler at gmail.com
+
+The content of this file is based on
+- PG_Manager by Martin Dobias (GPLv2 license)
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+"""
+
+from PyQt4.QtCore import Qt, QObject, QSettings, QByteArray, SIGNAL, pyqtSignal
+from PyQt4.QtGui import QDialog, QWidget, QAction, QKeySequence, \
+ QDialogButtonBox, QApplication, QCursor, QMessageBox, QClipboard, QInputDialog, QIcon, QStyledItemDelegate, QStandardItemModel, QStandardItem
+from PyQt4.Qsci import QsciAPIs
+from PyQt4.QtXml import QDomDocument
+
+from qgis.core import QgsProject, QgsDataSourceURI
+
+from .db_plugins import createDbPlugin
+from .db_plugins.plugin import BaseError
+from .db_plugins.postgis.plugin import PGDatabase
+from .dlg_db_error import DlgDbError
+from .dlg_query_builder import QueryBuilderDlg
+
+try:
+ from qgis.gui import QgsCodeEditorSQL
+except:
+ from .sqledit import SqlEdit
+ from qgis import gui
+
+ gui.QgsCodeEditorSQL = SqlEdit
+
+from .ui.ui_DlgSqlLayerWindow import Ui_DbManagerDlgSqlLayerWindow as Ui_Dialog
+
+import re
+
+
+class DlgSqlLayerWindow(QWidget, Ui_Dialog):
+ nameChanged = pyqtSignal(str)
+
+ def __init__(self, iface, layer, parent=None):
+ QWidget.__init__(self, parent)
+ self.iface = iface
+ self.layer = layer
+
+ uri = QgsDataSourceURI(layer.source())
+ dbplugin = None
+ db = None
+ if layer.dataProvider().name() == 'postgres':
+ dbplugin = createDbPlugin('postgis', 'postgres')
+ elif layer.dataProvider().name() == 'spatialite':
+ dbplugin = createDbPlugin('spatialite', 'spatialite')
+ elif layer.dataProvider().name() == 'oracle':
+ dbplugin = createDbPlugin('oracle', 'oracle')
+ elif layer.dataProvider().name() == 'virtual':
+ dbplugin = createDbPlugin('vlayers', 'virtual')
+ if dbplugin:
+ dbplugin.connectToUri(uri)
+ db = dbplugin.db
+
+ self.dbplugin = dbplugin
+ self.db = db
+ self.filter = ""
+ self.allowMultiColumnPk = isinstance(db, PGDatabase) # at the moment only PostgreSQL allows a primary key to span multiple columns, spatialite doesn't
+ self.aliasSubQuery = isinstance(db, PGDatabase) # only PostgreSQL requires subqueries to be aliases
+ self.setupUi(self)
+ self.setWindowTitle(
+ u"%s - %s [%s]" % (self.windowTitle(), db.connection().connectionName(), db.connection().typeNameString()))
+
+ self.defaultLayerName = 'QueryLayer'
+
+ if self.allowMultiColumnPk:
+ self.uniqueColumnCheck.setText(self.trUtf8("Column(s) with unique values"))
+ else:
+ self.uniqueColumnCheck.setText(self.trUtf8("Column with unique values"))
+
+ self.editSql.setFocus()
+ self.editSql.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
+ self.editSql.setMarginVisible(True)
+ self.initCompleter()
+
+ # allow copying results
+ copyAction = QAction("copy", self)
+ self.viewResult.addAction(copyAction)
+ copyAction.setShortcuts(QKeySequence.Copy)
+
+ copyAction.triggered.connect(self.copySelectedResults)
+
+ self.btnExecute.clicked.connect(self.executeSql)
+ self.btnSetFilter.clicked.connect(self.setFilter)
+ self.btnClear.clicked.connect(self.clearSql)
+
+ self.presetStore.clicked.connect(self.storePreset)
+ self.presetDelete.clicked.connect(self.deletePreset)
+ self.presetCombo.activated[str].connect(self.loadPreset)
+ self.presetCombo.activated[str].connect(self.presetName.setText)
+
+ self.updatePresetsCombobox()
+
+ self.geomCombo.setEditable(True)
+ self.geomCombo.lineEdit().setReadOnly(True)
+
+ self.uniqueCombo.setEditable(True)
+ self.uniqueCombo.lineEdit().setReadOnly(True)
+ self.uniqueModel = QStandardItemModel(self.uniqueCombo)
+ self.uniqueCombo.setModel(self.uniqueModel)
+ if self.allowMultiColumnPk:
+ self.uniqueCombo.setItemDelegate(QStyledItemDelegate())
+ self.uniqueModel.itemChanged.connect(self.uniqueChanged) # react to the (un)checking of an item
+ self.uniqueCombo.lineEdit().textChanged.connect(self.uniqueTextChanged) # there are other events that change the displayed text and some of them can not be caught directly
+
+ self.layerTypeWidget.hide() # show if load as raster is supported
+ #self.loadLayerBtn.clicked.connect(self.loadSqlLayer)
+ self.updateLayerBtn.clicked.connect(self.updateSqlLayer)
+ self.getColumnsBtn.clicked.connect(self.fillColumnCombos)
+
+ self.queryBuilderFirst = True
+ self.queryBuilderBtn.setIcon(QIcon(":/db_manager/icons/sql.gif"))
+ self.queryBuilderBtn.clicked.connect(self.displayQueryBuilder)
+
+ self.presetName.textChanged.connect(self.nameChanged)
+
+ # Update from layer
+ # Fisrtly the SQL from QgsDataSourceURI table
+ sql = uri.table()
+ if uri.keyColumn() == '_uid_':
+ match = re.search('^\(SELECT .+ AS _uid_,\* FROM \((.*)\) AS _subq_.+_\s*\)$', sql, re.S)
+ if match:
+ sql = match.group(1)
+ else:
+ match = re.search('^\((SELECT .+ FROM .+)\)$', sql, re.S)
+ if match:
+ sql = match.group(1)
+ self.editSql.setText(sql)
+ self.executeSql()
+
+ # Then the columns
+ self.geomCombo.setCurrentIndex(self.geomCombo.findText(uri.geometryColumn(), Qt.MatchExactly))
+ if uri.keyColumn() != '_uid_':
+ self.uniqueColumnCheck.setCheckState(Qt.Checked)
+ if self.allowMultiColumnPk:
+ itemsData = uri.keyColumn().split(',')
+ for item in self.uniqueModel.findItems("*", Qt.MatchWildcard):
+ if item.data() in itemsData:
+ item.setCheckState(Qt.Checked)
+ else:
+ keyColumn = uri.keyColumn()
+ for item in self.uniqueModel.findItems("*", Qt.MatchWildcard):
+ if item.data() == keyColumn:
+ self.uniqueCombo.setCurrentIndex(self.uniqueModel.indexFromItem(item).row())
+
+ # Finally layer name, filter and selectAtId
+ self.layerNameEdit.setText(layer.name())
+ self.filter = uri.sql()
+ if uri.selectAtIdDisabled():
+ self.avoidSelectById.setCheckState(Qt.Checked)
+
+ def updatePresetsCombobox(self):
+ self.presetCombo.clear()
+
+ names = []
+ entries = QgsProject.instance().subkeyList('DBManager', 'savedQueries')
+ for entry in entries:
+ name = QgsProject.instance().readEntry('DBManager', 'savedQueries/' + entry + '/name')[0]
+ names.append(name)
+
+ for name in sorted(names):
+ self.presetCombo.addItem(name)
+ self.presetCombo.setCurrentIndex(-1)
+
+ def storePreset(self):
+ query = self._getSqlQuery()
+ if query == "":
+ return
+ name = self.presetName.text()
+ QgsProject.instance().writeEntry('DBManager', 'savedQueries/q' + unicode(name.__hash__()) + '/name', name)
+ QgsProject.instance().writeEntry('DBManager', 'savedQueries/q' + unicode(name.__hash__()) + '/query', query)
+ index = self.presetCombo.findText(name)
+ if index == -1:
+ self.presetCombo.addItem(name)
+ self.presetCombo.setCurrentIndex(self.presetCombo.count() - 1)
+ else:
+ self.presetCombo.setCurrentIndex(index)
+
+ def deletePreset(self):
+ name = self.presetCombo.currentText()
+ QgsProject.instance().removeEntry('DBManager', 'savedQueries/q' + unicode(name.__hash__()))
+ self.presetCombo.removeItem(self.presetCombo.findText(name))
+ self.presetCombo.setCurrentIndex(-1)
+
+ def loadPreset(self, name):
+ query = QgsProject.instance().readEntry('DBManager', 'savedQueries/q' + unicode(name.__hash__()) + '/query')[0]
+ name = QgsProject.instance().readEntry('DBManager', 'savedQueries/q' + unicode(name.__hash__()) + '/name')[0]
+ self.editSql.setText(query)
+
+ def clearSql(self):
+ self.editSql.clear()
+ self.editSql.setFocus()
+ self.filter = ""
+
+ def executeSql(self):
+
+ sql = self._getSqlQuery()
+ if sql == "":
+ return
+
+ QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
+
+ # delete the old model
+ old_model = self.viewResult.model()
+ self.viewResult.setModel(None)
+ if old_model:
+ old_model.deleteLater()
+
+ cols = []
+ quotedCols = []
+
+ try:
+ # set the new model
+ model = self.db.sqlResultModel(sql, self)
+ self.viewResult.setModel(model)
+ self.lblResult.setText(self.tr("%d rows, %.1f seconds") % (model.affectedRows(), model.secs()))
+ cols = self.viewResult.model().columnNames()
+ for col in cols:
+ quotedCols.append(self.db.connector.quoteId(col))
+
+ except BaseError as e:
+ QApplication.restoreOverrideCursor()
+ DlgDbError.showError(e, self)
+ self.uniqueModel.clear()
+ self.geomCombo.clear()
+ return
+
+ self.setColumnCombos(cols, quotedCols)
+
+ self.update()
+ QApplication.restoreOverrideCursor()
+
+ def _getSqlLayer(self, _filter):
+ hasUniqueField = self.uniqueColumnCheck.checkState() == Qt.Checked
+ if hasUniqueField:
+ if self.allowMultiColumnPk:
+ checkedCols = []
+ for item in self.uniqueModel.findItems("*", Qt.MatchWildcard):
+ if item.checkState() == Qt.Checked:
+ checkedCols.append(item.data())
+ uniqueFieldName = ",".join(checkedCols)
+ elif self.uniqueCombo.currentIndex() >= 0:
+ uniqueFieldName = self.uniqueModel.item(self.uniqueCombo.currentIndex()).data()
+ else:
+ uniqueFieldName = None
+ else:
+ uniqueFieldName = None
+ hasGeomCol = self.hasGeometryCol.checkState() == Qt.Checked
+ if hasGeomCol:
+ geomFieldName = self.geomCombo.currentText()
+ else:
+ geomFieldName = None
+
+ query = self._getSqlQuery()
+ if query == "":
+ return None
+
+ # remove a trailing ';' from query if present
+ if query.strip().endswith(';'):
+ query = query.strip()[:-1]
+
+ from qgis.core import QgsMapLayer, QgsMapLayerRegistry
+
+ layerType = QgsMapLayer.VectorLayer if self.vectorRadio.isChecked() else QgsMapLayer.RasterLayer
+
+ # get a new layer name
+ names = []
+ for layer in QgsMapLayerRegistry.instance().mapLayers().values():
+ names.append(layer.name())
+
+ layerName = self.layerNameEdit.text()
+ if layerName == "":
+ layerName = self.defaultLayerName
+ newLayerName = layerName
+ index = 1
+ while newLayerName in names:
+ index += 1
+ newLayerName = u"%s_%d" % (layerName, index)
+
+ # create the layer
+ layer = self.db.toSqlLayer(query, geomFieldName, uniqueFieldName, newLayerName, layerType,
+ self.avoidSelectById.isChecked(), _filter)
+ if layer.isValid():
+ return layer
+ else:
+ return None
+
+ def loadSqlLayer(self):
+ QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
+ try:
+ layer = self._getSqlLayer(self.filter)
+ if layer == None:
+ return
+
+ from qgis.core import QgsMapLayerRegistry
+ QgsMapLayerRegistry.instance().addMapLayers([layer], True)
+ finally:
+ QApplication.restoreOverrideCursor()
+
+ def updateSqlLayer(self):
+ QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
+ try:
+ layer = self._getSqlLayer(self.filter)
+ if layer == None:
+ return
+
+ #self.layer.dataProvider().setDataSourceUri(layer.dataProvider().dataSourceUri())
+ #self.layer.dataProvider().reloadData()
+ XMLDocument = QDomDocument("style")
+ XMLMapLayers = XMLDocument.createElement("maplayers")
+ XMLMapLayer = XMLDocument.createElement("maplayer")
+ self.layer.writeLayerXML(XMLMapLayer, XMLDocument)
+ XMLMapLayer.firstChildElement("datasource").firstChild().setNodeValue(layer.source())
+ XMLMapLayers.appendChild(XMLMapLayer)
+ XMLDocument.appendChild(XMLMapLayers)
+ self.layer.readLayerXML(XMLMapLayer)
+ self.layer.reload()
+ self.iface.actionDraw().trigger()
+ self.iface.mapCanvas().refresh()
+ self.iface.legendInterface().refreshLayerSymbology(layer)
+ finally:
+ QApplication.restoreOverrideCursor()
+
+ def fillColumnCombos(self):
+ query = self._getSqlQuery()
+ if query == "":
+ return
+
+ QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
+
+ # remove a trailing ';' from query if present
+ if query.strip().endswith(';'):
+ query = query.strip()[:-1]
+
+ # get all the columns
+ cols = []
+ quotedCols = []
+ connector = self.db.connector
+ if self.aliasSubQuery:
+ # get a new alias
+ aliasIndex = 0
+ while True:
+ alias = "_subQuery__%d" % aliasIndex
+ escaped = re.compile('\\b("?)' + re.escape(alias) + '\\1\\b')
+ if not escaped.search(query):
+ break
+ aliasIndex += 1
+
+ sql = u"SELECT * FROM (%s\n) AS %s LIMIT 0" % (unicode(query), connector.quoteId(alias))
+ else:
+ sql = u"SELECT * FROM (%s\n) WHERE 1=0" % unicode(query)
+
+ c = None
+ try:
+ c = connector._execute(None, sql)
+ cols = connector._get_cursor_columns(c)
+ for col in cols:
+ quotedCols.append(connector.quoteId(col))
+
+ except BaseError as e:
+ QApplication.restoreOverrideCursor()
+ DlgDbError.showError(e, self)
+ self.uniqueModel.clear()
+ self.geomCombo.clear()
+ return
+
+ finally:
+ if c:
+ c.close()
+ del c
+
+ self.setColumnCombos(cols, quotedCols)
+
+ QApplication.restoreOverrideCursor()
+
+ def setColumnCombos(self, cols, quotedCols):
+ # get sensible default columns. do this before sorting in case there's hints in the column order (eg, id is more likely to be first)
+ try:
+ defaultGeomCol = next(col for col in cols if col in ['geom', 'geometry', 'the_geom', 'way'])
+ except:
+ defaultGeomCol = None
+ try:
+ defaultUniqueCol = [col for col in cols if 'id' in col][0]
+ except:
+ defaultUniqueCol = None
+
+ colNames = sorted(zip(cols, quotedCols))
+ newItems = []
+ uniqueIsFilled = False
+ for (col, quotedCol) in colNames:
+ item = QStandardItem(col)
+ item.setData(quotedCol)
+ item.setEnabled(True)
+ item.setCheckable(self.allowMultiColumnPk)
+ item.setSelectable(not self.allowMultiColumnPk)
+ if self.allowMultiColumnPk:
+ matchingItems = self.uniqueModel.findItems(col)
+ if matchingItems:
+ item.setCheckState(matchingItems[0].checkState())
+ uniqueIsFilled = uniqueIsFilled or matchingItems[0].checkState() == Qt.Checked
+ else:
+ item.setCheckState(Qt.Unchecked)
+ newItems.append(item)
+ if self.allowMultiColumnPk:
+ self.uniqueModel.clear()
+ self.uniqueModel.appendColumn(newItems)
+ self.uniqueChanged()
+ else:
+ previousUniqueColumn = self.uniqueCombo.currentText()
+ self.uniqueModel.clear()
+ self.uniqueModel.appendColumn(newItems)
+ if self.uniqueModel.findItems(previousUniqueColumn):
+ self.uniqueCombo.setEditText(previousUniqueColumn)
+ uniqueIsFilled = True
+
+ oldGeometryColumn = self.geomCombo.currentText()
+ self.geomCombo.clear()
+ self.geomCombo.addItems(cols)
+ self.geomCombo.setCurrentIndex(self.geomCombo.findText(oldGeometryColumn, Qt.MatchExactly))
+
+ # set sensible default columns if the columns are not already set
+ try:
+ if self.geomCombo.currentIndex() == -1:
+ self.geomCombo.setCurrentIndex(cols.index(defaultGeomCol))
+ except:
+ pass
+ items = self.uniqueModel.findItems(defaultUniqueCol)
+ if items and not uniqueIsFilled:
+ if self.allowMultiColumnPk:
+ items[0].setCheckState(Qt.Checked)
+ else:
+ self.uniqueCombo.setEditText(defaultUniqueCol)
+ try:
+ pass
+ except:
+ pass
+
+ def copySelectedResults(self):
+ if len(self.viewResult.selectedIndexes()) <= 0:
+ return
+ model = self.viewResult.model()
+
+ # convert to string using tab as separator
+ text = model.headerToString("\t")
+ for idx in self.viewResult.selectionModel().selectedRows():
+ text += "\n" + model.rowToString(idx.row(), "\t")
+
+ QApplication.clipboard().setText(text, QClipboard.Selection)
+ QApplication.clipboard().setText(text, QClipboard.Clipboard)
+
+ def initCompleter(self):
+ dictionary = None
+ if self.db:
+ dictionary = self.db.connector.getSqlDictionary()
+ if not dictionary:
+ # use the generic sql dictionary
+ from .sql_dictionary import getSqlDictionary
+
+ dictionary = getSqlDictionary()
+
+ wordlist = []
+ for name, value in dictionary.iteritems():
+ wordlist += value # concat lists
+ wordlist = list(set(wordlist)) # remove duplicates
+
+ api = QsciAPIs(self.editSql.lexer())
+ for word in wordlist:
+ api.add(word)
+
+ api.prepare()
+ self.editSql.lexer().setAPIs(api)
+
+ def displayQueryBuilder(self):
+ dlg = QueryBuilderDlg(self.iface, self.db, self, reset=self.queryBuilderFirst)
+ self.queryBuilderFirst = False
+ r = dlg.exec_()
+ if r == QDialog.Accepted:
+ self.editSql.setText(dlg.query)
+
+ def _getSqlQuery(self):
+ sql = self.editSql.selectedText()
+ if len(sql) == 0:
+ sql = self.editSql.text()
+ return sql
+
+ def uniqueChanged(self):
+ # when an item is (un)checked, simply trigger an update of the combobox text
+ self.uniqueTextChanged(None)
+
+ def uniqueTextChanged(self, text):
+ # Whenever there is new text displayed in the combobox, check if it is the correct one and if not, display the correct one.
+ checkedItems = []
+ for item in self.uniqueModel.findItems("*", Qt.MatchWildcard):
+ if item.checkState() == Qt.Checked:
+ checkedItems.append(item.text())
+ label = ", ".join(checkedItems)
+ if text != label:
+ self.uniqueCombo.setEditText(label)
+
+ def setFilter(self):
+ from qgis.gui import QgsQueryBuilder
+ layer = self._getSqlLayer("")
+ if not layer:
+ return
+
+ dlg = QgsQueryBuilder(layer)
+ dlg.setSql(self.filter)
+ if dlg.exec_():
+ self.filter = dlg.sql()
+ layer.deleteLater()
diff --git a/python/plugins/db_manager/ui/DlgImportVector.ui b/python/plugins/db_manager/ui/DlgImportVector.ui
index 34f6060..c2ec343 100644
--- a/python/plugins/db_manager/ui/DlgImportVector.ui
+++ b/python/plugins/db_manager/ui/DlgImportVector.ui
@@ -253,7 +253,7 @@
</property>
</widget>
</item>
- <item row="7" column="0" colspan="2">
+ <item row="8" column="0" colspan="2">
<widget class="QCheckBox" name="chkSpatialIndex">
<property name="text">
<string>Create spatial index</string>
@@ -267,6 +267,13 @@
</property>
</widget>
</item>
+ <item row="7" column="0">
+ <widget class="QCheckBox" name="chkLowercaseFieldNames">
+ <property name="text">
+ <string>Convert field names to lowercase</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
diff --git a/python/plugins/db_manager/ui/DlgSqlLayerWindow.ui b/python/plugins/db_manager/ui/DlgSqlLayerWindow.ui
new file mode 100644
index 0000000..1d0d596
--- /dev/null
+++ b/python/plugins/db_manager/ui/DlgSqlLayerWindow.ui
@@ -0,0 +1,407 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DbManagerDlgSqlLayerWindow</class>
+ <widget class="QDialog" name="DbManagerDlgSqlLayerWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>662</width>
+ <height>525</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>SQL window</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="3" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="avoidSelectById">
+ <property name="toolTip">
+ <string><html><head/><body><p>Avoid selecting feature by id. Sometimes - especially when running expensive queries/views - fetching the data sequentially instead of fetching features by id can be much quicker.</p></body></html></string>
+ </property>
+ <property name="text">
+ <string>Avoid selecting by feature id</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="updateLayerBtn">
+ <property name="text">
+ <string>Update</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="0">
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="QWidget" name="layoutWidget">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QToolButton" name="queryBuilderBtn">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Saved query:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="presetCombo"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Name</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="presetName">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="presetStore">
+ <property name="text">
+ <string>Store</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="presetDelete">
+ <property name="text">
+ <string>Delete</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QgsCodeEditorSQL" name="editSql"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QPushButton" name="btnExecute">
+ <property name="text">
+ <string>&Execute (F5)</string>
+ </property>
+ <property name="shortcut">
+ <string>F5</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblResult">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnClear">
+ <property name="text">
+ <string>&Clear</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="layoutWidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTableView" name="viewResult">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>3</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="horizontalScrollMode">
+ <enum>QAbstractItemView::ScrollPerPixel</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QCheckBox" name="uniqueColumnCheck">
+ <property name="text">
+ <string>Column(s) with
+unique values</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="uniqueCombo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="insertPolicy">
+ <enum>QComboBox::NoInsert</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="hasGeometryCol">
+ <property name="text">
+ <string>Geometry column</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="geomCombo">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="insertPolicy">
+ <enum>QComboBox::NoInsert</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="getColumnsBtn">
+ <property name="text">
+ <string>Retrieve
+columns</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Layer name (prefix)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="layerNameEdit">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="layerTypeWidget" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Type</string>
+ </property>
+ <property name="indent">
+ <number>40</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="vectorRadio">
+ <property name="text">
+ <string>Vector</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="rasterRadio">
+ <property name="text">
+ <string>Raster</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnSetFilter">
+ <property name="text">
+ <string>Set filter</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QgsCodeEditorSQL</class>
+ <extends>QTextEdit</extends>
+ <header>qgis.gui</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>btnExecute</tabstop>
+ <tabstop>btnClear</tabstop>
+ <tabstop>viewResult</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>hasGeometryCol</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>geomCombo</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>379</x>
+ <y>385</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>525</x>
+ <y>385</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>uniqueColumnCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>uniqueCombo</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>109</x>
+ <y>385</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>274</x>
+ <y>385</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/python/plugins/processing/ProcessingPlugin.py b/python/plugins/processing/ProcessingPlugin.py
index 61a583d..6557a2d 100644
--- a/python/plugins/processing/ProcessingPlugin.py
+++ b/python/plugins/processing/ProcessingPlugin.py
@@ -118,7 +118,7 @@ class ProcessingPlugin:
self.commanderAction.triggered.connect(self.openCommander)
self.menu.addAction(self.commanderAction)
self.iface.registerMainWindowAction(self.commanderAction,
- self.tr('Ctrl+Alt+M'))
+ self.tr('Ctrl+Alt+D'))
initializeMenus()
createMenus()
diff --git a/python/plugins/processing/algs/gdal/GdalAlgorithm.py b/python/plugins/processing/algs/gdal/GdalAlgorithm.py
index a0a3f53..8dc4310 100644
--- a/python/plugins/processing/algs/gdal/GdalAlgorithm.py
+++ b/python/plugins/processing/algs/gdal/GdalAlgorithm.py
@@ -16,8 +16,6 @@
* *
***************************************************************************
"""
-from processing.tools import dataobjects
-
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
@@ -35,6 +33,7 @@ from qgis.PyQt.QtGui import QIcon
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.algs.gdal.GdalAlgorithmDialog import GdalAlgorithmDialog
from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools import dataobjects
pluginPath = os.path.normpath(os.path.join(
os.path.split(os.path.dirname(__file__))[0], os.pardir))
diff --git a/python/plugins/processing/algs/gdal/ogr2ogrtopostgis.py b/python/plugins/processing/algs/gdal/ogr2ogrtopostgis.py
index 2f49b41..652dd7b 100644
--- a/python/plugins/processing/algs/gdal/ogr2ogrtopostgis.py
+++ b/python/plugins/processing/algs/gdal/ogr2ogrtopostgis.py
@@ -93,15 +93,15 @@ class Ogr2OgrToPostGis(GdalAlgorithm):
self.addParameter(ParameterCrs(self.S_SRS,
self.tr('Override source CRS'), '', optional=True))
self.addParameter(ParameterString(self.HOST,
- self.tr('Host'), 'localhost', optional=False))
+ self.tr('Host'), 'localhost', optional=True))
self.addParameter(ParameterString(self.PORT,
- self.tr('Port'), '5432', optional=False))
+ self.tr('Port'), '5432', optional=True))
self.addParameter(ParameterString(self.USER,
- self.tr('Username'), '', optional=False))
+ self.tr('Username'), '', optional=True))
self.addParameter(ParameterString(self.DBNAME,
- self.tr('Database name'), '', optional=False))
+ self.tr('Database name'), '', optional=True))
self.addParameter(ParameterString(self.PASSWORD,
- self.tr('Password'), '', optional=False))
+ self.tr('Password'), '', optional=True))
self.addParameter(ParameterString(self.SCHEMA,
self.tr('Schema name'), 'public', optional=True))
self.addParameter(ParameterString(self.TABLE,
@@ -153,6 +153,28 @@ class Ogr2OgrToPostGis(GdalAlgorithm):
self.addParameter(ParameterString(self.OPTIONS,
self.tr('Additional creation options'), '', optional=True))
+ def getConnectionString(self):
+ host = self.getParameterValue(self.HOST)
+ port = self.getParameterValue(self.PORT)
+ user = self.getParameterValue(self.USER)
+ dbname = self.getParameterValue(self.DBNAME)
+ password = self.getParameterValue(self.PASSWORD)
+ schema = self.getParameterValue(self.SCHEMA)
+ arguments = []
+ if host:
+ arguments.append('host=' + host)
+ if port:
+ arguments.append('port=' + str(port))
+ if dbname:
+ arguments.append('dbname=' + dbname)
+ if password:
+ arguments.append('password=' + password)
+ if schema:
+ arguments.append('active_schema=' + schema)
+ if user:
+ arguments.append('user=' + user)
+ return GdalUtils.escapeAndJoin(arguments)
+
def getConsoleCommands(self):
inLayer = self.getParameterValue(self.INPUT_LAYER)
ogrLayer = ogrConnectionString(inLayer)[1:-1]
@@ -160,12 +182,6 @@ class Ogr2OgrToPostGis(GdalAlgorithm):
ssrs = unicode(self.getParameterValue(self.S_SRS))
tsrs = unicode(self.getParameterValue(self.T_SRS))
asrs = unicode(self.getParameterValue(self.A_SRS))
- host = unicode(self.getParameterValue(self.HOST))
- port = unicode(self.getParameterValue(self.PORT))
- user = unicode(self.getParameterValue(self.USER))
- dbname = unicode(self.getParameterValue(self.DBNAME))
- password = unicode(self.getParameterValue(self.PASSWORD))
- schema = unicode(self.getParameterValue(self.SCHEMA))
table = unicode(self.getParameterValue(self.TABLE))
pk = unicode(self.getParameterValue(self.PK))
pkstring = "-lco FID=" + pk
@@ -202,17 +218,9 @@ class Ogr2OgrToPostGis(GdalAlgorithm):
arguments.append('"' + shapeEncoding + '"')
arguments.append('-f')
arguments.append('PostgreSQL')
- arguments.append('PG:"host=' + host)
- arguments.append('port=' + port)
- if len(dbname) > 0:
- arguments.append('dbname=' + dbname)
- if len(password) > 0:
- arguments.append('password=' + password)
- if len(schema) > 0:
- arguments.append('active_schema=' + schema)
- else:
- arguments.append('active_schema=public')
- arguments.append('user=' + user + '"')
+ arguments.append('PG:"')
+ arguments.append(self.getConnectionString())
+ arguments.append('"')
arguments.append(dimstring)
arguments.append(ogrLayer)
arguments.append(ogrLayerName(inLayer))
diff --git a/python/plugins/processing/algs/gdal/ogr2ogrtopostgislist.py b/python/plugins/processing/algs/gdal/ogr2ogrtopostgislist.py
index b79d065..afe31ff 100644
--- a/python/plugins/processing/algs/gdal/ogr2ogrtopostgislist.py
+++ b/python/plugins/processing/algs/gdal/ogr2ogrtopostgislist.py
@@ -210,7 +210,7 @@ class Ogr2OgrToPostGisList(GdalAlgorithm):
arguments = []
arguments.append('-progress')
arguments.append('--config PG_USE_COPY YES')
- if len(shapeEncoding) > 0:
+ if shapeEncoding:
arguments.append('--config')
arguments.append('SHAPE_ENCODING')
arguments.append('"' + shapeEncoding + '"')
diff --git a/python/plugins/processing/algs/gdal/warp.py b/python/plugins/processing/algs/gdal/warp.py
index 752ae04..84e0fdf 100644
--- a/python/plugins/processing/algs/gdal/warp.py
+++ b/python/plugins/processing/algs/gdal/warp.py
@@ -87,11 +87,11 @@ class warp(GdalAlgorithm):
0.0, None, 0.0))
self.addParameter(ParameterSelection(self.METHOD,
self.tr('Resampling method'), self.METHOD_OPTIONS))
- self.addParameter(ParameterExtent(self.RAST_EXT, self.tr('Raster extent')))
+ self.addParameter(ParameterExtent(self.RAST_EXT, self.tr('Raster extent'), optional=True))
- if GdalUtils.version() > 2000000:
+ if GdalUtils.version() >= 2000000:
self.addParameter(ParameterCrs(self.EXT_CRS,
- self.tr('CRS of the raster extent'), ''))
+ self.tr('CRS of the raster extent'), '', optional=True))
params = []
params.append(ParameterSelection(self.RTYPE,
@@ -176,9 +176,10 @@ class warp(GdalAlgorithm):
if rastext:
arguments.extend(rastext)
- if rastext and len(rastext_crs) > 0:
- arguments.append('-te_srs')
- arguments.append(rastext_crs)
+ if GdalUtils.version() >= 2000000:
+ if rastext and rastext_crs is not None:
+ arguments.append('-te_srs')
+ arguments.append(rastext_crs)
if extra and len(extra) > 0:
arguments.append(extra)
diff --git a/python/plugins/processing/algs/grass/GrassAlgorithm.py b/python/plugins/processing/algs/grass/GrassAlgorithm.py
index b19cbe5..216ab2e 100644
--- a/python/plugins/processing/algs/grass/GrassAlgorithm.py
+++ b/python/plugins/processing/algs/grass/GrassAlgorithm.py
@@ -84,6 +84,7 @@ class GrassAlgorithm(GeoAlgorithm):
self.descriptionFile = descriptionfile
self.defineCharacteristicsFromFile()
self.numExportedLayers = 0
+ self._icon = None
def getCopy(self):
newone = GrassAlgorithm(self.descriptionFile)
@@ -91,7 +92,10 @@ class GrassAlgorithm(GeoAlgorithm):
return newone
def getIcon(self):
- return QIcon(os.path.join(pluginPath, 'images', 'grass.svg'))
+ if self._icon is None:
+ self._icon = QIcon(os.path.join(pluginPath, 'images', 'grass.svg'))
+ return self._icon
+
def help(self):
return False, 'http://grass.osgeo.org/grass64/manuals/' + self.grassName + '.html'
@@ -158,7 +162,7 @@ class GrassAlgorithm(GeoAlgorithm):
elif isinstance(output, OutputVector):
vectorOutputs += 1
if isinstance(output, OutputHTML):
- self.addOutput(OutputFile("rawoutput", output.description +
+ self.addOutput(OutputFile("rawoutput", output.description +
" (raw output)", "txt"))
line = lines.readline().strip('\n').strip()
except Exception as e:
@@ -180,7 +184,7 @@ class GrassAlgorithm(GeoAlgorithm):
if hasVectorInput:
param = ParameterNumber(self.GRASS_SNAP_TOLERANCE_PARAMETER,
'v.in.ogr snap tolerance (-1 = no snap)',
- -1, None, -1.0)
+ - 1, None, -1.0)
param.isAdvanced = True
self.addParameter(param)
param = ParameterNumber(self.GRASS_MIN_AREA_PARAMETER,
diff --git a/python/plugins/processing/algs/grass7/Grass7Algorithm.py b/python/plugins/processing/algs/grass7/Grass7Algorithm.py
index e5ccf0b..c81159d 100644
--- a/python/plugins/processing/algs/grass7/Grass7Algorithm.py
+++ b/python/plugins/processing/algs/grass7/Grass7Algorithm.py
@@ -83,6 +83,7 @@ class Grass7Algorithm(GeoAlgorithm):
self.descriptionFile = descriptionfile
self.defineCharacteristicsFromFile()
self.numExportedLayers = 0
+ self._icon = None
self.uniqueSufix = unicode(uuid.uuid4()).replace('-', '')
# Use the ext mechanism
@@ -98,7 +99,9 @@ class Grass7Algorithm(GeoAlgorithm):
return newone
def getIcon(self):
- return QIcon(os.path.join(pluginPath, 'images', 'grass.svg'))
+ if self._icon is None:
+ self._icon = QIcon(os.path.join(pluginPath, 'images', 'grass.svg'))
+ return self._icon
def help(self):
localDoc = None
@@ -192,7 +195,7 @@ class Grass7Algorithm(GeoAlgorithm):
elif isinstance(output, OutputVector):
vectorOutputs += 1
if isinstance(output, OutputHTML):
- self.addOutput(OutputFile("rawoutput", output.description +
+ self.addOutput(OutputFile("rawoutput", output.description +
" (raw output)", "txt"))
line = lines.readline().strip('\n').strip()
except Exception as e:
@@ -214,7 +217,7 @@ class Grass7Algorithm(GeoAlgorithm):
if hasVectorInput:
param = ParameterNumber(self.GRASS_SNAP_TOLERANCE_PARAMETER,
'v.in.ogr snap tolerance (-1 = no snap)',
- -1, None, -1.0)
+ - 1, None, -1.0)
param.isAdvanced = True
self.addParameter(param)
param = ParameterNumber(self.GRASS_MIN_AREA_PARAMETER,
diff --git a/python/plugins/processing/algs/grass7/Grass7Utils.py b/python/plugins/processing/algs/grass7/Grass7Utils.py
index 9abeda2..5beb0ea 100644
--- a/python/plugins/processing/algs/grass7/Grass7Utils.py
+++ b/python/plugins/processing/algs/grass7/Grass7Utils.py
@@ -243,8 +243,8 @@ class Grass7Utils:
Grass7Utils.createGrass7BatchJobFileFromGrass7Commands(commands)
os.chmod(Grass7Utils.grassBatchJobFilename(), stat.S_IEXEC
| stat.S_IREAD | stat.S_IWRITE)
- if isMac() and os.path.exists(Grass7Utils.grassPath() + os.sep + '*grass.sh*'):
- command = Grass7Utils.grassPath() + os.sep + '*grass.sh* ' \
+ if isMac() and os.path.exists(Grass7Utils.grassPath() + os.sep + 'grass.sh'):
+ command = Grass7Utils.grassPath() + os.sep + 'grass.sh ' \
+ Grass7Utils.grassMapsetFolder() + '/PERMANENT'
else:
command = 'grass70 ' + Grass7Utils.grassMapsetFolder() \
diff --git a/python/plugins/processing/algs/grass7/ext/i_aster_toar.py b/python/plugins/processing/algs/grass7/ext/i_aster_toar.py
index d0aac70..0f37758 100644
--- a/python/plugins/processing/algs/grass7/ext/i_aster_toar.py
+++ b/python/plugins/processing/algs/grass7/ext/i_aster_toar.py
@@ -26,7 +26,7 @@ __copyright__ = '(C) 2016, Médéric Ribreux'
__revision__ = '$Format:%H$'
from i import multipleOutputDir
-from processoing.core.parameters import getParameterFromString
+from processing.core.parameters import getParameterFromString
def processCommand(alg):
diff --git a/python/plugins/processing/algs/help/qgis.yaml b/python/plugins/processing/algs/help/qgis.yaml
index bcf266f..10a9574 100644
--- a/python/plugins/processing/algs/help/qgis.yaml
+++ b/python/plugins/processing/algs/help/qgis.yaml
@@ -33,6 +33,12 @@ qgis:basicstatisticsfortextfields: >
Statistics are generated as an HTML file.
+qgis:boundary: >
+ Returns the closure of the combinatorial boundary of the input geometries (ie the topological boundary of the geometry). For instance, a polygon geometry will have a boundary consisting of the linestrings for each ring in the polygon. Only valid for polygon or line layers.
+
+qgis:boundingboxes: >
+ This algorithm calculates the bounding box (envelope) of each feature in an input layer.
+
qgis:buildvirtualvector: >
This algorithm creates a virtual layer that contains a set of vector layer.
@@ -64,19 +70,19 @@ qgis:convexhull: >
If a field is specified, it will divide the features into classes based on that field, and compute a separate convex hull for the features in each class.
qgis:countpointsinpolygon: >
- This algorithms takes a points layer and a polygon layer and counts the number of points from the first one in each polygons of the second one.
+ This algorithm takes a points layer and a polygon layer and counts the number of points from the first one in each polygons of the second one.
A new polygons layer is generated, with the exact same content as the input polygons layer, but containing an additional field with the points count corresponding to each polygon.
qgis:countpointsinpolygonweighted: >
- This algorithms takes a points layer and a polygon layer and counts the number of points from the first one in each polygons of the second one.
+ This algorithm takes a points layer and a polygon layer and counts the number of points from the first one in each polygons of the second one.
An attribute is used in the points layer to assign weights to each point.
A new polygons layer is generated, with the exact same content as the input polygons layer, but containing an additional field with the points count corresponding to each polygon.
qgis:countuniquepointsinpolygon: >
- This algorithms takes a points layer and a polygon layer and counts the number of points from the first one in each polygons of the second one.
+ This algorithm takes a points layer and a polygon layer and counts the number of points from the first one in each polygons of the second one.
Points are classified based on an attribute, and if several points with the same attribute value are within the extent of the polygon, only one of them is counted. The final count of point in a polygon is, therefore, the count of different classes that are found in it.
@@ -93,7 +99,7 @@ qgis:creategrid:
The CRS of the output layer must be defined. The grid extent and the spacing values are supposed to be expressed in the coordinates and units of this CRS.
qgis:createpointsalonglines: >
- This algorithms creates a points layer, with points distributed along the lines of an input vector layer. the distance between points (measured along the line) is defined as a parameter.
+ This algorithm creates a points layer, with points distributed along the lines of an input vector layer. the distance between points (measured along the line) is defined as a parameter.
Start and end points can be defined, so the first and last point do not fall on the line first and last node. Start and end points are defined as distances, mesaureed from the first and last nodes of the lines, in the units of the projection used by the lines layer.
@@ -128,7 +134,7 @@ qgis:dissolve: >
This algorithm takes a polygon vector layer and dissolve adjacent polygons into single geometries. An attribute can be specified to dissolve only polygons belonging to the same class (having the same value for the specified attribute), or all polygons can be dissolved, considering only their geometries.
qgis:distancematrix: >
- This algorithms creates a table containing a distance matrix, with distances between all the points in a points layer.
+ This algorithm creates a table containing a distance matrix, with distances between all the points in a points layer.
qgis:distancetonearesthub: >
@@ -147,10 +153,10 @@ qgis:exportaddgeometrycolumns: >
Depending on the geometry type of the vector layer, the attributes added to the table will be different.
qgis:extractbyattribute: >
- This algorithms creates new vector layer that only contain certain features from an input layer. The criteria for adding features to the resulting layer is defined based on the values of an attribute from the input layer.
+ This algorithm creates new vector layer that only contain certain features from an input layer. The criteria for adding features to the resulting layer is defined based on the values of an attribute from the input layer.
qgis:extractbylocation: >
- This algorithms creates new vector layer that only contain certain features from an input layer. The criteria for adding features to the resulting layer is defined based on the spatial relationship between each feature and the features in an additional layer.
+ This algorithm creates new vector layer that only contain certain features from an input layer. The criteria for adding features to the resulting layer is defined based on the spatial relationship between each feature and the features in an additional layer.
qgis:extractnodes: >
This algorithm takes a line or polygon layer and generates a point layer with points representing the nodes in the input lines or polygons. The attributes associated to each point are the same ones associated to the line or polygon that the point belongs to.
@@ -162,7 +168,7 @@ qgis:fixeddistancebuffer: >
This algorithm computes a buffer area for all the features in an input layer, using a fixed distance.
qgis:frequencyanalysis: >
- This algorithms generates a table with frequency analysis of the values of a selected attribute from an input vector layer
+ This algorithm generates a table with frequency analysis of the values of a selected attribute from an input vector layer
qgis:generatepointspixelcentroidsalongline:
@@ -177,7 +183,7 @@ qgis:hypsometriccurves: >
This algorithm computes hypsometric curves for an input Digital Elevation Model. Curves are produced as table files in an output folder specified by the user.
qgis:importintopostgis: >
- This algorithms imports a vector layer into a PostGIS database, creating a new table.
+ This algorithm imports a vector layer into a PostGIS database, creating a new table.
Prior to this a connection between QGIS and the PostGIS database has to be created (for example with the DB Manager).
@@ -198,7 +204,7 @@ qgis:joinattributestable: >
The additional attributes and their values are taken from a second vector layer. An attribute is selected in each of them to define the join criteria.
qgis:keepnbiggestparts: >
- This algorithms takes a polygon layer and creates a new polygon layer in which multipart goemetries have been removed, leaving only the n largest (in terms of area) parts
+ This algorithm takes a polygon layer and creates a new polygon layer in which multipart goemetries have been removed, leaving only the n largest (in terms of area) parts
qgis:lineintersections:
This algorithm creates point features where the lines in the Intersect layer intersect the lines in the Input layer.
@@ -225,6 +231,11 @@ qgis:meancoordinates: >
If an attribute is selected in the <Unique ID field> parameters, features will be grouped according to values in this field. Instead of a single point with the center of mass of the whole layer, the output layer will contain a center of mass for the features in each category.
+qgis:mergelines: >
+ This algorithm joins all connected parts of MultiLineString geometries into single LineString geometries.
+
+ If any parts of the input MultiLineString geometries are not connected, the resultant geometry will be a MultiLineString containing any lines which could be merged and any non-connected line parts.
+
qgis:mergevectorlayers: >
This algorithm combines two vector layer of the same geometry type into a single one.
@@ -254,6 +265,10 @@ qgis:orientedminimumboundingbox: >
qgis:pointsdisplacement:
+qgis:pointonsurface: >
+ Returns a point guaranteed to lie on the surface of a geometry.
+
+
qgis:pointslayerfromtable: >
This algorithm generates a points layer based on the values from an input table.
@@ -313,14 +328,13 @@ qgis:randompointsinlayerbounds: >
This algorithm creates a new point layer with a given number of random points, all of them within the extent of a given layer. A distance factor can be specified, to avoid points being too close to each other.
qgis:randompointsinsidepolygonsfixed: >
- This algorithms creates a new point layer with random points insides the ppolygons of a given layer. The number of points in each polygon can be defined as a fixed count or as a density value, and it will be the same for all polygons.
+ This algorithm creates a new point layer with random points insides the ppolygons of a given layer. The number of points in each polygon can be defined as a fixed count or as a density value, and it will be the same for all polygons.
qgis:randompointsinsidepolygonsvariable: >
This algorithm creates a new point layer with random points insides the ppolygons of a given layer. The number of points in each polygon can be defined as a fixed count or as a density value. The count/density valu is taken from an attribute, so it can be different for each polygons in the input layer.
qgis:randomselection: >
This algorithm takes a vector layer and selects a subset of its features. No new layer is generated by this algorithm.
-
The subset is defined randomly, using a percentage or count value to define the total number of features in the subset.
qgis:randomselectionwithinsubsets: >
@@ -341,12 +355,14 @@ qgis:rasterlayerstatistics: >
The raster layer must have a single band.
qgis:refactorfields: >
- This algorithms allows editing the structure of the attributes table of a vector layer. Fields can be modified in their type and name, using a fields mapping
+ This algorithm allows editing the structure of the attributes table of a vector layer. Fields can be modified in their type and name, using a fields mapping
The original layer is not modified. A new layer is generated, which contains a modified attributes table, accordint to the provided fields mapping
qgis:regularpoints:
+qgis:removenullgeometries: >
+ This algorithm removes any features which do not have a geometry from a vector layer. All other features will be copied unchanged.
qgis:reprojectlayer: >
This algorithm reprojects a vector layer. It creates a new layer with the same features as the input one, but with geometries reprojected to a new CRS.
@@ -359,26 +375,26 @@ qgis:saveselectedfeatures: >
If the selected layer has no selected features, all features will be added to the resulting feature.
qgis:selectbyattribute: >
- This algorithms creates a selection in a vector layer. The criteria for selected features is defined based on the values of an attribute from the input layer.
+ This algorithm creates a selection in a vector layer. The criteria for selected features is defined based on the values of an attribute from the input layer.
qgis:selectbyattributesum:
qgis:selectbyexpression: >
- This algorithms creates a selection in a vector layer. The criteria for selecting features is based on a QGIS expression.
+ This algorithm creates a selection in a vector layer. The criteria for selecting features is based on a QGIS expression.
For more information about expressions see the<a href ="{qgisdocs}/user_manual/working_with_vector/expression.html">user manual</a>
qgis:selectbylocation: >
- This algorithms creates creates a selection in a vector layer. The criteria for selecting features is based on the spatial relationship between each feature and the features in an additional layer.
+ This algorithm creates creates a selection in a vector layer. The criteria for selecting features is based on the spatial relationship between each feature and the features in an additional layer.
qgis:setstyleforrasterlayer: >
- This algorithms sets the style of a raster layer. The style must be defined in a QML file.
+ This algorithm sets the style of a raster layer. The style must be defined in a QML file.
qgis:setstyleforvectorlayer: >
- This algorithms sets the style of a vector layer. The style must be defined in a QML file.
+ This algorithm sets the style of a vector layer. The style must be defined in a QML file.
qgis:simplifygeometries: >
This algorithm simplifies the geometries in a line or polygon layer. It creates a new layer with the same features as the ones in the input layer, but with geometries containing a lower number of vertices.
diff --git a/python/plugins/processing/algs/help/saga.yaml b/python/plugins/processing/algs/help/saga.yaml
new file mode 100644
index 0000000..8068ccb
--- /dev/null
+++ b/python/plugins/processing/algs/help/saga.yaml
@@ -0,0 +1,48 @@
+saga:rastercalculator: >
+ This algorithm allows to perform algebraic operations on raster layers
+
+ It requires a base layer, and a set of additional layers. The base layer is identified as "a" in the formula, while the additional layers are identified as "b, c, d...", using the order in which they appear in the multiple selection dialog.
+
+ The resulting layer has the extent and cellsize of the main layer.
+
+ The following operators and functions are available.
+
+ - Addition (+)
+
+ - Subtraction ( - )
+
+ - Multiplication (*)
+
+ - Division (/)
+
+ - Power (^)
+
+ - ln(x): returns natural logarithm of x.
+
+ - sin(x): returns the sine of x. x must be in radians
+
+ - cos(x): returns the cosine of x. x must be in radians
+
+ - cos(x): returns the tangente of x. x must be in radians
+
+ - asin(x): returns the arcsine of x, in radians
+
+ - acos(x): returns the arccosine of x, in radians
+
+ - atan(x): returns the arctangent of x, in radians
+
+ - atan2(x,y): returns the arctangent y/x, in radians
+
+ - abs(x): return the absolute value of x. abs(- 5)=5
+
+ - int(x): returns the integer part of x. int(5.4)=5
+
+ - mod(x,y): returns the modulus of x/y. mod(7,4)=3
+
+ - gt(x,y): true if x is greater than y
+
+ - lt(x,y): true if x is lower than y
+
+ - eq(x,y): true if x equals y. When using this function SAGA evaluates it in a per–cell basis. Therefore, eq(a,b) will not return 1 if grid a equals grid b. It will return 1 for those cells that have the same value in both grids, and zero otherwise.
+
+ - ifelse(condition, x, y) returns x if condition evaluates to true (condition=1) or y if it evaluates to false
\ No newline at end of file
diff --git a/python/plugins/processing/algs/qgis/Boundary.py b/python/plugins/processing/algs/qgis/Boundary.py
new file mode 100644
index 0000000..079cacd
--- /dev/null
+++ b/python/plugins/processing/algs/qgis/Boundary.py
@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ Boundary.py
+ --------------
+ Date : July 2016
+ Copyright : (C) 2016 by Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Nyall Dawson'
+__date__ = 'July 2016'
+__copyright__ = '(C) 2016, Nyall Dawson'
+
+# This will get replaced with a git SHA1 when you do a git archive323
+
+__revision__ = '$Format:%H$'
+
+import os
+
+from qgis.core import QgsGeometry, QGis
+
+from qgis.PyQt.QtGui import QIcon
+
+from processing.core.GeoAlgorithm import GeoAlgorithm
+from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
+from processing.core.parameters import ParameterVector
+from processing.core.outputs import OutputVector
+from processing.tools import dataobjects, vector
+
+pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
+
+
+class Boundary(GeoAlgorithm):
+
+ INPUT_LAYER = 'INPUT_LAYER'
+ OUTPUT_LAYER = 'OUTPUT_LAYER'
+
+ def getIcon(self):
+ return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'convex_hull.png'))
+
+ def defineCharacteristics(self):
+ self.name, self.i18n_name = self.trAlgorithm('Boundary')
+ self.group, self.i18n_group = self.trAlgorithm('Vector geometry tools')
+
+ self.addParameter(ParameterVector(self.INPUT_LAYER,
+ self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_LINE,
+ ParameterVector.VECTOR_TYPE_POLYGON]))
+ self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Boundary')))
+
+ def processAlgorithm(self, progress):
+ layer = dataobjects.getObjectFromUri(
+ self.getParameterValue(self.INPUT_LAYER))
+
+ if layer.geometryType() == QGis.Line:
+ output_wkb = QGis.WKBMultiPoint
+ elif layer.geometryType() == QGis.Polygon:
+ output_wkb = QGis.WKBLineString
+
+ writer = self.getOutputFromName(
+ self.OUTPUT_LAYER).getVectorWriter(
+ layer.fields(),
+ output_wkb,
+ layer.crs())
+
+ features = vector.features(layer)
+ total = 100.0 / len(features)
+
+ for current, input_feature in enumerate(features):
+ output_feature = input_feature
+ if input_feature.constGeometry():
+ input_geometry = QgsGeometry(input_feature.geometry())
+ output_geometry = QgsGeometry(input_geometry.geometry().boundary())
+ if not output_geometry:
+ raise GeoAlgorithmExecutionException(
+ self.tr('Error calculating boundary'))
+
+ output_feature.setGeometry(output_geometry)
+
+ writer.addFeature(output_feature)
+ progress.setPercentage(int(current * total))
+
+ del writer
diff --git a/python/plugins/processing/algs/qgis/BoundingBox.py b/python/plugins/processing/algs/qgis/BoundingBox.py
new file mode 100644
index 0000000..e5a0ce1
--- /dev/null
+++ b/python/plugins/processing/algs/qgis/BoundingBox.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ BoundingBox.py
+ --------------
+ Date : July 2016
+ Copyright : (C) 2016 by Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Nyall Dawson'
+__date__ = 'July 2016'
+__copyright__ = '(C) 2016, Nyall Dawson'
+
+# This will get replaced with a git SHA1 when you do a git archive323
+
+__revision__ = '$Format:%H$'
+
+import os
+
+from qgis.core import QgsGeometry, QGis
+
+from qgis.PyQt.QtGui import QIcon
+
+from processing.core.GeoAlgorithm import GeoAlgorithm
+from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
+from processing.core.parameters import ParameterVector
+from processing.core.outputs import OutputVector
+from processing.tools import dataobjects, vector
+
+pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
+
+
+class BoundingBox(GeoAlgorithm):
+
+ INPUT_LAYER = 'INPUT_LAYER'
+ OUTPUT_LAYER = 'OUTPUT_LAYER'
+
+ def getIcon(self):
+ return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'matrix.png'))
+
+ def defineCharacteristics(self):
+ self.name, self.i18n_name = self.trAlgorithm('Bounding boxes')
+ self.group, self.i18n_group = self.trAlgorithm('Vector geometry tools')
+
+ self.addParameter(ParameterVector(self.INPUT_LAYER,
+ self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_ANY]))
+ self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Bounds')))
+
+ def processAlgorithm(self, progress):
+ layer = dataobjects.getObjectFromUri(
+ self.getParameterValue(self.INPUT_LAYER))
+
+ writer = self.getOutputFromName(
+ self.OUTPUT_LAYER).getVectorWriter(
+ layer.fields().toList(),
+ QGis.WKBPolygon,
+ layer.crs())
+
+ features = vector.features(layer)
+ total = 100.0 / len(features)
+
+ for current, input_feature in enumerate(features):
+ output_feature = input_feature
+ if input_feature.constGeometry():
+ input_geometry = QgsGeometry(input_feature.constGeometry())
+ output_geometry = QgsGeometry.fromRect(input_geometry.boundingBox())
+ if not output_geometry:
+ raise GeoAlgorithmExecutionException(
+ self.tr('Error calculating bounding box'))
+
+ output_feature.setGeometry(output_geometry)
+
+ writer.addFeature(output_feature)
+ progress.setPercentage(int(current * total))
+
+ del writer
diff --git a/python/plugins/processing/algs/qgis/Buffer.py b/python/plugins/processing/algs/qgis/Buffer.py
index db55b0d..433ae2f 100644
--- a/python/plugins/processing/algs/qgis/Buffer.py
+++ b/python/plugins/processing/algs/qgis/Buffer.py
@@ -57,8 +57,11 @@ def buffering(progress, writer, distance, field, useField, layer, dissolve,
value = distance
inGeom = QgsGeometry(inFeat.geometry())
- if inGeom.isGeosEmpty() or not inGeom.isGeosValid():
- ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Feature {} has empty or invalid geometry. Skipping...'.format(inFeat.id()))
+ if inGeom.isGeosEmpty():
+ ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Feature {} has empty geometry. Skipping...'.format(inFeat.id()))
+ continue
+ if not inGeom.isGeosValid():
+ ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Feature {} has invalid geometry. Skipping...'.format(inFeat.id()))
continue
outGeom = inGeom.buffer(float(value), segments)
if first:
@@ -82,8 +85,11 @@ def buffering(progress, writer, distance, field, useField, layer, dissolve,
else:
value = distance
inGeom = QgsGeometry(inFeat.geometry())
- if inGeom.isGeosEmpty() or not inGeom.isGeosValid():
- ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Feature {} has empty or invalid geometry. Skipping...'.format(inFeat.id()))
+ if inGeom.isGeosEmpty():
+ ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Feature {} has empty geometry. Skipping...'.format(inFeat.id()))
+ continue
+ if not inGeom.isGeosValid():
+ ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Feature {} has invalid geometry. Skipping...'.format(inFeat.id()))
continue
outGeom = inGeom.buffer(float(value), segments)
diff --git a/python/plugins/processing/algs/qgis/Clip.py b/python/plugins/processing/algs/qgis/Clip.py
index 6a492d1..b9f13f0 100644
--- a/python/plugins/processing/algs/qgis/Clip.py
+++ b/python/plugins/processing/algs/qgis/Clip.py
@@ -60,77 +60,96 @@ class Clip(GeoAlgorithm):
self.addOutput(OutputVector(Clip.OUTPUT, self.tr('Clipped')))
def processAlgorithm(self, progress):
- layerA = dataobjects.getObjectFromUri(
+ source_layer = dataobjects.getObjectFromUri(
self.getParameterValue(Clip.INPUT))
- layerB = dataobjects.getObjectFromUri(
+ mask_layer = dataobjects.getObjectFromUri(
self.getParameterValue(Clip.OVERLAY))
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
- layerA.pendingFields(),
- layerA.dataProvider().geometryType(),
- layerA.dataProvider().crs())
-
- inFeatA = QgsFeature()
- inFeatB = QgsFeature()
- outFeat = QgsFeature()
-
- index = vector.spatialindex(layerB)
-
- selectionA = vector.features(layerA)
-
- total = 100.0 / len(selectionA)
-
- for current, inFeatA in enumerate(selectionA):
- geom = QgsGeometry(inFeatA.geometry())
- attrs = inFeatA.attributes()
- intersects = index.intersects(geom.boundingBox())
- first = True
- found = False
- if len(intersects) > 0:
- for i in intersects:
- layerB.getFeatures(
- QgsFeatureRequest().setFilterFid(i)).nextFeature(
- inFeatB)
- tmpGeom = QgsGeometry(inFeatB.geometry())
- if tmpGeom.intersects(geom):
- found = True
- if first:
- outFeat.setGeometry(QgsGeometry(tmpGeom))
- first = False
- else:
- cur_geom = QgsGeometry(outFeat.geometry())
- new_geom = QgsGeometry(cur_geom.combine(tmpGeom))
- if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
- ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
- self.tr('GEOS geoprocessing error: One or '
- 'more input features have invalid '
- 'geometry.'))
- break
-
- outFeat.setGeometry(QgsGeometry(new_geom))
- if found:
- cur_geom = QgsGeometry(outFeat.geometry())
- new_geom = QgsGeometry(geom.intersection(cur_geom))
+ source_layer.fields(),
+ QgsWKBTypes.multiType(QGis.fromOldWkbType(source_layer.wkbType())),
+ source_layer.crs())
+
+ # first build up a list of clip geometries
+ clip_geoms = []
+ for maskFeat in vector.features(mask_layer, QgsFeatureRequest().setSubsetOfAttributes([])):
+ clip_geoms.append(QgsGeometry(maskFeat.constGeometry()))
+
+ # are we clipping against a single feature? if so, we can show finer progress reports
+ if len(clip_geoms) > 1:
+ combined_clip_geom = QgsGeometry.unaryUnion(clip_geoms)
+ single_clip_feature = False
+ else:
+ combined_clip_geom = clip_geoms[0]
+ single_clip_feature = True
+
+ # use prepared geometries for faster intersection tests
+ engine = QgsGeometry.createGeometryEngine(combined_clip_geom.geometry())
+ engine.prepareGeometry()
+
+ tested_feature_ids = set()
+
+ for i, clip_geom in enumerate(clip_geoms):
+ input_features = [f for f in vector.features(source_layer, QgsFeatureRequest().setFilterRect(clip_geom.boundingBox()))]
+
+ if not input_features:
+ continue
+
+ if single_clip_feature:
+ total = 100.0 / len(input_features)
+ else:
+ total = 0
+
+ for current, in_feat in enumerate(input_features):
+ if not in_feat.constGeometry():
+ continue
+
+ if in_feat.id() in tested_feature_ids:
+ # don't retest a feature we have already checked
+ continue
+
+ tested_feature_ids.add(in_feat.id())
+
+ if not engine.intersects(in_feat.constGeometry().geometry()):
+ continue
+
+ if not engine.contains(in_feat.constGeometry().geometry()):
+ cur_geom = QgsGeometry(in_feat.constGeometry())
+ new_geom = combined_clip_geom.intersection(cur_geom)
if new_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(new_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
- int_com = QgsGeometry(geom.combine(cur_geom))
- int_sym = QgsGeometry(geom.symDifference(cur_geom))
- new_geom = QgsGeometry(int_com.difference(int_sym))
- if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
+ int_com = in_feat.constGeometry().combine(new_geom)
+ int_sym = in_feat.constGeometry().symDifference(new_geom)
+ if not int_com or not int_sym:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('GEOS geoprocessing error: One or more '
'input features have invalid geometry.'))
- continue
- try:
- outFeat.setGeometry(new_geom)
- outFeat.setAttributes(attrs)
- writer.addFeature(outFeat)
- except:
- ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
- self.tr('Feature geometry error: One or more '
- 'output features ignored due to '
- 'invalid geometry.'))
- continue
-
- progress.setPercentage(int(current * total))
+ else:
+ new_geom = int_com.difference(int_sym)
+ if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
+ ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
+ self.tr('GEOS geoprocessing error: One or more '
+ 'input features have invalid geometry.'))
+ else:
+ # clip geometry totally contains feature geometry, so no need to perform intersection
+ new_geom = QgsGeometry(in_feat.constGeometry())
+
+ try:
+ out_feat = QgsFeature()
+ out_feat.setGeometry(new_geom)
+ out_feat.setAttributes(in_feat.attributes())
+ writer.addFeature(out_feat)
+ except:
+ ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
+ self.tr('Feature geometry error: One or more '
+ 'output features ignored due to '
+ 'invalid geometry.'))
+ continue
+
+ if single_clip_feature:
+ progress.setPercentage(int(current * total))
+
+ if not single_clip_feature:
+ # coarse progress report for multiple clip geometries
+ progress.setPercentage(100.0 * i / len(clip_geoms))
del writer
diff --git a/python/plugins/processing/algs/qgis/Difference.py b/python/plugins/processing/algs/qgis/Difference.py
index 56f38a1..93a3225 100644
--- a/python/plugins/processing/algs/qgis/Difference.py
+++ b/python/plugins/processing/algs/qgis/Difference.py
@@ -68,7 +68,7 @@ class Difference(GeoAlgorithm):
self.getParameterValue(Difference.OVERLAY))
ignoreInvalid = self.getParameterValue(Difference.IGNORE_INVALID)
- geomType = layerA.wkbType()
+ geomType = QgsWKBTypes.multiType(QGis.fromOldWkbType(layerA.wkbType()))
writer = self.getOutputFromName(
Difference.OUTPUT).getVectorWriter(layerA.pendingFields(),
geomType,
diff --git a/python/plugins/processing/algs/qgis/Dissolve.py b/python/plugins/processing/algs/qgis/Dissolve.py
index 1b12e14..449244a 100644
--- a/python/plugins/processing/algs/qgis/Dissolve.py
+++ b/python/plugins/processing/algs/qgis/Dissolve.py
@@ -26,6 +26,7 @@ __copyright__ = '(C) 2012, Victor Olaya'
__revision__ = '$Format:%H$'
import os
+from collections import defaultdict
from qgis.PyQt.QtGui import QIcon
@@ -36,7 +37,7 @@ from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterBoolean
-from processing.core.parameters import ParameterTableField
+from processing.core.parameters import ParameterTableMultipleField
from processing.core.outputs import OutputVector
from processing.tools import vector, dataobjects
@@ -60,14 +61,14 @@ class Dissolve(GeoAlgorithm):
self.tr('Input layer'),
[ParameterVector.VECTOR_TYPE_POLYGON, ParameterVector.VECTOR_TYPE_LINE]))
self.addParameter(ParameterBoolean(Dissolve.DISSOLVE_ALL,
- self.tr('Dissolve all (do not use field)'), True))
- self.addParameter(ParameterTableField(Dissolve.FIELD,
- self.tr('Unique ID field'), Dissolve.INPUT, optional=True))
+ self.tr('Dissolve all (do not use fields)'), True))
+ self.addParameter(ParameterTableMultipleField(Dissolve.FIELD,
+ self.tr('Unique ID fields'), Dissolve.INPUT, optional=True))
self.addOutput(OutputVector(Dissolve.OUTPUT, self.tr('Dissolved')))
def processAlgorithm(self, progress):
useField = not self.getParameterValue(Dissolve.DISSOLVE_ALL)
- fieldname = self.getParameterValue(Dissolve.FIELD)
+ field_names = self.getParameterValue(Dissolve.FIELD)
vlayerA = dataobjects.getObjectFromUri(
self.getParameterValue(Dissolve.INPUT))
fields = vlayerA.fields()
@@ -85,7 +86,7 @@ class Dissolve(GeoAlgorithm):
progress.setPercentage(int(current * total))
if first:
attrs = inFeat.attributes()
- tmpInGeom = inFeat.geometry()
+ tmpInGeom = QgsGeometry(inFeat.geometry())
if tmpInGeom.isGeosEmpty():
continue
errors = tmpInGeom.validateGeometry()
@@ -101,10 +102,8 @@ class Dissolve(GeoAlgorithm):
outFeat.setGeometry(tmpInGeom)
first = False
else:
- tmpInGeom = inFeat.geometry()
- if tmpInGeom is None or tmpInGeom.isGeosEmpty():
- ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
- self.tr('Skipped feature %i, which has a null geometry' % current))
+ tmpInGeom = QgsGeometry(inFeat.geometry())
+ if tmpInGeom.isGeosEmpty():
continue
tmpOutGeom = QgsGeometry(outFeat.geometry())
errors = tmpInGeom.validateGeometry()
@@ -118,48 +117,27 @@ class Dissolve(GeoAlgorithm):
+ error.what())
continue
try:
- tmpOutGeom = tmpOutGeom.combine(tmpInGeom)
- if tmpOutGeom is None or tmpOutGeom.isGeosEmpty():
- ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
- self.tr('Skipped feature %i. Dissolve resulted in null geometry' % current))
- continue
- errors = tmpOutGeom.validateGeometry()
- if errors:
- for error in errors:
- ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
- self.tr('ValidateGeometry()'
- 'error:One or more input'
- 'features have invalid '
- 'geometry: ')
- + error.what())
- continue
+ tmpOutGeom = QgsGeometry(tmpOutGeom.combine(tmpInGeom))
outFeat.setGeometry(tmpOutGeom)
except:
- raise
raise GeoAlgorithmExecutionException(
self.tr('Geometry exception while dissolving'))
- print outFeat.geometry().exportToWkt()
outFeat.setAttributes(attrs)
writer.addFeature(outFeat)
else:
- fieldIdx = vlayerA.fieldNameIndex(fieldname)
- unique = vector.getUniqueValues(vlayerA, int(fieldIdx))
- nFeat = len(unique)
- myDict = {}
- attrDict = {}
- for item in unique:
- myDict[unicode(item).strip()] = []
- attrDict[unicode(item).strip()] = None
+ field_indexes = [vlayerA.fieldNameIndex(f) for f in field_names.split(';')]
- unique = None
+ attribute_dict = {}
+ geometry_dict = defaultdict(lambda: [])
- for current, inFeat in enumerate(features):
+ for inFeat in features:
attrs = inFeat.attributes()
- tempItem = attrs[fieldIdx]
- tmpInGeom = inFeat.geometry()
- if tmpInGeom is None or tmpInGeom.isGeosEmpty():
- ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
- self.tr('Skipped feature %i, which has a null geometry' % current))
+
+ index_attrs = tuple([attrs[i] for i in field_indexes])
+
+ tmpInGeom = QgsGeometry(inFeat.geometry())
+ if tmpInGeom.isGeosEmpty():
+ continue
errors = tmpInGeom.validateGeometry()
if len(errors) != 0:
for error in errors:
@@ -170,16 +148,17 @@ class Dissolve(GeoAlgorithm):
'geometry: ')
+ error.what())
- if attrDict[unicode(tempItem).strip()] is None:
+ if not index_attrs in attribute_dict:
# keep attributes of first feature
- attrDict[unicode(tempItem).strip()] = attrs
+ attribute_dict[index_attrs] = attrs
- myDict[unicode(tempItem).strip()].append(tmpInGeom)
+ geometry_dict[index_attrs].append(tmpInGeom)
- features = None
+ nFeat = len(attribute_dict)
nElement = 0
- for key, value in myDict.items():
+ for key, value in geometry_dict.items():
+ outFeat = QgsFeature()
nElement += 1
progress.setPercentage(int(nElement * 100 / nFeat))
try:
@@ -188,7 +167,7 @@ class Dissolve(GeoAlgorithm):
raise GeoAlgorithmExecutionException(
self.tr('Geometry exception while dissolving'))
outFeat.setGeometry(tmpOutGeom)
- outFeat.setAttributes(attrDict[key])
+ outFeat.setAttributes(attribute_dict[key])
writer.addFeature(outFeat)
del writer
diff --git a/python/plugins/processing/algs/qgis/Eliminate.py b/python/plugins/processing/algs/qgis/Eliminate.py
index 60e9601..634b1db 100644
--- a/python/plugins/processing/algs/qgis/Eliminate.py
+++ b/python/plugins/processing/algs/qgis/Eliminate.py
@@ -28,7 +28,7 @@ __revision__ = '$Format:%H$'
import os
from qgis.PyQt.QtGui import QIcon
-from qgis.PyQt.QtCore import QLocale, QDate
+from qgis.PyQt.QtCore import QLocale, QDate, QVariant
from qgis.core import QgsFeatureRequest, QgsFeature, QgsGeometry
@@ -113,26 +113,26 @@ class Eliminate(GeoAlgorithm):
selectType = processLayer.fields()[selectindex].type()
selectionError = False
- if selectType == 2:
+ if selectType in [QVariant.Int, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]:
try:
y = int(comparisonvalue)
except ValueError:
selectionError = True
msg = self.tr('Cannot convert "%s" to integer' % unicode(comparisonvalue))
- elif selectType == 6:
+ elif selectType == QVariant.Double:
try:
y = float(comparisonvalue)
except ValueError:
selectionError = True
msg = self.tr('Cannot convert "%s" to float' % unicode(comparisonvalue))
- elif selectType == 10:
+ elif selectType == QVariant.String:
# 10: string, boolean
try:
y = unicode(comparisonvalue)
except ValueError:
selectionError = True
msg = self.tr('Cannot convert "%s" to unicode' % unicode(comparisonvalue))
- elif selectType == 14:
+ elif selectType == QVariant.Date:
# date
dateAndFormat = comparisonvalue.split(' ')
@@ -157,7 +157,7 @@ class Eliminate(GeoAlgorithm):
msg += self.tr('Enter the date and the date format, e.g. "07.26.2011" "MM.dd.yyyy".')
if (comparison == 'begins with' or comparison == 'contains') \
- and selectType != 10:
+ and selectType != QVariant.String:
selectionError = True
msg = self.tr('"%s" can only be used with string fields' % comparison)
@@ -173,14 +173,14 @@ class Eliminate(GeoAlgorithm):
if aValue is None:
continue
- if selectType == 2:
+ if selectType in [QVariant.Int, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]:
x = int(aValue)
- elif selectType == 6:
+ elif selectType == QVariant.Double:
x = float(aValue)
- elif selectType == 10:
+ elif selectType == QVariant.String:
# 10: string, boolean
x = unicode(aValue)
- elif selectType == 14:
+ elif selectType == QVariant.Date:
# date
x = aValue # should be date
diff --git a/python/plugins/processing/algs/qgis/ImportIntoPostGIS.py b/python/plugins/processing/algs/qgis/ImportIntoPostGIS.py
index 4a02307..1547065 100644
--- a/python/plugins/processing/algs/qgis/ImportIntoPostGIS.py
+++ b/python/plugins/processing/algs/qgis/ImportIntoPostGIS.py
@@ -94,7 +94,7 @@ class ImportIntoPostGIS(GeoAlgorithm):
convertLowerCase = self.getParameterValue(self.LOWERCASE_NAMES)
dropStringLength = self.getParameterValue(self.DROP_STRING_LENGTH)
forceSinglePart = self.getParameterValue(self.FORCE_SINGLEPART)
- primaryKeyField = self.getParameterValue(self.PRIMARY_KEY)
+ primaryKeyField = self.getParameterValue(self.PRIMARY_KEY) or 'id'
encoding = self.getParameterValue(self.ENCODING)
layerUri = self.getParameterValue(self.INPUT)
@@ -103,6 +103,7 @@ class ImportIntoPostGIS(GeoAlgorithm):
table = self.getParameterValue(self.TABLENAME).strip()
if table == '':
table = layer.name()
+ table = "_".join(table.split(".")[:-1])
table = table.replace(' ', '').lower()[0:62]
providerName = 'postgres'
@@ -126,10 +127,7 @@ class ImportIntoPostGIS(GeoAlgorithm):
geomColumn = None
uri = db.uri
- if primaryKeyField:
- uri.setDataSource(schema, table, geomColumn, '', primaryKeyField)
- else:
- uri.setDataSource(schema, table, geomColumn, '')
+ uri.setDataSource(schema, table, geomColumn, '', primaryKeyField)
if encoding:
layer.setProviderEncoding(encoding)
diff --git a/python/plugins/processing/algs/qgis/Intersection.py b/python/plugins/processing/algs/qgis/Intersection.py
index f74375a..39ccc3f 100644
--- a/python/plugins/processing/algs/qgis/Intersection.py
+++ b/python/plugins/processing/algs/qgis/Intersection.py
@@ -34,7 +34,7 @@ from qgis.core import QGis, QgsFeatureRequest, QgsFeature, QgsGeometry, QgsWKBTy
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.ProcessingLog import ProcessingLog
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
-from processing.core.parameters import ParameterVector
+from processing.core.parameters import ParameterVector, ParameterBoolean
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector
@@ -54,6 +54,7 @@ class Intersection(GeoAlgorithm):
INPUT = 'INPUT'
INPUT2 = 'INPUT2'
+ IGNORE_NULL = 'IGNORE_NULL'
OUTPUT = 'OUTPUT'
def getIcon(self):
@@ -66,6 +67,9 @@ class Intersection(GeoAlgorithm):
self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterVector(self.INPUT2,
self.tr('Intersect layer'), [ParameterVector.VECTOR_TYPE_ANY]))
+ self.addParameter(ParameterBoolean(Intersection.IGNORE_NULL,
+ self.tr('Ignore NULL geometries'),
+ False, True))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Intersection')))
def processAlgorithm(self, progress):
@@ -73,8 +77,9 @@ class Intersection(GeoAlgorithm):
self.getParameterValue(self.INPUT))
vlayerB = dataobjects.getObjectFromUri(
self.getParameterValue(self.INPUT2))
+ ignoreNull = self.getParameterValue(Intersection.IGNORE_NULL)
- geomType = vlayerA.wkbType()
+ geomType = QgsWKBTypes.multiType(QGis.fromOldWkbType(vlayerA.wkbType()))
fields = vector.combineVectorFields(vlayerA, vlayerB)
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields,
geomType, vlayerA.crs())
@@ -84,13 +89,30 @@ class Intersection(GeoAlgorithm):
total = 100.0 / len(selectionA)
for current, inFeatA in enumerate(selectionA):
progress.setPercentage(int(current * total))
- geom = QgsGeometry(inFeatA.geometry())
+ geom = inFeatA.geometry()
+ if not geom:
+ if ignoreNull:
+ continue
+ else:
+ raise GeoAlgorithmExecutionException(
+ self.tr('Input layer A contains NULL geometries. Please check "Ignore NULL geometries" if you want to run this algorithm anyway.'))
+ if not geom.isGeosValid():
+ raise GeoAlgorithmExecutionException(
+ self.tr('Input layer A contains invalid geometries (Feature {}). Unable to complete intersection algorithm.'.format(inFeatA.id())))
atMapA = inFeatA.attributes()
intersects = index.intersects(geom.boundingBox())
- for i in intersects:
- request = QgsFeatureRequest().setFilterFid(i)
- inFeatB = vlayerB.getFeatures(request).next()
+ for inFeatB in vlayerB.getFeatures(QgsFeatureRequest().setFilterFids(intersects)):
tmpGeom = QgsGeometry(inFeatB.geometry())
+ if not geom:
+ if ignoreNull:
+ continue
+ else:
+ raise GeoAlgorithmExecutionException(
+ self.tr('Input layer B contains NULL geometries. Please check "Ignore NULL geometries" if you want to run this algorithm anyway.'))
+ if not geom.isGeosValid():
+ raise GeoAlgorithmExecutionException(
+ self.tr('Input layer B contains invalid geometries (Feature {}). Unable to complete intersection algorithm.'.format(inFeatB.id())))
+
if geom.intersects(tmpGeom):
atMapB = inFeatB.attributes()
int_geom = QgsGeometry(geom.intersection(tmpGeom))
diff --git a/python/plugins/processing/algs/qgis/MergeLines.py b/python/plugins/processing/algs/qgis/MergeLines.py
new file mode 100644
index 0000000..fe1c08a
--- /dev/null
+++ b/python/plugins/processing/algs/qgis/MergeLines.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ Smooth.py
+ ---------
+ Date : July 2016
+ Copyright : (C) 2016 by Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Nyall Dawson'
+__date__ = 'July 2016'
+__copyright__ = '(C) 2016, Nyall Dawson'
+
+# This will get replaced with a git SHA1 when you do a git archive323
+
+__revision__ = '$Format:%H$'
+
+import os
+
+from qgis.core import QgsFeature, QgsGeometry
+
+from qgis.PyQt.QtGui import QIcon
+
+from processing.core.GeoAlgorithm import GeoAlgorithm
+from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
+from processing.core.parameters import ParameterVector
+from processing.core.outputs import OutputVector
+from processing.tools import dataobjects, vector
+
+pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
+
+
+class MergeLines(GeoAlgorithm):
+
+ INPUT_LAYER = 'INPUT_LAYER'
+ OUTPUT_LAYER = 'OUTPUT_LAYER'
+
+ def getIcon(self):
+ return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'to_lines.png'))
+
+ def defineCharacteristics(self):
+ self.name, self.i18n_name = self.trAlgorithm('Merge lines')
+ self.group, self.i18n_group = self.trAlgorithm('Vector geometry tools')
+
+ self.addParameter(ParameterVector(self.INPUT_LAYER,
+ self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_LINE]))
+ self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Merged')))
+
+ def processAlgorithm(self, progress):
+ layer = dataobjects.getObjectFromUri(
+ self.getParameterValue(self.INPUT_LAYER))
+
+ writer = self.getOutputFromName(
+ self.OUTPUT_LAYER).getVectorWriter(
+ layer.fields().toList(),
+ layer.wkbType(),
+ layer.crs())
+
+ features = vector.features(layer)
+ total = 100.0 / len(features)
+
+ for current, inFeat in enumerate(features):
+ outFeat = QgsFeature()
+ attrs = inFeat.attributes()
+ outFeat.setAttributes(attrs)
+
+ inGeom = QgsGeometry(inFeat.constGeometry())
+ if inGeom:
+ outGeom = inGeom.mergeLines()
+ if outGeom is None:
+ raise GeoAlgorithmExecutionException(
+ self.tr('Error merging lines'))
+
+ outFeat.setGeometry(outGeom)
+
+ writer.addFeature(outFeat)
+ progress.setPercentage(int(current * total))
+
+ del writer
diff --git a/python/plugins/processing/algs/qgis/MergeLines_BACKUP_1606.py b/python/plugins/processing/algs/qgis/MergeLines_BACKUP_1606.py
new file mode 100644
index 0000000..c3c831e
--- /dev/null
+++ b/python/plugins/processing/algs/qgis/MergeLines_BACKUP_1606.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ Smooth.py
+ ---------
+ Date : July 2016
+ Copyright : (C) 2016 by Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Nyall Dawson'
+__date__ = 'July 2016'
+__copyright__ = '(C) 2016, Nyall Dawson'
+
+# This will get replaced with a git SHA1 when you do a git archive323
+
+__revision__ = '$Format:%H$'
+
+import os
+
+from qgis.core import QgsFeature
+
+from qgis.PyQt.QtGui import QIcon
+
+from processing.core.GeoAlgorithm import GeoAlgorithm
+from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
+from processing.core.parameters import ParameterVector
+from processing.core.outputs import OutputVector
+from processing.tools import dataobjects, vector
+
+pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
+
+
+class MergeLines(GeoAlgorithm):
+
+ INPUT_LAYER = 'INPUT_LAYER'
+ OUTPUT_LAYER = 'OUTPUT_LAYER'
+
+ def getIcon(self):
+ return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'to_lines.png'))
+
+ def defineCharacteristics(self):
+ self.name, self.i18n_name = self.trAlgorithm('Merge lines')
+ self.group, self.i18n_group = self.trAlgorithm('Vector geometry tools')
+
+ self.addParameter(ParameterVector(self.INPUT_LAYER,
+ self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_LINE]))
+ self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Merged')))
+
+ def processAlgorithm(self, progress):
+ layer = dataobjects.getObjectFromUri(
+ self.getParameterValue(self.INPUT_LAYER))
+
+ writer = self.getOutputFromName(
+ self.OUTPUT_LAYER).getVectorWriter(
+ layer.fields().toList(),
+ layer.wkbType(),
+ layer.crs())
+
+ features = vector.features(layer)
+ total = 100.0 / len(features)
+
+ for current, inFeat in enumerate(features):
+ outFeat = QgsFeature()
+ attrs = inFeat.attributes()
+ outFeat.setAttributes(attrs)
+
+ inGeom = inFeat.geometry()
+ if inGeom:
+ outGeom = inGeom.mergeLines()
+ if outGeom is None:
+ raise GeoAlgorithmExecutionException(
+ self.tr('Error merging lines'))
+
+ outFeat.setGeometry(outGeom)
+
+ writer.addFeature(outFeat)
+ progress.setPercentage(int(current * total))
+
+ del writer
diff --git a/python/plugins/processing/algs/qgis/MergeLines_BASE_1606.py b/python/plugins/processing/algs/qgis/MergeLines_BASE_1606.py
new file mode 100644
index 0000000..e3bbe3b
--- /dev/null
+++ b/python/plugins/processing/algs/qgis/MergeLines_BASE_1606.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ Smooth.py
+ ---------
+ Date : July 2016
+ Copyright : (C) 2016 by Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Nyall Dawson'
+__date__ = 'July 2016'
+__copyright__ = '(C) 2016, Nyall Dawson'
+
+# This will get replaced with a git SHA1 when you do a git archive323
+
+__revision__ = '$Format:%H$'
+
+import os
+
+from qgis.core import QgsFeature
+
+from qgis.PyQt.QtGui import QIcon
+
+from processing.core.GeoAlgorithm import GeoAlgorithm
+from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
+from processing.core.parameters import ParameterVector
+from processing.core.outputs import OutputVector
+from processing.tools import dataobjects, vector
+
+pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
+
+
+class MergeLines(GeoAlgorithm):
+
+ INPUT_LAYER = 'INPUT_LAYER'
+ OUTPUT_LAYER = 'OUTPUT_LAYER'
+
+ def getIcon(self):
+ return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'to_lines.png'))
+
+ def defineCharacteristics(self):
+ self.name, self.i18n_name = self.trAlgorithm('Merge lines')
+ self.group, self.i18n_group = self.trAlgorithm('Vector geometry tools')
+
+ self.addParameter(ParameterVector(self.INPUT_LAYER,
+ self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_LINE]))
+ self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Merged')))
+
+ def processAlgorithm(self, progress):
+ layer = dataobjects.getObjectFromUri(
+ self.getParameterValue(self.INPUT_LAYER))
+ provider = layer.dataProvider()
+
+ writer = self.getOutputFromName(
+ self.OUTPUT_LAYER).getVectorWriter(
+ layer.fields().toList(),
+ provider.wkbType(),
+ layer.crs())
+
+ features = vector.features(layer)
+ total = 100.0 / len(features)
+
+ for current, inFeat in enumerate(features):
+ outFeat = QgsFeature()
+ attrs = inFeat.attributes()
+ outFeat.setAttributes(attrs)
+
+ inGeom = inFeat.geometry()
+ if inGeom:
+ outGeom = inGeom.mergeLines()
+ if outGeom is None:
+ raise GeoAlgorithmExecutionException(
+ self.tr('Error merging lines'))
+
+ outFeat.setGeometry(outGeom)
+
+ writer.addFeature(outFeat)
+ progress.setPercentage(int(current * total))
+
+ del writer
diff --git a/python/plugins/processing/algs/qgis/MergeLines_LOCAL_1606.py b/python/plugins/processing/algs/qgis/MergeLines_LOCAL_1606.py
new file mode 100644
index 0000000..e69de29
diff --git a/python/plugins/processing/algs/qgis/MergeLines_REMOTE_1606.py b/python/plugins/processing/algs/qgis/MergeLines_REMOTE_1606.py
new file mode 100644
index 0000000..c3c831e
--- /dev/null
+++ b/python/plugins/processing/algs/qgis/MergeLines_REMOTE_1606.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ Smooth.py
+ ---------
+ Date : July 2016
+ Copyright : (C) 2016 by Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Nyall Dawson'
+__date__ = 'July 2016'
+__copyright__ = '(C) 2016, Nyall Dawson'
+
+# This will get replaced with a git SHA1 when you do a git archive323
+
+__revision__ = '$Format:%H$'
+
+import os
+
+from qgis.core import QgsFeature
+
+from qgis.PyQt.QtGui import QIcon
+
+from processing.core.GeoAlgorithm import GeoAlgorithm
+from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
+from processing.core.parameters import ParameterVector
+from processing.core.outputs import OutputVector
+from processing.tools import dataobjects, vector
+
+pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
+
+
+class MergeLines(GeoAlgorithm):
+
+ INPUT_LAYER = 'INPUT_LAYER'
+ OUTPUT_LAYER = 'OUTPUT_LAYER'
+
+ def getIcon(self):
+ return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'to_lines.png'))
+
+ def defineCharacteristics(self):
+ self.name, self.i18n_name = self.trAlgorithm('Merge lines')
+ self.group, self.i18n_group = self.trAlgorithm('Vector geometry tools')
+
+ self.addParameter(ParameterVector(self.INPUT_LAYER,
+ self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_LINE]))
+ self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Merged')))
+
+ def processAlgorithm(self, progress):
+ layer = dataobjects.getObjectFromUri(
+ self.getParameterValue(self.INPUT_LAYER))
+
+ writer = self.getOutputFromName(
+ self.OUTPUT_LAYER).getVectorWriter(
+ layer.fields().toList(),
+ layer.wkbType(),
+ layer.crs())
+
+ features = vector.features(layer)
+ total = 100.0 / len(features)
+
+ for current, inFeat in enumerate(features):
+ outFeat = QgsFeature()
+ attrs = inFeat.attributes()
+ outFeat.setAttributes(attrs)
+
+ inGeom = inFeat.geometry()
+ if inGeom:
+ outGeom = inGeom.mergeLines()
+ if outGeom is None:
+ raise GeoAlgorithmExecutionException(
+ self.tr('Error merging lines'))
+
+ outFeat.setGeometry(outGeom)
+
+ writer.addFeature(outFeat)
+ progress.setPercentage(int(current * total))
+
+ del writer
diff --git a/python/plugins/processing/algs/qgis/PointOnSurface.py b/python/plugins/processing/algs/qgis/PointOnSurface.py
new file mode 100644
index 0000000..096273f
--- /dev/null
+++ b/python/plugins/processing/algs/qgis/PointOnSurface.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ PointOnSurface.py
+ --------------
+ Date : July 2016
+ Copyright : (C) 2016 by Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Nyall Dawson'
+__date__ = 'July 2016'
+__copyright__ = '(C) 2016, Nyall Dawson'
+
+# This will get replaced with a git SHA1 when you do a git archive323
+
+__revision__ = '$Format:%H$'
+
+import os
+
+from qgis.core import QgsGeometry, QGis
+
+from qgis.PyQt.QtGui import QIcon
+
+from processing.core.GeoAlgorithm import GeoAlgorithm
+from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
+from processing.core.parameters import ParameterVector
+from processing.core.outputs import OutputVector
+from processing.tools import dataobjects, vector
+
+pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
+
+
+class PointOnSurface(GeoAlgorithm):
+
+ INPUT_LAYER = 'INPUT_LAYER'
+ OUTPUT_LAYER = 'OUTPUT_LAYER'
+
+ def defineCharacteristics(self):
+ self.name, self.i18n_name = self.trAlgorithm('Point on surface')
+ self.group, self.i18n_group = self.trAlgorithm('Vector geometry tools')
+
+ self.addParameter(ParameterVector(self.INPUT_LAYER,
+ self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_ANY]))
+ self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Point')))
+
+ def processAlgorithm(self, progress):
+ layer = dataobjects.getObjectFromUri(
+ self.getParameterValue(self.INPUT_LAYER))
+
+ writer = self.getOutputFromName(
+ self.OUTPUT_LAYER).getVectorWriter(
+ layer.fields().toList(),
+ QGis.WKBPoint,
+ layer.crs())
+
+ features = vector.features(layer)
+ total = 100.0 / len(features)
+
+ for current, input_feature in enumerate(features):
+ output_feature = input_feature
+ if input_feature.constGeometry():
+ input_geometry = QgsGeometry(input_feature.geometry())
+ output_geometry = input_geometry.pointOnSurface()
+ if not output_geometry:
+ raise GeoAlgorithmExecutionException(
+ self.tr('Error calculating point on surface'))
+
+ output_feature.setGeometry(output_geometry)
+
+ writer.addFeature(output_feature)
+ progress.setPercentage(int(current * total))
+
+ del writer
diff --git a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
index b802f6c..095f45e 100644
--- a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
+++ b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
@@ -146,6 +146,11 @@ from .SpatialIndex import SpatialIndex
from .DefineProjection import DefineProjection
from .RectanglesOvalsDiamondsVariable import RectanglesOvalsDiamondsVariable
from .RectanglesOvalsDiamondsFixed import RectanglesOvalsDiamondsFixed
+from .MergeLines import MergeLines
+from .BoundingBox import BoundingBox
+from .Boundary import Boundary
+from .PointOnSurface import PointOnSurface
+from .RemoveNullGeometry import RemoveNullGeometry
pluginPath = os.path.normpath(os.path.join(
os.path.split(os.path.dirname(__file__))[0], os.pardir))
@@ -197,7 +202,9 @@ class QGISAlgorithmProvider(AlgorithmProvider):
CheckValidity(), OrientedMinimumBoundingBox(), Smooth(),
ReverseLineDirection(), SpatialIndex(), DefineProjection(),
RectanglesOvalsDiamondsVariable(),
- RectanglesOvalsDiamondsFixed()
+ RectanglesOvalsDiamondsFixed(), MergeLines(),
+ BoundingBox(), Boundary(), PointOnSurface(),
+ RemoveNullGeometry()
]
if hasMatplotlib:
diff --git a/python/plugins/processing/algs/qgis/RemoveNullGeometry.py b/python/plugins/processing/algs/qgis/RemoveNullGeometry.py
new file mode 100644
index 0000000..15b1dc9
--- /dev/null
+++ b/python/plugins/processing/algs/qgis/RemoveNullGeometry.py
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ RemoveNullGeometry.py
+ --------------
+ Date : October 2016
+ Copyright : (C) 2016 by Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Nyall Dawson'
+__date__ = 'October 2016'
+__copyright__ = '(C) 2016, Nyall Dawson'
+
+# This will get replaced with a git SHA1 when you do a git archive323
+
+__revision__ = '$Format:%H$'
+
+from processing.core.GeoAlgorithm import GeoAlgorithm
+from processing.core.parameters import ParameterVector
+from processing.core.outputs import OutputVector
+from processing.tools import dataobjects, vector
+
+
+class RemoveNullGeometry(GeoAlgorithm):
+
+ INPUT_LAYER = 'INPUT_LAYER'
+ OUTPUT_LAYER = 'OUTPUT_LAYER'
+
+ def defineCharacteristics(self):
+ self.name, self.i18n_name = self.trAlgorithm('Remove null geometries')
+ self.group, self.i18n_group = self.trAlgorithm('Vector selection tools')
+
+ self.addParameter(ParameterVector(self.INPUT_LAYER,
+ self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_ANY]))
+ self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Removed null geometry')))
+
+ def processAlgorithm(self, progress):
+ layer = dataobjects.getObjectFromUri(
+ self.getParameterValue(self.INPUT_LAYER))
+ writer = self.getOutputFromName(
+ self.OUTPUT_LAYER).getVectorWriter(
+ layer.fields(),
+ layer.wkbType(),
+ layer.crs())
+
+ features = vector.features(layer)
+ total = 100.0 / len(features)
+
+ for current, input_feature in enumerate(features):
+ if input_feature.constGeometry():
+ writer.addFeature(input_feature)
+
+ progress.setPercentage(int(current * total))
+
+ del writer
diff --git a/python/plugins/processing/algs/qgis/SymmetricalDifference.py b/python/plugins/processing/algs/qgis/SymmetricalDifference.py
index 251b8cc..2282f84 100644
--- a/python/plugins/processing/algs/qgis/SymmetricalDifference.py
+++ b/python/plugins/processing/algs/qgis/SymmetricalDifference.py
@@ -65,7 +65,7 @@ class SymmetricalDifference(GeoAlgorithm):
layerB = dataobjects.getObjectFromUri(
self.getParameterValue(self.OVERLAY))
- geomType = layerA.wkbType()
+ geomType = QgsWKBTypes.multiType(QGis.fromOldWkbType(layerA.wkbType()))
fields = vector.combineVectorFields(layerA, layerB)
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
fields, geomType, layerA.crs())
diff --git a/python/plugins/processing/algs/qgis/Union.py b/python/plugins/processing/algs/qgis/Union.py
index 1fff140..abca9c8 100644
--- a/python/plugins/processing/algs/qgis/Union.py
+++ b/python/plugins/processing/algs/qgis/Union.py
@@ -75,7 +75,7 @@ class Union(GeoAlgorithm):
geomType = vlayerA.wkbType()
fields = vector.combineVectorFields(vlayerA, vlayerB)
writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields,
- geomType, vproviderA.crs())
+ geomType, vlayerA.crs())
inFeatA = QgsFeature()
inFeatB = QgsFeature()
outFeat = QgsFeature()
diff --git a/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py b/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py
index cc0fa6c..ea34618 100644
--- a/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py
+++ b/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py
@@ -89,15 +89,10 @@ class FieldsCalculatorDialog(BASE, WIDGET):
self.builder.loadRecent('fieldcalc')
- self.updateLayer()
+ self.initContext()
- def updateLayer(self):
- self.layer = dataobjects.getObject(self.cmbInputLayer.currentText())
-
- self.builder.setLayer(self.layer)
- self.builder.loadFieldNames()
-
- exp_context = QgsExpressionContext()
+ def initContext(self):
+ exp_context = self.builder.expressionContext()
exp_context.appendScope(QgsExpressionContextUtils.globalScope())
exp_context.appendScope(QgsExpressionContextUtils.projectScope())
exp_context.appendScope(QgsExpressionContextUtils.layerScope(self.layer))
@@ -105,6 +100,10 @@ class FieldsCalculatorDialog(BASE, WIDGET):
exp_context.setHighlightedVariables(["row_number"])
self.builder.setExpressionContext(exp_context)
+ def updateLayer(self):
+ self.layer = dataobjects.getObject(self.cmbInputLayer.currentText())
+ self.builder.setLayer(self.layer)
+ self.builder.loadFieldNames()
self.populateFields()
def setupSpinboxes(self, index):
diff --git a/python/plugins/processing/algs/qgis/ui/FieldsMappingPanel.py b/python/plugins/processing/algs/qgis/ui/FieldsMappingPanel.py
index aa1a3d4..1f64f72 100644
--- a/python/plugins/processing/algs/qgis/ui/FieldsMappingPanel.py
+++ b/python/plugins/processing/algs/qgis/ui/FieldsMappingPanel.py
@@ -32,10 +32,9 @@ from collections import OrderedDict
from qgis.PyQt import uic
from qgis.PyQt.QtGui import QBrush, QIcon
from qgis.PyQt.QtWidgets import QComboBox, QHeaderView, QLineEdit, QMessageBox, QSpinBox, QStyledItemDelegate
-from qgis.PyQt.QtCore import QItemSelectionModel
-from qgis.PyQt.QtCore import QAbstractTableModel, QModelIndex, QVariant, Qt, pyqtSlot
+from qgis.PyQt.QtCore import QItemSelectionModel, QAbstractTableModel, QModelIndex, QVariant, Qt, pyqtSlot
-from qgis.core import QgsExpression
+from qgis.core import QgsExpression, QgsApplication
from qgis.gui import QgsFieldExpressionWidget
from processing.tools import dataobjects
@@ -313,16 +312,11 @@ class FieldsMappingPanel(BASE, WIDGET):
super(FieldsMappingPanel, self).__init__(parent)
self.setupUi(self)
- self.addButton.setIcon(
- QIcon(':/images/themes/default/mActionNewAttribute.png'))
- self.deleteButton.setIcon(
- QIcon(':/images/themes/default/mActionDeleteAttribute.svg'))
- self.upButton.setIcon(
- QIcon(':/images/themes/default/mActionArrowUp.png'))
- self.downButton.setIcon(
- QIcon(':/images/themes/default/mActionArrowDown.png'))
- self.resetButton.setIcon(
- QIcon(':/images/themes/default/mIconClear.png'))
+ self.addButton.setIcon(QgsApplication.getThemeIcon("/mActionNewAttribute.svg"))
+ self.deleteButton.setIcon(QgsApplication.getThemeIcon('/mActionDeleteAttribute.svg'))
+ self.upButton.setIcon(QgsApplication.getThemeIcon('/mActionArrowUp.png'))
+ self.downButton.setIcon(QgsApplication.getThemeIcon('/mActionArrowDown.png'))
+ self.resetButton.setIcon(QgsApplication.getThemeIcon('/mIconClear.svg'))
self.model = FieldsMappingModel()
self.fieldsView.setModel(self.model)
@@ -340,8 +334,8 @@ class FieldsMappingPanel(BASE, WIDGET):
dlg = QMessageBox(self)
dlg.setText("Do you want to reset the field mapping?")
dlg.setStandardButtons(
- QMessageBox.StandardButtons(QMessageBox.Yes
- + QMessageBox.No))
+ QMessageBox.StandardButtons(QMessageBox.Yes |
+ QMessageBox.No))
dlg.setDefaultButton(QMessageBox.No)
if dlg.exec_() == QMessageBox.Yes:
self.on_resetButton_clicked()
@@ -358,10 +352,10 @@ class FieldsMappingPanel(BASE, WIDGET):
self.model.insertRows(rowCount, 1)
index = self.model.index(rowCount, 0)
self.fieldsView.selectionModel().select(index,
- QItemSelectionModel.SelectionFlags(QItemSelectionModel.Clear
- + QItemSelectionModel.Select
- + QItemSelectionModel.Current
- + QItemSelectionModel.Rows))
+ QItemSelectionModel.SelectionFlags(QItemSelectionModel.Clear |
+ QItemSelectionModel.Select |
+ QItemSelectionModel.Current |
+ QItemSelectionModel.Rows))
self.fieldsView.scrollTo(index)
self.fieldsView.scrollTo(index)
@@ -396,10 +390,10 @@ class FieldsMappingPanel(BASE, WIDGET):
self.model.removeRows(row + 1, 1)
sel.select(self.model.index(row - 1, 0),
- QItemSelectionModel.SelectionFlags(QItemSelectionModel.Clear
- + QItemSelectionModel.Select
- + QItemSelectionModel.Current
- + QItemSelectionModel.Rows))
+ QItemSelectionModel.SelectionFlags(QItemSelectionModel.Clear |
+ QItemSelectionModel.Select |
+ QItemSelectionModel.Current |
+ QItemSelectionModel.Rows))
@pyqtSlot(bool, name='on_downButton_clicked')
def on_downButton_clicked(self, checked=False):
@@ -422,10 +416,10 @@ class FieldsMappingPanel(BASE, WIDGET):
self.model.removeRows(row, 1)
sel.select(self.model.index(row + 1, 0),
- QItemSelectionModel.SelectionFlags(QItemSelectionModel.Clear
- + QItemSelectionModel.Select
- + QItemSelectionModel.Current
- + QItemSelectionModel.Rows))
+ QItemSelectionModel.SelectionFlags(QItemSelectionModel.Clear |
+ QItemSelectionModel.Select |
+ QItemSelectionModel.Current |
+ QItemSelectionModel.Rows))
@pyqtSlot(bool, name='on_resetButton_clicked')
def on_resetButton_clicked(self, checked=False):
diff --git a/python/plugins/processing/algs/r/RAlgorithm.py b/python/plugins/processing/algs/r/RAlgorithm.py
index f9accdd..af48e24 100644
--- a/python/plugins/processing/algs/r/RAlgorithm.py
+++ b/python/plugins/processing/algs/r/RAlgorithm.py
@@ -243,7 +243,7 @@ class RAlgorithm(GeoAlgorithm):
found = True
break
if found:
- param = ParameterTableMultipleField(token, desc, field)
+ param = ParameterTableMultipleField(name, desc, field)
elif token.lower().strip() == 'extent':
param = ParameterExtent(name, desc)
elif token.lower().strip() == 'point':
diff --git a/python/plugins/processing/algs/r/RUtils.py b/python/plugins/processing/algs/r/RUtils.py
index 1fdc7e2..4a4c4d6 100644
--- a/python/plugins/processing/algs/r/RUtils.py
+++ b/python/plugins/processing/algs/r/RUtils.py
@@ -33,7 +33,7 @@ import subprocess
from qgis.PyQt.QtCore import QSettings, QCoreApplication
from processing.core.ProcessingConfig import ProcessingConfig
from processing.core.ProcessingLog import ProcessingLog
-from processing.tools.system import userFolder, isWindows, mkdir
+from processing.tools.system import userFolder, isWindows, mkdir, getTempFilenameInTempFolder
class RUtils:
@@ -43,6 +43,8 @@ class RUtils:
R_USE64 = 'R_USE64'
R_LIBS_USER = 'R_LIBS_USER'
+ rscriptfilename = userFolder() + os.sep + 'processing_script.r'
+
@staticmethod
def RFolder():
folder = ProcessingConfig.getSetting(RUtils.R_FOLDER)
@@ -106,7 +108,7 @@ class RUtils:
@staticmethod
def getRScriptFilename():
- return userFolder() + os.sep + 'processing_script.r'
+ return RUtils.rscriptfilename
@staticmethod
def getConsoleOutputFilename():
@@ -114,6 +116,9 @@ class RUtils:
@staticmethod
def executeRAlgorithm(alg, progress):
+ # generate new R script file name in a temp folder
+ RUtils.rscriptfilename = getTempFilenameInTempFolder('processing_script.r')
+ # run commands
RUtils.verboseCommands = alg.getVerboseCommands()
RUtils.createRScriptFromRCommands(alg.getFullSetOfRCommands())
if isWindows():
diff --git a/python/plugins/processing/algs/saga/SagaNameDecorator.py b/python/plugins/processing/algs/saga/SagaNameDecorator.py
index 67c9014..c49c002 100644
--- a/python/plugins/processing/algs/saga/SagaNameDecorator.py
+++ b/python/plugins/processing/algs/saga/SagaNameDecorator.py
@@ -53,7 +53,7 @@ groups = {'grid_analysis': 'Raster analysis',
'pj_geotrans': 'Projections and Transformations',
'pj_proj4': 'Projections and Transformations',
'pointcloud_tools': 'Point clouds',
- 'shapes_grid': 'Vector to raster',
+ 'shapes_grid': 'Vector <-> raster',
'shapes_lines': 'Vector line tools',
'shapes_points': 'Vector point tools',
'shapes_polygons': 'Vector polygon tools',
diff --git a/python/plugins/processing/core/GeoAlgorithm.py b/python/plugins/processing/core/GeoAlgorithm.py
index f157052..9ebe2f1 100644
--- a/python/plugins/processing/core/GeoAlgorithm.py
+++ b/python/plugins/processing/core/GeoAlgorithm.py
@@ -486,7 +486,8 @@ class GeoAlgorithm:
for param in self.parameters:
s += '\t' + unicode(param) + '\n'
for out in self.outputs:
- s += '\t' + unicode(out) + '\n'
+ if not out.hidden:
+ s += '\t' + unicode(out) + '\n'
s += '\n'
return s
diff --git a/python/plugins/processing/core/ProcessingConfig.py b/python/plugins/processing/core/ProcessingConfig.py
index 95ff91c..af6532b 100644
--- a/python/plugins/processing/core/ProcessingConfig.py
+++ b/python/plugins/processing/core/ProcessingConfig.py
@@ -58,6 +58,7 @@ class ProcessingConfig:
POST_EXECUTION_SCRIPT = 'POST_EXECUTION_SCRIPT'
SHOW_CRS_DEF = 'SHOW_CRS_DEF'
WARN_UNMATCHING_CRS = 'WARN_UNMATCHING_CRS'
+ WARN_UNMATCHING_EXTENT_CRS = 'WARN_UNMATCHING_EXTENT_CRS'
DEFAULT_OUTPUT_RASTER_LAYER_EXT = 'DEFAULT_OUTPUT_RASTER_LAYER_EXT'
DEFAULT_OUTPUT_VECTOR_LAYER_EXT = 'DEFAULT_OUTPUT_VECTOR_LAYER_EXT'
SHOW_PROVIDERS_TOOLTIP = "SHOW_PROVIDERS_TOOLTIP"
@@ -108,6 +109,10 @@ class ProcessingConfig:
ProcessingConfig.tr("Warn before executing if layer CRS's do not match"), True))
ProcessingConfig.addSetting(Setting(
ProcessingConfig.tr('General'),
+ ProcessingConfig.WARN_UNMATCHING_EXTENT_CRS,
+ ProcessingConfig.tr("Warn before executing if extent CRS might not match layers CRS"), True))
+ ProcessingConfig.addSetting(Setting(
+ ProcessingConfig.tr('General'),
ProcessingConfig.RASTER_STYLE,
ProcessingConfig.tr('Style for raster layers'), '',
valuetype=Setting.FILE))
diff --git a/python/plugins/processing/core/parameters.py b/python/plugins/processing/core/parameters.py
index c71d105..83ecda8 100644
--- a/python/plugins/processing/core/parameters.py
+++ b/python/plugins/processing/core/parameters.py
@@ -740,17 +740,17 @@ class ParameterString(Parameter):
NEWLINE = '\n'
ESCAPED_NEWLINE = '\\n'
- def __init__(self, name='', description='', default=None, multiline=False,
+ def __init__(self, name='', description='', default='', multiline=False,
optional=False, evaluateExpressions=False):
Parameter.__init__(self, name, description, default, optional)
self.multiline = parseBool(multiline)
self.evaluateExpressions = parseBool(evaluateExpressions)
def setValue(self, obj):
- if obj is None:
+ if not bool(obj):
if not self.optional:
return False
- self.value = None
+ self.value = ''
return True
self.value = unicode(obj).replace(
diff --git a/python/plugins/processing/gui/AlgorithmDialog.py b/python/plugins/processing/gui/AlgorithmDialog.py
index 9ba485f..7fd6346 100644
--- a/python/plugins/processing/gui/AlgorithmDialog.py
+++ b/python/plugins/processing/gui/AlgorithmDialog.py
@@ -64,6 +64,8 @@ from processing.core.outputs import OutputTable
from processing.tools import dataobjects
+from qgis.utils import iface
+
class AlgorithmDialog(AlgorithmDialogBase):
@@ -189,6 +191,35 @@ class AlgorithmDialog(AlgorithmDialogBase):
else:
return param.setValue(unicode(widget.text()))
+ def checkExtentCRS(self):
+ unmatchingCRS = False
+ hasExtent = False
+ projectCRS = iface.mapCanvas().mapSettings().destinationCrs()
+ layers = dataobjects.getAllLayers()
+ for param in self.alg.parameters:
+ if isinstance(param, (ParameterRaster, ParameterVector, ParameterMultipleInput)):
+ if param.value:
+ if isinstance(param, ParameterMultipleInput):
+ inputlayers = param.value.split(';')
+ else:
+ inputlayers = [param.value]
+ for inputlayer in inputlayers:
+ for layer in layers:
+ if layer.source() == inputlayer:
+ if layer.crs() != projectCRS:
+ unmatchingCRS = True
+
+ p = dataobjects.getObjectFromUri(inputlayer)
+ if p is not None:
+ if p.crs() != projectCRS:
+ unmatchingCRS = True
+ if isinstance(param, ParameterExtent):
+ value = self.mainWidget.valueItems[param.name].leText.text().strip()
+ if value:
+ hasExtent = True
+
+ return hasExtent and unmatchingCRS
+
def accept(self):
self.settings.setValue("/Processing/dialogBase", self.saveGeometry())
@@ -204,6 +235,17 @@ class AlgorithmDialog(AlgorithmDialogBase):
QMessageBox.No)
if reply == QMessageBox.No:
return
+ checkExtentCRS = ProcessingConfig.getSetting(ProcessingConfig.WARN_UNMATCHING_EXTENT_CRS)
+ if checkExtentCRS and self.checkExtentCRS():
+ reply = QMessageBox.question(self, self.tr("Extent CRS"),
+ self.tr('Extent parameters must use the same CRS as the input layers.\n'
+ 'Your input layers do not have the same extent as the project, '
+ 'so the extent might be in a wrong CRS if you have selected it from the canvas.\n'
+ 'Do you want to continue?'),
+ QMessageBox.Yes | QMessageBox.No,
+ QMessageBox.No)
+ if reply == QMessageBox.No:
+ return
msg = self.alg._checkParameterValuesBeforeExecuting()
if msg:
QMessageBox.warning(
diff --git a/python/plugins/processing/gui/AlgorithmDialogBase.py b/python/plugins/processing/gui/AlgorithmDialogBase.py
index c4e02db..de07d67 100644
--- a/python/plugins/processing/gui/AlgorithmDialogBase.py
+++ b/python/plugins/processing/gui/AlgorithmDialogBase.py
@@ -113,7 +113,7 @@ class AlgorithmDialogBase(BASE, WIDGET):
if reply.error() != QNetworkReply.NoError:
html = self.tr('<h2>No help available for this algorithm</h2><p>{}</p>'.format(reply.errorString()))
else:
- html = unicode(reply.readAll())
+ html = str(reply.readAll()).decode('utf-8')
reply.deleteLater()
self.txtHelp.setHtml(html)
diff --git a/python/plugins/processing/gui/AlgorithmExecutor.py b/python/plugins/processing/gui/AlgorithmExecutor.py
index 136ecc5..01f456d 100644
--- a/python/plugins/processing/gui/AlgorithmExecutor.py
+++ b/python/plugins/processing/gui/AlgorithmExecutor.py
@@ -49,7 +49,8 @@ def runalg(alg, progress=None):
return True
except GeoAlgorithmExecutionException as e:
ProcessingLog.addToLog(sys.exc_info()[0], ProcessingLog.LOG_ERROR)
- progress.error(e.msg)
+ if progress is not None:
+ progress.error(e.msg)
return False
@@ -87,7 +88,7 @@ def runalgIterating(alg, paramToIter, progress):
out.value = filename
progress.setText(tr('Executing iteration %s/%s...' % (unicode(i), unicode(len(filelist)))))
progress.setPercentage(i * 100 / len(filelist))
- if runalg(alg):
+ if runalg(alg, progress):
handleAlgorithmResults(alg, None, False)
else:
return False
diff --git a/python/plugins/processing/gui/BatchPanel.py b/python/plugins/processing/gui/BatchPanel.py
index e3c317e..c120ee8 100644
--- a/python/plugins/processing/gui/BatchPanel.py
+++ b/python/plugins/processing/gui/BatchPanel.py
@@ -171,7 +171,8 @@ class BatchPanel(BASE, WIDGET):
else:
item = QLineEdit()
try:
- item.setText(unicode(param.default))
+ if param.default:
+ item.setText(unicode(param.default))
except:
pass
@@ -346,12 +347,12 @@ class BatchPanel(BASE, WIDGET):
self.tblParameters.setCellWidget(row, column, item)
def removeRows(self):
- #~ self.tblParameters.setUpdatesEnabled(False)
- #~ indexes = self.tblParameters.selectionModel().selectedIndexes()
- #~ indexes.sort()
- #~ for i in reversed(indexes):
- #~ self.tblParameters.model().removeRow(i.row())
- #~ self.tblParameters.setUpdatesEnabled(True)
+ # ~ self.tblParameters.setUpdatesEnabled(False)
+ # ~ indexes = self.tblParameters.selectionModel().selectedIndexes()
+ # ~ indexes.sort()
+ # ~ for i in reversed(indexes):
+ # ~ self.tblParameters.model().removeRow(i.row())
+ # ~ self.tblParameters.setUpdatesEnabled(True)
if self.tblParameters.rowCount() > 2:
self.tblParameters.setRowCount(self.tblParameters.rowCount() - 1)
diff --git a/python/plugins/processing/gui/ListMultiselectWidget.py b/python/plugins/processing/gui/ListMultiselectWidget.py
index f7ca14b..308952b 100644
--- a/python/plugins/processing/gui/ListMultiselectWidget.py
+++ b/python/plugins/processing/gui/ListMultiselectWidget.py
@@ -149,7 +149,7 @@ class ListMultiSelectWidget(QGroupBox):
def _setupUI(self):
self.setSizePolicy(
- QSizePolicy.Preferred, QSizePolicy.Ignored)
+ QSizePolicy.Preferred, QSizePolicy.Preferred)
self.setMinimumHeight(180)
diff --git a/python/plugins/processing/gui/OutputSelectionPanel.py b/python/plugins/processing/gui/OutputSelectionPanel.py
index 515bc16..ad0808d 100644
--- a/python/plugins/processing/gui/OutputSelectionPanel.py
+++ b/python/plugins/processing/gui/OutputSelectionPanel.py
@@ -54,6 +54,8 @@ class OutputSelectionPanel(BASE, WIDGET):
SAVE_TO_TEMP_FILE = QCoreApplication.translate(
'OutputSelectionPanel', '[Save to temporary file]')
+ SAVE_TO_TEMP_LAYER = QCoreApplication.translate(
+ 'OutputSelectionPanel', '[Create temporary layer]')
def __init__(self, output, alg):
super(OutputSelectionPanel, self).__init__(None)
@@ -63,7 +65,12 @@ class OutputSelectionPanel(BASE, WIDGET):
self.alg = alg
if hasattr(self.leText, 'setPlaceholderText'):
- self.leText.setPlaceholderText(self.SAVE_TO_TEMP_FILE)
+ if isinstance(output, OutputVector) \
+ and alg.provider.supportsNonFileBasedOutput():
+ # use memory layers for temporary files if supported
+ self.leText.setPlaceholderText(self.SAVE_TO_TEMP_LAYER)
+ else:
+ self.leText.setPlaceholderText(self.SAVE_TO_TEMP_FILE)
self.btnSelect.clicked.connect(self.selectOutput)
@@ -73,8 +80,14 @@ class OutputSelectionPanel(BASE, WIDGET):
else:
popupMenu = QMenu()
- actionSaveToTempFile = QAction(
- self.tr('Save to a temporary file'), self.btnSelect)
+ if isinstance(self.output, OutputVector) \
+ and self.alg.provider.supportsNonFileBasedOutput():
+ # use memory layers for temporary files if supported
+ actionSaveToTempFile = QAction(
+ self.tr('Create temporary layer'), self.btnSelect)
+ else:
+ actionSaveToTempFile = QAction(
+ self.tr('Save to a temporary file'), self.btnSelect)
actionSaveToTempFile.triggered.connect(self.saveToTemporaryFile)
popupMenu.addAction(actionSaveToTempFile)
@@ -90,10 +103,6 @@ class OutputSelectionPanel(BASE, WIDGET):
if isinstance(self.output, OutputVector) \
and self.alg.provider.supportsNonFileBasedOutput():
- actionSaveToMemory = QAction(
- self.tr('Save to memory layer'), self.btnSelect)
- actionSaveToMemory.triggered.connect(self.saveToMemory)
- popupMenu.addAction(actionSaveToMemory)
actionSaveToSpatialite = QAction(
self.tr('Save to Spatialite table...'), self.btnSelect)
actionSaveToSpatialite.triggered.connect(self.saveToSpatialite)
@@ -188,9 +197,6 @@ class OutputSelectionPanel(BASE, WIDGET):
'the_geom' if self.output.hasGeometry() else None)
self.leText.setText("spatialite:" + uri.uri())
- def saveToMemory(self):
- self.leText.setText('memory:')
-
def selectFile(self):
fileFilter = self.output.getFileFilter(self.alg)
@@ -239,8 +245,13 @@ class OutputSelectionPanel(BASE, WIDGET):
fileName = result
if fileName.startswith("[") and fileName.endswith("]"):
fileName = fileName[1:-1]
- if fileName.strip() in ['', self.SAVE_TO_TEMP_FILE]:
- value = None
+ if fileName.strip() in ['', self.SAVE_TO_TEMP_FILE, self.SAVE_TO_TEMP_LAYER]:
+ if isinstance(self.output, OutputVector) \
+ and self.alg.provider.supportsNonFileBasedOutput():
+ # use memory layers for temporary files if supported
+ value = 'memory:'
+ else:
+ value = None
elif fileName.startswith('memory:'):
value = fileName
elif fileName.startswith('postgis:'):
diff --git a/python/plugins/processing/gui/ScriptEditorDialog.py b/python/plugins/processing/gui/ScriptEditorDialog.py
index 6f9fa24..f7a3dc1 100644
--- a/python/plugins/processing/gui/ScriptEditorDialog.py
+++ b/python/plugins/processing/gui/ScriptEditorDialog.py
@@ -76,13 +76,13 @@ class ScriptEditorDialog(BASE, WIDGET):
QIcon(os.path.join(pluginPath, 'images', 'edithelp.png')))
self.btnRun.setIcon(
QIcon(os.path.join(pluginPath, 'images', 'runalgorithm.png')))
- self.btnCut.setIcon(QgsApplication.getThemeIcon('/mActionEditCut.png'))
+ self.btnCut.setIcon(QgsApplication.getThemeIcon('/mActionEditCut.svg'))
self.btnCopy.setIcon(
- QgsApplication.getThemeIcon('/mActionEditCopy.png'))
+ QgsApplication.getThemeIcon('/mActionEditCopy.svg'))
self.btnPaste.setIcon(
- QgsApplication.getThemeIcon('/mActionEditPaste.png'))
- self.btnUndo.setIcon(QgsApplication.getThemeIcon('/mActionUndo.png'))
- self.btnRedo.setIcon(QgsApplication.getThemeIcon('/mActionRedo.png'))
+ QgsApplication.getThemeIcon('/mActionEditPaste.svg'))
+ self.btnUndo.setIcon(QgsApplication.getThemeIcon('/mActionUndo.svg'))
+ self.btnRedo.setIcon(QgsApplication.getThemeIcon('/mActionRedo.svg'))
self.btnSnippets.setIcon(QgsApplication.getThemeIcon('/mActionHelpAPI.png'))
# Connect signals and slots
@@ -97,8 +97,8 @@ class ScriptEditorDialog(BASE, WIDGET):
self.btnPaste.clicked.connect(self.editor.paste)
self.btnUndo.clicked.connect(self.editor.undo)
self.btnRedo.clicked.connect(self.editor.redo)
- self.btnIncreaseFont.clicked.connect(self.increaseFontSize)
- self.btnDecreaseFont.clicked.connect(self.decreaseFontSize)
+ self.btnIncreaseFont.clicked.connect(self.editor.zoomIn)
+ self.btnDecreaseFont.clicked.connect(self.editor.zoomOut)
self.editor.textChanged.connect(lambda: self.setHasChanged(True))
self.alg = alg
@@ -138,15 +138,6 @@ class ScriptEditorDialog(BASE, WIDGET):
self.editor.setLexerType(self.algType)
- def increaseFontSize(self):
- font = self.editor.defaultFont
- self.editor.setFonts(font.pointSize() + 1)
- self.editor.initLexer()
-
- def decreaseFontSize(self):
- font = self.editor.defaultFont
- self.editor.setFonts(font.pointSize() - 1)
- self.editor.initLexer()
def showSnippets(self, evt):
popupmenu = QMenu()
@@ -200,7 +191,7 @@ class ScriptEditorDialog(BASE, WIDGET):
filterName = self.tr('Processing R script (*.rsx)')
self.filename = QFileDialog.getOpenFileName(
- self, self.tr('Save script'), scriptDir, filterName)
+ self, self.tr('Open script'), scriptDir, filterName)
if self.filename == '':
return
diff --git a/python/plugins/processing/modeler/ModelerAlgorithm.py b/python/plugins/processing/modeler/ModelerAlgorithm.py
index 2e91cce..474f8a8 100644
--- a/python/plugins/processing/modeler/ModelerAlgorithm.py
+++ b/python/plugins/processing/modeler/ModelerAlgorithm.py
@@ -151,10 +151,11 @@ class Algorithm():
return unicode(value)
params.append(_toString(value))
for out in self.algorithm.outputs:
- if out.name in self.outputs:
- params.append(safeName(self.outputs[out.name].description).lower())
- else:
- params.append(str(None))
+ if not out.hidden:
+ if out.name in self.outputs:
+ params.append(safeName(self.outputs[out.name].description).lower())
+ else:
+ params.append(str(None))
s.append("outputs_%s=processing.runalg('%s', %s)" % (self.name, self.consoleName, ",".join(params)))
return s
@@ -209,7 +210,11 @@ class ModelerAlgorithm(GeoAlgorithm):
def getCopy(self):
newone = ModelerAlgorithm()
newone.provider = self.provider
- newone.algs = copy.deepcopy(self.algs)
+
+ newone.algs = {}
+ for algname, alg in self.algs.iteritems():
+ newone.algs[algname] = Algorithm()
+ newone.algs[algname].__dict__.update(copy.deepcopy(alg.todict()))
newone.inputs = copy.deepcopy(self.inputs)
newone.defineCharacteristics()
newone.name = self.name
diff --git a/python/plugins/processing/modeler/ModelerDialog.py b/python/plugins/processing/modeler/ModelerDialog.py
index 696d437..4329493 100644
--- a/python/plugins/processing/modeler/ModelerDialog.py
+++ b/python/plugins/processing/modeler/ModelerDialog.py
@@ -158,7 +158,7 @@ class ModelerDialog(BASE, WIDGET):
self.btnOpen.setIcon(QgsApplication.getThemeIcon('/mActionFileOpen.svg'))
self.btnSave.setIcon(QgsApplication.getThemeIcon('/mActionFileSave.svg'))
self.btnSaveAs.setIcon(QgsApplication.getThemeIcon('/mActionFileSaveAs.svg'))
- self.btnExportImage.setIcon(QgsApplication.getThemeIcon('/mActionSaveMapAsImage.png'))
+ self.btnExportImage.setIcon(QgsApplication.getThemeIcon('/mActionSaveMapAsImage.svg'))
self.btnExportPython.setIcon(QgsApplication.getThemeIcon('/console/iconSaveAsConsole.png'))
self.btnEditHelp.setIcon(QIcon(os.path.join(pluginPath, 'images', 'edithelp.png')))
self.btnRun.setIcon(QIcon(os.path.join(pluginPath, 'images', 'runalgorithm.png')))
diff --git a/python/plugins/processing/script/ScriptSelector.py b/python/plugins/processing/script/ScriptSelector.py
index 5a2aa51..44fce24 100644
--- a/python/plugins/processing/script/ScriptSelector.py
+++ b/python/plugins/processing/script/ScriptSelector.py
@@ -34,7 +34,7 @@ from processing.core.alglist import algList
pluginPath = os.path.split(os.path.dirname(__file__))[0]
WIDGET, BASE = uic.loadUiType(
- os.path.join(pluginPath, 'ui', 'DlgConfig.ui'))
+ os.path.join(pluginPath, 'ui', 'scriptselector.ui'))
class ScriptSelector(BASE, WIDGET):
diff --git a/python/plugins/processing/tests/CMakeLists.txt b/python/plugins/processing/tests/CMakeLists.txt
index ac9cb33..3cf8fa4 100644
--- a/python/plugins/processing/tests/CMakeLists.txt
+++ b/python/plugins/processing/tests/CMakeLists.txt
@@ -7,6 +7,7 @@ PLUGIN_INSTALL(processing tests/data ${TEST_DATA_FILES})
IF(ENABLE_TESTS)
INCLUDE(UsePythonTest)
ADD_PYTHON_TEST(ProcessingParametersTest ParametersTest.py)
+ ADD_PYTHON_TEST(ProcessingToolsTest ToolsTest.py)
ADD_PYTHON_TEST(ProcessingQgisAlgorithmsTest QgisAlgorithmsTest.py)
ADD_PYTHON_TEST(ProcessingGdalAlgorithmsTest GdalAlgorithmsTest.py)
ADD_PYTHON_TEST(ProcessingGrass7AlgorithmsImageryTest Grass7AlgorithmsImageryTest.py)
diff --git a/python/plugins/processing/tests/GdalAlgorithmsTest.py b/python/plugins/processing/tests/GdalAlgorithmsTest.py
index 3766cdd..57f6f13 100644
--- a/python/plugins/processing/tests/GdalAlgorithmsTest.py
+++ b/python/plugins/processing/tests/GdalAlgorithmsTest.py
@@ -26,6 +26,7 @@ __copyright__ = '(C) 2016, Matthias Kuhn'
__revision__ = ':%H$'
import AlgorithmsTestBase
+from processing.algs.gdal.ogr2ogrtopostgis import Ogr2OgrToPostGis
import nose2
import shutil
@@ -54,5 +55,52 @@ class TestGdalAlgorithms(unittest.TestCase, AlgorithmsTestBase.AlgorithmsTest):
return 'gdal_algorithm_tests.yaml'
+class TestGdalOgr2OgrToPostgis(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ #start_app()
+ pass
+
+ @classmethod
+ def tearDownClass(cls):
+ pass
+
+ # See http://hub.qgis.org/issues/15706
+ def test_getConnectionString(self):
+
+ obj = Ogr2OgrToPostGis()
+
+ cs = obj.getConnectionString()
+ # NOTE: defaults are debatable, see
+ # https://github.com/qgis/QGIS/pull/3607#issuecomment-253971020
+ self.assertEquals(obj.getConnectionString(),
+ "host=localhost port=5432 active_schema=public")
+
+ obj.setParameterValue('HOST', 'remote')
+ self.assertEquals(obj.getConnectionString(),
+ "host=remote port=5432 active_schema=public")
+
+ obj.setParameterValue('HOST', '')
+ self.assertEquals(obj.getConnectionString(),
+ "port=5432 active_schema=public")
+
+ obj.setParameterValue('PORT', '5555')
+ self.assertEquals(obj.getConnectionString(),
+ "port=5555 active_schema=public")
+
+ obj.setParameterValue('PORT', '')
+ self.assertEquals(obj.getConnectionString(),
+ "active_schema=public")
+
+ obj.setParameterValue('USER', 'usr')
+ self.assertEquals(obj.getConnectionString(),
+ "active_schema=public user=usr")
+
+ obj.setParameterValue('PASSWORD', 'pwd')
+ self.assertEquals(obj.getConnectionString(),
+ "password=pwd active_schema=public user=usr")
+
+
if __name__ == '__main__':
nose2.main()
diff --git a/python/plugins/processing/tests/ParametersTest.py b/python/plugins/processing/tests/ParametersTest.py
index 850fdca..5f71138 100644
--- a/python/plugins/processing/tests/ParametersTest.py
+++ b/python/plugins/processing/tests/ParametersTest.py
@@ -412,7 +412,7 @@ class ParameterStringTest(unittest.TestCase):
optionalParameter.setValue('check')
self.assertEqual(optionalParameter.value, 'check')
self.assertTrue(optionalParameter.setValue(None))
- self.assertEqual(optionalParameter.value, None)
+ self.assertEqual(optionalParameter.value, '')
requiredParameter = ParameterCrs('myName', 'myDesc', default='test', optional=False)
self.assertEqual(requiredParameter.value, 'test')
diff --git a/python/plugins/processing/tests/ToolsTest.py b/python/plugins/processing/tests/ToolsTest.py
new file mode 100644
index 0000000..d07e2b5
--- /dev/null
+++ b/python/plugins/processing/tests/ToolsTest.py
@@ -0,0 +1,159 @@
+# -*- coding: utf-8 -*-
+
+"""
+***************************************************************************
+ ToolsTest
+ ---------------------
+ Date : July 2017
+ Copyright : (C) 2017 by Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************
+"""
+
+__author__ = 'Nyall Dawson'
+__date__ = 'July 2016'
+__copyright__ = '(C) 2016, Nyall Dawson'
+
+# This will get replaced with a git SHA1 when you do a git archive
+
+__revision__ = '$Format:%H$'
+
+from qgis.testing import start_app, unittest
+from processing.tests.TestData import points2
+from processing.tools import vector
+from qgis.core import (QgsVectorLayer, QgsFeatureRequest)
+from processing.core.ProcessingConfig import ProcessingConfig
+
+import os.path
+import errno
+import shutil
+
+dataFolder = os.path.join(os.path.dirname(__file__), '../../../../tests/testdata/')
+tmpBaseFolder = os.path.join(os.sep, 'tmp', 'qgis_test', str(os.getpid()))
+
+
+def mkDirP(path):
+ try:
+ os.makedirs(path)
+ except OSError as exc:
+ if exc.errno == errno.EEXIST and os.path.isdir(path):
+ pass
+ else:
+ raise
+
+start_app()
+
+
+class VectorTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ mkDirP(tmpBaseFolder)
+
+ @classmethod
+ def tearDownClass(cls):
+ shutil.rmtree(tmpBaseFolder)
+ pass
+
+ # See http://hub.qgis.org/issues/15698
+ def test_ogrLayerName(self):
+ tmpdir = os.path.join(tmpBaseFolder, 'ogrLayerName')
+ os.mkdir(tmpdir)
+
+ def linkTestfile(f, t):
+ os.link(os.path.join(dataFolder, f), os.path.join(tmpdir, t))
+
+ # URI from OGR provider
+ linkTestfile('geom_data.csv', 'a.csv')
+ name = vector.ogrLayerName(tmpdir)
+ self.assertEqual(name, 'a')
+
+ # URI from OGR provider
+ linkTestfile('wkt_data.csv', 'b.csv')
+ name = vector.ogrLayerName(tmpdir + '|layerid=0')
+ self.assertEqual(name, 'a')
+ name = vector.ogrLayerName(tmpdir + '|layerid=1')
+ self.assertEqual(name, 'b')
+
+ # URI from OGR provider
+ name = vector.ogrLayerName(tmpdir + '|layerid=2')
+ self.assertEqual(name, 'invalid-layerid')
+
+ # URI from OGR provider
+ name = vector.ogrLayerName(tmpdir + '|layername=f')
+ self.assertEqual(name, 'f') # layername takes precedence
+
+ # URI from OGR provider
+ name = vector.ogrLayerName(tmpdir + '|layerid=0|layername=f2')
+ self.assertEqual(name, 'f2') # layername takes precedence
+
+ # URI from OGR provider
+ name = vector.ogrLayerName(tmpdir + '|layername=f2|layerid=0')
+ self.assertEqual(name, 'f2') # layername takes precedence
+
+ # URI from Sqlite provider
+ name = vector.ogrLayerName('dbname=\'/tmp/x.sqlite\' table="t" (geometry) sql=')
+ self.assertEqual(name, 't')
+
+ # URI from PostgreSQL provider
+ name = vector.ogrLayerName('port=5493 sslmode=disable key=\'edge_id\' srid=0 type=LineString table="city_data"."edge" (geom) sql=')
+ self.assertEqual(name, 'city_data.edge')
+
+ def testFeatures(self):
+ ProcessingConfig.initialize()
+
+ test_data = points2()
+ test_layer = QgsVectorLayer(test_data, 'test', 'ogr')
+
+ # test with all features
+ features = vector.features(test_layer)
+ self.assertEqual(len(features), 8)
+ self.assertEqual(set([f.id() for f in features]), set([0, 1, 2, 3, 4, 5, 6, 7]))
+
+ # test with selected features
+ previous_value = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
+ ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, True)
+ test_layer.selectByIds([2, 4, 6])
+ features = vector.features(test_layer)
+ self.assertEqual(len(features), 3)
+ self.assertEqual(set([f.id() for f in features]), set([2, 4, 6]))
+
+ # selection, but not using selected features
+ ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, False)
+ test_layer.selectByIds([2, 4, 6])
+ features = vector.features(test_layer)
+ self.assertEqual(len(features), 8)
+ self.assertEqual(set([f.id() for f in features]), set([0, 1, 2, 3, 4, 5, 6, 7]))
+
+ # using selected features, but no selection
+ ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, True)
+ test_layer.removeSelection()
+ features = vector.features(test_layer)
+ self.assertEqual(len(features), 8)
+ self.assertEqual(set([f.id() for f in features]), set([0, 1, 2, 3, 4, 5, 6, 7]))
+
+ # test that feature request is honored
+ ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, False)
+ features = vector.features(test_layer, QgsFeatureRequest().setFilterFids([1, 3, 5]))
+ self.assertEqual(set([f.id() for f in features]), set([1, 3, 5]))
+
+ # test that feature request is honored when using selections
+ ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, True)
+ test_layer.selectByIds([2, 4, 6])
+ features = vector.features(test_layer, QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry))
+ self.assertTrue(all([f.geometry() == None for f in features]))
+ features = vector.features(test_layer, QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry))
+ self.assertEqual(set([f.id() for f in features]), set([2, 4, 6]))
+
+ ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/plugins/processing/tests/testdata/dissolve_polys.gfs b/python/plugins/processing/tests/testdata/dissolve_polys.gfs
new file mode 100644
index 0000000..b283ea0
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/dissolve_polys.gfs
@@ -0,0 +1,31 @@
+<GMLFeatureClassList>
+ <GMLFeatureClass>
+ <Name>dissolve_polys</Name>
+ <ElementPath>dissolve_polys</ElementPath>
+ <GeometryType>3</GeometryType>
+ <SRSName>EPSG:4326</SRSName>
+ <DatasetSpecificInfo>
+ <FeatureCount>10</FeatureCount>
+ <ExtentXMin>-1.00000</ExtentXMin>
+ <ExtentXMax>9.16296</ExtentXMax>
+ <ExtentYMin>-3.00000</ExtentYMin>
+ <ExtentYMax>6.08868</ExtentYMax>
+ </DatasetSpecificInfo>
+ <PropertyDefn>
+ <Name>name</Name>
+ <ElementPath>name</ElementPath>
+ <Type>String</Type>
+ <Width>2</Width>
+ </PropertyDefn>
+ <PropertyDefn>
+ <Name>intval</Name>
+ <ElementPath>intval</ElementPath>
+ <Type>Integer</Type>
+ </PropertyDefn>
+ <PropertyDefn>
+ <Name>floatval</Name>
+ <ElementPath>floatval</ElementPath>
+ <Type>Real</Type>
+ </PropertyDefn>
+ </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/python/plugins/processing/tests/testdata/dissolve_polys.gml b/python/plugins/processing/tests/testdata/dissolve_polys.gml
new file mode 100644
index 0000000..d62342f
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/dissolve_polys.gml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation=""
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
+ <gml:coord><gml:X>9.162955854126682</gml:X><gml:Y>6.088675623800385</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:dissolve_polys fid="polys.0">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 -1,3 3,3 3,2 2,2 2,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>aa</ogr:name>
+ <ogr:intval>1</ogr:intval>
+ <ogr:floatval>44.123455999999997</ogr:floatval>
+ </ogr:dissolve_polys>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_polys fid="polys.1">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6.241458733205375,-0.054510556621882 7.241458733205375,-1.054510556621882 5.241458733205375,-1.054510556621882 6.241458733205375,-0.054510556621882</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>dd</ogr:name>
+ <ogr:floatval>0.000000000000000</ogr:floatval>
+ </ogr:dissolve_polys>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_polys fid="polys.2">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,5 2,6 3,6 3,5 2,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>bb</ogr:name>
+ <ogr:intval>1</ogr:intval>
+ <ogr:floatval>0.123000000000000</ogr:floatval>
+ </ogr:dissolve_polys>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_polys fid="polys.3">
+ <ogr:intval>120</ogr:intval>
+ <ogr:floatval>-100291.432130000001052</ogr:floatval>
+ </ogr:dissolve_polys>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_polys fid="polys.4">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,2 6,1 6,-3 2,-1 2,2 3,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>aa</ogr:name>
+ <ogr:intval>1</ogr:intval>
+ <ogr:floatval>3.330000000000000</ogr:floatval>
+ </ogr:dissolve_polys>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_polys fid="polys.5">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.443378119001919,4.423608445297505 2.443378119001919,5.423608445297505 3.443378119001919,5.423608445297505 3.443378119001919,4.423608445297505 2.443378119001919,4.423608445297505</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>bb</ogr:name>
+ <ogr:intval>1</ogr:intval>
+ <ogr:floatval>0.123000000000000</ogr:floatval>
+ </ogr:dissolve_polys>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_polys fid="polys.6">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4.172552783109405,4.822648752399233 4.172552783109405,5.822648752399233 5.172552783109405,5.822648752399233 5.172552783109405,4.822648752399233 4.172552783109405,4.822648752399233</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>bb</ogr:name>
+ <ogr:intval>1</ogr:intval>
+ <ogr:floatval>0.123000000000000</ogr:floatval>
+ </ogr:dissolve_polys>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_polys fid="polys.7">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>8.162955854126682,2.738771593090211 8.162955854126682,3.738771593090211 9.162955854126682,3.738771593090211 9.162955854126682,2.738771593090211 8.162955854126682,2.738771593090211</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>cc</ogr:name>
+ <ogr:floatval>0.123000000000000</ogr:floatval>
+ </ogr:dissolve_polys>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_polys fid="polys.9">
+ <ogr:name>dd</ogr:name>
+ </ogr:dissolve_polys>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_polys fid="polys.8">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.620729366602688,5.088675623800385 2.620729366602688,6.088675623800385 3.620729366602688,6.088675623800385 3.620729366602688,5.088675623800385 2.620729366602688,5.088675623800385</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>bb</ogr:name>
+ <ogr:intval>2</ogr:intval>
+ <ogr:floatval>0.123000000000000</ogr:floatval>
+ </ogr:dissolve_polys>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon.gml b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon.gml
new file mode 100644
index 0000000..5bd140d
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon.gml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ clip_lines_by_multipolygon.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>2</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.0">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,2 8,2</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.2">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,1 2,2</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2,2 3,2</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>3,2 3,3</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.3">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>4,1 3,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.5">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon.xsd b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon.xsd
new file mode 100644
index 0000000..0438e77
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="clip_lines_by_multipolygon" type="ogr:clip_lines_by_multipolygon_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="clip_lines_by_multipolygon_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:LineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_BACKUP_3790.gml b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_BACKUP_3790.gml
new file mode 100644
index 0000000..5bd140d
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_BACKUP_3790.gml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ clip_lines_by_multipolygon.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>2</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.0">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,2 8,2</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.2">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,1 2,2</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2,2 3,2</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>3,2 3,3</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.3">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>4,1 3,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.5">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_BASE_3790.gml b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_BASE_3790.gml
new file mode 100644
index 0000000..7423966
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_BASE_3790.gml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ clip_lines_by_multipolygon.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>2</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.0">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,2 8,2</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.2">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,1 2,2</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2,2 3,2</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>3,2 3,3</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.3">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 4,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.5">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_LOCAL_3790.gml b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_LOCAL_3790.gml
new file mode 100644
index 0000000..e69de29
diff --git a/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_REMOTE_3790.gml b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_REMOTE_3790.gml
new file mode 100644
index 0000000..5bd140d
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_lines_by_multipolygon_REMOTE_3790.gml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ clip_lines_by_multipolygon.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>2</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.0">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,2 8,2</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.2">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,1 2,2</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2,2 3,2</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>3,2 3,3</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.3">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>4,1 3,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_multipolygon fid="lines.5">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_lines_by_multipolygon>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_lines_by_polygon.gml b/python/plugins/processing/tests/testdata/expected/clip_lines_by_polygon.gml
new file mode 100644
index 0000000..25bb64c
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_lines_by_polygon.gml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ clip_lines_by_polygon.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0.776536312849161</gml:X><gml:Y>-3</gml:Y></gml:coord>
+ <gml:coord><gml:X>8.572346368715085</gml:X><gml:Y>2.179050279329609</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:clip_lines_by_polygon fid="lines2.0">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>0.776536312849161,2.179050279329609 4.049720670391062,1.334357541899442 5.70391061452514,-1.991620111731844 8.572346368715085,-2.220391061452514 8.565567160553801,-3.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_polygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_lines_by_polygon fid="lines2.1">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>7.956424581005587,0.683240223463688 7.160699686605804,0.0</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>7.0,-0.1379829769809 4.595251396648044,-2.202793296089386</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:clip_lines_by_polygon>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_lines_by_polygon.xsd b/python/plugins/processing/tests/testdata/expected/clip_lines_by_polygon.xsd
new file mode 100644
index 0000000..8bf59a0
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_lines_by_polygon.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="clip_lines_by_polygon" type="ogr:clip_lines_by_polygon_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="clip_lines_by_polygon_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:LineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_multipolygons_by_polygons.gml b/python/plugins/processing/tests/testdata/expected/clip_multipolygons_by_polygons.gml
new file mode 100644
index 0000000..297eae4
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_multipolygons_by_polygons.gml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ clip_multipolygons_by_polygons.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0</gml:X><gml:Y>0</gml:Y></gml:coord>
+ <gml:coord><gml:X>8</gml:X><gml:Y>2</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:clip_multipolygons_by_polygons fid="multipolys.0">
+ <ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2 1, 2 2, 3 2, 4 1.66666666666667, 4 1, 2 1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
+ <ogr:Bname>Test</ogr:Bname>
+ <ogr:Bintval>1</ogr:Bintval>
+ <ogr:Bfloatval>0.123</ogr:Bfloatval>
+ </ogr:clip_multipolygons_by_polygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_multipolygons_by_polygons fid="multipolys.1">
+ <ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>7 0, 7 1, 8 1, 8 0, 7 0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
+ </ogr:clip_multipolygons_by_polygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_multipolygons_by_polygons fid="multipolys.2">
+ <ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0,0 0,1 1,1 1,0 0,0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
+ <ogr:Bname>Test</ogr:Bname>
+ <ogr:Bintval>2</ogr:Bintval>
+ <ogr:Bfloatval>-0.123</ogr:Bfloatval>
+ </ogr:clip_multipolygons_by_polygons>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_multipolygons_by_polygons.xsd b/python/plugins/processing/tests/testdata/expected/clip_multipolygons_by_polygons.xsd
new file mode 100644
index 0000000..26f5502
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_multipolygons_by_polygons.xsd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="clip_multipolygons_by_polygons" type="ogr:clip_multipolygons_by_polygons_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="clip_multipolygons_by_polygons_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:MultiPolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="Bname" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="Bintval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="10"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="Bfloatval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_points_by_multipolygons.gml b/python/plugins/processing/tests/testdata/expected/clip_points_by_multipolygons.gml
new file mode 100644
index 0000000..5ad95f3
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_points_by_multipolygons.gml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ clip_points_by_multipolygons.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>1</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:clip_points_by_multipolygons fid="points.0">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_multipolygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_points_by_multipolygons fid="points.1">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_multipolygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_points_by_multipolygons fid="points.2">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_multipolygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_points_by_multipolygons fid="points.4">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>4,1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_multipolygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_points_by_multipolygons fid="points.6">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_multipolygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_points_by_multipolygons fid="points.7">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_multipolygons>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_points_by_multipolygons.xsd b/python/plugins/processing/tests/testdata/expected/clip_points_by_multipolygons.xsd
new file mode 100644
index 0000000..022c175
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_points_by_multipolygons.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="clip_points_by_multipolygons" type="ogr:clip_points_by_multipolygons_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="clip_points_by_multipolygons_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_points_by_polygons.gml b/python/plugins/processing/tests/testdata/expected/clip_points_by_polygons.gml
new file mode 100644
index 0000000..1db1e3b
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_points_by_polygons.gml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ clip_points_by_polygons.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>7</gml:X><gml:Y>3</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:clip_points_by_polygons fid="points.0">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_polygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_points_by_polygons fid="points.1">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_polygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_points_by_polygons fid="points.2">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_polygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_points_by_polygons fid="points.4">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>4,1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_polygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_points_by_polygons fid="points.7">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_polygons>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_points_by_polygons fid="points.8">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:clip_points_by_polygons>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_points_by_polygons.xsd b/python/plugins/processing/tests/testdata/expected/clip_points_by_polygons.xsd
new file mode 100644
index 0000000..872bcf0
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_points_by_polygons.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="clip_points_by_polygons" type="ogr:clip_points_by_polygons_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="clip_points_by_polygons_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_polys_by_multipolygon.gml b/python/plugins/processing/tests/testdata/expected/clip_polys_by_multipolygon.gml
new file mode 100644
index 0000000..28cf596
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_polys_by_multipolygon.gml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ clip_polys_by_multipolygon.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0</gml:X><gml:Y>0</gml:Y></gml:coord>
+ <gml:coord><gml:X>8</gml:X><gml:Y>2</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:clip_polys_by_multipolygon fid="polys.0">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0,0 0,1 1,1 1,0 0,0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>aaaaa</ogr:name>
+ <ogr:intval>33</ogr:intval>
+ <ogr:floatval>44.123456</ogr:floatval>
+ </ogr:clip_polys_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_polys_by_multipolygon fid="polys.3">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>7 1, 8 1, 8 0, 7 0, 7 1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>ASDF</ogr:name>
+ <ogr:intval>0</ogr:intval>
+ </ogr:clip_polys_by_multipolygon>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:clip_polys_by_multipolygon fid="polys.5">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2 1, 2 2, 3 2, 4 1.66666666666667, 4 1, 2 1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>elim</ogr:name>
+ <ogr:intval>2</ogr:intval>
+ <ogr:floatval>3.33</ogr:floatval>
+ </ogr:clip_polys_by_multipolygon>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/clip_polys_by_multipolygon.xsd b/python/plugins/processing/tests/testdata/expected/clip_polys_by_multipolygon.xsd
new file mode 100644
index 0000000..4fac3a7
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/clip_polys_by_multipolygon.xsd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="clip_polys_by_multipolygon" type="ogr:clip_polys_by_multipolygon_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="clip_polys_by_multipolygon_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="5"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="intval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="10"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="floatval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/dissolve_field.gml b/python/plugins/processing/tests/testdata/expected/dissolve_field.gml
new file mode 100644
index 0000000..600e2db
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/dissolve_field.gml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ dissolve_field.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
+ <gml:coord><gml:X>9.162955854126682</gml:X><gml:Y>6.088675623800385</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:dissolve_field fid="polys.0">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,2 6,1 6,-3 2,-1 -1,-1 -1,3 3,3 3,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>aa</ogr:name>
+ <ogr:intval>1</ogr:intval>
+ <ogr:floatval>44.123456</ogr:floatval>
+ </ogr:dissolve_field>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_field fid="polys.7">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>8.16295585412668,2.73877159309021 8.16295585412668,3.73877159309021 9.16295585412668,3.73877159309021 9.16295585412668,2.73877159309021 8.16295585412668,2.73877159309021</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>cc</ogr:name>
+ <ogr:floatval>0.123</ogr:floatval>
+ </ogr:dissolve_field>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_field fid="polys.1">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6.24145873320538,-0.054510556621882 7.24145873320538,-1.05451055662188 5.24145873320538,-1.05451055662188 6.24145873320538,-0.054510556621882</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>dd</ogr:name>
+ <ogr:floatval>0</ogr:floatval>
+ </ogr:dissolve_field>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_field fid="polys.3">
+ <ogr:intval>120</ogr:intval>
+ <ogr:floatval>-100291.43213</ogr:floatval>
+ </ogr:dissolve_field>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_field fid="polys.2">
+ <ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4.17255278310941,4.82264875239923 4.17255278310941,5.82264875239923 5.17255278310941,5.82264875239923 5.17255278310941,4.82264875239923 4.17255278310941,4.82264875239923</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordi [...]
+ <ogr:name>bb</ogr:name>
+ <ogr:intval>1</ogr:intval>
+ <ogr:floatval>0.123</ogr:floatval>
+ </ogr:dissolve_field>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/dissolve_field.xsd b/python/plugins/processing/tests/testdata/expected/dissolve_field.xsd
new file mode 100644
index 0000000..0a1ca1e
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/dissolve_field.xsd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="dissolve_field" type="ogr:dissolve_field_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="dissolve_field_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:GeometryPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="2"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="intval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="16"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="floatval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/dissolve_two_fields.gml b/python/plugins/processing/tests/testdata/expected/dissolve_two_fields.gml
new file mode 100644
index 0000000..c039a6d
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/dissolve_two_fields.gml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ dissolve_two_fields.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
+ <gml:coord><gml:X>9.162955854126682</gml:X><gml:Y>6.088675623800385</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:dissolve_two_fields fid="polys.0">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,2 6,1 6,-3 2,-1 -1,-1 -1,3 3,3 3,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>aa</ogr:name>
+ <ogr:intval>1</ogr:intval>
+ <ogr:floatval>44.123456</ogr:floatval>
+ </ogr:dissolve_two_fields>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_two_fields fid="polys.1">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6.24145873320538,-0.054510556621882 7.24145873320538,-1.05451055662188 5.24145873320538,-1.05451055662188 6.24145873320538,-0.054510556621882</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>dd</ogr:name>
+ <ogr:floatval>0</ogr:floatval>
+ </ogr:dissolve_two_fields>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_two_fields fid="polys.2">
+ <ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4.17255278310941,4.82264875239923 4.17255278310941,5.82264875239923 5.17255278310941,5.82264875239923 5.17255278310941,4.82264875239923 4.17255278310941,4.82264875239923</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordi [...]
+ <ogr:name>bb</ogr:name>
+ <ogr:intval>1</ogr:intval>
+ <ogr:floatval>0.123</ogr:floatval>
+ </ogr:dissolve_two_fields>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_two_fields fid="polys.3">
+ <ogr:intval>120</ogr:intval>
+ <ogr:floatval>-100291.43213</ogr:floatval>
+ </ogr:dissolve_two_fields>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_two_fields fid="polys.8">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.62072936660269,5.08867562380038 2.62072936660269,6.08867562380038 3.62072936660269,6.08867562380038 3.62072936660269,5.08867562380038 2.62072936660269,5.08867562380038</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>bb</ogr:name>
+ <ogr:intval>2</ogr:intval>
+ <ogr:floatval>0.123</ogr:floatval>
+ </ogr:dissolve_two_fields>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:dissolve_two_fields fid="polys.7">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>8.16295585412668,2.73877159309021 8.16295585412668,3.73877159309021 9.16295585412668,3.73877159309021 9.16295585412668,2.73877159309021 8.16295585412668,2.73877159309021</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>cc</ogr:name>
+ <ogr:floatval>0.123</ogr:floatval>
+ </ogr:dissolve_two_fields>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/dissolve_two_fields.xsd b/python/plugins/processing/tests/testdata/expected/dissolve_two_fields.xsd
new file mode 100644
index 0000000..61fcdc5
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/dissolve_two_fields.xsd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="dissolve_two_fields" type="ogr:dissolve_two_fields_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="dissolve_two_fields_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:GeometryPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="2"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="intval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="16"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="floatval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/lines_boundary.gml b/python/plugins/processing/tests/testdata/expected/lines_boundary.gml
new file mode 100644
index 0000000..8299857
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/lines_boundary.gml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ lines_boundary.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
+ <gml:coord><gml:X>11</gml:X><gml:Y>5</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:lines_boundary fid="lines.0">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>6,2</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>11,5</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ </ogr:lines_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_boundary fid="lines.1">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>-1,-1</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>1,-1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ </ogr:lines_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_boundary fid="lines.2">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>2,0</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>3,3</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ </ogr:lines_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_boundary fid="lines.3">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>3,1</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>5,1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ </ogr:lines_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_boundary fid="lines.4">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>7,-3</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>10,-3</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ </ogr:lines_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_boundary fid="lines.5">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>6,-3</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>10,1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ </ogr:lines_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_boundary fid="lines.6">
+ </ogr:lines_boundary>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/lines_boundary.xsd b/python/plugins/processing/tests/testdata/expected/lines_boundary.xsd
new file mode 100644
index 0000000..44b50ca
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/lines_boundary.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="lines_boundary" type="ogr:lines_boundary_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="lines_boundary_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:MultiPointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/lines_bounds.gml b/python/plugins/processing/tests/testdata/expected/lines_bounds.gml
new file mode 100644
index 0000000..836ed64
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/lines_bounds.gml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ lines_bounds.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
+ <gml:coord><gml:X>11</gml:X><gml:Y>5</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:lines_bounds fid="lines.0">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6,2 11,2 11,5 6,5 6,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:lines_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_bounds fid="lines.1">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 1,-1 1,-1 -1,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:lines_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_bounds fid="lines.2">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,0 3,0 3,3 2,3 2,0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:lines_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_bounds fid="lines.3">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,1 5,1 5,1 3,1 3,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:lines_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_bounds fid="lines.4">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>7,-3 10,-3 10,-3 7,-3 7,-3</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:lines_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_bounds fid="lines.5">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6,-3 10,-3 10,1 6,1 6,-3</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:lines_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:lines_bounds fid="lines.6">
+ </ogr:lines_bounds>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/lines_bounds.xsd b/python/plugins/processing/tests/testdata/expected/lines_bounds.xsd
new file mode 100644
index 0000000..8db5a1f
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/lines_bounds.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="lines_bounds" type="ogr:lines_bounds_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="lines_bounds_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/merge_lines.gml b/python/plugins/processing/tests/testdata/expected/merge_lines.gml
new file mode 100644
index 0000000..c7fe0d8
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/merge_lines.gml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ merge_lines.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>5.58042226487524</gml:X><gml:Y>4.119769673704415</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:merge_lines fid="lines.1">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:merge_lines>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:merge_lines fid="lines.2">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>3,1 5,1 5.02418426103647,2.4147792706334</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:merge_lines>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:merge_lines fid="lines.3">
+ </ogr:merge_lines>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:merge_lines fid="lines.4">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,0 2,2 3,2 3,3 5.58042226487524,2.9468330134357</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2.94433781190019,4.04721689059501 5.4595009596929,4.11976967370441</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:merge_lines>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/merge_lines.xsd b/python/plugins/processing/tests/testdata/expected/merge_lines.xsd
new file mode 100644
index 0000000..c3cbd14
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/merge_lines.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="merge_lines" type="ogr:merge_lines_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="merge_lines_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:MultiLineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/multi_to_single.gml b/python/plugins/processing/tests/testdata/expected/multi_to_single.gml
new file mode 100644
index 0000000..a439457
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multi_to_single.gml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ multi_to_single.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>5.58042226487524</gml:X><gml:Y>4.119769673704415</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:multi_to_single fid="lines.1">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:multi_to_single>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multi_to_single fid="lines.2">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:multi_to_single>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multi_to_single fid="lines.2">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5.02418426103647,2.4147792706334 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:multi_to_single>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multi_to_single fid="lines.3">
+ </ogr:multi_to_single>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multi_to_single fid="lines.4">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 2,2 3,2 3,3</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:multi_to_single>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multi_to_single fid="lines.4">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2.94433781190019,4.04721689059501 5.4595009596929,4.11976967370441</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:multi_to_single>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multi_to_single fid="lines.4">
+ <ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,3 5.58042226487524,2.9468330134357</gml:coordinates></gml:LineString></ogr:geometryProperty>
+ </ogr:multi_to_single>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/multi_to_single.xsd b/python/plugins/processing/tests/testdata/expected/multi_to_single.xsd
new file mode 100644
index 0000000..e5c9e7d
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multi_to_single.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="multi_to_single" type="ogr:multi_to_single_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="multi_to_single_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:LineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/multiline_boundary.gml b/python/plugins/processing/tests/testdata/expected/multiline_boundary.gml
new file mode 100644
index 0000000..bceafb8
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multiline_boundary.gml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ multiline_boundary.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>5.58042226487524</gml:X><gml:Y>4.119769673704415</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:multiline_boundary fid="lines.1">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>-1,-1</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>1,-1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ </ogr:multiline_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multiline_boundary fid="lines.2">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>3,1</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>5,1</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>5.024184261036468,2.414779270633399</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>5,1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiP [...]
+ </ogr:multiline_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multiline_boundary fid="lines.3">
+ </ogr:multiline_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multiline_boundary fid="lines.4">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>2,0</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>3,3</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>2.944337811900192,4.04721689059501</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>5.459500959692898,4.119769673704415</gml:coordinates></gml:Point [...]
+ </ogr:multiline_boundary>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/multiline_boundary.xsd b/python/plugins/processing/tests/testdata/expected/multiline_boundary.xsd
new file mode 100644
index 0000000..aa8a6ff
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multiline_boundary.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="multiline_boundary" type="ogr:multiline_boundary_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="multiline_boundary_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:MultiPointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/multiline_bounds.gml b/python/plugins/processing/tests/testdata/expected/multiline_bounds.gml
new file mode 100644
index 0000000..4fbdbbc
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multiline_bounds.gml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ multiline_bounds.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>5.58042226487524</gml:X><gml:Y>4.119769673704415</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:multiline_bounds fid="lines.1">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 1,-1 1,-1 -1,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:multiline_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multiline_bounds fid="lines.2">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,1 5.024184261036468,1.0 5.024184261036468,2.414779270633399 3.0,2.414779270633399 3,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:multiline_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multiline_bounds fid="lines.3">
+ </ogr:multiline_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multiline_bounds fid="lines.4">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,0 5.58042226487524,0.0 5.58042226487524,4.119769673704415 2.0,4.119769673704415 2,0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:multiline_bounds>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/multiline_bounds.xsd b/python/plugins/processing/tests/testdata/expected/multiline_bounds.xsd
new file mode 100644
index 0000000..93d7a1e
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multiline_bounds.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="multiline_bounds" type="ogr:multiline_bounds_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="multiline_bounds_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/multipoint_bounds.gml b/python/plugins/processing/tests/testdata/expected/multipoint_bounds.gml
new file mode 100644
index 0000000..fb52559
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multipoint_bounds.gml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ multipoint_bounds.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
+ <gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:multipoint_bounds fid="points.9">
+ <ogr:d>5</ogr:d>
+ </ogr:multipoint_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoint_bounds fid="points.0">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>1,1 3,1 3,3 1,3 1,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:d>1</ogr:d>
+ </ogr:multipoint_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoint_bounds fid="points.3">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4,1 5,1 5,2 4,2 4,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:d>2</ogr:d>
+ </ogr:multipoint_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoint_bounds fid="points.5">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0,-5 8,-5 8,-1 0,-1 0,-5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:d>3</ogr:d>
+ </ogr:multipoint_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoint_bounds fid="points.7">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0,-1 7,-1 7,-1 0,-1 0,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:d>4</ogr:d>
+ </ogr:multipoint_bounds>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/multipoint_bounds.xsd b/python/plugins/processing/tests/testdata/expected/multipoint_bounds.xsd
new file mode 100644
index 0000000..3aca844
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multipoint_bounds.xsd
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="multipoint_bounds" type="ogr:multipoint_bounds_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="multipoint_bounds_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:GeometryPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="d" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="16"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/multipoly_boundary.gml b/python/plugins/processing/tests/testdata/expected/multipoly_boundary.gml
new file mode 100644
index 0000000..d856763
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multipoly_boundary.gml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ multipoly_boundary.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>9</gml:X><gml:Y>6</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:multipoly_boundary fid="multipolys.0">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,1 2,2 3,2 3,3 4,3 4,1 2,1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ <ogr:Bname>Test</ogr:Bname>
+ <ogr:Bintval>1</ogr:Bintval>
+ <ogr:Bfloatval>0.123</ogr:Bfloatval>
+ </ogr:multipoly_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoly_boundary fid="multipolys.1">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>7,-1 8,-1 8,3 7,3 7,-1</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>7,6 7,5 7,4 8,4 9,5 9,6 7,6</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:multipoly_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoly_boundary fid="multipolys.2">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>0,0 0,1 1,1 1,0 0,0</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ <ogr:Bname>Test</ogr:Bname>
+ <ogr:Bintval>2</ogr:Bintval>
+ <ogr:Bfloatval>-0.123</ogr:Bfloatval>
+ </ogr:multipoly_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoly_boundary fid="multipolys.3">
+ <ogr:Bname>Test</ogr:Bname>
+ <ogr:Bintval>3</ogr:Bintval>
+ <ogr:Bfloatval>0</ogr:Bfloatval>
+ </ogr:multipoly_boundary>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/multipoly_boundary.xsd b/python/plugins/processing/tests/testdata/expected/multipoly_boundary.xsd
new file mode 100644
index 0000000..8563aa7
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multipoly_boundary.xsd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="multipoly_boundary" type="ogr:multipoly_boundary_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="multipoly_boundary_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:MultiLineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="Bname" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="Bintval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="16"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="Bfloatval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/multipoly_bounds.gml b/python/plugins/processing/tests/testdata/expected/multipoly_bounds.gml
new file mode 100644
index 0000000..98fb972
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multipoly_bounds.gml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ multipoly_bounds.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>9</gml:X><gml:Y>6</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:multipoly_bounds fid="multipolys.0">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,1 4,1 4,3 2,3 2,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:Bname>Test</ogr:Bname>
+ <ogr:Bintval>1</ogr:Bintval>
+ <ogr:Bfloatval>0.123</ogr:Bfloatval>
+ </ogr:multipoly_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoly_bounds fid="multipolys.1">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>7,-1 9,-1 9,6 7,6 7,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:multipoly_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoly_bounds fid="multipolys.2">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0,0 1,0 1,1 0,1 0,0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:Bname>Test</ogr:Bname>
+ <ogr:Bintval>2</ogr:Bintval>
+ <ogr:Bfloatval>-0.123</ogr:Bfloatval>
+ </ogr:multipoly_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoly_bounds fid="multipolys.3">
+ <ogr:Bname>Test</ogr:Bname>
+ <ogr:Bintval>3</ogr:Bintval>
+ <ogr:Bfloatval>0</ogr:Bfloatval>
+ </ogr:multipoly_bounds>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/multipoly_bounds.xsd b/python/plugins/processing/tests/testdata/expected/multipoly_bounds.xsd
new file mode 100644
index 0000000..f44a581
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/multipoly_bounds.xsd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="multipoly_bounds" type="ogr:multipoly_bounds_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="multipoly_bounds_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="Bname" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="Bintval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="16"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="Bfloatval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/point_bounds.gml b/python/plugins/processing/tests/testdata/expected/point_bounds.gml
new file mode 100644
index 0000000..804add3
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/point_bounds.gml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ point_bounds.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
+ <gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:point_bounds fid="points.0">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>1,1 1,1 1,1 1,1 1,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:point_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_bounds fid="points.1">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,3 3,3 3,3 3,3 3,3</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:point_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_bounds fid="points.2">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,2 2,2 2,2 2,2 2,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:point_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_bounds fid="points.3">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5,2 5,2 5,2 5,2 5,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:point_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_bounds fid="points.4">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4,1 4,1 4,1 4,1 4,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:point_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_bounds fid="points.5">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0,-5 0,-5 0,-5 0,-5 0,-5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:point_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_bounds fid="points.6">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>8,-1 8,-1 8,-1 8,-1 8,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:point_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_bounds fid="points.7">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>7,-1 7,-1 7,-1 7,-1 7,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:point_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_bounds fid="points.8">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0,-1 0,-1 0,-1 0,-1 0,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ </ogr:point_bounds>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/point_bounds.xsd b/python/plugins/processing/tests/testdata/expected/point_bounds.xsd
new file mode 100644
index 0000000..a73e551
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/point_bounds.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="point_bounds" type="ogr:point_bounds_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="point_bounds_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/point_on_line.gml b/python/plugins/processing/tests/testdata/expected/point_on_line.gml
new file mode 100644
index 0000000..5c5a616
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/point_on_line.gml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ point_on_line.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
+ <gml:coord><gml:X>9</gml:X><gml:Y>3</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:point_on_line fid="lines.0">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>9,3</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:point_on_line>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_line fid="lines.1">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>-1,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:point_on_line>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_line fid="lines.2">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:point_on_line>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_line fid="lines.3">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:point_on_line>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_line fid="lines.4">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-3</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:point_on_line>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_line fid="lines.5">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>6,-3</gml:coordinates></gml:Point></ogr:geometryProperty>
+ </ogr:point_on_line>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_line fid="lines.6">
+ </ogr:point_on_line>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/point_on_line.xsd b/python/plugins/processing/tests/testdata/expected/point_on_line.xsd
new file mode 100644
index 0000000..fab0ad2
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/point_on_line.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="point_on_line" type="ogr:point_on_line_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="point_on_line_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/point_on_multipoint.gml b/python/plugins/processing/tests/testdata/expected/point_on_multipoint.gml
new file mode 100644
index 0000000..d59071c
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/point_on_multipoint.gml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ point_on_multipoint.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
+ <gml:coord><gml:X>7</gml:X><gml:Y>2</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:point_on_multipoint fid="points.9">
+ <ogr:d>5</ogr:d>
+ </ogr:point_on_multipoint>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_multipoint fid="points.0">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
+ <ogr:d>1</ogr:d>
+ </ogr:point_on_multipoint>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_multipoint fid="points.3">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5,2</gml:coordinates></gml:Point></ogr:geometryProperty>
+ <ogr:d>2</ogr:d>
+ </ogr:point_on_multipoint>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_multipoint fid="points.5">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-5</gml:coordinates></gml:Point></ogr:geometryProperty>
+ <ogr:d>3</ogr:d>
+ </ogr:point_on_multipoint>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_multipoint fid="points.7">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
+ <ogr:d>4</ogr:d>
+ </ogr:point_on_multipoint>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/point_on_multipoint.xsd b/python/plugins/processing/tests/testdata/expected/point_on_multipoint.xsd
new file mode 100644
index 0000000..a51301c
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/point_on_multipoint.xsd
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="point_on_multipoint" type="ogr:point_on_multipoint_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="point_on_multipoint_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:GeometryPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="d" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="16"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/point_on_poly.gml b/python/plugins/processing/tests/testdata/expected/point_on_poly.gml
new file mode 100644
index 0000000..31eead2
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/point_on_poly.gml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ point_on_poly.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0.5</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>6.5</gml:X><gml:Y>5.5</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:point_on_poly fid="polys.0">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0.5,0.5</gml:coordinates></gml:Point></ogr:geometryProperty>
+ <ogr:name>aaaaa</ogr:name>
+ <ogr:intval>33</ogr:intval>
+ <ogr:floatval>44.123456</ogr:floatval>
+ </ogr:point_on_poly>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_poly fid="polys.1">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5.0,4.5</gml:coordinates></gml:Point></ogr:geometryProperty>
+ <ogr:name>Aaaaa</ogr:name>
+ <ogr:intval>-33</ogr:intval>
+ <ogr:floatval>0</ogr:floatval>
+ </ogr:point_on_poly>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_poly fid="polys.2">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2.5,5.5</gml:coordinates></gml:Point></ogr:geometryProperty>
+ <ogr:name>bbaaa</ogr:name>
+ <ogr:floatval>0.123</ogr:floatval>
+ </ogr:point_on_poly>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_poly fid="polys.3">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>6.5,-1.0</gml:coordinates></gml:Point></ogr:geometryProperty>
+ <ogr:name>ASDF</ogr:name>
+ <ogr:intval>0</ogr:intval>
+ </ogr:point_on_poly>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_poly fid="polys.4">
+ <ogr:intval>120</ogr:intval>
+ <ogr:floatval>-100291.43213</ogr:floatval>
+ </ogr:point_on_poly>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:point_on_poly fid="polys.5">
+ <ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>4,0</gml:coordinates></gml:Point></ogr:geometryProperty>
+ <ogr:name>elim</ogr:name>
+ <ogr:intval>2</ogr:intval>
+ <ogr:floatval>3.33</ogr:floatval>
+ </ogr:point_on_poly>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/point_on_poly.xsd b/python/plugins/processing/tests/testdata/expected/point_on_poly.xsd
new file mode 100644
index 0000000..f3d746e
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/point_on_poly.xsd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="point_on_poly" type="ogr:point_on_poly_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="point_on_poly_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="5"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="intval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="16"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="floatval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/poly_boundary.gml b/python/plugins/processing/tests/testdata/expected/poly_boundary.gml
new file mode 100644
index 0000000..beaf6dc
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/poly_boundary.gml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ poly_boundary.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
+ <gml:coord><gml:X>10</gml:X><gml:Y>6</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:poly_boundary fid="polys.0">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>-1,-1 -1,3 3,3 3,2 2,2 2,-1 -1,-1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ <ogr:name>aaaaa</ogr:name>
+ <ogr:intval>33</ogr:intval>
+ <ogr:floatval>44.123456</ogr:floatval>
+ </ogr:poly_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:poly_boundary fid="polys.1">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>5,5 6,4 4,4 5,5</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ <ogr:name>Aaaaa</ogr:name>
+ <ogr:intval>-33</ogr:intval>
+ <ogr:floatval>0</ogr:floatval>
+ </ogr:poly_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:poly_boundary fid="polys.2">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,5 2,6 3,6 3,5 2,5</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ <ogr:name>bbaaa</ogr:name>
+ <ogr:floatval>0.123</ogr:floatval>
+ </ogr:poly_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:poly_boundary fid="polys.3">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>6,1 10,1 10,-3 6,-3 6,1</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>7,0 7,-2 9,-2 9,0 7,0</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ <ogr:name>ASDF</ogr:name>
+ <ogr:intval>0</ogr:intval>
+ </ogr:poly_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:poly_boundary fid="polys.4">
+ <ogr:intval>120</ogr:intval>
+ <ogr:floatval>-100291.43213</ogr:floatval>
+ </ogr:poly_boundary>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:poly_boundary fid="polys.5">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>3,2 6,1 6,-3 2,-1 2,2 3,2</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ <ogr:name>elim</ogr:name>
+ <ogr:intval>2</ogr:intval>
+ <ogr:floatval>3.33</ogr:floatval>
+ </ogr:poly_boundary>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/poly_boundary.xsd b/python/plugins/processing/tests/testdata/expected/poly_boundary.xsd
new file mode 100644
index 0000000..d698297
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/poly_boundary.xsd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="poly_boundary" type="ogr:poly_boundary_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="poly_boundary_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:MultiLineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="5"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="intval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="16"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="floatval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/expected/poly_bounds.gml b/python/plugins/processing/tests/testdata/expected/poly_bounds.gml
new file mode 100644
index 0000000..028f515
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/poly_bounds.gml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ogr.maptools.org/ poly_bounds.xsd"
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
+ <gml:coord><gml:X>10</gml:X><gml:Y>6</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:poly_bounds fid="polys.0">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 3,-1 3,3 -1,3 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>aaaaa</ogr:name>
+ <ogr:intval>33</ogr:intval>
+ <ogr:floatval>44.123456</ogr:floatval>
+ </ogr:poly_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:poly_bounds fid="polys.1">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4,4 6,4 6,5 4,5 4,4</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>Aaaaa</ogr:name>
+ <ogr:intval>-33</ogr:intval>
+ <ogr:floatval>0</ogr:floatval>
+ </ogr:poly_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:poly_bounds fid="polys.2">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,5 3,5 3,6 2,6 2,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>bbaaa</ogr:name>
+ <ogr:floatval>0.123</ogr:floatval>
+ </ogr:poly_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:poly_bounds fid="polys.3">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6,-3 10,-3 10,1 6,1 6,-3</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>ASDF</ogr:name>
+ <ogr:intval>0</ogr:intval>
+ </ogr:poly_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:poly_bounds fid="polys.4">
+ <ogr:intval>120</ogr:intval>
+ <ogr:floatval>-100291.43213</ogr:floatval>
+ </ogr:poly_bounds>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:poly_bounds fid="polys.5">
+ <ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,-3 6,-3 6,2 2,2 2,-3</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
+ <ogr:name>elim</ogr:name>
+ <ogr:intval>2</ogr:intval>
+ <ogr:floatval>3.33</ogr:floatval>
+ </ogr:poly_bounds>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/expected/poly_bounds.xsd b/python/plugins/processing/tests/testdata/expected/poly_bounds.xsd
new file mode 100644
index 0000000..d2576f4
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/poly_bounds.xsd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
+<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
+<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
+<xs:complexType name="FeatureCollectionType">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureCollectionType">
+ <xs:attribute name="lockId" type="xs:string" use="optional"/>
+ <xs:attribute name="scope" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+<xs:element name="poly_bounds" type="ogr:poly_bounds_Type" substitutionGroup="gml:_Feature"/>
+<xs:complexType name="poly_bounds_Type">
+ <xs:complexContent>
+ <xs:extension base="gml:AbstractFeatureType">
+ <xs:sequence>
+ <xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="5"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="intval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:totalDigits value="16"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="floatval" nillable="true" minOccurs="0" maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+</xs:complexType>
+</xs:schema>
diff --git a/python/plugins/processing/tests/testdata/multilines.gfs b/python/plugins/processing/tests/testdata/multilines.gfs
new file mode 100644
index 0000000..01e53c6
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/multilines.gfs
@@ -0,0 +1,15 @@
+<GMLFeatureClassList>
+ <GMLFeatureClass>
+ <Name>multilines</Name>
+ <ElementPath>multilines</ElementPath>
+ <GeometryType>5</GeometryType>
+ <SRSName>EPSG:4326</SRSName>
+ <DatasetSpecificInfo>
+ <FeatureCount>4</FeatureCount>
+ <ExtentXMin>-1.00000</ExtentXMin>
+ <ExtentXMax>5.58042</ExtentXMax>
+ <ExtentYMin>-1.00000</ExtentYMin>
+ <ExtentYMax>4.11977</ExtentYMax>
+ </DatasetSpecificInfo>
+ </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/python/plugins/processing/tests/testdata/multilines.gml b/python/plugins/processing/tests/testdata/multilines.gml
new file mode 100644
index 0000000..bced644
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/multilines.gml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation=""
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>-1</gml:X><gml:Y>-1</gml:Y></gml:coord>
+ <gml:coord><gml:X>5.58042226487524</gml:X><gml:Y>4.119769673704415</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:multilines fid="lines.1">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:multilines>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multilines fid="lines.2">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>5.024184261036468,2.414779270633399 5,1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
+ </ogr:multilines>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multilines fid="lines.3">
+ </ogr:multilines>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multilines fid="lines.4">
+ <ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,0 2,2 3,2 3,3</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2.944337811900192,4.04721689059501 5.459500959692898,4.119769673704415</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>3,3 5.58042226487524,2.946833013435702</gml:coordinates>< [...]
+ </ogr:multilines>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/multipoints.gfs b/python/plugins/processing/tests/testdata/multipoints.gfs
new file mode 100644
index 0000000..335620f
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/multipoints.gfs
@@ -0,0 +1,19 @@
+<GMLFeatureClassList>
+ <GMLFeatureClass>
+ <Name>multipoints</Name>
+ <ElementPath>multipoints</ElementPath>
+ <SRSName>EPSG:4326</SRSName>
+ <DatasetSpecificInfo>
+ <FeatureCount>5</FeatureCount>
+ <ExtentXMin>0.00000</ExtentXMin>
+ <ExtentXMax>8.00000</ExtentXMax>
+ <ExtentYMin>-5.00000</ExtentYMin>
+ <ExtentYMax>3.00000</ExtentYMax>
+ </DatasetSpecificInfo>
+ <PropertyDefn>
+ <Name>d</Name>
+ <ElementPath>d</ElementPath>
+ <Type>Integer</Type>
+ </PropertyDefn>
+ </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/python/plugins/processing/tests/testdata/multipoints.gml b/python/plugins/processing/tests/testdata/multipoints.gml
new file mode 100644
index 0000000..b5fdece
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/multipoints.gml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation=""
+ xmlns:ogr="http://ogr.maptools.org/"
+ xmlns:gml="http://www.opengis.net/gml">
+ <gml:boundedBy>
+ <gml:Box>
+ <gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
+ <gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
+ </gml:Box>
+ </gml:boundedBy>
+
+ <gml:featureMember>
+ <ogr:multipoints fid="points.9">
+ <ogr:d>5</ogr:d>
+ </ogr:multipoints>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoints fid="points.0">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>2,2</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>3,3</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ <ogr:d>1</ogr:d>
+ </ogr:multipoints>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoints fid="points.3">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>5,2</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>4,1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ <ogr:d>2</ogr:d>
+ </ogr:multipoints>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoints fid="points.5">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>0,-5</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>8,-1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ <ogr:d>3</ogr:d>
+ </ogr:multipoints>
+ </gml:featureMember>
+ <gml:featureMember>
+ <ogr:multipoints fid="points.7">
+ <ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>7,-1</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>0,-1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
+ <ogr:d>4</ogr:d>
+ </ogr:multipoints>
+ </gml:featureMember>
+</ogr:FeatureCollection>
diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
index 053b627..07b594e 100644
--- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
+++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
@@ -23,7 +23,93 @@ tests:
OUTPUT:
name: expected/polys_deleteholes.gml
type: vector
-
+
+ - algorithm: qgis:clip
+ name: Clip lines by polygons
+ params:
+ INPUT:
+ name: custom/lines2.gml
+ type: vector
+ OVERLAY:
+ name: polys.gml
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/clip_lines_by_polygon.gml
+ type: vector
+
+
+ - algorithm: qgis:clip
+ name: Clip lines by multipolygon
+ params:
+ INPUT:
+ name: lines.gml
+ type: vector
+ OVERLAY:
+ name: multipolys.gml
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/clip_lines_by_multipolygon.gml
+ type: vector
+
+ - algorithm: qgis:clip
+ name: Clip polygons by multipolygons
+ params:
+ INPUT:
+ name: polys.gml
+ type: vector
+ OVERLAY:
+ name: multipolys.gml
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/clip_polys_by_multipolygon.gml
+ type: vector
+
+ - algorithm: qgis:clip
+ name: Clip multipolygons by polygons
+ params:
+ INPUT:
+ name: multipolys.gml
+ type: vector
+ OVERLAY:
+ name: polys.gml
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/clip_multipolygons_by_polygons.gml
+ type: vector
+
+ - algorithm: qgis:clip
+ name: Clip points by polygons
+ params:
+ INPUT:
+ name: points.gml
+ type: vector
+ OVERLAY:
+ name: polys.gml
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/clip_points_by_polygons.gml
+ type: vector
+
+ - algorithm: qgis:clip
+ name: Clip points by multipolygons
+ params:
+ INPUT:
+ name: points.gml
+ type: vector
+ OVERLAY:
+ name: multipolys.gml
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/clip_points_by_multipolygons.gml
+ type: vector
+
+
# These datasets should produce a geometry collection and not a polygon only
# dataset. If the algorithm is fixed, a new test should be introduced to
# check this behavior.
@@ -38,6 +124,7 @@ tests:
INPUT2:
name: polys.gml
type: vector
+ IGNORE_NULL: True
results:
OUTPUT:
name: expected/intersection_collection_fallback.shp
@@ -205,6 +292,31 @@ tests:
name: expected/eliminate_largest_area.gml
type: vector
+ - algorithm: qgis:dissolve
+ name: Dissolve using field
+ params:
+ DISSOLVE_ALL: false
+ FIELD: name
+ INPUT:
+ name: dissolve_polys.gml
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/dissolve_field.gml
+ type: vector
+
+ - algorithm: qgis:dissolve
+ name: Dissolve using two fields
+ params:
+ DISSOLVE_ALL: false
+ FIELD: intval;name
+ INPUT:
+ name: dissolve_polys.gml
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/dissolve_two_fields.gml
+ type: vector
- name: Dissolve with geometries reported as valid but as invalid with isGeosValid
algorithm: qgis:dissolve
@@ -306,3 +418,168 @@ tests:
compare:
geometry:
precision: 7
+
+ - algorithm: qgis:mergelines
+ name: Merge lines algorithm
+ params:
+ INPUT_LAYER:
+ name: multilines.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/merge_lines.gml
+ type: vector
+
+ - algorithm: qgis:multiparttosingleparts
+ name: Multiparts to singleparts
+ params:
+ INPUT:
+ name: multilines.gml
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/multi_to_single.gml
+ type: vector
+
+ - algorithm: qgis:boundingboxes
+ name: Bounding boxes for lines
+ params:
+ INPUT_LAYER:
+ name: lines.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/lines_bounds.gml
+ type: vector
+
+ - algorithm: qgis:boundingboxes
+ name: Bounding boxes for multilines
+ params:
+ INPUT_LAYER:
+ name: multilines.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/multiline_bounds.gml
+ type: vector
+
+ - algorithm: qgis:boundingboxes
+ name: Bounding boxes for multipolygons
+ params:
+ INPUT_LAYER:
+ name: multipolys.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/multipoly_bounds.gml
+ type: vector
+
+ - algorithm: qgis:boundingboxes
+ name: Bounding boxes for points
+ params:
+ INPUT_LAYER:
+ name: points.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/point_bounds.gml
+ type: vector
+
+ - algorithm: qgis:boundingboxes
+ name: Bounding boxes for polygons
+ params:
+ INPUT_LAYER:
+ name: polys.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/poly_bounds.gml
+ type: vector
+
+ - algorithm: qgis:boundingboxes
+ name: Bounding boxes for multipoints
+ params:
+ INPUT_LAYER:
+ name: multipoints.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/multipoint_bounds.gml
+ type: vector
+
+ - algorithm: qgis:boundary
+ name: Polygon boundary
+ params:
+ INPUT_LAYER:
+ name: polys.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/poly_boundary.gml
+ type: vector
+
+ - algorithm: qgis:boundary
+ name: Multipoly boundary
+ params:
+ INPUT_LAYER:
+ name: multipolys.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/multipoly_boundary.gml
+ type: vector
+
+ - algorithm: qgis:boundary
+ name: Line boundary
+ params:
+ INPUT_LAYER:
+ name: lines.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/lines_boundary.gml
+ type: vector
+
+ - algorithm: qgis:boundary
+ name: Multiline boundary
+ params:
+ INPUT_LAYER:
+ name: multilines.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/multiline_boundary.gml
+ type: vector
+
+ - algorithm: qgis:pointonsurface
+ name: Point on polygon surface
+ params:
+ INPUT_LAYER:
+ name: polys.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/point_on_poly.gml
+ type: vector
+
+ - algorithm: qgis:pointonsurface
+ name: Point on multipoint surface
+ params:
+ INPUT_LAYER:
+ name: multipoints.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/point_on_multipoint.gml
+ type: vector
+
+ - algorithm: qgis:pointonsurface
+ name: Point on line surface
+ params:
+ INPUT_LAYER:
+ name: lines.gml
+ type: vector
+ results:
+ OUTPUT_LAYER:
+ name: expected/point_on_line.gml
+ type: vector
diff --git a/python/plugins/processing/tools/dataobjects.py b/python/plugins/processing/tools/dataobjects.py
index b62ce70..d98d846 100644
--- a/python/plugins/processing/tools/dataobjects.py
+++ b/python/plugins/processing/tools/dataobjects.py
@@ -253,14 +253,15 @@ def getObjectFromUri(uri, forceLoad=True):
settings.setValue('/Projections/defaultBehaviour', '')
# If is not opened, we open it
+ name = os.path.basename(uri)
for provider in ['ogr', 'postgres', 'spatialite', 'virtual']:
- layer = QgsVectorLayer(uri, uri, provider)
+ layer = QgsVectorLayer(uri, name, provider)
if layer.isValid():
if prjSetting:
settings.setValue('/Projections/defaultBehaviour', prjSetting)
_loadedLayers[normalizeLayerSource(layer.source())] = layer
return layer
- layer = QgsRasterLayer(uri, uri)
+ layer = QgsRasterLayer(uri, name)
if layer.isValid():
if prjSetting:
settings.setValue('/Projections/defaultBehaviour', prjSetting)
@@ -290,18 +291,7 @@ def exportVectorLayer(layer, supported=None):
settings = QSettings()
systemEncoding = settings.value('/UI/encoding', 'System')
- filename = os.path.basename(unicode(layer.source()))
- idx = filename.rfind('.')
- if idx != -1:
- filename = filename[:idx]
-
- filename = unicode(layer.name())
- validChars = \
- 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:'
- filename = ''.join(c for c in filename if c in validChars)
- if len(filename) == 0:
- filename = 'layer'
- output = getTempFilenameInTempFolder(filename + '.shp')
+ output = getTempFilename('shp')
provider = layer.dataProvider()
useSelection = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
if useSelection and layer.selectedFeatureCount() != 0:
diff --git a/python/plugins/processing/tools/postgis.py b/python/plugins/processing/tools/postgis.py
index d938cee..69fab99 100644
--- a/python/plugins/processing/tools/postgis.py
+++ b/python/plugins/processing/tools/postgis.py
@@ -181,6 +181,7 @@ class GeoDB:
passwd=None, service=None, uri=None):
# Regular expression for identifiers without need to quote them
self.re_ident_ok = re.compile(r"^\w+$")
+ port = str(port)
if uri:
self.uri = uri
@@ -194,7 +195,7 @@ class GeoDB:
conninfo = self.uri.connectionInfo(False)
err = None
for i in range(4):
- expandedConnInfo = uri.connectionInfo(True)
+ expandedConnInfo = self.uri.connectionInfo(True)
try:
self.con = psycopg2.connect(expandedConnInfo.encode('utf-8'))
if err is not None:
diff --git a/python/plugins/processing/tools/vector.py b/python/plugins/processing/tools/vector.py
index babac40..1ae8dc4 100644
--- a/python/plugins/processing/tools/vector.py
+++ b/python/plugins/processing/tools/vector.py
@@ -34,10 +34,13 @@ import cStringIO
import psycopg2
+from osgeo import ogr
+
from qgis.PyQt.QtCore import QVariant, QSettings
from qgis.core import (QGis, QgsFields, QgsField, QgsGeometry, QgsRectangle,
QgsSpatialIndex, QgsMapLayerRegistry, QgsMapLayer, QgsVectorLayer,
- QgsVectorFileWriter, QgsDistanceArea, QgsDataSourceURI, QgsCredentials)
+ QgsVectorFileWriter, QgsDistanceArea, QgsDataSourceURI, QgsCredentials,
+ QgsFeatureRequest)
from processing.core.ProcessingConfig import ProcessingConfig
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
@@ -86,7 +89,7 @@ TYPE_MAP_SPATIALITE_LAYER = {
}
-def features(layer):
+def features(layer, request=QgsFeatureRequest()):
"""This returns an iterator over features in a vector layer,
considering the selection that might exist in the layer, and the
configuration that indicates whether to use only selected feature
@@ -97,15 +100,15 @@ def features(layer):
"""
class Features:
- def __init__(self, layer):
+ def __init__(self, layer, request):
self.layer = layer
self.selection = False
- self.iter = layer.getFeatures()
- if ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED):
- selected = layer.selectedFeatures()
- if len(selected) > 0:
- self.selection = True
- self.iter = iter(selected)
+ if ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)\
+ and layer.selectedFeatureCount() > 0:
+ self.iter = layer.selectedFeaturesIterator(request)
+ self.selection = True
+ else:
+ self.iter = layer.getFeatures(request)
def __iter__(self):
return self.iter
@@ -116,7 +119,7 @@ def features(layer):
else:
return int(self.layer.featureCount())
- return Features(layer)
+ return Features(layer, request)
def uniqueValues(layer, attribute):
@@ -199,7 +202,13 @@ def testForUniqueness(fieldList1, fieldList2):
def spatialindex(layer):
"""Creates a spatial index for the passed vector layer.
"""
- idx = QgsSpatialIndex(layer.getFeatures())
+ request = QgsFeatureRequest()
+ request.setSubsetOfAttributes([])
+ if ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED) \
+ and layer.selectedFeatureCount() > 0:
+ idx = QgsSpatialIndex(layer.selectedFeaturesIterator(request))
+ else:
+ idx = QgsSpatialIndex(layer.getFeatures(request))
return idx
@@ -508,21 +517,67 @@ def ogrConnectionString(uri):
return '"' + ogrstr + '"'
+#
+# The uri parameter is an URI from any QGIS provider,
+# so could have different formats.
+# Example formats:
+#
+# -- PostgreSQL provider
+# port=5493 sslmode=disable key='edge_id' srid=0 type=LineString table="city_data"."edge" (geom) sql=
+#
+# -- Spatialite provider
+# dbname='/tmp/x.sqlite' table="t" (geometry) sql='
+#
+# -- OGR provider (single-layer directory)
+# /tmp/x.gdb
+#
+# -- OGR provider (multi-layer directory)
+# /tmp/x.gdb|layerid=1
+#
+# -- OGR provider (multi-layer directory)
+# /tmp/x.gdb|layername=thelayer
+#
def ogrLayerName(uri):
- if 'host' in uri:
- regex = re.compile('(table=")(.+?)(\.)(.+?)"')
- r = regex.search(uri)
- return '"' + r.groups()[1] + '.' + r.groups()[3] + '"'
- elif 'dbname' in uri:
- regex = re.compile('(table=")(.+?)"')
- r = regex.search(uri)
- return r.groups()[1]
- elif 'layername' in uri:
- regex = re.compile('(layername=)(.*)')
+
+ # handle URIs of database providers
+ if ' table=' in uri:
+ # Matches table="schema"."table"
+ re_table_schema = re.compile(' table="([^"]*)"\."([^"]*)"')
+ r = re_table_schema.search(uri)
+ if r:
+ return r.groups()[0] + '.' + r.groups()[1]
+ # Matches table="table"
+ re_table = re.compile(' table="([^"]*)"')
+ r = re_table.search(uri)
+ if r:
+ return r.groups()[0]
+
+ # handle URIs of OGR provider with explicit layername
+ if 'layername' in uri:
+ regex = re.compile('(layername=)([^|]*)')
r = regex.search(uri)
return r.groups()[1]
- else:
- return os.path.basename(os.path.splitext(uri)[0])
+
+ fields = uri.split('|')
+ ogruri = fields[0]
+ fields = fields[1:]
+ layerid = 0
+ for f in fields:
+ if f.startswith('layername='):
+ # Name encoded in uri, nothing more needed
+ return f.split('=')[1]
+ if f.startswith('layerid='):
+ layerid = int(f.split('=')[1])
+ # Last layerid= takes precedence, to allow of layername to
+ # take precedence
+ ds = ogr.Open(ogruri)
+ if not ds:
+ return "invalid-uri"
+ ly = ds.GetLayer(layerid)
+ if not ly:
+ return "invalid-layerid"
+ name = ly.GetName()
+ return name
class VectorWriter:
diff --git a/python/pyplugin_installer/installer_data.py b/python/pyplugin_installer/installer_data.py
index 9208e41..6d4d95b 100644
--- a/python/pyplugin_installer/installer_data.py
+++ b/python/pyplugin_installer/installer_data.py
@@ -761,7 +761,7 @@ class Plugins(QObject):
# other remote metadata is preffered:
for attrib in ["name", "plugin_id", "description", "about", "category", "tags", "changelog", "author_name", "author_email", "homepage",
"tracker", "code_repository", "experimental", "deprecated", "version_available", "zip_repository",
- "download_url", "filename", "downloads", "average_vote", "rating_votes"]:
+ "download_url", "filename", "downloads", "average_vote", "rating_votes", "trusted"]:
if attrib not in translatableAttributes or attrib == "name": # include name!
if plugin[attrib]:
self.mPlugins[key][attrib] = plugin[attrib]
diff --git a/python/qsci_apis/pyqgis.pap b/python/qsci_apis/pyqgis.pap
index fc9c3d3..fa85424 100644
Binary files a/python/qsci_apis/pyqgis.pap and b/python/qsci_apis/pyqgis.pap differ
diff --git a/python/server/qgswmsconfigparser.sip b/python/server/qgswmsconfigparser.sip
index b08655c..f05752c 100644
--- a/python/server/qgswmsconfigparser.sip
+++ b/python/server/qgswmsconfigparser.sip
@@ -53,6 +53,9 @@ class QgsWMSConfigParser
/** True if the feature info response should contain the wkt geometry for vector features*/
virtual bool featureInfoWithWktGeometry() const = 0;
+ /** True if the feature info wkt geometry is delivered with segmentized curve types*/
+ virtual bool segmentizeFeatureInfoWktGeometry() const = 0;
+
/** Returns map with layer aliases for GetFeatureInfo (or 0 pointer if not supported). Key: layer name, Value: layer alias*/
virtual QHash<QString, QString> featureInfoLayerAliasMap() const = 0;
diff --git a/python/server/qgswmsprojectparser.sip b/python/server/qgswmsprojectparser.sip
index 4d22fc3..f6dd579 100644
--- a/python/server/qgswmsprojectparser.sip
+++ b/python/server/qgswmsprojectparser.sip
@@ -83,6 +83,10 @@ class QgsWMSProjectParser : public QgsWMSConfigParser
/** True if the feature info response should contain the wkt geometry for vector features*/
bool featureInfoWithWktGeometry() const /*override*/ ;
+ /** True if the feature info wkt geometry is delivered with segmentized curve types*/
+ bool segmentizeFeatureInfoWktGeometry() const /*override*/ ;
+
+
/** Returns map with layer aliases for GetFeatureInfo (or 0 pointer if not supported). Key: layer name, Value: layer alias*/
QHash<QString, QString> featureInfoLayerAliasMap() const /*override*/ ;
diff --git a/resources/context_help/HeatmapGui b/resources/context_help/HeatmapGui
index e722f10..612d8d2 100644
--- a/resources/context_help/HeatmapGui
+++ b/resources/context_help/HeatmapGui
@@ -26,7 +26,7 @@ clustering of points.</p>
<h4>Rows and Columns</h4>
<p>Used to change the dimensions of the output raster file. These values are also linked to the <b>Cell size X</b> and <b>Cell size Y</b> values.
-Increasing the number of rows or colums will decrease the cell size and increase the file size of the output file. The values in Rows and Columns
+Increasing the number of rows or columns will decrease the cell size and increase the file size of the output file. The values in Rows and Columns
are also linked, so doubling the number of rows will automatically double the number of columns and the cell sizes will also be halved. The geographical area of the output raster will remain the same!</p>
<h4>Cell size X and Y</h4>
diff --git a/resources/function_help/json/ILIKE b/resources/function_help/json/ILIKE
index 26968df..a17e8bf 100644
--- a/resources/function_help/json/ILIKE
+++ b/resources/function_help/json/ILIKE
@@ -3,16 +3,22 @@
"type": "operator",
"description": "Returns 1 if the first parameter matches case-insensitive the supplied pattern. LIKE can be used instead of ILIKE to make the match case-sensitive. Works with numbers also.",
"arguments": [
- {"arg":"string/number","description":"string to search"},
- {"arg":"pattern","description":"pattern to find"}
+ {"arg":"string/number","description":"string to search"},
+ {"arg":"pattern","description":"pattern to find, you can use '%' as a wildcard, '_' as a single char and '\\\\' to escape."}
],
"examples": [
- { "expression":"'A' ILIKE 'A'", "returns":"1"},
- { "expression":"'A' ILIKE 'a'", "returns":"1"},
- { "expression":"'A' ILIKE 'B'", "returns":"0"},
- { "expression":"'ABC' ILIKE 'b'", "returns":"0"},
- { "expression":"'ABC' ILIKE 'B'", "returns":"0"},
- { "expression":"'ABC' ILIKE '%b%'", "returns":"1"},
- { "expression":"'ABC' ILIKE '%B%'", "returns":"1"}
+ { "expression":"'A' ILIKE 'A'", "returns":"1"},
+ { "expression":"'A' ILIKE 'a'", "returns":"1"},
+ { "expression":"'A' ILIKE 'B'", "returns":"0"},
+ { "expression":"'ABC' ILIKE 'b'", "returns":"0"},
+ { "expression":"'ABC' ILIKE 'B'", "returns":"0"},
+ { "expression":"'ABC' ILIKE '_b_'", "returns":"1"},
+ { "expression":"'ABC' ILIKE '_B_'", "returns":"1"},
+ { "expression":"'ABCD' ILIKE '_b_'", "returns":"0"},
+ { "expression":"'ABCD' ILIKE '_B_'", "returns":"0"},
+ { "expression":"'ABCD' ILIKE '_b%'", "returns":"1"},
+ { "expression":"'ABCD' ILIKE '_B%'", "returns":"1"},
+ { "expression":"'ABCD' ILIKE '%b%'", "returns":"1"},
+ { "expression":"'ABCD' ILIKE '%B%'", "returns":"1"}
]
}
diff --git a/resources/function_help/json/LIKE b/resources/function_help/json/LIKE
index 2dba3f8..2ff339b 100644
--- a/resources/function_help/json/LIKE
+++ b/resources/function_help/json/LIKE
@@ -3,14 +3,19 @@
"type": "operator",
"description": "Returns 1 if the first parameter matches the supplied pattern. Works with numbers also.",
"arguments": [
- {"arg":"string/number","description":"value"},
- {"arg":"pattern","description":"pattern to compare value with"}
+ {"arg":"string/number","description":"value"},
+ {"arg":"pattern","description":"pattern to compare value with, you can use '%' as a wildcard, '_' as a single char and '\\\\' to escape."}
],
"examples": [
- { "expression":"'A' LIKE 'A'", "returns":"1"},
- { "expression":"'A' LIKE 'a'", "returns":"0"},
- { "expression":"'A' LIKE 'B'", "returns":"0"},
- { "expression":"'ABC' LIKE 'B'", "returns":"0"},
- { "expression":"'ABC' LIKE '%B%'", "returns":"1"}
+ { "expression":"'A' LIKE 'A'", "returns":"1"},
+ { "expression":"'A' LIKE 'a'", "returns":"0"},
+ { "expression":"'A' LIKE 'B'", "returns":"0"},
+ { "expression":"'ABC' LIKE 'B'", "returns":"0"},
+ { "expression":"'ABC' LIKE '_B_'", "returns":"1"},
+ { "expression":"'ABCD' LIKE '_B_'", "returns":"0"},
+ { "expression":"'ABCD' LIKE '_B%'", "returns":"1"},
+ { "expression":"'ABCD' LIKE '%B%'", "returns":"1"},
+ { "expression":"'1%' LIKE '1\\\\%'", "returns":"1"},
+ { "expression":"'1_' LIKE '1\\\\%'", "returns":"0"}
]
}
diff --git a/resources/function_help/json/angle_at_vertex b/resources/function_help/json/angle_at_vertex
new file mode 100644
index 0000000..2a585b0
--- /dev/null
+++ b/resources/function_help/json/angle_at_vertex
@@ -0,0 +1,8 @@
+{
+ "name": "angle_at_vertex",
+ "type": "function",
+ "description": "Returns the bisector angle (average angle) to the geometry for a specified vertex on a linestring geometry. Angles are in degrees clockwise from north.",
+ "arguments": [ {"arg":"geometry","description":"a linestring geometry"},
+ {"arg":"vertex","description":"vertex index, starting from 0"}],
+ "examples": [ { "expression":"angle_at_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)", "returns":"45.0"}]
+}
diff --git a/resources/function_help/json/boundary b/resources/function_help/json/boundary
new file mode 100644
index 0000000..2fb8b0f
--- /dev/null
+++ b/resources/function_help/json/boundary
@@ -0,0 +1,8 @@
+{
+ "name": "boundary",
+ "type": "function",
+ "description":"Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the geometry). For instance, a polygon geometry will have a boundary consisting of the linestrings for each ring in the polygon. Some geometry types do not have a defined boundary, eg points or geometry collections, and will return null.",
+ "arguments": [ {"arg":"geometry","description":"a geometry"} ],
+ "examples": [ { "expression":"geom_to_wkt(boundary(geom_from_wkt('Polygon((1 1, 0 0, -1 1, 1 1))')))", "returns":"'LineString(1 1,0 0,-1 1,1 1)'"}]
+}
+
diff --git a/resources/function_help/json/distance_to_vertex b/resources/function_help/json/distance_to_vertex
new file mode 100644
index 0000000..7350736
--- /dev/null
+++ b/resources/function_help/json/distance_to_vertex
@@ -0,0 +1,8 @@
+{
+ "name": "distance_to_vertex",
+ "type": "function",
+ "description": "Returns the distance along the geometry to a specified vertex.",
+ "arguments": [ {"arg":"geometry","description":"a linestring geometry"},
+ {"arg":"vertex","description":"vertex index, starting from 0"}],
+ "examples": [ { "expression":"distance_to_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)", "returns":"10.0"}]
+}
diff --git a/resources/function_help/json/line_interpolate_angle b/resources/function_help/json/line_interpolate_angle
new file mode 100644
index 0000000..490cdeb
--- /dev/null
+++ b/resources/function_help/json/line_interpolate_angle
@@ -0,0 +1,8 @@
+{
+ "name": "line_interpolate_angle",
+ "type": "function",
+ "description": "Returns the angle parallel to the geometry at a specified distance along a linestring geometry. Angles are in degrees clockwise from north.",
+ "arguments": [ {"arg":"geometry","description":"a linestring geometry"},
+ {"arg":"distance","description":"distance along line to interpolate angle at"}],
+ "examples": [ { "expression":"line_interpolate_angle(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),distance:=5)", "returns":"90.0"}]
+}
diff --git a/resources/function_help/json/line_interpolate_point b/resources/function_help/json/line_interpolate_point
new file mode 100644
index 0000000..4b5eaf3
--- /dev/null
+++ b/resources/function_help/json/line_interpolate_point
@@ -0,0 +1,8 @@
+{
+ "name": "line_interpolate_point",
+ "type": "function",
+ "description": "Returns the point interpolated by a specified distance along a linestring geometry.",
+ "arguments": [ {"arg":"geometry","description":"a linestring geometry"},
+ {"arg":"distance","description":"distance along line to interpolate"}],
+ "examples": [ { "expression":"geom_to_wkt(line_interpolate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),distance:=5))", "returns":"'Point (5 0)'"}]
+}
diff --git a/resources/function_help/json/line_locate_point b/resources/function_help/json/line_locate_point
new file mode 100644
index 0000000..6135f1e
--- /dev/null
+++ b/resources/function_help/json/line_locate_point
@@ -0,0 +1,8 @@
+{
+ "name": "line_locate_point",
+ "type": "function",
+ "description": "Returns the distance along a linestring corresponding to the closest position the linestring comes to a specified point geometry.",
+ "arguments": [ {"arg":"geometry","description":"a linestring geometry"},
+ {"arg":"point","description":"point geometry to locate closest position on linestring to"}],
+ "examples": [ { "expression":"line_locate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),point:=geom_from_wkt('Point(5 0)'))", "returns":"5.0"}]
+}
diff --git a/resources/function_help/json/line_merge b/resources/function_help/json/line_merge
new file mode 100644
index 0000000..73cf087
--- /dev/null
+++ b/resources/function_help/json/line_merge
@@ -0,0 +1,9 @@
+{
+ "name": "line_merge",
+ "type": "function",
+ "description":"Returns a LineString or MultiLineString geometry, where any connected LineStrings from the input geometry have been merged into a single linestring. This function will return null if passed a geometry which is not a LineString/MultiLineString.",
+ "arguments": [ {"arg":"geometry","description":"a LineString/MultiLineString geometry"} ],
+ "examples": [ { "expression":"geom_to_wkt(line_merge(geom_from_wkt('MULTILINESTRING((0 0, 1 1),(1 1, 2 2))')))", "returns":"'LineString(0 0,1 1,2 2)'"},
+ { "expression":"geom_to_wkt(line_merge(geom_from_wkt('MULTILINESTRING((0 0, 1 1),(11 1, 21 2))')))", "returns":"'MultiLineString((0 0, 1 1),(11 1, 21 2)'"}]
+}
+
diff --git a/resources/function_help/json/regexp_match b/resources/function_help/json/regexp_match
index 46422a3..90a193f 100644
--- a/resources/function_help/json/regexp_match
+++ b/resources/function_help/json/regexp_match
@@ -3,7 +3,7 @@
"type": "function",
"description": "Returns true if any part of a string matches the supplied regular expression.",
"arguments": [ {"arg":"input_string","description":"the string to test against the regular expression"},
- {"arg":"regex","description":"The regular expression to test against. Backslash characters must be double escaped (eg \"\\\\s\" to match a white space character). Non-greedy regular expressions are not supported."}
+ {"arg":"regex","description":"The regular expression to test against. Backslash characters must be double escaped (eg \"\\\\\\\\s\" to match a white space character). Non-greedy regular expressions are not supported."}
],
- "examples": [ { "expression":"regexp_match('QGIS ROCKS','\\\\sROCKS')", "returns":"true"}]
+ "examples": [ { "expression":"regexp_match('QGIS ROCKS','\\\\\\\\sROCKS')", "returns":"true"}]
}
diff --git a/resources/function_help/json/regexp_replace b/resources/function_help/json/regexp_replace
index 10a0147..aacce80 100644
--- a/resources/function_help/json/regexp_replace
+++ b/resources/function_help/json/regexp_replace
@@ -3,8 +3,8 @@
"type": "function",
"description": "Returns a string with the supplied regular expression replaced.",
"arguments": [ {"arg":"input_string","description":"the string to replace matches in"},
- {"arg":"regex","description":"The regular expression to replace. Backslash characters must be double escaped (eg \"\\\\s\" to match a white space character). Non-greedy regular expressions are not supported."},
- {"arg":"replacement","description":"The string that will replace any matching occurrences of the supplied regular expression. Captured groups can be inserted into the replacement string using \\\\1, \\\\2, etc."}
+ {"arg":"regex","description":"The regular expression to replace. Backslash characters must be double escaped (eg \"\\\\\\\\s\" to match a white space character). Non-greedy regular expressions are not supported."},
+ {"arg":"replacement","description":"The string that will replace any matching occurrences of the supplied regular expression. Captured groups can be inserted into the replacement string using \\\\\\\\1, \\\\\\\\2, etc."}
],
- "examples": [ { "expression":"regexp_replace('QGIS SHOULD ROCK','\\\\sSHOULD\\\\s',' DOES ')", "returns":"'QGIS DOES ROCK'"}]
+ "examples": [ { "expression":"regexp_replace('QGIS SHOULD ROCK','\\\\\\\\sSHOULD\\\\\\\\s',' DOES ')", "returns":"'QGIS DOES ROCK'"}]
}
diff --git a/resources/function_help/json/regexp_substr b/resources/function_help/json/regexp_substr
index 28a6cd4..58fabdb 100644
--- a/resources/function_help/json/regexp_substr
+++ b/resources/function_help/json/regexp_substr
@@ -3,7 +3,7 @@
"type": "function",
"description": "Returns the portion of a string which matches a supplied regular expression.",
"arguments": [ {"arg":"input_string","description":"the string to find matches in"},
- {"arg":"regex","description":"The regular expression to match against. Backslash characters must be double escaped (eg \"\\\\s\" to match a white space character). Non-greedy regular expressions are not supported."}
+ {"arg":"regex","description":"The regular expression to match against. Backslash characters must be double escaped (eg \"\\\\\\\\s\" to match a white space character). Non-greedy regular expressions are not supported."}
],
- "examples": [ { "expression":"regexp_substr('abc123','(\\\\d+)')", "returns":"'123'"}]
+ "examples": [ { "expression":"regexp_substr('abc123','(\\\\\\\\d+)')", "returns":"'123'"}]
}
diff --git a/resources/symbology-ng-style.db b/resources/symbology-ng-style.db
index 130aa0b..4807ad6 100644
Binary files a/resources/symbology-ng-style.db and b/resources/symbology-ng-style.db differ
diff --git a/resources/symbology-ng-style.xml b/resources/symbology-ng-style.xml
index 2d79053..da1fb44 100644
--- a/resources/symbology-ng-style.xml
+++ b/resources/symbology-ng-style.xml
@@ -1430,5 +1430,29 @@
<prop k="discrete" v="0"/>
<prop k="stops" v="0.25;254,204,92,255:0.5;253,141,60,255:0.75;240,59,32,255"/>
</colorramp>
+<colorramp name="Inferno" type="gradient">
+ <prop v="0,0,4,255" k="color1"/>
+ <prop v="252,255,164,255" k="color2"/>
+ <prop v="0" k="discrete"/>
+ <prop v="0.0196078;2,2,12,255:0.0392157;5,4,23,255:0.0588235;10,7,34,255:0.0784314;16,9,45,255:0.0980392;22,11,57,255:0.117647;30,12,69,255:0.137255;38,12,81,255:0.156863;47,10,91,255:0.176471;56,9,98,255:0.196078;64,10,103,255:0.215686;73,11,106,255:0.235294;81,14,108,255:0.254902;89,16,110,255:0.27451;97,19,110,255:0.294118;105,22,110,255:0.313725;113,25,110,255:0.333333;120,28,109,255:0.352941;128,31,108,255:0.372549;136,34,106,255:0.392157;144,37,104,255:0.411765;152,39,102,255 [...]
+ </colorramp>
+ <colorramp name="Magma" type="gradient">
+ <prop v="0,0,4,255" k="color1"/>
+ <prop v="252,253,191,255" k="color2"/>
+ <prop v="0" k="discrete"/>
+ <prop v="0.0196078;2,2,11,255:0.0392157;5,4,22,255:0.0588235;9,7,32,255:0.0784314;14,11,43,255:0.0980392;20,14,54,255:0.117647;26,16,66,255:0.137255;33,17,78,255:0.156863;41,17,90,255:0.176471;49,17,101,255:0.196078;57,15,110,255:0.215686;66,15,117,255:0.235294;74,16,121,255:0.254902;82,19,124,255:0.27451;90,22,126,255:0.294118;98,25,128,255:0.313725;106,28,129,255:0.333333;114,31,129,255:0.352941;121,34,130,255:0.372549;129,37,129,255:0.392157;137,40,129,255:0.411765;145,43,129,25 [...]
+ </colorramp>
+ <colorramp name="Plasma" type="gradient">
+ <prop v="13,8,135,255" k="color1"/>
+ <prop v="240,249,33,255" k="color2"/>
+ <prop v="0" k="discrete"/>
+ <prop v="0.0196078;27,6,141,255:0.0392157;38,5,145,255:0.0588235;47,5,150,255:0.0784314;56,4,154,255:0.0980392;65,4,157,255:0.117647;73,3,160,255:0.137255;81,2,163,255:0.156863;89,1,165,255:0.176471;97,0,167,255:0.196078;105,0,168,255:0.215686;113,0,168,255:0.235294;120,1,168,255:0.254902;128,4,168,255:0.27451;135,7,166,255:0.294118;142,12,164,255:0.313725;149,17,161,255:0.333333;156,23,158,255:0.352941;162,29,154,255:0.372549;168,34,150,255:0.392157;174,40,146,255:0.411765;180,46, [...]
+ </colorramp>
+ <colorramp name="Viridis" type="gradient">
+ <prop v="68,1,84,255" k="color1"/>
+ <prop v="253,231,37,255" k="color2"/>
+ <prop v="0" k="discrete"/>
+ <prop v="0.0196078;70,8,92,255:0.0392157;71,16,99,255:0.0588235;72,23,105,255:0.0784314;72,29,111,255:0.0980392;72,36,117,255:0.117647;71,42,122,255:0.137255;70,48,126,255:0.156863;69,55,129,255:0.176471;67,61,132,255:0.196078;65,66,135,255:0.215686;63,72,137,255:0.235294;61,78,138,255:0.254902;58,83,139,255:0.27451;56,89,140,255:0.294118;53,94,141,255:0.313725;51,99,141,255:0.333333;49,104,142,255:0.352941;46,109,142,255:0.372549;44,113,142,255:0.392157;42,118,142,255:0.411765;41, [...]
+ </colorramp>
</colorramps>
</qgis_style>
diff --git a/scripts/chkspelling.sh b/scripts/chkspelling.sh
index 40ff89f..7494694 100755
--- a/scripts/chkspelling.sh
+++ b/scripts/chkspelling.sh
@@ -17,6 +17,6 @@
RE=$(echo $(cut -d: -f1 scripts/spelling.dat | sed -e 's/^/\\</; s/$/\\>|/;') | sed -e 's/| /|/g; s/|$//;')
-EX="\.(svn-base|tmp|xpm|ts|o)|spelling\.dat|Exception_to_GPL_for_Qt.txt|sqlite3.c|qgisstyle|LexerR.py|debian/build*|ms-windows/osgeo4w|ChangeLog|src/plugins/grass/qtermwidget|src/app/gps/qwtpolar-|debian/tmp|src/plugins/dxf2shp_converter/dxflib|python/ext-libs|i18n/"
+EX="\.(svn-base|tmp|xpm|ts|o)|spelling\.dat|Exception_to_GPL_for_Qt.txt|sqlite3.c|qgisstyle|LexerR.py|debian/build.*|debian/.*/usr/|ms-windows/osgeo4w|ChangeLog|src/plugins/grass/qtermwidget|src/app/gps/qwtpolar-|debian/tmp|src/plugins/dxf2shp_converter/dxflib|python/ext-libs|i18n/"
egrep --exclude=*.{png,svg,db,bz2,pdf,qgs,qml,api,pyc} --exclude-dir=.git --exclude-dir=debian/build* --color=always "$RE" -ir . | egrep -iv "$EX"
diff --git a/scripts/generate_test_mask_image.py b/scripts/generate_test_mask_image.py
index 58b7d65..785ea9b 100755
--- a/scripts/generate_test_mask_image.py
+++ b/scripts/generate_test_mask_image.py
@@ -53,7 +53,7 @@ def colorDiff(c1, c2):
def imageFromPath(path):
- if (path[:7] == 'http://' or path[:7] == 'file://'):
+ if (path[:7] == 'http://' or path[:8] == 'https://' or path[:7] == 'file://'):
#fetch remote image
data = urllib2.urlopen(path).read()
image = QImage()
diff --git a/scripts/qgm2cpp.pl b/scripts/qgm2cpp.pl
index 19927e3..c488975 100644
--- a/scripts/qgm2cpp.pl
+++ b/scripts/qgm2cpp.pl
@@ -44,7 +44,7 @@ sub parse {
if $label =~ /^\s+/ || $label =~ /\s+$/ || $label !~ /^[A-Z0-9(]/;
$label =~ s/^\s+//;
$label =~ s/\s+$//;
- $label =~ ucfirst $label;
+ $label = ucfirst $label;
$labels{$label} = 1;
} else {
parse($a->{$b});
diff --git a/scripts/release.pl b/scripts/release.pl
index 0484079..7853935 100755
--- a/scripts/release.pl
+++ b/scripts/release.pl
@@ -102,8 +102,8 @@ my $branch = `git rev-parse --abbrev-ref HEAD 2>/dev/null`;
$branch =~ s/\s+$//;
pod2usage("Not on a branch") unless $branch;
pod2usage("Current branch is $branch. master or a release branch expected") if $branch !~ /^(master.*|release-(\d+)_(\d+))$/;
-pod2usage("Version mismatch ($2.$3 in branch $branch vs. $major.$minor in CMakeLists.txt)") if $branch ne "master" && ( $major != $2 || $minor != $3 );
-pod2usage("Release name Master expected on master branch" ) if $branch eq "master" && $releasename ne "Master";
+pod2usage("Version mismatch ($2.$3) in branch $branch vs. $major.$minor in CMakeLists.txt)") if $branch !~ /master/ && ( $major != $2 || $minor != $3 );
+pod2usage("Release name Master expected on master branch" ) if $branch =~ /^master/ && $releasename ne "Master";
if( $branch =~ /^master.*/ ) {
pod2usage("No point releases on master branch") if $dopoint;
@@ -136,9 +136,9 @@ if( $domajor ) {
my $splashwidth;
unless( $dopoint ) {
pod2usage("Splash images/splash/splash-$newmajor.$newminor.png not found") unless -r "images/splash/splash-$newmajor.$newminor.png";
- pod2usage("NSIS image ms-windows/Installer-Files/WelcomeFinishPage-$newmajor.$newminor.bmp not found") unless -r "ms-windows/Installer-Files/WelcomeFinishPage-$newmajor.$newminor.bmp";
- my $welcomeformat = `identify -format '%wx%h %m' ms-windows/Installer-Files/WelcomeFinishPage-$newmajor.$newminor.bmp`;
- pod2usage("NSIS Image ms-windows/Installer-Files/WelcomeFinishPage-$newmajor.$newminor.bmp mis-sized [$welcomeformat vs. 164x314 BMP3]") unless $welcomeformat =~ /^164x314 /;
+ pod2usage("NSIS image ms-windows/Installer-Files/WelcomeFinishPage-$newmajor.$newminor.png not found") unless -r "ms-windows/Installer-Files/WelcomeFinishPage-$newmajor.$newminor.png";
+ my $welcomeformat = `identify -format '%wx%h %m' ms-windows/Installer-Files/WelcomeFinishPage-$newmajor.$newminor.png`;
+ pod2usage("NSIS Image ms-windows/Installer-Files/WelcomeFinishPage-$newmajor.$newminor.png mis-sized [$welcomeformat vs. 164x314 BMP3]") unless $welcomeformat =~ /^164x314 /;
}
print "Last pull rebase...\n";
@@ -182,7 +182,7 @@ run( "cp debian/changelog /tmp", "backup changelog failed" );
unless( $dopoint ) {
run( "cp -v images/splash/splash-$newmajor.$newminor.png images/splash/splash.png", "splash png switch failed" );
- run( "convert -resize 164x314 ms-windows/Installer-Files/WelcomeFinishPage-$newmajor.$newminor.bmp BMP3:ms-windows/Installer-Files/WelcomeFinishPage.bmp", "installer bitmap switch failed" );
+ run( "convert -resize 164x314 ms-windows/Installer-Files/WelcomeFinishPage-$newmajor.$newminor.png BMP3:ms-windows/Installer-Files/WelcomeFinishPage.bmp", "installer bitmap switch failed" );
if( -f "images/splash/splash-release.xcf.bz2" ) {
run( "cp -v images/splash/splash-$newmajor.$newminor.xcf.bz2 images/splash/splash.xcf.bz2", "splash xcf switch failed" );
@@ -207,7 +207,7 @@ unless( $dopoint ) {
$newminor++;
print "Updating master...\n";
- run( "git checkout master", "checkout master failed" );
+ run( "git checkout $branch", "checkout master failed" );
if($dopremajor) {
print " Creating master_$newmajor...\n";
@@ -230,7 +230,7 @@ unless( $dopoint ) {
run( "dch --newversion $newmajor.$newminor.0 'New development version $newmajor.$newminor after branch of $release'", "dch failed" );
run( "git commit -a -m 'Bump version to $newmajor.$newminor'", "bump version failed" );
- push @topush, "master";
+ push @topush, $branch;
}
push @topush, $relbranch;
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index 3ca56a8..2dd97ff 100644
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -115,6 +115,7 @@ SET(QGIS_APP_SRCS
qgsrelationadddlg.cpp
qgsselectbyformdialog.cpp
qgsstatisticalsummarydockwidget.cpp
+ qgssubstitutionlistwidget.cpp
qgstextannotationdialog.cpp
qgssnappingdialog.cpp
qgssvgannotationdialog.cpp
@@ -292,6 +293,7 @@ SET (QGIS_APP_MOC_HDRS
qgssnappingdialog.h
qgssponsors.h
qgsstatisticalsummarydockwidget.h
+ qgssubstitutionlistwidget.h
qgssvgannotationdialog.h
qgstextannotationdialog.h
qgstipgui.h
@@ -351,15 +353,18 @@ SET (WITH_QWTPOLAR TRUE CACHE BOOL "Determines whether QwtPolar should be built"
IF (WITH_QWTPOLAR)
ADD_DEFINITIONS(-DWITH_QWTPOLAR)
+
# Try to find QwtPolar on the system
FIND_PACKAGE(QwtPolar)
+
# If not found on the system, offer the possibility to build QwtPolar
# internally
- IF(NOT FOUND_QwtPolar)
- SET(DEFAULT_WITH_INTERNAL_QWTPOLAR TRUE)
- ELSE(NOT FOUND_QwtPolar)
+ IF(QWTPOLAR_FOUND)
SET(DEFAULT_WITH_INTERNAL_QWTPOLAR FALSE)
- ENDIF(NOT FOUND_QwtPolar)
+ ELSE(QWTPOLAR_FOUND)
+ SET(DEFAULT_WITH_INTERNAL_QWTPOLAR TRUE)
+ ENDIF(QWTPOLAR_FOUND)
+
SET (WITH_INTERNAL_QWTPOLAR DEFAULT_WITH_INTERNAL_QWTPOLAR CACHE BOOL "Use internal build of QwtPolar")
IF(WITH_INTERNAL_QWTPOLAR)
diff --git a/src/app/composer/qgscomposer.cpp b/src/app/composer/qgscomposer.cpp
index 7a7dfb6..ce4ffa0 100644
--- a/src/app/composer/qgscomposer.cpp
+++ b/src/app/composer/qgscomposer.cpp
@@ -385,7 +385,7 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
layoutMenu->addAction( mActionAddNewLegend );
layoutMenu->addAction( mActionAddImage );
QMenu *shapeMenu = layoutMenu->addMenu( "Add Shape" );
- shapeMenu->setIcon( QgsApplication::getThemeIcon( "/mActionAddBasicShape.png" ) );
+ shapeMenu->setIcon( QgsApplication::getThemeIcon( "/mActionAddBasicShape.svg" ) );
shapeMenu->addAction( mActionAddRectangle );
shapeMenu->addAction( mActionAddTriangle );
shapeMenu->addAction( mActionAddEllipse );
diff --git a/src/app/composer/qgscomposerlegendwidget.cpp b/src/app/composer/qgscomposerlegendwidget.cpp
index 6cf04d4..ac20f59 100644
--- a/src/app/composer/qgscomposerlegendwidget.cpp
+++ b/src/app/composer/qgscomposerlegendwidget.cpp
@@ -43,6 +43,23 @@
#include <QInputDialog>
+static int _unfilteredLegendNodeIndex( QgsLayerTreeModelLegendNode* legendNode )
+{
+ return legendNode->model()->layerOriginalLegendNodes( legendNode->layerNode() ).indexOf( legendNode );
+}
+
+static int _originalLegendNodeIndex( QgsLayerTreeModelLegendNode* legendNode )
+{
+ // figure out index of the legend node as it comes out of the map layer legend.
+ // first legend nodes may be reordered, output of that is available in layerOriginalLegendNodes().
+ // next the nodes may be further filtered (by scale, map content etc).
+ // so here we go in reverse order: 1. find index before filtering, 2. find index before reorder
+ int unfilteredNodeIndex = _unfilteredLegendNodeIndex( legendNode );
+ QList<int> order = QgsMapLayerLegendUtils::legendNodeOrder( legendNode->layerNode() );
+ return ( unfilteredNodeIndex >= 0 && unfilteredNodeIndex < order.count() ? order[unfilteredNodeIndex] : -1 );
+}
+
+
QgsComposerLegendWidget::QgsComposerLegendWidget( QgsComposerLegend* legend )
: QgsComposerItemBaseWidget( nullptr, legend )
, mLegend( legend )
@@ -480,7 +497,7 @@ void QgsComposerLegendWidget::on_mMoveDownToolButton_clicked()
}
else // legend node
{
- _moveLegendNode( legendNode->layerNode(), index.row(), 1 );
+ _moveLegendNode( legendNode->layerNode(), _unfilteredLegendNodeIndex( legendNode ), 1 );
mItemTreeView->layerTreeModel()->refreshLayerLegend( legendNode->layerNode() );
}
@@ -517,7 +534,7 @@ void QgsComposerLegendWidget::on_mMoveUpToolButton_clicked()
}
else // legend node
{
- _moveLegendNode( legendNode->layerNode(), index.row(), -1 );
+ _moveLegendNode( legendNode->layerNode(), _unfilteredLegendNodeIndex( legendNode ), -1 );
mItemTreeView->layerTreeModel()->refreshLayerLegend( legendNode->layerNode() );
}
@@ -688,7 +705,7 @@ void QgsComposerLegendWidget::on_mRemoveToolButton_clicked()
if ( QgsLayerTreeModelLegendNode* legendNode = mItemTreeView->layerTreeModel()->index2legendNode( index ) )
{
QgsLayerTreeLayer* nodeLayer = legendNode->layerNode();
- nodesWithRemoval[nodeLayer].append( index.row() );
+ nodesWithRemoval[nodeLayer].append( _unfilteredLegendNodeIndex( legendNode ) );
}
}
Q_FOREACH ( QgsLayerTreeLayer* nodeLayer, nodesWithRemoval.keys() )
@@ -1006,17 +1023,12 @@ void QgsComposerLegendWidget::on_mItemTreeView_doubleClicked( const QModelIndex
currentNode->setCustomProperty( "legend/title-label", newText );
// force update of label of the legend node with embedded icon (a bit clumsy i know)
- QList<QgsLayerTreeModelLegendNode*> nodes = model->layerLegendNodes( QgsLayerTree::toLayer( currentNode ) );
- if ( nodes.count() == 1 && nodes[0]->isEmbeddedInParent() )
- nodes[0]->setUserLabel( QString() );
+ if ( QgsLayerTreeModelLegendNode* embeddedNode = model->legendNodeEmbeddedInParent( QgsLayerTree::toLayer( currentNode ) ) )
+ embeddedNode->setUserLabel( QString() );
}
else if ( legendNode )
{
- QList<int> order = QgsMapLayerLegendUtils::legendNodeOrder( legendNode->layerNode() );
- //find unfiltered row number
- QList<QgsLayerTreeModelLegendNode*> layerLegendNodes = model->layerOriginalLegendNodes( legendNode->layerNode() );
- int unfilteredRowIndex = layerLegendNodes.indexOf( legendNode );
- int originalIndex = ( unfilteredRowIndex >= 0 && unfilteredRowIndex < order.count() ? order[unfilteredRowIndex] : -1 );
+ int originalIndex = _originalLegendNodeIndex( legendNode );
QgsMapLayerLegendUtils::setLegendNodeUserLabel( legendNode->layerNode(), originalIndex, newText );
model->refreshLayerLegend( legendNode->layerNode() );
}
diff --git a/src/app/composer/qgscomposermapwidget.cpp b/src/app/composer/qgscomposermapwidget.cpp
index 2e1285f..90dddd7 100644
--- a/src/app/composer/qgscomposermapwidget.cpp
+++ b/src/app/composer/qgscomposermapwidget.cpp
@@ -135,7 +135,7 @@ QgsComposerMapWidget::QgsComposerMapWidget( QgsComposerMap* composerMap )
// keep layers from preset button
QMenu* menuKeepLayers = new QMenu( this );
mLayerListFromPresetButton->setMenu( menuKeepLayers );
- mLayerListFromPresetButton->setIcon( QgsApplication::getThemeIcon( "/mActionShowAllLayers.png" ) );
+ mLayerListFromPresetButton->setIcon( QgsApplication::getThemeIcon( "/mActionShowAllLayers.svg" ) );
mLayerListFromPresetButton->setToolTip( tr( "Set layer list from a visibility preset" ) );
connect( menuKeepLayers, SIGNAL( aboutToShow() ), this, SLOT( aboutToShowKeepLayersVisibilityPresetsMenu() ) );
diff --git a/src/app/composer/qgscomposerpicturewidget.cpp b/src/app/composer/qgscomposerpicturewidget.cpp
index add36f5..99f5f04 100644
--- a/src/app/composer/qgscomposerpicturewidget.cpp
+++ b/src/app/composer/qgscomposerpicturewidget.cpp
@@ -44,6 +44,13 @@ QgsComposerPictureWidget::QgsComposerPictureWidget( QgsComposerPicture* picture
mOutlineColorButton->setColorDialogTitle( tr( "Select outline color" ) );
mOutlineColorButton->setContext( "composer" );
+ mNorthTypeComboBox->blockSignals( true );
+ mNorthTypeComboBox->addItem( tr( "Grid north" ), QgsComposerPicture::GridNorth );
+ mNorthTypeComboBox->addItem( tr( "True north" ), QgsComposerPicture::TrueNorth );
+ mNorthTypeComboBox->blockSignals( false );
+ mPictureRotationOffsetSpinBox->setClearValue( 0.0 );
+ mPictureRotationSpinBox->setClearValue( 0.0 );
+
//add widget for general composer item properties
QgsComposerItemWidget* itemPropertiesWidget = new QgsComposerItemWidget( this, picture );
mainLayout->addWidget( itemPropertiesWidget );
@@ -280,6 +287,8 @@ void QgsComposerPictureWidget::on_mRotationFromComposerMapCheckBox_stateChanged(
mPicture->setRotationMap( -1 );
mPictureRotationSpinBox->setEnabled( true );
mComposerMapComboBox->setEnabled( false );
+ mNorthTypeComboBox->setEnabled( false );
+ mPictureRotationOffsetSpinBox->setEnabled( false );
mPicture->setPictureRotation( mPictureRotationSpinBox->value() );
}
else
@@ -288,6 +297,8 @@ void QgsComposerPictureWidget::on_mRotationFromComposerMapCheckBox_stateChanged(
int mapId = map ? map->id() : -1;
mPicture->setRotationMap( mapId );
mPictureRotationSpinBox->setEnabled( false );
+ mNorthTypeComboBox->setEnabled( true );
+ mPictureRotationOffsetSpinBox->setEnabled( true );
mComposerMapComboBox->setEnabled( true );
}
mPicture->endCommand();
@@ -335,6 +346,8 @@ void QgsComposerPictureWidget::setGuiElementValues()
mPictureLineEdit->blockSignals( true );
mComposerMapComboBox->blockSignals( true );
mRotationFromComposerMapCheckBox->blockSignals( true );
+ mNorthTypeComboBox->blockSignals( true );
+ mPictureRotationOffsetSpinBox->blockSignals( true );
mResizeModeComboBox->blockSignals( true );
mAnchorPointComboBox->blockSignals( true );
mFillColorButton->blockSignals( true );
@@ -355,13 +368,19 @@ void QgsComposerPictureWidget::setGuiElementValues()
mRotationFromComposerMapCheckBox->setCheckState( Qt::Checked );
mPictureRotationSpinBox->setEnabled( false );
mComposerMapComboBox->setEnabled( true );
+ mNorthTypeComboBox->setEnabled( true );
+ mPictureRotationOffsetSpinBox->setEnabled( true );
}
else
{
mRotationFromComposerMapCheckBox->setCheckState( Qt::Unchecked );
mPictureRotationSpinBox->setEnabled( true );
mComposerMapComboBox->setEnabled( false );
+ mNorthTypeComboBox->setEnabled( false );
+ mPictureRotationOffsetSpinBox->setEnabled( false );
}
+ mNorthTypeComboBox->setCurrentIndex( mNorthTypeComboBox->findData( mPicture->northMode() ) );
+ mPictureRotationOffsetSpinBox->setValue( mPicture->northOffset() );
mResizeModeComboBox->setCurrentIndex(( int )mPicture->resizeMode() );
//disable picture rotation for non-zoom modes
@@ -389,6 +408,8 @@ void QgsComposerPictureWidget::setGuiElementValues()
mPictureRotationSpinBox->blockSignals( false );
mPictureLineEdit->blockSignals( false );
mComposerMapComboBox->blockSignals( false );
+ mNorthTypeComboBox->blockSignals( false );
+ mPictureRotationOffsetSpinBox->blockSignals( false );
mResizeModeComboBox->blockSignals( false );
mAnchorPointComboBox->blockSignals( false );
mFillColorButton->blockSignals( false );
@@ -665,6 +686,22 @@ void QgsComposerPictureWidget::on_mOutlineWidthSpinBox_valueChanged( double d )
mPicture->update();
}
+void QgsComposerPictureWidget::on_mPictureRotationOffsetSpinBox_valueChanged( double d )
+{
+ mPicture->beginCommand( tr( "Picture North offset changed" ), QgsComposerMergeCommand::ComposerPictureNorthOffset );
+ mPicture->setNorthOffset( d );
+ mPicture->endCommand();
+ mPicture->update();
+}
+
+void QgsComposerPictureWidget::on_mNorthTypeComboBox_currentIndexChanged( int index )
+{
+ mPicture->beginCommand( tr( "Picture North mode changed" ) );
+ mPicture->setNorthMode( static_cast< QgsComposerPicture::NorthMode >( mNorthTypeComboBox->itemData( index ).toInt() ) );
+ mPicture->endCommand();
+ mPicture->update();
+}
+
void QgsComposerPictureWidget::resizeEvent( QResizeEvent * event )
{
Q_UNUSED( event );
diff --git a/src/app/composer/qgscomposerpicturewidget.h b/src/app/composer/qgscomposerpicturewidget.h
index b89d4f9..e86ac26 100644
--- a/src/app/composer/qgscomposerpicturewidget.h
+++ b/src/app/composer/qgscomposerpicturewidget.h
@@ -72,6 +72,8 @@ class QgsComposerPictureWidget: public QgsComposerItemBaseWidget, private Ui::Qg
void on_mFillColorButton_colorChanged( const QColor& color );
void on_mOutlineColorButton_colorChanged( const QColor& color );
void on_mOutlineWidthSpinBox_valueChanged( double d );
+ void on_mPictureRotationOffsetSpinBox_valueChanged( double d );
+ void on_mNorthTypeComboBox_currentIndexChanged( int index );
private:
QgsComposerPicture* mPicture;
diff --git a/src/app/gps/qwtpolar-0.1/qwt_polar_plot.cpp b/src/app/gps/qwtpolar-0.1/qwt_polar_plot.cpp
index 623d6ac..b2af0cc 100644
--- a/src/app/gps/qwtpolar-0.1/qwt_polar_plot.cpp
+++ b/src/app/gps/qwtpolar-0.1/qwt_polar_plot.cpp
@@ -186,7 +186,7 @@ const QwtTextLabel *QwtPolarPlot::titleLabel() const
\param legend Legend
\param pos The legend's position. For top/left position the number
- of colums will be limited to 1, otherwise it will be set to
+ of columns will be limited to 1, otherwise it will be set to
unlimited.
\param ratio Ratio between legend and the bounding rect
diff --git a/src/app/gps/qwtpolar-1.0/qwt_polar_plot.cpp b/src/app/gps/qwtpolar-1.0/qwt_polar_plot.cpp
index aa6c404..add40f7 100644
--- a/src/app/gps/qwtpolar-1.0/qwt_polar_plot.cpp
+++ b/src/app/gps/qwtpolar-1.0/qwt_polar_plot.cpp
@@ -167,7 +167,7 @@ const QwtTextLabel *QwtPolarPlot::titleLabel() const
\param legend Legend
\param pos The legend's position. For top/left position the number
- of colums will be limited to 1, otherwise it will be set to
+ of columns will be limited to 1, otherwise it will be set to
unlimited.
\param ratio Ratio between legend and the bounding rect
diff --git a/src/app/gps/qwtpolar-1.1.1/qwt_polar_plot.cpp b/src/app/gps/qwtpolar-1.1.1/qwt_polar_plot.cpp
index 09cc540..b1b8b53 100644
--- a/src/app/gps/qwtpolar-1.1.1/qwt_polar_plot.cpp
+++ b/src/app/gps/qwtpolar-1.1.1/qwt_polar_plot.cpp
@@ -171,7 +171,7 @@ const QwtTextLabel *QwtPolarPlot::titleLabel() const
\param legend Legend
\param pos The legend's position. For top/left position the number
- of colums will be limited to 1, otherwise it will be set to
+ of columns will be limited to 1, otherwise it will be set to
unlimited.
\param ratio Ratio between legend and the bounding rect
diff --git a/src/app/main.cpp b/src/app/main.cpp
index 1010493..2ba0afa 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -205,6 +205,14 @@ static void dumpBacktrace( unsigned int depth )
depth = 20;
#if ((defined(linux) || defined(__linux__)) && !defined(ANDROID)) || defined(__FreeBSD__)
+ // Below there is a bunch of operations that are not safe in multi-threaded
+ // environment (dup()+close() combo, wait(), juggling with file descriptors).
+ // Maybe some problems could be resolved with dup2() and waitpid(), but it seems
+ // that if the operations on descriptors are not serialized, things will get nasty.
+ // That's why there's this lovely mutex here...
+ static QMutex mutex;
+ QMutexLocker locker( &mutex );
+
int stderr_fd = -1;
if ( access( "/usr/bin/c++filt", X_OK ) < 0 )
{
diff --git a/src/app/nodetool/qgsmaptoolnodetool.cpp b/src/app/nodetool/qgsmaptoolnodetool.cpp
index 04907bc..723c7a2 100644
--- a/src/app/nodetool/qgsmaptoolnodetool.cpp
+++ b/src/app/nodetool/qgsmaptoolnodetool.cpp
@@ -201,6 +201,7 @@ QgsFeature QgsMapToolNodeTool::getFeatureAtPoint( QgsMapMouseEvent* e )
QgsFeatureRequest request;
request.setFilterRect( QgsRectangle( e->mapPoint().x(), e->mapPoint().y(), e->mapPoint().x(), e->mapPoint().y() ) );
+ request.setFlags( QgsFeatureRequest::ExactIntersect );
QgsFeatureIterator features = vlayer->getFeatures( request );
features.nextFeature( feature );
@@ -271,12 +272,11 @@ void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )
// get geometry and find if snapping is near it
int atVertex, beforeVertex, afterVertex;
- double dist;
- QgsPoint closestLayerVertex = mSelectedFeature->geometry()->closestVertex( layerCoordPoint, atVertex, beforeVertex, afterVertex, dist );
- dist = sqrt( dist );
+ double sqrDist; // will be negative on error
+ QgsPoint closestLayerVertex = mSelectedFeature->geometry()->closestVertex( layerCoordPoint, atVertex, beforeVertex, afterVertex, sqrDist );
mSnapper.snapToCurrentLayer( e->pos(), snapResults, QgsSnapper::SnapToVertex, tol );
- if ( dist <= tol )
+ if ( sqrDist >= 0 && sqrt( sqrDist ) <= tol )
{
// some vertex selected
mMoving = true;
diff --git a/src/app/pluginmanager/qgspluginmanager.cpp b/src/app/pluginmanager/qgspluginmanager.cpp
index 0a1380b..ef4efec 100644
--- a/src/app/pluginmanager/qgspluginmanager.cpp
+++ b/src/app/pluginmanager/qgspluginmanager.cpp
@@ -617,7 +617,7 @@ void QgsPluginManager::showPluginDetails( QStandardItem * item )
" padding:0px;"
" margin:0px;"
" font-family:verdana;"
- " font-size: 1.1em;"
+ " font-size: 10pt;"
" }"
" div#votes {"
" width:360px;"
@@ -1133,11 +1133,11 @@ void QgsPluginManager::setCurrentTab( int idx )
if ( it != mTabDescriptions.constEnd() )
{
tabInfoHTML += "<style>"
- "body, table {"
- "margin:4px;"
- "font-family:verdana;"
- "font-size: 12px;"
- "}"
+ " body, p {"
+ " margin: 2px;"
+ " font-family: verdana;"
+ " font-size: 10pt;"
+ " }"
"</style>";
// tabInfoHTML += "<style>" + QgsApplication::reportStyleSheet() + "</style>";
tabInfoHTML += it.value();
diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp
index 94f4c2e..cffbfa9 100644
--- a/src/app/qgisapp.cpp
+++ b/src/app/qgisapp.cpp
@@ -1277,10 +1277,17 @@ void QgisApp::dragEnterEvent( QDragEnterEvent *event )
void QgisApp::dropEvent( QDropEvent *event )
{
- mMapCanvas->freeze();
+ // dragging app is locked for the duration of dropEvent. This causes explorer windows to hang
+ // while large projects/layers are loaded. So instead we return from dropEvent as quickly as possible
+ // and do the actual handling of the drop after a very short timeout
+ QTimer* timer = new QTimer( this );
+ timer->setSingleShot( true );
+ timer->setInterval( 50 );
+
// get the file list
QList<QUrl>::iterator i;
QList<QUrl>urls = event->mimeData()->urls();
+ QStringList files;
for ( i = urls.begin(); i != urls.end(); ++i )
{
QString fileName = i->toLocalFile();
@@ -1333,13 +1340,37 @@ void QgisApp::dropEvent( QDropEvent *event )
// so we test for length to make sure we have something
if ( !fileName.isEmpty() )
{
- openFile( fileName );
+ files << fileName;
}
}
+ timer->setProperty( "files", files );
+ QgsMimeDataUtils::UriList lst;
if ( QgsMimeDataUtils::isUriList( event->mimeData() ) )
{
- QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( event->mimeData() );
+ lst = QgsMimeDataUtils::decodeUriList( event->mimeData() );
+ }
+ timer->setProperty( "uris", QVariant::fromValue( lst ) );
+
+ connect( timer, SIGNAL( timeout() ), this, SLOT( dropEventTimeout() ) );
+
+ event->acceptProposedAction();
+ timer->start();
+}
+
+void QgisApp::dropEventTimeout()
+{
+ mMapCanvas->freeze();
+ QStringList files = sender()->property( "files" ).toStringList();
+
+ Q_FOREACH ( const QString& file, files )
+ {
+ openFile( file );
+ }
+
+ QgsMimeDataUtils::UriList lst = sender()->property( "uris" ).value<QgsMimeDataUtils::UriList>();
+ if ( !lst.isEmpty() )
+ {
Q_FOREACH ( const QgsMimeDataUtils::Uri& u, lst )
{
QString uri = crsAndFormatAdjustedLayerUri( u.uri, u.supportedCrs, u.supportedFormats );
@@ -1358,9 +1389,10 @@ void QgisApp::dropEvent( QDropEvent *event )
}
}
}
+ sender()->deleteLater();
+
mMapCanvas->freeze( false );
mMapCanvas->refresh();
- event->acceptProposedAction();
}
bool QgisApp::event( QEvent * event )
@@ -2496,8 +2528,8 @@ void QgisApp::setTheme( const QString& theThemeName )
mActionNewVectorLayer->setIcon( QgsApplication::getThemeIcon( "/mActionNewVectorLayer.svg" ) );
mActionNewMemoryLayer->setIcon( QgsApplication::getThemeIcon( "/mActionCreateMemory.svg" ) );
mActionAddAllToOverview->setIcon( QgsApplication::getThemeIcon( "/mActionAddAllToOverview.svg" ) );
- mActionHideAllLayers->setIcon( QgsApplication::getThemeIcon( "/mActionHideAllLayers.png" ) );
- mActionShowAllLayers->setIcon( QgsApplication::getThemeIcon( "/mActionShowAllLayers.png" ) );
+ mActionHideAllLayers->setIcon( QgsApplication::getThemeIcon( "/mActionHideAllLayers.svg" ) );
+ mActionShowAllLayers->setIcon( QgsApplication::getThemeIcon( "/mActionShowAllLayers.svg" ) );
mActionHideSelectedLayers->setIcon( QgsApplication::getThemeIcon( "/mActionHideSelectedLayers.png" ) );
mActionShowSelectedLayers->setIcon( QgsApplication::getThemeIcon( "/mActionShowSelectedLayers.png" ) );
mActionRemoveAllFromOverview->setIcon( QgsApplication::getThemeIcon( "/mActionRemoveAllFromOverview.svg" ) );
@@ -2612,7 +2644,7 @@ void QgisApp::setTheme( const QString& theThemeName )
mActionDecorationCopyright->setIcon( QgsApplication::getThemeIcon( "/copyright_label.png" ) );
mActionDecorationNorthArrow->setIcon( QgsApplication::getThemeIcon( "/north_arrow.png" ) );
mActionDecorationScaleBar->setIcon( QgsApplication::getThemeIcon( "/scale_bar.png" ) );
- mActionDecorationGrid->setIcon( QgsApplication::getThemeIcon( "/transformed.png" ) );
+ mActionDecorationGrid->setIcon( QgsApplication::getThemeIcon( "/transformed.svg" ) );
//change themes of all composers
QSet<QgsComposer*>::const_iterator composerIt = mPrintComposers.constBegin();
@@ -3037,11 +3069,11 @@ void QgisApp::initLayerTreeView()
QAction* actionExpandAll = new QAction( tr( "Expand All" ), this );
actionExpandAll->setIcon( QgsApplication::getThemeIcon( "/mActionExpandTree.svg" ) );
actionExpandAll->setToolTip( tr( "Expand All" ) );
- connect( actionExpandAll, SIGNAL( triggered( bool ) ), mLayerTreeView, SLOT( expandAll() ) );
+ connect( actionExpandAll, SIGNAL( triggered( bool ) ), mLayerTreeView, SLOT( expandAllNodes() ) );
QAction* actionCollapseAll = new QAction( tr( "Collapse All" ), this );
actionCollapseAll->setIcon( QgsApplication::getThemeIcon( "/mActionCollapseTree.svg" ) );
actionCollapseAll->setToolTip( tr( "Collapse All" ) );
- connect( actionCollapseAll, SIGNAL( triggered( bool ) ), mLayerTreeView, SLOT( collapseAll() ) );
+ connect( actionCollapseAll, SIGNAL( triggered( bool ) ), mLayerTreeView, SLOT( collapseAllNodes() ) );
QWidget* spacer = new QWidget();
spacer->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
@@ -5068,13 +5100,15 @@ void QgisApp::dxfExport()
dxfExport.setSymbologyScaleDenominator( d.symbologyScale() );
dxfExport.setSymbologyExport( d.symbologyMode() );
dxfExport.setLayerTitleAsName( d.layerTitleAsName() );
+ dxfExport.setDestinationCrs( d.crs() );
if ( mapCanvas() )
{
dxfExport.setMapUnits( mapCanvas()->mapUnits() );
//extent
if ( d.exportMapExtent() )
{
- dxfExport.setExtent( mapCanvas()->extent() );
+ QgsCoordinateTransform t( mapCanvas()->mapSettings().destinationCrs(), QgsCoordinateReferenceSystem( d.crs(), QgsCoordinateReferenceSystem::InternalCrsId ) );
+ dxfExport.setExtent( t.transformBoundingBox( mapCanvas()->extent() ) );
}
}
@@ -7380,6 +7414,11 @@ void QgisApp::editPaste( QgsMapLayer *destinationLayer )
remap.insert( idx, dst );
}
+ QgsExpressionContext context;
+ context << QgsExpressionContextUtils::globalScope()
+ << QgsExpressionContextUtils::projectScope()
+ << QgsExpressionContextUtils::layerScope( pasteVectorLayer );
+
int dstAttrCount = pasteVectorLayer->fields().count();
QgsFeatureList::iterator featureIt = features.begin();
@@ -7391,8 +7430,18 @@ void QgisApp::editPaste( QgsMapLayer *destinationLayer )
// pre-initialized with default values
for ( int dst = 0; dst < dstAttr.count(); ++dst )
{
- QVariant defVal( pasteVectorLayer->dataProvider()->defaultValue( dst ) );
- if ( !defVal.isNull() )
+ QVariant defVal;
+ if ( !pasteVectorLayer->defaultValueExpression( dst ).isEmpty() )
+ {
+ // client side default expression set - use this in preference to provider default
+ defVal = pasteVectorLayer->defaultValue( dst, *featureIt, &context );
+ }
+ else
+ {
+ defVal = pasteVectorLayer->dataProvider()->defaultValue( dst );
+ }
+
+ if ( defVal.isValid() && !defVal.isNull() )
{
dstAttr[ dst ] = defVal;
}
diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h
index ddfa0b6..906a5e9 100644
--- a/src/app/qgisapp.h
+++ b/src/app/qgisapp.h
@@ -1322,6 +1322,9 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
/** Set the layer for the map style dock. Doesn't show the style dock */
void setMapStyleDockLayer( QgsMapLayer *layer );
+ //! Handles processing of dropped mimedata
+ void dropEventTimeout();
+
signals:
/** Emitted when a key is pressed and we want non widget sublasses to be able
to pick up on this (e.g. maplayer) */
diff --git a/src/app/qgsannotationwidget.cpp b/src/app/qgsannotationwidget.cpp
index dacff37..50cbdd9 100644
--- a/src/app/qgsannotationwidget.cpp
+++ b/src/app/qgsannotationwidget.cpp
@@ -59,7 +59,7 @@ QgsAnnotationWidget::QgsAnnotationWidget( QgsAnnotationItem* item, QWidget * par
const QgsMarkerSymbolV2* symbol = mItem->markerSymbol();
if ( symbol )
{
- mMarkerSymbol = symbol->clone();
+ mMarkerSymbol.reset( symbol->clone() );
updateCenterIcon();
}
@@ -69,7 +69,6 @@ QgsAnnotationWidget::QgsAnnotationWidget( QgsAnnotationItem* item, QWidget * par
QgsAnnotationWidget::~QgsAnnotationWidget()
{
- delete mMarkerSymbol;
}
void QgsAnnotationWidget::apply()
@@ -80,8 +79,7 @@ void QgsAnnotationWidget::apply()
mItem->setFrameBorderWidth( mFrameWidthSpinBox->value() );
mItem->setFrameColor( mFrameColorButton->color() );
mItem->setFrameBackgroundColor( mBackgroundColorButton->color() );
- mItem->setMarkerSymbol( mMarkerSymbol );
- mMarkerSymbol = nullptr; //item takes ownership
+ mItem->setMarkerSymbol( mMarkerSymbol->clone() );
mItem->update();
}
}
@@ -108,8 +106,7 @@ void QgsAnnotationWidget::on_mMapMarkerButton_clicked()
}
else
{
- delete mMarkerSymbol;
- mMarkerSymbol = markerSymbol;
+ mMarkerSymbol.reset( markerSymbol );
updateCenterIcon();
}
}
@@ -120,7 +117,7 @@ void QgsAnnotationWidget::updateCenterIcon()
{
return;
}
- QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( mMarkerSymbol, mMapMarkerButton->iconSize() );
+ QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( mMarkerSymbol.data(), mMapMarkerButton->iconSize() );
mMapMarkerButton->setIcon( icon );
}
diff --git a/src/app/qgsannotationwidget.h b/src/app/qgsannotationwidget.h
index 49d530f..d431e78 100644
--- a/src/app/qgsannotationwidget.h
+++ b/src/app/qgsannotationwidget.h
@@ -44,7 +44,7 @@ class APP_EXPORT QgsAnnotationWidget: public QWidget, private Ui::QgsAnnotationW
private:
QgsAnnotationItem* mItem;
- QgsMarkerSymbolV2* mMarkerSymbol;
+ QScopedPointer< QgsMarkerSymbolV2 > mMarkerSymbol;
void blockAllSignals( bool block );
void updateCenterIcon();
diff --git a/src/app/qgsapplayertreeviewmenuprovider.cpp b/src/app/qgsapplayertreeviewmenuprovider.cpp
index 4ab0817..20d37b6 100644
--- a/src/app/qgsapplayertreeviewmenuprovider.cpp
+++ b/src/app/qgsapplayertreeviewmenuprovider.cpp
@@ -282,9 +282,9 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu()
// symbology item
if ( symbolNode->flags() & Qt::ItemIsUserCheckable )
{
- menu->addAction( QgsApplication::getThemeIcon( "/mActionShowAllLayers.png" ), tr( "&Show All Items" ),
+ menu->addAction( QgsApplication::getThemeIcon( "/mActionShowAllLayers.svg" ), tr( "&Show All Items" ),
symbolNode, SLOT( checkAllItems() ) );
- menu->addAction( QgsApplication::getThemeIcon( "/mActionHideAllLayers.png" ), tr( "&Hide All Items" ),
+ menu->addAction( QgsApplication::getThemeIcon( "/mActionHideAllLayers.svg" ), tr( "&Hide All Items" ),
symbolNode, SLOT( uncheckAllItems() ) );
menu->addSeparator();
}
diff --git a/src/app/qgsattributetypedialog.cpp b/src/app/qgsattributetypedialog.cpp
index 6791bd9..2231709 100644
--- a/src/app/qgsattributetypedialog.cpp
+++ b/src/app/qgsattributetypedialog.cpp
@@ -69,10 +69,12 @@ QgsAttributeTypeDialog::QgsAttributeTypeDialog( QgsVectorLayer *vl, int fieldIdx
isFieldEditableCheckBox->setEnabled( false );
}
+ connect( mExpressionWidget, SIGNAL( expressionChanged( QString ) ), this, SLOT( defaultExpressionChanged() ) );
+
QSettings settings;
restoreGeometry( settings.value( "/Windows/QgsAttributeTypeDialog/geometry" ).toByteArray() );
- constraintExpression->setLayer( vl );
+ constraintExpressionWidget->setLayer( vl );
}
QgsAttributeTypeDialog::~QgsAttributeTypeDialog()
@@ -152,12 +154,16 @@ void QgsAttributeTypeDialog::setWidgetV2Type( const QString& type )
stackedWidget->addWidget( cfgWdg );
stackedWidget->setCurrentWidget( cfgWdg );
mEditorConfigWidgets.insert( type, cfgWdg );
+ connect( cfgWdg, SIGNAL( changed() ), this, SLOT( defaultExpressionChanged() ) );
}
else
{
QgsDebugMsg( "Oops, couldn't create editor widget config dialog..." );
}
}
+
+ //update default expression preview
+ defaultExpressionChanged();
}
void QgsAttributeTypeDialog::setWidgetV2Config( const QgsEditorWidgetConfig& config )
@@ -180,14 +186,14 @@ bool QgsAttributeTypeDialog::labelOnTop() const
return labelOnTopCheckBox->isChecked();
}
-void QgsAttributeTypeDialog::setExpressionDescription( const QString &desc )
+void QgsAttributeTypeDialog::setConstraintExpressionDescription( const QString &desc )
{
- constraintExpressionDescription->setText( desc );
+ leConstraintExpressionDescription->setText( desc );
}
-QString QgsAttributeTypeDialog::expressionDescription()
+QString QgsAttributeTypeDialog::constraintExpressionDescription()
{
- return constraintExpressionDescription->text();
+ return leConstraintExpressionDescription->text();
}
bool QgsAttributeTypeDialog::notNull() const
@@ -195,14 +201,24 @@ bool QgsAttributeTypeDialog::notNull() const
return notNullCheckBox->isChecked();
}
-void QgsAttributeTypeDialog::setExpression( const QString &str )
+void QgsAttributeTypeDialog::setConstraintExpression( const QString &str )
+{
+ constraintExpressionWidget->setField( str );
+}
+
+QString QgsAttributeTypeDialog::defaultValueExpression() const
+{
+ return mExpressionWidget->expression();
+}
+
+void QgsAttributeTypeDialog::setDefaultValueExpression( const QString& expression )
{
- constraintExpression->setField( str );
+ mExpressionWidget->setExpression( expression );
}
-QString QgsAttributeTypeDialog::expression() const
+QString QgsAttributeTypeDialog::constraintExpression() const
{
- return constraintExpression->asExpression();
+ return constraintExpressionWidget->asExpression();
}
void QgsAttributeTypeDialog::setFieldEditable( bool editable )
@@ -221,3 +237,53 @@ void QgsAttributeTypeDialog::on_selectionListWidget_currentRowChanged( int index
setWidgetV2Type( editType );
}
+
+void QgsAttributeTypeDialog::defaultExpressionChanged()
+{
+ QString expression = mExpressionWidget->expression();
+ if ( expression.isEmpty() )
+ {
+ mDefaultPreviewLabel->setText( QString() );
+ return;
+ }
+
+ QgsExpressionContext context;
+ context << QgsExpressionContextUtils::globalScope()
+ << QgsExpressionContextUtils::projectScope()
+ << QgsExpressionContextUtils::layerScope( mLayer );
+
+ if ( !mPreviewFeature.isValid() )
+ {
+ // get first feature
+ QgsFeatureIterator it = mLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ) );
+ it.nextFeature( mPreviewFeature );
+ }
+
+ context.setFeature( mPreviewFeature );
+
+ QgsExpression exp = QgsExpression( expression );
+ exp.prepare( &context );
+
+ if ( exp.hasParserError() )
+ {
+ mDefaultPreviewLabel->setText( "<i>" + exp.parserErrorString() + "</i>" );
+ return;
+ }
+
+ QVariant val = exp.evaluate( &context );
+ if ( exp.hasEvalError() )
+ {
+ mDefaultPreviewLabel->setText( "<i>" + exp.evalErrorString() + "</i>" );
+ return;
+ }
+
+ QString previewText = val.toString();
+
+ QgsEditorWidgetFactory *factory = QgsEditorWidgetRegistry::instance()->factory( editorWidgetV2Type() );
+ if ( factory )
+ {
+ previewText = factory->representValue( mLayer, mFieldIdx, editorWidgetV2Config(), QVariant(), val );
+ }
+
+ mDefaultPreviewLabel->setText( "<i>" + previewText + "</i>" );
+}
diff --git a/src/app/qgsattributetypedialog.h b/src/app/qgsattributetypedialog.h
index 012ea3e..e051c69 100644
--- a/src/app/qgsattributetypedialog.h
+++ b/src/app/qgsattributetypedialog.h
@@ -21,6 +21,7 @@
#include "qgsvectorlayer.h"
#include "qgseditorconfigwidget.h"
+#include "qgsfeature.h"
class QDialog;
class QLayout;
@@ -94,31 +95,42 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut
*/
bool notNull() const;
- /*
+ /**
* Setter for constraint expression description
* @param desc the expression description
* @note added in QGIS 2.16
**/
- void setExpressionDescription( const QString &desc );
+ void setConstraintExpressionDescription( const QString &desc );
- /*
+ /**
* Getter for constraint expression description
* @return the expression description
* @note added in QGIS 2.16
**/
- QString expressionDescription();
+ QString constraintExpressionDescription();
/**
* Getter for the constraint expression
* @note added in QGIS 2.16
*/
- QString expression() const;
+ QString constraintExpression() const;
/**
* Setter for the constraint expression
* @note added in QGIS 2.16
*/
- void setExpression( const QString &str );
+ void setConstraintExpression( const QString &str );
+
+ /**
+ * Returns the expression used for the field's default value, or
+ * an empty string if no default value expression is set.
+ */
+ QString defaultValueExpression() const;
+
+ /**
+ * Sets the expression used for the field's default value
+ */
+ void setDefaultValueExpression( const QString& expression );
private slots:
/**
@@ -127,6 +139,8 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut
*/
void on_selectionListWidget_currentRowChanged( int index );
+ void defaultExpressionChanged();
+
private:
QgsVectorLayer *mLayer;
int mFieldIdx;
@@ -135,6 +149,8 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut
//! Cached configuration dialog (lazy loaded)
QMap< QString, QgsEditorConfigWidget* > mEditorConfigWidgets;
+
+ QgsFeature mPreviewFeature;
};
#endif
diff --git a/src/app/qgsdiagramproperties.cpp b/src/app/qgsdiagramproperties.cpp
index 027b254..2030257 100644
--- a/src/app/qgsdiagramproperties.cpp
+++ b/src/app/qgsdiagramproperties.cpp
@@ -96,6 +96,9 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer* layer,
mMaxValueSpinBox->setShowClearButton( false );
+ mDiagramAttributesTreeWidget->setItemDelegateForColumn( ColumnAttributeExpression, new EditBlockerDelegate( this ) );
+ mDiagramAttributesTreeWidget->setItemDelegateForColumn( ColumnColor, new EditBlockerDelegate( this ) );
+
connect( mFixedSizeRadio, SIGNAL( toggled( bool ) ), this, SLOT( scalingTypeChanged() ) );
connect( mAttributeBasedScalingRadio, SIGNAL( toggled( bool ) ), this, SLOT( scalingTypeChanged() ) );
@@ -184,7 +187,7 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer* layer,
QTreeWidgetItem *newItem = new QTreeWidgetItem( mAttributesTreeWidget );
QString name = QString( "\"%1\"" ).arg( layerFields[idx].name() );
newItem->setText( 0, name );
- newItem->setData( 0, Qt::UserRole, name );
+ newItem->setData( 0, RoleAttributeExpression, name );
newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
mDataDefinedXComboBox->addItem( layerFields[idx].name(), idx );
@@ -341,7 +344,7 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer* layer,
{
QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
newItem->setText( 0, *catIt );
- newItem->setData( 0, Qt::UserRole, *catIt );
+ newItem->setData( 0, RoleAttributeExpression, *catIt );
newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
QColor col( *coIt );
col.setAlpha( 255 );
@@ -519,7 +522,7 @@ void QgsDiagramProperties::addAttribute( QTreeWidgetItem * item )
newItem->setText( 0, item->text( 0 ) );
newItem->setText( 2, guessLegendText( item->text( 0 ) ) );
- newItem->setData( 0, Qt::UserRole, item->data( 0, Qt::UserRole ) );
+ newItem->setData( 0, RoleAttributeExpression, item->data( 0, RoleAttributeExpression ) );
newItem->setFlags(( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
//set initial color for diagram category
@@ -605,13 +608,33 @@ void QgsDiagramProperties::on_mDiagramFontButton_clicked()
void QgsDiagramProperties::on_mDiagramAttributesTreeWidget_itemDoubleClicked( QTreeWidgetItem * item, int column )
{
- if ( column == 1 ) //change color
+ switch ( column )
{
- QColor newColor = QgsColorDialogV2::getColor( item->background( 1 ).color(), nullptr );
- if ( newColor.isValid() )
+ case ColumnAttributeExpression:
{
- item->setBackground( 1, QBrush( newColor ) );
+ QString currentExpression = item->data( 0, RoleAttributeExpression ).toString();
+
+ QString newExpression = showExpressionBuilder( currentExpression );
+ if ( !newExpression.isEmpty() )
+ {
+ item->setData( 0, Qt::DisplayRole, newExpression );
+ item->setData( 0, RoleAttributeExpression, newExpression );
+ }
+ break;
+ }
+
+ case ColumnColor:
+ {
+ QColor newColor = QgsColorDialogV2::getColor( item->background( 1 ).color(), nullptr );
+ if ( newColor.isValid() )
+ {
+ item->setBackground( 1, QBrush( newColor ) );
+ }
+ break;
}
+
+ case ColumnLegendText:
+ break;
}
}
@@ -714,7 +737,7 @@ void QgsDiagramProperties::apply()
QColor color = mDiagramAttributesTreeWidget->topLevelItem( i )->background( 1 ).color();
color.setAlpha( 255 - ds.transparency );
categoryColors.append( color );
- categoryAttributes.append( mDiagramAttributesTreeWidget->topLevelItem( i )->data( 0, Qt::UserRole ).toString() );
+ categoryAttributes.append( mDiagramAttributesTreeWidget->topLevelItem( i )->data( 0, RoleAttributeExpression ).toString() );
categoryLabels.append( mDiagramAttributesTreeWidget->topLevelItem( i )->text( 2 ) );
}
ds.categoryColors = categoryColors;
@@ -832,15 +855,8 @@ void QgsDiagramProperties::apply()
mLayer->triggerRepaint();
}
-void QgsDiagramProperties::showAddAttributeExpressionDialog()
+QString QgsDiagramProperties::showExpressionBuilder( const QString& initialExpression )
{
- QString expression;
- QList<QTreeWidgetItem *> selections = mAttributesTreeWidget->selectedItems();
- if ( !selections.empty() )
- {
- expression = selections[0]->text( 0 );
- }
-
QgsExpressionContext context;
context << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope()
@@ -848,7 +864,7 @@ void QgsDiagramProperties::showAddAttributeExpressionDialog()
<< QgsExpressionContextUtils::mapSettingsScope( QgisApp::instance()->mapCanvas()->mapSettings() )
<< QgsExpressionContextUtils::layerScope( mLayer );
- QgsExpressionBuilderDialog dlg( mLayer, expression, this, "generic", context );
+ QgsExpressionBuilderDialog dlg( mLayer, initialExpression, this, "generic", context );
dlg.setWindowTitle( tr( "Expression based attribute" ) );
QgsDistanceArea myDa;
@@ -859,25 +875,42 @@ void QgsDiagramProperties::showAddAttributeExpressionDialog()
if ( dlg.exec() == QDialog::Accepted )
{
- QString expression = dlg.expressionText();
- //Only add the expression if the user has entered some text.
- if ( !expression.isEmpty() )
- {
- QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
-
- newItem->setText( 0, expression );
- newItem->setText( 2, expression );
- newItem->setData( 0, Qt::UserRole, expression );
- newItem->setFlags(( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
-
- //set initial color for diagram category
- int red = 1 + ( int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) );
- int green = 1 + ( int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) );
- int blue = 1 + ( int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) );
- QColor randomColor( red, green, blue );
- newItem->setBackground( 1, QBrush( randomColor ) );
- mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
- }
+ return dlg.expressionText();
+ }
+ else
+ {
+ return QString();
+ }
+}
+
+void QgsDiagramProperties::showAddAttributeExpressionDialog()
+{
+ QString expression;
+ QList<QTreeWidgetItem *> selections = mAttributesTreeWidget->selectedItems();
+ if ( !selections.empty() )
+ {
+ expression = selections[0]->text( 0 );
+ }
+
+ QString newExpression = showExpressionBuilder( expression );
+
+ //Only add the expression if the user has entered some text.
+ if ( !newExpression.isEmpty() )
+ {
+ QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
+
+ newItem->setText( 0, newExpression );
+ newItem->setText( 2, newExpression );
+ newItem->setData( 0, RoleAttributeExpression, newExpression );
+ newItem->setFlags(( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
+
+ //set initial color for diagram category
+ int red = 1 + ( int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) );
+ int green = 1 + ( int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) );
+ int blue = 1 + ( int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) );
+ QColor randomColor( red, green, blue );
+ newItem->setBackground( 1, QBrush( randomColor ) );
+ mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
}
activateWindow(); // set focus back parent
}
diff --git a/src/app/qgsdiagramproperties.h b/src/app/qgsdiagramproperties.h
index dbda855..a42f761 100644
--- a/src/app/qgsdiagramproperties.h
+++ b/src/app/qgsdiagramproperties.h
@@ -21,6 +21,7 @@
#include "qgssymbolv2.h"
#include <QDialog>
#include <ui_qgsdiagrampropertiesbase.h>
+#include <QStyledItemDelegate>
class QgsVectorLayer;
class QgsMapCanvas;
@@ -59,6 +60,21 @@ class APP_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr
QgsVectorLayer* mLayer;
private:
+
+ enum Columns
+ {
+ ColumnAttributeExpression = 0,
+ ColumnColor,
+ ColumnLegendText,
+ };
+
+ enum Roles
+ {
+ RoleAttributeExpression = Qt::UserRole,
+ };
+
+ QString showExpressionBuilder( const QString& initialExpression );
+
// Keeps track of the diagram type to properly save / restore settings when the diagram type combo box is set to no diagram.
QString mDiagramType;
QScopedPointer< QgsMarkerSymbolV2 > mSizeLegendSymbol;
@@ -67,4 +83,18 @@ class APP_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr
QgsMapCanvas *mMapCanvas;
};
+class EditBlockerDelegate: public QStyledItemDelegate
+{
+ public:
+ EditBlockerDelegate( QObject* parent = nullptr )
+ : QStyledItemDelegate( parent )
+ {}
+
+ virtual QWidget* createEditor( QWidget *, const QStyleOptionViewItem &, const QModelIndex & ) const override
+ {
+ return nullptr;
+ }
+};
+
+
#endif // QGSDIAGRAMPROPERTIES_H
diff --git a/src/app/qgsdxfexportdialog.cpp b/src/app/qgsdxfexportdialog.cpp
index b67a6ac..64da1cf 100644
--- a/src/app/qgsdxfexportdialog.cpp
+++ b/src/app/qgsdxfexportdialog.cpp
@@ -28,6 +28,8 @@
#include "qgslayertreemapcanvasbridge.h"
#include "qgsvisibilitypresetcollection.h"
#include "qgsmapcanvas.h"
+#include "qgsgenericprojectionselector.h"
+#include "qgscrscache.h"
#include <QFileDialog>
#include <QPushButton>
@@ -453,10 +455,21 @@ QgsDxfExportDialog::QgsDxfExportDialog( QWidget *parent, Qt::WindowFlags f )
QStringList ids = QgsProject::instance()->visibilityPresetCollection()->presets();
ids.prepend( "" );
mVisibilityPresets->addItems( ids );
- mVisibilityPresets->setCurrentIndex( mVisibilityPresets->findText( QgsProject::instance()->readEntry( "dxf", "/lastVisibilityPreset", "" ) ) );
+ mVisibilityPresets->setCurrentIndex( mVisibilityPresets->findText( QgsProject::instance()->readEntry( "dxf", "/lastVisibliltyPreset", "" ) ) );
buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
restoreGeometry( s.value( "/Windows/DxfExport/geometry" ).toByteArray() );
+
+ mCRS = QgsProject::instance()->readEntry( "dxf", "/lastDxfCrs",
+ s.value( "qgis/lastDxfCrs", QString::number( QgisApp::instance()->mapCanvas()->mapSettings().destinationCrs().srsid() ) ).toString()
+ ).toLong();
+
+ QgsCoordinateReferenceSystem crs = QgsCRSCache::instance()->crsBySrsId( mCRS );
+ mCrsSelector->setCrs( crs );
+ mCrsSelector->setLayerCrs( crs );
+ mCrsSelector->dialog()->setMessage( tr( "Select the coordinate reference system for the dxf file. "
+ "The data points will be transformed from the layer coordinate reference system." ) );
+
mEncoding->addItems( QgsDxfExport::encodings() );
mEncoding->setCurrentIndex( mEncoding->findText( QgsProject::instance()->readEntry( "dxf", "/lastDxfEncoding", s.value( "qgis/lastDxfEncoding", "CP1252" ).toString() ) ) );
}
@@ -600,6 +613,7 @@ void QgsDxfExportDialog::saveSettings()
s.setValue( "qgis/lastDxfMapRectangle", mMapExtentCheckBox->isChecked() );
s.setValue( "qgis/lastDxfLayerTitleAsName", mLayerTitleAsName->isChecked() );
s.setValue( "qgis/lastDxfEncoding", mEncoding->currentText() );
+ s.setValue( "qgis/lastDxfCrs", QString::number( mCRS ) );
QgsProject::instance()->writeEntry( "dxf", "/lastDxfSymbologyMode", mSymbologyModeComboBox->currentIndex() );
QgsProject::instance()->writeEntry( "dxf", "/lastSymbologyExportScale", mScaleWidget->scale() );
@@ -607,6 +621,7 @@ void QgsDxfExportDialog::saveSettings()
QgsProject::instance()->writeEntry( "dxf", "/lastDxfMapRectangle", mMapExtentCheckBox->isChecked() );
QgsProject::instance()->writeEntry( "dxf", "/lastDxfEncoding", mEncoding->currentText() );
QgsProject::instance()->writeEntry( "dxf", "/lastVisibilityPreset", mVisibilityPresets->currentText() );
+ QgsProject::instance()->writeEntry( "dxf", "/lastDxfCrs", QString::number( mCRS ) );
}
@@ -614,3 +629,13 @@ QString QgsDxfExportDialog::encoding() const
{
return mEncoding->currentText();
}
+
+void QgsDxfExportDialog::on_mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
+{
+ mCRS = crs.srsid();
+}
+
+long QgsDxfExportDialog::crs() const
+{
+ return mCRS;
+}
diff --git a/src/app/qgsdxfexportdialog.h b/src/app/qgsdxfexportdialog.h
index 3ba6646..b795cfc 100644
--- a/src/app/qgsdxfexportdialog.h
+++ b/src/app/qgsdxfexportdialog.h
@@ -88,6 +88,7 @@ class QgsDxfExportDialog : public QDialog, private Ui::QgsDxfExportDialogBase
bool exportMapExtent() const;
bool layerTitleAsName() const;
QString encoding() const;
+ long crs() const;
public slots:
/** Change the selection of layers in the list */
@@ -99,11 +100,14 @@ class QgsDxfExportDialog : public QDialog, private Ui::QgsDxfExportDialogBase
void setOkEnabled();
void saveSettings();
void on_mVisibilityPresets_currentIndexChanged( int index );
+ void on_mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs );
private:
void cleanGroup( QgsLayerTreeNode *node );
QgsLayerTreeGroup *mLayerTreeGroup;
FieldSelectorDelegate *mFieldSelectorDelegate;
+
+ long mCRS;
};
#endif // QGSDXFEXPORTDIALOG_H
diff --git a/src/app/qgsfeatureaction.cpp b/src/app/qgsfeatureaction.cpp
index ffcf4ac..ed79ab4 100644
--- a/src/app/qgsfeatureaction.cpp
+++ b/src/app/qgsfeatureaction.cpp
@@ -143,6 +143,11 @@ bool QgsFeatureAction::addFeature( const QgsAttributeMap& defaultAttributes, boo
bool reuseLastValues = settings.value( "/qgis/digitizing/reuseLastValues", false ).toBool();
QgsDebugMsg( QString( "reuseLastValues: %1" ).arg( reuseLastValues ) );
+ QgsExpressionContext context;
+ context << QgsExpressionContextUtils::globalScope()
+ << QgsExpressionContextUtils::projectScope()
+ << QgsExpressionContextUtils::layerScope( mLayer );
+
// add the fields to the QgsFeature
const QgsFields& fields = mLayer->fields();
mFeature->initAttributes( fields.count() );
@@ -154,6 +159,11 @@ bool QgsFeatureAction::addFeature( const QgsAttributeMap& defaultAttributes, boo
{
v = defaultAttributes.value( idx );
}
+ else if ( !mLayer->defaultValueExpression( idx ).isEmpty() )
+ {
+ // client side default expression set - use this in preference to reusing last value
+ v = mLayer->defaultValue( idx, *mFeature, &context );
+ }
else if ( reuseLastValues && sLastUsedValues.contains( mLayer ) && sLastUsedValues[ mLayer ].contains( idx ) && !pkAttrList.contains( idx ) )
{
v = sLastUsedValues[ mLayer ][idx];
diff --git a/src/app/qgsfieldsproperties.cpp b/src/app/qgsfieldsproperties.cpp
index 7156216..b5bd2b2 100644
--- a/src/app/qgsfieldsproperties.cpp
+++ b/src/app/qgsfieldsproperties.cpp
@@ -28,6 +28,7 @@
#include "qgsrelationmanager.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
+#include "qgsfieldexpressionwidget.h"
#include <QTreeWidgetItem>
#include <QWidget>
@@ -73,7 +74,7 @@ QgsFieldsProperties::QgsFieldsProperties( QgsVectorLayer *layer, QWidget* parent
// tab and group display
mAddItemButton->setEnabled( false );
- mDesignerTree = new DesignerTree( mAttributesTreeFrame );
+ mDesignerTree = new DesignerTree( mLayer, mAttributesTreeFrame );
mDesignerListLayout->addWidget( mDesignerTree );
mDesignerTree->setHeaderLabels( QStringList() << tr( "Label" ) );
@@ -155,29 +156,45 @@ void QgsFieldsProperties::onAttributeSelectionChanged()
updateButtons();
}
-QTreeWidgetItem *QgsFieldsProperties::loadAttributeEditorTreeItem( QgsAttributeEditorElement* const widgetDef, QTreeWidgetItem* parent )
+QTreeWidgetItem* QgsFieldsProperties::loadAttributeEditorTreeItem( QgsAttributeEditorElement* const widgetDef, QTreeWidgetItem* parent )
{
QTreeWidgetItem* newWidget = nullptr;
switch ( widgetDef->type() )
{
case QgsAttributeEditorElement::AeTypeField:
- newWidget = mDesignerTree->addItem( parent, DesignerTreeItemData( DesignerTreeItemData::Field, widgetDef->name() ) );
+ {
+ DesignerTreeItemData itemData = DesignerTreeItemData( DesignerTreeItemData::Field, widgetDef->name() );
+ itemData.setShowLabel( widgetDef->showLabel() );
+ newWidget = mDesignerTree->addItem( parent, itemData );
break;
+ }
case QgsAttributeEditorElement::AeTypeRelation:
- newWidget = mDesignerTree->addItem( parent, DesignerTreeItemData( DesignerTreeItemData::Relation, widgetDef->name() ) );
+ {
+ const QgsAttributeEditorRelation* relationEditor = static_cast<const QgsAttributeEditorRelation*>( widgetDef );
+ DesignerTreeItemData itemData = DesignerTreeItemData( DesignerTreeItemData::Relation, widgetDef->name() );
+ itemData.setShowLabel( widgetDef->showLabel() );
+ RelationEditorConfiguration relEdConfig;
+ relEdConfig.showLinkButton = relationEditor->showLinkButton();
+ relEdConfig.showUnlinkButton = relationEditor->showUnlinkButton();
+ itemData.setRelationEditorConfiguration( relEdConfig );
+
+ newWidget = mDesignerTree->addItem( parent, itemData );
break;
+ }
case QgsAttributeEditorElement::AeTypeContainer:
{
DesignerTreeItemData itemData( DesignerTreeItemData::Container, widgetDef->name() );
+ itemData.setShowLabel( widgetDef->showLabel() );
- const QgsAttributeEditorContainer* container = dynamic_cast<const QgsAttributeEditorContainer*>( widgetDef );
+ const QgsAttributeEditorContainer* container = static_cast<const QgsAttributeEditorContainer*>( widgetDef );
if ( !container )
break;
itemData.setColumnCount( container->columnCount() );
itemData.setShowAsGroupBox( container->isGroupBox() );
+ itemData.setVisibilityExpression( container->visibilityExpression() );
newWidget = mDesignerTree->addItem( parent, itemData );
Q_FOREACH ( QgsAttributeEditorElement* wdg, container->children() )
@@ -333,7 +350,7 @@ void QgsFieldsProperties::setRow( int row, int idx, const QgsField& field )
setConfigForRow( row, cfg );
//set the alias for the attribute
- mFieldsList->setItem( row, attrAliasCol, new QTableWidgetItem( mLayer->attributeAlias( idx ) ) );
+ mFieldsList->setItem( row, attrAliasCol, new QTableWidgetItem( field.alias() ) );
//published WMS/WFS attributes
QTableWidgetItem* wmsAttrItem = new QTableWidgetItem();
@@ -543,8 +560,9 @@ void QgsFieldsProperties::attributeTypeDialog()
attributeTypeDialog.setFieldEditable( cfg.mEditable );
attributeTypeDialog.setLabelOnTop( cfg.mLabelOnTop );
attributeTypeDialog.setNotNull( cfg.mNotNull );
- attributeTypeDialog.setExpression( cfg.mConstraint );
- attributeTypeDialog.setExpressionDescription( cfg.mConstraintDescription );
+ attributeTypeDialog.setConstraintExpression( cfg.mConstraint );
+ attributeTypeDialog.setConstraintExpressionDescription( cfg.mConstraintDescription );
+ attributeTypeDialog.setDefaultValueExpression( mLayer->defaultValueExpression( index ) );
attributeTypeDialog.setWidgetV2Config( cfg.mEditorWidgetV2Config );
attributeTypeDialog.setWidgetV2Type( cfg.mEditorWidgetV2Type );
@@ -555,8 +573,9 @@ void QgsFieldsProperties::attributeTypeDialog()
cfg.mEditable = attributeTypeDialog.fieldEditable();
cfg.mLabelOnTop = attributeTypeDialog.labelOnTop();
cfg.mNotNull = attributeTypeDialog.notNull();
- cfg.mConstraintDescription = attributeTypeDialog.expressionDescription();
- cfg.mConstraint = attributeTypeDialog.expression();
+ cfg.mConstraintDescription = attributeTypeDialog.constraintExpressionDescription();
+ cfg.mConstraint = attributeTypeDialog.constraintExpression();
+ mLayer->setDefaultValueExpression( index, attributeTypeDialog.defaultValueExpression() );
cfg.mEditorWidgetV2Type = attributeTypeDialog.editorWidgetV2Type();
cfg.mEditorWidgetV2Config = attributeTypeDialog.editorWidgetV2Config();
@@ -880,7 +899,10 @@ QgsAttributeEditorElement* QgsFieldsProperties::createAttributeEditorWidget( QTr
case DesignerTreeItemData::Relation:
{
QgsRelation relation = QgsProject::instance()->relationManager()->relation( itemData.name() );
- widgetDef = new QgsAttributeEditorRelation( itemData.name(), relation, parent );
+ QgsAttributeEditorRelation* relDef = new QgsAttributeEditorRelation( itemData.name(), relation, parent );
+ relDef->setShowLinkButton( itemData.relationEditorConfiguration().showLinkButton );
+ relDef->setShowUnlinkButton( itemData.relationEditorConfiguration().showUnlinkButton );
+ widgetDef = relDef;
break;
}
@@ -889,6 +911,7 @@ QgsAttributeEditorElement* QgsFieldsProperties::createAttributeEditorWidget( QTr
QgsAttributeEditorContainer* container = new QgsAttributeEditorContainer( item->text( 0 ), parent );
container->setColumnCount( itemData.columnCount() );
container->setIsGroupBox( forceGroup ? true : itemData.showAsGroupBox() );
+ container->setVisibilityExpression( itemData.visibilityExpression() );
for ( int t = 0; t < item->childCount(); t++ )
{
@@ -900,6 +923,8 @@ QgsAttributeEditorElement* QgsFieldsProperties::createAttributeEditorWidget( QTr
}
}
+ widgetDef->setShowLabel( itemData.showLabel() );
+
return widgetDef;
}
@@ -1110,8 +1135,9 @@ QTreeWidgetItem* DesignerTree::addContainer( QTreeWidgetItem* parent, const QStr
return newItem;
}
-DesignerTree::DesignerTree( QWidget* parent )
+DesignerTree::DesignerTree( QgsVectorLayer* layer, QWidget* parent )
: QTreeWidget( parent )
+ , mLayer( layer )
{
connect( this, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( onItemDoubleClicked( QTreeWidgetItem*, int ) ) );
}
@@ -1268,21 +1294,43 @@ void DesignerTree::onItemDoubleClicked( QTreeWidgetItem* item, int column )
Q_UNUSED( column )
QgsFieldsProperties::DesignerTreeItemData itemData = item->data( 0, QgsFieldsProperties::DesignerTreeRole ).value<QgsFieldsProperties::DesignerTreeItemData>();
+ QGroupBox* baseData = new QGroupBox( tr( "Base configuration" ) );
+
+ QFormLayout* baseLayout = new QFormLayout();
+ baseData->setLayout( baseLayout );
+ QCheckBox* showLabelCheckbox = new QCheckBox( "Show label" );
+ showLabelCheckbox->setChecked( itemData.showLabel() );
+ baseLayout->addWidget( showLabelCheckbox );
+ QWidget* baseWidget = new QWidget();
+ baseWidget->setLayout( baseLayout );
+
if ( itemData.type() == QgsFieldsProperties::DesignerTreeItemData::Container )
{
QDialog dlg;
dlg.setWindowTitle( tr( "Configure container" ) );
QFormLayout* layout = new QFormLayout() ;
dlg.setLayout( layout );
+ layout->addWidget( baseWidget );
QCheckBox* showAsGroupBox = nullptr;
QLineEdit* title = new QLineEdit( itemData.name() );
QSpinBox* columnCount = new QSpinBox();
+ QGroupBox* visibilityExpressionGroupBox = new QGroupBox( tr( "Control visibility by expression " ) );
+ visibilityExpressionGroupBox->setCheckable( true );
+ visibilityExpressionGroupBox->setChecked( itemData.visibilityExpression().enabled() );
+ visibilityExpressionGroupBox->setLayout( new QGridLayout );
+ QgsFieldExpressionWidget* visibilityExpressionWidget = new QgsFieldExpressionWidget;
+ visibilityExpressionWidget->setLayer( mLayer );
+ visibilityExpressionWidget->setExpressionDialogTitle( tr( "Visibility expression" ) );
+ visibilityExpressionWidget->setExpression( itemData.visibilityExpression()->expression() );
+ visibilityExpressionGroupBox->layout()->addWidget( visibilityExpressionWidget );
+
columnCount->setRange( 1, 5 );
columnCount->setValue( itemData.columnCount() );
layout->addRow( tr( "Title" ), title );
layout->addRow( tr( "Column count" ), columnCount );
+ layout->addWidget( visibilityExpressionGroupBox );
if ( !item->parent() )
{
@@ -1304,10 +1352,72 @@ void DesignerTree::onItemDoubleClicked( QTreeWidgetItem* item, int column )
itemData.setColumnCount( columnCount->value() );
itemData.setShowAsGroupBox( showAsGroupBox ? showAsGroupBox->isChecked() : true );
itemData.setName( title->text() );
+ itemData.setShowLabel( showLabelCheckbox->isChecked() );
+
+ QgsOptionalExpression visibilityExpression;
+ visibilityExpression.setData( QgsExpression( visibilityExpressionWidget->expression() ) );
+ visibilityExpression.setEnabled( visibilityExpressionGroupBox->isChecked() );
+ itemData.setVisibilityExpression( visibilityExpression );
+
item->setData( 0, QgsFieldsProperties::DesignerTreeRole, itemData.asQVariant() );
item->setText( 0, title->text() );
}
}
+ else if ( itemData.type() == QgsFieldsProperties::DesignerTreeItemData::Relation )
+ {
+ QDialog dlg;
+ dlg.setWindowTitle( tr( "Configure relation editor" ) );
+ QFormLayout* layout = new QFormLayout() ;
+ dlg.setLayout( layout );
+ layout->addWidget( baseWidget );
+
+ QCheckBox* showLinkButton = new QCheckBox( tr( "Show link button" ) );
+ showLinkButton->setChecked( itemData.relationEditorConfiguration().showLinkButton );
+ QCheckBox* showUnlinkButton = new QCheckBox( tr( "Show unlink button" ) );
+ showUnlinkButton->setChecked( itemData.relationEditorConfiguration().showUnlinkButton );
+ layout->addRow( showLinkButton );
+ layout->addRow( showUnlinkButton );
+
+ QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
+
+ connect( buttonBox, SIGNAL( accepted() ), &dlg, SLOT( accept() ) );
+ connect( buttonBox, SIGNAL( rejected() ), &dlg, SLOT( reject() ) );
+
+ dlg.layout()->addWidget( buttonBox );
+
+ if ( dlg.exec() )
+ {
+ QgsFieldsProperties::RelationEditorConfiguration relEdCfg;
+ relEdCfg.showLinkButton = showLinkButton->isChecked();
+ relEdCfg.showUnlinkButton = showUnlinkButton->isChecked();
+ itemData.setShowLabel( showLabelCheckbox->isChecked() );
+ itemData.setRelationEditorConfiguration( relEdCfg );
+
+ item->setData( 0, QgsFieldsProperties::DesignerTreeRole, itemData.asQVariant() );
+ }
+ }
+ else
+ {
+ QDialog dlg;
+ dlg.setWindowTitle( tr( "Configure field" ) );
+ dlg.setLayout( new QGridLayout() );
+ dlg.layout()->addWidget( baseWidget );
+
+ QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok
+ | QDialogButtonBox::Cancel );
+
+ connect( buttonBox, SIGNAL( accepted() ), &dlg, SLOT( accept() ) );
+ connect( buttonBox, SIGNAL( rejected() ), &dlg, SLOT( reject() ) );
+
+ dlg.layout()->addWidget( buttonBox );
+
+ if ( dlg.exec() )
+ {
+ itemData.setShowLabel( showLabelCheckbox->isChecked() );
+
+ item->setData( 0, QgsFieldsProperties::DesignerTreeRole, itemData.asQVariant() );
+ }
+ }
}
/*
@@ -1342,3 +1452,33 @@ void QgsFieldsProperties::DesignerTreeItemData::setShowAsGroupBox( bool showAsGr
{
mShowAsGroupBox = showAsGroupBox;
}
+
+bool QgsFieldsProperties::DesignerTreeItemData::showLabel() const
+{
+ return mShowLabel;
+}
+
+void QgsFieldsProperties::DesignerTreeItemData::setShowLabel( bool showLabel )
+{
+ mShowLabel = showLabel;
+}
+
+QgsOptionalExpression QgsFieldsProperties::DesignerTreeItemData::visibilityExpression() const
+{
+ return mVisibilityExpression;
+}
+
+void QgsFieldsProperties::DesignerTreeItemData::setVisibilityExpression( const QgsOptionalExpression& visibilityExpression )
+{
+ mVisibilityExpression = visibilityExpression;
+}
+
+QgsFieldsProperties::RelationEditorConfiguration QgsFieldsProperties::DesignerTreeItemData::relationEditorConfiguration() const
+{
+ return mRelationEditorConfiguration;
+}
+
+void QgsFieldsProperties::DesignerTreeItemData::setRelationEditorConfiguration( const QgsFieldsProperties::RelationEditorConfiguration& relationEditorConfiguration )
+{
+ mRelationEditorConfiguration = relationEditorConfiguration;
+}
diff --git a/src/app/qgsfieldsproperties.h b/src/app/qgsfieldsproperties.h
index 798ec97..ba80ae1 100644
--- a/src/app/qgsfieldsproperties.h
+++ b/src/app/qgsfieldsproperties.h
@@ -42,6 +42,16 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
FieldConfigRole
};
+ struct RelationEditorConfiguration
+ {
+ RelationEditorConfiguration()
+ : showLinkButton( true )
+ , showUnlinkButton( true )
+ {}
+ bool showLinkButton;
+ bool showUnlinkButton;
+ };
+
class DesignerTreeItemData
{
public:
@@ -56,6 +66,7 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
: mType( Field )
, mColumnCount( 1 )
, mShowAsGroupBox( false )
+ , mShowLabel( true )
{}
DesignerTreeItemData( Type type, const QString& name )
@@ -63,6 +74,7 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
, mName( name )
, mColumnCount( 1 )
, mShowAsGroupBox( false )
+ , mShowLabel( true )
{}
QString name() const { return mName; }
@@ -79,11 +91,23 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
bool showAsGroupBox() const;
void setShowAsGroupBox( bool showAsGroupBox );
+ bool showLabel() const;
+ void setShowLabel( bool showLabel );
+
+ QgsOptionalExpression visibilityExpression() const;
+ void setVisibilityExpression( const QgsOptionalExpression& visibilityExpression );
+
+ RelationEditorConfiguration relationEditorConfiguration() const;
+ void setRelationEditorConfiguration( const RelationEditorConfiguration& relationEditorConfiguration );
+
private:
Type mType;
QString mName;
int mColumnCount;
bool mShowAsGroupBox;
+ bool mShowLabel;
+ QgsOptionalExpression mVisibilityExpression;
+ RelationEditorConfiguration mRelationEditorConfiguration;
};
/**
@@ -264,7 +288,7 @@ class DesignerTree : public QTreeWidget
Q_OBJECT
public:
- explicit DesignerTree( QWidget* parent = nullptr );
+ explicit DesignerTree( QgsVectorLayer* layer, QWidget* parent = nullptr );
QTreeWidgetItem* addItem( QTreeWidgetItem* parent, QgsFieldsProperties::DesignerTreeItemData data );
QTreeWidgetItem* addContainer( QTreeWidgetItem* parent, const QString& title , int columnCount );
@@ -281,6 +305,9 @@ class DesignerTree : public QTreeWidget
private slots:
void onItemDoubleClicked( QTreeWidgetItem* item, int column );
+
+ private:
+ QgsVectorLayer* mLayer;
};
Q_DECLARE_METATYPE( QgsFieldsProperties::FieldConfig )
diff --git a/src/app/qgsformannotationdialog.cpp b/src/app/qgsformannotationdialog.cpp
index 839c135..09f5aae 100644
--- a/src/app/qgsformannotationdialog.cpp
+++ b/src/app/qgsformannotationdialog.cpp
@@ -89,3 +89,11 @@ void QgsFormAnnotationDialog::deleteItem()
mItem = nullptr;
}
+void QgsFormAnnotationDialog::on_mButtonBox_clicked( QAbstractButton* button )
+{
+ if ( mButtonBox->buttonRole( button ) == QDialogButtonBox::ApplyRole )
+ {
+ applySettingsToItem();
+ }
+}
+
diff --git a/src/app/qgsformannotationdialog.h b/src/app/qgsformannotationdialog.h
index 13e0d8b..0ae8b60 100644
--- a/src/app/qgsformannotationdialog.h
+++ b/src/app/qgsformannotationdialog.h
@@ -35,6 +35,7 @@ class APP_EXPORT QgsFormAnnotationDialog: public QDialog, private Ui::QgsFormAnn
void applySettingsToItem();
void on_mBrowseToolButton_clicked();
void deleteItem();
+ void on_mButtonBox_clicked( QAbstractButton* button );
};
#endif // QGSFORMANNOTATIONDIALOG_H
diff --git a/src/app/qgshtmlannotationdialog.cpp b/src/app/qgshtmlannotationdialog.cpp
index a3c77e7..0ae1896 100644
--- a/src/app/qgshtmlannotationdialog.cpp
+++ b/src/app/qgshtmlannotationdialog.cpp
@@ -94,3 +94,11 @@ void QgsHtmlAnnotationDialog::deleteItem()
mItem = nullptr;
}
+void QgsHtmlAnnotationDialog::on_mButtonBox_clicked( QAbstractButton* button )
+{
+ if ( mButtonBox->buttonRole( button ) == QDialogButtonBox::ApplyRole )
+ {
+ applySettingsToItem();
+ }
+}
+
diff --git a/src/app/qgshtmlannotationdialog.h b/src/app/qgshtmlannotationdialog.h
index 1d3b28a..e44fd3b 100644
--- a/src/app/qgshtmlannotationdialog.h
+++ b/src/app/qgshtmlannotationdialog.h
@@ -35,6 +35,7 @@ class APP_EXPORT QgsHtmlAnnotationDialog: public QDialog, private Ui::QgsFormAnn
void applySettingsToItem();
void on_mBrowseToolButton_clicked();
void deleteItem();
+ void on_mButtonBox_clicked( QAbstractButton* button );
};
#endif // QgsHTMLAnnotationDialog_H
diff --git a/src/app/qgsidentifyresultsdialog.cpp b/src/app/qgsidentifyresultsdialog.cpp
index 8d36af2..a878524 100644
--- a/src/app/qgsidentifyresultsdialog.cpp
+++ b/src/app/qgsidentifyresultsdialog.cpp
@@ -37,6 +37,7 @@
#include "qgsvectordataprovider.h"
#include "qgswebview.h"
#include "qgswebframe.h"
+#include "qgsstringutils.h"
#include <QCloseEvent>
#include <QLabel>
@@ -53,6 +54,7 @@
#include <QDesktopServices>
#include <QMessageBox>
#include <QComboBox>
+#include <QTextDocument>
//graph
#include <qwt_plot.h>
@@ -61,7 +63,6 @@
#include <qwt_legend.h>
#include "qgsvectorcolorrampv2.h" // for random colors
-
QgsIdentifyResultsWebView::QgsIdentifyResultsWebView( QWidget *parent ) : QgsWebView( parent )
{
setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Minimum );
@@ -473,12 +474,18 @@ void QgsIdentifyResultsDialog::addFeature( QgsVectorLayer *vlayer, const QgsFeat
if ( i >= fields.count() )
continue;
+ if ( vlayer->editFormConfig()->widgetType( i ) == "Hidden" )
+ {
+ continue;
+ }
+
QString defVal;
if ( fields.fieldOrigin( i ) == QgsFields::OriginProvider && vlayer->dataProvider() )
defVal = vlayer->dataProvider()->defaultValue( fields.fieldOriginIndex( i ) ).toString();
QString value = defVal == attrs.at( i ) ? defVal : fields.at( i ).displayString( attrs.at( i ) );
QTreeWidgetItem *attrItem = new QTreeWidgetItem( QStringList() << QString::number( i ) << value );
+ featItem->addChild( attrItem );
attrItem->setData( 0, Qt::DisplayRole, vlayer->attributeDisplayName( i ) );
attrItem->setData( 0, Qt::UserRole, fields[i].name() );
@@ -486,15 +493,21 @@ void QgsIdentifyResultsDialog::addFeature( QgsVectorLayer *vlayer, const QgsFeat
attrItem->setData( 1, Qt::UserRole, value );
- if ( vlayer->editFormConfig()->widgetType( i ) == "Hidden" )
+ value = representValue( vlayer, fields.at( i ).name(), attrs.at( i ) );
+ bool foundLinks = false;
+ QString links = QgsStringUtils::insertLinks( value, &foundLinks );
+ if ( foundLinks )
{
- delete attrItem;
- continue;
+ QLabel* valueLabel = new QLabel( links );
+ valueLabel->setOpenExternalLinks( true );
+ attrItem->treeWidget()->setItemWidget( attrItem, 1, valueLabel );
+ attrItem->setData( 1, Qt::DisplayRole, QString() );
+ }
+ else
+ {
+ attrItem->setData( 1, Qt::DisplayRole, value );
+ attrItem->treeWidget()->setItemWidget( attrItem, 1, nullptr );
}
-
- value = representValue( vlayer, fields[i].name(), attrs.at( i ) );
-
- attrItem->setData( 1, Qt::DisplayRole, value );
if ( fields[i].name() == vlayer->displayField() )
{
@@ -502,8 +515,6 @@ void QgsIdentifyResultsDialog::addFeature( QgsVectorLayer *vlayer, const QgsFeat
featItem->setText( 1, attrItem->text( 1 ) );
featureLabeled = true;
}
-
- featItem->addChild( attrItem );
}
if ( !featureLabeled )
@@ -958,7 +969,7 @@ void QgsIdentifyResultsDialog::contextMenuEvent( QContextMenuEvent* event )
if ( vlayer )
{
mActionPopup->addAction(
- QgsApplication::getThemeIcon( "/mActionPropertyItem.png" ),
+ QgsApplication::getThemeIcon( "/mActionPropertyItem.svg" ),
vlayer->isEditable() ? tr( "Edit feature form" ) : tr( "View feature form" ),
this, SLOT( featureForm() ) );
}
@@ -1482,7 +1493,21 @@ void QgsIdentifyResultsDialog::attributeValueChanged( QgsFeatureId fid, int idx,
if ( item->data( 0, Qt::UserRole + 1 ).toInt() == idx )
{
value = representValue( vlayer, fld.name(), val );
- item->setData( 1, Qt::DisplayRole, value );
+
+ bool foundLinks = false;
+ QString links = QgsStringUtils::insertLinks( value, &foundLinks );
+ if ( foundLinks )
+ {
+ QLabel* valueLabel = new QLabel( links );
+ valueLabel->setOpenExternalLinks( true );
+ item->treeWidget()->setItemWidget( item, 1, valueLabel );
+ item->setData( 1, Qt::DisplayRole, QString() );
+ }
+ else
+ {
+ item->treeWidget()->setItemWidget( item, 1, nullptr );
+ item->setData( 1, Qt::DisplayRole, value );
+ }
return;
}
}
diff --git a/src/app/qgslabelinggui.cpp b/src/app/qgslabelinggui.cpp
index b2f89bd..3dd2acf 100644
--- a/src/app/qgslabelinggui.cpp
+++ b/src/app/qgslabelinggui.cpp
@@ -35,6 +35,7 @@
#include "qgssvgselectorwidget.h"
#include "qgsvectorlayerlabeling.h"
#include "qgslogger.h"
+#include "qgssubstitutionlistwidget.h"
#include <QCheckBox>
#include <QSettings>
@@ -139,6 +140,7 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
connect( mShadowTranspSlider, SIGNAL( valueChanged( int ) ), mShadowTranspSpnBx, SLOT( setValue( int ) ) );
connect( mShadowTranspSpnBx, SIGNAL( valueChanged( int ) ), mShadowTranspSlider, SLOT( setValue( int ) ) );
connect( mLimitLabelChkBox, SIGNAL( toggled( bool ) ), mLimitLabelSpinBox, SLOT( setEnabled( bool ) ) );
+ connect( mCheckBoxSubstituteText, SIGNAL( toggled( bool ) ), mToolButtonConfigureSubstitutes, SLOT( setEnabled( bool ) ) );
//connections to prevent users removing all line placement positions
connect( chkLineAbove, SIGNAL( toggled( bool ) ), this, SLOT( updateLinePlacementOptions() ) );
@@ -220,6 +222,7 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
mPlacePolygonBtnGrp->addButton( radPolygonHorizontal, ( int )QgsPalLayerSettings::Horizontal );
mPlacePolygonBtnGrp->addButton( radPolygonFree, ( int )QgsPalLayerSettings::Free );
mPlacePolygonBtnGrp->addButton( radPolygonPerimeter, ( int )QgsPalLayerSettings::Line );
+ mPlacePolygonBtnGrp->addButton( radPolygonPerimeterCurved, ( int )QgsPalLayerSettings::PerimeterCurved );
mPlacePolygonBtnGrp->setExclusive( true );
connect( mPlacePolygonBtnGrp, SIGNAL( buttonClicked( int ) ), this, SLOT( updatePlacementWidgets() ) );
@@ -351,6 +354,7 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
<< mLineDistanceDDBtn
<< mLineDistanceSpnBx
<< mLineDistanceUnitDDBtn
+ << mLineDistanceUnitWidget
<< mMaxCharAngleDDBtn
<< mMaxCharAngleInDSpinBox
<< mMaxCharAngleOutDSpinBox
@@ -364,6 +368,7 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
<< mPointAngleSpinBox
<< mPointOffsetDDBtn
<< mPointOffsetUnitsDDBtn
+ << mPointOffsetUnitWidget
<< mPointOffsetXSpinBox
<< mPointOffsetYSpinBox
<< mPointPositionOrderDDBtn
@@ -375,6 +380,7 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
<< mRepeatDistanceDDBtn
<< mRepeatDistanceSpinBox
<< mRepeatDistanceUnitDDBtn
+ << mRepeatDistanceUnitWidget
<< mScaleBasedVisibilityChkBx
<< mScaleBasedVisibilityDDBtn
<< mScaleBasedVisibilityMaxDDBtn
@@ -393,10 +399,12 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
<< mShadowOffsetGlobalChkBx
<< mShadowOffsetSpnBx
<< mShadowOffsetUnitsDDBtn
+ << mShadowOffsetUnitWidget
<< mShadowRadiusAlphaChkBx
<< mShadowRadiusDDBtn
<< mShadowRadiusDblSpnBx
<< mShadowRadiusUnitsDDBtn
+ << mShadowRadiusUnitWidget
<< mShadowScaleDDBtn
<< mShadowScaleSpnBx
<< mShadowTranspDDBtn
@@ -410,6 +418,7 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
<< mShapeBorderUnitsDDBtn
<< mShapeBorderWidthDDBtn
<< mShapeBorderWidthSpnBx
+ << mShapeBorderWidthUnitWidget
<< mShapeDrawChkBx
<< mShapeDrawDDBtn
<< mShapeFillColorBtn
@@ -418,6 +427,7 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
<< mShapeOffsetUnitsDDBtn
<< mShapeOffsetXSpnBx
<< mShapeOffsetYSpnBx
+ << mShapeOffsetUnitWidget
<< mShapePenStyleCmbBx
<< mShapePenStyleDDBtn
<< mShapeRadiusDDBtn
@@ -428,11 +438,13 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
<< mShapeRotationDDBtn
<< mShapeRotationDblSpnBx
<< mShapeRotationTypeDDBtn
+ << mShapeRadiusUnitWidget
<< mShapeSVGPathDDBtn
<< mShapeSVGPathLineEdit
<< mShapeSizeCmbBx
<< mShapeSizeTypeDDBtn
<< mShapeSizeUnitsDDBtn
+ << mShapeSizeUnitWidget
<< mShapeSizeXDDBtn
<< mShapeSizeXSpnBx
<< mShapeSizeYDDBtn
@@ -465,8 +477,10 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
<< radPolygonFree
<< radPolygonHorizontal
<< radPolygonPerimeter
+ << radPolygonPerimeterCurved
<< radPredefinedOrder
- << mFieldExpressionWidget;
+ << mFieldExpressionWidget
+ << mCheckBoxSubstituteText;
connectValueChanged( widgets, SLOT( updatePreview() ) );
connect( mQuadrantBtnGrp, SIGNAL( buttonClicked( int ) ), this, SLOT( updatePreview() ) );
@@ -504,6 +518,10 @@ void QgsLabelingGui::connectValueChanged( QList<QWidget *> widgets, const char *
{
connect( w, SIGNAL( fieldChanged( QString ) ), this, slot );
}
+ else if ( QgsUnitSelectionWidget* w = qobject_cast<QgsUnitSelectionWidget*>( widget ) )
+ {
+ connect( w, SIGNAL( changed() ), this, slot );
+ }
else if ( QComboBox* w = qobject_cast<QComboBox*>( widget ) )
{
connect( w, SIGNAL( currentIndexChanged( int ) ), this, slot );
@@ -623,6 +641,8 @@ void QgsLabelingGui::init()
// set the current field or add the current expression to the bottom of the list
mFieldExpressionWidget->setRow( -1 );
mFieldExpressionWidget->setField( lyr.fieldName );
+ mCheckBoxSubstituteText->setChecked( lyr.useSubstitutions );
+ mSubstitutions = lyr.substitutions;
// populate placement options
mCentroidRadioWhole->setChecked( lyr.centroidWhole );
@@ -641,8 +661,7 @@ void QgsLabelingGui::init()
chkLineAbove->setChecked( lyr.placementFlags & QgsPalLayerSettings::AboveLine );
chkLineBelow->setChecked( lyr.placementFlags & QgsPalLayerSettings::BelowLine );
chkLineOn->setChecked( lyr.placementFlags & QgsPalLayerSettings::OnLine );
- if ( !( lyr.placementFlags & QgsPalLayerSettings::MapOrientation ) )
- chkLineOrientationDependent->setChecked( true );
+ chkLineOrientationDependent->setChecked( !( lyr.placementFlags & QgsPalLayerSettings::MapOrientation ) );
switch ( lyr.placement )
{
@@ -672,6 +691,9 @@ void QgsLabelingGui::init()
case QgsPalLayerSettings::Free:
radPolygonFree->setChecked( true );
break;
+ case QgsPalLayerSettings::PerimeterCurved:
+ radPolygonPerimeterCurved->setChecked( true );
+ break;
}
// Label repeat distance
@@ -962,11 +984,17 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
lyr.placement = QgsPalLayerSettings::OrderedPositionsAroundPoint;
}
else if (( curPlacementWdgt == pageLine && radLineParallel->isChecked() )
- || ( curPlacementWdgt == pagePolygon && radPolygonPerimeter->isChecked() )
- || ( curPlacementWdgt == pageLine && radLineCurved->isChecked() ) )
+ || ( curPlacementWdgt == pagePolygon && radPolygonPerimeter->isChecked() ) )
+ {
+ lyr.placement = QgsPalLayerSettings::Line;
+ }
+ else if ( curPlacementWdgt == pageLine && radLineCurved->isChecked() )
+ {
+ lyr.placement = QgsPalLayerSettings::Curved;
+ }
+ else if ( curPlacementWdgt == pagePolygon && radPolygonPerimeterCurved->isChecked() )
{
- bool curved = ( curPlacementWdgt == pageLine && radLineCurved->isChecked() );
- lyr.placement = ( curved ? QgsPalLayerSettings::Curved : QgsPalLayerSettings::Line );
+ lyr.placement = QgsPalLayerSettings::PerimeterCurved;
}
else if (( curPlacementWdgt == pageLine && radLineHorizontal->isChecked() )
|| ( curPlacementWdgt == pagePolygon && radPolygonHorizontal->isChecked() ) )
@@ -1004,6 +1032,8 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
lyr.scaleVisibility = mScaleBasedVisibilityChkBx->isChecked();
lyr.scaleMin = mScaleBasedVisibilityMinSpnBx->value();
lyr.scaleMax = mScaleBasedVisibilityMaxSpnBx->value();
+ lyr.useSubstitutions = mCheckBoxSubstituteText->isChecked();
+ lyr.substitutions = mSubstitutions;
// buffer
lyr.bufferDraw = mBufferDrawChkBx->isChecked();
@@ -1707,7 +1737,8 @@ void QgsLabelingGui::updatePlacementWidgets()
}
else if (( curWdgt == pageLine && radLineParallel->isChecked() )
|| ( curWdgt == pagePolygon && radPolygonPerimeter->isChecked() )
- || ( curWdgt == pageLine && radLineCurved->isChecked() ) )
+ || ( curWdgt == pageLine && radLineCurved->isChecked() )
+ || ( curWdgt == pagePolygon && radPolygonPerimeterCurved->isChecked() ) )
{
showLineFrame = true;
showDistanceFrame = true;
@@ -1717,9 +1748,11 @@ void QgsLabelingGui::updatePlacementWidgets()
chkLineOrientationDependent->setEnabled( offline );
mPlacementDistanceFrame->setEnabled( offline );
- showMaxCharAngleFrame = ( curWdgt == pageLine && radLineCurved->isChecked() );
+ bool isCurved = ( curWdgt == pageLine && radLineCurved->isChecked() )
+ || ( curWdgt == pagePolygon && radPolygonPerimeterCurved->isChecked() );
+ showMaxCharAngleFrame = isCurved;
// TODO: enable mMultiLinesFrame when supported for curved labels
- enableMultiLinesFrame = !( curWdgt == pageLine && radLineCurved->isChecked() );
+ enableMultiLinesFrame = !isCurved;
}
mPlacementLineFrame->setVisible( showLineFrame );
@@ -1731,7 +1764,8 @@ void QgsLabelingGui::updatePlacementWidgets()
mPlacementDistanceFrame->setVisible( showDistanceFrame );
mPlacementOffsetTypeFrame->setVisible( showOffsetTypeFrame );
mPlacementRotationFrame->setVisible( showRotationFrame );
- mPlacementRepeatDistanceFrame->setVisible( curWdgt == pageLine || ( curWdgt == pagePolygon && radPolygonPerimeter->isChecked() ) );
+ mPlacementRepeatDistanceFrame->setVisible( curWdgt == pageLine || ( curWdgt == pagePolygon &&
+ ( radPolygonPerimeter->isChecked() || radPolygonPerimeterCurved->isChecked() ) ) );
mPlacementMaxCharAngleFrame->setVisible( showMaxCharAngleFrame );
mMultiLinesFrame->setEnabled( enableMultiLinesFrame );
@@ -1960,6 +1994,12 @@ void QgsLabelingGui::updateLinePlacementOptions()
}
}
+void QgsLabelingGui::onSubstitutionsChanged( const QgsStringReplacementCollection& substitutions )
+{
+ mSubstitutions = substitutions;
+ emit widgetChanged();
+}
+
void QgsLabelingGui::updateSvgWidgets( const QString& svgPath )
{
if ( mShapeSVGPathLineEdit->text() != svgPath )
@@ -2086,6 +2126,42 @@ void QgsLabelingGui::on_mChkNoObstacle_toggled( bool active )
mObstaclePriorityFrame->setEnabled( active );
}
+void QgsLabelingGui::on_chkLineOrientationDependent_toggled( bool active )
+{
+ if ( active )
+ {
+ chkLineAbove->setText( tr( "Left of line" ) );
+ chkLineBelow->setText( tr( "Right of line" ) );
+ }
+ else
+ {
+ chkLineAbove->setText( tr( "Above line" ) );
+ chkLineBelow->setText( tr( "Below line" ) );
+ }
+}
+
+void QgsLabelingGui::on_mToolButtonConfigureSubstitutes_clicked()
+{
+ QgsPanelWidget* panel = QgsPanelWidget::findParentPanel( this );
+ if ( panel && panel->dockMode() )
+ {
+ QgsSubstitutionListWidget* widget = new QgsSubstitutionListWidget( panel );
+ widget->setPanelTitle( tr( "Substitutions" ) );
+ widget->setSubstitutions( mSubstitutions );
+ connect( widget, SIGNAL( substitutionsChanged( QgsStringReplacementCollection ) ), this, SLOT( onSubstitutionsChanged( QgsStringReplacementCollection ) ) );
+ panel->openPanel( widget );
+ return;
+ }
+
+ QgsSubstitutionListDialog dlg( this );
+ dlg.setSubstitutions( mSubstitutions );
+ if ( dlg.exec() == QDialog::Accepted )
+ {
+ mSubstitutions = dlg.substitutions();
+ emit widgetChanged();
+ }
+}
+
void QgsLabelingGui::showBackgroundRadius( bool show )
{
mShapeRadiusLabel->setVisible( show );
diff --git a/src/app/qgslabelinggui.h b/src/app/qgslabelinggui.h
index f944372..4353c0b 100644
--- a/src/app/qgslabelinggui.h
+++ b/src/app/qgslabelinggui.h
@@ -21,6 +21,7 @@
#include <QDialog>
#include <QFontDatabase>
#include <ui_qgslabelingguibase.h>
+#include "qgsstringutils.h"
class QgsVectorLayer;
class QgsMapCanvas;
@@ -95,6 +96,9 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
void on_mDirectSymbLeftToolBtn_clicked();
void on_mDirectSymbRightToolBtn_clicked();
void on_mChkNoObstacle_toggled( bool active );
+ void on_chkLineOrientationDependent_toggled( bool active );
+
+ void on_mToolButtonConfigureSubstitutes_clicked();
protected:
void blockInitSignals( bool block );
@@ -135,6 +139,8 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
bool mLoadSvgParams;
+ QgsStringReplacementCollection mSubstitutions;
+
void enableDataDefinedAlignment( bool enable );
private slots:
@@ -143,6 +149,7 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
void showBackgroundPenStyle( bool show );
void on_mShapeSVGPathLineEdit_textChanged( const QString& text );
void updateLinePlacementOptions();
+ void onSubstitutionsChanged( const QgsStringReplacementCollection& substitutions );
};
#endif
diff --git a/src/app/qgslabelingwidget.cpp b/src/app/qgslabelingwidget.cpp
index 5c12c4a..558c87f 100644
--- a/src/app/qgslabelingwidget.cpp
+++ b/src/app/qgslabelingwidget.cpp
@@ -181,4 +181,5 @@ void QgsLabelingWidget::showEngineConfigDialog()
{
QgsLabelEngineConfigDialog dlg( this );
dlg.exec();
+ emit widgetChanged();
}
diff --git a/src/app/qgslayerstylingwidget.cpp b/src/app/qgslayerstylingwidget.cpp
index 1cbb2e7..8912297 100644
--- a/src/app/qgslayerstylingwidget.cpp
+++ b/src/app/qgslayerstylingwidget.cpp
@@ -37,6 +37,7 @@
#include "qgsrendererv2.h"
#include "qgsrendererv2registry.h"
#include "qgsmaplayerregistry.h"
+#include "qgsrasterdataprovider.h"
#include "qgsrasterlayer.h"
#include "qgsmaplayerconfigwidget.h"
#include "qgsmaplayerstylemanagerwidget.h"
@@ -170,10 +171,14 @@ void QgsLayerStylingWidget::setLayer( QgsMapLayer *layer )
transparencyItem->setToolTip( tr( "Transparency" ) );
transparencyItem->setData( Qt::UserRole, RasterTransparency );
mOptionsListWidget->addItem( transparencyItem );
- QListWidgetItem* histogramItem = new QListWidgetItem( QgsApplication::getThemeIcon( "propertyicons/histogram.png" ), QString() );
- histogramItem->setData( Qt::UserRole, RasterHistogram );
- mOptionsListWidget->addItem( histogramItem );
- histogramItem->setToolTip( tr( "Histogram" ) );
+
+ if ( static_cast<QgsRasterLayer*>( layer )->dataProvider()->capabilities() & QgsRasterDataProvider::Size )
+ {
+ QListWidgetItem* histogramItem = new QListWidgetItem( QgsApplication::getThemeIcon( "propertyicons/histogram.png" ), QString() );
+ histogramItem->setData( Qt::UserRole, RasterHistogram );
+ mOptionsListWidget->addItem( histogramItem );
+ histogramItem->setToolTip( tr( "Histogram" ) );
+ }
}
Q_FOREACH ( QgsMapLayerConfigWidgetFactory* factory, mPageFactories )
@@ -262,8 +267,7 @@ void QgsLayerStylingWidget::apply()
{
emit styleChanged( mCurrentLayer );
QgsProject::instance()->setDirty( true );
- mMapCanvas->clearCache();
- mMapCanvas->refresh();
+ mCurrentLayer->triggerRepaint();
}
connect( mCurrentLayer, SIGNAL( styleChanged() ), this, SLOT( updateCurrentWidgetLayer() ) );
}
@@ -328,6 +332,7 @@ void QgsLayerStylingWidget::updateCurrentWidgetLayer()
if ( panel )
{
connect( panel, SIGNAL( widgetChanged( QgsPanelWidget* ) ), this, SLOT( autoApply() ) );
+ panel->setDockMode( true );
mWidgetStack->addMainPanel( panel );
}
}
@@ -379,33 +384,39 @@ void QgsLayerStylingWidget::updateCurrentWidgetLayer()
{
case 0: // Style
mRasterStyleWidget = new QgsRendererRasterPropertiesWidget( rlayer, mMapCanvas, mWidgetStack );
+ mRasterStyleWidget->setDockMode( true );
connect( mRasterStyleWidget, SIGNAL( widgetChanged() ), this, SLOT( autoApply() ) );
mWidgetStack->addMainPanel( mRasterStyleWidget );
break;
case 1: // Transparency
{
QgsRasterTransparencyWidget* transwidget = new QgsRasterTransparencyWidget( rlayer, mMapCanvas, mWidgetStack );
+ transwidget->setDockMode( true );
connect( transwidget, SIGNAL( widgetChanged() ), this, SLOT( autoApply() ) );
mWidgetStack->addMainPanel( transwidget );
break;
}
case 2: // Histogram
{
- if ( mRasterStyleWidget )
+ if ( rlayer->dataProvider()->capabilities() & QgsRasterDataProvider::Size )
{
- mRasterStyleWidget->deleteLater();
- delete mRasterStyleWidget;
+ if ( mRasterStyleWidget )
+ {
+ mRasterStyleWidget->deleteLater();
+ delete mRasterStyleWidget;
+ }
+ mRasterStyleWidget = new QgsRendererRasterPropertiesWidget( rlayer, mMapCanvas, mWidgetStack );
+ mRasterStyleWidget->syncToLayer( rlayer );
+ connect( mRasterStyleWidget, SIGNAL( widgetChanged() ), this, SLOT( autoApply() ) );
+
+ QgsRasterHistogramWidget* widget = new QgsRasterHistogramWidget( rlayer, mWidgetStack );
+ connect( widget, SIGNAL( widgetChanged() ), this, SLOT( autoApply() ) );
+ QString name = mRasterStyleWidget->currentRenderWidget()->renderer()->type();
+ widget->setRendererWidget( name, mRasterStyleWidget->currentRenderWidget() );
+ widget->setDockMode( true );
+
+ mWidgetStack->addMainPanel( widget );
}
- mRasterStyleWidget = new QgsRendererRasterPropertiesWidget( rlayer, mMapCanvas, mWidgetStack );
- mRasterStyleWidget->syncToLayer( rlayer );
- connect( mRasterStyleWidget, SIGNAL( widgetChanged() ), this, SLOT( autoApply() ) );
-
- QgsRasterHistogramWidget* widget = new QgsRasterHistogramWidget( rlayer, mWidgetStack );
- connect( widget, SIGNAL( widgetChanged() ), this, SLOT( autoApply() ) );
- QString name = mRasterStyleWidget->currentRenderWidget()->renderer()->type();
- widget->setRendererWidget( name, mRasterStyleWidget->currentRenderWidget() );
-
- mWidgetStack->addMainPanel( widget );
break;
}
default:
diff --git a/src/app/qgsmeasuredialog.cpp b/src/app/qgsmeasuredialog.cpp
index edd12e5..15cb2f0 100644
--- a/src/app/qgsmeasuredialog.cpp
+++ b/src/app/qgsmeasuredialog.cpp
@@ -113,6 +113,13 @@ void QgsMeasureDialog::unitsChanged( int index )
mTable->clear();
mTotal = 0.;
updateUi();
+
+ if ( !mTool->done() )
+ {
+ // re-add temporary mouse cursor position
+ addPoint( mLastMousePoint );
+ mouseMove( mLastMousePoint );
+ }
}
void QgsMeasureDialog::restart()
@@ -207,16 +214,24 @@ void QgsMeasureDialog::removeLastPoint()
//remove final row
delete mTable->takeTopLevelItem( mTable->topLevelItemCount() - 1 );
- QgsPoint p1( mTool->points().last() );
- double d = mDa.measureLine( p1, mLastMousePoint );
-
mTotal = mDa.measureLine( mTool->points() );
- editTotal->setText( formatDistance( mTotal + d ) );
- d = convertLength( d, mDistanceUnits );
+ if ( !mTool->done() )
+ {
+ // need to add the distance for the temporary mouse cursor point
+ QgsPoint p1( mTool->points().last() );
+ double d = mDa.measureLine( p1, mLastMousePoint );
- QTreeWidgetItem *item = mTable->topLevelItem( mTable->topLevelItemCount() - 1 );
- item->setText( 0, QLocale::system().toString( d, 'f', mDecimalPlaces ) );
+ d = convertLength( d, mDistanceUnits );
+
+ QTreeWidgetItem *item = mTable->topLevelItem( mTable->topLevelItemCount() - 1 );
+ item->setText( 0, QLocale::system().toString( d, 'f', mDecimalPlaces ) );
+ editTotal->setText( formatDistance( mTotal + d ) );
+ }
+ else
+ {
+ editTotal->setText( formatDistance( mTotal ) );
+ }
}
}
diff --git a/src/app/qgsmergeattributesdialog.cpp b/src/app/qgsmergeattributesdialog.cpp
index 0ca2acd..2298a01 100644
--- a/src/app/qgsmergeattributesdialog.cpp
+++ b/src/app/qgsmergeattributesdialog.cpp
@@ -522,6 +522,11 @@ QgsAttributes QgsMergeAttributesDialog::mergedAttributes() const
return QgsAttributes();
}
+ QgsExpressionContext context;
+ context << QgsExpressionContextUtils::globalScope()
+ << QgsExpressionContextUtils::projectScope()
+ << QgsExpressionContextUtils::layerScope( mVectorLayer );
+
int widgetIndex = 0;
QgsAttributes results( mFields.count() );
for ( int fieldIdx = 0; fieldIdx < mFields.count(); ++fieldIdx )
@@ -529,7 +534,9 @@ QgsAttributes QgsMergeAttributesDialog::mergedAttributes() const
if ( mHiddenAttributes.contains( fieldIdx ) )
{
//hidden attribute, set to default value
- if ( mVectorLayer->dataProvider() )
+ if ( !mVectorLayer->defaultValueExpression( fieldIdx ).isEmpty() )
+ results[fieldIdx] = mVectorLayer->defaultValue( fieldIdx, mFeatureList.at( 0 ), &context );
+ else if ( mVectorLayer->dataProvider() )
results[fieldIdx] = mVectorLayer->dataProvider()->defaultValue( fieldIdx );
else
results[fieldIdx] = QVariant();
@@ -551,6 +558,10 @@ QgsAttributes QgsMergeAttributesDialog::mergedAttributes() const
{
results[fieldIdx] = currentItem->data( Qt::DisplayRole );
}
+ else if ( !mVectorLayer->defaultValueExpression( fieldIdx ).isEmpty() )
+ {
+ results[fieldIdx] = mVectorLayer->defaultValue( fieldIdx, mFeatureList.at( 0 ), &context );
+ }
else if ( mVectorLayer->dataProvider() )
{
results[fieldIdx] = mVectorLayer->dataProvider()->defaultValue( fieldIdx );
diff --git a/src/app/qgsprojectproperties.cpp b/src/app/qgsprojectproperties.cpp
index 451c8e1..70c4bc1 100644
--- a/src/app/qgsprojectproperties.cpp
+++ b/src/app/qgsprojectproperties.cpp
@@ -530,6 +530,9 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
bool addWktGeometry = QgsProject::instance()->readBoolEntry( "WMSAddWktGeometry", "/" );
mAddWktGeometryCheckBox->setChecked( addWktGeometry );
+ bool segmentizeFeatureInfoGeometry = QgsProject::instance()->readBoolEntry( "WMSSegmentizeFeatureInfoGeometry", "/" );
+ mSegmentizeFeatureInfoGeometryCheckBox->setChecked( segmentizeFeatureInfoGeometry );
+
bool useLayerIDs = QgsProject::instance()->readBoolEntry( "WMSUseLayerIDs", "/" );
mWmsUseLayerIDs->setChecked( useLayerIDs );
@@ -1077,6 +1080,7 @@ void QgsProjectProperties::apply()
}
QgsProject::instance()->writeEntry( "WMSAddWktGeometry", "/", mAddWktGeometryCheckBox->isChecked() );
+ QgsProject::instance()->writeEntry( "WMSSegmentizeFeatureInfoGeometry", "/", mSegmentizeFeatureInfoGeometryCheckBox->isChecked() );
QgsProject::instance()->writeEntry( "WMSUseLayerIDs", "/", mWmsUseLayerIDs->isChecked() );
QString maxWidthText = mMaxWidthLineEdit->text();
diff --git a/src/app/qgsrelationmanagerdialog.cpp b/src/app/qgsrelationmanagerdialog.cpp
index a7c78d6..938ea41 100644
--- a/src/app/qgsrelationmanagerdialog.cpp
+++ b/src/app/qgsrelationmanagerdialog.cpp
@@ -46,6 +46,7 @@ void QgsRelationManagerDialog::setLayers( const QList< QgsVectorLayer* >& layers
void QgsRelationManagerDialog::addRelation( const QgsRelation &rel )
{
+ mRelationsTable->setSortingEnabled( false );
int row = mRelationsTable->rowCount();
mRelationsTable->insertRow( row );
@@ -74,6 +75,7 @@ void QgsRelationManagerDialog::addRelation( const QgsRelation &rel )
item = new QTableWidgetItem( rel.id() );
item->setFlags( Qt::ItemIsEditable );
mRelationsTable->setItem( row, 5, item );
+ mRelationsTable->setSortingEnabled( true );
}
void QgsRelationManagerDialog::on_mBtnAddRelation_clicked()
diff --git a/src/app/qgsstatusbarcoordinateswidget.cpp b/src/app/qgsstatusbarcoordinateswidget.cpp
index 9ed6302..69f2c4c 100644
--- a/src/app/qgsstatusbarcoordinateswidget.cpp
+++ b/src/app/qgsstatusbarcoordinateswidget.cpp
@@ -193,7 +193,7 @@ void QgsStatusBarCoordinatesWidget::extentsViewToggled( bool theFlag )
if ( theFlag )
{
//extents view mode!
- mToggleExtentsViewButton->setIcon( QgsApplication::getThemeIcon( "extents.png" ) );
+ mToggleExtentsViewButton->setIcon( QgsApplication::getThemeIcon( "extents.svg" ) );
mLineEdit->setToolTip( tr( "Map coordinates for the current view extents" ) );
mLineEdit->setReadOnly( true );
showExtent();
@@ -201,7 +201,7 @@ void QgsStatusBarCoordinatesWidget::extentsViewToggled( bool theFlag )
else
{
//mouse cursor pos view mode!
- mToggleExtentsViewButton->setIcon( QgsApplication::getThemeIcon( "tracking.png" ) );
+ mToggleExtentsViewButton->setIcon( QgsApplication::getThemeIcon( "tracking.svg" ) );
mLineEdit->setToolTip( tr( "Map coordinates at mouse cursor position" ) );
mLineEdit->setReadOnly( false );
mLabel->setText( tr( "Coordinate:" ) );
diff --git a/src/app/qgssubstitutionlistwidget.cpp b/src/app/qgssubstitutionlistwidget.cpp
new file mode 100644
index 0000000..7fbe0dc
--- /dev/null
+++ b/src/app/qgssubstitutionlistwidget.cpp
@@ -0,0 +1,230 @@
+/***************************************************************************
+ qgssubstitutionlistwidget.cpp
+ -----------------------------
+ begin : August 2016
+ copyright : (C) 2016 Nyall Dawson
+ email : nyall dot dawson at gmail dot com
+
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "qgssubstitutionlistwidget.h"
+#include <QDialogButtonBox>
+#include <QCheckBox>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QTextStream>
+
+QgsSubstitutionListWidget::QgsSubstitutionListWidget( QWidget* parent )
+ : QgsPanelWidget( parent )
+{
+ setupUi( this );
+ connect( mTableSubstitutions, SIGNAL( cellChanged( int, int ) ), this, SLOT( tableChanged() ) );
+}
+
+void QgsSubstitutionListWidget::setSubstitutions( const QgsStringReplacementCollection& substitutions )
+{
+ mTableSubstitutions->blockSignals( true );
+ mTableSubstitutions->clearContents();
+ Q_FOREACH ( const QgsStringReplacement& replacement, substitutions.replacements() )
+ {
+ addSubstitution( replacement );
+ }
+ mTableSubstitutions->blockSignals( false );
+}
+
+QgsStringReplacementCollection QgsSubstitutionListWidget::substitutions() const
+{
+ QList< QgsStringReplacement > result;
+ for ( int i = 0; i < mTableSubstitutions->rowCount(); ++i )
+ {
+ if ( !mTableSubstitutions->item( i, 0 ) )
+ continue;
+
+ if ( mTableSubstitutions->item( i, 0 )->text().isEmpty() )
+ continue;
+
+ QCheckBox* chkCaseSensitive = qobject_cast<QCheckBox*>( mTableSubstitutions->cellWidget( i, 2 ) );
+ QCheckBox* chkWholeWord = qobject_cast<QCheckBox*>( mTableSubstitutions->cellWidget( i, 3 ) );
+
+ QgsStringReplacement replacement( mTableSubstitutions->item( i, 0 )->text(),
+ mTableSubstitutions->item( i, 1 )->text(),
+ chkCaseSensitive->isChecked(),
+ chkWholeWord->isChecked() );
+ result << replacement;
+ }
+ return QgsStringReplacementCollection( result );
+}
+
+void QgsSubstitutionListWidget::on_mButtonAdd_clicked()
+{
+ addSubstitution( QgsStringReplacement( QString(), QString(), false, true ) );
+ mTableSubstitutions->setFocus();
+ mTableSubstitutions->setCurrentCell( mTableSubstitutions->rowCount() - 1, 0 );
+}
+
+void QgsSubstitutionListWidget::on_mButtonRemove_clicked()
+{
+ int currentRow = mTableSubstitutions->currentRow();
+ mTableSubstitutions->removeRow( currentRow );
+ tableChanged();
+}
+
+void QgsSubstitutionListWidget::tableChanged()
+{
+ emit substitutionsChanged( substitutions() );
+}
+
+void QgsSubstitutionListWidget::on_mButtonExport_clicked()
+{
+ QString fileName = QFileDialog::getSaveFileName( this, tr( "Save substitutions" ), QDir::homePath(),
+ tr( "XML files (*.xml *.XML)" ) );
+ if ( fileName.isEmpty() )
+ {
+ return;
+ }
+
+ // ensure the user never ommited the extension from the file name
+ if ( !fileName.endsWith( ".xml", Qt::CaseInsensitive ) )
+ {
+ fileName += ".xml";
+ }
+
+ QDomDocument doc;
+ QDomElement root = doc.createElement( "substitutions" );
+ root.setAttribute( "version", "1.0" );
+ QgsStringReplacementCollection collection = substitutions();
+ collection.writeXml( root, doc );
+ doc.appendChild( root );
+
+ QFile file( fileName );
+ if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
+ {
+ QMessageBox::warning( nullptr, tr( "Export substitutions" ),
+ tr( "Cannot write file %1:\n%2." ).arg( fileName, file.errorString() ),
+ QMessageBox::Ok,
+ QMessageBox::Ok );
+ return;
+ }
+
+ QTextStream out( &file );
+ doc.save( out, 4 );
+}
+
+void QgsSubstitutionListWidget::on_mButtonImport_clicked()
+{
+ QString fileName = QFileDialog::getOpenFileName( this, tr( "Load substitutions" ), QDir::homePath(),
+ tr( "XML files (*.xml *.XML)" ) );
+ if ( fileName.isEmpty() )
+ {
+ return;
+ }
+
+ QFile file( fileName );
+ if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
+ {
+ QMessageBox::warning( nullptr, tr( "Import substitutions" ),
+ tr( "Cannot read file %1:\n%2." ).arg( fileName, file.errorString() ),
+ QMessageBox::Ok,
+ QMessageBox::Ok );
+ return;
+ }
+
+ QDomDocument doc;
+ QString errorStr;
+ int errorLine;
+ int errorColumn;
+
+ if ( !doc.setContent( &file, true, &errorStr, &errorLine, &errorColumn ) )
+ {
+ QMessageBox::warning( nullptr, tr( "Import substitutions" ),
+ tr( "Parse error at line %1, column %2:\n%3" )
+ .arg( errorLine )
+ .arg( errorColumn )
+ .arg( errorStr ),
+ QMessageBox::Ok,
+ QMessageBox::Ok );
+ return;
+ }
+
+ QDomElement root = doc.documentElement();
+ if ( root.tagName() != "substitutions" )
+ {
+ QMessageBox::warning( nullptr, tr( "Import substitutions" ),
+ tr( "The selected file is not a substitution list." ),
+ QMessageBox::Ok,
+ QMessageBox::Ok );
+ return;
+ }
+
+ QgsStringReplacementCollection collection;
+ collection.readXml( root );
+ setSubstitutions( collection );
+ tableChanged();
+}
+
+void QgsSubstitutionListWidget::addSubstitution( const QgsStringReplacement& substitution )
+{
+ int row = mTableSubstitutions->rowCount();
+ mTableSubstitutions->insertRow( row );
+
+ Qt::ItemFlags itemFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable
+ | Qt::ItemIsEditable;
+
+ QTableWidgetItem* matchItem = new QTableWidgetItem( substitution.match() );
+ matchItem->setFlags( itemFlags );
+ mTableSubstitutions->setItem( row, 0, matchItem );
+ QTableWidgetItem* replaceItem = new QTableWidgetItem( substitution.replacement() );
+ replaceItem->setFlags( itemFlags );
+ mTableSubstitutions->setItem( row, 1, replaceItem );
+
+ QCheckBox* caseSensitiveChk = new QCheckBox( this );
+ caseSensitiveChk->setChecked( substitution.caseSensitive() );
+ mTableSubstitutions->setCellWidget( row, 2, caseSensitiveChk );
+ connect( caseSensitiveChk, SIGNAL( toggled( bool ) ), this, SLOT( tableChanged() ) );
+
+ QCheckBox* wholeWordChk = new QCheckBox( this );
+ wholeWordChk->setChecked( substitution.wholeWordOnly() );
+ mTableSubstitutions->setCellWidget( row, 3, wholeWordChk );
+ connect( wholeWordChk, SIGNAL( toggled( bool ) ), this, SLOT( tableChanged() ) );
+}
+
+
+//
+// QgsSubstitutionListDialog
+//
+
+
+QgsSubstitutionListDialog::QgsSubstitutionListDialog( QWidget* parent )
+ : QDialog( parent )
+ , mWidget( nullptr )
+{
+ setWindowTitle( tr( "Substitutions" ) );
+ QVBoxLayout* vLayout = new QVBoxLayout();
+ mWidget = new QgsSubstitutionListWidget();
+ vLayout->addWidget( mWidget );
+ QDialogButtonBox* bbox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal );
+ connect( bbox, SIGNAL( accepted() ), this, SLOT( accept() ) );
+ connect( bbox, SIGNAL( rejected() ), this, SLOT( reject() ) );
+ vLayout->addWidget( bbox );
+ setLayout( vLayout );
+}
+
+void QgsSubstitutionListDialog::setSubstitutions( const QgsStringReplacementCollection& substitutions )
+{
+ mWidget->setSubstitutions( substitutions );
+}
+
+QgsStringReplacementCollection QgsSubstitutionListDialog::substitutions() const
+{
+ return mWidget->substitutions();
+}
diff --git a/src/app/qgssubstitutionlistwidget.h b/src/app/qgssubstitutionlistwidget.h
new file mode 100644
index 0000000..e8b20cb
--- /dev/null
+++ b/src/app/qgssubstitutionlistwidget.h
@@ -0,0 +1,111 @@
+/***************************************************************************
+ qgssubstitutionlistwidget.h
+ ---------------------------
+ begin : August 2016
+ copyright : (C) 2016 Nyall Dawson
+ email : nyall dot dawson at gmail dot com
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef QGSSUBSTITUTIONLISTWIDGET_H
+#define QGSSUBSTITUTIONLISTWIDGET_H
+
+#include <QDialog>
+#include "qgspanelwidget.h"
+#include "ui_qgssubstitutionlistwidgetbase.h"
+#include "qgsstringutils.h"
+
+/** \class QgsSubstitutionListWidget
+ * \ingroup app
+ * A widget which allows users to specify a list of substitutions to apply to a string, with
+ * options for exporting and importing substitution lists.
+ * \note added in QGIS 2.18
+ * \see QgsSubstitutionListDialog
+ */
+class APP_EXPORT QgsSubstitutionListWidget : public QgsPanelWidget, private Ui::QgsSubstitutionListWidgetBase
+{
+ Q_OBJECT
+ Q_PROPERTY( QgsStringReplacementCollection substitutions READ substitutions WRITE setSubstitutions NOTIFY substitutionsChanged )
+
+ public:
+
+ /** Constructor for QgsSubstitutionListWidget.
+ * @param parent parent widget
+ */
+ QgsSubstitutionListWidget( QWidget* parent = nullptr );
+
+ /** Sets the list of substitutions to show in the widget.
+ * @param substitutions substitution list
+ * @see substitutions()
+ */
+ void setSubstitutions( const QgsStringReplacementCollection& substitutions );
+
+ /** Returns the list of substitutions currently defined by the widget.
+ * @see setSubstitutions()
+ */
+ QgsStringReplacementCollection substitutions() const;
+
+ signals:
+
+ //! Emitted when the substitution definitions change.
+ void substitutionsChanged( const QgsStringReplacementCollection& substitutions );
+
+ private slots:
+
+ void on_mButtonAdd_clicked();
+ void on_mButtonRemove_clicked();
+ void tableChanged();
+ void on_mButtonExport_clicked();
+ void on_mButtonImport_clicked();
+
+ private:
+
+ void addSubstitution( const QgsStringReplacement& substitution );
+
+};
+
+/** \class QgsSubstitutionListDialog
+ * \ingroup app
+ * A dialog which allows users to specify a list of substitutions to apply to a string, with
+ * options for exporting and importing substitution lists.
+ * \see QgsSubstitutionListWidget
+*/
+class APP_EXPORT QgsSubstitutionListDialog : public QDialog
+{
+ Q_OBJECT
+ Q_PROPERTY( QgsStringReplacementCollection substitutions READ substitutions WRITE setSubstitutions )
+
+ public:
+
+ /** Constructor for QgsSubstitutionListDialog.
+ * @param parent parent widget
+ */
+ QgsSubstitutionListDialog( QWidget* parent = nullptr );
+
+ /** Sets the list of substitutions to show in the dialog.
+ * @param substitutions substitution list
+ * @see substitutions()
+ */
+ void setSubstitutions( const QgsStringReplacementCollection& substitutions );
+
+ /** Returns the list of substitutions currently defined by the dialog.
+ * @see setSubstitutions()
+ */
+ QgsStringReplacementCollection substitutions() const;
+
+
+ private:
+
+ QgsSubstitutionListWidget* mWidget;
+
+};
+
+#endif // QGSSUBSTITUTIONLISTWIDGET_H
diff --git a/src/app/qgssvgannotationdialog.cpp b/src/app/qgssvgannotationdialog.cpp
index 453421f..e74fd3f 100644
--- a/src/app/qgssvgannotationdialog.cpp
+++ b/src/app/qgssvgannotationdialog.cpp
@@ -89,3 +89,11 @@ void QgsSvgAnnotationDialog::deleteItem()
delete mItem;
mItem = nullptr;
}
+
+void QgsSvgAnnotationDialog::on_mButtonBox_clicked( QAbstractButton* button )
+{
+ if ( mButtonBox->buttonRole( button ) == QDialogButtonBox::ApplyRole )
+ {
+ applySettingsToItem();
+ }
+}
diff --git a/src/app/qgssvgannotationdialog.h b/src/app/qgssvgannotationdialog.h
index f11136a..7a672a5 100644
--- a/src/app/qgssvgannotationdialog.h
+++ b/src/app/qgssvgannotationdialog.h
@@ -34,6 +34,7 @@ class APP_EXPORT QgsSvgAnnotationDialog: public QDialog, private Ui::QgsFormAnno
void on_mBrowseToolButton_clicked();
void applySettingsToItem();
void deleteItem();
+ void on_mButtonBox_clicked( QAbstractButton* button );
private:
QgsSvgAnnotationDialog(); //forbidden
diff --git a/src/app/qgstextannotationdialog.cpp b/src/app/qgstextannotationdialog.cpp
index ef32a60..06d9edf 100644
--- a/src/app/qgstextannotationdialog.cpp
+++ b/src/app/qgstextannotationdialog.cpp
@@ -58,6 +58,15 @@ QgsTextAnnotationDialog::~QgsTextAnnotationDialog()
delete mTextDocument;
}
+void QgsTextAnnotationDialog::on_mButtonBox_clicked( QAbstractButton *button )
+{
+ if ( mButtonBox->buttonRole( button ) == QDialogButtonBox::ApplyRole )
+ {
+ applyTextToItem();
+ mEmbeddedWidget->apply();
+ }
+}
+
void QgsTextAnnotationDialog::showEvent( QShowEvent* )
{
backgroundColorChanged( mItem ? mItem->frameBackgroundColor() : Qt::white );
diff --git a/src/app/qgstextannotationdialog.h b/src/app/qgstextannotationdialog.h
index 3634f42..3896791 100644
--- a/src/app/qgstextannotationdialog.h
+++ b/src/app/qgstextannotationdialog.h
@@ -49,6 +49,7 @@ class APP_EXPORT QgsTextAnnotationDialog: public QDialog, private Ui::QgsTextAnn
void setCurrentFontPropertiesToGui();
void deleteItem();
void backgroundColorChanged( const QColor& color );
+ void on_mButtonBox_clicked( QAbstractButton* button );
};
#endif // QGSTEXTANNOTATIONDIALOG_H
diff --git a/src/app/qgsvectorlayerproperties.cpp b/src/app/qgsvectorlayerproperties.cpp
index d4c7082..fb5a5e6 100644
--- a/src/app/qgsvectorlayerproperties.cpp
+++ b/src/app/qgsvectorlayerproperties.cpp
@@ -245,7 +245,7 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
QVBoxLayout* diagLayout = new QVBoxLayout( mDiagramFrame );
diagLayout->setMargin( 0 );
- diagramPropertiesDialog = new QgsDiagramProperties( mLayer, mDiagramFrame, nullptr );
+ diagramPropertiesDialog = new QgsDiagramProperties( mLayer, mDiagramFrame, QgisApp::instance()->mapCanvas() );
diagramPropertiesDialog->layout()->setContentsMargins( -1, 0, -1, 0 );
diagLayout->addWidget( diagramPropertiesDialog );
mDiagramFrame->setLayout( diagLayout );
@@ -562,8 +562,8 @@ void QgsVectorLayerProperties::apply()
// set up the scale based layer visibility stuff....
mLayer->setScaleBasedVisibility( mScaleVisibilityGroupBox->isChecked() );
// caution: layer uses scale denoms, widget uses true scales
- mLayer->setMaximumScale( 1.0 / mScaleRangeWidget->minimumScale() );
- mLayer->setMinimumScale( 1.0 / mScaleRangeWidget->maximumScale() );
+ mLayer->setMaximumScale( mScaleRangeWidget->maximumScaleDenom() );
+ mLayer->setMinimumScale( mScaleRangeWidget->minimumScaleDenom() );
// provider-specific options
if ( mLayer->dataProvider() )
diff --git a/src/app/qgsvisibilitypresets.cpp b/src/app/qgsvisibilitypresets.cpp
index 1c72a7f..76451ea 100644
--- a/src/app/qgsvisibilitypresets.cpp
+++ b/src/app/qgsvisibilitypresets.cpp
@@ -68,7 +68,7 @@ void QgsVisibilityPresets::addPerLayerCheckedLegendSymbols( QgsVisibilityPresetC
bool hasCheckableItems = false;
bool someItemsUnchecked = false;
QSet<QString> checkedItems;
- Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, model->layerLegendNodes( nodeLayer ) )
+ Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, model->layerLegendNodes( nodeLayer, true ) )
{
if ( legendNode->flags() & Qt::ItemIsUserCheckable )
{
@@ -210,7 +210,7 @@ void QgsVisibilityPresets::applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent
{
const QSet<QString>& checkedNodes = rec.mPerLayerCheckedLegendSymbols[nodeLayer->layerId()];
// some nodes are not checked
- Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, model->layerLegendNodes( nodeLayer ) )
+ Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, model->layerLegendNodes( nodeLayer, true ) )
{
Qt::CheckState shouldHaveState = checkedNodes.contains( legendNode->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString() ) ? Qt::Checked : Qt::Unchecked;
if (( legendNode->flags() & Qt::ItemIsUserCheckable ) &&
@@ -221,7 +221,7 @@ void QgsVisibilityPresets::applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent
else
{
// all nodes should be checked
- Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, model->layerLegendNodes( nodeLayer ) )
+ Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, model->layerLegendNodes( nodeLayer, true ) )
{
if (( legendNode->flags() & Qt::ItemIsUserCheckable ) &&
legendNode->data( Qt::CheckStateRole ).toInt() != Qt::Checked )
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 834b1dd..754ef22 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -81,6 +81,7 @@ SET(QGIS_CORE_SRCS
qgsactionmanager.cpp
qgsaggregatecalculator.cpp
qgsattributetableconfig.cpp
+ qgsbearingutils.cpp
qgsbrowsermodel.cpp
qgscachedfeatureiterator.cpp
qgscacheindex.cpp
@@ -163,6 +164,7 @@ SET(QGIS_CORE_SRCS
qgsofflineediting.cpp
qgsogcutils.cpp
qgsogrutils.cpp
+ qgsoptionalexpression.cpp
qgsowsconnection.cpp
qgspaintenginehack.cpp
qgspallabeling.cpp
@@ -460,6 +462,8 @@ SET(QGIS_CORE_MOC_HDRS
qgsdataprovider.h
qgsdbfilterproxymodel.h
qgseditformconfig.h
+ qgsfeedback.h
+ qgsfield.h
qgsgeometryvalidator.h
qgsgml.h
qgsgmlschema.h
@@ -610,6 +614,7 @@ SET(QGIS_CORE_HDRS
qgsannotation.h
qgsattributetableconfig.h
qgsattributeaction.h
+ qgsbearingutils.h
qgscachedfeatureiterator.h
qgscacheindex.h
qgscacheindexfeatureid.h
@@ -648,7 +653,6 @@ SET(QGIS_CORE_HDRS
qgsfeatureiterator.h
qgsfeaturerequest.h
qgsfeaturestore.h
- qgsfield.h
qgsfield_p.h
qgsfontutils.h
qgsgeometrycache.h
@@ -677,6 +681,8 @@ SET(QGIS_CORE_HDRS
qgsmultirenderchecker.h
qgsobjectcustomproperties.h
qgsogcutils.h
+ qgsoptional.h
+ qgsoptionalexpression.h
qgsowsconnection.h
qgspaintenginehack.h
qgspallabeling.h
diff --git a/src/core/composer/qgscomposerattributetable.h b/src/core/composer/qgscomposerattributetable.h
index eaee3a5..d1f3ff5 100644
--- a/src/core/composer/qgscomposerattributetable.h
+++ b/src/core/composer/qgscomposerattributetable.h
@@ -187,7 +187,7 @@ class CORE_EXPORT QgsComposerAttributeTable: public QgsComposerTable
void setFeatureFilter( const QString& expression );
/** Returns the attributes fields which are shown by the table.
- * @returns a QSet of integers refering to the attributes in the vector layer. If
+ * @returns a QSet of integers referring to the attributes in the vector layer. If
* result is an empty QSet than all feature attributes will be shown.
* @see setDisplayAttributes
* @deprecated use QgsComposerTable::columns() instead
@@ -195,7 +195,7 @@ class CORE_EXPORT QgsComposerAttributeTable: public QgsComposerTable
Q_DECL_DEPRECATED QSet<int> displayAttributes() const;
/** Sets the attributes to display in the table.
- * @param attr QSet of integer values refering to the attributes from the vector layer to show.
+ * @param attr QSet of integer values referring to the attributes from the vector layer to show.
* Set to an empty QSet to show all feature attributes.
* @param refresh set to true to force the table to refetch features from its vector layer
* and immediately update the display of the table. This may result in the table changing size
diff --git a/src/core/composer/qgscomposerattributetablev2.h b/src/core/composer/qgscomposerattributetablev2.h
index ce40a5e..809848e 100644
--- a/src/core/composer/qgscomposerattributetablev2.h
+++ b/src/core/composer/qgscomposerattributetablev2.h
@@ -257,7 +257,7 @@ class CORE_EXPORT QgsComposerAttributeTableV2: public QgsComposerTableV2
void setFeatureFilter( const QString& expression );
/** Sets the attributes to display in the table.
- * @param attr QSet of integer values refering to the attributes from the vector layer to show.
+ * @param attr QSet of integer values referring to the attributes from the vector layer to show.
* Set to an empty QSet to show all feature attributes.
* @param refresh set to true to force the table to refetch features from its vector layer
* and immediately update the display of the table. This may result in the table changing size
diff --git a/src/core/composer/qgscomposeritem.cpp b/src/core/composer/qgscomposeritem.cpp
index e491511..8807883 100644
--- a/src/core/composer/qgscomposeritem.cpp
+++ b/src/core/composer/qgscomposeritem.cpp
@@ -524,7 +524,13 @@ void QgsComposerItem::drawSelectionBoxes( QPainter* p )
selectedItemPen.setWidth( 0 );
p->setPen( selectedItemPen );
p->setBrush( Qt::NoBrush );
- p->drawPolygon( rect() );
+
+ // drawPolygon causes issues on windows - corners of path may be missing resulting in triangles being drawn
+ // instead of rectangles! (Same cause as #13343)
+ QPainterPath path;
+ path.addPolygon( rect() );
+ p->drawPath( path );
+
p->restore();
}
diff --git a/src/core/composer/qgscomposeritemcommand.h b/src/core/composer/qgscomposeritemcommand.h
index 0a5a094..7f189c5 100644
--- a/src/core/composer/qgscomposeritemcommand.h
+++ b/src/core/composer/qgscomposeritemcommand.h
@@ -109,6 +109,7 @@ class CORE_EXPORT QgsComposerMergeCommand: public QgsComposerItemCommand
LegendRasterBorderWidth,
//composer picture
ComposerPictureRotation,
+ ComposerPictureNorthOffset,
// composer scalebar
ScaleBarLineWidth,
ScaleBarHeight,
diff --git a/src/core/composer/qgscomposerlegend.h b/src/core/composer/qgscomposerlegend.h
index c52bffe..a34c0db 100644
--- a/src/core/composer/qgscomposerlegend.h
+++ b/src/core/composer/qgscomposerlegend.h
@@ -79,13 +79,13 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
* @param enabled set to false to disable automatic resizing. The legend frame will not
* be expanded to fit legend items, and items may be cropped from display.
* @see resizeToContents()
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
void setResizeToContents( bool enabled );
/** Returns whether the legend should automatically resize to fit its contents.
* @see setResizeToContents()
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
bool resizeToContents() const;
diff --git a/src/core/composer/qgscomposermodel.cpp b/src/core/composer/qgscomposermodel.cpp
index 8dc113a..9d051ed 100644
--- a/src/core/composer/qgscomposermodel.cpp
+++ b/src/core/composer/qgscomposermodel.cpp
@@ -233,7 +233,7 @@ QVariant QgsComposerModel::headerData( int section, Qt::Orientation orientation,
lockIcon = QgsApplication::getThemeIcon( "/locked.svg" );
static QIcon showIcon;
if ( showIcon.isNull() )
- showIcon = QgsApplication::getThemeIcon( "/mActionShowAllLayers.png" );
+ showIcon = QgsApplication::getThemeIcon( "/mActionShowAllLayers.svg" );
switch ( role )
{
diff --git a/src/core/composer/qgscomposermousehandles.cpp b/src/core/composer/qgscomposermousehandles.cpp
index 7d571bc..9f81b44 100644
--- a/src/core/composer/qgscomposermousehandles.cpp
+++ b/src/core/composer/qgscomposermousehandles.cpp
@@ -194,7 +194,12 @@ void QgsComposerMouseHandles::drawSelectedItemBounds( QPainter* painter )
//not resizing or moving, so just map from scene bounds
itemBounds = mapRectFromItem(( *itemIter ), ( *itemIter )->rectWithFrame() );
}
- painter->drawPolygon( itemBounds );
+
+ // drawPolygon causes issues on windows - corners of path may be missing resulting in triangles being drawn
+ // instead of rectangles! (Same cause as #13343)
+ QPainterPath path;
+ path.addPolygon( itemBounds );
+ painter->drawPath( path );
}
painter->restore();
}
diff --git a/src/core/composer/qgscomposerpicture.cpp b/src/core/composer/qgscomposerpicture.cpp
index 3745ac8..f929c71 100644
--- a/src/core/composer/qgscomposerpicture.cpp
+++ b/src/core/composer/qgscomposerpicture.cpp
@@ -28,6 +28,10 @@
#include "qgsnetworkcontentfetcher.h"
#include "qgssymbollayerv2utils.h"
#include "qgssvgcache.h"
+#include "qgslogger.h"
+#include "qgsbearingutils.h"
+#include "qgsmapsettings.h"
+
#include <QDomDocument>
#include <QDomElement>
#include <QFileInfo>
@@ -44,6 +48,8 @@ QgsComposerPicture::QgsComposerPicture( QgsComposition *composition )
, mMode( Unknown )
, mPictureRotation( 0 )
, mRotationMap( nullptr )
+ , mNorthMode( GridNorth )
+ , mNorthOffset( 0.0 )
, mResizeMode( QgsComposerPicture::Zoom )
, mPictureAnchor( UpperLeft )
, mSvgFillColor( QColor( 255, 255, 255 ) )
@@ -61,6 +67,8 @@ QgsComposerPicture::QgsComposerPicture()
, mMode( Unknown )
, mPictureRotation( 0 )
, mRotationMap( nullptr )
+ , mNorthMode( GridNorth )
+ , mNorthOffset( 0.0 )
, mResizeMode( QgsComposerPicture::Zoom )
, mPictureAnchor( UpperLeft )
, mSvgFillColor( QColor( 255, 255, 255 ) )
@@ -419,6 +427,43 @@ void QgsComposerPicture::remotePictureLoaded()
mLoaded = true;
}
+void QgsComposerPicture::updateMapRotation()
+{
+ if ( !mRotationMap )
+ return;
+
+ // take map rotation
+ double rotation = mRotationMap->mapRotation();
+
+ // handle true north
+ switch ( mNorthMode )
+ {
+ case GridNorth:
+ break; // nothing to do
+
+ case TrueNorth:
+ {
+ QgsPoint center = mRotationMap->currentMapExtent()->center();
+ QgsCoordinateReferenceSystem crs = mComposition->mapSettings().destinationCrs();
+
+ try
+ {
+ double bearing = QgsBearingUtils::bearingTrueNorth( crs, center );
+ rotation += bearing;
+ }
+ catch ( QgsException& e )
+ {
+ Q_UNUSED( e );
+ QgsDebugMsg( QString( "Caught exception %1" ).arg( e.what() ) );
+ }
+ break;
+ }
+ }
+
+ rotation += mNorthOffset;
+ setPictureRotation( rotation );
+}
+
void QgsComposerPicture::loadPicture( const QString &path )
{
if ( path.startsWith( "http" ) )
@@ -650,7 +695,8 @@ void QgsComposerPicture::setRotationMap( int composerMapId )
if ( composerMapId == -1 ) //disable rotation from map
{
- QObject::disconnect( mRotationMap, SIGNAL( mapRotationChanged( double ) ), this, SLOT( setPictureRotation( double ) ) );
+ disconnect( mRotationMap, SIGNAL( mapRotationChanged( double ) ), this, SLOT( updateMapRotation() ) );
+ disconnect( mRotationMap, SIGNAL( extentChanged() ), this, SLOT( updateMapRotation() ) );
mRotationMap = nullptr;
}
@@ -661,12 +707,14 @@ void QgsComposerPicture::setRotationMap( int composerMapId )
}
if ( mRotationMap )
{
- QObject::disconnect( mRotationMap, SIGNAL( mapRotationChanged( double ) ), this, SLOT( setPictureRotation( double ) ) );
+ disconnect( mRotationMap, SIGNAL( mapRotationChanged( double ) ), this, SLOT( updateMapRotation() ) );
+ disconnect( mRotationMap, SIGNAL( extentChanged() ), this, SLOT( updateMapRotation() ) );
}
mPictureRotation = map->mapRotation();
- QObject::connect( map, SIGNAL( mapRotationChanged( double ) ), this, SLOT( setPictureRotation( double ) ) );
+ connect( map, SIGNAL( mapRotationChanged( double ) ), this, SLOT( updateMapRotation() ) );
+ connect( map, SIGNAL( extentChanged() ), this, SLOT( updateMapRotation() ) );
mRotationMap = map;
- update();
+ updateMapRotation();
emit pictureRotationChanged( mPictureRotation );
}
@@ -761,6 +809,8 @@ bool QgsComposerPicture::writeXML( QDomElement& elem, QDomDocument & doc ) const
{
composerPictureElem.setAttribute( "mapId", mRotationMap->id() );
}
+ composerPictureElem.setAttribute( "northMode", mNorthMode );
+ composerPictureElem.setAttribute( "northOffset", mNorthOffset );
_writeXML( composerPictureElem, doc );
elem.appendChild( composerPictureElem );
@@ -827,6 +877,9 @@ bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocumen
}
//rotation map
+ mNorthMode = static_cast< NorthMode >( itemElem.attribute( "northMode", "0" ).toInt() );
+ mNorthOffset = itemElem.attribute( "northOffset", "0" ).toDouble();
+
int rotationMapId = itemElem.attribute( "mapId", "-1" ).toInt();
if ( rotationMapId == -1 )
{
@@ -837,10 +890,12 @@ bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocumen
if ( mRotationMap )
{
- QObject::disconnect( mRotationMap, SIGNAL( mapRotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
+ disconnect( mRotationMap, SIGNAL( mapRotationChanged( double ) ), this, SLOT( updateMapRotation() ) );
+ disconnect( mRotationMap, SIGNAL( extentChanged() ), this, SLOT( updateMapRotation() ) );
}
mRotationMap = mComposition->getComposerMapById( rotationMapId );
- QObject::connect( mRotationMap, SIGNAL( mapRotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
+ connect( mRotationMap, SIGNAL( mapRotationChanged( double ) ), this, SLOT( updateMapRotation() ) );
+ connect( mRotationMap, SIGNAL( extentChanged() ), this, SLOT( updateMapRotation() ) );
}
refreshPicture();
@@ -861,6 +916,18 @@ int QgsComposerPicture::rotationMap() const
}
}
+void QgsComposerPicture::setNorthMode( QgsComposerPicture::NorthMode mode )
+{
+ mNorthMode = mode;
+ updateMapRotation();
+}
+
+void QgsComposerPicture::setNorthOffset( double offset )
+{
+ mNorthOffset = offset;
+ updateMapRotation();
+}
+
void QgsComposerPicture::setPictureAnchor( QgsComposerItem::ItemPositionMode anchor )
{
mPictureAnchor = anchor;
diff --git a/src/core/composer/qgscomposerpicture.h b/src/core/composer/qgscomposerpicture.h
index deb25a9..bbec0f0 100644
--- a/src/core/composer/qgscomposerpicture.h
+++ b/src/core/composer/qgscomposerpicture.h
@@ -53,6 +53,13 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
Unknown
};
+ //! Method for syncing rotation to a map's North direction
+ enum NorthMode
+ {
+ GridNorth = 0, /*!< Align to grid north */
+ TrueNorth, /*!< Align to true north */
+ };
+
QgsComposerPicture( QgsComposition *composition );
~QgsComposerPicture();
@@ -155,6 +162,38 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
*/
bool useRotationMap() const { return mRotationMap; }
+ /**
+ * Returns the mode used to align the picture to a map's North.
+ * @see setNorthMode()
+ * @see northOffset()
+ * @note added in QGIS 2.18
+ */
+ NorthMode northMode() const { return mNorthMode; }
+
+ /**
+ * Sets the mode used to align the picture to a map's North.
+ * @see northMode()
+ * @see setNorthOffset()
+ * @note added in QGIS 2.18
+ */
+ void setNorthMode( NorthMode mode );
+
+ /**
+ * Returns the offset added to the picture's rotation from a map's North.
+ * @see setNorthOffset()
+ * @see northMode()
+ * @note added in QGIS 2.18
+ */
+ double northOffset() const { return mNorthOffset; }
+
+ /**
+ * Sets the offset added to the picture's rotation from a map's North.
+ * @see northOffset()
+ * @see setNorthMode()
+ * @note added in QGIS 2.18
+ */
+ void setNorthOffset( double offset );
+
/** Returns the resize mode used for drawing the picture within the composer
* item's frame.
* @returns resize mode of picture
@@ -366,6 +405,12 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
double mPictureRotation;
/** Map that sets the rotation (or 0 if this picture uses map independent rotation)*/
const QgsComposerMap* mRotationMap;
+
+ //! Mode used to align to North
+ NorthMode mNorthMode;
+ //! Offset for north arrow
+ double mNorthOffset;
+
/** Width of the picture (in mm)*/
double mPictureWidth;
/** Height of the picture (in mm)*/
@@ -404,6 +449,8 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
private slots:
void remotePictureLoaded();
+
+ void updateMapRotation();
};
#endif
diff --git a/src/core/composer/qgscomposition.h b/src/core/composer/qgscomposition.h
index 9b25521..1d9b48f 100644
--- a/src/core/composer/qgscomposition.h
+++ b/src/core/composer/qgscomposition.h
@@ -1147,7 +1147,7 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
void statusMsgChanged( const QString& message );
/** Emitted whenever the expression variables stored in the composition have been changed.
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
void variablesChanged();
diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp
index fcae555..9ef65a1 100644
--- a/src/core/dxf/qgsdxfexport.cpp
+++ b/src/core/dxf/qgsdxfexport.cpp
@@ -38,6 +38,7 @@
#include "qgsmaplayerregistry.h"
#include "qgsunittypes.h"
#include "qgstextlabelfeature.h"
+#include "qgscrscache.h"
#include "qgswkbtypes.h"
#include "qgspointv2.h"
@@ -370,6 +371,7 @@ QgsDxfExport::QgsDxfExport()
, mSymbolLayerCounter( 0 )
, mNextHandleId( DXF_HANDSEED )
, mBlockCounter( 0 )
+ , mCrs( -1 )
{
}
@@ -388,6 +390,7 @@ QgsDxfExport& QgsDxfExport::operator=( const QgsDxfExport & dxfExport )
mSymbolLayerCounter = 0; // internal counter
mNextHandleId = 0;
mBlockCounter = 0;
+ mCrs = -1;
return *this;
}
@@ -501,6 +504,39 @@ int QgsDxfExport::writeToFile( QIODevice* d, const QString& encoding )
mTextStream.setDevice( d );
mTextStream.setCodec( encoding.toLocal8Bit() );
+ if ( mExtent.isEmpty() )
+ {
+ QList< QPair<QgsVectorLayer*, int> >::const_iterator layerIt = mLayers.constBegin();
+ for ( ; layerIt != mLayers.constEnd(); ++layerIt )
+ {
+ if ( layerIt->first )
+ {
+ QgsRectangle layerExtent = layerIt->first->extent();
+ layerExtent = mMapSettings.layerToMapCoordinates( layerIt->first, layerExtent );
+
+ if ( mExtent.isEmpty() )
+ {
+ mExtent = layerExtent;
+ }
+ else
+ {
+ mExtent.combineExtentWith( layerExtent );
+ }
+ }
+ }
+ }
+
+ mMapSettings.setMapUnits( mMapUnits );
+ mMapSettings.setExtent( mExtent );
+
+ int dpi = 96;
+ mFactor = 1000 * dpi / mSymbologyScaleDenominator / 25.4 * QgsUnitTypes::fromUnitToUnitFactor( mMapUnits, QGis::Meters );
+ mMapSettings.setOutputSize( QSize( mExtent.width() * mFactor, mExtent.height() * mFactor ) );
+ mMapSettings.setOutputDpi( dpi );
+ if ( mCrs >= 0 )
+ mMapSettings.setDestinationCrs( QgsCRSCache::instance()->crsBySrsId( mCrs ) );
+ mMapSettings.setCrsTransformEnabled( mCrs >= 0 );
+
writeHeader( dxfEncoding( encoding ) );
writeTables();
writeBlocks();
@@ -521,17 +557,13 @@ void QgsDxfExport::writeHeader( const QString& codepage )
writeGroup( 9, "$ACADVER" );
writeGroup( 1, "AC1015" );
- QgsRectangle ext( mExtent.isEmpty() ? dxfExtent() : mExtent );
- if ( !ext.isEmpty() )
- {
- // EXTMIN
- writeGroup( 9, "$EXTMIN" );
- writeGroup( 0, QgsPointV2( QgsWKBTypes::PointZ, ext.xMinimum(), ext.yMinimum() ) );
+ // EXTMIN
+ writeGroup( 9, "$EXTMIN" );
+ writeGroup( 0, QgsPointV2( QgsWKBTypes::PointZ, mExtent.xMinimum(), mExtent.yMinimum() ) );
- // EXTMAX
- writeGroup( 9, "$EXTMAX" );
- writeGroup( 0, QgsPointV2( QgsWKBTypes::PointZ, ext.xMaximum(), ext.yMaximum() ) );
- }
+ // EXTMAX
+ writeGroup( 9, "$EXTMAX" );
+ writeGroup( 0, QgsPointV2( QgsWKBTypes::PointZ, mExtent.xMaximum(), mExtent.yMaximum() ) );
// Global linetype scale
writeGroup( 9, "$LTSCALE" );
@@ -675,8 +707,6 @@ void QgsDxfExport::writeTables()
writeHandle();
writeGroup( 100, "AcDbSymbolTable" );
- QgsRectangle ext( mExtent.isEmpty() ? dxfExtent() : mExtent );
-
writeGroup( 0, "VPORT" );
writeHandle();
writeGroup( 100, "AcDbSymbolTableRecord" );
@@ -690,9 +720,9 @@ void QgsDxfExport::writeTables()
writeGroup( 4, QgsPointV2( 1.0, 1.0 ) ); // snap spacing
writeGroup( 5, QgsPointV2( 1.0, 1.0 ) ); // grid spacing
writeGroup( 6, QgsPointV2( QgsWKBTypes::PointZ, 0.0, 0.0, 1.0 ) ); // view direction from target point
- writeGroup( 7, QgsPointV2( ext.center() ) ); // view target point
- writeGroup( 40, ext.height() ); // view height
- writeGroup( 41, ext.width() / ext.height() ); // view aspect ratio
+ writeGroup( 7, QgsPointV2( mExtent.center() ) ); // view target point
+ writeGroup( 40, mExtent.height() ); // view height
+ writeGroup( 41, mExtent.width() / mExtent.height() ); // view aspect ratio
writeGroup( 42, 50.0 ); // lens length
writeGroup( 43, 0.0 ); // front clipping plane
writeGroup( 44, 0.0 ); // back clipping plane
@@ -905,35 +935,23 @@ void QgsDxfExport::writeEntities()
mBlockHandle = QString( "%1" ).arg( mBlockHandles[ "*Model_Space" ], 0, 16 );
- QgsRectangle bbox = mExtent.isEmpty() ? dxfExtent() : mExtent;
-
- QgsMapSettings mapSettings;
- mapSettings.setMapUnits( mMapUnits );
- mapSettings.setExtent( bbox );
-
- int dpi = 96;
- double factor = 1000 * dpi / mSymbologyScaleDenominator / 25.4 * QgsUnitTypes::fromUnitToUnitFactor( mMapUnits, QGis::Meters );
- mapSettings.setOutputSize( QSize( bbox.width() * factor, bbox.height() * factor ) );
- mapSettings.setOutputDpi( dpi );
- mapSettings.setCrsTransformEnabled( false );
-
QImage image( 10, 10, QImage::Format_ARGB32_Premultiplied );
image.setDotsPerMeterX( 96 / 25.4 * 1000 );
image.setDotsPerMeterY( 96 / 25.4 * 1000 );
QPainter painter( &image );
+
QgsRenderContext ctx;
ctx.setPainter( &painter );
ctx.setRendererScale( mSymbologyScaleDenominator );
- ctx.setExtent( bbox );
+ ctx.setExtent( mExtent );
+
ctx.setScaleFactor( 96.0 / 25.4 );
- Q_NOWARN_DEPRECATED_PUSH
- ctx.setMapToPixel( QgsMapToPixel( 1.0 / factor, bbox.xMinimum(), bbox.yMinimum(), bbox.height() * factor ) );
- Q_NOWARN_DEPRECATED_POP
+ ctx.setMapToPixel( QgsMapToPixel( 1.0 / mFactor, mExtent.center().x(), mExtent.center().y(), mExtent.width() * mFactor, mExtent.height() * mFactor, 0 ) );
// label engine
QgsLabelingEngineV2 engine;
engine.readSettingsFromProject();
- engine.setMapSettings( mapSettings );
+ engine.setMapSettings( mMapSettings );
// iterate through the maplayers
QList< QPair< QgsVectorLayer*, int > >::const_iterator layerIt = mLayers.constBegin();
@@ -998,12 +1016,12 @@ void QgsDxfExport::writeEntities()
}
QgsFeatureRequest freq = QgsFeatureRequest().setSubsetOfAttributes( attributes, vl->fields() ).setExpressionContext( ctx.expressionContext() );
- if ( !mExtent.isEmpty() )
- {
- freq.setFilterRect( mExtent );
- }
+ freq.setFilterRect( mMapSettings.mapToLayerCoordinates( vl, mExtent ) );
QgsFeatureIterator featureIt = vl->getFeatures( freq );
+
+ const QgsCoordinateTransform *ct = mMapSettings.hasCrsTransformEnabled() ? mMapSettings.layerTransform( vl ) : nullptr;
+
QgsFeature fet;
while ( featureIt.nextFeature( fet ) )
{
@@ -1013,7 +1031,7 @@ void QgsDxfExport::writeEntities()
sctx.setFeature( &fet );
if ( mSymbologyExport == NoSymbology )
{
- addFeature( sctx, lName, nullptr, nullptr ); // no symbology at all
+ addFeature( sctx, ct, lName, nullptr, nullptr ); // no symbology at all
}
else
{
@@ -1031,7 +1049,7 @@ void QgsDxfExport::writeEntities()
int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
for ( int i = 0; i < nSymbolLayers; ++i )
{
- addFeature( sctx, lName, ( *symbolIt )->symbolLayer( i ), *symbolIt );
+ addFeature( sctx, ct, lName, ( *symbolIt )->symbolLayer( i ), *symbolIt );
}
}
}
@@ -1043,7 +1061,7 @@ void QgsDxfExport::writeEntities()
{
continue;
}
- addFeature( sctx, lName, s->symbolLayer( 0 ), s );
+ addFeature( sctx, ct, lName, s->symbolLayer( 0 ), s );
}
if ( lp )
@@ -1081,7 +1099,8 @@ void QgsDxfExport::writeEntitiesSymbolLevels( QgsVectorLayer* layer )
QHash< QgsSymbolV2*, QList<QgsFeature> > features;
QgsRenderContext ctx = renderContext();
- ctx.expressionContext() << QgsExpressionContextUtils::globalScope()
+ ctx.expressionContext()
+ << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope()
<< QgsExpressionContextUtils::layerScope( layer );
QgsSymbolV2RenderContext sctx( ctx, QgsSymbolV2::MM, 1.0, false, 0, nullptr );
@@ -1094,10 +1113,8 @@ void QgsDxfExport::writeEntitiesSymbolLevels( QgsVectorLayer* layer )
req.setFlags( QgsFeatureRequest::NoGeometry );
}
req.setSubsetOfAttributes( QStringList( renderer->usedAttributes() ), layer->fields() );
- if ( !mExtent.isEmpty() )
- {
- req.setFilterRect( mExtent );
- }
+ req.setFilterRect( mMapSettings.mapToLayerCoordinates( layer, mExtent ) );
+
QgsFeatureIterator fit = layer->getFeatures( req );
// fetch features
@@ -1138,6 +1155,8 @@ void QgsDxfExport::writeEntitiesSymbolLevels( QgsVectorLayer* layer )
}
}
+ const QgsCoordinateTransform *ct = mMapSettings.hasCrsTransformEnabled() ? mMapSettings.layerTransform( layer ) : nullptr;
+
// export symbol layers and symbology
for ( int l = 0; l < levels.count(); l++ )
{
@@ -1158,7 +1177,7 @@ void QgsDxfExport::writeEntitiesSymbolLevels( QgsVectorLayer* layer )
for ( ; featureIt != featureList.end(); ++featureIt )
{
sctx.setFeature( &*featureIt );
- addFeature( sctx, layer->name(), levelIt.key()->symbolLayer( llayer ), levelIt.key() );
+ addFeature( sctx, ct, layer->name(), levelIt.key()->symbolLayer( llayer ), levelIt.key() );
}
}
}
@@ -3649,6 +3668,7 @@ void QgsDxfExport::writeMText( const QString& layer, const QString& text, const
if ( !mTextStream.codec()->canEncode( text ) )
{
// TODO return error
+ QgsDebugMsg( QString( "could not encode:%1" ).arg( text ) );
return;
}
@@ -3693,38 +3713,20 @@ void QgsDxfExport::writeSolid( const QString& layer, const QColor& color, const
writePolygon( QgsRingSequenceV2() << p, layer, "SOLID", color );
}
-QgsRectangle QgsDxfExport::dxfExtent() const
-{
- QgsRectangle extent;
- QList< QPair<QgsVectorLayer*, int> >::const_iterator layerIt = mLayers.constBegin();
- for ( ; layerIt != mLayers.constEnd(); ++layerIt )
- {
- if ( layerIt->first )
- {
- if ( extent.isEmpty() )
- {
- extent = layerIt->first->extent();
- }
- else
- {
- QgsRectangle layerExtent = layerIt->first->extent();
- extent.combineExtentWith( layerExtent );
- }
- }
- }
- return extent;
-}
-
-void QgsDxfExport::addFeature( QgsSymbolV2RenderContext& ctx, const QString& layer, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol )
+void QgsDxfExport::addFeature( QgsSymbolV2RenderContext& ctx, const QgsCoordinateTransform *ct, const QString& layer, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol )
{
- const QgsFeature* fet = ctx.feature();
+ const QgsFeature *fet = ctx.feature();
if ( !fet )
return;
if ( !fet->constGeometry() )
return;
- const QgsAbstractGeometryV2 *geom = fet->constGeometry()->geometry();
+ QScopedPointer<QgsAbstractGeometryV2> geom( fet->constGeometry()->geometry()->clone() );
+ if ( ct )
+ {
+ geom->transform( *ct );
+ }
QgsWKBTypes::Type geometryType = geom->wkbType();
@@ -3778,110 +3780,135 @@ void QgsDxfExport::addFeature( QgsSymbolV2RenderContext& ctx, const QString& lay
if ( penStyle != Qt::NoPen )
{
- // single line
- if ( QgsWKBTypes::flatType( geometryType ) == QgsWKBTypes::LineString )
- {
- const QgsAbstractGeometryV2 *offsetGeom = geom;
- if ( !qgsDoubleNear( offset, 0.0 ) )
- {
- QgsGeos geos( geom );
- offsetGeom = geos.offsetCurve( offset, 0, GEOSBUF_JOIN_MITRE, 2.0 );
- if ( !offsetGeom )
- offsetGeom = geom;
- }
+ const QgsAbstractGeometryV2 *tempGeom = geom.data();
- writePolyline( offsetGeom->coordinateSequence().at( 0 ).at( 0 ), layer, lineStyleName, penColor, width );
+ switch ( QgsWKBTypes::flatType( geometryType ) )
+ {
+ case QgsWKBTypes::CircularString:
+ case QgsWKBTypes::CompoundCurve:
+ tempGeom = geom->segmentize();
+ FALLTHROUGH;
+ case QgsWKBTypes::LineString:
+ if ( !qgsDoubleNear( offset, 0.0 ) )
+ {
+ QgsGeos geos( tempGeom );
+ if ( tempGeom != geom.data() )
+ delete tempGeom;
+ tempGeom = geos.offsetCurve( offset, 0, GEOSBUF_JOIN_MITRE, 2.0 );
+ if ( !tempGeom )
+ tempGeom = geom.data();
+ }
- if ( offsetGeom != geom )
- delete offsetGeom;
- }
+ writePolyline( tempGeom->coordinateSequence().at( 0 ).at( 0 ), layer, lineStyleName, penColor, width );
- // multiline
- if ( QgsWKBTypes::flatType( geometryType ) == QgsWKBTypes::MultiLineString )
- {
- const QgsAbstractGeometryV2 *offsetGeom = geom;
+ break;
- if ( !qgsDoubleNear( offset, 0.0 ) )
+ case QgsWKBTypes::MultiCurve:
+ tempGeom = geom->segmentize();
+ FALLTHROUGH;
+ case QgsWKBTypes::MultiLineString:
{
- QgsGeos geos( geom );
- offsetGeom = geos.offsetCurve( offset, 0, GEOSBUF_JOIN_MITRE, 2.0 );
- if ( !offsetGeom )
- offsetGeom = geom;
- }
+ if ( !qgsDoubleNear( offset, 0.0 ) )
+ {
+ QgsGeos geos( tempGeom );
+ if ( tempGeom != geom.data() )
+ delete tempGeom;
+ tempGeom = geos.offsetCurve( offset, 0, GEOSBUF_JOIN_MITRE, 2.0 );
+ if ( !tempGeom )
+ tempGeom = geom.data();
+ }
- const QgsCoordinateSequenceV2 &cs = offsetGeom->coordinateSequence();
- for ( int i = 0; i < cs.size(); i++ )
- {
- writePolyline( cs.at( i ).at( 0 ), layer, lineStyleName, penColor, width );
+ const QgsCoordinateSequenceV2 &cs = tempGeom->coordinateSequence();
+ for ( int i = 0; i < cs.size(); i++ )
+ {
+ writePolyline( cs.at( i ).at( 0 ), layer, lineStyleName, penColor, width );
+ }
+
+ break;
}
- if ( offsetGeom != geom )
- delete offsetGeom;
- }
+ case QgsWKBTypes::CurvePolygon:
+ tempGeom = geom->segmentize();
+ FALLTHROUGH;
+ case QgsWKBTypes::Polygon:
+ {
+ if ( !qgsDoubleNear( offset, 0.0 ) )
+ {
+ QgsGeos geos( tempGeom );
+ if ( tempGeom != geom.data() )
+ delete tempGeom;
+ tempGeom = geos.buffer( offset, 0, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, 2.0 );
+ if ( !tempGeom )
+ tempGeom = geom.data();
+ }
- // polygon
- if ( QgsWKBTypes::flatType( geometryType ) == QgsWKBTypes::Polygon )
- {
- const QgsAbstractGeometryV2 *bufferGeom = geom;
+ const QgsCoordinateSequenceV2 &cs = tempGeom->coordinateSequence();
+ for ( int i = 0; i < cs.at( 0 ).size(); i++ )
+ {
+ writePolyline( cs.at( 0 ).at( i ), layer, lineStyleName, penColor, width );
+ }
- if ( !qgsDoubleNear( offset, 0.0 ) )
- {
- QgsGeos geos( geom );
- bufferGeom = geos.buffer( offset, 0, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, 2.0 );
- if ( !bufferGeom )
- bufferGeom = geom;
+ break;
}
- const QgsCoordinateSequenceV2 &cs = bufferGeom->coordinateSequence();
- for ( int i = 0; i < cs.at( 0 ).size(); i++ )
+ case QgsWKBTypes::MultiPolygon:
{
- writePolyline( cs.at( 0 ).at( i ), layer, lineStyleName, penColor, width );
- }
-
- if ( bufferGeom != geom )
- delete bufferGeom;
- }
+ if ( !qgsDoubleNear( offset, 0.0 ) )
+ {
+ QgsGeos geos( tempGeom );
+ if ( tempGeom != geom.data() )
+ delete tempGeom;
+ tempGeom = geos.buffer( offset, 0, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, 2.0 );
+ if ( !tempGeom )
+ tempGeom = geom.data();
+ }
- // multipolygon or polygon
- if ( QgsWKBTypes::flatType( geometryType ) == QgsWKBTypes::MultiPolygon )
- {
- const QgsAbstractGeometryV2 *bufferGeom = geom;
+ const QgsCoordinateSequenceV2 &cs = tempGeom->coordinateSequence();
+ for ( int i = 0; i < cs.size(); i++ )
+ for ( int j = 0; j < cs.at( i ).size(); j++ )
+ writePolyline( cs.at( i ).at( j ), layer, lineStyleName, penColor, width );
- if ( !qgsDoubleNear( offset, 0.0 ) )
- {
- QgsGeos geos( geom );
- bufferGeom = geos.buffer( offset, 0, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, 2.0 );
- if ( !bufferGeom )
- bufferGeom = geom;
+ break;
}
- const QgsCoordinateSequenceV2 &cs = bufferGeom->coordinateSequence();
- for ( int i = 0; i < cs.size(); i++ )
- for ( int j = 0; j < cs.at( i ).size(); j++ )
- writePolyline( cs.at( i ).at( j ), layer, lineStyleName, penColor, width );
-
- if ( bufferGeom != geom )
- delete bufferGeom;
+ default:
+ break;
}
+
+ if ( tempGeom != geom.data() )
+ delete tempGeom;
}
if ( brushStyle != Qt::NoBrush )
{
- // polygon
- if ( QgsWKBTypes::flatType( geometryType ) == QgsWKBTypes::Polygon )
- {
- writePolygon( geom->coordinateSequence().at( 0 ), layer, "SOLID", brushColor );
- }
+ const QgsAbstractGeometryV2 *tempGeom = geom.data();
- // multipolygon or polygon
- if ( QgsWKBTypes::flatType( geometryType ) == QgsWKBTypes::MultiPolygon )
+ switch ( QgsWKBTypes::flatType( geometryType ) )
{
- const QgsCoordinateSequenceV2 &cs = geom->coordinateSequence();
- for ( int i = 0; i < cs.size(); i++ )
+ case QgsWKBTypes::CurvePolygon:
+ tempGeom = tempGeom->segmentize();
+ FALLTHROUGH;
+ case QgsWKBTypes::Polygon:
+ writePolygon( tempGeom->coordinateSequence().at( 0 ), layer, "SOLID", brushColor );
+ break;
+
+ case QgsWKBTypes::MultiPolygon:
{
- writePolygon( cs.at( i ), layer, "SOLID", brushColor );
+ const QgsCoordinateSequenceV2 &cs = geom->coordinateSequence();
+ for ( int i = 0; i < cs.size(); i++ )
+ {
+ writePolygon( cs.at( i ), layer, "SOLID", brushColor );
+ }
+ break;
}
+
+ default:
+ break;
+
}
+
+ if ( tempGeom != geom.data() )
+ delete tempGeom;
}
}
@@ -4416,7 +4443,7 @@ void QgsDxfExport::drawLabel( QString layerId, QgsRenderContext& context, pal::L
txt.prepend( "\\K" ).append( "\\k" );
}
- txt.prepend( QString( "\\f%1|i%2|b%3;\\H%4;\\W0.75;" )
+ txt.prepend( QString( "\\f%1|i%2|b%3;\\H%4;" )
.arg( tmpLyr.textFont.family() )
.arg( tmpLyr.textFont.italic() ? 1 : 0 )
.arg( tmpLyr.textFont.bold() ? 1 : 0 )
@@ -4433,3 +4460,13 @@ void QgsDxfExport::registerDxfLayer( QString layerId, QgsFeatureId fid, QString
mDxfLayerNames[layerId][fid] = layerName;
}
+
+void QgsDxfExport::setDestinationCrs( long crs )
+{
+ mCrs = crs;
+}
+
+long QgsDxfExport::destinationCrs()
+{
+ return mCrs;
+}
diff --git a/src/core/dxf/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h
index 9e7b929..fcfd81b 100644
--- a/src/core/dxf/qgsdxfexport.h
+++ b/src/core/dxf/qgsdxfexport.h
@@ -20,6 +20,7 @@
#include "qgsgeometry.h"
#include "qgssymbolv2.h"
+#include "qgsmapsettings.h"
#include <QColor>
#include <QList>
@@ -96,6 +97,16 @@ class CORE_EXPORT QgsDxfExport
QGis::UnitType mapUnits() const { return mMapUnits; }
/**
+ * Set destination CRS
+ */
+ void setDestinationCrs( long crs );
+
+ /**
+ * Set destination CRS
+ */
+ long destinationCrs();
+
+ /**
* Set symbology export mode
* @param e the mode
*/
@@ -418,9 +429,7 @@ class CORE_EXPORT QgsDxfExport
void writeSymbolLayerLinetype( const QgsSymbolLayerV2 *symbolLayer );
void writeLinetype( const QString &styleName, const QVector<qreal> &pattern, QgsSymbolV2::OutputUnit u );
- QgsRectangle dxfExtent() const;
-
- void addFeature( QgsSymbolV2RenderContext &ctx, const QString &layer, const QgsSymbolLayerV2 *symbolLayer, const QgsSymbolV2 *symbol );
+ void addFeature( QgsSymbolV2RenderContext &ctx, const QgsCoordinateTransform *ct, const QString &layer, const QgsSymbolLayerV2 *symbolLayer, const QgsSymbolV2 *symbol );
//returns dxf palette index from symbol layer color
static QColor colorFromSymbolLayer( const QgsSymbolLayerV2 *symbolLayer, QgsSymbolV2RenderContext &ctx );
@@ -448,6 +457,9 @@ class CORE_EXPORT QgsDxfExport
//! DXF layer name for each label feature
QMap< QString, QMap<QgsFeatureId, QString> > mDxfLayerNames;
+ long mCrs;
+ QgsMapSettings mMapSettings;
+ double mFactor;
};
#endif // QGSDXFEXPORT_H
diff --git a/src/core/effects/qgspainteffect.cpp b/src/core/effects/qgspainteffect.cpp
index 71b11be..01192df 100644
--- a/src/core/effects/qgspainteffect.cpp
+++ b/src/core/effects/qgspainteffect.cpp
@@ -162,6 +162,11 @@ void QgsPaintEffect::end( QgsRenderContext &context )
context.setPainter( mPrevPainter );
mPrevPainter = nullptr;
+ // clear any existing pen/brush - sometimes these are not correctly restored when restoring a painter
+ // with a QPicture destination - see #15696
+ context.painter()->setPen( Qt::NoPen );
+ context.painter()->setBrush( Qt::NoBrush );
+
//draw using effect
render( *mTempPicture, context );
diff --git a/src/core/geometry/qgsabstractgeometryv2.h b/src/core/geometry/qgsabstractgeometryv2.h
index f602ee7..27bc7fc 100644
--- a/src/core/geometry/qgsabstractgeometryv2.h
+++ b/src/core/geometry/qgsabstractgeometryv2.h
@@ -110,10 +110,16 @@ class CORE_EXPORT QgsAbstractGeometryV2
virtual bool isValid() const = 0;
virtual QgsMultiPointV2* locateAlong() const = 0;
virtual QgsMultiCurveV2* locateBetween() const = 0;
- virtual QgsCurveV2* boundary() const = 0;
virtual QgsRectangle envelope() const = 0;
#endif
+ /** Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the geometry).
+ * For instance, a polygon geometry will have a boundary consisting of the linestrings for each ring in the polygon.
+ * @returns boundary for geometry. May be null for some geometry types.
+ * @note added in QGIS 2.18
+ */
+ virtual QgsAbstractGeometryV2* boundary() const = 0;
+
//import
/** Sets the geometry from a WKB string.
@@ -239,7 +245,7 @@ class CORE_EXPORT QgsAbstractGeometryV2
* @param leftOf returns whether the point lies on the left side of the nearest segment (true if point is to left of segment,
* false if point is to right of segment)
* @param epsilon epsilon for segment snapping
- * @returns squared distance to closest segment
+ * @returns squared distance to closest segment or negative value on error
*/
virtual double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const = 0;
diff --git a/src/core/geometry/qgscircularstringv2.cpp b/src/core/geometry/qgscircularstringv2.cpp
index 39d8a65..2c55584 100644
--- a/src/core/geometry/qgscircularstringv2.cpp
+++ b/src/core/geometry/qgscircularstringv2.cpp
@@ -845,6 +845,9 @@ double QgsCircularStringV2::closestSegment( const QgsPointV2& pt, QgsPointV2& se
}
}
+ if ( minDist == std::numeric_limits<double>::max() )
+ return -1; // error: no segments
+
segmentPt = minDistSegmentPoint;
vertexAfter = minDistVertexAfter;
vertexAfter.part = 0;
diff --git a/src/core/geometry/qgscurvepolygonv2.cpp b/src/core/geometry/qgscurvepolygonv2.cpp
index 379db18..94f41f3 100644
--- a/src/core/geometry/qgscurvepolygonv2.cpp
+++ b/src/core/geometry/qgscurvepolygonv2.cpp
@@ -23,6 +23,7 @@
#include "qgslinestringv2.h"
#include "qgspolygonv2.h"
#include "qgswkbptr.h"
+#include "qgsmulticurvev2.h"
#include <QPainter>
#include <QPainterPath>
@@ -420,6 +421,25 @@ QgsPolygonV2* QgsCurvePolygonV2::surfaceToPolygon() const
return polygon;
}
+QgsAbstractGeometryV2* QgsCurvePolygonV2::boundary() const
+{
+ if ( mInteriorRings.isEmpty() )
+ {
+ return mExteriorRing->clone();
+ }
+ else
+ {
+ QgsMultiCurveV2* multiCurve = new QgsMultiCurveV2();
+ multiCurve->addGeometry( mExteriorRing->clone() );
+ int nInteriorRings = mInteriorRings.size();
+ for ( int i = 0; i < nInteriorRings; ++i )
+ {
+ multiCurve->addGeometry( mInteriorRings.at( i )->clone() );
+ }
+ return multiCurve;
+ }
+}
+
QgsPolygonV2* QgsCurvePolygonV2::toPolygon( double tolerance, SegmentationToleranceType toleranceType ) const
{
if ( !mExteriorRing )
@@ -616,7 +636,7 @@ double QgsCurvePolygonV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segm
{
if ( !mExteriorRing )
{
- return 0.0;
+ return -1;
}
QList<QgsCurveV2*> segmentList;
segmentList.append( mExteriorRing );
diff --git a/src/core/geometry/qgscurvepolygonv2.h b/src/core/geometry/qgscurvepolygonv2.h
index 48c2038..19f7dba 100644
--- a/src/core/geometry/qgscurvepolygonv2.h
+++ b/src/core/geometry/qgscurvepolygonv2.h
@@ -55,6 +55,7 @@ class CORE_EXPORT QgsCurvePolygonV2: public QgsSurfaceV2
virtual double area() const override;
virtual double perimeter() const override;
QgsPolygonV2* surfaceToPolygon() const override;
+ virtual QgsAbstractGeometryV2* boundary() const override;
//curve polygon interface
int numInteriorRings() const;
diff --git a/src/core/geometry/qgscurvev2.cpp b/src/core/geometry/qgscurvev2.cpp
index 91e7116..2c70f6b 100644
--- a/src/core/geometry/qgscurvev2.cpp
+++ b/src/core/geometry/qgscurvev2.cpp
@@ -17,6 +17,8 @@
#include "qgscurvev2.h"
#include "qgslinestringv2.h"
+#include "qgspointv2.h"
+#include "qgsmultipointv2.h"
QgsCurveV2::QgsCurveV2(): QgsAbstractGeometryV2()
{}
@@ -79,6 +81,20 @@ bool QgsCurveV2::nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const
return pointAt( id.vertex, vertex, id.type );
}
+QgsAbstractGeometryV2* QgsCurveV2::boundary() const
+{
+ if ( isEmpty() )
+ return nullptr;
+
+ if ( isClosed() )
+ return nullptr;
+
+ QgsMultiPointV2* multiPoint = new QgsMultiPointV2();
+ multiPoint->addGeometry( new QgsPointV2( startPoint() ) );
+ multiPoint->addGeometry( new QgsPointV2( endPoint() ) );
+ return multiPoint;
+}
+
QgsCurveV2* QgsCurveV2::segmentize( double tolerance, SegmentationToleranceType toleranceType ) const
{
return curveToLine( tolerance, toleranceType );
diff --git a/src/core/geometry/qgscurvev2.h b/src/core/geometry/qgscurvev2.h
index 46f5fea..cb2d416 100644
--- a/src/core/geometry/qgscurvev2.h
+++ b/src/core/geometry/qgscurvev2.h
@@ -102,6 +102,8 @@ class CORE_EXPORT QgsCurveV2: public QgsAbstractGeometryV2
*/
virtual QgsCurveV2* reversed() const = 0;
+ virtual QgsAbstractGeometryV2* boundary() const override;
+
/** Returns a geometry without curves. Caller takes ownership
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
diff --git a/src/core/geometry/qgsgeometry.cpp b/src/core/geometry/qgsgeometry.cpp
index 8c4d2bf..f58749c 100644
--- a/src/core/geometry/qgsgeometry.cpp
+++ b/src/core/geometry/qgsgeometry.cpp
@@ -347,6 +347,7 @@ QgsPoint QgsGeometry::closestVertex( const QgsPoint& point, int& atVertex, int&
{
if ( !d->geometry )
{
+ sqrDist = -1;
return QgsPoint( 0, 0 );
}
@@ -382,6 +383,46 @@ double QgsGeometry::distanceToVertex( int vertex ) const
return QgsGeometryUtils::distanceToVertex( *( d->geometry ), id );
}
+double QgsGeometry::angleAtVertex( int vertex ) const
+{
+ if ( !d->geometry )
+ {
+ return 0;
+ }
+
+ QgsVertexId v2;
+ if ( !vertexIdFromVertexNr( vertex, v2 ) )
+ {
+ return 0;
+ }
+
+ QgsVertexId v1;
+ QgsVertexId v3;
+ QgsGeometryUtils::adjacentVertices( *d->geometry, v2, v1, v3 );
+ if ( v1.isValid() && v3.isValid() )
+ {
+ QgsPointV2 p1 = d->geometry->vertexAt( v1 );
+ QgsPointV2 p2 = d->geometry->vertexAt( v2 );
+ QgsPointV2 p3 = d->geometry->vertexAt( v3 );
+ double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
+ double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
+ return QgsGeometryUtils::averageAngle( angle1, angle2 );
+ }
+ else if ( v3.isValid() )
+ {
+ QgsPointV2 p1 = d->geometry->vertexAt( v2 );
+ QgsPointV2 p2 = d->geometry->vertexAt( v3 );
+ return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
+ }
+ else if ( v1.isValid() )
+ {
+ QgsPointV2 p1 = d->geometry->vertexAt( v1 );
+ QgsPointV2 p2 = d->geometry->vertexAt( v2 );
+ return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
+ }
+ return 0.0;
+}
+
void QgsGeometry::adjacentVertices( int atVertex, int& beforeVertex, int& afterVertex ) const
{
if ( !d->geometry )
@@ -547,12 +588,14 @@ double QgsGeometry::closestVertexWithContext( const QgsPoint& point, int& atVert
{
if ( !d->geometry )
{
- return 0.0;
+ return -1;
}
QgsVertexId vId;
QgsPointV2 pt( point.x(), point.y() );
QgsPointV2 closestPoint = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, vId );
+ if ( !vId.isValid() )
+ return -1;
atVertex = vertexNrFromVertexId( vId );
return QgsGeometryUtils::sqrDistance2D( closestPoint, pt );
}
@@ -566,7 +609,7 @@ double QgsGeometry::closestSegmentWithContext(
{
if ( !d->geometry )
{
- return 0;
+ return -1;
}
QgsPointV2 segmentPt;
@@ -574,6 +617,8 @@ double QgsGeometry::closestSegmentWithContext(
bool leftOfBool;
double sqrDist = d->geometry->closestSegment( QgsPointV2( point.x(), point.y() ), segmentPt, vertexAfter, &leftOfBool, epsilon );
+ if ( sqrDist < 0 )
+ return -1;
minDistPoint.setX( segmentPt.x() );
minDistPoint.setY( segmentPt.y() );
@@ -1382,7 +1427,12 @@ QgsGeometry* QgsGeometry::interpolate( double distance ) const
{
return nullptr;
}
- QgsGeos geos( d->geometry );
+
+ QgsGeometry line = *this;
+ if ( type() == QGis::Polygon )
+ line = QgsGeometry( d->geometry->boundary() );
+
+ QgsGeos geos( line.geometry() );
QgsAbstractGeometryV2* result = geos.interpolate( distance );
if ( !result )
{
@@ -1391,6 +1441,79 @@ QgsGeometry* QgsGeometry::interpolate( double distance ) const
return new QgsGeometry( result );
}
+double QgsGeometry::lineLocatePoint( const QgsGeometry& point ) const
+{
+ if ( type() != QGis::Line )
+ return -1;
+
+ if ( QgsWKBTypes::flatType( point.d->geometry->wkbType() ) != QgsWKBTypes::Point )
+ return -1;
+
+ QgsGeometry segmentized = *this;
+ if ( QgsWKBTypes::isCurvedType( d->geometry->wkbType() ) )
+ {
+ segmentized = QgsGeometry( static_cast< QgsCurveV2* >( d->geometry )->segmentize() );
+ }
+
+ QgsGeos geos( d->geometry );
+ return geos.lineLocatePoint( *( static_cast< QgsPointV2* >( point.d->geometry ) ) );
+}
+
+double QgsGeometry::interpolateAngle( double distance ) const
+{
+ if ( !d->geometry )
+ return 0.0;
+
+ // always operate on segmentized geometries
+ QgsGeometry segmentized = *this;
+ if ( QgsWKBTypes::isCurvedType( d->geometry->wkbType() ) )
+ {
+ segmentized = QgsGeometry( static_cast< QgsCurveV2* >( d->geometry )->segmentize() );
+ }
+
+ QgsVertexId previous;
+ QgsVertexId next;
+ if ( !QgsGeometryUtils::verticesAtDistance( *segmentized.geometry(), distance, previous, next ) )
+ return 0.0;
+
+ if ( previous == next )
+ {
+ // distance coincided exactly with a vertex
+ QgsVertexId v2 = previous;
+ QgsVertexId v1;
+ QgsVertexId v3;
+ QgsGeometryUtils::adjacentVertices( *segmentized.geometry(), v2, v1, v3 );
+ if ( v1.isValid() && v3.isValid() )
+ {
+ QgsPointV2 p1 = segmentized.geometry()->vertexAt( v1 );
+ QgsPointV2 p2 = segmentized.geometry()->vertexAt( v2 );
+ QgsPointV2 p3 = segmentized.geometry()->vertexAt( v3 );
+ double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
+ double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
+ return QgsGeometryUtils::averageAngle( angle1, angle2 );
+ }
+ else if ( v3.isValid() )
+ {
+ QgsPointV2 p1 = segmentized.geometry()->vertexAt( v2 );
+ QgsPointV2 p2 = segmentized.geometry()->vertexAt( v3 );
+ return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
+ }
+ else
+ {
+ QgsPointV2 p1 = segmentized.geometry()->vertexAt( v1 );
+ QgsPointV2 p2 = segmentized.geometry()->vertexAt( v2 );
+ return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
+ }
+ }
+ else
+ {
+ QgsPointV2 p1 = segmentized.geometry()->vertexAt( previous );
+ QgsPointV2 p2 = segmentized.geometry()->vertexAt( next );
+ return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
+ }
+}
+
+
QgsGeometry* QgsGeometry::intersection( const QgsGeometry* geometry ) const
{
if ( !d->geometry || !geometry->d->geometry )
@@ -1421,6 +1544,23 @@ QgsGeometry* QgsGeometry::combine( const QgsGeometry* geometry ) const
return new QgsGeometry( resultGeom );
}
+QgsGeometry QgsGeometry::mergeLines() const
+{
+ if ( !d->geometry )
+ {
+ return QgsGeometry();
+ }
+
+ if ( QgsWKBTypes::flatType( d->geometry->wkbType() ) == QgsWKBTypes::LineString )
+ {
+ // special case - a single linestring was passed
+ return QgsGeometry( *this );
+ }
+
+ QgsGeos geos( d->geometry );
+ return geos.mergeLines();
+}
+
QgsGeometry* QgsGeometry::difference( const QgsGeometry* geometry ) const
{
if ( !d->geometry || !geometry->d->geometry )
diff --git a/src/core/geometry/qgsgeometry.h b/src/core/geometry/qgsgeometry.h
index d4ae8d2..0bde341 100644
--- a/src/core/geometry/qgsgeometry.h
+++ b/src/core/geometry/qgsgeometry.h
@@ -221,7 +221,7 @@ class CORE_EXPORT QgsGeometry
* @param afterVertex will be set to the vertex index of the next vertex after the closest one. Will be set to -1 if
* not present.
* @param sqrDist will be set to the square distance between the closest vertex and the specified point
- * @returns closest point in geometry
+ * @returns closest point in geometry. If not found (empty geometry), returns null point nad sqrDist is negative.
*/
//TODO QGIS 3.0 - rename beforeVertex to previousVertex, afterVertex to nextVertex
QgsPoint closestVertex( const QgsPoint& point, int& atVertex, int& beforeVertex, int& afterVertex, double& sqrDist ) const;
@@ -235,6 +235,15 @@ class CORE_EXPORT QgsGeometry
double distanceToVertex( int vertex ) const;
/**
+ * Returns the bisector angle for this geometry at the specified vertex.
+ * @param vertex vertex index to calculate bisector angle at
+ * @returns bisector angle, in radians clockwise from north
+ * @note added in QGIS 2.18
+ * @see interpolateAngle()
+ */
+ double angleAtVertex( int vertex ) const;
+
+ /**
* Returns the indexes of the vertices before and after the given vertex index.
*
* This function takes into account the following factors:
@@ -515,9 +524,32 @@ class CORE_EXPORT QgsGeometry
/**
* Return interpolated point on line at distance
* @note added in 1.9
+ * @see lineLocatePoint()
*/
QgsGeometry* interpolate( double distance ) const;
+ /** Returns a distance representing the location along this linestring of the closest point
+ * on this linestring geometry to the specified point. Ie, the returned value indicates
+ * how far along this linestring you need to traverse to get to the closest location
+ * where this linestring comes to the specified point.
+ * @param point point to seek proximity to
+ * @return distance along line, or -1 on error
+ * @note only valid for linestring geometries
+ * @see interpolate()
+ * @note added in QGIS 2.18
+ */
+ double lineLocatePoint( const QgsGeometry& point ) const;
+
+ /** Returns the angle parallel to the linestring or polygon boundary at the specified distance
+ * along the geometry. Angles are in radians, clockwise from north.
+ * If the distance coincides precisely at a node then the average angle from the segment either side
+ * of the node is returned.
+ * @param distance distance along geometry
+ * @note added in QGIS 2.18
+ * @see angleAtVertex()
+ */
+ double interpolateAngle( double distance ) const;
+
/** Returns a geometry representing the points shared by this geometry and other. */
QgsGeometry* intersection( const QgsGeometry* geometry ) const;
@@ -527,6 +559,15 @@ class CORE_EXPORT QgsGeometry
*/
QgsGeometry* combine( const QgsGeometry* geometry ) const;
+ /** Merges any connected lines in a LineString/MultiLineString geometry and
+ * converts them to single line strings.
+ * @returns a LineString or MultiLineString geometry, with any connected lines
+ * joined. An empty geometry will be returned if the input geometry was not a
+ * MultiLineString geometry.
+ * @note added in QGIS 2.18
+ */
+ QgsGeometry mergeLines() const;
+
/** Returns a geometry representing the points making up this geometry that do not make up other. */
QgsGeometry* difference( const QgsGeometry* geometry ) const;
diff --git a/src/core/geometry/qgsgeometrycollectionv2.cpp b/src/core/geometry/qgsgeometrycollectionv2.cpp
index cb6b176..3e81c17 100644
--- a/src/core/geometry/qgsgeometrycollectionv2.cpp
+++ b/src/core/geometry/qgsgeometrycollectionv2.cpp
@@ -75,6 +75,11 @@ void QgsGeometryCollectionV2::clear()
clearCache(); //set bounding box invalid
}
+QgsAbstractGeometryV2*QgsGeometryCollectionV2::boundary() const
+{
+ return nullptr;
+}
+
int QgsGeometryCollectionV2::numGeometries() const
{
return mGeometries.size();
diff --git a/src/core/geometry/qgsgeometrycollectionv2.h b/src/core/geometry/qgsgeometrycollectionv2.h
index 4d489a6..241d39f 100644
--- a/src/core/geometry/qgsgeometrycollectionv2.h
+++ b/src/core/geometry/qgsgeometrycollectionv2.h
@@ -54,6 +54,7 @@ class CORE_EXPORT QgsGeometryCollectionV2: public QgsAbstractGeometryV2
virtual int dimension() const override;
virtual QString geometryType() const override { return "GeometryCollection"; }
virtual void clear() override;
+ virtual QgsAbstractGeometryV2* boundary() const override;
/** Adds a geometry and takes ownership. Returns true in case of success.*/
virtual bool addGeometry( QgsAbstractGeometryV2* g );
diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp
index 77fa2c1..4a53d96 100644
--- a/src/core/geometry/qgsgeometryutils.cpp
+++ b/src/core/geometry/qgsgeometryutils.cpp
@@ -65,6 +65,7 @@ QgsPointV2 QgsGeometryUtils::closestVertex( const QgsAbstractGeometryV2& geom, c
double minDist = std::numeric_limits<double>::max();
double currentDist = 0;
QgsPointV2 minDistPoint;
+ id = QgsVertexId(); // set as invalid
QgsVertexId vertexId;
QgsPointV2 vertex;
@@ -119,6 +120,51 @@ double QgsGeometryUtils::distanceToVertex( const QgsAbstractGeometryV2 &geom, co
return -1;
}
+bool QgsGeometryUtils::verticesAtDistance( const QgsAbstractGeometryV2& geometry, double distance, QgsVertexId& previousVertex, QgsVertexId& nextVertex )
+{
+ double currentDist = 0;
+ previousVertex = QgsVertexId();
+ nextVertex = QgsVertexId();
+
+ QgsPointV2 point;
+ QgsPointV2 previousPoint;
+
+ if ( qgsDoubleNear( distance, 0.0 ) )
+ {
+ geometry.nextVertex( previousVertex, point );
+ nextVertex = previousVertex;
+ return true;
+ }
+
+ bool first = true;
+ while ( currentDist < distance && geometry.nextVertex( nextVertex, point ) )
+ {
+ if ( !first )
+ {
+ currentDist += sqrt( QgsGeometryUtils::sqrDistance2D( previousPoint, point ) );
+ }
+
+ if ( qgsDoubleNear( currentDist, distance ) )
+ {
+ // exact hit!
+ previousVertex = nextVertex;
+ return true;
+ }
+
+ if ( currentDist > distance )
+ {
+ return true;
+ }
+
+ previousVertex = nextVertex;
+ previousPoint = point;
+ first = false;
+ }
+
+ //could not find target distance
+ return false;
+}
+
void QgsGeometryUtils::adjacentVertices( const QgsAbstractGeometryV2& geom, QgsVertexId atVertex, QgsVertexId& beforeVertex, QgsVertexId& afterVertex )
{
bool polygonType = ( geom.dimension() == 2 );
@@ -156,9 +202,16 @@ void QgsGeometryUtils::adjacentVertices( const QgsAbstractGeometryV2& geom, QgsV
}
else if ( atVertex.vertex == 0 )
{
- afterVertex.part = atVertex.part;
- afterVertex.ring = atVertex.ring;
- afterVertex.vertex = atVertex.vertex + 1;
+ if ( ring.size() > 1 )
+ {
+ afterVertex.part = atVertex.part;
+ afterVertex.ring = atVertex.ring;
+ afterVertex.vertex = atVertex.vertex + 1;
+ }
+ else
+ {
+ afterVertex = QgsVertexId(); //after vertex invalid
+ }
if ( polygonType && ring.size() > 3 )
{
beforeVertex.part = atVertex.part;
diff --git a/src/core/geometry/qgsgeometryutils.h b/src/core/geometry/qgsgeometryutils.h
index f8d8a5f..642d2e3 100644
--- a/src/core/geometry/qgsgeometryutils.h
+++ b/src/core/geometry/qgsgeometryutils.h
@@ -37,7 +37,8 @@ class CORE_EXPORT QgsGeometryUtils
*/
static QList<QgsLineStringV2*> extractLineStrings( const QgsAbstractGeometryV2* geom );
- /** Returns the closest vertex to a geometry for a specified point
+ /** Returns the closest vertex to a geometry for a specified point.
+ * On error null point will be returned and "id" argument will be invalid.
*/
static QgsPointV2 closestVertex( const QgsAbstractGeometryV2& geom, const QgsPointV2& pt, QgsVertexId& id );
@@ -49,6 +50,21 @@ class CORE_EXPORT QgsGeometryUtils
*/
static double distanceToVertex( const QgsAbstractGeometryV2& geom, const QgsVertexId& id );
+ /** Retrieves the vertices which are before and after the interpolated point at a specified distance along a linestring
+ * (or polygon boundary).
+ * @param geometry line or polygon geometry
+ * @param distance distance to traverse along geometry
+ * @param previousVertex will be set to previous vertex ID
+ * @param nextVertex will be set to next vertex ID
+ * @note if the distance coincides exactly with a vertex, then both previousVertex and nextVertex will be set to this vertex
+ * @returns true if vertices were successfully retrieved
+ * @note added in QGIS 2.18
+ */
+ static bool verticesAtDistance( const QgsAbstractGeometryV2& geometry,
+ double distance,
+ QgsVertexId& previousVertex,
+ QgsVertexId& nextVertex );
+
/** Returns vertices adjacent to a specified vertex within a geometry.
*/
static void adjacentVertices( const QgsAbstractGeometryV2& geom, QgsVertexId atVertex, QgsVertexId& beforeVertex, QgsVertexId& afterVertex );
@@ -235,7 +251,7 @@ class CORE_EXPORT QgsGeometryUtils
for ( int i = 0; i < container.size(); ++i )
{
sqrDist = container.at( i )->closestSegment( pt, segmentPt, vertexAfter, leftOf, epsilon );
- if ( sqrDist < minDist )
+ if ( sqrDist >= 0 && sqrDist < minDist )
{
minDist = sqrDist;
minDistSegmentX = segmentPt.x();
@@ -265,6 +281,9 @@ class CORE_EXPORT QgsGeometryUtils
}
}
+ if ( minDist == std::numeric_limits<double>::max() )
+ return -1; // error: no segments
+
segmentPt.setX( minDistSegmentX );
segmentPt.setY( minDistSegmentY );
vertexAfter = minDistVertexAfter;
diff --git a/src/core/geometry/qgsgeos.cpp b/src/core/geometry/qgsgeos.cpp
index b837726..ae0b992 100644
--- a/src/core/geometry/qgsgeos.cpp
+++ b/src/core/geometry/qgsgeos.cpp
@@ -1794,6 +1794,25 @@ QgsAbstractGeometryV2* QgsGeos::reshapeGeometry( const QgsLineStringV2& reshapeW
}
}
+QgsGeometry QgsGeos::mergeLines( QString* errorMsg ) const
+{
+ if ( !mGeos )
+ {
+ return QgsGeometry();
+ }
+
+ if ( GEOSGeomTypeId_r( geosinit.ctxt, mGeos ) != GEOS_MULTILINESTRING )
+ return QgsGeometry();
+
+ GEOSGeomScopedPtr geos;
+ try
+ {
+ geos.reset( GEOSLineMerge_r( geosinit.ctxt, mGeos ) );
+ }
+ CATCH_GEOS_WITH_ERRMSG( QgsGeometry() );
+ return QgsGeometry( fromGeos( geos.get() ) );
+}
+
QgsGeometry QgsGeos::closestPoint( const QgsGeometry& other, QString* errorMsg ) const
{
if ( !mGeos || other.isEmpty() )
@@ -1872,6 +1891,36 @@ QgsGeometry QgsGeos::shortestLine( const QgsGeometry& other, QString* errorMsg )
return QgsGeometry( line );
}
+double QgsGeos::lineLocatePoint( const QgsPointV2& point, QString* errorMsg ) const
+{
+ if ( !mGeos )
+ {
+ return -1;
+ }
+
+ GEOSGeomScopedPtr otherGeom( asGeos( &point, mPrecision ) );
+ if ( !otherGeom )
+ {
+ return -1;
+ }
+
+ double distance = -1;
+ try
+ {
+ distance = GEOSProject_r( geosinit.ctxt, mGeos, otherGeom.get() );
+ }
+ catch ( GEOSException &e )
+ {
+ if ( errorMsg )
+ {
+ *errorMsg = e.what();
+ }
+ return -1;
+ }
+
+ return distance;
+}
+
/** Extract coordinates of linestring's endpoints. Returns false on error. */
static bool _linestringEndpoints( const GEOSGeometry* linestring, double& x1, double& y1, double& x2, double& y2 )
diff --git a/src/core/geometry/qgsgeos.h b/src/core/geometry/qgsgeos.h
index f5001e4..eaecef9 100644
--- a/src/core/geometry/qgsgeos.h
+++ b/src/core/geometry/qgsgeos.h
@@ -88,6 +88,16 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
QgsAbstractGeometryV2* offsetCurve( double distance, int segments, int joinStyle, double mitreLimit, QString* errorMsg = nullptr ) const override;
QgsAbstractGeometryV2* reshapeGeometry( const QgsLineStringV2& reshapeWithLine, int* errorCode, QString* errorMsg = nullptr ) const;
+ /** Merges any connected lines in a LineString/MultiLineString geometry and
+ * converts them to single line strings.
+ * @param errorMsg if specified, will be set to any reported GEOS errors
+ * @returns a LineString or MultiLineString geometry, with any connected lines
+ * joined. An empty geometry will be returned if the input geometry was not a
+ * LineString/MultiLineString geometry.
+ * @note added in QGIS 2.18
+ */
+ QgsGeometry mergeLines( QString* errorMsg = nullptr ) const;
+
/** Returns the closest point on the geometry to the other geometry.
* @note added in QGIS 2.14
* @see shortestLine()
@@ -100,6 +110,17 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
*/
QgsGeometry shortestLine( const QgsGeometry& other, QString* errorMsg = nullptr ) const;
+ /** Returns a distance representing the location along this linestring of the closest point
+ * on this linestring geometry to the specified point. Ie, the returned value indicates
+ * how far along this linestring you need to traverse to get to the closest location
+ * where this linestring comes to the specified point.
+ * @param point point to seek proximity to
+ * @param errorMsg error messages emitted, if any
+ * @note only valid for linestring geometries
+ * @return distance along line, or -1 on error
+ */
+ double lineLocatePoint( const QgsPointV2& point, QString* errorMsg = nullptr ) const;
+
/** Create a geometry from a GEOSGeometry
* @param geos GEOSGeometry. Ownership is NOT transferred.
*/
diff --git a/src/core/geometry/qgslinestringv2.cpp b/src/core/geometry/qgslinestringv2.cpp
index 4be74ad..8b25f3d 100644
--- a/src/core/geometry/qgslinestringv2.cpp
+++ b/src/core/geometry/qgslinestringv2.cpp
@@ -747,16 +747,10 @@ double QgsLineStringV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmen
double segmentPtX, segmentPtY;
int size = mX.size();
- if ( size == 0 )
+ if ( size == 0 || size == 1 )
{
vertexAfter = QgsVertexId( 0, 0, 0 );
- return sqrDist;
- }
- else if ( size == 1 )
- {
- segmentPt = pointN( 0 );
- vertexAfter = QgsVertexId( 0, 0, 1 );
- return QgsGeometryUtils::sqrDistance2D( pt, segmentPt );
+ return -1;
}
for ( int i = 1; i < size; ++i )
{
diff --git a/src/core/geometry/qgsmulticurvev2.cpp b/src/core/geometry/qgsmulticurvev2.cpp
index d812e3f..9961e7d 100644
--- a/src/core/geometry/qgsmulticurvev2.cpp
+++ b/src/core/geometry/qgsmulticurvev2.cpp
@@ -20,6 +20,7 @@ email : marco.hugentobler at sourcepole dot com
#include "qgscompoundcurvev2.h"
#include "qgsgeometryutils.h"
#include "qgslinestringv2.h"
+#include "qgsmultipointv2.h"
QgsMultiCurveV2::QgsMultiCurveV2()
: QgsGeometryCollectionV2()
@@ -125,3 +126,25 @@ QgsMultiCurveV2* QgsMultiCurveV2::reversed() const
}
return reversedMultiCurve;
}
+
+QgsAbstractGeometryV2* QgsMultiCurveV2::boundary() const
+{
+ QgsMultiPointV2* multiPoint = new QgsMultiPointV2();
+ for ( int i = 0; i < mGeometries.size(); ++i )
+ {
+ if ( QgsCurveV2* curve = dynamic_cast<QgsCurveV2*>( mGeometries.at( i ) ) )
+ {
+ if ( !curve->isClosed() )
+ {
+ multiPoint->addGeometry( new QgsPointV2( curve->startPoint() ) );
+ multiPoint->addGeometry( new QgsPointV2( curve->endPoint() ) );
+ }
+ }
+ }
+ if ( multiPoint->numGeometries() == 0 )
+ {
+ delete multiPoint;
+ return nullptr;
+ }
+ return multiPoint;
+}
diff --git a/src/core/geometry/qgsmulticurvev2.h b/src/core/geometry/qgsmulticurvev2.h
index 5724c93..3da550f 100644
--- a/src/core/geometry/qgsmulticurvev2.h
+++ b/src/core/geometry/qgsmulticurvev2.h
@@ -47,6 +47,9 @@ class CORE_EXPORT QgsMultiCurveV2: public QgsGeometryCollectionV2
* @note added in QGIS 2.14
*/
QgsMultiCurveV2* reversed() const;
+
+ virtual QgsAbstractGeometryV2* boundary() const override;
+
};
#endif // QGSMULTICURVEV2_H
diff --git a/src/core/geometry/qgsmultilinestringv2.cpp b/src/core/geometry/qgsmultilinestringv2.cpp
index de5b55e..b705cc3 100644
--- a/src/core/geometry/qgsmultilinestringv2.cpp
+++ b/src/core/geometry/qgsmultilinestringv2.cpp
@@ -118,3 +118,4 @@ QgsAbstractGeometryV2* QgsMultiLineStringV2::toCurveType() const
}
return multiCurve;
}
+
diff --git a/src/core/geometry/qgsmultipointv2.cpp b/src/core/geometry/qgsmultipointv2.cpp
index aeff6f7..cd4bb46 100644
--- a/src/core/geometry/qgsmultipointv2.cpp
+++ b/src/core/geometry/qgsmultipointv2.cpp
@@ -105,3 +105,8 @@ bool QgsMultiPointV2::addGeometry( QgsAbstractGeometryV2* g )
setZMTypeFromSubGeometry( g, QgsWKBTypes::MultiPoint );
return QgsGeometryCollectionV2::addGeometry( g );
}
+
+QgsAbstractGeometryV2* QgsMultiPointV2::boundary() const
+{
+ return nullptr;
+}
diff --git a/src/core/geometry/qgsmultipointv2.h b/src/core/geometry/qgsmultipointv2.h
index 8448891..8978ab5 100644
--- a/src/core/geometry/qgsmultipointv2.h
+++ b/src/core/geometry/qgsmultipointv2.h
@@ -44,6 +44,8 @@ class CORE_EXPORT QgsMultiPointV2: public QgsGeometryCollectionV2
/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g ) override;
+ virtual QgsAbstractGeometryV2* boundary() const override;
+
protected:
virtual bool wktOmitChildType() const override { return true; }
diff --git a/src/core/geometry/qgsmultipolygonv2.cpp b/src/core/geometry/qgsmultipolygonv2.cpp
index b0d85e8..faa4737 100644
--- a/src/core/geometry/qgsmultipolygonv2.cpp
+++ b/src/core/geometry/qgsmultipolygonv2.cpp
@@ -20,6 +20,7 @@ email : marco.hugentobler at sourcepole dot com
#include "qgslinestringv2.h"
#include "qgspolygonv2.h"
#include "qgscurvepolygonv2.h"
+#include "qgsmultilinestringv2.h"
QgsMultiPolygonV2::QgsMultiPolygonV2()
: QgsMultiSurfaceV2()
@@ -133,3 +134,38 @@ QgsAbstractGeometryV2* QgsMultiPolygonV2::toCurveType() const
}
return multiSurface;
}
+
+QgsAbstractGeometryV2* QgsMultiPolygonV2::boundary() const
+{
+ QgsMultiLineStringV2* multiLine = new QgsMultiLineStringV2();
+ for ( int i = 0; i < mGeometries.size(); ++i )
+ {
+ if ( QgsPolygonV2* polygon = dynamic_cast<QgsPolygonV2*>( mGeometries.at( i ) ) )
+ {
+ QgsAbstractGeometryV2* polygonBoundary = polygon->boundary();
+
+ if ( QgsLineStringV2* lineStringBoundary = dynamic_cast< QgsLineStringV2* >( polygonBoundary ) )
+ {
+ multiLine->addGeometry( lineStringBoundary );
+ }
+ else if ( QgsMultiLineStringV2* multiLineStringBoundary = dynamic_cast< QgsMultiLineStringV2* >( polygonBoundary ) )
+ {
+ for ( int j = 0; j < multiLineStringBoundary->numGeometries(); ++j )
+ {
+ multiLine->addGeometry( multiLineStringBoundary->geometryN( j )->clone() );
+ }
+ delete multiLineStringBoundary;
+ }
+ else
+ {
+ delete polygonBoundary;
+ }
+ }
+ }
+ if ( multiLine->numGeometries() == 0 )
+ {
+ delete multiLine;
+ return nullptr;
+ }
+ return multiLine;
+}
diff --git a/src/core/geometry/qgsmultipolygonv2.h b/src/core/geometry/qgsmultipolygonv2.h
index 527e0a8..def9db1 100644
--- a/src/core/geometry/qgsmultipolygonv2.h
+++ b/src/core/geometry/qgsmultipolygonv2.h
@@ -40,7 +40,6 @@ class CORE_EXPORT QgsMultiPolygonV2: public QgsMultiSurfaceV2
QDomElement asGML3( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const override;
QString asJSON( int precision = 17 ) const override;
-
/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g ) override;
@@ -48,6 +47,8 @@ class CORE_EXPORT QgsMultiPolygonV2: public QgsMultiSurfaceV2
@return the converted geometry. Caller takes ownership*/
QgsAbstractGeometryV2* toCurveType() const override;
+ virtual QgsAbstractGeometryV2* boundary() const override;
+
protected:
virtual bool wktOmitChildType() const override { return true; }
diff --git a/src/core/geometry/qgsmultisurfacev2.cpp b/src/core/geometry/qgsmultisurfacev2.cpp
index b87e3a6..326f7aa 100644
--- a/src/core/geometry/qgsmultisurfacev2.cpp
+++ b/src/core/geometry/qgsmultisurfacev2.cpp
@@ -21,6 +21,7 @@ email : marco.hugentobler at sourcepole dot com
#include "qgslinestringv2.h"
#include "qgspolygonv2.h"
#include "qgscurvepolygonv2.h"
+#include "qgsmulticurvev2.h"
QgsMultiSurfaceV2::QgsMultiSurfaceV2()
: QgsGeometryCollectionV2()
@@ -132,3 +133,21 @@ bool QgsMultiSurfaceV2::addGeometry( QgsAbstractGeometryV2* g )
setZMTypeFromSubGeometry( g, QgsWKBTypes::MultiSurface );
return QgsGeometryCollectionV2::addGeometry( g );
}
+
+QgsAbstractGeometryV2* QgsMultiSurfaceV2::boundary() const
+{
+ QgsMultiCurveV2* multiCurve = new QgsMultiCurveV2();
+ for ( int i = 0; i < mGeometries.size(); ++i )
+ {
+ if ( QgsSurfaceV2* surface = dynamic_cast<QgsSurfaceV2*>( mGeometries.at( i ) ) )
+ {
+ multiCurve->addGeometry( surface->boundary() );
+ }
+ }
+ if ( multiCurve->numGeometries() == 0 )
+ {
+ delete multiCurve;
+ return nullptr;
+ }
+ return multiCurve;
+}
diff --git a/src/core/geometry/qgsmultisurfacev2.h b/src/core/geometry/qgsmultisurfacev2.h
index 40ea625..a675d62 100644
--- a/src/core/geometry/qgsmultisurfacev2.h
+++ b/src/core/geometry/qgsmultisurfacev2.h
@@ -43,6 +43,8 @@ class CORE_EXPORT QgsMultiSurfaceV2: public QgsGeometryCollectionV2
/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g ) override;
+
+ virtual QgsAbstractGeometryV2* boundary() const override;
};
#endif // QGSMULTISURFACEV2_H
diff --git a/src/core/geometry/qgspointv2.cpp b/src/core/geometry/qgspointv2.cpp
index 5327e80..a21fbb2 100644
--- a/src/core/geometry/qgspointv2.cpp
+++ b/src/core/geometry/qgspointv2.cpp
@@ -281,6 +281,11 @@ QgsCoordinateSequenceV2 QgsPointV2::coordinateSequence() const
return cs;
}
+QgsAbstractGeometryV2* QgsPointV2::boundary() const
+{
+ return nullptr;
+}
+
/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
* full unit tests.
@@ -306,11 +311,12 @@ bool QgsPointV2::moveVertex( QgsVertexId position, const QgsPointV2& newPos )
double QgsPointV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
{
+ Q_UNUSED( pt );
+ Q_UNUSED( segmentPt );
+ Q_UNUSED( vertexAfter );
Q_UNUSED( leftOf );
Q_UNUSED( epsilon );
- segmentPt = *this;
- vertexAfter = QgsVertexId( 0, 0, 0 );
- return QgsGeometryUtils::sqrDistance2D( *this, pt );
+ return -1; // no segments - return error
}
bool QgsPointV2::nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const
diff --git a/src/core/geometry/qgspointv2.h b/src/core/geometry/qgspointv2.h
index 4328a6d..286d16a 100644
--- a/src/core/geometry/qgspointv2.h
+++ b/src/core/geometry/qgspointv2.h
@@ -169,6 +169,7 @@ class CORE_EXPORT QgsPointV2: public QgsAbstractGeometryV2
bool transformZ = false ) override;
void transform( const QTransform& t ) override;
virtual QgsCoordinateSequenceV2 coordinateSequence() const override;
+ virtual QgsAbstractGeometryV2* boundary() const override;
//low-level editing
virtual bool insertVertex( QgsVertexId position, const QgsPointV2& vertex ) override { Q_UNUSED( position ); Q_UNUSED( vertex ); return false; }
diff --git a/src/core/geometry/qgspolygonv2.cpp b/src/core/geometry/qgspolygonv2.cpp
index 39fe7bc..5c9a3df 100644
--- a/src/core/geometry/qgspolygonv2.cpp
+++ b/src/core/geometry/qgspolygonv2.cpp
@@ -19,6 +19,7 @@
#include "qgsapplication.h"
#include "qgsgeometryutils.h"
#include "qgslinestringv2.h"
+#include "qgsmultilinestringv2.h"
#include "qgswkbptr.h"
QgsPolygonV2::QgsPolygonV2()
@@ -242,6 +243,28 @@ void QgsPolygonV2::setExteriorRing( QgsCurveV2* ring )
clearCache();
}
+QgsAbstractGeometryV2* QgsPolygonV2::boundary() const
+{
+ if ( !mExteriorRing )
+ return nullptr;
+
+ if ( mInteriorRings.isEmpty() )
+ {
+ return mExteriorRing->clone();
+ }
+ else
+ {
+ QgsMultiLineStringV2* multiLine = new QgsMultiLineStringV2();
+ multiLine->addGeometry( mExteriorRing->clone() );
+ int nInteriorRings = mInteriorRings.size();
+ for ( int i = 0; i < nInteriorRings; ++i )
+ {
+ multiLine->addGeometry( mInteriorRings.at( i )->clone() );
+ }
+ return multiLine;
+ }
+}
+
QgsPolygonV2* QgsPolygonV2::surfaceToPolygon() const
{
return clone();
diff --git a/src/core/geometry/qgspolygonv2.h b/src/core/geometry/qgspolygonv2.h
index 70417ff..e510092 100644
--- a/src/core/geometry/qgspolygonv2.h
+++ b/src/core/geometry/qgspolygonv2.h
@@ -59,5 +59,7 @@ class CORE_EXPORT QgsPolygonV2: public QgsCurvePolygonV2
//overridden to handle LineString25D rings
virtual void setExteriorRing( QgsCurveV2* ring ) override;
+ virtual QgsAbstractGeometryV2* boundary() const override;
+
};
#endif // QGSPOLYGONV2_H
diff --git a/src/core/layertree/qgslayertreemodel.cpp b/src/core/layertree/qgslayertreemodel.cpp
index 55b5edf..d283752 100644
--- a/src/core/layertree/qgslayertreemodel.cpp
+++ b/src/core/layertree/qgslayertreemodel.cpp
@@ -44,13 +44,20 @@ class EmbeddedWidgetLegendNode : public QgsLayerTreeModelLegendNode
EmbeddedWidgetLegendNode( QgsLayerTreeLayer* nodeL )
: QgsLayerTreeModelLegendNode( nodeL )
{
+ // we need a valid rule key to allow the model to build a tree out of legend nodes
+ // if that's possible (if there is a node without a rule key, building of tree is cancelled)
+ mRuleKey = "embedded-widget-" + QUuid::createUuid().toString();
}
virtual QVariant data( int role ) const override
{
- Q_UNUSED( role );
+ if ( role == RuleKeyRole )
+ return mRuleKey;
return QVariant();
}
+
+ private:
+ QString mRuleKey;
};
///@endcond
@@ -1101,7 +1108,7 @@ const QIcon& QgsLayerTreeModel::iconGroup()
static QIcon icon;
if ( icon.isNull() )
- icon = QgsApplication::getThemeIcon( "/mActionFolder.png" );
+ icon = QgsApplication::getThemeIcon( "/mActionFolder.svg" );
return icon;
}
@@ -1204,30 +1211,45 @@ void QgsLayerTreeModel::addLegendToLayer( QgsLayerTreeLayer* nodeL )
QList<QgsLayerTreeModelLegendNode*> filteredLstNew = filterLegendNodes( lstNew );
- bool hasOnlyEmbedded = filteredLstNew.count() == 1 && filteredLstNew[0]->isEmbeddedInParent();
-
Q_FOREACH ( QgsLayerTreeModelLegendNode* n, lstNew )
{
n->setParent( this );
connect( n, SIGNAL( dataChanged() ), this, SLOT( legendNodeDataChanged() ) );
}
- LayerLegendData data;
- data.originalNodes = lstNew;
- data.activeNodes = filteredLstNew;
- data.tree = nullptr;
+ // See if we have an embedded node - if we do, we will not use it among active nodes.
+ // Legend node embedded in parent does not have to be the first one,
+ // there can be also nodes generated for embedded widgets
+ QgsLayerTreeModelLegendNode* embeddedNode = nullptr;
+ Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, filteredLstNew )
+ {
+ if ( legendNode->isEmbeddedInParent() )
+ {
+ embeddedNode = legendNode;
+ filteredLstNew.removeOne( legendNode );
+ break;
+ }
+ }
+
+ LayerLegendTree* legendTree = nullptr;
// maybe the legend nodes form a tree - try to create a tree structure from the list
if ( testFlag( ShowLegendAsTree ) )
- tryBuildLegendTree( data );
+ legendTree = tryBuildLegendTree( filteredLstNew );
+
+ int count = legendTree ? legendTree->children[nullptr].count() : filteredLstNew.count();
- int count = data.tree ? data.tree->children[nullptr].count() : filteredLstNew.count();
+ if ( !filteredLstNew.isEmpty() ) beginInsertRows( node2index( nodeL ), 0, count - 1 );
- if ( ! hasOnlyEmbedded ) beginInsertRows( node2index( nodeL ), 0, count - 1 );
+ LayerLegendData data;
+ data.originalNodes = lstNew;
+ data.activeNodes = filteredLstNew;
+ data.embeddedNodeInParent = embeddedNode;
+ data.tree = legendTree;
mLegend[nodeL] = data;
- if ( ! hasOnlyEmbedded ) endInsertRows();
+ if ( !filteredLstNew.isEmpty() ) endInsertRows();
if ( hasStyleOverride )
ml->styleManager()->restoreOverrideStyle();
@@ -1238,11 +1260,11 @@ void QgsLayerTreeModel::addLegendToLayer( QgsLayerTreeLayer* nodeL )
}
-void QgsLayerTreeModel::tryBuildLegendTree( LayerLegendData& data )
+QgsLayerTreeModel::LayerLegendTree* QgsLayerTreeModel::tryBuildLegendTree( const QList<QgsLayerTreeModelLegendNode*>& nodes )
{
// first check whether there are any legend nodes that are not top-level
bool hasParentKeys = false;
- Q_FOREACH ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
+ Q_FOREACH ( QgsLayerTreeModelLegendNode* n, nodes )
{
if ( !n->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString().isEmpty() )
{
@@ -1251,30 +1273,31 @@ void QgsLayerTreeModel::tryBuildLegendTree( LayerLegendData& data )
}
}
if ( !hasParentKeys )
- return; // all legend nodes are top-level => stick with list representation
+ return nullptr; // all legend nodes are top-level => stick with list representation
// make mapping from rules to nodes and do some sanity checks
QHash<QString, QgsLayerTreeModelLegendNode*> rule2node;
rule2node[QString()] = nullptr;
- Q_FOREACH ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
+ Q_FOREACH ( QgsLayerTreeModelLegendNode* n, nodes )
{
QString ruleKey = n->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString();
if ( ruleKey.isEmpty() ) // in tree all nodes must have key
- return;
+ return nullptr;
if ( rule2node.contains( ruleKey ) ) // and they must be unique
- return;
+ return nullptr;
rule2node[ruleKey] = n;
}
// create the tree structure
- data.tree = new LayerLegendTree;
- Q_FOREACH ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
+ LayerLegendTree* tree = new LayerLegendTree;
+ Q_FOREACH ( QgsLayerTreeModelLegendNode* n, nodes )
{
QString parentRuleKey = n->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString();
QgsLayerTreeModelLegendNode* parent = rule2node.value( parentRuleKey, nullptr );
- data.tree->parents[n] = parent;
- data.tree->children[parent] << n;
+ tree->parents[n] = parent;
+ tree->children[parent] << n;
}
+ return tree;
}
@@ -1308,6 +1331,7 @@ QModelIndex QgsLayerTreeModel::legendNode2index( QgsLayerTreeModelLegendNode* le
int row = data.activeNodes.indexOf( legendNode );
if ( row < 0 ) // legend node may be filtered (exists within the list of original nodes, but not in active nodes)
return QModelIndex();
+
return index( row, 0, parentIndex );
}
@@ -1332,10 +1356,6 @@ int QgsLayerTreeModel::legendRootRowCount( QgsLayerTreeLayer* nL ) const
return data.tree->children[nullptr].count();
int count = data.activeNodes.count();
-
- if ( legendEmbeddedInParent( nL ) )
- count--; // one item less -- it is embedded in parent
-
return count;
}
@@ -1400,35 +1420,34 @@ Qt::ItemFlags QgsLayerTreeModel::legendNodeFlags( QgsLayerTreeModelLegendNode* n
bool QgsLayerTreeModel::legendEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const
{
- return legendNodeEmbeddedInParent( nodeLayer );
+ return mLegend[nodeLayer].embeddedNodeInParent != nullptr;
}
QgsLayerTreeModelLegendNode* QgsLayerTreeModel::legendNodeEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const
{
- // legend node embedded in parent does not have to be the first one...
- // there could be extra legend nodes generated for embedded widgets
- const LayerLegendData& data = mLegend[nodeLayer];
- Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, data.activeNodes )
- {
- if ( legendNode->isEmbeddedInParent() )
- return legendNode;
- }
- return nullptr;
+ return mLegend[nodeLayer].embeddedNodeInParent;
}
QIcon QgsLayerTreeModel::legendIconEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const
{
- QgsLayerTreeModelLegendNode* legendNode = legendNodeEmbeddedInParent( nodeLayer );
+ QgsLayerTreeModelLegendNode* legendNode = mLegend[nodeLayer].embeddedNodeInParent;
if ( !legendNode )
return QIcon();
return QIcon( qvariant_cast<QPixmap>( legendNode->data( Qt::DecorationRole ) ) );
}
-QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::layerLegendNodes( QgsLayerTreeLayer* nodeLayer )
+QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::layerLegendNodes( QgsLayerTreeLayer* nodeLayer, bool skipNodeEmbeddedInParent )
{
- return mLegend.value( nodeLayer ).activeNodes;
+ if ( !mLegend.contains( nodeLayer ) )
+ return QList<QgsLayerTreeModelLegendNode*>();
+
+ const LayerLegendData& data = mLegend[nodeLayer];
+ QList<QgsLayerTreeModelLegendNode*> lst( data.activeNodes );
+ if ( !skipNodeEmbeddedInParent && data.embeddedNodeInParent )
+ lst.prepend( data.embeddedNodeInParent );
+ return lst;
}
QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::layerOriginalLegendNodes( QgsLayerTreeLayer* nodeLayer )
diff --git a/src/core/layertree/qgslayertreemodel.h b/src/core/layertree/qgslayertreemodel.h
index 8088317..ee1cdee 100644
--- a/src/core/layertree/qgslayertreemodel.h
+++ b/src/core/layertree/qgslayertreemodel.h
@@ -119,15 +119,21 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
QModelIndex legendNode2index( QgsLayerTreeModelLegendNode* legendNode );
//! Return filtered list of active legend nodes attached to a particular layer node
+ //! (by default it returns also legend node embedded in parent layer node (if any) unless skipNodeEmbeddedInParent is true)
//! @note added in 2.6
+ //! @note skipNodeEmbeddedInParent added in 2.18
//! @see layerOriginalLegendNodes()
- QList<QgsLayerTreeModelLegendNode*> layerLegendNodes( QgsLayerTreeLayer* nodeLayer );
+ QList<QgsLayerTreeModelLegendNode*> layerLegendNodes( QgsLayerTreeLayer* nodeLayer, bool skipNodeEmbeddedInParent = false );
//! Return original (unfiltered) list of legend nodes attached to a particular layer node
//! @note added in 2.14
//! @see layerLegendNodes()
QList<QgsLayerTreeModelLegendNode*> layerOriginalLegendNodes( QgsLayerTreeLayer* nodeLayer );
+ //! Return legend node that may be embbeded in parent (i.e. its icon will be used for layer's icon).
+ //! @note added in 2.18
+ QgsLayerTreeModelLegendNode* legendNodeEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const;
+
/** Searches through the layer tree to find a legend node with a matching layer ID
* and rule key.
* @param layerId map layer ID
@@ -277,8 +283,6 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
QVariant legendNodeData( QgsLayerTreeModelLegendNode* node, int role ) const;
Qt::ItemFlags legendNodeFlags( QgsLayerTreeModelLegendNode* node ) const;
bool legendEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const;
- /** Return legend node that may be embbeded in parent (i.e. its icon will be used for layer's icon). */
- QgsLayerTreeModelLegendNode* legendNodeEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const;
QIcon legendIconEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const;
void legendCleanup();
void legendInvalidateMapBasedData();
@@ -311,9 +315,19 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
//! @note not available in Python bindings
struct LayerLegendData
{
+ LayerLegendData()
+ : embeddedNodeInParent( nullptr )
+ , tree( nullptr )
+ {
+ }
+
//! Active legend nodes. May have been filtered.
//! Owner of legend nodes is still originalNodes !
QList<QgsLayerTreeModelLegendNode*> activeNodes;
+ //! A legend node that is not displayed separately, its icon is instead
+ //! shown within the layer node's item.
+ //! May be null. if non-null, node is owned by originalNodes !
+ QgsLayerTreeModelLegendNode* embeddedNodeInParent;
//! Data structure for storage of legend nodes.
//! These are nodes as received from QgsMapLayerLegend
QList<QgsLayerTreeModelLegendNode*> originalNodes;
@@ -322,7 +336,7 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
};
//! @note not available in Python bindings
- void tryBuildLegendTree( LayerLegendData& data );
+ LayerLegendTree* tryBuildLegendTree( const QList<QgsLayerTreeModelLegendNode*>& nodes );
//! Overrides of map layers' styles: key = layer ID, value = style XML.
//! This allows to show legend that is different from the current style of layers
diff --git a/src/core/layertree/qgslayertreemodellegendnode.cpp b/src/core/layertree/qgslayertreemodellegendnode.cpp
index d38d3b1..d88d501 100644
--- a/src/core/layertree/qgslayertreemodellegendnode.cpp
+++ b/src/core/layertree/qgslayertreemodellegendnode.cpp
@@ -109,9 +109,9 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings& set
// Vertical alignment of label with symbol
if ( labelSize.height() < symbolSize.height() )
- labelY += symbolSize.height() / 2 + textHeight / 2; // label centered with symbol
- else
- labelY += textHeight; // label starts at top and runs under symbol
+ labelY += symbolSize.height() / 2 - labelSize.height() / 2; // label centered with symbol
+
+ labelY += textHeight;
}
for ( QStringList::Iterator itemPart = lines.begin(); itemPart != lines.end(); ++itemPart )
diff --git a/src/core/pal/feature.cpp b/src/core/pal/feature.cpp
index 8473231..266adf1 100644
--- a/src/core/pal/feature.cpp
+++ b/src/core/pal/feature.cpp
@@ -39,6 +39,7 @@
#include "qgsgeos.h"
#include "qgsmessagelog.h"
#include "costcalculator.h"
+#include "qgsgeometryutils.h"
#include <QLinkedList>
#include <cmath>
#include <cfloat>
@@ -585,168 +586,387 @@ int FeaturePart::createCandidatesAroundPoint( double x, double y, QList< LabelPo
return candidates.count();
}
-// TODO work with squared distance by removing call to sqrt or dist_euc2d
int FeaturePart::createCandidatesAlongLine( QList< LabelPosition* >& lPos, PointSet *mapShape )
{
- int i;
- double distlabel = getLabelDistance();
-
- double xrm = getLabelWidth();
- double yrm = getLabelHeight();
-
- double *d; // segments lengths distance bw pt[i] && pt[i+1]
- double *ad; // absolute distance bw pt[0] and pt[i] along the line
- double ll; // line length
- double dist;
- double bx, by, ex, ey;
- int nbls;
- double alpha;
- double cost;
+ //prefer to label along straightish segments:
+ int candidates = createCandidatesAlongLineNearStraightSegments( lPos, mapShape );
+
+ if ( candidates < mLF->layer()->pal->line_p )
+ {
+ // but not enough candidates yet, so fallback to labeling near whole line's midpoint
+ candidates = createCandidatesAlongLineNearMidpoint( lPos, mapShape, candidates > 0 ? 0.01 : 0.0 );
+ }
+ return candidates;
+}
+int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosition*>& lPos, PointSet* mapShape )
+{
+ double labelWidth = getLabelWidth();
+ double labelHeight = getLabelHeight();
+ double distanceLineToLabel = getLabelDistance();
LineArrangementFlags flags = mLF->layer()->arrangementFlags();
if ( flags == 0 )
flags = FLAG_ON_LINE; // default flag
- QLinkedList<LabelPosition*> positions;
+ // first scan through the whole line and look for segments where the angle at a node is greater than 45 degrees - these form a "hard break" which labels shouldn't cross over
+ QVector< int > extremeAngleNodes;
+ PointSet * line = mapShape;
+ int numberNodes = line->nbPoints;
+ double *x = line->x;
+ double *y = line->y;
+
+ // closed line? if so, we need to handle the final node angle
+ bool closedLine = qgsDoubleNear( x[0], x[ numberNodes - 1] ) && qgsDoubleNear( y[0], y[numberNodes - 1 ] );
+ for ( int i = 1; i <= numberNodes - ( closedLine ? 1 : 2 ); ++i )
+ {
+ double x1 = x[i-1];
+ double x2 = x[i];
+ double x3 = x[ i == numberNodes - 1 ? 1 : i+1]; // wraparound for closed linestrings
+ double y1 = y[i-1];
+ double y2 = y[i];
+ double y3 = y[ i == numberNodes - 1 ? 1 : i+1]; // wraparound for closed linestrings
+ if ( qgsDoubleNear( y2, y3 ) && qgsDoubleNear( x2, x3 ) )
+ continue;
+ if ( qgsDoubleNear( y1, y2 ) && qgsDoubleNear( x1, x2 ) )
+ continue;
+ double vertexAngle = M_PI - ( atan2( y3 - y2, x3 - x2 ) - atan2( y2 - y1, x2 - x1 ) );
+ vertexAngle = QgsGeometryUtils::normalizedAngle( vertexAngle );
+
+ // extreme angles form more than 45 degree angle at a node - these are the ones we don't want labels to cross
+ if ( vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0 )
+ extremeAngleNodes << i;
+ }
+ extremeAngleNodes << numberNodes - 1;
+
+ if ( extremeAngleNodes.isEmpty() )
+ {
+ // no extreme angles - createCandidatesAlongLineNearMidpoint will be more appropriate
+ return 0;
+ }
+
+ // calculate lengths of segments, and work out longest straight-ish segment
+ double* segmentLengths = new double[ numberNodes-1 ]; // segments lengths distance bw pt[i] && pt[i+1]
+ double* distanceToSegment = new double[ numberNodes ]; // absolute distance bw pt[0] and pt[i] along the line
+ double totalLineLength = 0.0;
+ QVector< double > straightSegmentLengths;
+ QVector< double > straightSegmentAngles;
+ straightSegmentLengths.reserve( extremeAngleNodes.size() + 1 );
+ straightSegmentAngles.reserve( extremeAngleNodes.size() + 1 );
+ double currentStraightSegmentLength = 0;
+ double longestSegmentLength = 0;
+ int segmentIndex = 0;
+ double segmentStartX = x[0];
+ double segmentStartY = y[0];
+ for ( int i = 0; i < numberNodes - 1; i++ )
+ {
+ if ( i == 0 )
+ distanceToSegment[i] = 0;
+ else
+ distanceToSegment[i] = distanceToSegment[i-1] + segmentLengths[i-1];
+
+ segmentLengths[i] = GeomFunction::dist_euc2d( x[i], y[i], x[i+1], y[i+1] );
+ totalLineLength += segmentLengths[i];
+ if ( extremeAngleNodes.contains( i ) )
+ {
+ // at an extreme angle node, so reset counters
+ straightSegmentLengths << currentStraightSegmentLength;
+ straightSegmentAngles << QgsGeometryUtils::normalizedAngle( atan2( y[i] - segmentStartY, x[i] - segmentStartX ) );
+ longestSegmentLength = qMax( longestSegmentLength, currentStraightSegmentLength );
+ segmentIndex++;
+ currentStraightSegmentLength = 0;
+ segmentStartX = x[i];
+ segmentStartY = y[i];
+ }
+ currentStraightSegmentLength += segmentLengths[i];
+ }
+ distanceToSegment[line->nbPoints-1] = totalLineLength;
+ straightSegmentLengths << currentStraightSegmentLength;
+ straightSegmentAngles << QgsGeometryUtils::normalizedAngle( atan2( y[numberNodes-1] - segmentStartY, x[numberNodes-1] - segmentStartX ) );
+ longestSegmentLength = qMax( longestSegmentLength, currentStraightSegmentLength );
+ double middleOfLine = totalLineLength / 2.0;
+
+ if ( totalLineLength < labelWidth )
+ {
+ delete[] segmentLengths;
+ delete[] distanceToSegment;
+ return 0; //createCandidatesAlongLineNearMidpoint will be more appropriate
+ }
+
+ double lineStepDistance = ( totalLineLength - labelWidth ); // distance to move along line with each candidate
+ lineStepDistance = qMin( qMin( labelHeight, labelWidth ), lineStepDistance / mLF->layer()->pal->line_p );
+
+ double distanceToEndOfSegment = 0.0;
+ int lastNodeInSegment = 0;
+ // finally, loop through all these straight segments. For each we create candidates along the straight segment.
+ for ( int i = 0; i < straightSegmentLengths.count(); ++i )
+ {
+ currentStraightSegmentLength = straightSegmentLengths.at( i );
+ double currentSegmentAngle = straightSegmentAngles.at( i );
+ lastNodeInSegment = extremeAngleNodes.at( i );
+ double distanceToStartOfSegment = distanceToEndOfSegment;
+ distanceToEndOfSegment = distanceToSegment[ lastNodeInSegment ];
+ double distanceToCenterOfSegment = 0.5 * ( distanceToEndOfSegment + distanceToStartOfSegment );
+
+ if ( currentStraightSegmentLength < labelWidth )
+ // can't fit a label on here
+ continue;
+
+ double currentDistanceAlongLine = distanceToStartOfSegment;
+ double candidateStartX, candidateStartY, candidateEndX, candidateEndY;
+ double candidateLength = 0.0;
+ double cost = 0.0;
+ double angle = 0.0;
+ double beta = 0.0;
+
+ //calculate some cost penalties
+ double segmentCost = 1.0 - ( distanceToEndOfSegment - distanceToStartOfSegment ) / longestSegmentLength; // 0 -> 1 (lower for longer segments)
+ double segmentAngleCost = 1 - qAbs( fmod( currentSegmentAngle, M_PI ) - M_PI_2 ) / M_PI_2; // 0 -> 1, lower for more horizontal segments
+
+ while ( currentDistanceAlongLine + labelWidth < distanceToEndOfSegment )
+ {
+ // calculate positions along linestring corresponding to start and end of current label candidate
+ line->getPointByDistance( segmentLengths, distanceToSegment, currentDistanceAlongLine, &candidateStartX, &candidateStartY );
+ line->getPointByDistance( segmentLengths, distanceToSegment, currentDistanceAlongLine + labelWidth, &candidateEndX, &candidateEndY );
+
+ candidateLength = sqrt(( candidateEndX - candidateStartX ) * ( candidateEndX - candidateStartX ) + ( candidateEndY - candidateStartY ) * ( candidateEndY - candidateStartY ) );
+
+
+ // LOTS OF DIFFERENT COSTS TO BALANCE HERE - feel free to tweak these, but please add a unit test
+ // which covers the situation you are adjusting for (eg "given equal length lines, choose the more horizontal line")
+
+ cost = candidateLength / labelWidth;
+ if ( cost > 0.98 )
+ cost = 0.0001;
+ else
+ {
+ // jaggy line has a greater cost
+ cost = ( 1 - cost ) / 100; // ranges from 0.0001 to 0.01 (however a cost 0.005 is already a lot!)
+ }
+
+ // penalize positions which are further from the straight segments's midpoint
+ double labelCenter = currentDistanceAlongLine + labelWidth / 2.0;
+ double costCenter = 2 * qAbs( labelCenter - distanceToCenterOfSegment ) / ( distanceToEndOfSegment - distanceToStartOfSegment ); // 0 -> 1
+ cost += costCenter * 0.0005; // < 0, 0.0005 >
+
+ if ( !closedLine )
+ {
+ // penalize positions which are further from absolute center of whole linestring
+ // this only applies to non closed linestrings, since the middle of a closed linestring is effectively arbitrary
+ // and irrelevant to labeling
+ double costLineCenter = 2 * qAbs( labelCenter - middleOfLine ) / totalLineLength; // 0 -> 1
+ cost += costLineCenter * 0.0005; // < 0, 0.0005 >
+ }
+
+ cost += segmentCost * 0.0005; // prefer labels on longer straight segments
+ cost += segmentAngleCost * 0.0001; // prefer more horizontal segments, but this is less important than length considerations
+
+ if ( qgsDoubleNear( candidateEndY, candidateStartY ) && qgsDoubleNear( candidateEndX, candidateStartX ) )
+ {
+ angle = 0.0;
+ }
+ else
+ angle = atan2( candidateEndY - candidateStartY, candidateEndX - candidateStartX );
- int nbPoints;
- double *x;
- double *y;
+ beta = angle + M_PI / 2;
+
+ if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Line )
+ {
+ // find out whether the line direction for this candidate is from right to left
+ bool isRightToLeft = ( angle > M_PI / 2 || angle <= -M_PI / 2 );
+ // meaning of above/below may be reversed if using map orientation and the line has right-to-left direction
+ bool reversed = (( flags & FLAG_MAP_ORIENTATION ) ? isRightToLeft : false );
+ bool aboveLine = ( !reversed && ( flags & FLAG_ABOVE_LINE ) ) || ( reversed && ( flags & FLAG_BELOW_LINE ) );
+ bool belowLine = ( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) );
+
+ double placementCost = 0.0;
+ if ( belowLine )
+ {
+ if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - cos( beta ) *( distanceLineToLabel + labelHeight ), candidateStartY - sin( beta ) *( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle ) )
+ {
+ lPos.append( new LabelPosition( i, candidateStartX - cos( beta ) *( distanceLineToLabel + labelHeight ), candidateStartY - sin( beta ) *( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, cost + placementCost, this, isRightToLeft ) ); // Line
+ placementCost += 0.001;
+ }
+ }
+ if ( aboveLine )
+ {
+ if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX + cos( beta ) *distanceLineToLabel, candidateStartY + sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle ) )
+ {
+ lPos.append( new LabelPosition( i, candidateStartX + cos( beta ) *distanceLineToLabel, candidateStartY + sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, cost + placementCost, this, isRightToLeft ) ); // Line
+ placementCost += 0.001;
+ }
+ }
+ if ( flags & FLAG_ON_LINE )
+ {
+ if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - labelHeight*cos( beta ) / 2, candidateStartY - labelHeight*sin( beta ) / 2, labelWidth, labelHeight, angle ) )
+ lPos.append( new LabelPosition( i, candidateStartX - labelHeight*cos( beta ) / 2, candidateStartY - labelHeight*sin( beta ) / 2, labelWidth, labelHeight, angle, cost + placementCost, this, isRightToLeft ) ); // Line
+ }
+ }
+ else if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Horizontal )
+ {
+ lPos.append( new LabelPosition( i, candidateStartX - labelWidth / 2, candidateStartY - labelHeight / 2, labelWidth, labelHeight, 0, cost, this ) ); // Line
+ }
+ else
+ {
+ // an invalid arrangement?
+ }
+
+ currentDistanceAlongLine += lineStepDistance;
+ }
+ }
+
+ delete[] segmentLengths;
+ delete[] distanceToSegment;
+ return lPos.size();
+}
+
+int FeaturePart::createCandidatesAlongLineNearMidpoint( QList<LabelPosition*>& lPos, PointSet* mapShape, double initialCost )
+{
+ double distanceLineToLabel = getLabelDistance();
+
+ double labelWidth = getLabelWidth();
+ double labelHeight = getLabelHeight();
+
+ double angle;
+ double cost;
+
+ LineArrangementFlags flags = mLF->layer()->arrangementFlags();
+ if ( flags == 0 )
+ flags = FLAG_ON_LINE; // default flag
+
+ QList<LabelPosition*> positions;
PointSet * line = mapShape;
- nbPoints = line->nbPoints;
- x = line->x;
- y = line->y;
+ int nbPoints = line->nbPoints;
+ double *x = line->x;
+ double *y = line->y;
- d = new double[nbPoints-1];
- ad = new double[nbPoints];
+ double* segmentLengths = new double[nbPoints-1]; // segments lengths distance bw pt[i] && pt[i+1]
+ double* distanceToSegment = new double[nbPoints]; // absolute distance bw pt[0] and pt[i] along the line
- ll = 0.0; // line length
- for ( i = 0; i < line->nbPoints - 1; i++ )
+ double totalLineLength = 0.0; // line length
+ for ( int i = 0; i < line->nbPoints - 1; i++ )
{
if ( i == 0 )
- ad[i] = 0;
+ distanceToSegment[i] = 0;
else
- ad[i] = ad[i-1] + d[i-1];
+ distanceToSegment[i] = distanceToSegment[i-1] + segmentLengths[i-1];
- d[i] = GeomFunction::dist_euc2d( x[i], y[i], x[i+1], y[i+1] );
- ll += d[i];
+ segmentLengths[i] = GeomFunction::dist_euc2d( x[i], y[i], x[i+1], y[i+1] );
+ totalLineLength += segmentLengths[i];
}
+ distanceToSegment[line->nbPoints-1] = totalLineLength;
- ad[line->nbPoints-1] = ll;
-
- nbls = static_cast< int >( ll / xrm ); // ratio bw line length and label width
- dist = ( ll - xrm );
- double l;
+ double lineStepDistance = ( totalLineLength - labelWidth ); // distance to move along line with each candidate
+ double currentDistanceAlongLine = 0;
- if ( nbls > 0 )
+ if ( totalLineLength > labelWidth )
{
- //dist /= nbls;
- l = 0;
- dist = qMin( yrm, xrm );
+ lineStepDistance = qMin( qMin( labelHeight, labelWidth ), lineStepDistance / mLF->layer()->pal->line_p );
}
- else // line length < label with => centering label position
+ else // line length < label width => centering label position
{
- l = - ( xrm - ll ) / 2.0;
- dist = xrm;
- ll = xrm;
+ currentDistanceAlongLine = - ( labelWidth - totalLineLength ) / 2.0;
+ lineStepDistance = -1;
+ totalLineLength = labelWidth;
}
- double birdfly;
+ double candidateLength;
double beta;
- i = 0;
- while ( l < ll - xrm )
+ double candidateStartX, candidateStartY, candidateEndX, candidateEndY;
+ int i = 0;
+ while ( currentDistanceAlongLine < totalLineLength - labelWidth )
{
- // => bx, by
- line->getPointByDistance( d, ad, l, &bx, &by );
- // same but l = l+xrm
- line->getPointByDistance( d, ad, l + xrm, &ex, &ey );
-
- // Label is bigger than line ...
- if ( l < 0 )
- birdfly = sqrt(( x[nbPoints-1] - x[0] ) * ( x[nbPoints-1] - x[0] )
- + ( y[nbPoints-1] - y[0] ) * ( y[nbPoints-1] - y[0] ) );
+ // calculate positions along linestring corresponding to start and end of current label candidate
+ line->getPointByDistance( segmentLengths, distanceToSegment, currentDistanceAlongLine, &candidateStartX, &candidateStartY );
+ line->getPointByDistance( segmentLengths, distanceToSegment, currentDistanceAlongLine + labelWidth, &candidateEndX, &candidateEndY );
+
+ if ( currentDistanceAlongLine < 0 )
+ {
+ // label is bigger than line, use whole available line
+ candidateLength = sqrt(( x[nbPoints-1] - x[0] ) * ( x[nbPoints-1] - x[0] )
+ + ( y[nbPoints-1] - y[0] ) * ( y[nbPoints-1] - y[0] ) );
+ }
else
- birdfly = sqrt(( ex - bx ) * ( ex - bx ) + ( ey - by ) * ( ey - by ) );
+ {
+ candidateLength = sqrt(( candidateEndX - candidateStartX ) * ( candidateEndX - candidateStartX ) + ( candidateEndY - candidateStartY ) * ( candidateEndY - candidateStartY ) );
+ }
- cost = birdfly / xrm;
+ cost = candidateLength / labelWidth;
if ( cost > 0.98 )
cost = 0.0001;
else
- cost = ( 1 - cost ) / 100; // < 0.0001, 0.01 > (but 0.005 is already pretty much)
+ {
+ // jaggy line has a greater cost
+ cost = ( 1 - cost ) / 100; // ranges from 0.0001 to 0.01 (however a cost 0.005 is already a lot!)
+ }
// penalize positions which are further from the line's midpoint
- double costCenter = qAbs( ll / 2 - ( l + xrm / 2 ) ) / ll; // <0, 0.5>
+ double costCenter = qAbs( totalLineLength / 2 - ( currentDistanceAlongLine + labelWidth / 2 ) ) / totalLineLength; // <0, 0.5>
cost += costCenter / 1000; // < 0, 0.0005 >
+ cost += initialCost;
- if ( qgsDoubleNear( ey, by ) && qgsDoubleNear( ex, bx ) )
+ if ( qgsDoubleNear( candidateEndY, candidateStartY ) && qgsDoubleNear( candidateEndX, candidateStartX ) )
{
- alpha = 0.0;
+ angle = 0.0;
}
else
- alpha = atan2( ey - by, ex - bx );
+ angle = atan2( candidateEndY - candidateStartY, candidateEndX - candidateStartX );
- beta = alpha + M_PI / 2;
+ beta = angle + M_PI / 2;
if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Line )
{
// find out whether the line direction for this candidate is from right to left
- bool isRightToLeft = ( alpha > M_PI / 2 || alpha <= -M_PI / 2 );
- // meaning of above/below may be reversed if using line position dependent orientation
- // and the line has right-to-left direction
+ bool isRightToLeft = ( angle > M_PI / 2 || angle <= -M_PI / 2 );
+ // meaning of above/below may be reversed if using map orientation and the line has right-to-left direction
bool reversed = (( flags & FLAG_MAP_ORIENTATION ) ? isRightToLeft : false );
bool aboveLine = ( !reversed && ( flags & FLAG_ABOVE_LINE ) ) || ( reversed && ( flags & FLAG_BELOW_LINE ) );
bool belowLine = ( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) );
if ( aboveLine )
{
- if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), bx + cos( beta ) *distlabel, by + sin( beta ) *distlabel, xrm, yrm, alpha ) )
- positions.append( new LabelPosition( i, bx + cos( beta ) *distlabel, by + sin( beta ) *distlabel, xrm, yrm, alpha, cost, this, isRightToLeft ) ); // Line
+ if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX + cos( beta ) *distanceLineToLabel, candidateStartY + sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle ) )
+ positions.append( new LabelPosition( i, candidateStartX + cos( beta ) *distanceLineToLabel, candidateStartY + sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, cost, this, isRightToLeft ) ); // Line
}
if ( belowLine )
{
- if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), bx - cos( beta ) *( distlabel + yrm ), by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha ) )
- positions.append( new LabelPosition( i, bx - cos( beta ) *( distlabel + yrm ), by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha, cost, this, isRightToLeft ) ); // Line
+ if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - cos( beta ) *( distanceLineToLabel + labelHeight ), candidateStartY - sin( beta ) *( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle ) )
+ positions.append( new LabelPosition( i, candidateStartX - cos( beta ) *( distanceLineToLabel + labelHeight ), candidateStartY - sin( beta ) *( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, cost, this, isRightToLeft ) ); // Line
}
if ( flags & FLAG_ON_LINE )
{
- if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha ) )
- positions.append( new LabelPosition( i, bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha, cost, this, isRightToLeft ) ); // Line
+ if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - labelHeight*cos( beta ) / 2, candidateStartY - labelHeight*sin( beta ) / 2, labelWidth, labelHeight, angle ) )
+ positions.append( new LabelPosition( i, candidateStartX - labelHeight*cos( beta ) / 2, candidateStartY - labelHeight*sin( beta ) / 2, labelWidth, labelHeight, angle, cost, this, isRightToLeft ) ); // Line
}
}
else if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Horizontal )
{
- positions.append( new LabelPosition( i, bx - xrm / 2, by - yrm / 2, xrm, yrm, 0, cost, this ) ); // Line
+ positions.append( new LabelPosition( i, candidateStartX - labelWidth / 2, candidateStartY - labelHeight / 2, labelWidth, labelHeight, 0, cost, this ) ); // Line
}
else
{
// an invalid arrangement?
}
- l += dist;
+ currentDistanceAlongLine += lineStepDistance;
i++;
- if ( nbls == 0 )
+ if ( lineStepDistance < 0 )
break;
}
//delete line;
- delete[] d;
- delete[] ad;
+ delete[] segmentLengths;
+ delete[] distanceToSegment;
- int nbp = positions.size();
- while ( !positions.isEmpty() )
- {
- lPos << positions.takeFirst();
- }
-
- return nbp;
+ lPos.append( positions );
+ return lPos.size();
}
-LabelPosition* FeaturePart::curvedPlacementAtOffset( PointSet* path_positions, double* path_distances, int orientation, int index, double distance )
+LabelPosition* FeaturePart::curvedPlacementAtOffset( PointSet* path_positions, double* path_distances, int& orientation, int index, double distance, bool& reversed, bool& flip )
{
// Check that the given distance is on the given index and find the correct index and distance if not
while ( distance < 0 && index > 1 )
@@ -773,19 +993,7 @@ LabelPosition* FeaturePart::curvedPlacementAtOffset( PointSet* path_positions, d
LabelInfo* li = mLF->curvedLabelInfo();
- // Keep track of the initial index,distance incase we need to re-call get_placement_offset
- int initial_index = index;
- double initial_distance = distance;
-
double string_height = li->label_height;
- double old_x = path_positions->x[index-1];
- double old_y = path_positions->y[index-1];
-
- double new_x = path_positions->x[index];
- double new_y = path_positions->y[index];
-
- double dx = new_x - old_x;
- double dy = new_y - old_y;
double segment_length = path_distances[index];
if ( qgsDoubleNear( segment_length, 0.0 ) )
@@ -794,16 +1002,56 @@ LabelPosition* FeaturePart::curvedPlacementAtOffset( PointSet* path_positions, d
return nullptr;
}
+ if ( orientation == 0 ) // Must be map orientation
+ {
+ // Calculate the orientation based on the angle of the path segment under consideration
+
+ double _distance = distance;
+ int endindex = index;
+
+ for ( int i = 0; i < li->char_num; i++ )
+ {
+ LabelInfo::CharacterInfo& ci = li->char_info[i];
+ double start_x, start_y, end_x, end_y;
+ if ( nextCharPosition( ci.width, path_distances[index], path_positions, endindex, _distance, start_x, start_y, end_x, end_y ) == false )
+ {
+ return nullptr;
+ }
+ }
+
+ // Determine the angle of the path segment under consideration
+ double dx = path_positions->x[endindex] - path_positions->x[index];
+ double dy = path_positions->y[endindex] - path_positions->y[index];
+ double line_angle = atan2( -dy, dx );
+
+ bool isRightToLeft = ( line_angle > 0.55 * M_PI || line_angle < -0.45 * M_PI );
+ reversed = isRightToLeft;
+ orientation = isRightToLeft ? -1 : 1;
+ }
+
+ if ( !showUprightLabels() )
+ {
+ if ( orientation < 0 )
+ {
+ flip = true; // Report to the caller, that the orientation is flipped
+ reversed = !reversed;
+ orientation = 1;
+ }
+ }
+
LabelPosition* slp = nullptr;
LabelPosition* slp_tmp = nullptr;
- // current_placement = placement_result()
- double angle = atan2( -dy, dx );
- bool orientation_forced = ( orientation != 0 ); // Whether the orientation was set by the caller
- if ( !orientation_forced )
- orientation = ( angle > 0.55 * M_PI || angle < -0.45 * M_PI ? -1 : 1 );
+ double old_x = path_positions->x[index-1];
+ double old_y = path_positions->y[index-1];
+
+ double new_x = path_positions->x[index];
+ double new_y = path_positions->y[index];
+
+ double dx = new_x - old_x;
+ double dy = new_y - old_y;
- int upside_down_char_count = 0; // Count of characters that are placed upside down.
+ double angle = atan2( -dy, dx );
for ( int i = 0; i < li->char_num; i++ )
{
@@ -811,60 +1059,15 @@ LabelPosition* FeaturePart::curvedPlacementAtOffset( PointSet* path_positions, d
// grab the next character according to the orientation
LabelInfo::CharacterInfo& ci = ( orientation > 0 ? li->char_info[i] : li->char_info[li->char_num-i-1] );
-
- // Coordinates this character will start at
- if ( qgsDoubleNear( segment_length, 0.0 ) )
+ double start_x, start_y, end_x, end_y;
+ if ( nextCharPosition( ci.width, path_distances[index], path_positions, index, distance, start_x, start_y, end_x, end_y ) == false )
{
- // Not allowed to place across on 0 length segments or discontinuities
delete slp;
return nullptr;
}
- double start_x = old_x + dx * distance / segment_length;
- double start_y = old_y + dy * distance / segment_length;
- // Coordinates this character ends at, calculated below
- double end_x = 0;
- double end_y = 0;
-
- if ( segment_length - distance >= ci.width )
- {
- // if the distance remaining in this segment is enough, we just go further along the segment
- distance += ci.width;
- end_x = old_x + dx * distance / segment_length;
- end_y = old_y + dy * distance / segment_length;
- }
- else
- {
- // If there isn't enough distance left on this segment
- // then we need to search until we find the line segment that ends further than ci.width away
- do
- {
- old_x = new_x;
- old_y = new_y;
- index++;
- if ( index >= path_positions->nbPoints ) // Bail out if we run off the end of the shape
- {
- delete slp;
- return nullptr;
- }
- new_x = path_positions->x[index];
- new_y = path_positions->y[index];
- dx = new_x - old_x;
- dy = new_y - old_y;
- segment_length = path_distances[index];
- }
- while ( sqrt( pow( start_x - new_x, 2 ) + pow( start_y - new_y, 2 ) ) < ci.width ); // Distance from start_ to new_
-
- // Calculate the position to place the end of the character on
- GeomFunction::findLineCircleIntersection( start_x, start_y, ci.width, old_x, old_y, new_x, new_y, end_x, end_y );
-
- // Need to calculate distance on the new segment
- distance = sqrt( pow( old_x - end_x, 2 ) + pow( old_y - end_y, 2 ) );
- }
-
// Calculate angle from the start of the character to the end based on start_/end_ position
angle = atan2( start_y - end_y, end_x - start_x );
- //angle = atan2(end_y-start_y, end_x-start_x);
// Test last_character_angle vs angle
// since our rendering angle has changed then check against our
@@ -886,7 +1089,10 @@ LabelPosition* FeaturePart::curvedPlacementAtOffset( PointSet* path_positions, d
// and we're calculating the mean line here
double dist = 0.9 * li->label_height / 2;
if ( orientation < 0 )
+ {
dist = -dist;
+ flip = true;
+ }
start_x += dist * cos( angle + M_PI_2 );
start_y -= dist * sin( angle + M_PI_2 );
@@ -915,36 +1121,15 @@ LabelPosition* FeaturePart::curvedPlacementAtOffset( PointSet* path_positions, d
slp_tmp->setNextPart( tmp );
slp_tmp = tmp;
- //current_placement.add_node(ci.character,render_x, -render_y, render_angle);
- //current_placement.add_node(ci.character,render_x - current_placement.starting_x, render_y - current_placement.starting_y, render_angle)
-
// Normalise to 0 <= angle < 2PI
- while ( render_angle >= 2*M_PI ) render_angle -= 2 * M_PI;
+ while ( render_angle >= 2 * M_PI ) render_angle -= 2 * M_PI;
while ( render_angle < 0 ) render_angle += 2 * M_PI;
- if ( render_angle > M_PI / 2 && render_angle < 1.5*M_PI )
- upside_down_char_count++;
+ if ( render_angle > M_PI / 2 && render_angle < 1.5 * M_PI )
+ slp->incrementUpsideDownCharCount();
}
// END FOR
- // If we placed too many characters upside down
- if ( upside_down_char_count >= li->char_num / 2.0 )
- {
- // if we auto-detected the orientation then retry with the opposite orientation
- if ( !orientation_forced )
- {
- orientation = -orientation;
- delete slp;
- slp = curvedPlacementAtOffset( path_positions, path_distances, orientation, initial_index, initial_distance );
- }
- else
- {
- // Otherwise we have failed to find a placement
- delete slp;
- return nullptr;
- }
- }
-
return slp;
}
@@ -985,106 +1170,120 @@ int FeaturePart::createCurvedCandidatesAlongLine( QList< LabelPosition* >& lPos,
return 0;
}
- //calculate overall angle of line
- double lineAngle;
- double bx = mapShape->x[0];
- double by = mapShape->y[0];
- double ex = mapShape->x[ mapShape->nbPoints - 1 ];
- double ey = mapShape->y[ mapShape->nbPoints - 1 ];
- if ( qgsDoubleNear( ey, by ) && qgsDoubleNear( ex, bx ) )
- {
- lineAngle = 0.0;
- }
- else
- lineAngle = atan2( ey - by, ex - bx );
-
- // find out whether the line direction for this candidate is from right to left
- bool isRightToLeft = ( lineAngle > M_PI / 2 || lineAngle <= -M_PI / 2 );
-
QLinkedList<LabelPosition*> positions;
- double delta = qMax( li->label_height, total_distance / 10.0 );
+ double delta = qMax( li->label_height, total_distance / mLF->layer()->pal->line_p );
unsigned long flags = mLF->layer()->arrangementFlags();
if ( flags == 0 )
flags = FLAG_ON_LINE; // default flag
- // placements may need to be reversed if using line position dependent orientation
- // and the line has right-to-left direction
- bool reversed = ( !( flags & FLAG_MAP_ORIENTATION ) ? isRightToLeft : false );
// generate curved labels
- for ( int i = 0; i*delta < total_distance; i++ )
+ for ( double i = 0; i < total_distance; i += delta )
{
- LabelPosition* slp = curvedPlacementAtOffset( mapShape, path_distances, 0, 1, i * delta );
+ bool flip = false;
+ // placements may need to be reversed if using map orientation and the line has right-to-left direction
+ bool reversed = false;
- if ( slp )
+ // an orientation of 0 means try both orientations and choose the best
+ int orientation = 0;
+ if ( !( flags & FLAG_MAP_ORIENTATION ) )
{
- // evaluate cost
- double angle_diff = 0.0, angle_last = 0.0, diff;
- LabelPosition* tmp = slp;
- double sin_avg = 0, cos_avg = 0;
- while ( tmp )
- {
- if ( tmp != slp ) // not first?
- {
- diff = fabs( tmp->getAlpha() - angle_last );
- if ( diff > 2*M_PI ) diff -= 2 * M_PI;
- diff = qMin( diff, 2 * M_PI - diff ); // difference 350 deg is actually just 10 deg...
- angle_diff += diff;
- }
+ //... but if we are using line orientation flags, then we can only accept a single orientation,
+ // as we need to ensure that the labels fall inside or outside the polyline or polygon (and not mixed)
+ orientation = 1;
+ }
- sin_avg += sin( tmp->getAlpha() );
- cos_avg += cos( tmp->getAlpha() );
- angle_last = tmp->getAlpha();
- tmp = tmp->getNextPart();
+ LabelPosition* slp = curvedPlacementAtOffset( mapShape, path_distances, orientation, 1, i, reversed, flip );
+ if ( slp == nullptr )
+ continue;
+
+ // If we placed too many characters upside down
+ if ( slp->upsideDownCharCount() >= li->char_num / 2.0 )
+ {
+ // if labels should be shown upright then retry with the opposite orientation
+ if (( showUprightLabels() && !flip ) )
+ {
+ delete slp;
+ orientation = -orientation;
+ slp = curvedPlacementAtOffset( mapShape, path_distances, orientation, 1, i, reversed, flip );
+ }
+ }
+ if ( slp == nullptr )
+ continue;
+
+ // evaluate cost
+ double angle_diff = 0.0, angle_last = 0.0, diff;
+ LabelPosition* tmp = slp;
+ double sin_avg = 0, cos_avg = 0;
+ while ( tmp )
+ {
+ if ( tmp != slp ) // not first?
+ {
+ diff = fabs( tmp->getAlpha() - angle_last );
+ if ( diff > 2*M_PI ) diff -= 2 * M_PI;
+ diff = qMin( diff, 2 * M_PI - diff ); // difference 350 deg is actually just 10 deg...
+ angle_diff += diff;
}
- double angle_diff_avg = li->char_num > 1 ? ( angle_diff / ( li->char_num - 1 ) ) : 0; // <0, pi> but pi/8 is much already
- double cost = angle_diff_avg / 100; // <0, 0.031 > but usually <0, 0.003 >
- if ( cost < 0.0001 ) cost = 0.0001;
+ sin_avg += sin( tmp->getAlpha() );
+ cos_avg += cos( tmp->getAlpha() );
+ angle_last = tmp->getAlpha();
+ tmp = tmp->getNextPart();
+ }
- // penalize positions which are further from the line's midpoint
- double labelCenter = ( i * delta ) + getLabelWidth() / 2;
- double costCenter = qAbs( total_distance / 2 - labelCenter ) / total_distance; // <0, 0.5>
- cost += costCenter / 1000; // < 0, 0.0005 >
- slp->setCost( cost );
+ double angle_diff_avg = li->char_num > 1 ? ( angle_diff / ( li->char_num - 1 ) ) : 0; // <0, pi> but pi/8 is much already
+ double cost = angle_diff_avg / 100; // <0, 0.031 > but usually <0, 0.003 >
+ if ( cost < 0.0001 ) cost = 0.0001;
+
+ // penalize positions which are further from the line's midpoint
+ double labelCenter = i + getLabelWidth() / 2;
+ double costCenter = qAbs( total_distance / 2 - labelCenter ) / total_distance; // <0, 0.5>
+ cost += costCenter / 1000; // < 0, 0.0005 >
+ slp->setCost( cost );
+
+ // average angle is calculated with respect to periodicity of angles
+ double angle_avg = atan2( sin_avg / li->char_num, cos_avg / li->char_num );
+ bool localreversed = flip ? !reversed : reversed;
+ // displacement - we loop through 3 times, generating above, online then below line placements successively
+ for ( int i = 0; i <= 2; ++i )
+ {
+ LabelPosition* p = nullptr;
+ if ( i == 0 && (( !localreversed && ( flags & FLAG_ABOVE_LINE ) ) || ( localreversed && ( flags & FLAG_BELOW_LINE ) ) ) )
+ p = _createCurvedCandidate( slp, angle_avg, mLF->distLabel() + li->label_height / 2 );
+ if ( i == 1 && flags & FLAG_ON_LINE )
+ {
+ p = _createCurvedCandidate( slp, angle_avg, 0 );
+ p->setCost( p->cost() + 0.002 );
+ }
+ if ( i == 2 && (( !localreversed && ( flags & FLAG_BELOW_LINE ) ) || ( localreversed && ( flags & FLAG_ABOVE_LINE ) ) ) )
+ {
+ p = _createCurvedCandidate( slp, angle_avg, -li->label_height / 2 - mLF->distLabel() );
+ p->setCost( p->cost() + 0.001 );
+ }
- // average angle is calculated with respect to periodicity of angles
- double angle_avg = atan2( sin_avg / li->char_num, cos_avg / li->char_num );
- // displacement - we loop through 3 times, generating above, online then below line placements successively
- for ( int i = 0; i <= 2; ++i )
+ if ( p && mLF->permissibleZonePrepared() )
{
- LabelPosition* p = nullptr;
- if ( i == 0 && (( !reversed && ( flags & FLAG_ABOVE_LINE ) ) || ( reversed && ( flags & FLAG_BELOW_LINE ) ) ) )
- p = _createCurvedCandidate( slp, angle_avg, mLF->distLabel() + li->label_height / 2 );
- if ( i == 1 && flags & FLAG_ON_LINE )
- p = _createCurvedCandidate( slp, angle_avg, 0 );
- if ( i == 2 && (( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) ) ) )
- p = _createCurvedCandidate( slp, angle_avg, -li->label_height / 2 - mLF->distLabel() );
-
- if ( p && mLF->permissibleZonePrepared() )
+ bool within = true;
+ LabelPosition* currentPos = p;
+ while ( within && currentPos )
{
- bool within = true;
- LabelPosition* currentPos = p;
- while ( within && currentPos )
- {
- within = GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), currentPos->getX(), currentPos->getY(), currentPos->getWidth(), currentPos->getHeight(), currentPos->getAlpha() );
- currentPos = currentPos->getNextPart();
- }
- if ( !within )
- {
- delete p;
- p = nullptr;
- }
+ within = GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), currentPos->getX(), currentPos->getY(), currentPos->getWidth(), currentPos->getHeight(), currentPos->getAlpha() );
+ currentPos = currentPos->getNextPart();
+ }
+ if ( !within )
+ {
+ delete p;
+ p = nullptr;
}
-
- if ( p )
- positions.append( p );
}
- // delete original candidate
- delete slp;
+
+ if ( p )
+ positions.append( p );
}
- }
+ // delete original candidate
+ delete slp;
+ }
int nbp = positions.size();
for ( int i = 0; i < nbp; i++ )
@@ -1097,9 +1296,6 @@ int FeaturePart::createCurvedCandidatesAlongLine( QList< LabelPosition* >& lPos,
return nbp;
}
-
-
-
/*
* seg 2
* pt3 ____________pt2
@@ -1164,7 +1360,6 @@ int FeaturePart::createCandidatesForPolygon( QList< LabelPosition*>& lPos, Point
dx = labelWidth / 2.0;
dy = labelHeight / 2.0;
-
int numTry = 0;
//fit in polygon only mode slows down calculation a lot, so if it's enabled
@@ -1349,7 +1544,7 @@ int FeaturePart::createCandidates( QList< LabelPosition*>& lPos,
createCandidatesAroundPoint( x[0], y[0], lPos, angle );
break;
case GEOS_LINESTRING:
- if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Curved )
+ if ( mLF->layer()->isCurved() )
createCurvedCandidatesAlongLine( lPos, mapShape );
else
createCandidatesAlongLine( lPos, mapShape );
@@ -1370,6 +1565,9 @@ int FeaturePart::createCandidates( QList< LabelPosition*>& lPos,
case QgsPalLayerSettings::Line:
createCandidatesAlongLine( lPos, mapShape );
break;
+ case QgsPalLayerSettings::PerimeterCurved:
+ createCurvedCandidatesAlongLine( lPos, mapShape );
+ break;
default:
createCandidatesForPolygon( lPos, mapShape );
break;
@@ -1530,3 +1728,89 @@ double FeaturePart::calculatePriority() const
return mLF->priority() >= 0 ? mLF->priority() : mLF->layer()->priority();
}
+
+bool FeaturePart::showUprightLabels() const
+{
+ bool uprightLabel = false;
+
+ switch ( mLF->layer()->upsidedownLabels() )
+ {
+ case Layer::Upright:
+ uprightLabel = true;
+ break;
+ case Layer::ShowDefined:
+ // upright only dynamic labels
+ if ( !hasFixedRotation() || ( !hasFixedPosition() && fixedAngle() == 0.0 ) )
+ {
+ uprightLabel = true;
+ }
+ break;
+ case Layer::ShowAll:
+ break;
+ default:
+ uprightLabel = true;
+ }
+ return uprightLabel;
+}
+
+bool FeaturePart::nextCharPosition( double charWidth, double segment_length, PointSet* path_positions, int& index, double& distance,
+ double& start_x, double& start_y, double& end_x, double& end_y ) const
+{
+ // Coordinates this character will start at
+ if ( qgsDoubleNear( segment_length, 0.0 ) )
+ {
+ // Not allowed to place across on 0 length segments or discontinuities
+ return false;
+ }
+
+ double old_x = path_positions->x[index-1];
+ double old_y = path_positions->y[index-1];
+
+ double new_x = path_positions->x[index];
+ double new_y = path_positions->y[index];
+
+ double dx = new_x - old_x;
+ double dy = new_y - old_y;
+
+ start_x = old_x + dx * distance / segment_length;
+ start_y = old_y + dy * distance / segment_length;
+
+ // Coordinates this character ends at, calculated below
+ end_x = 0;
+ end_y = 0;
+
+ if ( segment_length - distance >= charWidth )
+ {
+ // if the distance remaining in this segment is enough, we just go further along the segment
+ distance += charWidth;
+ end_x = old_x + dx * distance / segment_length;
+ end_y = old_y + dy * distance / segment_length;
+ }
+ else
+ {
+ // If there isn't enough distance left on this segment
+ // then we need to search until we find the line segment that ends further than ci.width away
+ do
+ {
+ old_x = new_x;
+ old_y = new_y;
+ index++;
+ if ( index >= path_positions->nbPoints ) // Bail out if we run off the end of the shape
+ {
+ return false;
+ }
+ new_x = path_positions->x[index];
+ new_y = path_positions->y[index];
+ dx = new_x - old_x;
+ dy = new_y - old_y;
+ }
+ while ( sqrt( pow( start_x - new_x, 2 ) + pow( start_y - new_y, 2 ) ) < charWidth ); // Distance from start_ to new_
+
+ // Calculate the position to place the end of the character on
+ GeomFunction::findLineCircleIntersection( start_x, start_y, charWidth, old_x, old_y, new_x, new_y, end_x, end_y );
+
+ // Need to calculate distance on the new segment
+ distance = sqrt( pow( old_x - end_x, 2 ) + pow( old_y - end_y, 2 ) );
+ }
+ return true;
+}
diff --git a/src/core/pal/feature.h b/src/core/pal/feature.h
index 05adb6f..6f150af 100644
--- a/src/core/pal/feature.h
+++ b/src/core/pal/feature.h
@@ -161,8 +161,36 @@ namespace pal
*/
int createCandidatesAlongLine( QList<LabelPosition *> &lPos, PointSet *mapShape );
+ /** Generate candidates for line feature, by trying to place candidates towards the middle of the longest
+ * straightish segments of the line. Segments closer to horizontal are preferred over vertical segments.
+ * @param lPos pointer to an array of candidates, will be filled by generated candidates
+ * @param mapShape a pointer to the line
+ * @returns the number of generated candidates
+ */
+ int createCandidatesAlongLineNearStraightSegments( QList<LabelPosition *> &lPos, PointSet *mapShape );
+
+ /** Generate candidates for line feature, by trying to place candidates as close as possible to the line's midpoint.
+ * Candidates can "cut corners" if it helps them place near this mid point.
+ * @param lPos pointer to an array of candidates, will be filled by generated candidates
+ * @param mapShape a pointer to the line
+ * @param initialCost initial cost for candidates generated using this method. If set, cost can be increased
+ * by a preset amount.
+ * @returns the number of generated candidates
+ */
+ int createCandidatesAlongLineNearMidpoint( QList<LabelPosition *> &lPos, PointSet *mapShape, double initialCost = 0.0 );
+
+ /** Returns the label position for a curved label at a specific offset along a path.
+ * @param path_positions line path to place label on
+ * @param path_distances array of distances to each segment on path
+ * @param orientation can be 0 for automatic calculation of orientation, or -1/+1 for a specific label orientation
+ * @param index
+ * @param distance distance to offset label along curve by
+ * @param reversed if true label is reversed from lefttoright to righttoleft
+ * @param flip if true label is placed on the other side of the line
+ * @returns calculated label position
+ */
LabelPosition* curvedPlacementAtOffset( PointSet* path_positions, double* path_distances,
- int orientation, int index, double distance );
+ int& orientation, int index, double distance, bool& reversed, bool& flip );
/** Generate curved candidates for line features.
* @param lPos pointer to an array of candidates, will be filled by generated candidates
@@ -197,13 +225,28 @@ namespace pal
double getLabelHeight() const { return mLF->size().height(); }
double getLabelDistance() const { return mLF->distLabel(); }
- bool getFixedRotation() { return mLF->hasFixedAngle(); }
- double getLabelAngle() { return mLF->fixedAngle(); }
- bool getFixedPosition() { return mLF->hasFixedPosition(); }
- bool getAlwaysShow() { return mLF->alwaysShow(); }
- bool isObstacle() { return mLF->isObstacle(); }
- double obstacleFactor() { return mLF->obstacleFactor(); }
- double repeatDistance() { return mLF->repeatDistance(); }
+ //! Returns true if the feature's label has a fixed rotation
+ bool hasFixedRotation() const { return mLF->hasFixedAngle(); }
+
+ //! Returns the fixed angle for the feature's label
+ double fixedAngle() const { return mLF->fixedAngle(); }
+
+ //! Returns true if the feature's label has a fixed position
+ bool hasFixedPosition() const { return mLF->hasFixedPosition(); }
+
+ //! Returns true if the feature's label should always been shown,
+ //! even when it collides with other labels
+ bool alwaysShow() const { return mLF->alwaysShow(); }
+
+ //! Returns true if the feature should act as an obstacle to labels
+ bool isObstacle() const { return mLF->isObstacle(); }
+
+ //! Returns the feature's obstacle factor, which represents the penalty
+ //! incurred for a label to overlap the feature
+ double obstacleFactor() const { return mLF->obstacleFactor(); }
+
+ //! Returns the distance between repeating labels for this feature
+ double repeatDistance() const { return mLF->repeatDistance(); }
//! Get number of holes (inner rings) - they are considered as obstacles
int getNumSelfObstacles() const { return mHoles.count(); }
@@ -226,6 +269,12 @@ namespace pal
*/
double calculatePriority() const;
+ //! Returns true if feature's label must be displayed upright
+ bool showUprightLabels() const;
+
+ //! Returns true if the next char position is found. The referenced parameters are updated.
+ bool nextCharPosition( double charWidth, double segment_length, PointSet* path_positions, int& index, double& distance,
+ double& start_x, double& start_y, double& end_x, double& end_y ) const;
protected:
diff --git a/src/core/pal/labelposition.cpp b/src/core/pal/labelposition.cpp
index efe3549..b7befb2 100644
--- a/src/core/pal/labelposition.cpp
+++ b/src/core/pal/labelposition.cpp
@@ -60,6 +60,7 @@ LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h,
, quadrant( quadrant )
, mCost( cost )
, mHasObstacleConflict( false )
+ , mUpsideDownCharCount( 0 )
{
type = GEOS_POLYGON;
nbPoints = 4;
@@ -77,8 +78,6 @@ LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h,
double dx1, dx2, dy1, dy2;
- double tx, ty;
-
dx1 = cos( this->alpha ) * w;
dy1 = sin( this->alpha ) * w;
@@ -98,31 +97,14 @@ LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h,
y[3] = y1 + dy2;
// upside down ? (curved labels are always correct)
- if ( feature->layer()->arrangement() != QgsPalLayerSettings::Curved &&
+ if ( !feature->layer()->isCurved() &&
this->alpha > M_PI / 2 && this->alpha <= 3*M_PI / 2 )
{
- bool uprightLabel = false;
-
- switch ( feature->layer()->upsidedownLabels() )
+ if ( feature->showUprightLabels() )
{
- case Layer::Upright:
- uprightLabel = true;
- break;
- case Layer::ShowDefined:
- // upright only dynamic labels
- if ( !feature->getFixedRotation() || ( !feature->getFixedPosition() && feature->getLabelAngle() == 0.0 ) )
- {
- uprightLabel = true;
- }
- break;
- case Layer::ShowAll:
- break;
- default:
- uprightLabel = true;
- }
+ // Turn label upsidedown by inverting boundary points
+ double tx, ty;
- if ( uprightLabel )
- {
tx = x[0];
ty = y[0];
@@ -183,6 +165,7 @@ LabelPosition::LabelPosition( const LabelPosition& other )
reversed = other.reversed;
quadrant = other.quadrant;
mHasObstacleConflict = other.mHasObstacleConflict;
+ mUpsideDownCharCount = other.mUpsideDownCharCount;
}
bool LabelPosition::isIn( double *bbox )
diff --git a/src/core/pal/labelposition.h b/src/core/pal/labelposition.h
index d032c5d..41a820d 100644
--- a/src/core/pal/labelposition.h
+++ b/src/core/pal/labelposition.h
@@ -228,6 +228,11 @@ namespace pal
int getPartId() const { return partId; }
void setPartId( int id ) { partId = id; }
+ //! Increases the count of upside down characters for this label position
+ int incrementUpsideDownCharCount() { return ++mUpsideDownCharCount; }
+
+ //! Returns the number of upside down characters for this label position
+ int upsideDownCharCount() const { return mUpsideDownCharCount; }
void removeFromIndex( RTree<LabelPosition*, double, 2, double> *index );
void insertIntoIndex( RTree<LabelPosition*, double, 2, double> *index );
@@ -296,6 +301,7 @@ namespace pal
private:
double mCost;
bool mHasObstacleConflict;
+ int mUpsideDownCharCount;
/** Calculates the total number of parts for this label position
*/
diff --git a/src/core/pal/layer.cpp b/src/core/pal/layer.cpp
index e00b438..0b2590f 100644
--- a/src/core/pal/layer.cpp
+++ b/src/core/pal/layer.cpp
@@ -35,6 +35,7 @@
#include "geomfunction.h"
#include "util.h"
#include "qgslabelingenginev2.h"
+
#include <cmath>
#include <vector>
diff --git a/src/core/pal/layer.h b/src/core/pal/layer.h
index e31c5d4..eb8cd21 100644
--- a/src/core/pal/layer.h
+++ b/src/core/pal/layer.h
@@ -93,6 +93,10 @@ namespace pal
*/
QgsPalLayerSettings::Placement arrangement() const { return mArrangement; }
+ /** Returns true if the layer has curved labels
+ */
+ bool isCurved() const { return mArrangement == QgsPalLayerSettings::Curved || mArrangement == QgsPalLayerSettings::PerimeterCurved; }
+
/** Sets the layer's arrangement policy.
* @param arrangement arrangement policy
* @see arrangement
diff --git a/src/core/pal/pal.cpp b/src/core/pal/pal.cpp
index cf57d39..fefb4d8 100644
--- a/src/core/pal/pal.cpp
+++ b/src/core/pal/pal.cpp
@@ -71,9 +71,9 @@ Pal::Pal()
setSearch( CHAIN );
- point_p = 8;
- line_p = 8;
- poly_p = 8;
+ point_p = 16;
+ line_p = 50;
+ poly_p = 30;
showPartial = true;
}
diff --git a/src/core/pal/problem.cpp b/src/core/pal/problem.cpp
index e62479a..14b2500 100644
--- a/src/core/pal/problem.cpp
+++ b/src/core/pal/problem.cpp
@@ -2268,7 +2268,7 @@ QList<LabelPosition*> * Problem::getSolution( bool returnInactive )
}
else if ( returnInactive
|| mLabelPositions.at( featStartId[i] )->getFeaturePart()->layer()->displayAll()
- || mLabelPositions.at( featStartId[i] )->getFeaturePart()->getAlwaysShow() )
+ || mLabelPositions.at( featStartId[i] )->getFeaturePart()->alwaysShow() )
{
solList->push_back( mLabelPositions.at( featStartId[i] ) ); // unplaced label
}
diff --git a/src/core/pal/util.cpp b/src/core/pal/util.cpp
index d42a217..dbcf56e 100644
--- a/src/core/pal/util.cpp
+++ b/src/core/pal/util.cpp
@@ -33,6 +33,8 @@
#include "labelposition.h"
#include "feature.h"
#include "geomfunction.h"
+
+#include <qgslogger.h>
#include <cfloat>
#ifndef M_PI
@@ -105,11 +107,13 @@ QLinkedList<const GEOSGeometry *>* pal::Util::unmulti( const GEOSGeometry *the_g
int nGeom;
int i;
+ GEOSContextHandle_t geosctxt = geosContext();
+
while ( !queue->isEmpty() )
{
geom = queue->takeFirst();
- GEOSContextHandle_t geosctxt = geosContext();
- switch ( GEOSGeomTypeId_r( geosctxt, geom ) )
+ int type = GEOSGeomTypeId_r( geosctxt, geom );
+ switch ( type )
{
case GEOS_MULTIPOINT:
case GEOS_MULTILINESTRING:
@@ -126,6 +130,7 @@ QLinkedList<const GEOSGeometry *>* pal::Util::unmulti( const GEOSGeometry *the_g
final_queue->append( geom );
break;
default:
+ QgsDebugMsg( QString( "unexpected geometry type:%1" ).arg( type ) );
delete final_queue;
delete queue;
return nullptr;
diff --git a/src/core/qgsannotation.h b/src/core/qgsannotation.h
index 5ed3e5d..b53ef63 100644
--- a/src/core/qgsannotation.h
+++ b/src/core/qgsannotation.h
@@ -26,7 +26,7 @@ class QStyleOptionGraphicsItem;
/** \ingroup core
* \class QgsAnnotation
- * \note added in QGIS 3.0
+ * \note added in QGIS 2.18
*
* \brief An interface for annotation items which are drawn over a map.
*
diff --git a/src/core/qgsapplication.cpp b/src/core/qgsapplication.cpp
index 420dfe2..947678e 100644
--- a/src/core/qgsapplication.cpp
+++ b/src/core/qgsapplication.cpp
@@ -712,8 +712,20 @@ QStringList QgsApplication::svgPaths()
myPathList = myPaths.split( '|' );
}
- myPathList << ABISYM( mDefaultSvgPaths );
- return myPathList;
+ // maintain user set order while stripping duplicates
+ QStringList paths;
+ Q_FOREACH ( const QString& path, myPathList )
+ {
+ if ( !paths.contains( path ) )
+ paths.append( path );
+ }
+ Q_FOREACH ( const QString& path, ABISYM( mDefaultSvgPaths ) )
+ {
+ if ( !paths.contains( path ) )
+ paths.append( path );
+ }
+
+ return paths;
}
/*!
diff --git a/src/core/qgsapplication.h b/src/core/qgsapplication.h
index 9b42aef..08ce1d0 100644
--- a/src/core/qgsapplication.h
+++ b/src/core/qgsapplication.h
@@ -370,7 +370,7 @@ class CORE_EXPORT QgsApplication : public QApplication
* be called whenever global, application-wide settings are altered to advise listeners
* that they may need to update their state.
* @see settingsChanged()
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
void emitSettingsChanged();
@@ -379,7 +379,7 @@ class CORE_EXPORT QgsApplication : public QApplication
void preNotify( QObject * receiver, QEvent * event, bool * done );
/** Emitted whenever any global, application-wide settings are changed.
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
* @see emitSettingsChanged()
*/
void settingsChanged();
diff --git a/src/core/qgsbearingutils.cpp b/src/core/qgsbearingutils.cpp
new file mode 100644
index 0000000..0c8cfcd
--- /dev/null
+++ b/src/core/qgsbearingutils.cpp
@@ -0,0 +1,51 @@
+/***************************************************************************
+ qgsbearingutils.cpp
+ -------------------
+ begin : October 2016
+ copyright : (C) 2016 by Nyall Dawson
+ email : nyall dot dawson at gmail dot com
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "qgsbearingutils.h"
+#include "qgscoordinatereferencesystem.h"
+#include "qgspoint.h"
+#include "qgscoordinatetransform.h"
+#include "qgsexception.h"
+
+double QgsBearingUtils::bearingTrueNorth( const QgsCoordinateReferenceSystem &crs, const QgsPoint &point )
+{
+ // step 1 - transform point into WGS84 geographic crs
+ QgsCoordinateReferenceSystem destCrs;
+ destCrs.createFromOgcWmsCrs( "EPSG:4326" );
+ QgsCoordinateTransform transform( crs, destCrs );
+
+ if ( !transform.isInitialised() )
+ {
+ //raise
+ throw QgsException( QObject::tr( "Could not create transform to calculate true north" ) );
+ }
+
+ if ( transform.isShortCircuited() )
+ return 0.0;
+
+ QgsPoint p1 = transform.transform( point );
+
+ // shift point a tiny bit north
+ QgsPoint p2 = p1;
+ p2.setY( p2.y() + 0.000001 );
+
+ //transform back
+ QgsPoint p3 = transform.transform( p2, QgsCoordinateTransform::ReverseTransform );
+
+ // find bearing from point to p3
+ return point.azimuth( p3 );
+}
diff --git a/src/core/qgsbearingutils.h b/src/core/qgsbearingutils.h
new file mode 100644
index 0000000..400d107
--- /dev/null
+++ b/src/core/qgsbearingutils.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ qgsbearingutils.h
+ -----------------
+ begin : October 2016
+ copyright : (C) 2016 by Nyall Dawson
+ email : nyall dot dawson at gmail dot com
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSBEARINGUTILS_H
+#define QGSBEARINGUTILS_H
+
+class QgsCoordinateReferenceSystem;
+class QgsPoint;
+
+
+/**
+ * \class QgsBearingUtils
+ * \ingroup core
+ * Utilities for calculating bearings and directions.
+ * \note Added in version 2.18
+*/
+class CORE_EXPORT QgsBearingUtils
+{
+ public:
+
+ /**
+ * Returns the direction to true north from a specified point and for a specified
+ * coordinate reference system. The returned value is in degrees clockwise from
+ * vertical. An exception will be thrown if the bearing could not be calculated.
+ */
+ static double bearingTrueNorth( const QgsCoordinateReferenceSystem& crs,
+ const QgsPoint& point );
+
+};
+
+#endif //QGSBEARINGUTILS_H
diff --git a/src/core/qgscolorscheme.cpp b/src/core/qgscolorscheme.cpp
index 0d36a1a..bd039b1 100644
--- a/src/core/qgscolorscheme.cpp
+++ b/src/core/qgscolorscheme.cpp
@@ -373,6 +373,21 @@ QgsUserColorScheme* QgsUserColorScheme::clone() const
return new QgsUserColorScheme( mFilename );
}
+QgsColorScheme::SchemeFlags QgsUserColorScheme::flags() const
+{
+ QgsColorScheme::SchemeFlags f = QgsGplColorScheme::flags();
+
+ QSettings s;
+ QStringList showInMenuSchemes = s.value( QString( "/colors/showInMenuList" ) ).toStringList();
+
+ if ( showInMenuSchemes.contains( mName ) )
+ {
+ f |= QgsColorScheme::ShowInColorButtonMenu;
+ }
+
+ return f;
+}
+
bool QgsUserColorScheme::erase()
{
QString filePath = gplFilePath();
@@ -385,6 +400,23 @@ bool QgsUserColorScheme::erase()
return QFile::remove( filePath );
}
+void QgsUserColorScheme::setShowSchemeInMenu( bool show )
+{
+ QSettings s;
+ QStringList showInMenuSchemes = s.value( QString( "/colors/showInMenuList" ) ).toStringList();
+
+ if ( show && !showInMenuSchemes.contains( mName ) )
+ {
+ showInMenuSchemes << mName;
+ }
+ else if ( !show && showInMenuSchemes.contains( mName ) )
+ {
+ showInMenuSchemes.removeAll( mName );
+ }
+
+ s.setValue( "/colors/showInMenuList", showInMenuSchemes );
+}
+
QString QgsUserColorScheme::gplFilePath()
{
QString palettesDir = QgsApplication::qgisSettingsDirPath() + "/palettes";
diff --git a/src/core/qgscolorscheme.h b/src/core/qgscolorscheme.h
index c1058fc..17621a6 100644
--- a/src/core/qgscolorscheme.h
+++ b/src/core/qgscolorscheme.h
@@ -152,6 +152,8 @@ class CORE_EXPORT QgsUserColorScheme : public QgsGplColorScheme
virtual bool isEditable() const override { return true; }
+ virtual QgsColorScheme::SchemeFlags flags() const override;
+
/** Sets the name for the scheme
* @param name new name
*/
@@ -162,6 +164,12 @@ class CORE_EXPORT QgsUserColorScheme : public QgsGplColorScheme
*/
bool erase();
+ /** Sets whether a this scheme should be shown in color button menus.
+ * @param show set to true to show in color button menus, or false to hide from menus
+ * @note added in QGIS 2.18
+ */
+ void setShowSchemeInMenu( bool show );
+
protected:
QString mName;
diff --git a/src/core/qgsdataitem.cpp b/src/core/qgsdataitem.cpp
index b3c73bd..1aa35a3 100644
--- a/src/core/qgsdataitem.cpp
+++ b/src/core/qgsdataitem.cpp
@@ -130,7 +130,7 @@ const QIcon &QgsLayerItem::iconTable()
static QIcon icon;
if ( icon.isNull() )
- icon = QgsApplication::getThemeIcon( "/mIconTableLayer.png" );
+ icon = QgsApplication::getThemeIcon( "/mIconTableLayer.svg" );
return icon;
}
@@ -696,7 +696,7 @@ QgsLayerItem::QgsLayerItem( QgsDataItem* parent, const QString& name, const QStr
mIconName = "/mIconPolygonLayer.svg";
break;
case TableLayer:
- mIconName = "/mIconTableLayer.png";
+ mIconName = "/mIconTableLayer.svg";
break;
case Raster:
mIconName = "/mIconRaster.svg";
diff --git a/src/core/qgsdataitemproviderregistry.cpp b/src/core/qgsdataitemproviderregistry.cpp
index 8e7e516..8608cd1 100644
--- a/src/core/qgsdataitemproviderregistry.cpp
+++ b/src/core/qgsdataitemproviderregistry.cpp
@@ -21,6 +21,8 @@
#include "qgslogger.h"
#include "qgsproviderregistry.h"
+typedef QList<QgsDataItemProvider*> dataItemProviders_t();
+
/**
* \ingroup core
@@ -64,6 +66,17 @@ QgsDataItemProviderRegistry::QgsDataItemProviderRegistry()
if ( !library )
continue;
+ // new / better way of returning data items from providers
+
+ dataItemProviders_t* dataItemProvidersFn = reinterpret_cast< dataItemProviders_t * >( cast_to_fptr( library->resolve( "dataItemProviders" ) ) );
+ if ( dataItemProvidersFn )
+ {
+ // the function is a factory - we keep ownership of the returned providers
+ mProviders << dataItemProvidersFn();
+ }
+
+ // legacy support - using dataItem() and dataCapabilities() methods
+
dataCapabilities_t * dataCapabilities = reinterpret_cast< dataCapabilities_t * >( cast_to_fptr( library->resolve( "dataCapabilities" ) ) );
if ( !dataCapabilities )
{
diff --git a/src/core/qgseditformconfig.cpp b/src/core/qgseditformconfig.cpp
index 3217d9d..42f59f2 100644
--- a/src/core/qgseditformconfig.cpp
+++ b/src/core/qgseditformconfig.cpp
@@ -427,6 +427,15 @@ QgsAttributeEditorElement* QgsEditFormConfig::attributeEditorElementFromDomEleme
else
container->setIsGroupBox( qobject_cast<QgsAttributeEditorContainer*>( parent ) );
+ bool visibilityExpressionEnabled = elem.attribute( "visibilityExpressionEnabled" ).toInt( &ok );
+ QgsOptionalExpression visibilityExpression;
+ if ( ok )
+ {
+ visibilityExpression.setEnabled( visibilityExpressionEnabled );
+ visibilityExpression.setData( QgsExpression( elem.attribute( "visibilityExpression" ) ) );
+ }
+ container->setVisibilityExpression( visibilityExpression );
+
QDomNodeList childNodeList = elem.childNodes();
for ( int i = 0; i < childNodeList.size(); i++ )
@@ -450,8 +459,17 @@ QgsAttributeEditorElement* QgsEditFormConfig::attributeEditorElementFromDomEleme
// At this time, the relations are not loaded
// So we only grab the id and delegate the rest to onRelationsLoaded()
QString name = elem.attribute( "name" );
- newElement = new QgsAttributeEditorRelation( name, elem.attribute( "relation", "[None]" ), parent );
+ QgsAttributeEditorRelation* relElement = new QgsAttributeEditorRelation( name, elem.attribute( "relation", "[None]" ), parent );
+ relElement->setShowLinkButton( elem.attribute( "showLinkButton", "1" ).toInt() );
+ relElement->setShowUnlinkButton( elem.attribute( "showUnlinkButton", "1" ).toInt() );
+ newElement = relElement;
}
+
+ if ( elem.hasAttribute( "showLabel" ) )
+ newElement->setShowLabel( elem.attribute( "showLabel" ).toInt() );
+ else
+ newElement->setShowLabel( true );
+
return newElement;
}
@@ -487,3 +505,132 @@ void QgsAttributeEditorContainer::setColumnCount( int columnCount )
{
mColumnCount = columnCount;
}
+
+void QgsAttributeEditorContainer::saveConfiguration( QDomElement& elem ) const
+{
+ elem.setAttribute( "columnCount", mColumnCount );
+ elem.setAttribute( "groupBox", mIsGroupBox ? 1 : 0 );
+ elem.setAttribute( "visibilityExpressionEnabled", mVisibilityExpression.enabled() ? 1 : 0 );
+ elem.setAttribute( "visibilityExpression", mVisibilityExpression->expression() );
+
+ Q_FOREACH ( QgsAttributeEditorElement* child, mChildren )
+ {
+ QDomDocument doc = elem.ownerDocument();
+ elem.appendChild( child->toDomElement( doc ) );
+ }
+}
+
+QgsOptionalExpression QgsAttributeEditorContainer::visibilityExpression() const
+{
+ return mVisibilityExpression;
+}
+
+void QgsAttributeEditorContainer::setVisibilityExpression( const QgsOptionalExpression& visibilityExpression )
+{
+ mVisibilityExpression = visibilityExpression;
+}
+
+QString QgsAttributeEditorContainer::typeIdentifier() const
+{
+ return "attributeEditorContainer";
+}
+
+void QgsAttributeEditorContainer::addChildElement( QgsAttributeEditorElement *widget )
+{
+ mChildren.append( widget );
+}
+
+void QgsAttributeEditorContainer::setName( const QString& name )
+{
+ mName = name;
+}
+
+QList<QgsAttributeEditorElement*> QgsAttributeEditorContainer::findElements( QgsAttributeEditorElement::AttributeEditorType type ) const
+{
+ QList<QgsAttributeEditorElement*> results;
+
+ Q_FOREACH ( QgsAttributeEditorElement* elem, mChildren )
+ {
+ if ( elem->type() == type )
+ {
+ results.append( elem );
+ }
+
+ if ( elem->type() == AeTypeContainer )
+ {
+ QgsAttributeEditorContainer* cont = dynamic_cast<QgsAttributeEditorContainer*>( elem );
+ if ( cont )
+ results += cont->findElements( type );
+ }
+ }
+
+ return results;
+}
+
+void QgsAttributeEditorField::saveConfiguration( QDomElement &elem ) const
+{
+ elem.setAttribute( "index", mIdx );
+}
+
+QString QgsAttributeEditorField::typeIdentifier() const
+{
+ return "attributeEditorField";
+}
+
+QDomElement QgsAttributeEditorElement::toDomElement( QDomDocument& doc ) const
+{
+ QDomElement elem = doc.createElement( typeIdentifier() );
+ elem.setAttribute( "name", mName );
+ elem.setAttribute( "showLabel", mShowLabel );
+
+ saveConfiguration( elem );
+ return elem;
+}
+
+bool QgsAttributeEditorElement::showLabel() const
+{
+ return mShowLabel;
+}
+
+void QgsAttributeEditorElement::setShowLabel( bool showLabel )
+{
+ mShowLabel = showLabel;
+}
+
+void QgsAttributeEditorRelation::saveConfiguration( QDomElement& elem ) const
+{
+ elem.setAttribute( "relation", mRelation.id() );
+ elem.setAttribute( "showLinkButton", mShowLinkButton );
+ elem.setAttribute( "showUnlinkButton", mShowUnlinkButton );
+}
+
+QString QgsAttributeEditorRelation::typeIdentifier() const
+{
+ return "attributeEditorRelation";
+}
+
+bool QgsAttributeEditorRelation::showUnlinkButton() const
+{
+ return mShowUnlinkButton;
+}
+
+void QgsAttributeEditorRelation::setShowUnlinkButton( bool showUnlinkButton )
+{
+ mShowUnlinkButton = showUnlinkButton;
+}
+
+bool QgsAttributeEditorRelation::init( QgsRelationManager* relationManager )
+{
+ mRelation = relationManager->relation( mRelationId );
+ return mRelation.isValid();
+}
+
+bool QgsAttributeEditorRelation::showLinkButton() const
+{
+ return mShowLinkButton;
+}
+
+void QgsAttributeEditorRelation::setShowLinkButton( bool showLinkButton )
+{
+ mShowLinkButton = showLinkButton;
+}
diff --git a/src/core/qgseditformconfig.h b/src/core/qgseditformconfig.h
index 38c8b79..33cc615 100644
--- a/src/core/qgseditformconfig.h
+++ b/src/core/qgseditformconfig.h
@@ -22,6 +22,7 @@
#include "qgseditorwidgetconfig.h"
#include "qgsrelationmanager.h"
+#include "qgsoptionalexpression.h"
/** \ingroup core
* This is an abstract base class for any elements of a drag and drop form.
@@ -56,6 +57,7 @@ class CORE_EXPORT QgsAttributeEditorElement : public QObject
: QObject( parent )
, mType( type )
, mName( name )
+ , mShowLabel( true )
{}
//! Destructor
@@ -76,17 +78,48 @@ class CORE_EXPORT QgsAttributeEditorElement : public QObject
AttributeEditorType type() const { return mType; }
/**
- * Is reimplemented in classes inheriting from this to serialize it.
+ * Get the XML Dom element to save this element.
*
* @param doc The QDomDocument which is used to create new XML elements
*
- * @return An DOM element which represents this element
+ * @return A DOM element to serialize this element
*/
- virtual QDomElement toDomElement( QDomDocument& doc ) const = 0;
+ QDomElement toDomElement( QDomDocument& doc ) const;
+
+ /**
+ * Controls if this element should be labeled with a title (field, relation or groupname).
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLabel() const;
+
+ /**
+ * Controls if this element should be labeled with a title (field, relation or groupname).
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLabel( bool showLabel );
protected:
AttributeEditorType mType;
QString mName;
+ bool mShowLabel;
+
+ private:
+ /**
+ * Should be implemented by subclasses to save type specific configuration.
+ *
+ * @note Added in QGIS 2.18
+ */
+ virtual void saveConfiguration( QDomElement& elem ) const = 0;
+
+ /**
+ * All subclasses need to overwrite this method and return a type specific identifier.
+ * Needs to be XML key compatible.
+ *
+ * @note Added in QGIS 2.18
+ */
+ virtual QString typeIdentifier() const = 0;
};
@@ -115,15 +148,6 @@ class CORE_EXPORT QgsAttributeEditorContainer : public QgsAttributeEditorElement
virtual ~QgsAttributeEditorContainer() {}
/**
- * Will serialize this containers information into a QDomElement for saving it in an XML file.
- *
- * @param doc The QDomDocument used to generate the QDomElement
- *
- * @return The XML element
- */
- virtual QDomElement toDomElement( QDomDocument& doc ) const override;
-
- /**
* Add a child element to this container. This may be another container, a field or a relation.
*
* @param element The element to add as child
@@ -175,10 +199,28 @@ class CORE_EXPORT QgsAttributeEditorContainer : public QgsAttributeEditorElement
*/
void setColumnCount( int columnCount );
+ /**
+ * An expression that controls the visibility of this container.
+ *
+ * @note Added in QGIS 2.18
+ */
+ QgsOptionalExpression visibilityExpression() const;
+
+ /**
+ * An expression that controls the visibility of this container.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setVisibilityExpression( const QgsOptionalExpression& visibilityExpression );
+
private:
+ virtual void saveConfiguration( QDomElement& elem ) const override;
+ virtual QString typeIdentifier() const override;
+
bool mIsGroupBox;
QList<QgsAttributeEditorElement*> mChildren;
int mColumnCount;
+ QgsOptionalExpression mVisibilityExpression;
};
/** \ingroup core
@@ -205,21 +247,14 @@ class CORE_EXPORT QgsAttributeEditorField : public QgsAttributeEditorElement
virtual ~QgsAttributeEditorField() {}
/**
- * Will serialize this elements information into a QDomElement for saving it in an XML file.
- *
- * @param doc The QDomDocument used to generate the QDomElement
- *
- * @return The XML element
- */
- virtual QDomElement toDomElement( QDomDocument& doc ) const override;
-
- /**
* Return the index of the field
* @return
*/
int idx() const { return mIdx; }
private:
+ virtual void saveConfiguration( QDomElement& elem ) const override;
+ virtual QString typeIdentifier() const override;
int mIdx;
};
@@ -240,7 +275,10 @@ class CORE_EXPORT QgsAttributeEditorRelation : public QgsAttributeEditorElement
*/
QgsAttributeEditorRelation( const QString& name, const QString &relationId, QObject *parent )
: QgsAttributeEditorElement( AeTypeRelation, name, parent )
- , mRelationId( relationId ) {}
+ , mRelationId( relationId )
+ , mShowLinkButton( true )
+ , mShowUnlinkButton( true )
+ {}
/**
* Creates a new element which embeds a relation.
@@ -252,21 +290,15 @@ class CORE_EXPORT QgsAttributeEditorRelation : public QgsAttributeEditorElement
QgsAttributeEditorRelation( const QString& name, const QgsRelation& relation, QObject *parent )
: QgsAttributeEditorElement( AeTypeRelation, name, parent )
, mRelationId( relation.id() )
- , mRelation( relation ) {}
+ , mRelation( relation )
+ , mShowLinkButton( true )
+ , mShowUnlinkButton( true )
+ {}
//! Destructor
virtual ~QgsAttributeEditorRelation() {}
/**
- * Will serialize this elements information into a QDomElement for saving it in an XML file.
- *
- * @param doc The QDomDocument used to generate the QDomElement
- *
- * @return The XML element
- */
- virtual QDomElement toDomElement( QDomDocument& doc ) const override;
-
- /**
* Get the id of the relation which shall be embedded
*
* @return the id
@@ -281,9 +313,39 @@ class CORE_EXPORT QgsAttributeEditorRelation : public QgsAttributeEditorElement
*/
bool init( QgsRelationManager *relManager );
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLinkButton() const;
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLinkButton( bool showLinkButton );
+
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showUnlinkButton() const;
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowUnlinkButton( bool showUnlinkButton );
+
private:
+ virtual void saveConfiguration( QDomElement& elem ) const override;
+ virtual QString typeIdentifier() const override;
QString mRelationId;
QgsRelation mRelation;
+ bool mShowLinkButton;
+ bool mShowUnlinkButton;
};
diff --git a/src/core/qgsexpression.cpp b/src/core/qgsexpression.cpp
index 4d4be85..0ed5e2a 100644
--- a/src/core/qgsexpression.cpp
+++ b/src/core/qgsexpression.cpp
@@ -1826,6 +1826,34 @@ static QVariant fcnGeometryN( const QVariantList& values, const QgsExpressionCon
return result;
}
+static QVariant fcnBoundary( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
+{
+ QgsGeometry geom = getGeometry( values.at( 0 ), parent );
+
+ if ( geom.isEmpty() )
+ return QVariant();
+
+ QgsAbstractGeometryV2* boundary = geom.geometry()->boundary();
+ if ( !boundary )
+ return QVariant();
+
+ return QVariant::fromValue( QgsGeometry( boundary ) );
+}
+
+static QVariant fcnLineMerge( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
+{
+ QgsGeometry geom = getGeometry( values.at( 0 ), parent );
+
+ if ( geom.isEmpty() )
+ return QVariant();
+
+ QgsGeometry merged = geom.mergeLines();
+ if ( merged.isEmpty() )
+ return QVariant();
+
+ return QVariant::fromValue( merged );
+}
+
static QVariant fcnMakePoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
if ( values.count() < 2 || values.count() > 4 )
@@ -2587,6 +2615,52 @@ static QVariant fcnShortestLine( const QVariantList& values, const QgsExpression
return result;
}
+static QVariant fcnLineInterpolatePoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
+{
+ QgsGeometry lineGeom = getGeometry( values.at( 0 ), parent );
+ double distance = getDoubleValue( values.at( 1 ), parent );
+
+ QgsGeometry* geom = lineGeom.interpolate( distance );
+
+ QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
+ delete geom;
+ return result;
+}
+
+static QVariant fcnLineInterpolateAngle( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
+{
+ QgsGeometry lineGeom = getGeometry( values.at( 0 ), parent );
+ double distance = getDoubleValue( values.at( 1 ), parent );
+
+ return lineGeom.interpolateAngle( distance ) * 180.0 / M_PI;
+}
+
+static QVariant fcnAngleAtVertex( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
+{
+ QgsGeometry geom = getGeometry( values.at( 0 ), parent );
+ int vertex = getIntValue( values.at( 1 ), parent );
+
+ return geom.angleAtVertex( vertex ) * 180.0 / M_PI;
+}
+
+static QVariant fcnDistanceToVertex( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
+{
+ QgsGeometry geom = getGeometry( values.at( 0 ), parent );
+ int vertex = getIntValue( values.at( 1 ), parent );
+
+ return geom.distanceToVertex( vertex );
+}
+
+static QVariant fcnLineLocatePoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
+{
+ QgsGeometry lineGeom = getGeometry( values.at( 0 ), parent );
+ QgsGeometry pointGeom = getGeometry( values.at( 1 ), parent );
+
+ double distance = lineGeom.lineLocatePoint( pointGeom );
+
+ return distance >= 0 ? distance : QVariant();
+}
+
static QVariant fcnRound( const QVariantList& values, const QgsExpressionContext *, QgsExpression* parent )
{
if ( values.length() == 2 )
@@ -3182,9 +3256,12 @@ const QStringList& QgsExpression::BuiltinFunctions()
<< "disjoint" << "intersects" << "touches" << "crosses" << "contains"
<< "relate"
<< "overlaps" << "within" << "buffer" << "centroid" << "bounds" << "reverse" << "exterior_ring"
+ << "boundary" << "line_merge"
<< "bounds_width" << "bounds_height" << "is_closed" << "convex_hull" << "difference"
<< "distance" << "intersection" << "sym_difference" << "combine"
<< "extrude" << "azimuth" << "project" << "closest_point" << "shortest_line"
+ << "line_locate_point" << "line_interpolate_point"
+ << "line_interpolate_angle" << "angle_at_vertex" << "distance_to_vertex"
<< "union" << "geom_to_wkt" << "geomToWKT" << "geometry"
<< "transform" << "get_feature" << "getFeature"
<< "levenshtein" << "longest_common_substring" << "hamming_distance"
@@ -3221,7 +3298,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
<< new StaticFunction( "sqrt", ParameterList() << Parameter( "value" ), fcnSqrt, "Math" )
<< new StaticFunction( "radians", ParameterList() << Parameter( "degrees" ), fcnRadians, "Math" )
<< new StaticFunction( "degrees", ParameterList() << Parameter( "radians" ), fcnDegrees, "Math" )
- << new StaticFunction( "azimuth", ParameterList() << Parameter( "point_a" ) << Parameter( "point_b" ), fcnAzimuth, "Math" )
+ << new StaticFunction( "azimuth", ParameterList() << Parameter( "point_a" ) << Parameter( "point_b" ), fcnAzimuth, QStringList() << "Math" << "GeometryGroup" )
<< new StaticFunction( "project", ParameterList() << Parameter( "point" ) << Parameter( "distance" ) << Parameter( "bearing" ), fcnProject, "GeometryGroup" )
<< new StaticFunction( "abs", ParameterList() << Parameter( "value" ), fcnAbs, "Math" )
<< new StaticFunction( "cos", ParameterList() << Parameter( "angle" ), fcnCos, "Math" )
@@ -3246,13 +3323,13 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
<< new StaticFunction( "floor", 1, fcnFloor, "Math" )
<< new StaticFunction( "ceil", 1, fcnCeil, "Math" )
<< new StaticFunction( "pi", 0, fcnPi, "Math", QString(), false, QStringList(), false, QStringList() << "$pi" )
- << new StaticFunction( "to_int", 1, fcnToInt, "Conversions", QString(), false, QStringList(), false, QStringList() << "toint" )
- << new StaticFunction( "to_real", 1, fcnToReal, "Conversions", QString(), false, QStringList(), false, QStringList() << "toreal" )
- << new StaticFunction( "to_string", 1, fcnToString, "Conversions", QString(), false, QStringList(), false, QStringList() << "tostring" )
- << new StaticFunction( "to_datetime", 1, fcnToDateTime, "Conversions", QString(), false, QStringList(), false, QStringList() << "todatetime" )
- << new StaticFunction( "to_date", 1, fcnToDate, "Conversions", QString(), false, QStringList(), false, QStringList() << "todate" )
- << new StaticFunction( "to_time", 1, fcnToTime, "Conversions", QString(), false, QStringList(), false, QStringList() << "totime" )
- << new StaticFunction( "to_interval", 1, fcnToInterval, "Conversions", QString(), false, QStringList(), false, QStringList() << "tointerval" )
+ << new StaticFunction( "to_int", ParameterList() << Parameter( "value" ), fcnToInt, "Conversions", QString(), false, QStringList(), false, QStringList() << "toint" )
+ << new StaticFunction( "to_real", ParameterList() << Parameter( "value" ), fcnToReal, "Conversions", QString(), false, QStringList(), false, QStringList() << "toreal" )
+ << new StaticFunction( "to_string", ParameterList() << Parameter( "value" ), fcnToString, QStringList() << "Conversions" << "String", QString(), false, QStringList(), false, QStringList() << "tostring" )
+ << new StaticFunction( "to_datetime", ParameterList() << Parameter( "value" ), fcnToDateTime, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "todatetime" )
+ << new StaticFunction( "to_date", ParameterList() << Parameter( "value" ), fcnToDate, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "todate" )
+ << new StaticFunction( "to_time", ParameterList() << Parameter( "value" ), fcnToTime, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "totime" )
+ << new StaticFunction( "to_interval", ParameterList() << Parameter( "value" ), fcnToInterval, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "tointerval" )
<< new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals", QString(), false, QStringList(), false, QStringList(), true )
<< new StaticFunction( "if", 3, fcnIf, "Conditionals", QString(), False, QStringList(), true )
<< new StaticFunction( "aggregate", ParameterList() << Parameter( "layer" ) << Parameter( "aggregate" ) << Parameter( "expression" )
@@ -3279,7 +3356,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
<< new StaticFunction( "max_length", aggParams, fcnAggregateMaxLength, "Aggregates", QString(), False, QStringList(), true )
<< new StaticFunction( "concatenate", aggParams << Parameter( "concatenator", true ), fcnAggregateStringConcat, "Aggregates", QString(), False, QStringList(), true )
- << new StaticFunction( "regexp_match", 2, fcnRegexpMatch, "Conditionals" )
+ << new StaticFunction( "regexp_match", ParameterList() << Parameter( "string" ) << Parameter( "regex" ), fcnRegexpMatch, QStringList() << "Conditionals" << "String" )
<< new StaticFunction( "now", 0, fcnNow, "Date and Time", QString(), false, QStringList(), false, QStringList() << "$now" )
<< new StaticFunction( "age", 2, fcnAge, "Date and Time" )
<< new StaticFunction( "year", 1, fcnYear, "Date and Time" )
@@ -3300,7 +3377,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
<< new StaticFunction( "soundex", 1, fcnSoundex, "Fuzzy Matching" )
<< new StaticFunction( "char", 1, fcnChar, "String" )
<< new StaticFunction( "wordwrap", ParameterList() << Parameter( "text" ) << Parameter( "length" ) << Parameter( "delimiter", true, " " ), fcnWordwrap, "String" )
- << new StaticFunction( "length", 1, fcnLength, "String" )
+ << new StaticFunction( "length", ParameterList() << Parameter( "text", true, "" ), fcnLength, QStringList() << "String" << "GeometryGroup" )
<< new StaticFunction( "replace", 3, fcnReplace, "String" )
<< new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" )
<< new StaticFunction( "regexp_substr", 2, fcnRegexpSubstr, "String" )
@@ -3313,7 +3390,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
<< new StaticFunction( "lpad", 3, fcnLPad, "String" )
<< new StaticFunction( "format", -1, fcnFormatString, "String" )
<< new StaticFunction( "format_number", 2, fcnFormatNumber, "String" )
- << new StaticFunction( "format_date", 2, fcnFormatDate, "String" )
+ << new StaticFunction( "format_date", ParameterList() << Parameter( "date" ) << Parameter( "format" ), fcnFormatDate, QStringList() << "String" << "Date and Time" )
<< new StaticFunction( "color_rgb", 3, fcnColorRgb, "Color" )
<< new StaticFunction( "color_rgba", 4, fncColorRgba, "Color" )
<< new StaticFunction( "ramp_color", 2, fcnRampColor, "Color" )
@@ -3373,6 +3450,8 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
<< new StaticFunction( "exterior_ring", 1, fcnExteriorRing, "GeometryGroup" )
<< new StaticFunction( "interior_ring_n", 2, fcnInteriorRingN, "GeometryGroup" )
<< new StaticFunction( "geometry_n", 2, fcnGeometryN, "GeometryGroup" )
+ << new StaticFunction( "boundary", ParameterList() << Parameter( "geometry" ), fcnBoundary, "GeometryGroup" )
+ << new StaticFunction( "line_merge", ParameterList() << Parameter( "geometry" ), fcnLineMerge, "GeometryGroup" )
<< new StaticFunction( "bounds", 1, fcnBounds, "GeometryGroup" )
<< new StaticFunction( "num_points", 1, fcnGeomNumPoints, "GeometryGroup" )
<< new StaticFunction( "num_interior_rings", 1, fcnGeomNumInteriorRings, "GeometryGroup" )
@@ -3395,6 +3474,16 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
<< new StaticFunction( "order_parts", 3, fcnOrderParts, "GeometryGroup", QString() )
<< new StaticFunction( "closest_point", 2, fcnClosestPoint, "GeometryGroup" )
<< new StaticFunction( "shortest_line", 2, fcnShortestLine, "GeometryGroup" )
+ << new StaticFunction( "line_interpolate_point", ParameterList() << Parameter( "geometry" )
+ << Parameter( "distance" ), fcnLineInterpolatePoint, "GeometryGroup" )
+ << new StaticFunction( "line_interpolate_angle", ParameterList() << Parameter( "geometry" )
+ << Parameter( "distance" ), fcnLineInterpolateAngle, "GeometryGroup" )
+ << new StaticFunction( "line_locate_point", ParameterList() << Parameter( "geometry" )
+ << Parameter( "point" ), fcnLineLocatePoint, "GeometryGroup" )
+ << new StaticFunction( "angle_at_vertex", ParameterList() << Parameter( "geometry" )
+ << Parameter( "vertex" ), fcnAngleAtVertex, "GeometryGroup" )
+ << new StaticFunction( "distance_to_vertex", ParameterList() << Parameter( "geometry" )
+ << Parameter( "vertex" ), fcnDistanceToVertex, "GeometryGroup" )
<< new StaticFunction( "$rownum", 0, fcnRowNumber, "deprecated" )
<< new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
<< new StaticFunction( "$currentfeature", 0, fcnFeature, "Record" )
@@ -3492,6 +3581,14 @@ bool QgsExpression::isValid( const QString &text, const QgsExpressionContext *co
return !exp.hasParserError();
}
+void QgsExpression::setExpression( const QString& expression )
+{
+ detach();
+ d->mRootNode = ::parseExpression( expression, d->mParserErrorString );
+ d->mEvalErrorString = QString();
+ d->mExp = expression;
+}
+
void QgsExpression::setScale( double scale ) { d->mScale = scale; }
double QgsExpression::scale() { return d->mScale; }
@@ -3617,6 +3714,18 @@ QgsExpression::~QgsExpression()
delete d;
}
+bool QgsExpression::operator==( const QgsExpression& other ) const
+{
+ if ( d == other.d || d->mExp == other.d->mExp )
+ return true;
+ return false;
+}
+
+bool QgsExpression::isValid() const
+{
+ return d->mRootNode;
+}
+
bool QgsExpression::hasParserError() const { return !d->mParserErrorString.isNull(); }
QString QgsExpression::parserErrorString() const { return d->mParserErrorString; }
@@ -3795,7 +3904,7 @@ int QgsExpression::currentRowNumber() { return d->mRowNumber; }
QString QgsExpression::dump() const
{
if ( !d->mRootNode )
- return tr( "(no root)" );
+ return QString();
return d->mRootNode->dump();
}
@@ -4234,9 +4343,33 @@ QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression *parent, const Q
if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
{
QString esc_regexp = QRegExp::escape( regexp );
- // XXX escape % and _ ???
- esc_regexp.replace( '%', ".*" );
- esc_regexp.replace( '_', '.' );
+ // manage escape % and _
+ if ( esc_regexp.startsWith( '%' ) )
+ {
+ esc_regexp.replace( 0, 1, ".*" );
+ }
+ QRegExp rx( "[^\\\\](%)" );
+ int pos = 0;
+ while (( pos = rx.indexIn( esc_regexp, pos ) ) != -1 )
+ {
+ esc_regexp.replace( pos + 1, 1, ".*" );
+ pos += 1;
+ }
+ rx.setPattern( "\\\\%" );
+ esc_regexp.replace( rx, "%" );
+ if ( esc_regexp.startsWith( '_' ) )
+ {
+ esc_regexp.replace( 0, 1, "." );
+ }
+ rx.setPattern( "[^\\\\](_)" );
+ pos = 0;
+ while (( pos = rx.indexIn( esc_regexp, pos ) ) != -1 )
+ {
+ esc_regexp.replace( pos + 1, 1, '.' );
+ pos += 1;
+ }
+ rx.setPattern( "\\\\_" );
+ esc_regexp.replace( rx, "_" );
matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str );
}
else
diff --git a/src/core/qgsexpression.h b/src/core/qgsexpression.h
index 87dc579..c2854dd 100644
--- a/src/core/qgsexpression.h
+++ b/src/core/qgsexpression.h
@@ -113,7 +113,7 @@ class CORE_EXPORT QgsExpression
/**
* Creates a new expression based on the provided string.
* The string will immediately be parsed. For optimization
- * {@link prepare()} should alwys be called before every
+ * {@link prepare()} should always be called before every
* loop in which this expression is used.
*/
QgsExpression( const QString& expr );
@@ -124,14 +124,39 @@ class CORE_EXPORT QgsExpression
* it does not need to be re-parsed.
*/
QgsExpression( const QgsExpression& other );
+
/**
* Create a copy of this expression. This is preferred
* over recreating an expression from a string since
* it does not need to be re-parsed.
*/
QgsExpression& operator=( const QgsExpression& other );
+
+ /**
+ * Create an empty expression.
+ *
+ * @note Added in QGIS 2.18
+ */
+ QgsExpression();
+
~QgsExpression();
+ /**
+ * Compares two expressions. The operator returns true
+ * if the expression string is equal.
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool operator==( const QgsExpression& other ) const;
+
+ /**
+ * Checks if this expression is valid.
+ * A valid expression could be parsed but does not necessarily evaluate properly.
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool isValid() const;
+
//! Returns true if an error occurred when parsing the input expression
bool hasParserError() const;
//! Returns parser error
@@ -154,7 +179,8 @@ class CORE_EXPORT QgsExpression
/**
* Get list of columns referenced by the expression.
- * @note if the returned list contains the QgsFeatureRequest::AllAttributes constant then
+ *
+ * @note If the returned list contains the QgsFeatureRequest::AllAttributes constant then
* all attributes from the layer are required for evaluation of the expression.
* QgsFeatureRequest::setSubsetOfAttributes automatically handles this case.
*
@@ -251,6 +277,13 @@ class CORE_EXPORT QgsExpression
*/
static bool isValid( const QString& text, const QgsExpressionContext* context, QString &errorMessage );
+ /**
+ * Set the expression string, will reset the whole internal structure.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setExpression( const QString& expression );
+
void setScale( double scale );
double scale();
@@ -497,7 +530,31 @@ class CORE_EXPORT QgsExpression
: mName( fnname )
, mParams( params )
, mUsesGeometry( usesGeometry )
- , mGroup( group )
+ , mGroups( group.isEmpty() ? QStringList() : QStringList() << group )
+ , mHelpText( helpText )
+ , mReferencedColumns( referencedColumns )
+ , mLazyEval( lazyEval )
+ , mHandlesNull( handlesNull )
+ , mIsContextual( isContextual )
+ {
+ }
+
+ /** Constructor for function which uses unnamed parameters and group list
+ * @note added in QGIS 3.0
+ */
+ Function( const QString& fnname,
+ int params,
+ const QStringList& groups,
+ const QString& helpText = QString(),
+ bool usesGeometry = false,
+ const QStringList& referencedColumns = QStringList(),
+ bool lazyEval = false,
+ bool handlesNull = false,
+ bool isContextual = false )
+ : mName( fnname )
+ , mParams( params )
+ , mUsesGeometry( usesGeometry )
+ , mGroups( groups )
, mHelpText( helpText )
, mReferencedColumns( referencedColumns )
, mLazyEval( lazyEval )
@@ -522,7 +579,7 @@ class CORE_EXPORT QgsExpression
, mParams( 0 )
, mParameterList( params )
, mUsesGeometry( usesGeometry )
- , mGroup( group )
+ , mGroups( group.isEmpty() ? QStringList() : QStringList() << group )
, mHelpText( helpText )
, mReferencedColumns( referencedColumns )
, mLazyEval( lazyEval )
@@ -530,6 +587,31 @@ class CORE_EXPORT QgsExpression
, mIsContextual( isContextual )
{}
+ /** Constructor for function which uses named parameter list and group list.
+ * @note added in QGIS 3.0
+ */
+ Function( const QString& fnname,
+ const ParameterList& params,
+ const QStringList& groups,
+ const QString& helpText = QString(),
+ bool usesGeometry = false,
+ const QStringList& referencedColumns = QStringList(),
+ bool lazyEval = false,
+ bool handlesNull = false,
+ bool isContextual = false )
+ : mName( fnname )
+ , mParams( 0 )
+ , mParameterList( params )
+ , mUsesGeometry( usesGeometry )
+ , mGroups( groups )
+ , mHelpText( helpText )
+ , mReferencedColumns( referencedColumns )
+ , mLazyEval( lazyEval )
+ , mHandlesNull( handlesNull )
+ , mIsContextual( isContextual )
+ {}
+
+
virtual ~Function() {}
/** The name of the function. */
@@ -581,8 +663,23 @@ class CORE_EXPORT QgsExpression
*/
bool isContextual() const { return mIsContextual; }
- /** The group the function belongs to. */
- QString group() const { return mGroup; }
+ /** Returns true if the function is deprecated and should not be presented as a valid option
+ * to users in expression builders.
+ * @note added in QGIS 3.0
+ */
+ virtual bool isDeprecated() const { return mGroups.isEmpty() ? false : mGroups.contains( "deprecated" ); }
+
+ /** Returns the first group which the function belongs to.
+ * @note consider using groups() instead, as some functions naturally belong in multiple groups
+ */
+ QString group() const { return mGroups.isEmpty() ? QString() : mGroups.at( 0 ); }
+
+ /** Returns a list of the groups the function belongs to.
+ * @note added in QGIS 3.0
+ * @see group()
+ */
+ QStringList groups() const { return mGroups; }
+
/** The help text for the function. */
//TODO QGIS 3.0 - rename to helpText()
const QString helptext() const { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
@@ -615,7 +712,7 @@ class CORE_EXPORT QgsExpression
int mParams;
ParameterList mParameterList;
bool mUsesGeometry;
- QString mGroup;
+ QStringList mGroups;
QString mHelpText;
QStringList mReferencedColumns;
bool mLazyEval;
@@ -685,6 +782,25 @@ class CORE_EXPORT QgsExpression
, mAliases( aliases )
{}
+ /** Static function for evaluation against a QgsExpressionContext, using a named list of parameter values and list
+ * of groups.
+ */
+ StaticFunction( const QString& fnname,
+ const ParameterList& params,
+ FcnEvalContext fcn,
+ const QStringList& groups,
+ const QString& helpText = QString(),
+ bool usesGeometry = false,
+ const QStringList& referencedColumns = QStringList(),
+ bool lazyEval = false,
+ const QStringList& aliases = QStringList(),
+ bool handlesNull = false )
+ : Function( fnname, params, groups, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
+ , mFnc( nullptr )
+ , mContextFnc( fcn )
+ , mAliases( aliases )
+ {}
+
//! @deprecated use QgsExpressionContext variant instead
Q_DECL_DEPRECATED virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) override;
@@ -1371,11 +1487,6 @@ class CORE_EXPORT QgsExpression
static QString formatPreviewString( const QVariant& value );
protected:
- /**
- * Used by QgsOgcUtils to create an empty
- */
- QgsExpression();
-
void initGeomCalculator();
static QMap<QString, QVariant> gmSpecialColumns;
diff --git a/src/core/qgsexpressioncontext.cpp b/src/core/qgsexpressioncontext.cpp
index ed3c98f..5105603 100644
--- a/src/core/qgsexpressioncontext.cpp
+++ b/src/core/qgsexpressioncontext.cpp
@@ -759,8 +759,8 @@ QgsExpressionContextScope* QgsExpressionContextUtils::mapSettingsScope( const Qg
scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_id", "canvas", true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_rotation", mapSettings.rotation(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_scale", mapSettings.scale(), true ) );
- scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_width", mapSettings.extent().width(), true ) );
- scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_height", mapSettings.extent().height(), true ) );
+ scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_width", mapSettings.visibleExtent().width(), true ) );
+ scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_height", mapSettings.visibleExtent().height(), true ) );
QgsGeometry* centerPoint = QgsGeometry::fromPoint( mapSettings.visibleExtent().center() );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_center", QVariant::fromValue( *centerPoint ), true ) );
delete centerPoint;
diff --git a/src/core/qgsexpressioncontext.h b/src/core/qgsexpressioncontext.h
index b59698b..95ea1dd 100644
--- a/src/core/qgsexpressioncontext.h
+++ b/src/core/qgsexpressioncontext.h
@@ -337,7 +337,7 @@ class CORE_EXPORT QgsExpressionContext
/** Returns the index of the first scope with a matching name within the context.
* @param scopeName name of scope to find
* @returns index of scope, or -1 if scope was not found within the context.
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
int indexOfScope( const QString& scopeName ) const;
diff --git a/src/core/qgsexpressionfieldbuffer.cpp b/src/core/qgsexpressionfieldbuffer.cpp
index 2da2602..5ded28d 100644
--- a/src/core/qgsexpressionfieldbuffer.cpp
+++ b/src/core/qgsexpressionfieldbuffer.cpp
@@ -33,6 +33,11 @@ void QgsExpressionFieldBuffer::removeExpression( int index )
mExpressions.removeAt( index );
}
+void QgsExpressionFieldBuffer::renameExpression( int index, const QString& name )
+{
+ mExpressions[index].field.setName( name );
+}
+
void QgsExpressionFieldBuffer::updateExpression( int index, const QString& exp )
{
mExpressions[index].expression = exp;
diff --git a/src/core/qgsexpressionfieldbuffer.h b/src/core/qgsexpressionfieldbuffer.h
index 0d47fc0..0cecbb8 100644
--- a/src/core/qgsexpressionfieldbuffer.h
+++ b/src/core/qgsexpressionfieldbuffer.h
@@ -68,6 +68,16 @@ class CORE_EXPORT QgsExpressionFieldBuffer
void removeExpression( int index );
/**
+ * Renames an expression field at a given index
+ *
+ * @param index The index of the expression to change
+ * @param name New name for field
+ *
+ * @note added in 3.0
+ */
+ void renameExpression( int index, const QString& name );
+
+ /**
* Changes the expression at a given index
*
* @param index The index of the expression to change
diff --git a/src/core/qgsfeedback.h b/src/core/qgsfeedback.h
new file mode 100644
index 0000000..cdde1d3
--- /dev/null
+++ b/src/core/qgsfeedback.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ qgsfeedback.h
+ --------------------------------------
+ Date : July 2016
+ Copyright : (C) 2016 by Martin Dobias
+ Email : wonder dot sk at gmail dot com
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSFEEDBACK_H
+#define QGSFEEDBACK_H
+
+#include <QObject>
+
+/** \ingroup core
+ * Base class for feedback objects to be used for cancellation of something running in a worker thread.
+ * The class may be used as is or it may be subclassed for extended functionality
+ * for a particular operation (e.g. report progress or pass some data for preview).
+ *
+ * When cancel() is called, the internal code has two options to check for cancellation state:
+ * - if the worker thread uses an event loop (e.g. for network communication), the code can
+ * make a queued connection to cancelled() signal and handle the cancellation in its slot.
+ * - if the worker thread does not use an event loop, it can poll isCancelled() method regularly
+ * to see if the operation should be cancelled.
+ *
+ * The class is meant to be created and destroyed in the main thread.
+ *
+ * For map rendering, the object may be created in constructor of a QgsMapLayerRenderer
+ * subclass and available with QgsMapLayerRenderer::feedback() method. When a map rendering job
+ * gets cancelled, the cancel() method is called on the feedback object of all layers.
+ *
+ * @note added in QGIS 2.18
+ */
+class CORE_EXPORT QgsFeedback : public QObject
+{
+ Q_OBJECT
+ public:
+ //! Construct a feedback object
+ QgsFeedback( QObject* parent = nullptr )
+ : QObject( parent )
+ , mCancelled( false )
+ {}
+
+ virtual ~QgsFeedback() {}
+
+ //! Tells the internal routines that the current operation should be cancelled. This should be run by the main thread
+ void cancel()
+ {
+ if ( mCancelled )
+ return; // only emit the signal once
+ mCancelled = true;
+ emit cancelled();
+ }
+
+ //! Tells whether the operation has been cancelled already
+ bool isCancelled() const { return mCancelled; }
+
+ signals:
+ //! Internal routines can connect to this signal if they use event loop
+ void cancelled();
+
+ private:
+ //! Whether the operation has been cancelled already. False by default.
+ bool mCancelled;
+};
+
+#endif // QGSFEEDBACK_H
diff --git a/src/core/qgsfield.cpp b/src/core/qgsfield.cpp
index fd06b32..6d9ec35 100644
--- a/src/core/qgsfield.cpp
+++ b/src/core/qgsfield.cpp
@@ -86,6 +86,14 @@ QString QgsField::name() const
return d->name;
}
+QString QgsField::displayName() const
+{
+ if ( !d->alias.isEmpty() )
+ return d->alias;
+ else
+ return d->name;
+}
+
QVariant::Type QgsField::type() const
{
return d->type;
@@ -111,6 +119,11 @@ QString QgsField::comment() const
return d->comment;
}
+bool QgsField::isNumeric() const
+{
+ return d->type == QVariant::Double || d->type == QVariant::Int || d->type == QVariant::UInt || d->type == QVariant::LongLong || d->type == QVariant::ULongLong;
+}
+
/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
* full unit tests in testqgsfield.cpp.
@@ -146,6 +159,26 @@ void QgsField::setComment( const QString& comment )
d->comment = comment;
}
+QString QgsField::defaultValueExpression() const
+{
+ return d->defaultValueExpression;
+}
+
+void QgsField::setDefaultValueExpression( const QString& expression )
+{
+ d->defaultValueExpression = expression;
+}
+
+QString QgsField::alias() const
+{
+ return d->alias;
+}
+
+void QgsField::setAlias( const QString& alias )
+{
+ d->alias = alias;
+}
+
/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
* full unit tests in testqgsfield.cpp.
@@ -247,20 +280,24 @@ QDataStream& operator<<( QDataStream& out, const QgsField& field )
out << field.length();
out << field.precision();
out << field.comment();
+ out << field.alias();
+ out << field.defaultValueExpression();
return out;
}
QDataStream& operator>>( QDataStream& in, QgsField& field )
{
quint32 type, length, precision;
- QString name, typeName, comment;
- in >> name >> type >> typeName >> length >> precision >> comment;
+ QString name, typeName, comment, alias, defaultValueExpression;
+ in >> name >> type >> typeName >> length >> precision >> comment >> alias >> defaultValueExpression;
field.setName( name );
field.setType( static_cast< QVariant::Type >( type ) );
field.setTypeName( typeName );
field.setLength( static_cast< int >( length ) );
field.setPrecision( static_cast< int >( precision ) );
field.setComment( comment );
+ field.setAlias( alias );
+ field.setDefaultValueExpression( defaultValueExpression );
return in;
}
diff --git a/src/core/qgsfield.h b/src/core/qgsfield.h
index 13efb92..b1708a4 100644
--- a/src/core/qgsfield.h
+++ b/src/core/qgsfield.h
@@ -43,6 +43,16 @@ class QgsFieldsPrivate;
class CORE_EXPORT QgsField
{
+ Q_GADGET
+
+ Q_PROPERTY( bool isNumeric READ isNumeric )
+ Q_PROPERTY( int length READ length WRITE setLength )
+ Q_PROPERTY( int precision READ precision WRITE setPrecision )
+ Q_PROPERTY( QString comment READ comment WRITE setComment )
+ Q_PROPERTY( QString name READ name WRITE setName )
+ Q_PROPERTY( QString alias READ alias WRITE setAlias )
+ Q_PROPERTY( QString defaultValueExpression READ defaultValueExpression WRITE setDefaultValueExpression )
+
public:
/** Constructor. Constructs a new QgsField object.
* @param name Field name
@@ -76,9 +86,20 @@ class CORE_EXPORT QgsField
bool operator==( const QgsField& other ) const;
bool operator!=( const QgsField& other ) const;
- //! Gets the name of the field
+ /** Returns the name of the field.
+ * @see setName()
+ * @see displayName()
+ */
QString name() const;
+ /** Returns the name to use when displaying this field. This will be the
+ * field alias if set, otherwise the field name.
+ * @see name()
+ * @see alias()
+ * @note added in QGIS 2.18
+ */
+ QString displayName() const;
+
//! Gets variant type of the field as it will be retrieved from data source
QVariant::Type type() const;
@@ -108,6 +129,14 @@ class CORE_EXPORT QgsField
QString comment() const;
/**
+ * Returns if this field is numeric. Any integer or floating point type
+ * will return true for this.
+ *
+ * @note added in QGIS 2.18
+ */
+ bool isNumeric() const;
+
+ /**
* Set the field name.
* @param name Name of the field
*/
@@ -141,6 +170,36 @@ class CORE_EXPORT QgsField
*/
void setComment( const QString& comment );
+ /** Returns the expression used when calculating the default value for the field.
+ * @returns expression evaluated when calculating default values for field, or an
+ * empty string if no default is set
+ * @note added in QGIS 2.18
+ * @see setDefaultValueExpression()
+ */
+ QString defaultValueExpression() const;
+
+ /** Sets an expression to use when calculating the default value for the field.
+ * @param expression expression to evaluate when calculating default values for field. Pass
+ * an empty expression to clear the default.
+ * @note added in QGIS 2.18
+ * @see defaultValueExpression()
+ */
+ void setDefaultValueExpression( const QString& expression );
+
+ /** Returns the alias for the field (the friendly displayed name of the field ),
+ * or an empty string if there is no alias.
+ * @see setAlias()
+ * @note added in QGIS 2.18
+ */
+ QString alias() const;
+
+ /** Sets the alias for the field (the friendly displayed name of the field ).
+ * @param alias field alias, or empty string to remove an existing alias
+ * @see alias()
+ * @note added in QGIS 2.18
+ */
+ void setAlias( const QString& alias );
+
/** Formats string for display*/
QString displayString( const QVariant& v ) const;
diff --git a/src/core/qgsfield_p.h b/src/core/qgsfield_p.h
index 626417b..186490c 100644
--- a/src/core/qgsfield_p.h
+++ b/src/core/qgsfield_p.h
@@ -65,6 +65,8 @@ class QgsFieldPrivate : public QSharedData
, length( other.length )
, precision( other.precision )
, comment( other.comment )
+ , alias( other.alias )
+ , defaultValueExpression( other.defaultValueExpression )
{
}
@@ -73,7 +75,8 @@ class QgsFieldPrivate : public QSharedData
bool operator==( const QgsFieldPrivate& other ) const
{
return (( name == other.name ) && ( type == other.type )
- && ( length == other.length ) && ( precision == other.precision ) );
+ && ( length == other.length ) && ( precision == other.precision )
+ && ( alias == other.alias ) && ( defaultValueExpression == other.defaultValueExpression ) );
}
//! Name
@@ -93,6 +96,12 @@ class QgsFieldPrivate : public QSharedData
//! Comment
QString comment;
+
+ //! Alias for field name (friendly name shown to users)
+ QString alias;
+
+ //! Default value expression
+ QString defaultValueExpression;
};
diff --git a/src/core/qgsgeometryvalidator.cpp b/src/core/qgsgeometryvalidator.cpp
index fdbad39..163fdc3 100644
--- a/src/core/qgsgeometryvalidator.cpp
+++ b/src/core/qgsgeometryvalidator.cpp
@@ -147,11 +147,31 @@ void QgsGeometryValidator::validatePolyline( int i, QgsPolyline line, bool ring
if ( !intersectLines( line[j], v, line[k], w, s ) )
continue;
- double d = -distLine2Point( line[j], v.perpVector(), s );
+ double d = 0.0;
+ try
+ {
+ d = -distLine2Point( line[j], v.perpVector(), s );
+ }
+ catch ( QgsException & e )
+ {
+ Q_UNUSED( e );
+ QgsDebugMsg( "Error validating: " + e.what() );
+ continue;
+ }
if ( d < 0 || d > vl )
continue;
- d = -distLine2Point( line[k], w.perpVector(), s );
+ try
+ {
+ d = -distLine2Point( line[k], w.perpVector(), s );
+ }
+ catch ( QgsException & e )
+ {
+ Q_UNUSED( e );
+ QgsDebugMsg( "Error validating: " + e.what() );
+ continue;
+ }
+
if ( d <= 0 || d >= w.length() )
continue;
diff --git a/src/core/qgsgml.cpp b/src/core/qgsgml.cpp
index 5a50123..4238f5e 100644
--- a/src/core/qgsgml.cpp
+++ b/src/core/qgsgml.cpp
@@ -84,6 +84,20 @@ int QgsGml::getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangl
}
QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );
+ if ( !authcfg.isEmpty() )
+ {
+ if ( !QgsAuthManager::instance()->updateNetworkReply( reply, authcfg ) )
+ {
+ reply->deleteLater();
+ QgsMessageLog::logMessage(
+ tr( "GML Getfeature network reply update failed for authcfg %1" ).arg( authcfg ),
+ tr( "Network" ),
+ QgsMessageLog::CRITICAL
+ );
+ return 1;
+ }
+ }
+
connect( reply, SIGNAL( finished() ), this, SLOT( setFinished() ) );
connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( handleProgressEvent( qint64, qint64 ) ) );
@@ -454,7 +468,7 @@ QVector<QgsGmlStreamingParser::QgsGmlFeaturePtrGmlIdPair> QgsGmlStreamingParser:
}
#define LOCALNAME_EQUALS(string_constant) \
- ( localNameLen == strlen( string_constant ) && memcmp(pszLocalName, string_constant, localNameLen) == 0 )
+ ( localNameLen == ( int )strlen( string_constant ) && memcmp(pszLocalName, string_constant, localNameLen) == 0 )
void QgsGmlStreamingParser::startElement( const XML_Char* el, const XML_Char** attr )
{
@@ -675,7 +689,7 @@ void QgsGmlStreamingParser::startElement( const XML_Char* el, const XML_Char** a
isGeom = true;
}
else if ( isGMLNS &&
- localNameLen == strlen( "Polygon" ) && memcmp( pszLocalName, "Polygon", localNameLen ) == 0 )
+ localNameLen == ( int )strlen( "Polygon" ) && memcmp( pszLocalName, "Polygon", localNameLen ) == 0 )
{
isGeom = true;
mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
diff --git a/src/core/qgslabelfeature.h b/src/core/qgslabelfeature.h
index f99b67a..4d1935a 100644
--- a/src/core/qgslabelfeature.h
+++ b/src/core/qgslabelfeature.h
@@ -112,7 +112,7 @@ class CORE_EXPORT QgsLabelFeature
* are not contained within the zone.
* @param geometry permissible zone geometry. If an invalid QgsGeometry is passed then no zone limit
* will be applied to the label candidates (this is the default behaviour).
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
* @see permissibleZone()
*/
void setPermissibleZone( const QgsGeometry& geometry );
@@ -120,7 +120,7 @@ class CORE_EXPORT QgsLabelFeature
/** Returns the label's permissible zone geometry. If a valid geometry is returned, the feature's label
* MUST be fully contained within this zone, and the feature will not be labeled if no candidates can be
* generated which are not contained within the zone.
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
* @see setPermissibleZone()
* @see permissibleZonePrepared()
*/
@@ -128,7 +128,7 @@ class CORE_EXPORT QgsLabelFeature
/** Returns a GEOS prepared geometry representing the label's permissibleZone().
* @see permissibleZone()
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
//TODO - remove when QgsGeometry caches GEOS preparedness
const GEOSPreparedGeometry* permissibleZonePrepared() const { return mPermissibleZoneGeosPrepared; }
diff --git a/src/core/qgslabelingenginev2.cpp b/src/core/qgslabelingenginev2.cpp
index 5bc40b6..55ca7ae 100644
--- a/src/core/qgslabelingenginev2.cpp
+++ b/src/core/qgslabelingenginev2.cpp
@@ -71,9 +71,9 @@ class QgsLabelSorter
QgsLabelingEngineV2::QgsLabelingEngineV2()
: mFlags( RenderOutlineLabels | UsePartialCandidates )
, mSearchMethod( QgsPalLabeling::Chain )
- , mCandPoint( 8 )
- , mCandLine( 8 )
- , mCandPolygon( 8 )
+ , mCandPoint( 16 )
+ , mCandLine( 50 )
+ , mCandPolygon( 30 )
, mResults( nullptr )
{
mResults = new QgsLabelingResults;
@@ -343,9 +343,9 @@ void QgsLabelingEngineV2::readSettingsFromProject()
bool saved = false;
QgsProject* prj = QgsProject::instance();
mSearchMethod = static_cast< QgsPalLabeling::Search >( prj->readNumEntry( "PAL", "/SearchMethod", static_cast< int >( QgsPalLabeling::Chain ), &saved ) );
- mCandPoint = prj->readNumEntry( "PAL", "/CandidatesPoint", 8, &saved );
- mCandLine = prj->readNumEntry( "PAL", "/CandidatesLine", 8, &saved );
- mCandPolygon = prj->readNumEntry( "PAL", "/CandidatesPolygon", 8, &saved );
+ mCandPoint = prj->readNumEntry( "PAL", "/CandidatesPoint", 16, &saved );
+ mCandLine = prj->readNumEntry( "PAL", "/CandidatesLine", 50, &saved );
+ mCandPolygon = prj->readNumEntry( "PAL", "/CandidatesPolygon", 30, &saved );
mFlags = nullptr;
if ( prj->readBoolEntry( "PAL", "/ShowingCandidates", false, &saved ) ) mFlags |= DrawCandidates;
diff --git a/src/core/qgslegendrenderer.cpp b/src/core/qgslegendrenderer.cpp
index 8d49139..aad4a2e 100644
--- a/src/core/qgslegendrenderer.cpp
+++ b/src/core/qgslegendrenderer.cpp
@@ -594,8 +594,7 @@ QgsComposerLegendStyle::Style QgsLegendRenderer::nodeLegendStyle( QgsLayerTreeNo
return QgsComposerLegendStyle::Group;
else if ( QgsLayerTree::isLayer( node ) )
{
- QList<QgsLayerTreeModelLegendNode*> legendNodes = model->layerLegendNodes( QgsLayerTree::toLayer( node ) );
- if ( legendNodes.count() == 1 && legendNodes[0]->isEmbeddedInParent() )
+ if ( model->legendNodeEmbeddedInParent( QgsLayerTree::toLayer( node ) ) )
return QgsComposerLegendStyle::Hidden;
return QgsComposerLegendStyle::Subgroup;
}
diff --git a/src/core/qgsmaplayer.cpp b/src/core/qgsmaplayer.cpp
index 0b0fbd9..df2e483 100644
--- a/src/core/qgsmaplayer.cpp
+++ b/src/core/qgsmaplayer.cpp
@@ -246,7 +246,9 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
// This is modified version of old QgsWmsProvider::parseUri
// The new format has always params crs,format,layers,styles and that params
// should not appear in old format url -> use them to identify version
- if ( !mDataSource.contains( "crs=" ) && !mDataSource.contains( "format=" ) )
+ // XYZ tile layers do not need to contain crs,format params, but they have type=xyz
+ if ( !mDataSource.contains( "type=" ) &&
+ !mDataSource.contains( "crs=" ) && !mDataSource.contains( "format=" ) )
{
QgsDebugMsg( "Old WMS URI format detected -> converting to new format" );
QgsDataSourceURI uri;
diff --git a/src/core/qgsmaplayerrenderer.h b/src/core/qgsmaplayerrenderer.h
index 20ec0a5..9195416 100644
--- a/src/core/qgsmaplayerrenderer.h
+++ b/src/core/qgsmaplayerrenderer.h
@@ -18,6 +18,8 @@
#include <QStringList>
+class QgsFeedback;
+
/** \ingroup core
* Base class for utility classes that encapsulate information necessary
* for rendering of map layers. The rendering is typically done in a background
@@ -49,6 +51,10 @@ class CORE_EXPORT QgsMapLayerRenderer
//! Do the rendering (based on data stored in the class)
virtual bool render() = 0;
+ //! Access to feedback object of the layer renderer (may be null)
+ //! @note added in QGIS 2.18
+ virtual QgsFeedback* feedback() const { return nullptr; }
+
//! Return list of errors (problems) that happened during the rendering
QStringList errors() const { return mErrors; }
diff --git a/src/core/qgsmaprenderercustompainterjob.cpp b/src/core/qgsmaprenderercustompainterjob.cpp
index 6ddb709..2e2dce5 100644
--- a/src/core/qgsmaprenderercustompainterjob.cpp
+++ b/src/core/qgsmaprenderercustompainterjob.cpp
@@ -15,6 +15,7 @@
#include "qgsmaprenderercustompainterjob.h"
+#include "qgsfeedback.h"
#include "qgslabelingenginev2.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
@@ -74,7 +75,7 @@ void QgsMapRendererCustomPainterJob::start()
#ifndef QT_NO_DEBUG
QPaintDevice* thePaintDevice = mPainter->device();
QString errMsg = QString( "pre-set DPI not equal to painter's DPI (%1 vs %2)" ).arg( thePaintDevice->logicalDpiX() ).arg( mSettings.outputDpi() );
- Q_ASSERT_X( qgsDoubleNear( thePaintDevice->logicalDpiX(), mSettings.outputDpi() ), "Job::startRender()", errMsg.toAscii().data() );
+ Q_ASSERT_X( thePaintDevice->logicalDpiX() == round( mSettings.outputDpi() ), "Job::startRender()", errMsg.toAscii().data() );
#endif
delete mLabelingEngine;
@@ -97,14 +98,6 @@ void QgsMapRendererCustomPainterJob::start()
}
mLayerJobs = prepareJobs( mPainter, mLabelingEngine, mLabelingEngineV2 );
- // prepareJobs calls mapLayer->createMapRenderer may involve cloning a RasterDataProvider,
- // whose constructor may need to download some data (i.e. WMS, AMS) and doing so runs a
- // QEventLoop waiting for the network request to complete. If unluckily someone calls
- // mapCanvas->refresh() while this is happening, QgsMapRendererCustomPainterJob::cancel is
- // called, deleting the QgsMapRendererCustomPainterJob while this function is running.
- // Hence we need to check whether the job is still active before proceeding
- if ( !isActive() )
- return;
QgsDebugMsg( "Rendering prepared in (seconds): " + QString( "%1" ).arg( prepareTime.elapsed() / 1000.0 ) );
@@ -138,6 +131,8 @@ void QgsMapRendererCustomPainterJob::cancel()
for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
{
it->context.setRenderingStopped( true );
+ if ( it->renderer && it->renderer->feedback() )
+ it->renderer->feedback()->cancel();
}
QTime t;
@@ -273,7 +268,9 @@ void QgsMapRendererCustomPainterJob::doRender()
if ( job.img )
{
// If we flattened this layer for alternate blend modes, composite it now
+ mPainter->setOpacity( job.opacity );
mPainter->drawImage( 0, 0, *job.img );
+ mPainter->setOpacity( 1.0 );
}
}
@@ -408,6 +405,12 @@ bool QgsMapRendererJob::needTemporaryImage( QgsMapLayer* ml )
return true;
}
}
+ else if ( ml->type() == QgsMapLayer::RasterLayer )
+ {
+ // preview of intermediate raster rendering results requires a temporary output image
+ if ( mSettings.testFlag( QgsMapSettings::RenderPartialOutput ) )
+ return true;
+ }
return false;
}
diff --git a/src/core/qgsmaprendererjob.cpp b/src/core/qgsmaprendererjob.cpp
index dbdb26f..c177a27 100644
--- a/src/core/qgsmaprendererjob.cpp
+++ b/src/core/qgsmaprendererjob.cpp
@@ -245,6 +245,11 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsPalLabelin
job.cached = false;
job.img = nullptr;
job.blendMode = ml->blendMode();
+ job.opacity = 1.0;
+ if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ) )
+ {
+ job.opacity = 1.0 - vl->layerTransparency() / 100.0;
+ }
job.layerId = ml->id();
job.renderingTime = -1;
@@ -361,8 +366,10 @@ QImage QgsMapRendererJob::composeImage( const QgsMapSettings& settings, const La
const LayerRenderJob& job = *it;
painter.setCompositionMode( job.blendMode );
+ painter.setOpacity( job.opacity );
Q_ASSERT( job.img );
+
painter.drawImage( 0, 0, *job.img );
}
diff --git a/src/core/qgsmaprendererjob.h b/src/core/qgsmaprendererjob.h
index 75b04c5..acaacfc 100644
--- a/src/core/qgsmaprendererjob.h
+++ b/src/core/qgsmaprendererjob.h
@@ -46,6 +46,7 @@ struct LayerRenderJob
QImage* img; // may be null if it is not necessary to draw to separate image (e.g. sequential rendering)
QgsMapLayerRenderer* renderer; // must be deleted
QPainter::CompositionMode blendMode;
+ double opacity;
bool cached; // if true, img already contains cached image from previous rendering
QString layerId;
int renderingTime; //!< time it took to render the layer in ms (it is -1 if not rendered or still rendering)
diff --git a/src/core/qgsmaprendererparalleljob.cpp b/src/core/qgsmaprendererparalleljob.cpp
index d4b65b3..5441df0 100644
--- a/src/core/qgsmaprendererparalleljob.cpp
+++ b/src/core/qgsmaprendererparalleljob.cpp
@@ -15,6 +15,7 @@
#include "qgsmaprendererparalleljob.h"
+#include "qgsfeedback.h"
#include "qgslabelingenginev2.h"
#include "qgslogger.h"
#include "qgsmaplayerrenderer.h"
@@ -75,14 +76,6 @@ void QgsMapRendererParallelJob::start()
}
mLayerJobs = prepareJobs( nullptr, mLabelingEngine, mLabelingEngineV2 );
- // prepareJobs calls mapLayer->createMapRenderer may involve cloning a RasterDataProvider,
- // whose constructor may need to download some data (i.e. WMS, AMS) and doing so runs a
- // QEventLoop waiting for the network request to complete. If unluckily someone calls
- // mapCanvas->refresh() while this is happening, QgsMapRendererCustomPainterJob::cancel is
- // called, deleting the QgsMapRendererCustomPainterJob while this function is running.
- // Hence we need to check whether the job is still active before proceeding
- if ( !isActive() )
- return;
QgsDebugMsg( QString( "QThreadPool max thread count is %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
@@ -105,6 +98,8 @@ void QgsMapRendererParallelJob::cancel()
for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
{
it->context.setRenderingStopped( true );
+ if ( it->renderer && it->renderer->feedback() )
+ it->renderer->feedback()->cancel();
}
if ( mStatus == RenderingLayers )
diff --git a/src/core/qgsmapsettings.h b/src/core/qgsmapsettings.h
index ade03a3..59a74c6 100644
--- a/src/core/qgsmapsettings.h
+++ b/src/core/qgsmapsettings.h
@@ -164,7 +164,8 @@ class CORE_EXPORT QgsMapSettings
UseRenderingOptimization = 0x20, //!< Enable vector simplification and other rendering optimizations
DrawSelection = 0x40, //!< Whether vector selections should be shown in the rendered map
DrawSymbolBounds = 0x80, //!< Draw bounds of symbols (for debugging/testing)
- RenderMapTile = 0x100 //!< Draw map such that there are no problems between adjacent tiles
+ RenderMapTile = 0x100, //!< Draw map such that there are no problems between adjacent tiles
+ RenderPartialOutput = 0x200, //!< Whether to make extra effort to update map image with partially rendered layers (better for interactive map canvas). Added in QGIS 2.18
// TODO: ignore scale-based visibility (overview)
};
Q_DECLARE_FLAGS( Flags, Flag )
diff --git a/src/core/qgsmimedatautils.h b/src/core/qgsmimedatautils.h
index a1c4f09..ee0e878 100644
--- a/src/core/qgsmimedatautils.h
+++ b/src/core/qgsmimedatautils.h
@@ -55,5 +55,7 @@ class CORE_EXPORT QgsMimeDataUtils
};
+Q_DECLARE_METATYPE( QgsMimeDataUtils::UriList );
+
#endif // QGSMIMEDATAUTILS_H
diff --git a/src/core/qgsnetworkaccessmanager.cpp b/src/core/qgsnetworkaccessmanager.cpp
index 33bfe0f..4c39ba0 100644
--- a/src/core/qgsnetworkaccessmanager.cpp
+++ b/src/core/qgsnetworkaccessmanager.cpp
@@ -212,7 +212,9 @@ QNetworkReply *QgsNetworkAccessManager::createRequest( QNetworkAccessManager::Op
emit requestCreated( reply );
- // abort request, when network timeout happens
+ // The timer will call abortRequest slot to abort the connection if needed.
+ // The timer is stopped by the finished signal and is restarted on downloadProgress and
+ // uploadProgress.
QTimer *timer = new QTimer( reply );
timer->setObjectName( "timeoutTimer" );
connect( timer, SIGNAL( timeout() ), this, SLOT( abortRequest() ) );
@@ -221,6 +223,8 @@ QNetworkReply *QgsNetworkAccessManager::createRequest( QNetworkAccessManager::Op
connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ), timer, SLOT( start() ) );
connect( reply, SIGNAL( uploadProgress( qint64, qint64 ) ), timer, SLOT( start() ) );
+ connect( reply, SIGNAL( finished( ) ), timer, SLOT( stop( ) ) );
+ QgsDebugMsgLevel( QString( "Created [reply:%1]" ).arg(( qint64 ) reply, 0, 16 ), 3 );
return reply;
}
@@ -233,16 +237,15 @@ void QgsNetworkAccessManager::abortRequest()
QNetworkReply *reply = qobject_cast<QNetworkReply *>( timer->parent() );
Q_ASSERT( reply );
- QgsDebugMsg( QString( "Abort [reply:%1]" ).arg(( qint64 ) reply, 0, 16 ) );
-
+ reply->abort();
+ QgsDebugMsgLevel( QString( "Abort [reply:%1] %2" ).arg(( qint64 ) reply, 0, 16 ).arg( reply->url().toString() ), 3 );
QgsMessageLog::logMessage( tr( "Network request %1 timed out" ).arg( reply->url().toString() ), tr( "Network" ) );
-
- if ( reply->isRunning() )
- reply->close();
-
+ // Notify the application
emit requestTimedOut( reply );
+
}
+
QString QgsNetworkAccessManager::cacheLoadControlName( QNetworkRequest::CacheLoadControl theControl )
{
switch ( theControl )
diff --git a/src/core/qgsofflineediting.cpp b/src/core/qgsofflineediting.cpp
index bb70416..9acb4b9 100644
--- a/src/core/qgsofflineediting.cpp
+++ b/src/core/qgsofflineediting.cpp
@@ -77,7 +77,7 @@ QgsOfflineEditing::~QgsOfflineEditing()
* - remove remote layers
* - mark as offline project
*/
-bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds )
+bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds, bool onlySelected )
{
if ( layerIds.isEmpty() )
{
@@ -102,9 +102,9 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
QMap<QString, QgsVectorJoinList > joinInfoBuffer;
QMap<QString, QgsVectorLayer*> layerIdMapping;
- for ( int i = 0; i < layerIds.count(); i++ )
+ Q_FOREACH ( const QString& layerId, layerIds )
{
- QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerIds.at( i ) );
+ QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerId );
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( layer );
if ( !vl )
continue;
@@ -114,17 +114,17 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
// Join fields are prefixed with the layer name and we do not want the
// field name to change so we stabilize the field name by defining a
// custom prefix with the layername without _offline suffix.
- QgsVectorJoinList::iterator it = joins.begin();
- while ( it != joins.end() )
+ QgsVectorJoinList::iterator joinIt = joins.begin();
+ while ( joinIt != joins.end() )
{
- if (( *it ).prefix.isNull() )
+ if ( joinIt->prefix.isNull() )
{
- QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer(( *it ).joinLayerId ) );
+ QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinIt->joinLayerId ) );
if ( vl )
- ( *it ).prefix = vl->name() + '_';
+ joinIt->prefix = vl->name() + '_';
}
- ++it;
+ ++joinIt;
}
joinInfoBuffer.insert( vl->id(), joins );
}
@@ -139,7 +139,7 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
if ( vl )
{
QString origLayerId = vl->id();
- QgsVectorLayer* newLayer = copyVectorLayer( vl, db, dbPath );
+ QgsVectorLayer* newLayer = copyVectorLayer( vl, db, dbPath, onlySelected );
if ( newLayer )
{
@@ -195,7 +195,7 @@ bool QgsOfflineEditing::convertToOfflineProject( const QString& offlineDataPath,
return false;
}
-bool QgsOfflineEditing::isOfflineProject()
+bool QgsOfflineEditing::isOfflineProject() const
{
return !QgsProject::instance()->readEntry( PROJECT_ENTRY_SCOPE_OFFLINE, PROJECT_ENTRY_KEY_OFFLINE_DB_PATH ).isEmpty();
}
@@ -226,7 +226,7 @@ void QgsOfflineEditing::synchronize()
QgsDebugMsgLevel( QString( "Found %1 offline layers" ).arg( offlineLayers.count() ), 4 );
for ( int l = 0; l < offlineLayers.count(); l++ )
{
- QgsMapLayer* layer = offlineLayers[l];
+ QgsMapLayer* layer = offlineLayers.at( l );
emit layerProgressUpdated( l + 1, offlineLayers.count() );
@@ -252,8 +252,7 @@ void QgsOfflineEditing::synchronize()
QgsVectorLayer* offlineLayer = qobject_cast<QgsVectorLayer*>( layer );
// register this layer with the central layers registry
- QgsMapLayerRegistry::instance()->addMapLayers(
- QList<QgsMapLayer *>() << remoteLayer, true );
+ QgsMapLayerRegistry::instance()->addMapLayers( QList<QgsMapLayer *>() << remoteLayer, true );
// copy style
copySymbology( offlineLayer, remoteLayer );
@@ -315,8 +314,7 @@ void QgsOfflineEditing::synchronize()
// again with the same path
offlineLayer->dataProvider()->invalidateConnections( QgsDataSourceURI( offlineLayer->source() ).database() );
// remove offline layer
- QgsMapLayerRegistry::instance()->removeMapLayers(
- ( QStringList() << qgisLayerId ) );
+ QgsMapLayerRegistry::instance()->removeMapLayers( QStringList() << qgisLayerId );
// disable offline project
@@ -484,7 +482,7 @@ void QgsOfflineEditing::createLoggingTables( sqlite3* db )
*/
}
-QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, const QString& offlineDbPath )
+QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, const QString& offlineDbPath , bool onlySelected )
{
if ( !layer )
return nullptr;
@@ -635,9 +633,25 @@ QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlit
// NOTE: force feature recount for PostGIS layer, else only visible features are counted, before iterating over all features (WORKAROUND)
layer->setSubsetString( layer->subsetString() );
- QgsFeatureIterator fit = layer->dataProvider()->getFeatures();
+ QgsFeatureRequest req;
+
+ if ( onlySelected )
+ {
+ QgsFeatureIds selectedFids = layer->selectedFeaturesIds();
+ if ( !selectedFids.isEmpty() )
+ req.setFilterFids( selectedFids );
+ }
- emit progressModeSet( QgsOfflineEditing::CopyFeatures, layer->dataProvider()->featureCount() );
+ QgsFeatureIterator fit = layer->dataProvider()->getFeatures( req );
+
+ if ( req.filterType() == QgsFeatureRequest::FilterFids )
+ {
+ emit progressModeSet( QgsOfflineEditing::CopyFeatures, layer->selectedFeaturesIds().size() );
+ }
+ else
+ {
+ emit progressModeSet( QgsOfflineEditing::CopyFeatures, layer->dataProvider()->featureCount() );
+ }
int featureCount = 1;
QList<QgsFeatureId> remoteFeatureIds;
@@ -746,14 +760,12 @@ void QgsOfflineEditing::applyFeaturesAdded( QgsVectorLayer* offlineLayer, QgsVec
QString sql = QString( "SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId );
QList<int> newFeatureIds = sqlQueryInts( db, sql );
- // get default value for each field
- const QgsFields& remoteFlds = remoteLayer->fields();
- QVector<QVariant> defaultValues( remoteFlds.count() );
- for ( int i = 0; i < remoteFlds.count(); ++i )
- {
- if ( remoteFlds.fieldOrigin( i ) == QgsFields::OriginProvider )
- defaultValues[i] = remoteLayer->dataProvider()->defaultValue( remoteFlds.fieldOriginIndex( i ) );
- }
+ QgsFields remoteFlds = remoteLayer->fields();
+
+ QgsExpressionContext context;
+ context << QgsExpressionContextUtils::globalScope()
+ << QgsExpressionContextUtils::projectScope()
+ << QgsExpressionContextUtils::layerScope( remoteLayer );
// get new features from offline layer
QgsFeatureList features;
@@ -789,8 +801,13 @@ void QgsOfflineEditing::applyFeaturesAdded( QgsVectorLayer* offlineLayer, QgsVec
// (important especially e.g. for postgis primary key generated from a sequence)
for ( int k = 0; k < newAttrs.count(); ++k )
{
- if ( newAttrs.at( k ).isNull() && !defaultValues.at( k ).isNull() )
- newAttrs[k] = defaultValues.at( k );
+ if ( !newAttrs.at( k ).isNull() )
+ continue;
+
+ if ( !remoteLayer->defaultValueExpression( k ).isEmpty() )
+ newAttrs[k] = remoteLayer->defaultValue( k, f, &context );
+ else if ( remoteFlds.fieldOrigin( k ) == QgsFields::OriginProvider )
+ newAttrs[k] = remoteLayer->dataProvider()->defaultValue( remoteFlds.fieldOriginIndex( k ) );
}
f.setAttributes( newAttrs );
diff --git a/src/core/qgsofflineediting.h b/src/core/qgsofflineediting.h
index 7f9a7e3..0d088cb 100644
--- a/src/core/qgsofflineediting.h
+++ b/src/core/qgsofflineediting.h
@@ -51,14 +51,15 @@ class CORE_EXPORT QgsOfflineEditing : public QObject
~QgsOfflineEditing();
/** Convert current project for offline editing
- * @param offlineDataPath path to offline db file
- * @param offlineDbFile offline db file name
- * @param layerIds list of layer names to convert
+ * @param offlineDataPath Path to offline db file
+ * @param offlineDbFile Offline db file name
+ * @param layerIds List of layer names to convert
+ * @param onlySelected Only copy selected features from layers where a selection is present
*/
- bool convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds );
+ bool convertToOfflineProject( const QString& offlineDataPath, const QString& offlineDbFile, const QStringList& layerIds, bool onlySelected = false );
/** Return true if current project is offline */
- bool isOfflineProject();
+ bool isOfflineProject() const;
/** Synchronize to remote layers */
void synchronize();
@@ -98,7 +99,7 @@ class CORE_EXPORT QgsOfflineEditing : public QObject
void initializeSpatialMetadata( sqlite3 *sqlite_handle );
bool createSpatialiteDB( const QString& offlineDbPath );
void createLoggingTables( sqlite3* db );
- QgsVectorLayer* copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, const QString& offlineDbPath );
+ QgsVectorLayer* copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, const QString& offlineDbPath, bool onlySelected );
void applyAttributesAdded( QgsVectorLayer* remoteLayer, sqlite3* db, int layerId, int commitNo );
void applyFeaturesAdded( QgsVectorLayer* offlineLayer, QgsVectorLayer* remoteLayer, sqlite3* db, int layerId );
diff --git a/src/core/qgsogcutils.cpp b/src/core/qgsogcutils.cpp
index d026b13..fce0bc9 100644
--- a/src/core/qgsogcutils.cpp
+++ b/src/core/qgsogcutils.cpp
@@ -1666,6 +1666,10 @@ static int binaryOperatorFromTagName( const QString& tagName )
static QString binaryOperatorToTagName( QgsExpression::BinaryOperator op )
{
+ if ( op == QgsExpression::boILike )
+ {
+ return "PropertyIsLike";
+ }
return binaryOperatorsTagNamesMap().key( op, QString() );
}
@@ -1752,6 +1756,11 @@ QgsExpression::NodeBinaryOperator* QgsOgcUtils::nodeBinaryOperatorFromOgcFilter(
return nullptr;
}
+ if ( op == QgsExpression::boLike && element.hasAttribute( "matchCase" ) && element.attribute( "matchCase" ) == "false" )
+ {
+ op = QgsExpression::boILike;
+ }
+
QDomElement operandElem = element.firstChildElement();
QgsExpression::Node *expr = nodeFromOgcFilter( operandElem, errorMessage ), *leftOp = expr;
if ( !expr )
@@ -1772,6 +1781,64 @@ QgsExpression::NodeBinaryOperator* QgsOgcUtils::nodeBinaryOperatorFromOgcFilter(
return nullptr;
}
+ if ( op == QgsExpression::boLike || op == QgsExpression::boILike )
+ {
+ QString wildCard;
+ if ( element.hasAttribute( "wildCard" ) )
+ {
+ wildCard = element.attribute( "wildCard" );
+ }
+ QString singleChar;
+ if ( element.hasAttribute( "singleChar" ) )
+ {
+ singleChar = element.attribute( "singleChar" );
+ }
+ QString escape = "\\";
+ if ( element.hasAttribute( "escape" ) )
+ {
+ escape = element.attribute( "escape" );
+ }
+ // replace
+ QString oprValue = static_cast<const QgsExpression::NodeLiteral*>( opRight )->value().toString();
+ if ( !wildCard.isEmpty() && wildCard != "%" )
+ {
+ oprValue.replace( '%', "\\%" );
+ if ( oprValue.startsWith( wildCard ) )
+ {
+ oprValue.replace( 0, 1, "%" );
+ }
+ QRegExp rx( "[^" + QRegExp::escape( escape ) + "](" + QRegExp::escape( wildCard ) + ")" );
+ int pos = 0;
+ while (( pos = rx.indexIn( oprValue, pos ) ) != -1 )
+ {
+ oprValue.replace( pos + 1, 1, "%" );
+ pos += 1;
+ }
+ oprValue.replace( escape + wildCard, wildCard );
+ }
+ if ( !singleChar.isEmpty() && singleChar != "_" )
+ {
+ oprValue.replace( '_', "\\_" );
+ if ( oprValue.startsWith( singleChar ) )
+ {
+ oprValue.replace( 0, 1, "_" );
+ }
+ QRegExp rx( "[^" + QRegExp::escape( escape ) + "](" + QRegExp::escape( singleChar ) + ")" );
+ int pos = 0;
+ while (( pos = rx.indexIn( oprValue, pos ) ) != -1 )
+ {
+ oprValue.replace( pos + 1, 1, "_" );
+ pos += 1;
+ }
+ oprValue.replace( escape + singleChar, singleChar );
+ }
+ if ( !escape.isEmpty() && escape != "\\" )
+ {
+ oprValue.replace( escape + escape, escape );
+ }
+ opRight = new QgsExpression::NodeLiteral( oprValue );
+ }
+
expr = new QgsExpression::NodeBinaryOperator( static_cast< QgsExpression::BinaryOperator >( op ), expr, opRight );
}
@@ -2289,13 +2356,13 @@ QDomElement QgsOgcUtilsExprToFilter::expressionBinaryOperatorToOgcFilter( const
if ( op == QgsExpression::boILike )
boElem.setAttribute( "matchCase", "false" );
- // setup wildcards to <ogc:PropertyIsLike>
+ // setup wildCards to <ogc:PropertyIsLike>
boElem.setAttribute( "wildCard", "%" );
- boElem.setAttribute( "singleChar", "?" );
+ boElem.setAttribute( "singleChar", "_" );
if ( mFilterVersion == QgsOgcUtils::FILTER_OGC_1_0 )
- boElem.setAttribute( "escape", "!" );
+ boElem.setAttribute( "escape", "\\" );
else
- boElem.setAttribute( "escapeChar", "!" );
+ boElem.setAttribute( "escapeChar", "\\" );
}
boElem.appendChild( leftElem );
@@ -2716,6 +2783,8 @@ QDomElement QgsOgcUtilsSQLStatementToFilter::toOgcFilter( const QgsSQLStatement:
opText = "PropertyIsGreaterThan";
else if ( op == QgsSQLStatement::boLike )
opText = "PropertyIsLike";
+ else if ( op == QgsSQLStatement::boILike )
+ opText = "PropertyIsLike";
if ( opText.isEmpty() )
{
@@ -2731,13 +2800,13 @@ QDomElement QgsOgcUtilsSQLStatementToFilter::toOgcFilter( const QgsSQLStatement:
if ( op == QgsSQLStatement::boILike )
boElem.setAttribute( "matchCase", "false" );
- // setup wildcards to <ogc:PropertyIsLike>
+ // setup wildCards to <ogc:PropertyIsLike>
boElem.setAttribute( "wildCard", "%" );
- boElem.setAttribute( "singleChar", "?" );
+ boElem.setAttribute( "singleChar", "_" );
if ( mFilterVersion == QgsOgcUtils::FILTER_OGC_1_0 )
- boElem.setAttribute( "escape", "!" );
+ boElem.setAttribute( "escape", "\\" );
else
- boElem.setAttribute( "escapeChar", "!" );
+ boElem.setAttribute( "escapeChar", "\\" );
}
boElem.appendChild( leftElem );
diff --git a/src/core/qgsogrutils.cpp b/src/core/qgsogrutils.cpp
index b66e1c5..3df9d8a 100644
--- a/src/core/qgsogrutils.cpp
+++ b/src/core/qgsogrutils.cpp
@@ -273,7 +273,7 @@ QgsFeatureList QgsOgrUtils::stringToFeatureList( const QString& string, const Qg
}
OGR_DS_Destroy( hDS );
- VSIUnlink( "/vsimem/clipboard.dat" );
+ VSIUnlink( TO8( randomFileName ) );
return features;
}
diff --git a/src/core/qgsoptional.h b/src/core/qgsoptional.h
new file mode 100644
index 0000000..00a9956
--- /dev/null
+++ b/src/core/qgsoptional.h
@@ -0,0 +1,137 @@
+/***************************************************************************
+ qgsoptional.h - QgsOptional
+
+ ---------------------
+ begin : 7.9.2016
+ copyright : (C) 2016 by Matthias Kuhn
+ email : matthias at opengis.ch
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef QGSOPTIONAL_H
+#define QGSOPTIONAL_H
+
+
+/**
+ * \ingroup core
+ *
+ * \brief QgsOptional is a container for other classes and adds an additional enabled/disabled flag.
+ *
+ * Often it is used for configuration options which can be enabled or disabled but also have
+ * more internal configuration information that should not be lost when disabling and re-enabling.
+ *
+ * @note Added in QGIS 2.18
+ * @note For python you need to use implementations for specific template classes
+ */
+template<class T>
+class CORE_EXPORT QgsOptional
+{
+ public:
+ /**
+ * A QgsOptional is disabled by default if default constructed.
+ */
+ QgsOptional()
+ : mEnabled( false )
+ {
+ }
+
+ /**
+ * A QgsOptional is enabled by default if constructed with payload.
+ */
+ QgsOptional( const T& data )
+ : mEnabled( true )
+ , mData( data )
+ {
+ }
+
+ /**
+ * A QgsOptional constructed with enabled status and data
+ */
+ QgsOptional( const T& data, bool enabled )
+ : mEnabled( enabled )
+ , mData( data )
+ {
+ }
+
+ /**
+ * Compare this QgsOptional to another one.
+ *
+ * This will compare the enabled flag and call the == operator
+ * of the contained class.
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool operator== ( const QgsOptional<T>& other ) const
+ {
+ return mEnabled == other.mEnabled && mData == other.mData;
+ }
+
+ /**
+ * Boolean operator. Will return true if this optional is enabled.
+ */
+ operator bool() const
+ {
+ return mEnabled;
+ }
+
+ /**
+ * Check if this optional is enabled
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool enabled() const
+ {
+ return mEnabled;
+ }
+
+ /**
+ * Set if this optional is enabled
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setEnabled( bool enabled )
+ {
+ mEnabled = enabled;
+ }
+
+ /**
+ * Access the payload data
+ *
+ * @note Added in QGIS 2.18
+ */
+ const T* operator->() const
+ {
+ return &mData;
+ }
+
+ /**
+ * Access the payload data
+ *
+ * @note Added in QGIS 2.18
+ */
+ T data() const
+ {
+ return mData;
+ }
+
+ /**
+ * Set the payload data
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setData( const T& data )
+ {
+ mData = data;
+ }
+
+ private:
+ bool mEnabled;
+ T mData;
+};
+
+#endif // QGSOPTIONAL_H
diff --git a/src/core/qgsoptionalexpression.cpp b/src/core/qgsoptionalexpression.cpp
new file mode 100644
index 0000000..e93771c
--- /dev/null
+++ b/src/core/qgsoptionalexpression.cpp
@@ -0,0 +1,48 @@
+/***************************************************************************
+ qgsoptionalexpression - QgsOptionalExpression
+
+ ---------------------
+ begin : 14.9.2016
+ copyright : (C) 2016 by Matthias Kuhn
+ email : matthias at opengis.ch
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "qgsoptionalexpression.h"
+
+QgsOptionalExpression::QgsOptionalExpression()
+ : QgsOptional<QgsExpression>()
+{
+
+}
+
+QgsOptionalExpression::QgsOptionalExpression( const QgsExpression& expression )
+ : QgsOptional<QgsExpression>( expression )
+{
+
+}
+
+QgsOptionalExpression::QgsOptionalExpression( const QgsExpression& expression, bool enabled )
+ : QgsOptional<QgsExpression>( expression, enabled )
+{
+
+}
+
+void QgsOptionalExpression::writeXml( QDomElement& element )
+{
+ QDomText exp = element.ownerDocument().createTextNode( data().expression() );
+ element.setAttribute( "enabled", enabled() );
+ element.appendChild( exp );
+}
+
+void QgsOptionalExpression::readXml( const QDomElement& element )
+{
+ setEnabled( element.attribute( "enabled" ).toInt() );
+ setData( element.text() );
+}
diff --git a/src/core/qgsoptionalexpression.h b/src/core/qgsoptionalexpression.h
new file mode 100644
index 0000000..8ae56ff
--- /dev/null
+++ b/src/core/qgsoptionalexpression.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ qgsoptionalexpression.h - QgsOptionalExpression
+
+ ---------------------
+ begin : 8.9.2016
+ copyright : (C) 2016 by Matthias Kuhn
+ email : matthias at opengis.ch
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef QGSOPTIONALEXPRESSION_H
+#define QGSOPTIONALEXPRESSION_H
+
+#include "qgsoptional.h"
+#include "qgsexpression.h"
+
+/**
+ * \ingroup core
+ *
+ * An expression with an additional enabled flag.
+ *
+ * This can be used for configuration options where an expression can be enabled
+ * or diabled but when disabled it shouldn't lose it's information for the case
+ * it gets re-enabled later on and a user shouldn't be force to redo the configuration.
+ *
+ * @note Added in QGIS 2.18
+ */
+
+class CORE_EXPORT QgsOptionalExpression : public QgsOptional<QgsExpression>
+{
+ public:
+ /**
+ * Construct a default optional expression.
+ * It will be disabled and with an empty expression.
+ */
+ QgsOptionalExpression();
+
+ /**
+ * Construct an optional expression with the provided expression.
+ * It will be enabled.
+ */
+ QgsOptionalExpression( const QgsExpression& expression );
+
+ /**
+ * Construct an optional expression with the provided expression and enabled state.
+ */
+ QgsOptionalExpression( const QgsExpression& expression, bool enabled );
+
+ /**
+ * Save the optional expression to the provided QDomElement.
+ *
+ * The caller is responsible to pass an empty QDomElement and to append it to
+ * a parent element.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void writeXml( QDomElement& element );
+
+ /**
+ * Read the optional expression from the provided QDomElement.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void readXml( const QDomElement& element );
+};
+
+#if defined(Q_OS_WIN)
+template CORE_EXPORT QgsOptional<QgsExpression>;
+#endif
+
+#endif // QGSOPTIONALEXPRESSION_H
diff --git a/src/core/qgspallabeling.cpp b/src/core/qgspallabeling.cpp
index 6772e7a..32079b7 100644
--- a/src/core/qgspallabeling.cpp
+++ b/src/core/qgspallabeling.cpp
@@ -18,7 +18,6 @@
#include "qgspallabeling.h"
#include "qgstextlabelfeature.h"
#include "qgsunittypes.h"
-#include "qgsstringutils.h"
#include <list>
@@ -130,11 +129,12 @@ QgsPalLayerSettings::QgsPalLayerSettings()
// font processing info
mTextFontFound = true;
mTextFontFamily = QApplication::font().family();
+ useSubstitutions = false;
// text formatting
wrapChar = "";
multilineHeight = 1.0;
- multilineAlign = MultiLeft;
+ multilineAlign = MultiFollowPlacement;
addDirectionSymbol = false;
leftDirectionSymbol = QString( "<" );
rightDirectionSymbol = QString( ">" );
@@ -151,7 +151,7 @@ QgsPalLayerSettings::QgsPalLayerSettings()
bufferColor = Qt::white;
bufferTransp = 0;
bufferNoFill = false;
- bufferJoinStyle = Qt::BevelJoin;
+ bufferJoinStyle = Qt::RoundJoin;
bufferBlendMode = QPainter::CompositionMode_SourceOver;
// shape background
@@ -206,8 +206,8 @@ QgsPalLayerSettings::QgsPalLayerSettings()
offsetType = FromPoint;
angleOffset = 0;
preserveRotation = true;
- maxCurvedCharAngleIn = 20.0;
- maxCurvedCharAngleOut = -20.0;
+ maxCurvedCharAngleIn = 25.0;
+ maxCurvedCharAngleOut = -25.0;
priority = 5;
repeatDistance = 0;
repeatDistanceUnit = MM;
@@ -390,6 +390,8 @@ QgsPalLayerSettings& QgsPalLayerSettings::operator=( const QgsPalLayerSettings &
// font processing info
mTextFontFound = s.mTextFontFound;
mTextFontFamily = s.mTextFontFamily;
+ substitutions = s.substitutions;
+ useSubstitutions = s.useSubstitutions;
// text formatting
wrapChar = s.wrapChar;
@@ -790,6 +792,9 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
{
if ( layer->customProperty( "labeling" ).toString() != QLatin1String( "pal" ) )
{
+ if ( layer->geometryType() == QGis::Point )
+ placement = OrderedPositionsAroundPoint;
+
// for polygons the "over point" (over centroid) placement is better than the default
// "around point" (around centroid) which is more suitable for points
if ( layer->geometryType() == QGis::Polygon )
@@ -849,12 +854,16 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
blendMode = QgsMapRenderer::getCompositionMode(
static_cast< QgsMapRenderer::BlendMode >( layer->customProperty( "labeling/blendMode", QVariant( QgsMapRenderer::BlendNormal ) ).toUInt() ) );
previewBkgrdColor = QColor( layer->customProperty( "labeling/previewBkgrdColor", QVariant( "#ffffff" ) ).toString() );
-
+ QDomDocument doc( "substitutions" );
+ doc.setContent( layer->customProperty( "labeling/substitutions" ).toString() );
+ QDomElement replacementElem = doc.firstChildElement( "substitutions" );
+ substitutions.readXml( replacementElem );
+ useSubstitutions = layer->customProperty( "labeling/useSubstitutions" ).toBool();
// text formatting
wrapChar = layer->customProperty( "labeling/wrapChar" ).toString();
multilineHeight = layer->customProperty( "labeling/multilineHeight", QVariant( 1.0 ) ).toDouble();
- multilineAlign = static_cast< MultiLineAlign >( layer->customProperty( "labeling/multilineAlign", QVariant( MultiLeft ) ).toUInt() );
+ multilineAlign = static_cast< MultiLineAlign >( layer->customProperty( "labeling/multilineAlign", QVariant( MultiFollowPlacement ) ).toUInt() );
addDirectionSymbol = layer->customProperty( "labeling/addDirectionSymbol" ).toBool();
leftDirectionSymbol = layer->customProperty( "labeling/leftDirectionSymbol", QVariant( "<" ) ).toString();
rightDirectionSymbol = layer->customProperty( "labeling/rightDirectionSymbol", QVariant( ">" ) ).toString();
@@ -900,7 +909,7 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
bufferTransp = layer->customProperty( "labeling/bufferTransp" ).toInt();
bufferBlendMode = QgsMapRenderer::getCompositionMode(
static_cast< QgsMapRenderer::BlendMode >( layer->customProperty( "labeling/bufferBlendMode", QVariant( QgsMapRenderer::BlendNormal ) ).toUInt() ) );
- bufferJoinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( "labeling/bufferJoinStyle", QVariant( Qt::BevelJoin ) ).toUInt() );
+ bufferJoinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( "labeling/bufferJoinStyle", QVariant( Qt::RoundJoin ) ).toUInt() );
bufferNoFill = layer->customProperty( "labeling/bufferNoFill", QVariant( false ) ).toBool();
// background
@@ -1042,8 +1051,8 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
}
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();
- maxCurvedCharAngleOut = layer->customProperty( "labeling/maxCurvedCharAngleOut", QVariant( -20.0 ) ).toDouble();
+ maxCurvedCharAngleIn = layer->customProperty( "labeling/maxCurvedCharAngleIn", QVariant( 25.0 ) ).toDouble();
+ maxCurvedCharAngleOut = layer->customProperty( "labeling/maxCurvedCharAngleOut", QVariant( -25.0 ) ).toDouble();
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() );
@@ -1129,6 +1138,14 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
layer->setCustomProperty( "labeling/textTransp", textTransp );
layer->setCustomProperty( "labeling/blendMode", QgsMapRenderer::getBlendModeEnum( blendMode ) );
layer->setCustomProperty( "labeling/previewBkgrdColor", previewBkgrdColor.name() );
+ QDomDocument doc( "substitutions" );
+ QDomElement replacementElem = doc.createElement( "substitutions" );
+ substitutions.writeXml( replacementElem, doc );
+ QString replacementProps;
+ QTextStream stream( &replacementProps );
+ replacementElem.save( stream, -1 );
+ layer->setCustomProperty( "labeling/substitutions", replacementProps );
+ layer->setCustomProperty( "labeling/useSubstitutions", useSubstitutions );
// text formatting
layer->setCustomProperty( "labeling/wrapChar", wrapChar );
@@ -1300,13 +1317,14 @@ void QgsPalLayerSettings::readXml( QDomElement& elem )
blendMode = QgsMapRenderer::getCompositionMode(
static_cast< QgsMapRenderer::BlendMode >( textStyleElem.attribute( "blendMode", QString::number( QgsMapRenderer::BlendNormal ) ).toUInt() ) );
previewBkgrdColor = QColor( textStyleElem.attribute( "previewBkgrdColor", "#ffffff" ) );
-
+ substitutions.readXml( textStyleElem.firstChildElement( "substitutions" ) );
+ useSubstitutions = textStyleElem.attribute( "useSubstitutions" ).toInt();
// text formatting
QDomElement textFormatElem = elem.firstChildElement( "text-format" );
wrapChar = textFormatElem.attribute( "wrapChar" );
multilineHeight = textFormatElem.attribute( "multilineHeight", "1" ).toDouble();
- multilineAlign = static_cast< MultiLineAlign >( textFormatElem.attribute( "multilineAlign", QString::number( MultiLeft ) ).toUInt() );
+ multilineAlign = static_cast< MultiLineAlign >( textFormatElem.attribute( "multilineAlign", QString::number( MultiFollowPlacement ) ).toUInt() );
addDirectionSymbol = textFormatElem.attribute( "addDirectionSymbol" ).toInt();
leftDirectionSymbol = textFormatElem.attribute( "leftDirectionSymbol", "<" );
rightDirectionSymbol = textFormatElem.attribute( "rightDirectionSymbol", ">" );
@@ -1353,7 +1371,7 @@ void QgsPalLayerSettings::readXml( QDomElement& elem )
bufferTransp = textBufferElem.attribute( "bufferTransp" ).toInt();
bufferBlendMode = QgsMapRenderer::getCompositionMode(
static_cast< QgsMapRenderer::BlendMode >( textBufferElem.attribute( "bufferBlendMode", QString::number( QgsMapRenderer::BlendNormal ) ).toUInt() ) );
- bufferJoinStyle = static_cast< Qt::PenJoinStyle >( textBufferElem.attribute( "bufferJoinStyle", QString::number( Qt::BevelJoin ) ).toUInt() );
+ bufferJoinStyle = static_cast< Qt::PenJoinStyle >( textBufferElem.attribute( "bufferJoinStyle", QString::number( Qt::RoundJoin ) ).toUInt() );
bufferNoFill = textBufferElem.attribute( "bufferNoFill", "0" ).toInt();
// background
@@ -1498,8 +1516,8 @@ void QgsPalLayerSettings::readXml( QDomElement& elem )
}
angleOffset = placementElem.attribute( "angleOffset", "0" ).toDouble();
preserveRotation = placementElem.attribute( "preserveRotation", "1" ).toInt();
- maxCurvedCharAngleIn = placementElem.attribute( "maxCurvedCharAngleIn", "20" ).toDouble();
- maxCurvedCharAngleOut = placementElem.attribute( "maxCurvedCharAngleOut", "-20" ).toDouble();
+ maxCurvedCharAngleIn = placementElem.attribute( "maxCurvedCharAngleIn", "25" ).toDouble();
+ maxCurvedCharAngleOut = placementElem.attribute( "maxCurvedCharAngleOut", "-25" ).toDouble();
priority = placementElem.attribute( "priority" ).toInt();
repeatDistance = placementElem.attribute( "repeatDistance", "0" ).toDouble();
repeatDistanceUnit = static_cast< SizeUnit >( placementElem.attribute( "repeatDistanceUnit", QString::number( MM ) ).toUInt() );
@@ -1566,6 +1584,10 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc )
textStyleElem.setAttribute( "textTransp", textTransp );
textStyleElem.setAttribute( "blendMode", QgsMapRenderer::getBlendModeEnum( blendMode ) );
textStyleElem.setAttribute( "previewBkgrdColor", previewBkgrdColor.name() );
+ QDomElement replacementElem = doc.createElement( "substitutions" );
+ substitutions.writeXml( replacementElem, doc );
+ textStyleElem.appendChild( replacementElem );
+ textStyleElem.setAttribute( "useSubstitutions", useSubstitutions );
// text formatting
QDomElement textFormatElem = doc.createElement( "text-format" );
@@ -2318,6 +2340,12 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
labelText = v.isNull() ? "" : v.toString();
}
+ // apply text replacements
+ if ( useSubstitutions )
+ {
+ labelText = substitutions.process( labelText );
+ }
+
// apply capitalization
QgsStringUtils::Capitalization capitalization = QgsStringUtils::MixedCase;
// maintain API - capitalization may have been set in textFont
@@ -2411,7 +2439,7 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
double maxcharanglein = 20.0; // range 20.0-60.0
double maxcharangleout = -20.0; // range 20.0-95.0
- if ( placement == QgsPalLayerSettings::Curved )
+ if ( placement == QgsPalLayerSettings::Curved || placement == QgsPalLayerSettings::PerimeterCurved )
{
maxcharanglein = maxCurvedCharAngleIn;
maxcharangleout = maxCurvedCharAngleOut;
@@ -2506,12 +2534,23 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
}
}
+ // if using perimeter based labeling for polygons, get the polygon's
+ // linear boundary and use that for the label geometry
+ if (( geom->type() == QGis::Polygon )
+ && ( placement == Line || placement == PerimeterCurved ) )
+ {
+ QgsGeometry* boundaryGeom = new QgsGeometry( geom->geometry()->boundary() );
+ geom = boundaryGeom;
+ scopedClonedGeom.reset( boundaryGeom );
+ }
+
const GEOSGeometry* geos_geom = nullptr;
const QgsGeometry* preparedGeom = geom;
QScopedPointer<QgsGeometry> scopedPreparedGeom;
if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, ct, doClip ? extentGeom : nullptr ) )
{
scopedPreparedGeom.reset( QgsPalLabeling::prepareGeometry( geom, context, ct, doClip ? extentGeom : nullptr ) );
+
if ( !scopedPreparedGeom.data() )
return;
preparedGeom = scopedPreparedGeom.data();
@@ -2567,16 +2606,7 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
}
}
- GEOSGeometry* geos_geom_clone;
- GEOSGeomTypes geomType = ( GEOSGeomTypes ) GEOSGeomTypeId_r( QgsGeometry::getGEOSHandler(), geos_geom );
- if (( geomType == GEOS_POLYGON || geomType == GEOS_MULTIPOLYGON ) && repeatDistance > 0 && placement == Line )
- {
- geos_geom_clone = GEOSBoundary_r( QgsGeometry::getGEOSHandler(), geos_geom );
- }
- else
- {
- geos_geom_clone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geos_geom );
- }
+ GEOSGeometry* geos_geom_clone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geos_geom );
GEOSGeometry* geosObstacleGeomClone = nullptr;
if ( geosObstacleGeom )
{
@@ -2803,35 +2833,14 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
ydiff = yd;
}
- //project xPos and yPos from layer to map CRS
- double z = 0;
- if ( ct )
- {
- try
- {
- ct->transformInPlace( xPos, yPos, z );
- }
- catch ( QgsCsException &e )
- {
- Q_UNUSED( e );
- QgsDebugMsgLevel( QString( "Ignoring feature %1 due transformation exception on data-defined position" ).arg( f.id() ), 4 );
- return;
- }
- }
-
- //rotate position with map if data-defined
- if ( dataDefinedPosition && m2p.mapRotation() )
+ //project xPos and yPos from layer to map CRS, handle rotation
+ QgsGeometry ddPoint( new QgsPointV2( xPos, yPos ) );
+ if ( QgsPalLabeling::geometryRequiresPreparation( &ddPoint, context, ct ) )
{
- const QgsPoint& center = context.extent().center();
- QTransform t = QTransform::fromTranslate( center.x(), center.y() );
- t.rotate( -m2p.mapRotation() );
- t.translate( -center.x(), -center.y() );
- qreal xPosR, yPosR;
- qreal xPos_qreal = xPos, yPos_qreal = yPos;
- t.map( xPos_qreal, yPos_qreal, &xPosR, &yPosR );
- xPos = xPosR;
- yPos = yPosR;
-
+ QgsGeometry* newPoint = QgsPalLabeling::prepareGeometry( &ddPoint, context, ct );
+ xPos = static_cast< QgsPointV2* >( newPoint->geometry() )->x();
+ yPos = static_cast< QgsPointV2* >( newPoint->geometry() )->y();
+ delete newPoint;
}
xPos += xdiff;
@@ -2931,7 +2940,8 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
// TODO: only for placement which needs character info
// account for any data defined font metrics adjustments
- lf->calculateInfo( placement == QgsPalLayerSettings::Curved, labelFontMetrics.data(), xform, rasterCompressFactor, maxcharanglein, maxcharangleout );
+ lf->calculateInfo( placement == QgsPalLayerSettings::Curved || placement == QgsPalLayerSettings::PerimeterCurved,
+ labelFontMetrics.data(), xform, rasterCompressFactor, maxcharanglein, maxcharangleout );
// for labelFeature the LabelInfo is passed to feat when it is registered
// TODO: allow layer-wide feature dist in PAL...?
@@ -2960,16 +2970,24 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
}
}
+ if ( distinmapunit ) //convert distance from mm/map units to pixels
+ {
+ distance /= distMapUnitScale.computeMapUnitsPerPixel( context );
+ }
+ else //mm
+ {
+ distance *= vectorScaleFactor;
+ }
+
+ // when using certain placement modes, we force a tiny minimum distance. This ensures that
+ // candidates are created just offset from a border and avoids candidates being incorrectly flagged as colliding with neighbours
+ if ( placement == QgsPalLayerSettings::Line || placement == QgsPalLayerSettings::Curved || placement == QgsPalLayerSettings::PerimeterCurved )
+ {
+ distance = qMax( distance, 1.0 );
+ }
+
if ( !qgsDoubleNear( distance, 0.0 ) )
{
- if ( distinmapunit ) //convert distance from mm/map units to pixels
- {
- distance /= distMapUnitScale.computeMapUnitsPerPixel( context );
- }
- else //mm
- {
- distance *= vectorScaleFactor;
- }
double d = ptOne.distance( ptZero ) * distance;
( *labelFeature )->setDistLabel( d );
}
diff --git a/src/core/qgspallabeling.h b/src/core/qgspallabeling.h
index c82c54a..18dd62a 100644
--- a/src/core/qgspallabeling.h
+++ b/src/core/qgspallabeling.h
@@ -32,6 +32,7 @@
#include "qgsmaprenderer.h" // definition of QgsLabelingEngineInterface
#include "qgsdiagramrendererv2.h"
#include "qgsmapunitscale.h"
+#include "qgsstringutils.h"
namespace pal
{
@@ -89,6 +90,7 @@ class CORE_EXPORT QgsPalLayerSettings
Horizontal, /**< Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only.*/
Free, /**< Arranges candidates scattered throughout a polygon feature. Candidates are rotated to respect the polygon's orientation. Applies to polygon layers only.*/
OrderedPositionsAroundPoint, /**< Candidates are placed in predefined positions around a point. Peference is given to positions with greatest cartographic appeal, eg top right, bottom right, etc. Applies to point layers only.*/
+ PerimeterCurved, /** Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.*/
};
//! Positions for labels when using the QgsPalLabeling::OrderedPositionsAroundPoint placement mode
@@ -373,6 +375,11 @@ class CORE_EXPORT QgsPalLayerSettings
QPainter::CompositionMode blendMode;
QColor previewBkgrdColor;
+ //! Substitution collection for automatic text substitution with labels
+ QgsStringReplacementCollection substitutions;
+ //! True if substitutions should be applied
+ bool useSubstitutions;
+
//-- text formatting
QString wrapChar;
diff --git a/src/core/qgspointlocator.cpp b/src/core/qgspointlocator.cpp
index 3cda556..13b8a81 100644
--- a/src/core/qgspointlocator.cpp
+++ b/src/core/qgspointlocator.cpp
@@ -104,6 +104,8 @@ class QgsPointLocator_VisitorNearestVertex : public IVisitor
int vertexIndex, beforeVertex, afterVertex;
double sqrDist;
QgsPoint pt = geom->closestVertex( mSrcPoint, vertexIndex, beforeVertex, afterVertex, sqrDist );
+ if ( sqrDist < 0 )
+ return; // probably empty geometry
QgsPointLocator::Match m( QgsPointLocator::Vertex, mLocator->mLayer, id, sqrt( sqrDist ), pt, vertexIndex );
// in range queries the filter may reject some matches
@@ -859,6 +861,10 @@ QgsPointLocator::Match QgsPointLocator::nearestEdge( const QgsPoint& point, doub
return Match();
}
+ QGis::GeometryType geomType = mLayer->geometryType();
+ if ( geomType == QGis::Point )
+ return Match();
+
Match m;
QgsPointLocator_VisitorNearestEdge visitor( this, m, point, filter );
QgsRectangle rect( point.x() - tolerance, point.y() - tolerance, point.x() + tolerance, point.y() + tolerance );
@@ -877,6 +883,10 @@ QgsPointLocator::MatchList QgsPointLocator::edgesInRect( const QgsRectangle& rec
return MatchList();
}
+ QGis::GeometryType geomType = mLayer->geometryType();
+ if ( geomType == QGis::Point )
+ return MatchList();
+
MatchList lst;
QgsPointLocator_VisitorEdgesInRect visitor( this, lst, rect, filter );
mRTree->intersectsWithQuery( rect2region( rect ), visitor );
@@ -900,6 +910,10 @@ QgsPointLocator::MatchList QgsPointLocator::pointInPolygon( const QgsPoint& poin
return MatchList();
}
+ QGis::GeometryType geomType = mLayer->geometryType();
+ if ( geomType == QGis::Point || geomType == QGis::Line )
+ return MatchList();
+
MatchList lst;
QgsPointLocator_VisitorArea visitor( this, point, lst );
mRTree->intersectsWithQuery( point2point( point ), visitor );
diff --git a/src/core/qgsproject.cpp b/src/core/qgsproject.cpp
index 7471c6f..2713c80 100644
--- a/src/core/qgsproject.cpp
+++ b/src/core/qgsproject.cpp
@@ -419,7 +419,17 @@ void QgsProject::emitVariablesChanged()
void QgsProject::setFileName( const QString& name )
{
+ if ( name == imp_->file.fileName() )
+ return;
+
+ QString oldHomePath = homePath();
+
imp_->file.setFileName( name );
+ emit fileNameChanged();
+
+ QString newHomePath = homePath();
+ if ( newHomePath != oldHomePath )
+ emit homePathChanged();
setDirty( true );
}
diff --git a/src/core/qgsproject.h b/src/core/qgsproject.h
index 8f05a92..5a8f1c7 100644
--- a/src/core/qgsproject.h
+++ b/src/core/qgsproject.h
@@ -72,6 +72,8 @@ class CORE_EXPORT QgsProject : public QObject
{
Q_OBJECT
Q_PROPERTY( QStringList nonIdentifiableLayers READ nonIdentifiableLayers WRITE setNonIdentifiableLayers NOTIFY nonIdentifiableLayersChanged )
+ Q_PROPERTY( QString fileName READ fileName WRITE setFileName NOTIFY fileNameChanged )
+ Q_PROPERTY( QString homePath READ homePath NOTIFY homePathChanged )
public:
@@ -455,8 +457,14 @@ class CORE_EXPORT QgsProject : public QObject
//! Emitted when the list of layer which are excluded from map identification changes
void nonIdentifiableLayersChanged( QStringList nonIdentifiableLayers );
+ //! Emitted when the file name of the project changes
+ void fileNameChanged();
+
+ //! Emitted when the home path of the project changes
+ void homePathChanged();
+
/** Emitted whenever the expression variables stored in the project have been changed.
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
void variablesChanged();
@@ -474,7 +482,7 @@ class CORE_EXPORT QgsProject : public QObject
/** Causes the project to emit the variablesChanged() signal. This should
* be called whenever expression variables related to the project are changed.
* @see variablesChanged()
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
void emitVariablesChanged();
diff --git a/src/core/qgsprojectproperty.cpp b/src/core/qgsprojectproperty.cpp
index 5bc046f..36900b9 100644
--- a/src/core/qgsprojectproperty.cpp
+++ b/src/core/qgsprojectproperty.cpp
@@ -21,6 +21,18 @@
#include <QDomDocument>
#include <QStringList>
+QgsProperty::QgsProperty()
+{
+}
+
+QgsProperty::~QgsProperty()
+{
+}
+
+QgsPropertyValue::~QgsPropertyValue()
+{
+}
+
void QgsPropertyValue::dump( int tabs ) const
{
QString tabString;
diff --git a/src/core/qgsprojectproperty.h b/src/core/qgsprojectproperty.h
index d5a0ca9..e75bcf0 100644
--- a/src/core/qgsprojectproperty.h
+++ b/src/core/qgsprojectproperty.h
@@ -47,12 +47,8 @@ class QDomDocument;
class CORE_EXPORT QgsProperty
{
public:
-
- QgsProperty()
- {}
-
- virtual ~ QgsProperty()
- {}
+ QgsProperty();
+ virtual ~QgsProperty();
/** Dumps out the keys and values
*
@@ -125,7 +121,7 @@ class CORE_EXPORT QgsPropertyValue : public QgsProperty
: value_( value )
{}
- virtual ~QgsPropertyValue() {}
+ virtual ~QgsPropertyValue();
/** Returns true if is a QgsPropertyKey */
virtual bool isKey() const override { return false; }
@@ -190,7 +186,7 @@ class CORE_EXPORT QgsPropertyKey : public QgsProperty
{
public:
QgsPropertyKey( const QString &name = "" );
- virtual ~ QgsPropertyKey();
+ virtual ~QgsPropertyKey();
/// every key has a name
// @{
@@ -208,7 +204,7 @@ class CORE_EXPORT QgsPropertyKey : public QgsProperty
/// add the given property key
- QgsPropertyKey * addKey( const QString & keyName )
+ QgsPropertyKey *addKey( const QString & keyName )
{
delete mProperties.take( keyName );
mProperties.insert( keyName, new QgsPropertyKey( keyName ) );
diff --git a/src/core/qgsproviderregistry.cpp b/src/core/qgsproviderregistry.cpp
index 8108d2b..9e4d5be 100644
--- a/src/core/qgsproviderregistry.cpp
+++ b/src/core/qgsproviderregistry.cpp
@@ -108,11 +108,8 @@ void QgsProviderRegistry::init()
fileRegexp.setPattern( filePattern );
}
- QListIterator<QFileInfo> it( mLibraryDirectory.entryInfoList() );
- while ( it.hasNext() )
+ Q_FOREACH ( const QFileInfo& fi, mLibraryDirectory.entryInfoList() )
{
- QFileInfo fi( it.next() );
-
if ( !fileRegexp.isEmpty() )
{
if ( fileRegexp.indexIn( fi.fileName() ) == -1 )
diff --git a/src/core/qgsrendercontext.cpp b/src/core/qgsrendercontext.cpp
index 7e212ce..b2292dc 100644
--- a/src/core/qgsrendercontext.cpp
+++ b/src/core/qgsrendercontext.cpp
@@ -130,6 +130,7 @@ QgsRenderContext QgsRenderContext::fromMapSettings( const QgsMapSettings& mapSet
ctx.setFlag( DrawSymbolBounds, mapSettings.testFlag( QgsMapSettings::DrawSymbolBounds ) );
ctx.setFlag( RenderMapTile, mapSettings.testFlag( QgsMapSettings::RenderMapTile ) );
ctx.setFlag( Antialiasing, mapSettings.testFlag( QgsMapSettings::Antialiasing ) );
+ ctx.setFlag( RenderPartialOutput, mapSettings.testFlag( QgsMapSettings::RenderPartialOutput ) );
ctx.setRasterScaleFactor( 1.0 );
ctx.setScaleFactor( mapSettings.outputDpi() / 25.4 ); // = pixels per mm
ctx.setRendererScale( mapSettings.scale() );
diff --git a/src/core/qgsrendercontext.h b/src/core/qgsrendercontext.h
index 413d039..8328138 100644
--- a/src/core/qgsrendercontext.h
+++ b/src/core/qgsrendercontext.h
@@ -65,6 +65,7 @@ class CORE_EXPORT QgsRenderContext
DrawSymbolBounds = 0x20, //!< Draw bounds of symbols (for debugging/testing)
RenderMapTile = 0x40, //!< Draw map such that there are no problems between adjacent tiles
Antialiasing = 0x80, //!< Use antialiasing while drawing
+ RenderPartialOutput = 0x100, //!< Whether to make extra effort to update map image with partially rendered layers (better for interactive map canvas). Added in QGIS 2.18
};
Q_DECLARE_FLAGS( Flags, Flag )
diff --git a/src/core/qgsstringutils.cpp b/src/core/qgsstringutils.cpp
index 0ed5e7c..503c6fd 100644
--- a/src/core/qgsstringutils.cpp
+++ b/src/core/qgsstringutils.cpp
@@ -16,6 +16,7 @@
#include "qgsstringutils.h"
#include <QVector>
#include <QRegExp>
+#include <QTextDocument> // for Qt::escape
#include <QStringList>
#include <QTextBoundaryFinder>
@@ -344,3 +345,130 @@ QString QgsStringUtils::soundex( const QString& string )
return tmp;
}
+
+QString QgsStringUtils::insertLinks( const QString& string, bool *foundLinks )
+{
+ QString converted = string;
+
+ // http://alanstorm.com/url_regex_explained
+ // note - there's more robust implementations available, but we need one which works within the limitation of QRegExp
+ static QRegExp urlRegEx( "(\\b(([\\w-]+://?|www[.])[^\\s()<>]+(?:\\([\\w\\d]+\\)|([^!\"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^_`{|}~\\s]|/))))" );
+ static QRegExp protoRegEx( "^(?:f|ht)tps?://" );
+ static QRegExp emailRegEx( "([\\w._%+-]+@[\\w.-]+\\.[A-Za-z]+)" );
+
+ int offset = 0;
+ bool found = false;
+ while ( urlRegEx.indexIn( converted, offset ) != -1 )
+ {
+ found = true;
+ QString url = urlRegEx.cap( 1 );
+ QString protoUrl = url;
+ if ( protoRegEx.indexIn( protoUrl ) == -1 )
+ {
+ protoUrl.prepend( "http://" );
+ }
+ QString anchor = QString( "<a href=\"%1\">%2</a>" ).arg( Qt::escape( protoUrl ) ).arg( Qt::escape( url ) );
+ converted.replace( urlRegEx.pos( 1 ), url.length(), anchor );
+ offset = urlRegEx.pos( 1 ) + anchor.length();
+ }
+ offset = 0;
+ while ( emailRegEx.indexIn( converted, offset ) != -1 )
+ {
+ found = true;
+ QString email = emailRegEx.cap( 1 );
+ QString anchor = QString( "<a href=\"mailto:%1\">%1</a>" ).arg( Qt::escape( email ) ).arg( Qt::escape( email ) );
+ converted.replace( emailRegEx.pos( 1 ), email.length(), anchor );
+ offset = emailRegEx.pos( 1 ) + anchor.length();
+ }
+
+ if ( foundLinks )
+ *foundLinks = found;
+
+ return converted;
+}
+
+QgsStringReplacement::QgsStringReplacement( const QString& match, const QString& replacement, bool caseSensitive, bool wholeWordOnly )
+ : mMatch( match )
+ , mReplacement( replacement )
+ , mCaseSensitive( caseSensitive )
+ , mWholeWordOnly( wholeWordOnly )
+{
+ if ( mWholeWordOnly )
+ mRx = QRegExp( QString( "\\b%1\\b" ).arg( mMatch ),
+ mCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive );
+}
+
+QString QgsStringReplacement::process( const QString& input ) const
+{
+ QString result = input;
+ if ( !mWholeWordOnly )
+ {
+ return result.replace( mMatch, mReplacement, mCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive );
+ }
+ else
+ {
+ return result.replace( mRx, mReplacement );
+ }
+}
+
+QgsStringMap QgsStringReplacement::properties() const
+{
+ QgsStringMap map;
+ map.insert( "match", mMatch );
+ map.insert( "replace", mReplacement );
+ map.insert( "caseSensitive", mCaseSensitive ? "1" : "0" );
+ map.insert( "wholeWord", mWholeWordOnly ? "1" : "0" );
+ return map;
+}
+
+QgsStringReplacement QgsStringReplacement::fromProperties( const QgsStringMap& properties )
+{
+ return QgsStringReplacement( properties.value( "match" ),
+ properties.value( "replace" ),
+ properties.value( "caseSensitive", "0" ) == "1",
+ properties.value( "wholeWord", "0" ) == "1" );
+}
+
+QString QgsStringReplacementCollection::process( const QString& input ) const
+{
+ QString result = input;
+ Q_FOREACH ( const QgsStringReplacement& r, mReplacements )
+ {
+ result = r.process( result );
+ }
+ return result;
+}
+
+void QgsStringReplacementCollection::writeXml( QDomElement& elem, QDomDocument& doc ) const
+{
+ Q_FOREACH ( const QgsStringReplacement& r, mReplacements )
+ {
+ QgsStringMap props = r.properties();
+ QDomElement propEl = doc.createElement( "replacement" );
+ QgsStringMap::const_iterator it = props.constBegin();
+ for ( ; it != props.constEnd(); ++it )
+ {
+ propEl.setAttribute( it.key(), it.value() );
+ }
+ elem.appendChild( propEl );
+ }
+}
+
+void QgsStringReplacementCollection::readXml( const QDomElement& elem )
+{
+ mReplacements.clear();
+ QDomNodeList nodelist = elem.elementsByTagName( "replacement" );
+ for ( int i = 0;i < nodelist.count(); i++ )
+ {
+ QDomElement replacementElem = nodelist.at( i ).toElement();
+ QDomNamedNodeMap nodeMap = replacementElem.attributes();
+
+ QgsStringMap props;
+ for ( int j = 0; j < nodeMap.count(); ++j )
+ {
+ props.insert( nodeMap.item( j ).nodeName(), nodeMap.item( j ).nodeValue() );
+ }
+ mReplacements << QgsStringReplacement::fromProperties( props );
+ }
+
+}
diff --git a/src/core/qgsstringutils.h b/src/core/qgsstringutils.h
index 5120aba..2142924 100644
--- a/src/core/qgsstringutils.h
+++ b/src/core/qgsstringutils.h
@@ -14,11 +14,149 @@
***************************************************************************/
#include <QString>
+#include <QRegExp>
+#include <QList>
+#include <QDomDocument>
#include <QFont> // for enum values
+#include "qgis.h"
#ifndef QGSSTRINGUTILS_H
#define QGSSTRINGUTILS_H
+
+/** \ingroup core
+ * \class QgsStringReplacement
+ * \brief A representation of a single string replacement.
+ * \note Added in version 3.0
+ */
+
+class CORE_EXPORT QgsStringReplacement
+{
+
+ public:
+
+ /** Constructor for QgsStringReplacement.
+ * @param match string to match
+ * @param replacement string to replace match with
+ * @param caseSensitive set to true for a case sensitive match
+ * @param wholeWordOnly set to true to match complete words only, or false to allow partial word matches
+ */
+ QgsStringReplacement( const QString& match,
+ const QString& replacement,
+ bool caseSensitive = false,
+ bool wholeWordOnly = false );
+
+ //! Returns the string matched by this object
+ QString match() const { return mMatch; }
+
+ //! Returns the string to replace matches with
+ QString replacement() const { return mReplacement; }
+
+ //! Returns true if match is case sensitive
+ bool caseSensitive() const { return mCaseSensitive; }
+
+ //! Returns true if match only applies to whole words, or false if partial word matches are permitted
+ bool wholeWordOnly() const { return mWholeWordOnly; }
+
+ /** Processes a given input string, applying any valid replacements which should be made.
+ * @param input input string
+ * @returns input string with any matches replaced by replacement string
+ */
+ QString process( const QString& input ) const;
+
+ bool operator==( const QgsStringReplacement& other )
+ {
+ return mMatch == other.mMatch
+ && mReplacement == other.mReplacement
+ && mCaseSensitive == other.mCaseSensitive
+ && mWholeWordOnly == other.mWholeWordOnly;
+ }
+
+ /** Returns a map of the replacement properties.
+ * @see fromProperties()
+ */
+ QgsStringMap properties() const;
+
+ /** Creates a new QgsStringReplacement from an encoded properties map.
+ * @see properties()
+ */
+ static QgsStringReplacement fromProperties( const QgsStringMap& properties );
+
+ private:
+
+ QString mMatch;
+
+ QString mReplacement;
+
+ bool mCaseSensitive;
+
+ bool mWholeWordOnly;
+
+ QRegExp mRx;
+};
+
+
+/** \ingroup core
+ * \class QgsStringReplacementCollection
+ * \brief A collection of string replacements (specified using QgsStringReplacement objects).
+ * \note Added in version 3.0
+ */
+
+class CORE_EXPORT QgsStringReplacementCollection
+{
+
+ public:
+
+ /** Constructor for QgsStringReplacementCollection
+ * @param replacements initial list of string replacements
+ */
+ QgsStringReplacementCollection( const QList< QgsStringReplacement >& replacements = QList< QgsStringReplacement >() )
+ : mReplacements( replacements )
+ {}
+
+ /** Returns the list of string replacements in this collection.
+ * @see setReplacements()
+ */
+ QList< QgsStringReplacement > replacements() const { return mReplacements; }
+
+ /** Sets the list of string replacements in this collection.
+ * @param replacements list of string replacements to apply. Replacements are applied in the
+ * order they are specified here.
+ * @see replacements()
+ */
+ void setReplacements( const QList< QgsStringReplacement >& replacements )
+ {
+ mReplacements = replacements;
+ }
+
+ /** Processes a given input string, applying any valid replacements which should be made
+ * using QgsStringReplacement objects contained by this collection. Replacements
+ * are made in order of the QgsStringReplacement objects contained in the collection.
+ * @param input input string
+ * @returns input string with any matches replaced by replacement string
+ */
+ QString process( const QString& input ) const;
+
+ /** Writes the collection state to an XML element.
+ * @param elem target DOM element
+ * @param doc DOM document
+ * @see readXml()
+ */
+ void writeXml( QDomElement& elem, QDomDocument& doc ) const;
+
+ /** Reads the collection state from an XML element.
+ * @param elem DOM element
+ * @see writeXml()
+ */
+ void readXml( const QDomElement& elem );
+
+ private:
+
+ QList< QgsStringReplacement > mReplacements;
+
+
+};
+
/** \ingroup core
* \class QgsStringUtils
* \brief Utility functions for working with strings.
@@ -42,7 +180,7 @@ class CORE_EXPORT QgsStringUtils
* @param string input string
* @param capitalization capitalization type to apply
* @return capitalized string
- * @note added in QGIS 3.0
+ * @note added in QGIS 2.18
*/
static QString capitalize( const QString& string, Capitalization capitalization );
@@ -82,6 +220,15 @@ class CORE_EXPORT QgsStringUtils
* @returns 4 letter Soundex code
*/
static QString soundex( const QString &string );
+
+ /** Returns a string with any URL (eg http(s)/ftp) and mailto: text converted to valid HTML <a ...>
+ * links.
+ * @param string string to insert links into
+ * @param foundLinks if specified, will be set to true if any links were inserted into the string
+ * @returns string with inserted links
+ * @note added in QGIS 2.18
+ */
+ static QString insertLinks( const QString& string, bool* foundLinks = nullptr );
};
#endif //QGSSTRINGUTILS_H
diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp
index 5068d13..5fac29c 100644
--- a/src/core/qgsvectorlayer.cpp
+++ b/src/core/qgsvectorlayer.cpp
@@ -1679,6 +1679,25 @@ bool QgsVectorLayer::readXml( const QDomNode& layer_node )
readStyleManager( layer_node );
+ // default expressions
+ mDefaultExpressionMap.clear();
+ QDomNode defaultsNode = layer_node.namedItem( "defaults" );
+ if ( !defaultsNode.isNull() )
+ {
+ QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( "default" );
+ for ( int i = 0; i < defaultNodeList.size(); ++i )
+ {
+ QDomElement defaultElem = defaultNodeList.at( i ).toElement();
+
+ QString field = defaultElem.attribute( "field", QString() );
+ QString expression = defaultElem.attribute( "expression", QString() );
+ if ( field.isEmpty() || expression.isEmpty() )
+ continue;
+
+ mDefaultExpressionMap.insert( field, expression );
+ }
+ }
+ updateFields();
setLegend( QgsMapLayerLegend::defaultVectorLegend( this ) );
@@ -1880,6 +1899,17 @@ bool QgsVectorLayer::writeXml( QDomNode & layer_node,
// save expression fields
mExpressionFieldBuffer->writeXml( layer_node, document );
+ //default expressions
+ QDomElement defaultsElem = document.createElement( "defaults" );
+ Q_FOREACH ( const QgsField& field, mUpdatedFields )
+ {
+ QDomElement defaultElem = document.createElement( "default" );
+ defaultElem.setAttribute( "field", field.name() );
+ defaultElem.setAttribute( "expression", field.defaultValueExpression() );
+ defaultsElem.appendChild( defaultElem );
+ }
+ layer_node.appendChild( defaultsElem );
+
writeStyleManager( layer_node, document );
// renderer specific settings
@@ -1890,6 +1920,8 @@ bool QgsVectorLayer::writeXml( QDomNode & layer_node,
bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage )
{
+ updateFields();
+
readStyle( node, errorMessage );
// process the attribute actions
@@ -1931,6 +1963,7 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
mAttributeAliasMap.insert( field, aliasElem.attribute( "name" ) );
}
}
+ updateFields();
//Attributes excluded from WMS and WFS
mExcludeAttributesWMS.clear();
@@ -1961,6 +1994,8 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
mConditionalStyles->readXml( node );
+ readCustomProperties( node, "variable" );
+
return true;
}
@@ -2117,24 +2152,16 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString&
node.appendChild( afField );
//attribute aliases
- if ( !mAttributeAliasMap.isEmpty() )
+ QDomElement aliasElem = doc.createElement( "aliases" );
+ Q_FOREACH ( const QgsField& field, mUpdatedFields )
{
- QDomElement aliasElem = doc.createElement( "aliases" );
- QMap<QString, QString>::const_iterator a_it = mAttributeAliasMap.constBegin();
- for ( ; a_it != mAttributeAliasMap.constEnd(); ++a_it )
- {
- int idx = fieldNameIndex( a_it.key() );
- if ( idx < 0 )
- continue;
-
- QDomElement aliasEntryElem = doc.createElement( "alias" );
- aliasEntryElem.setAttribute( "field", a_it.key() );
- aliasEntryElem.setAttribute( "index", idx );
- aliasEntryElem.setAttribute( "name", a_it.value() );
- aliasElem.appendChild( aliasEntryElem );
- }
- node.appendChild( aliasElem );
+ QDomElement aliasEntryElem = doc.createElement( "alias" );
+ aliasEntryElem.setAttribute( "field", field.name() );
+ aliasEntryElem.setAttribute( "index", mUpdatedFields.indexFromName( field.name() ) );
+ aliasEntryElem.setAttribute( "name", field.alias() );
+ aliasElem.appendChild( aliasEntryElem );
}
+ node.appendChild( aliasElem );
//exclude attributes WMS
QDomElement excludeWMSElem = doc.createElement( "excludeAttributesWMS" );
@@ -2371,19 +2398,52 @@ void QgsVectorLayer::remAttributeAlias( int attIndex )
return;
QString name = fields().at( attIndex ).name();
+ mUpdatedFields[ attIndex ].setAlias( QString() );
if ( mAttributeAliasMap.contains( name ) )
{
mAttributeAliasMap.remove( name );
+ updateFields();
emit layerModified();
}
}
-bool QgsVectorLayer::renameAttribute( int attIndex, const QString& newName )
+bool QgsVectorLayer::renameAttribute( int index, const QString& newName )
{
- if ( !mEditBuffer || !mDataProvider )
+ if ( index < 0 || index >= fields().count() )
return false;
- return mEditBuffer->renameAttribute( attIndex, newName );
+ switch ( mUpdatedFields.fieldOrigin( index ) )
+ {
+ case QgsFields::OriginExpression:
+ {
+ if ( mExpressionFieldBuffer )
+ {
+ int oi = mUpdatedFields.fieldOriginIndex( index );
+ mExpressionFieldBuffer->renameExpression( oi, newName );
+ updateFields();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ case QgsFields::OriginProvider:
+ case QgsFields::OriginEdit:
+
+ if ( !mEditBuffer || !mDataProvider )
+ return false;
+
+ return mEditBuffer->renameAttribute( index, newName );
+
+ case QgsFields::OriginJoin:
+ case QgsFields::OriginUnknown:
+ return false;
+
+ }
+
+ return false; //avoid warning
}
void QgsVectorLayer::addAttributeAlias( int attIndex, const QString& aliasString )
@@ -2394,6 +2454,7 @@ void QgsVectorLayer::addAttributeAlias( int attIndex, const QString& aliasString
QString name = fields().at( attIndex ).name();
mAttributeAliasMap.insert( name, aliasString );
+ mUpdatedFields[ attIndex ].setAlias( aliasString );
emit layerModified(); // TODO[MD]: should have a different signal?
}
@@ -2402,22 +2463,26 @@ QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
if ( attributeIndex < 0 || attributeIndex >= fields().count() )
return QString();
- QString name = fields().at( attributeIndex ).name();
-
- return mAttributeAliasMap.value( name, QString() );
+ return fields().at( attributeIndex ).alias();
}
QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const
{
- QString displayName = attributeAlias( attributeIndex );
- if ( displayName.isEmpty() )
+ if ( attributeIndex >= 0 && attributeIndex < mUpdatedFields.count() )
+ return mUpdatedFields.at( attributeIndex ).displayName();
+ else
+ return QString();
+}
+
+QgsStringMap QgsVectorLayer::attributeAliases() const
+{
+ QgsStringMap map;
+ Q_FOREACH ( const QgsField& field, fields() )
{
- if ( attributeIndex >= 0 && attributeIndex < mUpdatedFields.count() )
- {
- displayName = mUpdatedFields.at( attributeIndex ).name();
- }
+ if ( !field.alias().isEmpty() )
+ map.insert( field.name(), field.alias() );
}
- return displayName;
+ return map;
}
bool QgsVectorLayer::deleteAttribute( int index )
@@ -2856,7 +2921,7 @@ void QgsVectorLayer::setCoordinateSystem()
}
-const QString QgsVectorLayer::displayField() const
+QString QgsVectorLayer::displayField() const
{
return mDisplayField;
}
@@ -2866,7 +2931,7 @@ void QgsVectorLayer::setDisplayExpression( const QString &displayExpression )
mDisplayExpression = displayExpression;
}
-const QString QgsVectorLayer::displayExpression()
+QString QgsVectorLayer::displayExpression() const
{
return mDisplayExpression;
}
@@ -3127,6 +3192,25 @@ void QgsVectorLayer::updateFields()
if ( mExpressionFieldBuffer )
mExpressionFieldBuffer->updateFields( mUpdatedFields );
+ // set aliases and default values
+ QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
+ for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
+ {
+ int index = mUpdatedFields.fieldNameIndex( aliasIt.key() );
+ if ( index < 0 )
+ continue;
+
+ mUpdatedFields[ index ].setAlias( aliasIt.value() );
+ }
+ QMap< QString, QString >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
+ for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
+ {
+ int index = mUpdatedFields.fieldNameIndex( defaultIt.key() );
+ if ( index < 0 )
+ continue;
+
+ mUpdatedFields[ index ].setDefaultValueExpression( defaultIt.value() );
+ }
if ( oldFields != mUpdatedFields )
{
emit updatedFields();
@@ -3143,6 +3227,79 @@ void QgsVectorLayer::createJoinCaches()
}
}
+QVariant QgsVectorLayer::defaultValue( int index, const QgsFeature& feature, QgsExpressionContext* context ) const
+{
+ if ( index < 0 || index >= mUpdatedFields.count() )
+ return QVariant();
+
+ QString expression = mUpdatedFields.at( index ).defaultValueExpression();
+ if ( expression.isEmpty() )
+ return mDataProvider->defaultValue( index );
+
+ QgsExpressionContext* evalContext = context;
+ QScopedPointer< QgsExpressionContext > tempContext;
+ if ( !evalContext )
+ {
+ // no context passed, so we create a default one
+ tempContext.reset( new QgsExpressionContext() );
+ tempContext->appendScope( QgsExpressionContextUtils::globalScope() );
+ tempContext->appendScope( QgsExpressionContextUtils::projectScope() );
+ tempContext->appendScope( QgsExpressionContextUtils::layerScope( this ) );
+ evalContext = tempContext.data();
+ }
+
+ if ( feature.isValid() )
+ {
+ QgsExpressionContextScope* featScope = new QgsExpressionContextScope();
+ featScope->setFeature( feature );
+ featScope->setFields( *feature.fields() );
+ evalContext->appendScope( featScope );
+ }
+
+ QVariant val;
+ QgsExpression exp( expression );
+ exp.prepare( evalContext );
+ if ( exp.hasEvalError() )
+ {
+ QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
+ }
+ else
+ {
+ val = exp.evaluate( evalContext );
+ }
+
+ if ( feature.isValid() )
+ {
+ delete evalContext->popScope();
+ }
+
+ return val;
+}
+
+void QgsVectorLayer::setDefaultValueExpression( int index, const QString& expression )
+{
+ if ( index < 0 || index >= mUpdatedFields.count() )
+ return;
+
+ if ( expression.isEmpty() )
+ {
+ mDefaultExpressionMap.remove( mUpdatedFields.at( index ).name() );
+ }
+ else
+ {
+ mDefaultExpressionMap.insert( mUpdatedFields.at( index ).name(), expression );
+ }
+ updateFields();
+}
+
+QString QgsVectorLayer::defaultValueExpression( int index ) const
+{
+ if ( index < 0 || index >= mUpdatedFields.count() )
+ return QString();
+ else
+ return mUpdatedFields.at( index ).defaultValueExpression();
+}
+
void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit )
{
uniqueValues.clear();
@@ -4144,60 +4301,6 @@ QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx )
return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
}
-QDomElement QgsAttributeEditorContainer::toDomElement( QDomDocument& doc ) const
-{
- QDomElement elem = doc.createElement( "attributeEditorContainer" );
- elem.setAttribute( "name", mName );
- elem.setAttribute( "columnCount", mColumnCount );
- elem.setAttribute( "groupBox", mIsGroupBox ? 1 : 0 );
-
- Q_FOREACH ( QgsAttributeEditorElement* child, mChildren )
- {
- elem.appendChild( child->toDomElement( doc ) );
- }
- return elem;
-}
-
-void QgsAttributeEditorContainer::addChildElement( QgsAttributeEditorElement *widget )
-{
- mChildren.append( widget );
-}
-
-void QgsAttributeEditorContainer::setName( const QString& name )
-{
- mName = name;
-}
-
-QList<QgsAttributeEditorElement*> QgsAttributeEditorContainer::findElements( QgsAttributeEditorElement::AttributeEditorType type ) const
-{
- QList<QgsAttributeEditorElement*> results;
-
- Q_FOREACH ( QgsAttributeEditorElement* elem, mChildren )
- {
- if ( elem->type() == type )
- {
- results.append( elem );
- }
-
- if ( elem->type() == AeTypeContainer )
- {
- QgsAttributeEditorContainer* cont = dynamic_cast<QgsAttributeEditorContainer*>( elem );
- if ( cont )
- results += cont->findElements( type );
- }
- }
-
- return results;
-}
-
-QDomElement QgsAttributeEditorField::toDomElement( QDomDocument& doc ) const
-{
- QDomElement elem = doc.createElement( "attributeEditorField" );
- elem.setAttribute( "name", mName );
- elem.setAttribute( "index", mIdx );
- return elem;
-}
-
int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
{
QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
@@ -4324,21 +4427,6 @@ bool QgsVectorLayer::applyNamedStyle( const QString& namedStyle, QString& errorM
return importNamedStyle( myDocument, errorMsg );
}
-
-QDomElement QgsAttributeEditorRelation::toDomElement( QDomDocument& doc ) const
-{
- QDomElement elem = doc.createElement( "attributeEditorRelation" );
- elem.setAttribute( "name", mName );
- elem.setAttribute( "relation", mRelation.id() );
- return elem;
-}
-
-bool QgsAttributeEditorRelation::init( QgsRelationManager* relationManager )
-{
- mRelation = relationManager->relation( mRelationId );
- return mRelation.isValid();
-}
-
QSet<QString> QgsVectorLayer::layerDependencies() const
{
if ( mDataProvider )
diff --git a/src/core/qgsvectorlayer.h b/src/core/qgsvectorlayer.h
index 0505afb..652f744 100644
--- a/src/core/qgsvectorlayer.h
+++ b/src/core/qgsvectorlayer.h
@@ -218,7 +218,7 @@ protected:
* - version=auto/1.0.0/1.1.0/2.0.0
* -sql=string: full SELECT SQL statement with optional WHERE, ORDER BY and possibly with JOIN if supported on server
* - filter=string: QGIS expression or OGC/FES filter
- * - retrictToRequestBBOX=1: to download only features in the view extent (or more generally
+ * - restrictToRequestBBOX=1: to download only features in the view extent (or more generally
* in the bounding box of the feature iterator)
* - maxNumFeatures=number
* - IgnoreAxisOrientation=1: to ignore EPSG axis order for WFS 1.1 or 2.0
@@ -556,7 +556,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
void setDisplayField( const QString& fldName = "" );
/** Returns the primary display field name used in the identify results dialog */
- const QString displayField() const;
+ QString displayField() const;
/** Set the preview expression, used to create a human readable preview string.
* Used e.g. in the attribute table feature list. Uses { @link QgsExpression }.
@@ -572,7 +572,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
*
* @return The expression which will be used to preview features for this layer
*/
- const QString displayExpression();
+ QString displayExpression() const;
/** Returns the data provider */
QgsVectorDataProvider* dataProvider();
@@ -597,6 +597,11 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
@returns true if join was found and successfully removed */
bool removeJoin( const QString& joinLayerId );
+ /**
+ * Acccessor to the join buffer object
+ * @note added 2.14.7
+ */
+ QgsVectorLayerJoinBuffer* joinBuffer() { return mJoinBuffer; }
const QList<QgsVectorJoinInfo> vectorJoins() const;
/**
@@ -1448,7 +1453,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Convenience function that returns the attribute alias if defined or the field name else */
QString attributeDisplayName( int attributeIndex ) const;
- const QMap< QString, QString >& attributeAliases() const { return mAttributeAliasMap; }
+ //! Returns a map of field name to attribute alias
+ QgsStringMap attributeAliases() const;
const QSet<QString>& excludeAttributesWMS() const { return mExcludeAttributesWMS; }
void setExcludeAttributesWMS( const QSet<QString>& att ) { mExcludeAttributesWMS = att; }
@@ -1733,6 +1739,42 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Caches joined attributes if required (and not already done) */
void createJoinCaches();
+ /** Returns the calculated default value for the specified field index. The default
+ * value may be taken from a client side default value expression (see setDefaultValueExpression())
+ * or taken from the underlying data provider.
+ * @param index field index
+ * @param feature optional feature to use for default value evaluation. If passed,
+ * then properties from the feature (such as geometry) can be used when calculating
+ * the default value.
+ * @param context optional expression context to evaluate expressions again. If not
+ * specified, a default context will be created
+ * @return calculated default value
+ * @note added in QGIS 2.18
+ * @see setDefaultValueExpression()
+ */
+ QVariant defaultValue( int index, const QgsFeature& feature = QgsFeature(),
+ QgsExpressionContext* context = nullptr ) const;
+
+ /** Sets an expression to use when calculating the default value for a field.
+ * @param index field index
+ * @param expression expression to evaluate when calculating default values for field. Pass
+ * an empty expression to clear the default.
+ * @note added in QGIS 2.18
+ * @see defaultValue()
+ * @see defaultValueExpression()
+ */
+ void setDefaultValueExpression( int index, const QString& expression );
+
+ /** Returns the expression used when calculating the default value for a field.
+ * @param index field index
+ * @returns expression evaluated when calculating default values for field, or an
+ * empty string if no default is set
+ * @note added in QGIS 2.18
+ * @see defaultValue()
+ * @see setDefaultValueExpression()
+ */
+ QString defaultValueExpression( int index ) const;
+
/** Calculates a list of unique values contained within an attribute in the layer. Note that
* in some circumstances when unsaved changes are present for the layer then the returned list
* may contain outdated values (for instance when the attribute value in a saved feature has
@@ -2197,7 +2239,10 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
QgsFields mUpdatedFields;
/** Map that stores the aliases for attributes. Key is the attribute name and value the alias for that attribute*/
- QMap< QString, QString > mAttributeAliasMap;
+ QgsStringMap mAttributeAliasMap;
+
+ //! Map which stores default value expressions for fields
+ QgsStringMap mDefaultExpressionMap;
/** Holds the configuration for the edit form */
QgsEditFormConfig* mEditFormConfig;
diff --git a/src/core/qgsvectorlayereditbuffer.cpp b/src/core/qgsvectorlayereditbuffer.cpp
index 4b393a8..ebe8e3a 100644
--- a/src/core/qgsvectorlayereditbuffer.cpp
+++ b/src/core/qgsvectorlayereditbuffer.cpp
@@ -65,12 +65,12 @@ void QgsVectorLayerEditBuffer::updateFields( QgsFields& fields )
// delete attributes from the higher indices to lower indices
for ( int i = mDeletedAttributeIds.count() - 1; i >= 0; --i )
{
- fields.remove( mDeletedAttributeIds[i] );
+ fields.remove( mDeletedAttributeIds.at( i ) );
}
// add new fields
for ( int i = 0; i < mAddedAttributes.count(); ++i )
{
- fields.append( mAddedAttributes[i], QgsFields::OriginEdit, i );
+ fields.append( mAddedAttributes.at( i ), QgsFields::OriginEdit, i );
}
// rename fields
QgsFieldNameMap::const_iterator renameIt = mRenamedAttributes.constBegin();
diff --git a/src/core/qgsvectorlayerfeatureiterator.cpp b/src/core/qgsvectorlayerfeatureiterator.cpp
index 98556f0..6648834 100644
--- a/src/core/qgsvectorlayerfeatureiterator.cpp
+++ b/src/core/qgsvectorlayerfeatureiterator.cpp
@@ -175,6 +175,28 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeat
changedIds << attIt.key();
}
mChangedFeaturesRequest.setFilterFids( changedIds );
+
+ if ( mChangedFeaturesRequest.limit() > 0 )
+ {
+ int providerLimit = mProviderRequest.limit();
+
+ // features may be deleted in buffer, so increase limit sent to provider
+ providerLimit += mSource->mDeletedFeatureIds.size();
+
+ if ( mProviderRequest.filterType() == QgsFeatureRequest::FilterExpression )
+ {
+ // attribute changes may mean some features no longer match expression, so increase limit sent to provider
+ providerLimit += mSource->mChangedAttributeValues.size();
+ }
+
+ if ( mProviderRequest.filterType() == QgsFeatureRequest::FilterExpression || mProviderRequest.filterType() == QgsFeatureRequest::FilterRect )
+ {
+ // geometry changes may mean some features no longer match expression or rect, so increase limit sent to provider
+ providerLimit += mSource->mChangedGeometries.size();
+ }
+
+ mProviderRequest.setLimit( providerLimit );
+ }
}
if ( request.filterType() == QgsFeatureRequest::FilterFid )
@@ -538,14 +560,14 @@ void QgsVectorLayerFeatureIterator::prepareExpression( int fieldIdx )
Q_FOREACH ( const QString& col, exp->referencedColumns() )
{
- int dependantFieldIdx = mSource->mFields.fieldNameIndex( col );
+ int dependentFieldIdx = mSource->mFields.fieldNameIndex( col );
if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
{
- mRequest.setSubsetOfAttributes( mRequest.subsetOfAttributes() << dependantFieldIdx );
+ mRequest.setSubsetOfAttributes( mRequest.subsetOfAttributes() << dependentFieldIdx );
}
- // also need to fetch this dependant field
- if ( !mPreparedFields.contains( dependantFieldIdx ) && !mFieldsToPrepare.contains( dependantFieldIdx ) )
- mFieldsToPrepare << dependantFieldIdx;
+ // also need to fetch this dependent field
+ if ( !mPreparedFields.contains( dependentFieldIdx ) && !mFieldsToPrepare.contains( dependentFieldIdx ) )
+ mFieldsToPrepare << dependentFieldIdx;
}
if ( exp->needsGeometry() )
diff --git a/src/core/qgsvectorlayerrenderer.cpp b/src/core/qgsvectorlayerrenderer.cpp
index 2d77054..0e19bab 100644
--- a/src/core/qgsvectorlayerrenderer.cpp
+++ b/src/core/qgsvectorlayerrenderer.cpp
@@ -53,7 +53,6 @@ QgsVectorLayerRenderer::QgsVectorLayerRenderer( QgsVectorLayer* layer, QgsRender
, mDiagrams( false )
, mLabelProvider( nullptr )
, mDiagramProvider( nullptr )
- , mLayerTransparency( 0 )
{
mSource = new QgsVectorLayerFeatureSource( layer );
@@ -64,7 +63,6 @@ QgsVectorLayerRenderer::QgsVectorLayerRenderer( QgsVectorLayer* layer, QgsRender
mGeometryType = layer->geometryType();
- mLayerTransparency = layer->layerTransparency();
mFeatureBlendMode = layer->featureBlendMode();
mSimplifyMethod = layer->simplifyMethod();
@@ -262,18 +260,6 @@ bool QgsVectorLayerRenderer::render()
mRendererV2->paintEffect()->end( mContext );
}
- //apply layer transparency for vector layers
- if ( mContext.useAdvancedEffects() && mLayerTransparency != 0 )
- {
- // a layer transparency has been set, so update the alpha for the flattened layer
- // by combining it with the layer transparency
- QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * mLayerTransparency / 100 ) );
- // use destination in composition mode to merge source's alpha with destination
- mContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn );
- mContext.painter()->fillRect( 0, 0, mContext.painter()->device()->width(),
- mContext.painter()->device()->height(), transparentFillColor );
- }
-
return true;
}
diff --git a/src/core/qgsvectorlayerrenderer.h b/src/core/qgsvectorlayerrenderer.h
index fe880e4..331afde 100644
--- a/src/core/qgsvectorlayerrenderer.h
+++ b/src/core/qgsvectorlayerrenderer.h
@@ -136,7 +136,6 @@ class QgsVectorLayerRenderer : public QgsMapLayerRenderer
//! may be null. no need to delete: if exists it is owned by labeling engine
QgsVectorLayerDiagramProvider* mDiagramProvider;
- int mLayerTransparency;
QPainter::CompositionMode mFeatureBlendMode;
QgsVectorSimplifyMethod mSimplifyMethod;
diff --git a/src/core/qgswebpage.h b/src/core/qgswebpage.h
index d55e51a..57a1d5a 100644
--- a/src/core/qgswebpage.h
+++ b/src/core/qgswebpage.h
@@ -183,6 +183,8 @@ class CORE_EXPORT QWebPage : public QObject
signals:
+ void loadFinished( bool ok );
+
public slots:
protected:
diff --git a/src/core/qgswebview.h b/src/core/qgswebview.h
index 13d1740..03f12e1 100644
--- a/src/core/qgswebview.h
+++ b/src/core/qgswebview.h
@@ -66,6 +66,7 @@ class CORE_EXPORT QgsWebView : public QTextBrowser
, mPage( new QWebPage( this ) )
{
connect( this, SIGNAL( anchorClicked( const QUrl & ) ), this, SIGNAL( linkClicked( const QUrl & ) ) );
+ connect( this, SIGNAL( pageLoadFinished( bool ) ), mPage, SIGNAL( loadFinished( bool ) ) );
}
~QgsWebView()
@@ -99,8 +100,15 @@ class CORE_EXPORT QgsWebView : public QTextBrowser
return new QgsWebView();
}
- void setContent( const QByteArray&, const QString&, const QUrl& )
+ void setContent( const QByteArray& data, const QString& contentType, const QUrl& )
{
+ QString text = QString::fromUtf8( data );
+ if ( contentType == "text/html" )
+ setHtml( text );
+ else
+ setPlainText( text );
+
+ emit pageLoadFinished( true );
}
void print( QPrinter* )
@@ -110,6 +118,8 @@ class CORE_EXPORT QgsWebView : public QTextBrowser
signals:
void linkClicked( const QUrl &link );
+ void pageLoadFinished( bool ok );
+
private:
QWebSettings *mSettings;
QWebPage *mPage;
diff --git a/src/core/raster/qgsbrightnesscontrastfilter.cpp b/src/core/raster/qgsbrightnesscontrastfilter.cpp
index dbafdad..0da438d 100644
--- a/src/core/raster/qgsbrightnesscontrastfilter.cpp
+++ b/src/core/raster/qgsbrightnesscontrastfilter.cpp
@@ -111,6 +111,11 @@ bool QgsBrightnessContrastFilter::setInput( QgsRasterInterface* input )
QgsRasterBlock * QgsBrightnessContrastFilter::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock * QgsBrightnessContrastFilter::block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
Q_UNUSED( bandNo );
QgsDebugMsgLevel( QString( "width = %1 height = %2 extent = %3" ).arg( width ).arg( height ).arg( extent.toString() ), 4 );
@@ -122,7 +127,7 @@ QgsRasterBlock * QgsBrightnessContrastFilter::block( int bandNo, QgsRectangle c
// At this moment we know that we read rendered image
int bandNumber = 1;
- QgsRasterBlock *inputBlock = mInput->block( bandNumber, extent, width, height );
+ QgsRasterBlock *inputBlock = mInput->block2( bandNumber, extent, width, height, feedback );
if ( !inputBlock || inputBlock->isEmpty() )
{
QgsDebugMsg( "No raster data!" );
diff --git a/src/core/raster/qgsbrightnesscontrastfilter.h b/src/core/raster/qgsbrightnesscontrastfilter.h
index e17be96..ec93e2e 100644
--- a/src/core/raster/qgsbrightnesscontrastfilter.h
+++ b/src/core/raster/qgsbrightnesscontrastfilter.h
@@ -41,6 +41,7 @@ class CORE_EXPORT QgsBrightnessContrastFilter : public QgsRasterInterface
bool setInput( QgsRasterInterface* input ) override;
QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) override;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
void setBrightness( int brightness ) { mBrightness = qBound( -255, brightness, 255 ); }
int brightness() const { return mBrightness; }
diff --git a/src/core/raster/qgshillshaderenderer.cpp b/src/core/raster/qgshillshaderenderer.cpp
index 0fcebef..bcc647d 100644
--- a/src/core/raster/qgshillshaderenderer.cpp
+++ b/src/core/raster/qgshillshaderenderer.cpp
@@ -85,6 +85,11 @@ void QgsHillshadeRenderer::writeXML( QDomDocument &doc, QDomElement &parentElem
QgsRasterBlock *QgsHillshadeRenderer::block( int bandNo, const QgsRectangle &extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock *QgsHillshadeRenderer::block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
Q_UNUSED( bandNo );
QgsRasterBlock *outputBlock = new QgsRasterBlock();
if ( !mInput )
@@ -93,7 +98,7 @@ QgsRasterBlock *QgsHillshadeRenderer::block( int bandNo, const QgsRectangle &ext
return outputBlock;
}
- QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height );
+ QgsRasterBlock *inputBlock = mInput->block2( mBand, extent, width, height, feedback );
if ( !inputBlock || inputBlock->isEmpty() )
{
@@ -107,7 +112,7 @@ QgsRasterBlock *QgsHillshadeRenderer::block( int bandNo, const QgsRectangle &ext
if ( mAlphaBand > 0 && mBand != mAlphaBand )
{
- alphaBlock = mInput->block( mAlphaBand, extent, width, height );
+ alphaBlock = mInput->block2( mAlphaBand, extent, width, height, feedback );
if ( !alphaBlock || alphaBlock->isEmpty() )
{
// TODO: better to render without alpha
diff --git a/src/core/raster/qgshillshaderenderer.h b/src/core/raster/qgshillshaderenderer.h
index b57cb76..63398e2 100644
--- a/src/core/raster/qgshillshaderenderer.h
+++ b/src/core/raster/qgshillshaderenderer.h
@@ -56,6 +56,7 @@ class CORE_EXPORT QgsHillshadeRenderer : public QgsRasterRenderer
void writeXML( QDomDocument& doc, QDomElement& parentElem ) const override;
QgsRasterBlock *block( int bandNo, QgsRectangle const & extent, int width, int height ) override;
+ QgsRasterBlock *block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
QList<int> usesBands() const override;
diff --git a/src/core/raster/qgshuesaturationfilter.cpp b/src/core/raster/qgshuesaturationfilter.cpp
index 8ad57e0..15f9231 100644
--- a/src/core/raster/qgshuesaturationfilter.cpp
+++ b/src/core/raster/qgshuesaturationfilter.cpp
@@ -120,6 +120,11 @@ bool QgsHueSaturationFilter::setInput( QgsRasterInterface* input )
QgsRasterBlock * QgsHueSaturationFilter::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock * QgsHueSaturationFilter::block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
Q_UNUSED( bandNo );
QgsDebugMsgLevel( QString( "width = %1 height = %2 extent = %3" ).arg( width ).arg( height ).arg( extent.toString() ), 4 );
@@ -131,7 +136,7 @@ QgsRasterBlock * QgsHueSaturationFilter::block( int bandNo, QgsRectangle const
// At this moment we know that we read rendered image
int bandNumber = 1;
- QgsRasterBlock *inputBlock = mInput->block( bandNumber, extent, width, height );
+ QgsRasterBlock *inputBlock = mInput->block2( bandNumber, extent, width, height, feedback );
if ( !inputBlock || inputBlock->isEmpty() )
{
QgsDebugMsg( "No raster data!" );
diff --git a/src/core/raster/qgshuesaturationfilter.h b/src/core/raster/qgshuesaturationfilter.h
index 890b5ea..4737888 100644
--- a/src/core/raster/qgshuesaturationfilter.h
+++ b/src/core/raster/qgshuesaturationfilter.h
@@ -51,6 +51,7 @@ class CORE_EXPORT QgsHueSaturationFilter : public QgsRasterInterface
bool setInput( QgsRasterInterface* input ) override;
QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) override;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
void setSaturation( int saturation );
int saturation() const { return mSaturation; }
diff --git a/src/core/raster/qgsmultibandcolorrenderer.cpp b/src/core/raster/qgsmultibandcolorrenderer.cpp
index bb80178..a250c49 100644
--- a/src/core/raster/qgsmultibandcolorrenderer.cpp
+++ b/src/core/raster/qgsmultibandcolorrenderer.cpp
@@ -132,6 +132,11 @@ QgsRasterRenderer* QgsMultiBandColorRenderer::create( const QDomElement& elem, Q
QgsRasterBlock* QgsMultiBandColorRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock* QgsMultiBandColorRenderer::block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
Q_UNUSED( bandNo );
QgsRasterBlock *outputBlock = new QgsRasterBlock();
if ( !mInput )
@@ -185,7 +190,7 @@ QgsRasterBlock* QgsMultiBandColorRenderer::block( int bandNo, QgsRectangle cons
bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
- bandBlocks[*bandIt] = mInput->block( *bandIt, extent, width, height );
+ bandBlocks[*bandIt] = mInput->block2( *bandIt, extent, width, height, feedback );
if ( !bandBlocks[*bandIt] )
{
// We should free the alloced mem from block().
diff --git a/src/core/raster/qgsmultibandcolorrenderer.h b/src/core/raster/qgsmultibandcolorrenderer.h
index 3422439..2bebb9c 100644
--- a/src/core/raster/qgsmultibandcolorrenderer.h
+++ b/src/core/raster/qgsmultibandcolorrenderer.h
@@ -38,6 +38,7 @@ class CORE_EXPORT QgsMultiBandColorRenderer: public QgsRasterRenderer
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterInterface* input );
QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height ) override;
+ QgsRasterBlock* block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
int redBand() const { return mRedBand; }
void setRedBand( int band ) { mRedBand = band; }
diff --git a/src/core/raster/qgspalettedrasterrenderer.cpp b/src/core/raster/qgspalettedrasterrenderer.cpp
index 3e129ef..2457a56 100644
--- a/src/core/raster/qgspalettedrasterrenderer.cpp
+++ b/src/core/raster/qgspalettedrasterrenderer.cpp
@@ -153,13 +153,18 @@ void QgsPalettedRasterRenderer::setLabel( int idx, const QString& label )
QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock * QgsPalettedRasterRenderer::block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
QgsRasterBlock *outputBlock = new QgsRasterBlock();
if ( !mInput || mNColors == 0 )
{
return outputBlock;
}
- QgsRasterBlock *inputBlock = mInput->block( bandNo, extent, width, height );
+ QgsRasterBlock *inputBlock = mInput->block2( bandNo, extent, width, height, feedback );
if ( !inputBlock || inputBlock->isEmpty() )
{
@@ -176,7 +181,7 @@ QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle con
if ( mAlphaBand > 0 && mAlphaBand != mBand )
{
- alphaBlock = mInput->block( mAlphaBand, extent, width, height );
+ alphaBlock = mInput->block2( mAlphaBand, extent, width, height, feedback );
if ( !alphaBlock || alphaBlock->isEmpty() )
{
delete inputBlock;
diff --git a/src/core/raster/qgspalettedrasterrenderer.h b/src/core/raster/qgspalettedrasterrenderer.h
index 862d2d5..058f6bc 100644
--- a/src/core/raster/qgspalettedrasterrenderer.h
+++ b/src/core/raster/qgspalettedrasterrenderer.h
@@ -39,6 +39,7 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterInterface* input );
QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height ) override;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
/** Returns number of colors*/
int nColors() const { return mNColors; }
diff --git a/src/core/raster/qgsrasterdataprovider.cpp b/src/core/raster/qgsrasterdataprovider.cpp
index 5f84f38..3c8ef7f 100644
--- a/src/core/raster/qgsrasterdataprovider.cpp
+++ b/src/core/raster/qgsrasterdataprovider.cpp
@@ -44,6 +44,11 @@ void QgsRasterDataProvider::setUseSrcNoDataValue( int bandNo, bool use )
QgsRasterBlock * QgsRasterDataProvider::block( int theBandNo, QgsRectangle const & theExtent, int theWidth, int theHeight )
{
+ return block2( theBandNo, theExtent, theWidth, theHeight );
+}
+
+QgsRasterBlock * QgsRasterDataProvider::block2( int theBandNo, QgsRectangle const & theExtent, int theWidth, int theHeight, QgsRasterBlockFeedback* feedback )
+{
QgsDebugMsgLevel( QString( "theBandNo = %1 theWidth = %2 theHeight = %3" ).arg( theBandNo ).arg( theWidth ).arg( theHeight ), 4 );
QgsDebugMsgLevel( QString( "theExtent = %1" ).arg( theExtent.toString() ), 4 );
@@ -154,7 +159,7 @@ QgsRasterBlock * QgsRasterDataProvider::block( int theBandNo, QgsRectangle cons
tmpBlock = new QgsRasterBlock( dataType( theBandNo ), tmpWidth, tmpHeight );
}
- readBlock( theBandNo, tmpExtent, tmpWidth, tmpHeight, tmpBlock->bits() );
+ readBlock( theBandNo, tmpExtent, tmpWidth, tmpHeight, tmpBlock->bits(), feedback );
int pixelSize = dataTypeSize( theBandNo );
@@ -204,7 +209,7 @@ QgsRasterBlock * QgsRasterDataProvider::block( int theBandNo, QgsRectangle cons
}
else
{
- readBlock( theBandNo, theExtent, theWidth, theHeight, block->bits() );
+ readBlock( theBandNo, theExtent, theWidth, theHeight, block->bits(), feedback );
}
// apply scale and offset
diff --git a/src/core/raster/qgsrasterdataprovider.h b/src/core/raster/qgsrasterdataprovider.h
index c8c276d..7f21e8f 100644
--- a/src/core/raster/qgsrasterdataprovider.h
+++ b/src/core/raster/qgsrasterdataprovider.h
@@ -209,6 +209,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
/** Read block of data using given extent and size. */
virtual QgsRasterBlock *block( int theBandNo, const QgsRectangle &theExtent, int theWidth, int theHeight ) override;
+ virtual QgsRasterBlock *block2( int theBandNo, const QgsRectangle &theExtent, int theWidth, int theHeight, QgsRasterBlockFeedback* feedback = nullptr ) override;
/** Return true if source band has no data value */
virtual bool srcHasNoDataValue( int bandNo ) const { return mSrcHasNoDataValue.value( bandNo -1 ); }
@@ -446,8 +447,8 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
/** Read block of data using give extent and size
* @note not available in python bindings
*/
- virtual void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data )
- { Q_UNUSED( bandNo ); Q_UNUSED( viewExtent ); Q_UNUSED( width ); Q_UNUSED( height ); Q_UNUSED( data ); }
+ virtual void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data, QgsRasterBlockFeedback* feedback = nullptr )
+ { Q_UNUSED( bandNo ); Q_UNUSED( viewExtent ); Q_UNUSED( width ); Q_UNUSED( height ); Q_UNUSED( data ); Q_UNUSED( feedback ); }
/** Returns true if user no data contains value */
bool userNoDataValuesContains( int bandNo, double value ) const;
diff --git a/src/core/raster/qgsrasterdrawer.cpp b/src/core/raster/qgsrasterdrawer.cpp
index dc01514..a3b5a5d 100644
--- a/src/core/raster/qgsrasterdrawer.cpp
+++ b/src/core/raster/qgsrasterdrawer.cpp
@@ -17,6 +17,7 @@
#include "qgslogger.h"
#include "qgsrasterdrawer.h"
+#include "qgsrasterinterface.h"
#include "qgsrasteriterator.h"
#include "qgsrasterviewport.h"
#include "qgsmaptopixel.h"
@@ -29,7 +30,7 @@ QgsRasterDrawer::QgsRasterDrawer( QgsRasterIterator* iterator ): mIterator( iter
{
}
-void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel, const QgsRenderContext* ctx )
+void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel, const QgsRenderContext *ctx, QgsRasterBlockFeedback* feedback )
{
QgsDebugMsgLevel( "Entered", 4 );
if ( !p || !mIterator || !viewPort || !theQgsMapToPixel )
@@ -39,7 +40,7 @@ void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsM
// last pipe filter has only 1 band
int bandNumber = 1;
- mIterator->startRasterRead( bandNumber, viewPort->mWidth, viewPort->mHeight, viewPort->mDrawnExtent );
+ mIterator->startRasterRead( bandNumber, viewPort->mWidth, viewPort->mHeight, viewPort->mDrawnExtent, feedback );
//number of cols/rows in output pixels
int nCols = 0;
@@ -86,9 +87,26 @@ void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsM
}
}
+ if ( feedback && feedback->renderPartialOutput() )
+ {
+ // there could have been partial preview written before
+ // so overwrite anything with the resulting image.
+ // (we are guaranteed to have a temporary image for this layer, see QgsMapRendererJob::needTemporaryImage)
+ p->setCompositionMode( QPainter::CompositionMode_Source );
+ }
+
drawImage( p, viewPort, img, topLeftCol, topLeftRow, theQgsMapToPixel );
delete block;
+
+ p->setCompositionMode( QPainter::CompositionMode_SourceOver ); // go back to the default composition mode
+
+ // ok this does not matter much anyway as the tile size quite big so most of the time
+ // there would be just one tile for the whole display area, but it won't hurt...
+ if ( feedback && feedback->isCancelled() )
+ break;
+
+ // for compatibility
if ( ctx && ctx->renderingStopped() )
break;
}
diff --git a/src/core/raster/qgsrasterdrawer.h b/src/core/raster/qgsrasterdrawer.h
index 7eae769..4621e03 100644
--- a/src/core/raster/qgsrasterdrawer.h
+++ b/src/core/raster/qgsrasterdrawer.h
@@ -26,6 +26,7 @@ class QImage;
class QgsMapToPixel;
class QgsRenderContext;
struct QgsRasterViewPort;
+class QgsRasterBlockFeedback;
class QgsRasterIterator;
/** \ingroup core
@@ -41,8 +42,9 @@ class CORE_EXPORT QgsRasterDrawer
* @param viewPort viewport to render
* @param theQgsMapToPixel map to pixel converter
* @param ctx render context
+ * @param feedback optional raster feedback object for cancellation/preview. Added in QGIS 2.18.
*/
- void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel, const QgsRenderContext *ctx = nullptr );
+ void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel, const QgsRenderContext *ctx = nullptr, QgsRasterBlockFeedback* feedback = nullptr );
protected:
/** Draws raster part
diff --git a/src/core/raster/qgsrasterinterface.h b/src/core/raster/qgsrasterinterface.h
index 1a330ef..f7ad987 100644
--- a/src/core/raster/qgsrasterinterface.h
+++ b/src/core/raster/qgsrasterinterface.h
@@ -23,6 +23,7 @@
#include <QCoreApplication> // for tr()
#include <QImage>
+#include "qgsfeedback.h"
#include "qgslogger.h"
#include "qgsrasterbandstats.h"
#include "qgsrasterblock.h"
@@ -30,6 +31,46 @@
#include "qgsrectangle.h"
/** \ingroup core
+ * Feedback object tailored for raster block reading.
+ *
+ * @note added in QGIS 2.18
+ */
+class CORE_EXPORT QgsRasterBlockFeedback : public QgsFeedback
+{
+ public:
+ //! Construct a new raster block feedback object
+ QgsRasterBlockFeedback( QObject* parent = nullptr ) : QgsFeedback( parent ), mPreviewOnly( false ), mRenderPartialOutput( false ) {}
+
+ //! May be emitted by raster data provider to indicate that some partial data are available
+ //! and a new preview image may be produced
+ virtual void onNewData() {}
+
+ //! Whether the raster provider should return only data that are already available
+ //! without waiting for full result. By default this flag is not enabled.
+ //! @see setPreviewOnly()
+ bool isPreviewOnly() const { return mPreviewOnly; }
+ //! set flag whether the block request is for preview purposes only
+ //! @see isPreviewOnly()
+ void setPreviewOnly( bool preview ) { mPreviewOnly = preview; }
+
+ //! Whether our painter is drawing to a temporary image used just by this layer
+ //! @see setRenderPartialOutput()
+ bool renderPartialOutput() const { return mRenderPartialOutput; }
+ //! Set whether our painter is drawing to a temporary image used just by this layer
+ //! @see renderPartialOutput()
+ void setRenderPartialOutput( bool enable ) { mRenderPartialOutput = enable; }
+
+ private:
+ //! Whether the raster provider should return only data that are already available
+ //! without waiting for full result
+ bool mPreviewOnly;
+
+ //! Whether our painter is drawing to a temporary image used just by this layer
+ bool mRenderPartialOutput;
+};
+
+
+/** \ingroup core
* Base class for processing filters like renderers, reprojector, resampler etc.
*/
class CORE_EXPORT QgsRasterInterface
@@ -112,6 +153,23 @@ class CORE_EXPORT QgsRasterInterface
*/
virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) = 0;
+ /** Read block of data using given extent and size.
+ * Returns pointer to data.
+ * Caller is responsible to free the memory returned.
+ * @param bandNo band number
+ * @param extent extent of block
+ * @param width pixel width of block
+ * @param height pixel height of block
+ * @param feedback optional raster feedback object for cancellation/preview
+ * @note This is extended version of block() method. Default implementation falls back to calling block().
+ * @note Added in QGIS 2.18
+ */
+ virtual QgsRasterBlock *block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr )
+ {
+ Q_UNUSED( feedback );
+ return block( bandNo, extent, width, height );
+ }
+
/** Set input.
* Returns true if set correctly, false if cannot use that input */
virtual bool setInput( QgsRasterInterface* input ) { mInput = input; return true; }
@@ -241,6 +299,7 @@ class CORE_EXPORT QgsRasterInterface
int theStats = QgsRasterBandStats::All,
const QgsRectangle & theExtent = QgsRectangle(),
int theBinCount = 0 );
+
};
#endif
diff --git a/src/core/raster/qgsrasteriterator.cpp b/src/core/raster/qgsrasteriterator.cpp
index f2080c4..863fa54 100644
--- a/src/core/raster/qgsrasteriterator.cpp
+++ b/src/core/raster/qgsrasteriterator.cpp
@@ -19,12 +19,13 @@
QgsRasterIterator::QgsRasterIterator( QgsRasterInterface* input )
: mInput( input )
+ , mFeedback( nullptr )
, mMaximumTileWidth( 2000 )
, mMaximumTileHeight( 2000 )
{
}
-void QgsRasterIterator::startRasterRead( int bandNumber, int nCols, int nRows, const QgsRectangle& extent )
+void QgsRasterIterator::startRasterRead( int bandNumber, int nCols, int nRows, const QgsRectangle& extent, QgsRasterBlockFeedback* feedback )
{
if ( !mInput )
{
@@ -32,6 +33,7 @@ void QgsRasterIterator::startRasterRead( int bandNumber, int nCols, int nRows, c
}
mExtent = extent;
+ mFeedback = feedback;
//remove any previous part on that band
removePartInfo( bandNumber );
@@ -93,7 +95,7 @@ bool QgsRasterIterator::readNextRasterPart( int bandNumber,
double ymax = viewPortExtent.yMaximum() - pInfo.currentRow / static_cast< double >( pInfo.nRows ) * viewPortExtent.height();
QgsRectangle blockRect( xmin, ymin, xmax, ymax );
- *block = mInput->block( bandNumber, blockRect, nCols, nRows );
+ *block = mInput->block2( bandNumber, blockRect, nCols, nRows, mFeedback );
topLeftCol = pInfo.currentCol;
topLeftRow = pInfo.currentRow;
diff --git a/src/core/raster/qgsrasteriterator.h b/src/core/raster/qgsrasteriterator.h
index fa85965..e0857f9 100644
--- a/src/core/raster/qgsrasteriterator.h
+++ b/src/core/raster/qgsrasteriterator.h
@@ -20,6 +20,7 @@
class QgsMapToPixel;
class QgsRasterBlock;
+class QgsRasterBlockFeedback;
class QgsRasterInterface;
class QgsRasterProjector;
struct QgsRasterViewPort;
@@ -38,8 +39,9 @@ class CORE_EXPORT QgsRasterIterator
@param nCols number of columns
@param nRows number of rows
@param extent area to read
+ @param feedback optional raster feedback object for cancellation/preview. Added in QGIS 2.18.
*/
- void startRasterRead( int bandNumber, int nCols, int nRows, const QgsRectangle& extent );
+ void startRasterRead( int bandNumber, int nCols, int nRows, const QgsRectangle& extent, QgsRasterBlockFeedback* feedback = nullptr );
/** Fetches next part of raster data, caller takes ownership of the block and
caller should delete the block.
@@ -79,6 +81,7 @@ class CORE_EXPORT QgsRasterIterator
QgsRasterInterface* mInput;
QMap<int, RasterPartInfo> mRasterPartInfos;
QgsRectangle mExtent;
+ QgsRasterBlockFeedback* mFeedback;
int mMaximumTileWidth;
int mMaximumTileHeight;
diff --git a/src/core/raster/qgsrasterlayer.cpp b/src/core/raster/qgsrasterlayer.cpp
index 855fc84..e2ecebf 100644
--- a/src/core/raster/qgsrasterlayer.cpp
+++ b/src/core/raster/qgsrasterlayer.cpp
@@ -1039,7 +1039,7 @@ void QgsRasterLayer::setDrawingStyle( QString const & theDrawingStyleQString )
{
QgsDebugMsgLevel( "Setting drawingStyle to SingleBandColorDataStyle " + QString::number( QgsRaster::SingleBandColorDataStyle ), 4 );
drawingStyle = QgsRaster::SingleBandColorDataStyle;
- QgsDebugMsgLevel( "Setted drawingStyle to " + QString::number( drawingStyle ), 4 );
+ QgsDebugMsgLevel( "drawingStyle set to " + QString::number( drawingStyle ), 4 );
}
else
{
@@ -1309,6 +1309,8 @@ bool QgsRasterLayer::readSymbology( const QDomNode& layer_node, QString& errorMe
setBlendMode( QgsMapRenderer::getCompositionMode( static_cast< QgsMapRenderer::BlendMode >( e.text().toInt() ) ) );
}
+ readCustomProperties( layer_node );
+
return true;
}
diff --git a/src/core/raster/qgsrasterlayerrenderer.cpp b/src/core/raster/qgsrasterlayerrenderer.cpp
index 0e30a49..a9dc5de 100644
--- a/src/core/raster/qgsrasterlayerrenderer.cpp
+++ b/src/core/raster/qgsrasterlayerrenderer.cpp
@@ -26,8 +26,8 @@ QgsRasterLayerRenderer::QgsRasterLayerRenderer( QgsRasterLayer* layer, QgsRender
, mRasterViewPort( nullptr )
, mPipe( nullptr )
, mContext( rendererContext )
+ , mFeedback( new Feedback( this ) )
{
-
mPainter = rendererContext.painter();
const QgsMapToPixel& theQgsMapToPixel = rendererContext.mapToPixel();
mMapToPixel = &theQgsMapToPixel;
@@ -178,6 +178,8 @@ QgsRasterLayerRenderer::QgsRasterLayerRenderer( QgsRasterLayer* layer, QgsRender
QgsRasterLayerRenderer::~QgsRasterLayerRenderer()
{
+ delete mFeedback;
+
delete mRasterViewPort;
delete mPipe;
}
@@ -210,9 +212,46 @@ bool QgsRasterLayerRenderer::render()
// Drawer to pipe?
QgsRasterIterator iterator( mPipe->last() );
QgsRasterDrawer drawer( &iterator );
- drawer.draw( mPainter, mRasterViewPort, mMapToPixel, &mContext );
+ drawer.draw( mPainter, mRasterViewPort, mMapToPixel, nullptr, mFeedback );
QgsDebugMsgLevel( QString( "total raster draw time (ms): %1" ).arg( time.elapsed(), 5 ), 4 );
return true;
}
+
+QgsFeedback* QgsRasterLayerRenderer::feedback() const
+{
+ return mFeedback;
+}
+
+QgsRasterLayerRenderer::Feedback::Feedback( QgsRasterLayerRenderer *r )
+ : mR( r )
+ , mMinimalPreviewInterval( 250 )
+{
+ setRenderPartialOutput( r->mContext.testFlag( QgsRenderContext::RenderPartialOutput ) );
+}
+
+void QgsRasterLayerRenderer::Feedback::onNewData()
+{
+ if ( !renderPartialOutput() )
+ return; // we were not asked for partial renders and we may not have a temporary image for overwriting...
+
+ // update only once upon a time
+ // (preview itself takes some time)
+ if ( mLastPreview.isValid() && mLastPreview.msecsTo( QTime::currentTime() ) < mMinimalPreviewInterval )
+ return;
+
+ // TODO: update only the area that got new data
+
+ QgsDebugMsg( QString( "new raster preview! %1" ).arg( mLastPreview.msecsTo( QTime::currentTime() ) ) );
+ QTime t;
+ t.start();
+ QgsRasterBlockFeedback feedback;
+ feedback.setPreviewOnly( true );
+ feedback.setRenderPartialOutput( true );
+ QgsRasterIterator iterator( mR->mPipe->last() );
+ QgsRasterDrawer drawer( &iterator );
+ drawer.draw( mR->mPainter, mR->mRasterViewPort, mR->mMapToPixel, nullptr, &feedback );
+ QgsDebugMsg( QString( "total raster preview time: %1 ms" ).arg( t.elapsed() ) );
+ mLastPreview = QTime::currentTime();
+}
diff --git a/src/core/raster/qgsrasterlayerrenderer.h b/src/core/raster/qgsrasterlayerrenderer.h
index e2b5370..29585dc 100644
--- a/src/core/raster/qgsrasterlayerrenderer.h
+++ b/src/core/raster/qgsrasterlayerrenderer.h
@@ -21,11 +21,17 @@
class QPainter;
class QgsMapToPixel;
+class QgsRasterBlockFeedback;
class QgsRasterLayer;
class QgsRasterPipe;
struct QgsRasterViewPort;
class QgsRenderContext;
+class QgsRasterLayerRenderer;
+
+#include "qgsrasterinterface.h"
+
+
/** \ingroup core
* Implementation of threaded rendering for raster layers.
*
@@ -40,6 +46,8 @@ class QgsRasterLayerRenderer : public QgsMapLayerRenderer
virtual bool render() override;
+ virtual QgsFeedback* feedback() const override;
+
protected:
QPainter* mPainter;
@@ -48,6 +56,29 @@ class QgsRasterLayerRenderer : public QgsMapLayerRenderer
QgsRasterPipe* mPipe;
QgsRenderContext& mContext;
+
+ /** \ingroup core
+ * Specific internal feedback class to provide preview of raster layer rendering.
+ * @note added in 2.18
+ * @note not available in Python bindings
+ */
+ class Feedback : public QgsRasterBlockFeedback
+ {
+ public:
+ //! Create feedback object based on our layer renderer
+ explicit Feedback( QgsRasterLayerRenderer* r );
+
+ //! when notified of new data in data provider it launches a preview draw of the raster
+ virtual void onNewData() override;
+ private:
+ QgsRasterLayerRenderer* mR; //!< parent renderer instance
+ int mMinimalPreviewInterval; //!< in miliseconds
+ QTime mLastPreview; //!< when last preview has been generated
+ };
+
+ //! feedback class for cancellation and preview generation
+ Feedback* mFeedback;
};
+
#endif // QGSRASTERLAYERRENDERER_H
diff --git a/src/core/raster/qgsrasternuller.cpp b/src/core/raster/qgsrasternuller.cpp
index d9376ed..0c26d08 100644
--- a/src/core/raster/qgsrasternuller.cpp
+++ b/src/core/raster/qgsrasternuller.cpp
@@ -71,13 +71,18 @@ QGis::DataType QgsRasterNuller::dataType( int bandNo ) const
QgsRasterBlock * QgsRasterNuller::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock * QgsRasterNuller::block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
QgsDebugMsgLevel( "Entered", 4 );
if ( !mInput )
{
return new QgsRasterBlock();
}
- QgsRasterBlock *inputBlock = mInput->block( bandNo, extent, width, height );
+ QgsRasterBlock *inputBlock = mInput->block2( bandNo, extent, width, height, feedback );
if ( !inputBlock )
{
return new QgsRasterBlock();
diff --git a/src/core/raster/qgsrasternuller.h b/src/core/raster/qgsrasternuller.h
index d2f8e94..bffe980 100644
--- a/src/core/raster/qgsrasternuller.h
+++ b/src/core/raster/qgsrasternuller.h
@@ -46,6 +46,7 @@ class CORE_EXPORT QgsRasterNuller : public QgsRasterInterface
QGis::DataType dataType( int bandNo ) const override;
QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) override;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
void setNoData( int bandNo, const QgsRasterRangeList& noData );
diff --git a/src/core/raster/qgsrasterpipe.h b/src/core/raster/qgsrasterpipe.h
index def77c0..ee6effe 100644
--- a/src/core/raster/qgsrasterpipe.h
+++ b/src/core/raster/qgsrasterpipe.h
@@ -19,6 +19,7 @@
#define QGSRASTERPIPE_H
#include <QImage>
+#include <QMap>
#include <QObject>
#include "qgsbrightnesscontrastfilter.h"
diff --git a/src/core/raster/qgsrasterprojector.cpp b/src/core/raster/qgsrasterprojector.cpp
index 58488d9..4bf3f50 100644
--- a/src/core/raster/qgsrasterprojector.cpp
+++ b/src/core/raster/qgsrasterprojector.cpp
@@ -36,18 +36,15 @@ QgsRasterProjector::QgsRasterProjector(
, mDestCRS( theDestCRS )
, mSrcDatumTransform( theSrcDatumTransform )
, mDestDatumTransform( theDestDatumTransform )
- , mDestExtent( theDestExtent )
- , mExtent( theExtent )
- , mDestRows( theDestRows ), mDestCols( theDestCols )
- , pHelperTop( nullptr ), pHelperBottom( nullptr )
- , mMaxSrcXRes( theMaxSrcXRes ), mMaxSrcYRes( theMaxSrcYRes )
, mPrecision( Approximate )
- , mApproximate( true )
{
- QgsDebugMsgLevel( "Entered", 4 );
- QgsDebugMsgLevel( "theDestExtent = " + theDestExtent.toString(), 4 );
-
- calc();
+ // these are temporary variables, calculated on the fly in block() call
+ Q_UNUSED( theDestExtent );
+ Q_UNUSED( theDestRows );
+ Q_UNUSED( theDestCols );
+ Q_UNUSED( theMaxSrcXRes );
+ Q_UNUSED( theMaxSrcYRes );
+ Q_UNUSED( theExtent );
}
QgsRasterProjector::QgsRasterProjector(
@@ -62,18 +59,15 @@ QgsRasterProjector::QgsRasterProjector(
, mDestCRS( theDestCRS )
, mSrcDatumTransform( -1 )
, mDestDatumTransform( -1 )
- , mDestExtent( theDestExtent )
- , mExtent( theExtent )
- , mDestRows( theDestRows ), mDestCols( theDestCols )
- , pHelperTop( nullptr ), pHelperBottom( nullptr )
- , mMaxSrcXRes( theMaxSrcXRes ), mMaxSrcYRes( theMaxSrcYRes )
, mPrecision( Approximate )
- , mApproximate( false )
{
- QgsDebugMsgLevel( "Entered", 4 );
- QgsDebugMsgLevel( "theDestExtent = " + theDestExtent.toString(), 4 );
-
- calc();
+ // these are temporary variables, calculated on the fly in block() call
+ Q_UNUSED( theDestExtent );
+ Q_UNUSED( theDestRows );
+ Q_UNUSED( theDestCols );
+ Q_UNUSED( theMaxSrcXRes );
+ Q_UNUSED( theMaxSrcYRes );
+ Q_UNUSED( theExtent );
}
QgsRasterProjector::QgsRasterProjector(
@@ -86,86 +80,31 @@ QgsRasterProjector::QgsRasterProjector(
, mDestCRS( theDestCRS )
, mSrcDatumTransform( -1 )
, mDestDatumTransform( -1 )
- , mExtent( theExtent )
- , mDestRows( 0 )
- , mDestCols( 0 )
- , mDestXRes( 0.0 )
- , mDestYRes( 0.0 )
- , mSrcRows( 0 )
- , mSrcCols( 0 )
- , mSrcXRes( 0.0 )
- , mSrcYRes( 0.0 )
- , mDestRowsPerMatrixRow( 0.0 )
- , mDestColsPerMatrixCol( 0.0 )
- , pHelperTop( nullptr ), pHelperBottom( nullptr )
- , mHelperTopRow( 0 )
- , mCPCols( 0 )
- , mCPRows( 0 )
- , mSqrTolerance( 0.0 )
- , mMaxSrcXRes( theMaxSrcXRes )
- , mMaxSrcYRes( theMaxSrcYRes )
, mPrecision( Approximate )
- , mApproximate( false )
{
- QgsDebugMsgLevel( "Entered", 4 );
+ // these are temporary variables, calculated on the fly in block() call
+ Q_UNUSED( theMaxSrcXRes );
+ Q_UNUSED( theMaxSrcYRes );
+ Q_UNUSED( theExtent );
}
QgsRasterProjector::QgsRasterProjector()
: QgsRasterInterface( nullptr )
, mSrcDatumTransform( -1 )
, mDestDatumTransform( -1 )
- , mDestRows( 0 )
- , mDestCols( 0 )
- , mDestXRes( 0.0 )
- , mDestYRes( 0.0 )
- , mSrcRows( 0 )
- , mSrcCols( 0 )
- , mSrcXRes( 0.0 )
- , mSrcYRes( 0.0 )
- , mDestRowsPerMatrixRow( 0.0 )
- , mDestColsPerMatrixCol( 0.0 )
- , pHelperTop( nullptr )
- , pHelperBottom( nullptr )
- , mHelperTopRow( 0 )
- , mCPCols( 0 )
- , mCPRows( 0 )
- , mSqrTolerance( 0.0 )
- , mMaxSrcXRes( 0 )
- , mMaxSrcYRes( 0 )
, mPrecision( Approximate )
- , mApproximate( false )
{
QgsDebugMsgLevel( "Entered", 4 );
}
QgsRasterProjector::QgsRasterProjector( const QgsRasterProjector &projector )
: QgsRasterInterface( nullptr )
- , pHelperTop( nullptr )
- , pHelperBottom( nullptr )
- , mHelperTopRow( 0 )
- , mCPCols( 0 )
- , mCPRows( 0 )
- , mSqrTolerance( 0 )
- , mApproximate( false )
+ , mSrcCRS( projector.mSrcCRS )
+ , mDestCRS( projector.mDestCRS )
+ , mSrcDatumTransform( projector.mSrcDatumTransform )
+ , mDestDatumTransform( projector.mDestDatumTransform )
+ , mPrecision( projector.mPrecision )
{
- mSrcCRS = projector.mSrcCRS;
- mDestCRS = projector.mDestCRS;
- mSrcDatumTransform = projector.mSrcDatumTransform;
- mDestDatumTransform = projector.mDestDatumTransform;
- mMaxSrcXRes = projector.mMaxSrcXRes;
- mMaxSrcYRes = projector.mMaxSrcYRes;
- mExtent = projector.mExtent;
- mDestRows = projector.mDestRows;
- mDestCols = projector.mDestCols;
- mDestXRes = projector.mDestXRes;
- mDestYRes = projector.mDestYRes;
- mSrcRows = projector.mSrcRows;
- mSrcCols = projector.mSrcCols;
- mSrcXRes = projector.mSrcXRes;
- mSrcYRes = projector.mSrcYRes;
- mDestRowsPerMatrixRow = projector.mDestRowsPerMatrixRow;
- mDestColsPerMatrixCol = projector.mDestColsPerMatrixCol;
- mPrecision = projector.mPrecision;
}
QgsRasterProjector & QgsRasterProjector::operator=( const QgsRasterProjector & projector )
@@ -176,18 +115,18 @@ QgsRasterProjector & QgsRasterProjector::operator=( const QgsRasterProjector & p
mDestCRS = projector.mDestCRS;
mSrcDatumTransform = projector.mSrcDatumTransform;
mDestDatumTransform = projector.mDestDatumTransform;
- mMaxSrcXRes = projector.mMaxSrcXRes;
- mMaxSrcYRes = projector.mMaxSrcYRes;
- mExtent = projector.mExtent;
mPrecision = projector.mPrecision;
}
return *this;
}
+
QgsRasterProjector* QgsRasterProjector::clone() const
{
QgsDebugMsgLevel( "Entered", 4 );
- QgsRasterProjector * projector = new QgsRasterProjector( mSrcCRS, mDestCRS, mMaxSrcXRes, mMaxSrcYRes, mExtent );
+ QgsRasterProjector * projector = new QgsRasterProjector;
+ projector->mSrcCRS = mSrcCRS;
+ projector->mDestCRS = mDestCRS;
projector->mSrcDatumTransform = mSrcDatumTransform;
projector->mDestDatumTransform = mDestDatumTransform;
projector->mPrecision = mPrecision;
@@ -196,8 +135,6 @@ QgsRasterProjector* QgsRasterProjector::clone() const
QgsRasterProjector::~QgsRasterProjector()
{
- delete[] pHelperTop;
- delete[] pHelperBottom;
}
int QgsRasterProjector::bandCount() const
@@ -214,6 +151,9 @@ QGis::DataType QgsRasterProjector::dataType( int bandNo ) const
return QGis::UnknownDataType;
}
+/// @cond PRIVATE
+
+
void QgsRasterProjector::setCRS( const QgsCoordinateReferenceSystem & theSrcCRS, const QgsCoordinateReferenceSystem & theDestCRS, int srcDatumTransform, int destDatumTransform )
{
mSrcCRS = theSrcCRS;
@@ -222,22 +162,36 @@ void QgsRasterProjector::setCRS( const QgsCoordinateReferenceSystem & theSrcCRS,
mDestDatumTransform = destDatumTransform;
}
-void QgsRasterProjector::calc()
+
+ProjectorData::ProjectorData( const QgsRectangle& extent, int width, int height, QgsRasterInterface* input, const QgsCoordinateTransform* inverseCt, QgsRasterProjector::Precision precision )
+ : mApproximate( false )
+ , mInverseCt( inverseCt->clone() )
+ , mDestExtent( extent )
+ , mDestRows( height )
+ , mDestCols( width )
+ , mDestXRes( 0.0 )
+ , mDestYRes( 0.0 )
+ , mSrcRows( 0 )
+ , mSrcCols( 0 )
+ , mSrcXRes( 0.0 )
+ , mSrcYRes( 0.0 )
+ , mDestRowsPerMatrixRow( 0.0 )
+ , mDestColsPerMatrixCol( 0.0 )
+ , pHelperTop( nullptr )
+ , pHelperBottom( nullptr )
+ , mHelperTopRow( 0 )
+ , mCPCols( 0 )
+ , mCPRows( 0 )
+ , mSqrTolerance( 0.0 )
+ , mMaxSrcXRes( 0 )
+ , mMaxSrcYRes( 0 )
{
QgsDebugMsgLevel( "Entered", 4 );
- mCPMatrix.clear();
- mCPLegalMatrix.clear();
- delete[] pHelperTop;
- pHelperTop = nullptr;
- delete[] pHelperBottom;
- pHelperBottom = nullptr;
// Get max source resolution and extent if possible
- mMaxSrcXRes = 0;
- mMaxSrcYRes = 0;
- if ( mInput )
+ if ( input )
{
- QgsRasterDataProvider *provider = dynamic_cast<QgsRasterDataProvider*>( mInput->srcInput() );
+ QgsRasterDataProvider *provider = dynamic_cast<QgsRasterDataProvider*>( input->srcInput() );
if ( provider )
{
if ( provider->capabilities() & QgsRasterDataProvider::Size )
@@ -263,9 +217,7 @@ void QgsRasterProjector::calc()
double myDestRes = mDestXRes < mDestYRes ? mDestXRes : mDestYRes;
mSqrTolerance = myDestRes * myDestRes;
- const QgsCoordinateTransform* inverseCt = QgsCoordinateTransformCache::instance()->transform( mDestCRS.authid(), mSrcCRS.authid(), mDestDatumTransform, mSrcDatumTransform );
-
- if ( mPrecision == Approximate )
+ if ( precision == QgsRasterProjector::Approximate )
{
mApproximate = true;
}
@@ -344,7 +296,15 @@ void QgsRasterProjector::calc()
mSrcXRes = mSrcExtent.width() / mSrcCols;
}
-void QgsRasterProjector::calcSrcExtent()
+ProjectorData::~ProjectorData()
+{
+ delete[] pHelperTop;
+ delete[] pHelperBottom;
+ delete mInverseCt;
+}
+
+
+void ProjectorData::calcSrcExtent()
{
/* Run around the mCPMatrix and find source extent */
// Attention, source limits are not necessarily on destination edges, e.g.
@@ -408,7 +368,7 @@ void QgsRasterProjector::calcSrcExtent()
QgsDebugMsgLevel( "mSrcExtent = " + mSrcExtent.toString(), 4 );
}
-QString QgsRasterProjector::cpToString()
+QString ProjectorData::cpToString()
{
QString myString;
for ( int i = 0; i < mCPRows; i++ )
@@ -433,7 +393,7 @@ QString QgsRasterProjector::cpToString()
return myString;
}
-void QgsRasterProjector::calcSrcRowsCols()
+void ProjectorData::calcSrcRowsCols()
{
// Wee need to calculate minimum cell size in the source
// TODO: Think it over better, what is the right source resolution?
@@ -472,11 +432,10 @@ void QgsRasterProjector::calcSrcRowsCols()
else
{
// take highest from corners, points in in the middle of corners and center (3 x 3 )
- const QgsCoordinateTransform* inverseCt = QgsCoordinateTransformCache::instance()->transform( mDestCRS.authid(), mSrcCRS.authid(), mDestDatumTransform, mSrcDatumTransform );
//double
QgsRectangle srcExtent;
int srcXSize, srcYSize;
- if ( extentSize( inverseCt, mDestExtent, mDestCols, mDestRows, srcExtent, srcXSize, srcYSize ) )
+ if ( QgsRasterProjector::extentSize( mInverseCt, mDestExtent, mDestCols, mDestRows, srcExtent, srcXSize, srcYSize ) )
{
double srcXRes = srcExtent.width() / srcXSize;
double srcYRes = srcExtent.height() / srcYSize;
@@ -508,29 +467,22 @@ void QgsRasterProjector::calcSrcRowsCols()
}
-inline void QgsRasterProjector::destPointOnCPMatrix( int theRow, int theCol, double *theX, double *theY )
+inline void ProjectorData::destPointOnCPMatrix( int theRow, int theCol, double *theX, double *theY )
{
*theX = mDestExtent.xMinimum() + theCol * mDestExtent.width() / ( mCPCols - 1 );
*theY = mDestExtent.yMaximum() - theRow * mDestExtent.height() / ( mCPRows - 1 );
}
-inline int QgsRasterProjector::matrixRow( int theDestRow )
+inline int ProjectorData::matrixRow( int theDestRow )
{
return static_cast< int >( floor(( theDestRow + 0.5 ) / mDestRowsPerMatrixRow ) );
}
-inline int QgsRasterProjector::matrixCol( int theDestCol )
+inline int ProjectorData::matrixCol( int theDestCol )
{
return static_cast< int >( floor(( theDestCol + 0.5 ) / mDestColsPerMatrixCol ) );
}
-QgsPoint QgsRasterProjector::srcPoint( int theDestRow, int theCol )
-{
- Q_UNUSED( theDestRow );
- Q_UNUSED( theCol );
- return QgsPoint();
-}
-
-void QgsRasterProjector::calcHelper( int theMatrixRow, QgsPoint *thePoints )
+void ProjectorData::calcHelper( int theMatrixRow, QgsPoint *thePoints )
{
// TODO?: should we also precalc dest cell center coordinates for x and y?
for ( int myDestCol = 0; myDestCol < mDestCols; myDestCol++ )
@@ -555,7 +507,8 @@ void QgsRasterProjector::calcHelper( int theMatrixRow, QgsPoint *thePoints )
thePoints[myDestCol].setY( t );
}
}
-void QgsRasterProjector::nextHelper()
+
+void ProjectorData::nextHelper()
{
// We just switch pHelperTop and pHelperBottom, memory is not lost
QgsPoint *tmp;
@@ -566,7 +519,7 @@ void QgsRasterProjector::nextHelper()
mHelperTopRow++;
}
-bool QgsRasterProjector::srcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol, const QgsCoordinateTransform* ct )
+bool ProjectorData::srcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol )
{
if ( mApproximate )
{
@@ -574,11 +527,11 @@ bool QgsRasterProjector::srcRowCol( int theDestRow, int theDestCol, int *theSrcR
}
else
{
- return preciseSrcRowCol( theDestRow, theDestCol, theSrcRow, theSrcCol, ct );
+ return preciseSrcRowCol( theDestRow, theDestCol, theSrcRow, theSrcCol );
}
}
-bool QgsRasterProjector::preciseSrcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol, const QgsCoordinateTransform* ct )
+bool ProjectorData::preciseSrcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol )
{
#ifdef QGISDEBUG
QgsDebugMsgLevel( QString( "theDestRow = %1" ).arg( theDestRow ), 5 );
@@ -594,9 +547,9 @@ bool QgsRasterProjector::preciseSrcRowCol( int theDestRow, int theDestCol, int *
QgsDebugMsgLevel( QString( "x = %1 y = %2" ).arg( x ).arg( y ), 5 );
#endif
- if ( ct )
+ if ( mInverseCt )
{
- ct->transformInPlace( x, y, z );
+ mInverseCt->transformInPlace( x, y, z );
}
#ifdef QGISDEBUG
@@ -627,7 +580,7 @@ bool QgsRasterProjector::preciseSrcRowCol( int theDestRow, int theDestCol, int *
return true;
}
-bool QgsRasterProjector::approximateSrcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol )
+bool ProjectorData::approximateSrcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol )
{
int myMatrixRow = matrixRow( theDestRow );
int myMatrixCol = matrixCol( theDestCol );
@@ -684,7 +637,7 @@ bool QgsRasterProjector::approximateSrcRowCol( int theDestRow, int theDestCol, i
return true;
}
-void QgsRasterProjector::insertRows( const QgsCoordinateTransform* ct )
+void ProjectorData::insertRows( const QgsCoordinateTransform* ct )
{
for ( int r = 0; r < mCPRows - 1; r++ )
{
@@ -708,7 +661,7 @@ void QgsRasterProjector::insertRows( const QgsCoordinateTransform* ct )
}
}
-void QgsRasterProjector::insertCols( const QgsCoordinateTransform* ct )
+void ProjectorData::insertCols( const QgsCoordinateTransform* ct )
{
for ( int r = 0; r < mCPRows; r++ )
{
@@ -726,7 +679,7 @@ void QgsRasterProjector::insertCols( const QgsCoordinateTransform* ct )
}
-void QgsRasterProjector::calcCP( int theRow, int theCol, const QgsCoordinateTransform* ct )
+void ProjectorData::calcCP( int theRow, int theCol, const QgsCoordinateTransform* ct )
{
double myDestX, myDestY;
destPointOnCPMatrix( theRow, theCol, &myDestX, &myDestY );
@@ -751,7 +704,7 @@ void QgsRasterProjector::calcCP( int theRow, int theCol, const QgsCoordinateTran
}
}
-bool QgsRasterProjector::calcRow( int theRow, const QgsCoordinateTransform* ct )
+bool ProjectorData::calcRow( int theRow, const QgsCoordinateTransform* ct )
{
QgsDebugMsgLevel( QString( "theRow = %1" ).arg( theRow ), 3 );
for ( int i = 0; i < mCPCols; i++ )
@@ -762,7 +715,7 @@ bool QgsRasterProjector::calcRow( int theRow, const QgsCoordinateTransform* ct )
return true;
}
-bool QgsRasterProjector::calcCol( int theCol, const QgsCoordinateTransform* ct )
+bool ProjectorData::calcCol( int theCol, const QgsCoordinateTransform* ct )
{
QgsDebugMsgLevel( QString( "theCol = %1" ).arg( theCol ), 3 );
for ( int i = 0; i < mCPRows; i++ )
@@ -773,7 +726,7 @@ bool QgsRasterProjector::calcCol( int theCol, const QgsCoordinateTransform* ct )
return true;
}
-bool QgsRasterProjector::checkCols( const QgsCoordinateTransform* ct )
+bool ProjectorData::checkCols( const QgsCoordinateTransform* ct )
{
if ( !ct )
{
@@ -818,7 +771,7 @@ bool QgsRasterProjector::checkCols( const QgsCoordinateTransform* ct )
return true;
}
-bool QgsRasterProjector::checkRows( const QgsCoordinateTransform* ct )
+bool ProjectorData::checkRows( const QgsCoordinateTransform* ct )
{
if ( !ct )
{
@@ -863,6 +816,9 @@ bool QgsRasterProjector::checkRows( const QgsCoordinateTransform* ct )
return true;
}
+/// @endcond
+
+
QString QgsRasterProjector::precisionLabel( Precision precision )
{
switch ( precision )
@@ -877,6 +833,11 @@ QString QgsRasterProjector::precisionLabel( Precision precision )
QgsRasterBlock * QgsRasterProjector::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock * QgsRasterProjector::block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
QgsDebugMsgLevel( QString( "extent:\n%1" ).arg( extent.toString() ), 4 );
QgsDebugMsgLevel( QString( "width = %1 height = %2" ).arg( width ).arg( height ), 4 );
if ( !mInput )
@@ -888,25 +849,24 @@ QgsRasterBlock * QgsRasterProjector::block( int bandNo, QgsRectangle const & ex
if ( ! mSrcCRS.isValid() || ! mDestCRS.isValid() || mSrcCRS == mDestCRS )
{
QgsDebugMsgLevel( "No projection necessary", 4 );
- return mInput->block( bandNo, extent, width, height );
+ return mInput->block2( bandNo, extent, width, height, feedback );
}
- mDestExtent = extent;
- mDestRows = height;
- mDestCols = width;
- calc();
+ const QgsCoordinateTransform* inverseCt = QgsCoordinateTransformCache::instance()->transform( mDestCRS.authid(), mSrcCRS.authid(), mDestDatumTransform, mSrcDatumTransform );
+
+ ProjectorData pd( extent, width, height, mInput, inverseCt, mPrecision );
- QgsDebugMsgLevel( QString( "srcExtent:\n%1" ).arg( srcExtent().toString() ), 4 );
- QgsDebugMsgLevel( QString( "srcCols = %1 srcRows = %2" ).arg( srcCols() ).arg( srcRows() ), 4 );
+ QgsDebugMsgLevel( QString( "srcExtent:\n%1" ).arg( pd.srcExtent().toString() ), 4 );
+ QgsDebugMsgLevel( QString( "srcCols = %1 srcRows = %2" ).arg( pd.srcCols() ).arg( pd.srcRows() ), 4 );
// If we zoom out too much, projector srcRows / srcCols maybe 0, which can cause problems in providers
- if ( srcRows() <= 0 || srcCols() <= 0 )
+ if ( pd.srcRows() <= 0 || pd.srcCols() <= 0 )
{
QgsDebugMsgLevel( "Zero srcRows or srcCols", 4 );
return new QgsRasterBlock();
}
- QgsRasterBlock *inputBlock = mInput->block( bandNo, srcExtent(), srcCols(), srcRows() );
+ QgsRasterBlock *inputBlock = mInput->block2( bandNo, pd.srcExtent(), pd.srcCols(), pd.srcRows(), feedback );
if ( !inputBlock || inputBlock->isEmpty() )
{
QgsDebugMsg( "No raster data!" );
@@ -947,12 +907,6 @@ QgsRasterBlock * QgsRasterProjector::block( int bandNo, QgsRectangle const & ex
// we cannot fill output block with no data because we use memcpy for data, not setValue().
bool doNoData = !QgsRasterBlock::typeIsNumeric( inputBlock->dataType() ) && inputBlock->hasNoData() && !inputBlock->hasNoDataValue();
- const QgsCoordinateTransform* inverseCt = nullptr;
- if ( !mApproximate )
- {
- inverseCt = QgsCoordinateTransformCache::instance()->transform( mDestCRS.authid(), mSrcCRS.authid(), mDestDatumTransform, mSrcDatumTransform );
- }
-
outputBlock->setIsNoData();
int srcRow, srcCol;
@@ -960,10 +914,10 @@ QgsRasterBlock * QgsRasterProjector::block( int bandNo, QgsRectangle const & ex
{
for ( int j = 0; j < width; ++j )
{
- bool inside = srcRowCol( i, j, &srcRow, &srcCol, inverseCt );
+ bool inside = pd.srcRowCol( i, j, &srcRow, &srcCol );
if ( !inside ) continue; // we have everything set to no data
- qgssize srcIndex = static_cast< qgssize >( srcRow ) * mSrcCols + srcCol;
+ qgssize srcIndex = static_cast< qgssize >( srcRow ) * pd.srcCols() + srcCol;
QgsDebugMsgLevel( QString( "row = %1 col = %2 srcRow = %3 srcCol = %4" ).arg( i ).arg( j ).arg( srcRow ).arg( srcCol ), 5 );
// isNoData() may be slow so we check doNoData first
diff --git a/src/core/raster/qgsrasterprojector.h b/src/core/raster/qgsrasterprojector.h
index c1046bd..efb4597 100644
--- a/src/core/raster/qgsrasterprojector.h
+++ b/src/core/raster/qgsrasterprojector.h
@@ -36,12 +36,15 @@
class QgsPoint;
/** \ingroup core
+ * \brief QgsRasterProjector implements approximate projection support for
+ * it calculates grid of points in source CRS for target CRS + extent
+ * which are used to calculate affine transformation matrices.
* \class QgsRasterProjector
*/
class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
{
public:
- /** Precison defines if each pixel is reprojected or approximate reprojection based
+ /** Precision defines if each pixel is reprojected or approximate reprojection based
* on an approximation matrix of reprojected points is used.
*/
enum Precision
@@ -50,11 +53,8 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
Exact = 1, //!< Exact, precise but slow
};
- /** \brief QgsRasterProjector implements approximate projection support for
- * it calculates grid of points in source CRS for target CRS + extent
- * which are used to calculate affine transformation matrices.
- */
-
+ //! @deprecated since 2.18: use default constructor
+ Q_DECL_DEPRECATED
QgsRasterProjector( const QgsCoordinateReferenceSystem& theSrcCRS,
const QgsCoordinateReferenceSystem& theDestCRS,
int theSrcDatumTransform,
@@ -64,7 +64,8 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
double theMaxSrcXRes, double theMaxSrcYRes,
const QgsRectangle& theExtent
);
-
+ //! @deprecated since 2.18: use default constructor
+ Q_DECL_DEPRECATED
QgsRasterProjector( const QgsCoordinateReferenceSystem& theSrcCRS,
const QgsCoordinateReferenceSystem& theDestCRS,
const QgsRectangle& theDestExtent,
@@ -72,16 +73,21 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
double theMaxSrcXRes, double theMaxSrcYRes,
const QgsRectangle& theExtent
);
+ //! @deprecated since 2.18: use default constructor
+ Q_DECL_DEPRECATED
QgsRasterProjector( const QgsCoordinateReferenceSystem& theSrcCRS,
const QgsCoordinateReferenceSystem& theDestCRS,
double theMaxSrcXRes, double theMaxSrcYRes,
const QgsRectangle& theExtent
);
QgsRasterProjector();
- /** \brief Copy constructor */
+
+ /** \brief Copy constructor
+ * @deprecated since 2.18: use clone()
+ */
// To avoid synthesized which fails on copy of QgsCoordinateTransform
// (QObject child) in Python bindings
- QgsRasterProjector( const QgsRasterProjector &projector );
+ Q_DECL_DEPRECATED QgsRasterProjector( const QgsRasterProjector &projector );
/** \brief The destructor */
~QgsRasterProjector();
@@ -104,12 +110,8 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
/** \brief Get destination CRS */
QgsCoordinateReferenceSystem destCrs() const { return mDestCRS; }
- /** \brief set maximum source resolution */
- void setMaxSrcRes( double theMaxSrcXRes, double theMaxSrcYRes )
- {
- mMaxSrcXRes = theMaxSrcXRes;
- mMaxSrcYRes = theMaxSrcYRes;
- }
+ /** @deprecated since 2.18, does nothing */
+ Q_DECL_DEPRECATED void setMaxSrcRes( double theMaxSrcXRes, double theMaxSrcYRes ) { Q_UNUSED( theMaxSrcXRes ); Q_UNUSED( theMaxSrcYRes ); }
Precision precision() const { return mPrecision; }
void setPrecision( Precision precision ) { mPrecision = precision; }
@@ -117,6 +119,7 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
static QString precisionLabel( Precision precision );
QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height ) override;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
/** Calculate destination extent and size from source extent and size */
bool destExtentSize( const QgsRectangle& theSrcExtent, int theSrcXSize, int theSrcYSize,
@@ -128,24 +131,49 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
QgsRectangle& theDestExtent, int& theDestXSize, int& theDestYSize );
private:
- /** Get source extent */
- QgsRectangle srcExtent() { return mSrcExtent; }
- /** Get/set source width/height */
- int srcRows() { return mSrcRows; }
- int srcCols() { return mSrcCols; }
- void setSrcRows( int theRows ) { mSrcRows = theRows; mSrcXRes = mSrcExtent.height() / mSrcRows; }
- void setSrcCols( int theCols ) { mSrcCols = theCols; mSrcYRes = mSrcExtent.width() / mSrcCols; }
+ /** Source CRS */
+ QgsCoordinateReferenceSystem mSrcCRS;
+
+ /** Destination CRS */
+ QgsCoordinateReferenceSystem mDestCRS;
+
+ /** Source datum transformation id (or -1 if none) */
+ int mSrcDatumTransform;
+
+ /** Destination datum transformation id (or -1 if none) */
+ int mDestDatumTransform;
+
+ /** Requested precision */
+ Precision mPrecision;
+
+};
+
+/// @cond PRIVATE
+
+/**
+ * Internal class for reprojection of rasters - either exact or approximate.
+ * QgsRasterProjector creates it and then keeps calling srcRowCol() to get source pixel position
+ * for every destination pixel position.
+ */
+class ProjectorData
+{
+ public:
+ /** Initialize reprojector and calculate matrix */
+ ProjectorData( const QgsRectangle &extent, int width, int height, QgsRasterInterface *input, const QgsCoordinateTransform *inverseCt, QgsRasterProjector::Precision precision );
+ ~ProjectorData();
/** \brief Get source row and column indexes for current source extent and resolution
If source pixel is outside source extent theSrcRow and theSrcCol are left unchanged.
@return true if inside source
*/
- bool srcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol, const QgsCoordinateTransform* ct );
+ bool srcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol );
- int dstRows() const { return mDestRows; }
- int dstCols() const { return mDestCols; }
+ QgsRectangle srcExtent() const { return mSrcExtent; }
+ int srcRows() const { return mSrcRows; }
+ int srcCols() const { return mSrcCols; }
+ private:
/** \brief get destination point for _current_ destination position */
void destPointOnCPMatrix( int theRow, int theCol, double *theX, double *theY );
@@ -153,18 +181,12 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
int matrixRow( int theDestRow );
int matrixCol( int theDestCol );
- /** \brief get destination point for _current_ matrix position */
- QgsPoint srcPoint( int theRow, int theCol );
-
/** \brief Get precise source row and column indexes for current source extent and resolution */
- inline bool preciseSrcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol, const QgsCoordinateTransform* ct );
+ inline bool preciseSrcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol );
/** \brief Get approximate source row and column indexes for current source extent and resolution */
inline bool approximateSrcRowCol( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol );
- /** \brief Calculate matrix */
- void calc();
-
/** \brief insert rows to matrix */
void insertRows( const QgsCoordinateTransform* ct );
@@ -203,17 +225,12 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
/** Get mCPMatrix as string */
QString cpToString();
- /** Source CRS */
- QgsCoordinateReferenceSystem mSrcCRS;
-
- /** Destination CRS */
- QgsCoordinateReferenceSystem mDestCRS;
-
- /** Source datum transformation id (or -1 if none) */
- int mSrcDatumTransform;
+ /** Use approximation (requested precision is Approximate and it is possible to calculate
+ * an approximation matrix with a sufficient precision) */
+ bool mApproximate;
- /** Destination datum transformation id (or -1 if none) */
- int mDestDatumTransform;
+ /** Transformation from destination CRS to source CRS */
+ QgsCoordinateTransform* mInverseCt;
/** Destination extent */
QgsRectangle mDestExtent;
@@ -284,13 +301,9 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
double mMaxSrcXRes;
double mMaxSrcYRes;
- /** Requested precision */
- Precision mPrecision;
-
- /** Use approximation (requested precision is Approximate and it is possible to calculate
- * an approximation matrix with a sufficient precision) */
- bool mApproximate;
};
+/// @endcond
+
#endif
diff --git a/src/core/raster/qgsrasterrenderer.h b/src/core/raster/qgsrasterrenderer.h
index a924ccf..0e8daad 100644
--- a/src/core/raster/qgsrasterrenderer.h
+++ b/src/core/raster/qgsrasterrenderer.h
@@ -69,8 +69,6 @@ class CORE_EXPORT QgsRasterRenderer : public QgsRasterInterface
virtual bool setInput( QgsRasterInterface* input ) override;
- virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) override = 0;
-
bool usesTransparency() const;
void setOpacity( double opacity ) { mOpacity = opacity; }
diff --git a/src/core/raster/qgsrasterresamplefilter.cpp b/src/core/raster/qgsrasterresamplefilter.cpp
index 6e1d0f6..fc1514b 100644
--- a/src/core/raster/qgsrasterresamplefilter.cpp
+++ b/src/core/raster/qgsrasterresamplefilter.cpp
@@ -131,6 +131,11 @@ void QgsRasterResampleFilter::setZoomedOutResampler( QgsRasterResampler* r )
QgsRasterBlock * QgsRasterResampleFilter::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock * QgsRasterResampleFilter::block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
Q_UNUSED( bandNo );
QgsDebugMsgLevel( QString( "width = %1 height = %2 extent = %3" ).arg( width ).arg( height ).arg( extent.toString() ), 4 );
QgsRasterBlock *outputBlock = new QgsRasterBlock();
@@ -169,7 +174,7 @@ QgsRasterBlock * QgsRasterResampleFilter::block( int bandNo, QgsRectangle const
{
QgsDebugMsgLevel( "No oversampling.", 4 );
delete outputBlock;
- return mInput->block( bandNumber, extent, width, height );
+ return mInput->block2( bandNumber, extent, width, height, feedback );
}
//effective oversampling factors are different to global one because of rounding
@@ -181,7 +186,7 @@ QgsRasterBlock * QgsRasterResampleFilter::block( int bandNo, QgsRectangle const
int resWidth = width * oversamplingX;
int resHeight = height * oversamplingY;
- QgsRasterBlock *inputBlock = mInput->block( bandNumber, extent, resWidth, resHeight );
+ QgsRasterBlock *inputBlock = mInput->block2( bandNumber, extent, resWidth, resHeight, feedback );
if ( !inputBlock || inputBlock->isEmpty() )
{
QgsDebugMsg( "No raster data!" );
diff --git a/src/core/raster/qgsrasterresamplefilter.h b/src/core/raster/qgsrasterresamplefilter.h
index b336109..45083b5 100644
--- a/src/core/raster/qgsrasterresamplefilter.h
+++ b/src/core/raster/qgsrasterresamplefilter.h
@@ -43,6 +43,7 @@ class CORE_EXPORT QgsRasterResampleFilter : public QgsRasterInterface
bool setInput( QgsRasterInterface* input ) override;
QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) override;
+ QgsRasterBlock *block2( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
/** Set resampler for zoomed in scales. Takes ownership of the object*/
void setZoomedInResampler( QgsRasterResampler* r );
diff --git a/src/core/raster/qgssinglebandcolordatarenderer.cpp b/src/core/raster/qgssinglebandcolordatarenderer.cpp
index 8e55796..000d14f 100644
--- a/src/core/raster/qgssinglebandcolordatarenderer.cpp
+++ b/src/core/raster/qgssinglebandcolordatarenderer.cpp
@@ -54,6 +54,11 @@ QgsRasterRenderer* QgsSingleBandColorDataRenderer::create( const QDomElement& el
QgsRasterBlock* QgsSingleBandColorDataRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock* QgsSingleBandColorDataRenderer::block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
Q_UNUSED( bandNo );
QgsRasterBlock *outputBlock = new QgsRasterBlock();
@@ -62,7 +67,7 @@ QgsRasterBlock* QgsSingleBandColorDataRenderer::block( int bandNo, QgsRectangle
return outputBlock;
}
- QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height );
+ QgsRasterBlock *inputBlock = mInput->block2( mBand, extent, width, height, feedback );
if ( !inputBlock || inputBlock->isEmpty() )
{
QgsDebugMsg( "No raster data!" );
diff --git a/src/core/raster/qgssinglebandcolordatarenderer.h b/src/core/raster/qgssinglebandcolordatarenderer.h
index 4240360..0ccf9de 100644
--- a/src/core/raster/qgssinglebandcolordatarenderer.h
+++ b/src/core/raster/qgssinglebandcolordatarenderer.h
@@ -37,6 +37,7 @@ class CORE_EXPORT QgsSingleBandColorDataRenderer: public QgsRasterRenderer
bool setInput( QgsRasterInterface* input ) override;
QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height ) override;
+ QgsRasterBlock* block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
void writeXML( QDomDocument& doc, QDomElement& parentElem ) const override;
diff --git a/src/core/raster/qgssinglebandgrayrenderer.cpp b/src/core/raster/qgssinglebandgrayrenderer.cpp
index c430075..e7f09db 100644
--- a/src/core/raster/qgssinglebandgrayrenderer.cpp
+++ b/src/core/raster/qgssinglebandgrayrenderer.cpp
@@ -80,6 +80,11 @@ void QgsSingleBandGrayRenderer::setContrastEnhancement( QgsContrastEnhancement*
QgsRasterBlock* QgsSingleBandGrayRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock* QgsSingleBandGrayRenderer::block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
Q_UNUSED( bandNo );
QgsDebugMsgLevel( QString( "width = %1 height = %2" ).arg( width ).arg( height ), 4 );
@@ -89,7 +94,7 @@ QgsRasterBlock* QgsSingleBandGrayRenderer::block( int bandNo, QgsRectangle cons
return outputBlock;
}
- QgsRasterBlock *inputBlock = mInput->block( mGrayBand, extent, width, height );
+ QgsRasterBlock *inputBlock = mInput->block2( mGrayBand, extent, width, height, feedback );
if ( !inputBlock || inputBlock->isEmpty() )
{
QgsDebugMsg( "No raster data!" );
@@ -101,7 +106,7 @@ QgsRasterBlock* QgsSingleBandGrayRenderer::block( int bandNo, QgsRectangle cons
if ( mAlphaBand > 0 && mGrayBand != mAlphaBand )
{
- alphaBlock = mInput->block( mAlphaBand, extent, width, height );
+ alphaBlock = mInput->block2( mAlphaBand, extent, width, height, feedback );
if ( !alphaBlock || alphaBlock->isEmpty() )
{
// TODO: better to render without alpha
diff --git a/src/core/raster/qgssinglebandgrayrenderer.h b/src/core/raster/qgssinglebandgrayrenderer.h
index 84864b4..9c18579 100644
--- a/src/core/raster/qgssinglebandgrayrenderer.h
+++ b/src/core/raster/qgssinglebandgrayrenderer.h
@@ -42,6 +42,7 @@ class CORE_EXPORT QgsSingleBandGrayRenderer: public QgsRasterRenderer
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterInterface* input );
QgsRasterBlock *block( int bandNo, QgsRectangle const & extent, int width, int height ) override;
+ QgsRasterBlock *block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
int grayBand() const { return mGrayBand; }
void setGrayBand( int band ) { mGrayBand = band; }
diff --git a/src/core/raster/qgssinglebandpseudocolorrenderer.cpp b/src/core/raster/qgssinglebandpseudocolorrenderer.cpp
index 687808d..f03a6b2 100644
--- a/src/core/raster/qgssinglebandpseudocolorrenderer.cpp
+++ b/src/core/raster/qgssinglebandpseudocolorrenderer.cpp
@@ -109,6 +109,11 @@ QgsRasterRenderer* QgsSingleBandPseudoColorRenderer::create( const QDomElement&
QgsRasterBlock* QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
+ return block2( bandNo, extent, width, height );
+}
+
+QgsRasterBlock* QgsSingleBandPseudoColorRenderer::block2( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback )
+{
Q_UNUSED( bandNo );
QgsRasterBlock *outputBlock = new QgsRasterBlock();
@@ -118,7 +123,7 @@ QgsRasterBlock* QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangl
}
- QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height );
+ QgsRasterBlock *inputBlock = mInput->block2( mBand, extent, width, height, feedback );
if ( !inputBlock || inputBlock->isEmpty() )
{
QgsDebugMsg( "No raster data!" );
@@ -132,7 +137,7 @@ QgsRasterBlock* QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangl
QgsRasterBlock *alphaBlock = nullptr;
if ( mAlphaBand > 0 && mAlphaBand != mBand )
{
- alphaBlock = mInput->block( mAlphaBand, extent, width, height );
+ alphaBlock = mInput->block2( mAlphaBand, extent, width, height, feedback );
if ( !alphaBlock || alphaBlock->isEmpty() )
{
delete inputBlock;
diff --git a/src/core/raster/qgssinglebandpseudocolorrenderer.h b/src/core/raster/qgssinglebandpseudocolorrenderer.h
index 95b793a..c713b87 100644
--- a/src/core/raster/qgssinglebandpseudocolorrenderer.h
+++ b/src/core/raster/qgssinglebandpseudocolorrenderer.h
@@ -37,6 +37,7 @@ class CORE_EXPORT QgsSingleBandPseudoColorRenderer: public QgsRasterRenderer
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterInterface* input );
QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height ) override;
+ QgsRasterBlock* block2( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) override;
/** Takes ownership of the shader*/
void setShader( QgsRasterShader* shader );
diff --git a/src/core/symbology-ng/qgsarrowsymbollayer.cpp b/src/core/symbology-ng/qgsarrowsymbollayer.cpp
index e5310bc..7893566 100644
--- a/src/core/symbology-ng/qgsarrowsymbollayer.cpp
+++ b/src/core/symbology-ng/qgsarrowsymbollayer.cpp
@@ -709,7 +709,7 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF& points, QgsSymbolV2Re
QPointF pd( points.back() );
QPolygonF poly = curvedArrow( po, pm, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadLength, mScaledHeadThickness, mComputedHeadType, mComputedArrowType, mScaledOffset );
- mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
+ mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
}
// straight arrow
else if ( points.size() == 2 )
@@ -720,7 +720,7 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF& points, QgsSymbolV2Re
QPointF pd( points.at( 1 ) );
QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadLength, mScaledHeadThickness, mComputedHeadType, mComputedArrowType, mScaledOffset );
- mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
+ mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
}
}
else
@@ -740,7 +740,7 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF& points, QgsSymbolV2Re
QPointF pd( points.at( pIdx + 2 ) );
QPolygonF poly = curvedArrow( po, pm, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadLength, mScaledHeadThickness, mComputedHeadType, mComputedArrowType, mScaledOffset );
- mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
+ mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
}
// straight arrow
else if ( points.size() - pIdx == 2 )
@@ -751,7 +751,7 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF& points, QgsSymbolV2Re
QPointF pd( points.at( pIdx + 1 ) );
QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadLength, mScaledHeadThickness, mComputedHeadType, mComputedArrowType, mScaledOffset );
- mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
+ mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
}
}
}
@@ -770,7 +770,7 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF& points, QgsSymbolV2Re
QPointF pd( points.back() );
QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadLength, mScaledHeadThickness, mComputedHeadType, mComputedArrowType, mScaledOffset );
- mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
+ mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
}
}
else
@@ -787,7 +787,7 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF& points, QgsSymbolV2Re
QPointF pd( points.at( pIdx + 1 ) );
QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadLength, mScaledHeadThickness, mComputedHeadType, mComputedArrowType, mScaledOffset );
- mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
+ mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
}
}
}
diff --git a/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp b/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
index aeaf748..7954fe8 100644
--- a/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
+++ b/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
@@ -162,9 +162,9 @@ QgsCategorizedSymbolRendererV2::QgsCategorizedSymbolRendererV2( const QString& a
//trigger a detachment and copy of mCategories BUT that same method CAN be used to modify a symbol in place
Q_FOREACH ( const QgsRendererCategoryV2& cat, categories )
{
- if ( cat.symbol() )
+ if ( !cat.symbol() )
{
- QgsDebugMsg( "invalid symbol in a category! ignoring..." );
+ QgsDebugMsg( QString( "invalid symbol in category %1 (%2)! ignoring..." ).arg( cat.value().toString(), cat.label() ) );
}
mCategories << cat;
}
@@ -445,6 +445,12 @@ void QgsCategorizedSymbolRendererV2::startRender( QgsRenderContext& context, con
mTempSymbols[ cat.symbol()] = tempSymbol;
}
}
+
+ Q_FOREACH ( QgsSymbolV2 *symbol, mSymbolHash.values() )
+ {
+ symbol->startRender( context, &fields );
+ }
+
return;
}
@@ -455,6 +461,11 @@ void QgsCategorizedSymbolRendererV2::stopRender( QgsRenderContext& context )
cat.symbol()->stopRender( context );
}
+ Q_FOREACH ( QgsSymbolV2 *symbol, mSymbolHash.values() )
+ {
+ symbol->stopRender( context );
+ }
+
// cleanup mTempSymbols
QHash<QgsSymbolV2*, QgsSymbolV2*>::const_iterator it2 = mTempSymbols.constBegin();
for ( ; it2 != mTempSymbols.constEnd(); ++it2 )
diff --git a/src/core/symbology-ng/qgsgeometrygeneratorsymbollayerv2.cpp b/src/core/symbology-ng/qgsgeometrygeneratorsymbollayerv2.cpp
index 4b3c996..9979f7b 100644
--- a/src/core/symbology-ng/qgsgeometrygeneratorsymbollayerv2.cpp
+++ b/src/core/symbology-ng/qgsgeometrygeneratorsymbollayerv2.cpp
@@ -117,6 +117,8 @@ QgsSymbolLayerV2* QgsGeometryGeneratorSymbolLayerV2::clone() const
clone->setSymbolType( mSymbolType );
+ copyPaintEffect( clone );
+
return clone;
}
diff --git a/src/core/symbology-ng/qgslinesymbollayerv2.cpp b/src/core/symbology-ng/qgslinesymbollayerv2.cpp
index 051f626..7df7c38 100644
--- a/src/core/symbology-ng/qgslinesymbollayerv2.cpp
+++ b/src/core/symbology-ng/qgslinesymbollayerv2.cpp
@@ -889,6 +889,9 @@ void QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSym
}
}
+
+ context.renderContext().painter()->save();
+
if ( qgsDoubleNear( offset, 0.0 ) )
{
if ( placement == Interval )
@@ -915,6 +918,8 @@ void QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSym
renderPolylineVertex( points2, context, placement );
}
}
+
+ context.renderContext().painter()->restore();
}
void QgsMarkerLineSymbolLayerV2::renderPolygonOutline( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
@@ -948,11 +953,13 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points
QPointF lastPt = points[0];
double lengthLeft = 0; // how much is left until next marker
- bool first = mOffsetAlongLine ? false : true; //only draw marker at first vertex when no offset along line is set
QgsRenderContext& rc = context.renderContext();
double interval = mInterval;
+ QgsExpressionContextScope* scope = new QgsExpressionContextScope();
+ context.renderContext().expressionContext().appendScope( scope );
+
if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_INTERVAL ) )
{
context.setOriginalValueVariable( mInterval );
@@ -972,6 +979,7 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points
double painterUnitInterval = QgsSymbolLayerV2Utils::convertToPainterUnits( rc, interval, mIntervalUnit, mIntervalMapUnitScale );
lengthLeft = painterUnitInterval - QgsSymbolLayerV2Utils::convertToPainterUnits( rc, offsetAlongLine, mIntervalUnit, mIntervalMapUnitScale );
+ int pointNum = 0;
for ( int i = 1; i < points.count(); ++i )
{
const QPointF& pt = points[i];
@@ -995,12 +1003,6 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points
mMarker->setLineAngle( l.angle() * 180 / M_PI );
}
- // draw first marker
- if ( first )
- {
- mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() );
- first = false;
- }
// while we're not at the end of line segment, draw!
while ( lengthLeft > painterUnitInterval )
@@ -1008,12 +1010,15 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points
// "c" is 1 for regular point or in interval (0,1] for begin of line segment
lastPt += c * diff;
lengthLeft -= painterUnitInterval;
+ scope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, ++pointNum );
mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() );
c = 1; // reset c (if wasn't 1 already)
}
lastPt = pt;
}
+
+ delete context.renderContext().expressionContext().popScope();
}
static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
@@ -1037,6 +1042,10 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
int i, maxCount;
bool isRing = false;
+ QgsExpressionContextScope* scope = new QgsExpressionContextScope();
+ context.renderContext().expressionContext().appendScope( scope );
+ scope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_COUNT, points.size() );
+
double offsetAlongLine = mOffsetAlongLine;
if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE ) )
{
@@ -1059,8 +1068,11 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
QgsPointV2 vPoint;
double x, y, z;
QPointF mapPoint;
+ int pointNum = 0;
while ( context.renderContext().geometry()->nextVertex( vId, vPoint ) )
{
+ scope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, ++pointNum );
+
if (( placement == Vertex && vId.type == QgsVertexId::SegmentVertex )
|| ( placement == CurvePoint && vId.type == QgsVertexId::CurveVertex ) )
{
@@ -1082,6 +1094,8 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
mMarker->renderPoint( mapPoint, context.feature(), rc, -1, context.selected() );
}
}
+
+ delete context.renderContext().expressionContext().popScope();
return;
}
@@ -1104,6 +1118,7 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
}
else
{
+ delete context.renderContext().expressionContext().popScope();
return;
}
@@ -1114,11 +1129,16 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
renderOffsetVertexAlongLine( points, i, distance, context );
// restore original rotation
mMarker->setAngle( origAngle );
+
+ delete context.renderContext().expressionContext().popScope();
return;
}
+ int pointNum = 0;
for ( ; i < maxCount; ++i )
{
+ scope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, ++pointNum );
+
if ( isRing && placement == Vertex && i == points.count() - 1 )
{
continue; // don't draw the last marker - it has been drawn already
@@ -1135,6 +1155,8 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
// restore original rotation
mMarker->setAngle( origAngle );
+
+ delete context.renderContext().expressionContext().popScope();
}
double QgsMarkerLineSymbolLayerV2::markerAngle( const QPolygonF& points, bool isRing, int vertex )
diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
index a575ed1..dc8b9bd 100644
--- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
+++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
@@ -1726,12 +1726,12 @@ void QgsFilledMarkerSymbolLayer::draw( QgsSymbolV2RenderContext &context, QgsSim
if ( !polygon.isEmpty() )
{
- mFill->renderPolygon( polygon, /* rings */ nullptr, context.feature(), context.renderContext() );
+ mFill->renderPolygon( polygon, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
}
else
{
QPolygonF poly = path.toFillPolygon();
- mFill->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
+ mFill->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
}
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 470f1cb..0814ed6 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -209,6 +209,7 @@ SET(QGIS_GUI_SRCS
qgsexpressionbuilderdialog.cpp
qgsexpressionbuilderwidget.cpp
qgsexpressionhighlighter.cpp
+ qgsexpressionlineedit.cpp
qgsexpressionselectiondialog.cpp
qgsextentgroupbox.cpp
qgsexternalresourcewidget.cpp
@@ -298,6 +299,7 @@ SET(QGIS_GUI_SRCS
qgssublayersdialog.cpp
qgssqlcomposerdialog.cpp
qgssvgannotationitem.cpp
+ qgstabwidget.cpp
qgstablewidgetitem.cpp
qgstextannotationitem.cpp
qgstrackedvectorlayertools.cpp
@@ -367,6 +369,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsexpressionbuilderdialog.h
qgsexpressionbuilderwidget.h
qgsexpressionhighlighter.h
+ qgsexpressionlineedit.h
qgsexpressionselectiondialog.h
qgsextentgroupbox.h
qgsexternalresourcewidget.h
@@ -447,6 +450,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsslider.h
qgssqlcomposerdialog.h
qgssublayersdialog.h
+ qgstabwidget.h
qgsunitselectionwidget.h
qgsuserinputdockwidget.h
qgsvariableeditorwidget.h
@@ -708,25 +712,6 @@ IF (WITH_TOUCH)
ENDIF (WITH_TOUCH)
SET(QGIS_GUI_UI_HDRS
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthauthoritieseditor.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthcertificateinfo.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthcertificatemanager.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthconfigedit.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthconfigeditor.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthconfigidedit.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthconfigselect.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthconfiguriedit.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsautheditorwidgets.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthidentitieseditor.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthimportcertdialog.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthimportidentitydialog.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthmethodplugins.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthserverseditor.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthsslconfigwidget.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthsslerrorsdialog.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthsslimportdialog.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthsslimporterrors.h
- ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsauthtrustedcasdialog.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgscredentialdialog.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsdetaileditemwidgetbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsexpressionbuilderdialogbase.h
diff --git a/src/gui/attributetable/qgsattributetablefiltermodel.cpp b/src/gui/attributetable/qgsattributetablefiltermodel.cpp
index 9ade8a2..7ed131c 100644
--- a/src/gui/attributetable/qgsattributetablefiltermodel.cpp
+++ b/src/gui/attributetable/qgsattributetablefiltermodel.cpp
@@ -187,7 +187,7 @@ void QgsAttributeTableFilterModel::setAttributeTableConfig( const QgsAttributeTa
{
if ( newColumnMapping.size() == mColumnMapping.size() - removedColumnCount )
{
- beginRemoveColumns( QModelIndex(), firstRemovedColumn, firstRemovedColumn + removedColumnCount );
+ beginRemoveColumns( QModelIndex(), firstRemovedColumn, firstRemovedColumn );
mColumnMapping = newColumnMapping;
endRemoveColumns();
}
diff --git a/src/gui/attributetable/qgsattributetablemodel.cpp b/src/gui/attributetable/qgsattributetablemodel.cpp
index 454bf42..795ca86 100644
--- a/src/gui/attributetable/qgsattributetablemodel.cpp
+++ b/src/gui/attributetable/qgsattributetablemodel.cpp
@@ -540,12 +540,7 @@ QVariant QgsAttributeTableModel::headerData( int section, Qt::Orientation orient
}
else if ( section >= 0 && section < mFieldCount )
{
- QString attributeName = layer()->attributeAlias( mAttributes.at( section ) );
- if ( attributeName.isEmpty() )
- {
- QgsField field = layer()->fields().at( mAttributes.at( section ) );
- attributeName = field.name();
- }
+ QString attributeName = layer()->fields().at( mAttributes.at( section ) ).displayName();
return QVariant( attributeName );
}
else
diff --git a/src/gui/attributetable/qgsdualview.cpp b/src/gui/attributetable/qgsdualview.cpp
index 63968b7..f56292b 100644
--- a/src/gui/attributetable/qgsdualview.cpp
+++ b/src/gui/attributetable/qgsdualview.cpp
@@ -524,8 +524,7 @@ void QgsDualView::tableColumnResized( int column, int width )
if ( sourceCol >= 0 )
{
config.setColumnWidth( sourceCol, width );
- mLayerCache->layer()->setAttributeTableConfig( config );
- mConfig = config;
+ setAttributeTableConfig( config );
}
}
@@ -538,7 +537,6 @@ void QgsDualView::hideColumn()
if ( sourceCol >= 0 )
{
config.setColumnHidden( sourceCol, true );
- mLayerCache->layer()->setAttributeTableConfig( config );
setAttributeTableConfig( config );
}
}
@@ -561,7 +559,6 @@ void QgsDualView::resizeColumn()
if ( ok )
{
config.setColumnWidth( sourceCol, width );
- mLayerCache->layer()->setAttributeTableConfig( config );
setAttributeTableConfig( config );
}
}
@@ -661,7 +658,7 @@ void QgsDualView::onSortColumnChanged()
QgsAttributeTableConfig cfg = mLayerCache->layer()->attributeTableConfig();
cfg.setSortExpression( mFilterModel->sortExpression() );
cfg.setSortOrder( mFilterModel->sortOrder() );
- mLayerCache->layer()->setAttributeTableConfig( cfg );
+ setAttributeTableConfig( cfg );
}
void QgsDualView::sortByPreviewExpression()
@@ -717,7 +714,7 @@ void QgsDualView::setSortExpression( const QString& sortExpression, Qt::SortOrde
mConfig.setSortExpression( sortExpression );
mConfig.setSortOrder( sortOrder );
- mLayerCache->layer()->setAttributeTableConfig( mConfig );
+ setAttributeTableConfig( mConfig );
}
QString QgsDualView::sortExpression() const
diff --git a/src/gui/editorwidgets/core/qgseditorconfigwidget.h b/src/gui/editorwidgets/core/qgseditorconfigwidget.h
index fcaab94..78ae2dd 100644
--- a/src/gui/editorwidgets/core/qgseditorconfigwidget.h
+++ b/src/gui/editorwidgets/core/qgseditorconfigwidget.h
@@ -76,6 +76,13 @@ class GUI_EXPORT QgsEditorConfigWidget : public QWidget
*/
virtual ~QgsEditorConfigWidget() {}
+ signals:
+
+ /** Emitted when the configuration of the widget is changed.
+ * @note added in QGIS 2.18
+ */
+ void changed();
+
private:
QgsVectorLayer* mLayer;
int mField;
diff --git a/src/gui/editorwidgets/qgscheckboxconfigdlg.cpp b/src/gui/editorwidgets/qgscheckboxconfigdlg.cpp
index 1ed6d63..521065f 100644
--- a/src/gui/editorwidgets/qgscheckboxconfigdlg.cpp
+++ b/src/gui/editorwidgets/qgscheckboxconfigdlg.cpp
@@ -19,6 +19,9 @@ QgsCheckBoxConfigDlg::QgsCheckBoxConfigDlg( QgsVectorLayer* vl, int fieldIdx, QW
: QgsEditorConfigWidget( vl, fieldIdx, parent )
{
setupUi( this );
+
+ connect( leCheckedState, SIGNAL( textEdited( QString ) ), this, SIGNAL( changed() ) );
+ connect( leUncheckedState, SIGNAL( textEdited( QString ) ), this, SIGNAL( changed() ) );
}
QgsEditorWidgetConfig QgsCheckBoxConfigDlg::config()
diff --git a/src/gui/editorwidgets/qgsdatetimeeditconfig.cpp b/src/gui/editorwidgets/qgsdatetimeeditconfig.cpp
index dd1dd95..fc046cd 100644
--- a/src/gui/editorwidgets/qgsdatetimeeditconfig.cpp
+++ b/src/gui/editorwidgets/qgsdatetimeeditconfig.cpp
@@ -33,6 +33,11 @@ QgsDateTimeEditConfig::QgsDateTimeEditConfig( QgsVectorLayer* vl, int fieldIdx,
connect( mFieldHelpToolButton, SIGNAL( clicked( bool ) ), this, SLOT( showHelp( bool ) ) );
connect( mDisplayHelpToolButton, SIGNAL( clicked( bool ) ), this, SLOT( showHelp( bool ) ) );
+ connect( mFieldFormatEdit, SIGNAL( textChanged( QString ) ), this, SIGNAL( changed() ) );
+ connect( mDisplayFormatEdit, SIGNAL( textChanged( QString ) ), this, SIGNAL( changed() ) );
+ connect( mCalendarPopupCheckBox, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mAllowNullCheckBox, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+
// initialize
updateFieldFormat( mFieldFormatComboBox->currentIndex() );
displayFormatChanged( mDisplayFormatComboBox->currentIndex() );
diff --git a/src/gui/editorwidgets/qgsdoublespinbox.cpp b/src/gui/editorwidgets/qgsdoublespinbox.cpp
index 904cf0d..5325c5a 100644
--- a/src/gui/editorwidgets/qgsdoublespinbox.cpp
+++ b/src/gui/editorwidgets/qgsdoublespinbox.cpp
@@ -17,12 +17,14 @@
#include <QMouseEvent>
#include <QSettings>
#include <QStyle>
-#include <QToolButton>
#include "qgsdoublespinbox.h"
#include "qgsexpression.h"
#include "qgsapplication.h"
#include "qgslogger.h"
+#include "qgsfilterlineedit.h"
+
+#define CLEAR_ICON_SIZE 16
QgsDoubleSpinBox::QgsDoubleSpinBox( QWidget *parent )
: QDoubleSpinBox( parent )
@@ -31,25 +33,22 @@ QgsDoubleSpinBox::QgsDoubleSpinBox( QWidget *parent )
, mCustomClearValue( 0.0 )
, mExpressionsEnabled( true )
{
- mClearButton = new QToolButton( this );
- mClearButton->setIcon( QgsApplication::getThemeIcon( "/mIconClear.svg" ) );
- mClearButton->setCursor( Qt::ArrowCursor );
- mClearButton->setStyleSheet( "position: absolute; border: none; padding: 0px;" );
- connect( mClearButton, SIGNAL( clicked() ), this, SLOT( clear() ) );
+ mLineEdit = new QgsSpinBoxLineEdit();
- setStyleSheet( QString( "padding-right: %1px;" ).arg( mClearButton->sizeHint().width() + 18 + frameWidth() + 1 ) );
+ setLineEdit( mLineEdit );
QSize msz = minimumSizeHint();
- setMinimumSize( qMax( msz.width(), mClearButton->sizeHint().height() + frameWidth() * 2 + 2 ),
- qMax( msz.height(), mClearButton->sizeHint().height() + frameWidth() * 2 + 2 ) );
+ setMinimumSize( msz.width() + CLEAR_ICON_SIZE + 9 + frameWidth() * 2 + 2,
+ qMax( msz.height(), CLEAR_ICON_SIZE + frameWidth() * 2 + 2 ) );
+ connect( mLineEdit, SIGNAL( cleared() ), this, SLOT( clear() ) );
connect( this, SIGNAL( valueChanged( double ) ), this, SLOT( changed( double ) ) );
}
void QgsDoubleSpinBox::setShowClearButton( const bool showClearButton )
{
mShowClearButton = showClearButton;
- mClearButton->setVisible( shouldShowClearForValue( value() ) );
+ mLineEdit->setShowClearButton( showClearButton );
}
void QgsDoubleSpinBox::setExpressionsEnabled( const bool enabled )
@@ -60,18 +59,18 @@ void QgsDoubleSpinBox::setExpressionsEnabled( const bool enabled )
void QgsDoubleSpinBox::changeEvent( QEvent *event )
{
QDoubleSpinBox::changeEvent( event );
- mClearButton->setVisible( shouldShowClearForValue( value() ) );
+ mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
}
void QgsDoubleSpinBox::paintEvent( QPaintEvent *event )
{
- mClearButton->setVisible( shouldShowClearForValue( value() ) );
+ mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
QDoubleSpinBox::paintEvent( event );
}
void QgsDoubleSpinBox::changed( double value )
{
- mClearButton->setVisible( shouldShowClearForValue( value ) );
+ mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
}
void QgsDoubleSpinBox::clear()
@@ -187,14 +186,3 @@ bool QgsDoubleSpinBox::shouldShowClearForValue( const double value ) const
}
return value != clearValue();
}
-
-void QgsDoubleSpinBox::resizeEvent( QResizeEvent * event )
-{
- QDoubleSpinBox::resizeEvent( event );
-
- QSize sz = mClearButton->sizeHint();
-
- mClearButton->move( rect().right() - frameWidth() - 18 - sz.width(),
- ( rect().bottom() + 1 - sz.height() ) / 2 );
-
-}
diff --git a/src/gui/editorwidgets/qgsdoublespinbox.h b/src/gui/editorwidgets/qgsdoublespinbox.h
index 55cff69..6fc55dd 100644
--- a/src/gui/editorwidgets/qgsdoublespinbox.h
+++ b/src/gui/editorwidgets/qgsdoublespinbox.h
@@ -13,11 +13,12 @@
* *
***************************************************************************/
-#ifndef QGSDOUBLESPPINBOX_H
-#define QGSDOUBLESPPINBOX_H
+#ifndef QGSDOUBLESPINBOX_H
+#define QGSDOUBLESPINBOX_H
#include <QDoubleSpinBox>
-#include <QToolButton>
+
+class QgsSpinBoxLineEdit;
/** \ingroup gui
* @brief The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
@@ -28,21 +29,34 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
{
Q_OBJECT
Q_PROPERTY( bool showClearButton READ showClearButton WRITE setShowClearButton )
+ Q_PROPERTY( bool clearValue READ clearValue WRITE setClearValue )
Q_PROPERTY( bool expressionsEnabled READ expressionsEnabled WRITE setExpressionsEnabled )
public:
+
+ //! Behaviour when widget is cleared.
enum ClearValueMode
{
- MinimumValue,
- MaximumValue,
- CustomValue
+ MinimumValue, //!< Reset value to minimum()
+ MaximumValue, //!< Reset value to maximum()
+ CustomValue, //!< Reset value to custom value (see setClearValue() )
};
+ /** Constructor for QgsDoubleSpinBox.
+ * @param parent parent widget
+ */
explicit QgsDoubleSpinBox( QWidget *parent = nullptr );
- //! determines if the widget will show a clear button
- //! @note the clear button will set the widget to its minimum value
+ /** Sets whether the widget will show a clear button. The clear button
+ * allows users to reset the widget to a default or empty state.
+ * @param showClearButton set to true to show the clear button, or false to hide it
+ * @see showClearButton()
+ */
void setShowClearButton( const bool showClearButton );
+
+ /** Returns whether the widget is showing a clear button.
+ * @see setShowClearButton()
+ */
bool showClearButton() const {return mShowClearButton;}
/** Sets if the widget will allow entry of simple expressions, which are
@@ -51,6 +65,7 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
* @note added in QGIS 2.7
*/
void setExpressionsEnabled( const bool enabled );
+
/** Returns whether the widget will allow entry of simple expressions, which are
* evaluated and then discarded.
* @returns true if spin box allows expression entry
@@ -62,28 +77,30 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
virtual void clear() override;
/**
- * @brief setClearValue defines the clear value as a custom value and will automatically set the clear value mode to CustomValue
+ * Defines the clear value as a custom value and will automatically set the clear value mode to CustomValue.
* @param customValue defines the numerical value used as the clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
+ * @see setClearValue()
*/
void setClearValue( double customValue, const QString& clearValueText = QString() );
+
/**
- * @brief setClearValueMode defines if the clear value should be the minimum or maximum values of the widget or a custom value
+ * Defines if the clear value should be the minimum or maximum values of the widget or a custom value.
* @param mode mode to user for clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
*/
void setClearValueMode( ClearValueMode mode, const QString& clearValueText = QString() );
- //! returns the value used when clear() is called.
+ /** Returns the value used when clear() is called.
+ * @see setClearValue()
+ */
double clearValue() const;
virtual double valueFromText( const QString & text ) const override;
virtual QValidator::State validate( QString & input, int & pos ) const override;
-
void paintEvent( QPaintEvent* e ) override;
protected:
- virtual void resizeEvent( QResizeEvent* event ) override;
virtual void changeEvent( QEvent* event ) override;
private slots:
@@ -93,7 +110,7 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
int frameWidth() const;
bool shouldShowClearForValue( const double value ) const;
- void updateStyleSheet( const QColor& backgroundColor = QColor() );
+ QgsSpinBoxLineEdit* mLineEdit;
bool mShowClearButton;
ClearValueMode mClearValueMode;
@@ -101,8 +118,7 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
bool mExpressionsEnabled;
- QToolButton* mClearButton;
QString stripped( const QString &originalText ) const;
};
-#endif // QGSDOUBLESPPINBOX_H
+#endif // QGSDOUBLESPINBOX_H
diff --git a/src/gui/editorwidgets/qgsexternalresourceconfigdlg.cpp b/src/gui/editorwidgets/qgsexternalresourceconfigdlg.cpp
index cdc421d..52a37da 100644
--- a/src/gui/editorwidgets/qgsexternalresourceconfigdlg.cpp
+++ b/src/gui/editorwidgets/qgsexternalresourceconfigdlg.cpp
@@ -57,6 +57,20 @@ QgsExternalResourceConfigDlg::QgsExternalResourceConfigDlg( QgsVectorLayer* vl,
mDocumentViewerContentComboBox->addItem( tr( "Image" ), QgsExternalResourceWidget::Image );
mDocumentViewerContentComboBox->addItem( tr( "Web view" ), QgsExternalResourceWidget::Web );
+
+
+ connect( mFileWidgetGroupBox, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mFileWidgetButtonGroupBox, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mFileWidgetFilterLineEdit, SIGNAL( textChanged( QString ) ), this, SIGNAL( changed() ) );
+ connect( mUseLink, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mFullUrl, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mRootPath, SIGNAL( textChanged( QString ) ), this, SIGNAL( changed() ) );
+ connect( mStorageButtonGroup, SIGNAL( buttonClicked( int ) ), this, SIGNAL( changed() ) );
+ connect( mRelativeGroupBox, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mDocumentViewerGroupBox, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mDocumentViewerContentComboBox, SIGNAL( currentIndexChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( mDocumentViewerHeight, SIGNAL( valueChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( mDocumentViewerWidth, SIGNAL( valueChanged( int ) ), this, SIGNAL( changed() ) );
}
void QgsExternalResourceConfigDlg::chooseDefaultPath()
diff --git a/src/gui/editorwidgets/qgsphotoconfigdlg.cpp b/src/gui/editorwidgets/qgsphotoconfigdlg.cpp
index ccef083..1899f79 100644
--- a/src/gui/editorwidgets/qgsphotoconfigdlg.cpp
+++ b/src/gui/editorwidgets/qgsphotoconfigdlg.cpp
@@ -19,6 +19,8 @@ QgsPhotoConfigDlg::QgsPhotoConfigDlg( QgsVectorLayer* vl, int fieldIdx, QWidget
: QgsEditorConfigWidget( vl, fieldIdx, parent )
{
setupUi( this );
+ connect( sbWidgetHeight, SIGNAL( valueChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( sbWidgetWidth, SIGNAL( valueChanged( int ) ), this, SIGNAL( changed() ) );
}
QgsEditorWidgetConfig QgsPhotoConfigDlg::config()
diff --git a/src/gui/editorwidgets/qgsrangeconfigdlg.cpp b/src/gui/editorwidgets/qgsrangeconfigdlg.cpp
index 0d330bf..6d7753b 100644
--- a/src/gui/editorwidgets/qgsrangeconfigdlg.cpp
+++ b/src/gui/editorwidgets/qgsrangeconfigdlg.cpp
@@ -52,6 +52,16 @@ QgsRangeConfigDlg::QgsRangeConfigDlg( QgsVectorLayer* vl, int fieldIdx, QWidget
valuesLabel->setText( text );
connect( rangeWidget, SIGNAL( currentIndexChanged( int ) ), this, SLOT( rangeWidgetChanged( int ) ) );
+
+ connect( minimumSpinBox, SIGNAL( valueChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( maximumSpinBox, SIGNAL( valueChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( stepSpinBox, SIGNAL( valueChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( minimumDoubleSpinBox, SIGNAL( valueChanged( double ) ), this, SIGNAL( changed() ) );
+ connect( maximumDoubleSpinBox, SIGNAL( valueChanged( double ) ), this, SIGNAL( changed() ) );
+ connect( stepDoubleSpinBox, SIGNAL( valueChanged( double ) ), this, SIGNAL( changed() ) );
+ connect( rangeWidget, SIGNAL( currentIndexChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( allowNullCheckBox, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( suffixLineEdit, SIGNAL( textChanged( QString ) ), this, SIGNAL( changed() ) );
}
QgsEditorWidgetConfig QgsRangeConfigDlg::config()
diff --git a/src/gui/editorwidgets/qgsrelationreferenceconfigdlg.cpp b/src/gui/editorwidgets/qgsrelationreferenceconfigdlg.cpp
index 6b58462..a09e276 100644
--- a/src/gui/editorwidgets/qgsrelationreferenceconfigdlg.cpp
+++ b/src/gui/editorwidgets/qgsrelationreferenceconfigdlg.cpp
@@ -53,6 +53,18 @@ QgsRelationReferenceConfigDlg::QgsRelationReferenceConfigDlg( QgsVectorLayer* vl
mExpressionWidget->setField( relation.referencedLayer()->displayExpression() );
}
}
+
+ connect( mCbxAllowNull, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mCbxOrderByValue, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mCbxShowForm, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mCbxMapIdentification, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mCbxReadOnly, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mComboRelation, SIGNAL( currentIndexChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( mCbxAllowAddFeatures, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mFilterGroupBox, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mFilterFieldsList, SIGNAL( itemChanged( QListWidgetItem* ) ), this, SIGNAL( changed() ) );
+ connect( mCbxChainFilters, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SIGNAL( changed() ) );
}
void QgsRelationReferenceConfigDlg::setConfig( const QgsEditorWidgetConfig& config )
@@ -179,7 +191,7 @@ void QgsRelationReferenceConfigDlg::loadFields()
const QgsFields& flds = l->fields();
for ( int i = 0; i < flds.count(); i++ )
{
- mAvailableFieldsList->addItem( l->attributeAlias( i ).isEmpty() ? flds.at( i ).name() : l->attributeAlias( i ) );
+ mAvailableFieldsList->addItem( flds.at( i ).displayName() );
mAvailableFieldsList->item( mAvailableFieldsList->count() - 1 )->setData( Qt::UserRole, flds.at( i ).name() );
}
}
diff --git a/src/gui/editorwidgets/qgsrelationreferencesearchwidgetwrapper.cpp b/src/gui/editorwidgets/qgsrelationreferencesearchwidgetwrapper.cpp
index 9bd9120..c5301f2 100644
--- a/src/gui/editorwidgets/qgsrelationreferencesearchwidgetwrapper.cpp
+++ b/src/gui/editorwidgets/qgsrelationreferencesearchwidgetwrapper.cpp
@@ -183,6 +183,12 @@ void QgsRelationReferenceSearchWidgetWrapper::initWidget( QWidget* editor )
mWidget->setAllowAddFeatures( false );
mWidget->setOpenFormButtonVisible( false );
+ if ( config( "FilterFields", QVariant() ).isValid() )
+ {
+ mWidget->setFilterFields( config( "FilterFields" ).toStringList() );
+ mWidget->setChainFilters( config( "ChainFilters" ).toBool() );
+ }
+
QgsRelation relation = QgsProject::instance()->relationManager()->relation( config( "Relation" ).toString() );
mWidget->setRelation( relation, false );
diff --git a/src/gui/editorwidgets/qgsrelationreferencewidget.cpp b/src/gui/editorwidgets/qgsrelationreferencewidget.cpp
index e3a5645..046fef7 100644
--- a/src/gui/editorwidgets/qgsrelationreferencewidget.cpp
+++ b/src/gui/editorwidgets/qgsrelationreferencewidget.cpp
@@ -98,7 +98,7 @@ QgsRelationReferenceWidget::QgsRelationReferenceWidget( QWidget* parent )
// open form button
mOpenFormButton = new QToolButton();
- mOpenFormButton->setIcon( QgsApplication::getThemeIcon( "/mActionPropertyItem.png" ) );
+ mOpenFormButton->setIcon( QgsApplication::getThemeIcon( "/mActionPropertyItem.svg" ) );
mOpenFormButton->setText( tr( "Open related feature form" ) );
editLayout->addWidget( mOpenFormButton );
@@ -466,12 +466,14 @@ void QgsRelationReferenceWidget::init()
int idx = mReferencedLayer->fieldNameIndex( fieldName );
QComboBox* cb = new QComboBox();
cb->setProperty( "Field", fieldName );
+ cb->setProperty( "FieldAlias", mReferencedLayer->attributeDisplayName( idx ) );
mFilterComboBoxes << cb;
mReferencedLayer->uniqueValues( idx, uniqueValues );
- cb->addItem( mReferencedLayer->attributeAlias( idx ).isEmpty() ? fieldName : mReferencedLayer->attributeAlias( idx ) );
+ cb->addItem( mReferencedLayer->attributeDisplayName( idx ) );
QVariant nullValue = QSettings().value( "qgis/nullValue", "NULL" );
cb->addItem( nullValue.toString(), QVariant( mReferencedLayer->fields().at( idx ).type() ) );
+ qSort( uniqueValues.begin(), uniqueValues.end(), qgsVariantLessThan );
Q_FOREACH ( const QVariant& v, uniqueValues )
{
cb->addItem( v.toString(), v );
@@ -495,8 +497,8 @@ void QgsRelationReferenceWidget::init()
{
for ( int i = 0; i < mFilterComboBoxes.count() - 1; ++i )
{
- QVariant cv = ft.attribute( mFilterFields[i] );
- QVariant nv = ft.attribute( mFilterFields[i + 1] );
+ QVariant cv = ft.attribute( mFilterFields.at( i ) );
+ QVariant nv = ft.attribute( mFilterFields.at( i + 1 ) );
QString cf = cv.isNull() ? nullValue.toString() : cv.toString();
QString nf = nv.isNull() ? nullValue.toString() : nv.toString();
mFilterCache[mFilterFields[i]][cf] << nf;
@@ -530,12 +532,7 @@ void QgsRelationReferenceWidget::init()
mFeatureListModel->setInjectNull( mAllowNull );
if ( mOrderByValue )
{
- const QStringList referencedColumns = QgsExpression( mReferencedLayer->displayExpression() ).referencedColumns();
- if ( !referencedColumns.isEmpty() )
- {
- int sortIdx = mReferencedLayer->fieldNameIndex( referencedColumns.first() );
- mFilterModel->sort( sortIdx );
- }
+ mFilterModel->sort( mReferencedLayer->displayExpression() );
}
mComboBox->setModel( mFeatureListModel );
@@ -817,14 +814,17 @@ void QgsRelationReferenceWidget::filterChanged()
{
cb->blockSignals( true );
cb->clear();
- cb->addItem( cb->property( "Field" ).toString() );
+ cb->addItem( cb->property( "FieldAlias" ).toString() );
// ccb = scb
// cb = scb + 1
+ QStringList texts;
Q_FOREACH ( const QString& txt, mFilterCache[ccb->property( "Field" ).toString()][ccb->currentText()] )
{
- cb->addItem( txt );
+ texts << txt;
}
+ texts.sort();
+ cb->addItems( texts );
cb->setEnabled( true );
cb->blockSignals( false );
diff --git a/src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp b/src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp
index d27ad52..5f81df0 100644
--- a/src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp
+++ b/src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp
@@ -45,6 +45,31 @@ void QgsRelationWidgetWrapper::setVisible( bool visible )
mWidget->setVisible( visible );
}
+bool QgsRelationWidgetWrapper::showUnlinkButton() const
+{
+ return mWidget->showUnlinkButton();
+}
+
+void QgsRelationWidgetWrapper::setShowUnlinkButton( bool showUnlinkButton )
+{
+ if ( mWidget )
+ mWidget->setShowUnlinkButton( showUnlinkButton );
+}
+
+bool QgsRelationWidgetWrapper::showLabel() const
+{
+ if ( mWidget )
+ return mWidget->showLabel();
+ else
+ return false;
+}
+
+void QgsRelationWidgetWrapper::setShowLabel( bool showLabel )
+{
+ if ( mWidget )
+ mWidget->setShowLabel( showLabel );
+}
+
void QgsRelationWidgetWrapper::initWidget( QWidget* editor )
{
QgsRelationEditorWidget* w = dynamic_cast<QgsRelationEditorWidget*>( editor );
@@ -91,3 +116,14 @@ bool QgsRelationWidgetWrapper::valid() const
{
return mWidget;
}
+
+bool QgsRelationWidgetWrapper::showLinkButton() const
+{
+ return mWidget->showLinkButton();
+}
+
+void QgsRelationWidgetWrapper::setShowLinkButton( bool showLinkButton )
+{
+ if ( mWidget )
+ mWidget->setShowLinkButton( showLinkButton );
+}
diff --git a/src/gui/editorwidgets/qgsrelationwidgetwrapper.h b/src/gui/editorwidgets/qgsrelationwidgetwrapper.h
index cd41795..b3c2313 100644
--- a/src/gui/editorwidgets/qgsrelationwidgetwrapper.h
+++ b/src/gui/editorwidgets/qgsrelationwidgetwrapper.h
@@ -32,6 +32,48 @@ class GUI_EXPORT QgsRelationWidgetWrapper : public QgsWidgetWrapper
public:
explicit QgsRelationWidgetWrapper( QgsVectorLayer* vl, const QgsRelation& relation, QWidget* editor = nullptr, QWidget* parent = nullptr );
+ /**
+ * Defines if a title lable should be shown for this widget.
+ * Only has an effect after widget() has been called at least once.
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLabel() const;
+
+ /**
+ * Defines if a title lable should be shown for this widget.
+ * Only has an effect after widget() has been called at least once.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLabel( bool showLabel );
+
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLinkButton() const;
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLinkButton( bool showLinkButton );
+
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showUnlinkButton() const;
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowUnlinkButton( bool showUnlinkButton );
+
protected:
QWidget* createWidget( QWidget* parent ) override;
void initWidget( QWidget* editor ) override;
diff --git a/src/gui/editorwidgets/qgsspinbox.cpp b/src/gui/editorwidgets/qgsspinbox.cpp
index c3f3f0c..5373b14 100644
--- a/src/gui/editorwidgets/qgsspinbox.cpp
+++ b/src/gui/editorwidgets/qgsspinbox.cpp
@@ -17,12 +17,14 @@
#include <QMouseEvent>
#include <QSettings>
#include <QStyle>
-#include <QToolButton>
#include "qgsspinbox.h"
#include "qgsexpression.h"
#include "qgsapplication.h"
#include "qgslogger.h"
+#include "qgsfilterlineedit.h"
+
+#define CLEAR_ICON_SIZE 16
QgsSpinBox::QgsSpinBox( QWidget *parent )
: QSpinBox( parent )
@@ -31,25 +33,22 @@ QgsSpinBox::QgsSpinBox( QWidget *parent )
, mCustomClearValue( 0 )
, mExpressionsEnabled( true )
{
- mClearButton = new QToolButton( this );
- mClearButton->setIcon( QgsApplication::getThemeIcon( "/mIconClear.svg" ) );
- mClearButton->setCursor( Qt::ArrowCursor );
- mClearButton->setStyleSheet( "position: absolute; border: none; padding: 0px;" );
- connect( mClearButton, SIGNAL( clicked() ), this, SLOT( clear() ) );
+ mLineEdit = new QgsSpinBoxLineEdit();
- setStyleSheet( QString( "padding-right: %1px;" ).arg( mClearButton->sizeHint().width() + 18 + frameWidth() + 1 ) );
+ setLineEdit( mLineEdit );
QSize msz = minimumSizeHint();
- setMinimumSize( qMax( msz.width(), mClearButton->sizeHint().height() + frameWidth() * 2 + 2 ),
- qMax( msz.height(), mClearButton->sizeHint().height() + frameWidth() * 2 + 2 ) );
+ setMinimumSize( msz.width() + CLEAR_ICON_SIZE + 9 + frameWidth() * 2 + 2,
+ qMax( msz.height(), CLEAR_ICON_SIZE + frameWidth() * 2 + 2 ) );
+ connect( mLineEdit, SIGNAL( cleared() ), this, SLOT( clear() ) );
connect( this, SIGNAL( valueChanged( int ) ), this, SLOT( changed( int ) ) );
}
void QgsSpinBox::setShowClearButton( const bool showClearButton )
{
mShowClearButton = showClearButton;
- mClearButton->setVisible( shouldShowClearForValue( value() ) );
+ mLineEdit->setShowClearButton( showClearButton );
}
void QgsSpinBox::setExpressionsEnabled( const bool enabled )
@@ -60,18 +59,18 @@ void QgsSpinBox::setExpressionsEnabled( const bool enabled )
void QgsSpinBox::changeEvent( QEvent *event )
{
QSpinBox::changeEvent( event );
- mClearButton->setVisible( shouldShowClearForValue( value() ) );
+ mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
}
void QgsSpinBox::paintEvent( QPaintEvent *event )
{
- mClearButton->setVisible( shouldShowClearForValue( value() ) );
+ mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
QSpinBox::paintEvent( event );
}
void QgsSpinBox::changed( int value )
{
- mClearButton->setVisible( shouldShowClearForValue( value ) );
+ mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
}
void QgsSpinBox::clear()
@@ -187,14 +186,3 @@ QString QgsSpinBox::stripped( const QString &originalText ) const
return text;
}
-
-void QgsSpinBox::resizeEvent( QResizeEvent * event )
-{
- QSpinBox::resizeEvent( event );
-
- QSize sz = mClearButton->sizeHint();
-
- mClearButton->move( rect().right() - frameWidth() - 18 - sz.width(),
- ( rect().bottom() + 1 - sz.height() ) / 2 );
-
-}
diff --git a/src/gui/editorwidgets/qgsspinbox.h b/src/gui/editorwidgets/qgsspinbox.h
index 38400cc..d0bff10 100644
--- a/src/gui/editorwidgets/qgsspinbox.h
+++ b/src/gui/editorwidgets/qgsspinbox.h
@@ -13,11 +13,12 @@
* *
***************************************************************************/
-#ifndef QGSSPPINBOX_H
-#define QGSSPPINBOX_H
+#ifndef QGSSPINBOX_H
+#define QGSSPINBOX_H
#include <QSpinBox>
-#include <QToolButton>
+
+class QgsSpinBoxLineEdit;
/** \ingroup gui
* @brief The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
@@ -28,20 +29,34 @@ class GUI_EXPORT QgsSpinBox : public QSpinBox
{
Q_OBJECT
Q_PROPERTY( bool showClearButton READ showClearButton WRITE setShowClearButton )
+ Q_PROPERTY( bool clearValue READ clearValue WRITE setClearValue )
+ Q_PROPERTY( bool expressionsEnabled READ expressionsEnabled WRITE setExpressionsEnabled )
public:
+
+ //! Behaviour when widget is cleared.
enum ClearValueMode
{
- MinimumValue,
- MaximumValue,
- CustomValue
+ MinimumValue, //!< Reset value to minimum()
+ MaximumValue, //!< Reset value to maximum()
+ CustomValue, //!< Reset value to custom value (see setClearValue() )
};
+ /** Constructor for QgsSpinBox.
+ * @param parent parent widget
+ */
explicit QgsSpinBox( QWidget *parent = nullptr );
- //! determines if the widget will show a clear button
- //! @note the clear button will set the widget to its minimum value
+ /** Sets whether the widget will show a clear button. The clear button
+ * allows users to reset the widget to a default or empty state.
+ * @param showClearButton set to true to show the clear button, or false to hide it
+ * @see showClearButton()
+ */
void setShowClearButton( const bool showClearButton );
+
+ /** Returns whether the widget is showing a clear button.
+ * @see setShowClearButton()
+ */
bool showClearButton() const {return mShowClearButton;}
/** Sets if the widget will allow entry of simple expressions, which are
@@ -50,6 +65,7 @@ class GUI_EXPORT QgsSpinBox : public QSpinBox
* @note added in QGIS 2.7
*/
void setExpressionsEnabled( const bool enabled );
+
/** Returns whether the widget will allow entry of simple expressions, which are
* evaluated and then discarded.
* @returns true if spin box allows expression entry
@@ -61,26 +77,30 @@ class GUI_EXPORT QgsSpinBox : public QSpinBox
virtual void clear() override;
/**
- * @brief setClearValue defines the clear value for the widget and will automatically set the clear value mode to CustomValue
+ * Defines the clear value as a custom value and will automatically set the clear value mode to CustomValue.
* @param customValue defines the numerical value used as the clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
+ * @see setClearValue()
*/
void setClearValue( int customValue, const QString& clearValueText = QString() );
+
/**
- * @brief setClearValueMode defines if the clear value should be the minimum or maximum values of the widget or a custom value
+ * Defines if the clear value should be the minimum or maximum values of the widget or a custom value.
* @param mode mode to user for clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
*/
void setClearValueMode( ClearValueMode mode, const QString& clearValueText = QString() );
- //! returns the value used when clear() is called.
+ /** Returns the value used when clear() is called.
+ * @see setClearValue()
+ */
int clearValue() const;
virtual int valueFromText( const QString & text ) const override;
virtual QValidator::State validate( QString & input, int & pos ) const override;
protected:
- virtual void resizeEvent( QResizeEvent* event ) override;
+
virtual void changeEvent( QEvent* event ) override;
virtual void paintEvent( QPaintEvent* event ) override;
@@ -91,14 +111,15 @@ class GUI_EXPORT QgsSpinBox : public QSpinBox
int frameWidth() const;
bool shouldShowClearForValue( const int value ) const;
+ QgsSpinBoxLineEdit* mLineEdit;
+
bool mShowClearButton;
ClearValueMode mClearValueMode;
int mCustomClearValue;
bool mExpressionsEnabled;
- QToolButton* mClearButton;
QString stripped( const QString &originalText ) const;
};
-#endif // QGSSPPINBOX_H
+#endif // QGSSPINBOX_H
diff --git a/src/gui/editorwidgets/qgstexteditconfigdlg.cpp b/src/gui/editorwidgets/qgstexteditconfigdlg.cpp
index 8c732ad..2b99763 100644
--- a/src/gui/editorwidgets/qgstexteditconfigdlg.cpp
+++ b/src/gui/editorwidgets/qgstexteditconfigdlg.cpp
@@ -19,6 +19,8 @@ QgsTextEditConfigDlg::QgsTextEditConfigDlg( QgsVectorLayer* vl, int fieldIdx, QW
: QgsEditorConfigWidget( vl, fieldIdx, parent )
{
setupUi( this );
+ connect( mIsMultiline, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mUseHtml, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
}
diff --git a/src/gui/editorwidgets/qgstexteditwrapper.cpp b/src/gui/editorwidgets/qgstexteditwrapper.cpp
index 6c508a0..87e76ea 100644
--- a/src/gui/editorwidgets/qgstexteditwrapper.cpp
+++ b/src/gui/editorwidgets/qgstexteditwrapper.cpp
@@ -66,9 +66,19 @@ QVariant QgsTextEditWrapper::value() const
QVariant res( v );
if ( field().convertCompatible( res ) )
+ {
return res;
+ }
+ else if ( field().type() == QVariant::String && field().length() > 0 )
+ {
+ // for string fields convertCompatible may return false due to field length limit - in this case just truncate
+ // input rather then discarding it entirely
+ return QVariant( v.left( field().length() ) );
+ }
else
+ {
return QVariant( field().type() );
+ }
}
QWidget* QgsTextEditWrapper::createWidget( QWidget* parent )
diff --git a/src/gui/editorwidgets/qgsuniquevaluesconfigdlg.cpp b/src/gui/editorwidgets/qgsuniquevaluesconfigdlg.cpp
index c160894..f6e080f 100644
--- a/src/gui/editorwidgets/qgsuniquevaluesconfigdlg.cpp
+++ b/src/gui/editorwidgets/qgsuniquevaluesconfigdlg.cpp
@@ -19,6 +19,7 @@ QgsUniqueValuesConfigDlg::QgsUniqueValuesConfigDlg( QgsVectorLayer* vl, int fiel
: QgsEditorConfigWidget( vl, fieldIdx, parent )
{
setupUi( this );
+ connect( editableUniqueValues, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
}
diff --git a/src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp b/src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp
index 9737707..ce29222 100644
--- a/src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp
+++ b/src/gui/editorwidgets/qgsvaluemapconfigdlg.cpp
@@ -92,6 +92,8 @@ void QgsValueMapConfigDlg::vCellChanged( int row, int column )
{
tableWidget->insertRow( row + 1 );
} //else check type
+
+ emit changed();
}
void QgsValueMapConfigDlg::removeSelectedButtonPushed()
@@ -116,6 +118,7 @@ void QgsValueMapConfigDlg::removeSelectedButtonPushed()
tableWidget->removeRow( rowsToRemove.values().at( i ) - removed );
removed++;
}
+ emit changed();
}
void QgsValueMapConfigDlg::updateMap( const QMap<QString, QVariant> &map, bool insertNull )
diff --git a/src/gui/editorwidgets/qgsvaluerelationconfigdlg.cpp b/src/gui/editorwidgets/qgsvaluerelationconfigdlg.cpp
index 6d1e18f..eb11d8f 100644
--- a/src/gui/editorwidgets/qgsvaluerelationconfigdlg.cpp
+++ b/src/gui/editorwidgets/qgsvaluerelationconfigdlg.cpp
@@ -26,6 +26,15 @@ QgsValueRelationConfigDlg::QgsValueRelationConfigDlg( QgsVectorLayer* vl, int fi
connect( mLayerName, SIGNAL( layerChanged( QgsMapLayer* ) ), mKeyColumn, SLOT( setLayer( QgsMapLayer* ) ) );
connect( mLayerName, SIGNAL( layerChanged( QgsMapLayer* ) ), mValueColumn, SLOT( setLayer( QgsMapLayer* ) ) );
connect( mEditExpression, SIGNAL( clicked() ), this, SLOT( editExpression() ) );
+
+ connect( mLayerName, SIGNAL( layerChanged( QgsMapLayer* ) ), this, SIGNAL( changed() ) );
+ connect( mKeyColumn, SIGNAL( currentIndexChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( mValueColumn, SIGNAL( currentIndexChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( mAllowMulti, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mAllowNull, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mOrderByValue, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
+ connect( mFilterExpression, SIGNAL( textChanged() ), this, SIGNAL( changed() ) );
+ connect( mUseCompleter, SIGNAL( toggled( bool ) ), this, SIGNAL( changed() ) );
}
QgsEditorWidgetConfig QgsValueRelationConfigDlg::config()
diff --git a/src/gui/editorwidgets/qgsvaluerelationwidgetfactory.cpp b/src/gui/editorwidgets/qgsvaluerelationwidgetfactory.cpp
index 1754477..ec195e7 100644
--- a/src/gui/editorwidgets/qgsvaluerelationwidgetfactory.cpp
+++ b/src/gui/editorwidgets/qgsvaluerelationwidgetfactory.cpp
@@ -141,8 +141,6 @@ Qt::AlignmentFlag QgsValueRelationWidgetFactory::alignmentFlag( QgsVectorLayer*
Q_UNUSED( fieldIdx );
Q_UNUSED( config );
- QgsDebugMsg( "Entered" );
-
return Qt::AlignLeft;
}
diff --git a/src/gui/editorwidgets/qgswebviewconfigdlg.cpp b/src/gui/editorwidgets/qgswebviewconfigdlg.cpp
index 5d1ef21..c4ba7c1 100644
--- a/src/gui/editorwidgets/qgswebviewconfigdlg.cpp
+++ b/src/gui/editorwidgets/qgswebviewconfigdlg.cpp
@@ -19,6 +19,8 @@ QgsWebViewWidgetConfigDlg::QgsWebViewWidgetConfigDlg( QgsVectorLayer* vl, int fi
: QgsEditorConfigWidget( vl, fieldIdx, parent )
{
setupUi( this );
+ connect( sbWidgetHeight, SIGNAL( valueChanged( int ) ), this, SIGNAL( changed() ) );
+ connect( sbWidgetWidth, SIGNAL( valueChanged( int ) ), this, SIGNAL( changed() ) );
}
QgsEditorWidgetConfig QgsWebViewWidgetConfigDlg::config()
diff --git a/src/gui/effects/qgseffectstackpropertieswidget.cpp b/src/gui/effects/qgseffectstackpropertieswidget.cpp
index 2b53469..8890288 100644
--- a/src/gui/effects/qgseffectstackpropertieswidget.cpp
+++ b/src/gui/effects/qgseffectstackpropertieswidget.cpp
@@ -130,8 +130,18 @@ QgsEffectStackPropertiesWidget::QgsEffectStackPropertiesWidget( QgsEffectStack *
updateUi();
- // set effect as active item in the tree
- QModelIndex newIndex = mEffectsList->model()->index( 0, 0 );
+ // set first selected effect as active item in the tree
+ int initialRow = 0;
+ for ( int i = 0; i < stack->count(); ++i )
+ {
+ // list shows effects in opposite order to stack
+ if ( stack->effect( stack->count() - i - 1 )->enabled() )
+ {
+ initialRow = i;
+ break;
+ }
+ }
+ QModelIndex newIndex = mEffectsList->model()->index( initialRow, 0 );
mEffectsList->setCurrentIndex( newIndex );
setPanelTitle( tr( "Effects Properties" ) );
diff --git a/src/gui/layertree/qgslayertreeview.cpp b/src/gui/layertree/qgslayertreeview.cpp
index 2297e89..8f93800 100644
--- a/src/gui/layertree/qgslayertreeview.cpp
+++ b/src/gui/layertree/qgslayertreeview.cpp
@@ -138,7 +138,7 @@ void QgsLayerTreeView::modelRowsInserted( const QModelIndex& index, int start, i
if ( QgsMapLayer* layer = nodeLayer->layer() )
{
int widgetsCount = layer->customProperty( "embeddedWidgets/count", 0 ).toInt();
- QList<QgsLayerTreeModelLegendNode*> legendNodes = layerTreeModel()->layerLegendNodes( nodeLayer );
+ QList<QgsLayerTreeModelLegendNode*> legendNodes = layerTreeModel()->layerLegendNodes( nodeLayer, true );
for ( int i = 0; i < widgetsCount; ++i )
{
QString providerId = layer->customProperty( QString( "embeddedWidgets/%1/id" ).arg( i ) ).toString();
@@ -159,7 +159,7 @@ void QgsLayerTreeView::modelRowsInserted( const QModelIndex& index, int start, i
if ( expandedNodeKeys.isEmpty() )
return;
- Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, layerTreeModel()->layerLegendNodes( QgsLayerTree::toLayer( parentNode ) ) )
+ Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, layerTreeModel()->layerLegendNodes( QgsLayerTree::toLayer( parentNode ), true ) )
{
QString ruleKey = legendNode->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString();
if ( expandedNodeKeys.contains( ruleKey ) )
@@ -336,3 +336,49 @@ void QgsLayerTreeView::refreshLayerSymbology( const QString& layerId )
if ( nodeLayer )
layerTreeModel()->refreshLayerLegend( nodeLayer );
}
+
+
+static void _expandAllLegendNodes( QgsLayerTreeLayer* nodeLayer, bool expanded, QgsLayerTreeModel* model )
+{
+ // for layers we also need to find out with legend nodes contain some children and make them expanded/collapsed
+ // if we are collapsing, we just write out an empty list
+ QStringList lst;
+ if ( expanded )
+ {
+ Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, model->layerLegendNodes( nodeLayer, true ) )
+ {
+ QString parentKey = legendNode->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString();
+ if ( !parentKey.isEmpty() && !lst.contains( parentKey ) )
+ lst << parentKey;
+ }
+ }
+ nodeLayer->setCustomProperty( "expandedLegendNodes", lst );
+}
+
+
+static void _expandAllNodes( QgsLayerTreeGroup* parent, bool expanded, QgsLayerTreeModel* model )
+{
+ Q_FOREACH ( QgsLayerTreeNode* node, parent->children() )
+ {
+ node->setExpanded( expanded );
+ if ( QgsLayerTree::isGroup( node ) )
+ _expandAllNodes( QgsLayerTree::toGroup( node ), expanded, model );
+ else if ( QgsLayerTree::isLayer( node ) )
+ _expandAllLegendNodes( QgsLayerTree::toLayer( node ), expanded, model );
+ }
+}
+
+
+void QgsLayerTreeView::expandAllNodes()
+{
+ // unfortunately expandAll() does not emit expanded() signals
+ _expandAllNodes( layerTreeModel()->rootGroup(), true, layerTreeModel() );
+ expandAll();
+}
+
+void QgsLayerTreeView::collapseAllNodes()
+{
+ // unfortunately collapseAll() does not emit collapsed() signals
+ _expandAllNodes( layerTreeModel()->rootGroup(), false, layerTreeModel() );
+ collapseAll();
+}
diff --git a/src/gui/layertree/qgslayertreeview.h b/src/gui/layertree/qgslayertreeview.h
index e04adbd..e0e5040 100644
--- a/src/gui/layertree/qgslayertreeview.h
+++ b/src/gui/layertree/qgslayertreeview.h
@@ -92,6 +92,14 @@ class GUI_EXPORT QgsLayerTreeView : public QTreeView
//! Force refresh of layer symbology. Normally not needed as the changes of layer's renderer are monitored by the model
void refreshLayerSymbology( const QString& layerId );
+ //! Enhancement of QTreeView::expandAll() that also records expanded state in layer tree nodes
+ //! @note added in QGIS 2.18
+ void expandAllNodes();
+
+ //! Enhancement of QTreeView::collapseAll() that also records expanded state in layer tree nodes
+ //! @note added in QGIS 2.18
+ void collapseAllNodes();
+
signals:
//! Emitted when a current layer is changed
void currentLayerChanged( QgsMapLayer* layer );
diff --git a/src/gui/qgsattributeform.cpp b/src/gui/qgsattributeform.cpp
index b123c37..50efd83 100644
--- a/src/gui/qgsattributeform.cpp
+++ b/src/gui/qgsattributeform.cpp
@@ -26,6 +26,7 @@
#include "qgsattributeformeditorwidget.h"
#include "qgsmessagebar.h"
#include "qgsmessagebaritem.h"
+#include "qgstabwidget.h"
#include <QDir>
#include <QTextStream>
@@ -38,12 +39,12 @@
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
-#include <QTabWidget>
#include <QUiLoader>
#include <QMessageBox>
#include <QSettings>
#include <QToolButton>
#include <QMenu>
+#include <QSvgWidget>
int QgsAttributeForm::sFormCounter = 0;
@@ -185,20 +186,17 @@ void QgsAttributeForm::setMode( QgsAttributeForm::Mode mode )
case QgsAttributeForm::SingleEditMode:
setFeature( mFeature );
mSearchButtonBox->setVisible( false );
- mInvalidConstraintMessage->show();
break;
case QgsAttributeForm::AddFeatureMode:
synchronizeEnabledState();
mSearchButtonBox->setVisible( false );
- mInvalidConstraintMessage->show();
break;
case QgsAttributeForm::MultiEditMode:
resetMultiEdit( false );
synchronizeEnabledState();
mSearchButtonBox->setVisible( false );
- mInvalidConstraintMessage->show();
break;
case QgsAttributeForm::SearchMode:
@@ -211,7 +209,7 @@ void QgsAttributeForm::setMode( QgsAttributeForm::Mode mode )
}
else
{
- mInvalidConstraintMessage->hide();
+ mTopMessageWidget->hide();
}
break;
}
@@ -744,6 +742,14 @@ void QgsAttributeForm::updateConstraints( QgsEditorWidgetWrapper *eww )
// sync ok button status
synchronizeEnabledState();
+
+ mExpressionContext.setFeature( ft );
+
+ // Recheck visibility for all containers which are controlled by this value
+ Q_FOREACH ( ContainerInformation* info, mContainerInformationDependency.value( eww->field().name() ) )
+ {
+ info->apply( &mExpressionContext );
+ }
}
}
@@ -757,7 +763,11 @@ bool QgsAttributeForm::currentFormFeature( QgsFeature &feature )
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
{
QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
- if ( eww && dst.count() > eww->fieldIdx() )
+
+ if ( !eww )
+ continue;
+
+ if ( dst.count() > eww->fieldIdx() )
{
QVariant dstVar = dst.at( eww->fieldIdx() );
QVariant srcVar = eww->value();
@@ -780,9 +790,8 @@ bool QgsAttributeForm::currentFormFeature( QgsFeature &feature )
void QgsAttributeForm::clearInvalidConstraintsMessage()
{
- mInvalidConstraintMessage->hide();
+ mTopMessageWidget->hide();
mInvalidConstraintMessage->clear();
- mInvalidConstraintMessage->setStyleSheet( QString() );
}
void QgsAttributeForm::displayInvalidConstraintMessage( const QStringList& f,
@@ -797,14 +806,19 @@ void QgsAttributeForm::displayInvalidConstraintMessage( const QStringList& f,
for ( int i = 0; i < size; i++ )
descriptions += QString( "<li>%1: <i>%2</i></li>" ).arg( f[i] ).arg( d[i] );
- QString icPath = QgsApplication::iconPath( "/mIconWarn.png" );
-
- QString title = QString( "<img src=\"%1\"> <b>%2:" ).arg( icPath ).arg( tr( "Invalid fields" ) );
- QString msg = QString( "%1</b><ul>%2</ul>" ).arg( title ).arg( descriptions ) ;
+ QString msg = QString( "<b>%1</b><ul>%2</ul>" ).arg( tr( "Invalid fields" ) ).arg( descriptions ) ;
- mInvalidConstraintMessage->show();
mInvalidConstraintMessage->setText( msg );
- mInvalidConstraintMessage->setStyleSheet( "QLabel { background-color : #ffc800; }" );
+ mTopMessageWidget->show();
+}
+
+void QgsAttributeForm::registerContainerInformation( QgsAttributeForm::ContainerInformation* info )
+{
+ mContainerVisibilityInformation.append( info );
+ Q_FOREACH ( const QString& col, info->expression.referencedColumns() )
+ {
+ mContainerInformationDependency[ col ].append( info );
+ }
}
bool QgsAttributeForm::currentFormValidConstraints( QStringList &invalidFields,
@@ -1049,9 +1063,18 @@ void QgsAttributeForm::init()
mMessageBar->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
vl->addWidget( mMessageBar );
+ mTopMessageWidget = new QWidget();
+ mTopMessageWidget->hide();
+ mTopMessageWidget->setLayout( new QHBoxLayout() );
+
+ QSvgWidget* warningIcon = new QSvgWidget( QgsApplication::iconPath( "/mIconWarning.svg" ) );
+ warningIcon->setFixedSize( 48, 48 );
+ mTopMessageWidget->layout()->addWidget( warningIcon );
mInvalidConstraintMessage = new QLabel( this );
- mInvalidConstraintMessage->hide();
- vl->addWidget( mInvalidConstraintMessage );
+ mTopMessageWidget->layout()->addWidget( mInvalidConstraintMessage );
+ mTopMessageWidget->hide();
+
+ vl->addWidget( mTopMessageWidget );
setLayout( vl );
@@ -1090,7 +1113,7 @@ void QgsAttributeForm::init()
}
}
- QTabWidget* tabWidget = nullptr;
+ QgsTabWidget* tabWidget = nullptr;
// Tab layout
if ( !formWidget && mLayer->editFormConfig()->layout() == QgsEditFormConfig::TabLayout )
@@ -1112,13 +1135,14 @@ void QgsAttributeForm::init()
tabWidget = nullptr;
WidgetInfo widgetInfo = createWidgetFromDef( widgDef, formWidget, mLayer, mContext );
layout->addWidget( widgetInfo.widget, row, column, 1, 2 );
+ registerContainerInformation( new ContainerInformation( widgetInfo.widget, containerDef->visibilityExpression().data() ) );
column += 2;
}
else
{
if ( !tabWidget )
{
- tabWidget = new QTabWidget();
+ tabWidget = new QgsTabWidget();
layout->addWidget( tabWidget, row, column, 1, 2 );
column += 2;
}
@@ -1126,6 +1150,11 @@ void QgsAttributeForm::init()
QWidget* tabPage = new QWidget( tabWidget );
tabWidget->addTab( tabPage, widgDef->name() );
+
+ if ( containerDef->visibilityExpression().enabled() )
+ {
+ registerContainerInformation( new ContainerInformation( tabWidget, tabPage, containerDef->visibilityExpression().data() ) );
+ }
QGridLayout* tabPageLayout = new QGridLayout();
tabPage->setLayout( tabPageLayout );
@@ -1145,7 +1174,15 @@ void QgsAttributeForm::init()
label->setBuddy( widgetInfo.widget );
- if ( widgetInfo.labelOnTop )
+ if ( !widgetInfo.showLabel )
+ {
+ QVBoxLayout* c = new QVBoxLayout();
+ label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
+ c->addWidget( widgetInfo.widget );
+ layout->addLayout( c, row, column, 1, 2 );
+ column += 2;
+ }
+ else if ( widgetInfo.labelOnTop )
{
QVBoxLayout* c = new QVBoxLayout();
label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
@@ -1511,19 +1548,23 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
newWidgetInfo.labelOnTop = mLayer->editFormConfig()->labelOnTop( fieldDef->idx() );
newWidgetInfo.labelText = mLayer->attributeDisplayName( fieldDef->idx() );
+ newWidgetInfo.showLabel = widgetDef->showLabel();
break;
}
case QgsAttributeEditorElement::AeTypeRelation:
{
- const QgsAttributeEditorRelation* relDef = dynamic_cast<const QgsAttributeEditorRelation*>( widgetDef );
+ const QgsAttributeEditorRelation* relDef = static_cast<const QgsAttributeEditorRelation*>( widgetDef );
QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relDef->relation(), nullptr, this );
QgsEditorWidgetConfig cfg = mLayer->editFormConfig()->widgetConfig( relDef->relation().id() );
rww->setConfig( cfg );
rww->setContext( context );
newWidgetInfo.widget = rww->widget();
+ rww->setShowLabel( relDef->showLabel() );
+ rww->setShowLinkButton( relDef->showLinkButton() );
+ rww->setShowUnlinkButton( relDef->showUnlinkButton() );
mWidgets.append( rww );
newWidgetInfo.labelText = QString::null;
newWidgetInfo.labelOnTop = true;
@@ -1545,7 +1586,8 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
if ( container->isGroupBox() )
{
QGroupBox* groupBox = new QGroupBox( parent );
- groupBox->setTitle( container->name() );
+ if ( container->showLabel() )
+ groupBox->setTitle( container->name() );
myContainer = groupBox;
newWidgetInfo.widget = myContainer;
}
@@ -1581,6 +1623,12 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
{
WidgetInfo widgetInfo = createWidgetFromDef( childDef, myContainer, vl, context );
+ if ( childDef->type() == QgsAttributeEditorElement::AeTypeContainer )
+ {
+ QgsAttributeEditorContainer* containerDef = static_cast<QgsAttributeEditorContainer*>( childDef );
+ registerContainerInformation( new ContainerInformation( widgetInfo.widget, containerDef->visibilityExpression().data() ) );
+ }
+
if ( widgetInfo.labelText.isNull() )
{
gbLayout->addWidget( widgetInfo.widget, row, column, 1, 2 );
@@ -1633,6 +1681,8 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
break;
}
+ newWidgetInfo.showLabel = widgetDef->showLabel();
+
return newWidgetInfo;
}
@@ -1860,3 +1910,22 @@ int QgsAttributeForm::messageTimeout()
QSettings settings;
return settings.value( "/qgis/messageTimeout", 5 ).toInt();
}
+
+void QgsAttributeForm::ContainerInformation::apply( QgsExpressionContext* expressionContext )
+{
+ bool newVisibility = expression.evaluate( expressionContext ).toBool();
+
+ if ( newVisibility != isVisible )
+ {
+ if ( tabWidget )
+ {
+ tabWidget->setTabVisible( widget, newVisibility );
+ }
+ else
+ {
+ widget->setVisible( newVisibility );
+ }
+
+ isVisible = newVisibility;
+ }
+}
diff --git a/src/gui/qgsattributeform.h b/src/gui/qgsattributeform.h
index 76f96b9..2296e5b 100644
--- a/src/gui/qgsattributeform.h
+++ b/src/gui/qgsattributeform.h
@@ -29,6 +29,7 @@ class QgsAttributeFormEditorWidget;
class QgsMessageBar;
class QgsMessageBarItem;
class QgsWidgetWrapper;
+class QgsTabWidget;
/** \ingroup gui
* \class QgsAttributeForm
@@ -288,12 +289,14 @@ class GUI_EXPORT QgsAttributeForm : public QWidget
: widget( nullptr )
, labelOnTop( false )
, labelAlignRight( false )
+ , showLabel( true )
{}
QWidget* widget;
QString labelText;
bool labelOnTop;
bool labelAlignRight;
+ bool showLabel;
};
WidgetInfo createWidgetFromDef( const QgsAttributeEditorElement* widgetDef, QWidget* parent, QgsVectorLayer* vl, QgsAttributeEditorContext& context );
@@ -336,12 +339,44 @@ class GUI_EXPORT QgsAttributeForm : public QWidget
QgsMessageBarItem* mMultiEditUnsavedMessageBarItem;
QgsMessageBarItem* mMultiEditMessageBarItem;
QLabel* mInvalidConstraintMessage;
+ QWidget* mTopMessageWidget;
QList<QgsWidgetWrapper*> mWidgets;
QgsAttributeEditorContext mContext;
QDialogButtonBox* mButtonBox;
QWidget* mSearchButtonBox;
QList<QgsAttributeFormInterface*> mInterfaces;
QMap< int, QgsAttributeFormEditorWidget* > mFormEditorWidgets;
+ QgsExpressionContext mExpressionContext;
+
+ struct ContainerInformation
+ {
+ ContainerInformation( QgsTabWidget* tabWidget, QWidget* widget, QgsExpression expression )
+ : tabWidget( tabWidget )
+ , widget( widget )
+ , expression( expression )
+ , isVisible( true )
+ {}
+
+ ContainerInformation( QWidget* widget, QgsExpression expression )
+ : tabWidget( nullptr )
+ , widget( widget )
+ , expression( expression )
+ , isVisible( true )
+ {}
+
+ QgsTabWidget* tabWidget;
+ QWidget* widget;
+ QgsExpression expression;
+ bool isVisible;
+
+ void apply( QgsExpressionContext* expressionContext );
+ };
+
+ void registerContainerInformation( ContainerInformation* info );
+
+ // Contains information about tabs and groupboxes, their visibility state visibility conditions
+ QVector<ContainerInformation*> mContainerVisibilityInformation;
+ QMap<QString, QVector<ContainerInformation*> > mContainerInformationDependency;
// Variables below are used for python
static int sFormCounter;
diff --git a/src/gui/qgscolorbuttonv2.cpp b/src/gui/qgscolorbuttonv2.cpp
index 7ec50a7..332dcc3 100644
--- a/src/gui/qgscolorbuttonv2.cpp
+++ b/src/gui/qgscolorbuttonv2.cpp
@@ -94,6 +94,18 @@ const QPixmap& QgsColorButtonV2::transparentBackground()
void QgsColorButtonV2::showColorDialog()
{
+ if ( QgsPanelWidget* panel = QgsPanelWidget::findParentPanel( this ) )
+ {
+ QgsCompoundColorWidget* colorWidget = new QgsCompoundColorWidget( panel, color(), panel->dockMode() ? QgsCompoundColorWidget::LayoutVertical :
+ QgsCompoundColorWidget::LayoutDefault );
+ colorWidget->setPanelTitle( mColorDialogTitle );
+ colorWidget->setAllowAlpha( mAllowAlpha );
+ connect( colorWidget, SIGNAL( currentColorChanged( QColor ) ), this, SLOT( setValidTemporaryColor( QColor ) ) );
+ connect( colorWidget, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( panelAccepted( QgsPanelWidget* ) ) );
+ panel->openPanel( colorWidget );
+ return;
+ }
+
QColor newColor;
QSettings settings;
@@ -171,9 +183,9 @@ bool QgsColorButtonV2::event( QEvent *e )
int saturation = this->color().saturation();
QString info = QString( "HEX: %1 \n"
"RGB: %2 \n"
- "HSV: %3,%4,%4" ).arg( name )
+ "HSV: %3,%4,%5" ).arg( name )
.arg( QgsSymbolLayerV2Utils::encodeColor( this->color() ) )
- .arg( hue ).arg( value ).arg( saturation );
+ .arg( hue ).arg( saturation ).arg( value );
setToolTip( info );
}
return QToolButton::event( e );
@@ -368,6 +380,22 @@ void QgsColorButtonV2::setValidColor( const QColor& newColor )
}
}
+void QgsColorButtonV2::setValidTemporaryColor( const QColor& newColor )
+{
+ if ( newColor.isValid() )
+ {
+ setColor( newColor );
+ }
+}
+
+void QgsColorButtonV2::panelAccepted( QgsPanelWidget* widget )
+{
+ if ( QgsCompoundColorWidget* colorWidget = qobject_cast< QgsCompoundColorWidget* >( widget ) )
+ {
+ addRecentColor( colorWidget->color() );
+ }
+}
+
QPixmap QgsColorButtonV2::createMenuIcon( const QColor &color, const bool showChecks )
{
//create an icon pixmap
diff --git a/src/gui/qgscolorbuttonv2.h b/src/gui/qgscolorbuttonv2.h
index eaa71f3..5a25080 100644
--- a/src/gui/qgscolorbuttonv2.h
+++ b/src/gui/qgscolorbuttonv2.h
@@ -22,6 +22,7 @@
class QMimeData;
class QgsColorSchemeRegistry;
+class QgsPanelWidget;
/** \ingroup gui
* \class QgsColorButtonV2
@@ -420,6 +421,14 @@ class GUI_EXPORT QgsColorButtonV2 : public QToolButton
*/
void setValidColor( const QColor& newColor );
+ /** Sets color for button, if valid. The color is treated as a temporary color, and is not
+ * added to the recent colors list.
+ */
+ void setValidTemporaryColor( const QColor& newColor );
+
+ //! Called when a color widget panel is accepted, and adds the final color to the recent colors list
+ void panelAccepted( QgsPanelWidget* widget );
+
/** Adds a color to the recent colors list
* @param color to add to recent colors list
*/
diff --git a/src/gui/qgscolorschemelist.cpp b/src/gui/qgscolorschemelist.cpp
index ba447d2..48ba063 100644
--- a/src/gui/qgscolorschemelist.cpp
+++ b/src/gui/qgscolorschemelist.cpp
@@ -231,6 +231,11 @@ bool QgsColorSchemeList::isDirty() const
return mModel->isDirty();
}
+QgsColorScheme*QgsColorSchemeList::scheme()
+{
+ return mScheme;
+}
+
//
// QgsColorSchemeModel
//
diff --git a/src/gui/qgscolorschemelist.h b/src/gui/qgscolorschemelist.h
index 1785363..2dd10b7 100644
--- a/src/gui/qgscolorschemelist.h
+++ b/src/gui/qgscolorschemelist.h
@@ -182,12 +182,19 @@ class GUI_EXPORT QgsColorSchemeList: public QTreeView
*/
bool isDirty() const;
+ /** Returns the scheme currently selected in the list.
+ * @note added in QGIS 2.18
+ * @see setScheme()
+ */
+ QgsColorScheme* scheme();
+
public slots:
/** Sets the color scheme to show in the list
* @param scheme QgsColorScheme for colors to show in the list
* @param context context string provided to color scheme
* @param baseColor base color for color scheme
+ * @see scheme()
*/
void setScheme( QgsColorScheme* scheme, const QString &context = QString(), const QColor &baseColor = QColor() );
diff --git a/src/gui/qgscolorwidgets.cpp b/src/gui/qgscolorwidgets.cpp
index 6843740..e71de04 100644
--- a/src/gui/qgscolorwidgets.cpp
+++ b/src/gui/qgscolorwidgets.cpp
@@ -1178,6 +1178,27 @@ void QgsColorRampWidget::mouseMoveEvent( QMouseEvent *event )
QgsColorWidget::mouseMoveEvent( event );
}
+void QgsColorRampWidget::wheelEvent( QWheelEvent *event )
+{
+ int oldValue = componentValue();
+
+ if ( event->delta() > 0 )
+ {
+ setComponentValue( componentValue() + 1 );
+ }
+ else
+ {
+ setComponentValue( componentValue() - 1 );
+ }
+
+ if ( componentValue() != oldValue )
+ {
+ //value has changed
+ emit colorChanged( mCurrentColor );
+ emit valueChanged( componentValue() );
+ }
+}
+
void QgsColorRampWidget::mousePressEvent( QMouseEvent *event )
{
setColorFromPoint( event->posF() );
diff --git a/src/gui/qgscolorwidgets.h b/src/gui/qgscolorwidgets.h
index 73ab480..d4ffc04 100644
--- a/src/gui/qgscolorwidgets.h
+++ b/src/gui/qgscolorwidgets.h
@@ -515,6 +515,7 @@ class GUI_EXPORT QgsColorRampWidget : public QgsColorWidget
protected:
virtual void mouseMoveEvent( QMouseEvent *event ) override;
+ virtual void wheelEvent( QWheelEvent* event ) override;
virtual void mousePressEvent( QMouseEvent *event ) override;
virtual void keyPressEvent( QKeyEvent * event ) override;
diff --git a/src/gui/qgscomposeritemcombobox.cpp b/src/gui/qgscomposeritemcombobox.cpp
index f74dc54..b7c4acb 100644
--- a/src/gui/qgscomposeritemcombobox.cpp
+++ b/src/gui/qgscomposeritemcombobox.cpp
@@ -23,7 +23,7 @@ QgsComposerItemComboBox::QgsComposerItemComboBox( QWidget *parent, QgsCompositio
setComposition( composition );
setModelColumn( QgsComposerModel::ItemId );
- connect( this, SIGNAL( activated( int ) ), this, SLOT( indexChanged( int ) ) );
+ connect( this, SIGNAL( currentIndexChanged( int ) ), this, SLOT( indexChanged( int ) ) );
connect( mProxyModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( rowsChanged() ) );
connect( mProxyModel, SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( rowsChanged() ) );
}
diff --git a/src/gui/qgscompoundcolorwidget.cpp b/src/gui/qgscompoundcolorwidget.cpp
index d9e6d20..0389c90 100644
--- a/src/gui/qgscompoundcolorwidget.cpp
+++ b/src/gui/qgscompoundcolorwidget.cpp
@@ -28,15 +28,30 @@
#include <QDesktopWidget>
#include <QMouseEvent>
#include <QInputDialog>
+#include <QVBoxLayout>
-QgsCompoundColorWidget::QgsCompoundColorWidget( QWidget *parent, const QColor& color )
- : QWidget( parent )
+QgsCompoundColorWidget::QgsCompoundColorWidget( QWidget *parent, const QColor& color, Layout widgetLayout )
+ : QgsPanelWidget( parent )
, mAllowAlpha( true )
, mLastCustomColorIndex( 0 )
, mPickingColor( false )
{
setupUi( this );
+ if ( widgetLayout == LayoutVertical )
+ {
+ // shuffle stuff around
+ QVBoxLayout* newLayout = new QVBoxLayout();
+ newLayout->setMargin( 0 );
+ newLayout->setContentsMargins( 0, 0, 0, 0 );
+ newLayout->addWidget( mTabWidget );
+ newLayout->addWidget( mSlidersWidget );
+ newLayout->addWidget( mPreviewWidget );
+ newLayout->addWidget( mSwatchesWidget );
+ delete layout();
+ setLayout( newLayout );
+ }
+
QSettings settings;
mSchemeList->header()->hide();
@@ -51,13 +66,9 @@ QgsCompoundColorWidget::QgsCompoundColorWidget( QWidget *parent, const QColor& c
activeScheme = activeScheme >= mSchemeComboBox->count() ? 0 : activeScheme;
mSchemeList->setScheme( schemeList.at( activeScheme ) );
+
mSchemeComboBox->setCurrentIndex( activeScheme );
- mActionImportColors->setEnabled( schemeList.at( activeScheme )->isEditable() );
- mActionPasteColors->setEnabled( schemeList.at( activeScheme )->isEditable() );
- mAddColorToSchemeButton->setEnabled( schemeList.at( activeScheme )->isEditable() );
- mRemoveColorsFromSchemeButton->setEnabled( schemeList.at( activeScheme )->isEditable() );
- QgsUserColorScheme* userScheme = dynamic_cast<QgsUserColorScheme*>( schemeList.at( activeScheme ) );
- mActionRemovePalette->setEnabled( userScheme ? true : false );
+ updateActionsForCurrentScheme();
//listen out for selection changes in list, so we can enable/disable the copy colors option
connect( mSchemeList->selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), this, SLOT( listSelectionChanged( QItemSelection, QItemSelection ) ) );
@@ -83,6 +94,7 @@ QgsCompoundColorWidget::QgsCompoundColorWidget( QWidget *parent, const QColor& c
schemeMenu->addAction( mActionNewPalette );
schemeMenu->addAction( mActionImportPalette );
schemeMenu->addAction( mActionRemovePalette );
+ schemeMenu->addAction( mActionShowInButtons );
mSchemeToolButton->setMenu( schemeMenu );
connect( mSchemeComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( schemeIndexChanged( int ) ) );
@@ -479,12 +491,8 @@ void QgsCompoundColorWidget::schemeIndexChanged( int index )
QgsColorScheme* scheme = schemeList.at( index );
mSchemeList->setScheme( scheme );
- mActionImportColors->setEnabled( scheme->isEditable() );
- mActionPasteColors->setEnabled( scheme->isEditable() );
- mAddColorToSchemeButton->setEnabled( scheme->isEditable() );
- mRemoveColorsFromSchemeButton->setEnabled( scheme->isEditable() );
- QgsUserColorScheme* userScheme = dynamic_cast<QgsUserColorScheme*>( scheme );
- mActionRemovePalette->setEnabled( userScheme ? true : false );
+
+ updateActionsForCurrentScheme();
//copy action defaults to disabled
mActionCopyColors->setEnabled( false );
@@ -579,6 +587,15 @@ void QgsCompoundColorWidget::on_mTabWidget_currentChanged( int index )
mValueRadio->setEnabled( enabled );
}
+void QgsCompoundColorWidget::on_mActionShowInButtons_toggled( bool state )
+{
+ QgsUserColorScheme* scheme = dynamic_cast< QgsUserColorScheme* >( mSchemeList->scheme() );
+ if ( scheme )
+ {
+ scheme->setShowSchemeInMenu( state );
+ }
+}
+
void QgsCompoundColorWidget::saveSettings()
{
//save changes to scheme
@@ -838,3 +855,26 @@ void QgsCompoundColorWidget::on_mAddColorToSchemeButton_clicked()
{
mSchemeList->addColor( mColorPreview->color(), QgsSymbolLayerV2Utils::colorToName( mColorPreview->color() ) );
}
+
+void QgsCompoundColorWidget::updateActionsForCurrentScheme()
+{
+ QgsColorScheme* scheme = mSchemeList->scheme();
+
+ mActionImportColors->setEnabled( scheme->isEditable() );
+ mActionPasteColors->setEnabled( scheme->isEditable() );
+ mAddColorToSchemeButton->setEnabled( scheme->isEditable() );
+ mRemoveColorsFromSchemeButton->setEnabled( scheme->isEditable() );
+
+ QgsUserColorScheme* userScheme = dynamic_cast<QgsUserColorScheme*>( scheme );
+ mActionRemovePalette->setEnabled( userScheme ? true : false );
+ if ( userScheme )
+ {
+ mActionShowInButtons->setEnabled( true );
+ whileBlocking( mActionShowInButtons )->setChecked( userScheme->flags() & QgsColorScheme::ShowInColorButtonMenu );
+ }
+ else
+ {
+ whileBlocking( mActionShowInButtons )->setChecked( false );
+ mActionShowInButtons->setEnabled( false );
+ }
+}
diff --git a/src/gui/qgscompoundcolorwidget.h b/src/gui/qgscompoundcolorwidget.h
index 1373689..187e566 100644
--- a/src/gui/qgscompoundcolorwidget.h
+++ b/src/gui/qgscompoundcolorwidget.h
@@ -17,6 +17,7 @@
#define QGSCOMPOUNDCOLORWIDGET_H
#include "qgisgui.h"
+#include "qgspanelwidget.h"
#include "ui_qgscompoundcolorwidget.h"
/** \ingroup gui
@@ -26,18 +27,26 @@
* \note Added in version 2.16
*/
-class GUI_EXPORT QgsCompoundColorWidget : public QWidget, private Ui::QgsCompoundColorWidgetBase
+class GUI_EXPORT QgsCompoundColorWidget : public QgsPanelWidget, private Ui::QgsCompoundColorWidgetBase
{
Q_OBJECT
public:
+ //! Widget layout
+ enum Layout
+ {
+ LayoutDefault = 0, /*!< Use the default (rectangular) layout */
+ LayoutVertical, /*!< Use a narrower, vertically stacked layout */
+ };
+
/** Constructor for QgsCompoundColorWidget
* @param parent parent widget
* @param color initial color for dialog
+ * @param layout widget layout to use
*/
- QgsCompoundColorWidget( QWidget *parent = nullptr, const QColor& color = QColor() );
+ QgsCompoundColorWidget( QWidget *parent = nullptr, const QColor& color = QColor(), Layout layout = LayoutDefault );
~QgsCompoundColorWidget();
@@ -106,6 +115,10 @@ class GUI_EXPORT QgsCompoundColorWidget : public QWidget, private Ui::QgsCompoun
void on_mSampleButton_clicked();
void on_mTabWidget_currentChanged( int index );
+ private slots:
+
+ void on_mActionShowInButtons_toggled( bool state );
+
private:
bool mAllowAlpha;
@@ -144,6 +157,9 @@ class GUI_EXPORT QgsCompoundColorWidget : public QWidget, private Ui::QgsCompoun
/** Returns the path to the user's palette folder
*/
QString gplFilePath();
+
+ //! Updates the state of actions for the current selected scheme
+ void updateActionsForCurrentScheme();
};
#endif // QGSCOMPOUNDCOLORWIDGET_H
diff --git a/src/gui/qgsexpressionbuilderwidget.cpp b/src/gui/qgsexpressionbuilderwidget.cpp
index f3aa094..da39828 100644
--- a/src/gui/qgsexpressionbuilderwidget.cpp
+++ b/src/gui/qgsexpressionbuilderwidget.cpp
@@ -477,7 +477,7 @@ void QgsExpressionBuilderWidget::updateFunctionTree()
QString name = func->name();
if ( name.startsWith( '_' ) ) // do not display private functions
continue;
- if ( func->group() == "deprecated" ) // don't show deprecated functions
+ if ( func->isDeprecated() ) // don't show deprecated functions
continue;
if ( func->isContextual() )
{
@@ -489,14 +489,7 @@ void QgsExpressionBuilderWidget::updateFunctionTree()
name += '(';
else if ( !name.startsWith( '$' ) )
name += "()";
- registerItem( func->group(), func->name(), ' ' + name + ' ', func->helptext() );
- }
-
- QList<QgsExpression::Function*> specials = QgsExpression::specialColumns();
- for ( int i = 0; i < specials.size(); ++i )
- {
- QString name = specials[i]->name();
- registerItem( specials[i]->group(), name, ' ' + name + ' ' );
+ registerItemForAllGroups( func->groups(), func->name(), ' ' + name + ' ', func->helptext() );
}
loadExpressionContext();
@@ -619,7 +612,15 @@ void QgsExpressionBuilderWidget::loadExpressionContext()
continue;
if ( func->params() != 0 )
name += '(';
- registerItem( func->group(), func->name(), ' ' + name + ' ', func->helptext() );
+ registerItemForAllGroups( func->groups(), func->name(), ' ' + name + ' ', func->helptext() );
+ }
+}
+
+void QgsExpressionBuilderWidget::registerItemForAllGroups( const QStringList& groups, const QString& label, const QString& expressionText, const QString& helpText, QgsExpressionItem::ItemType type, bool highlightedItem, int sortOrder )
+{
+ Q_FOREACH ( const QString& group, groups )
+ {
+ registerItem( group, label, expressionText, helpText, type, highlightedItem, sortOrder );
}
}
diff --git a/src/gui/qgsexpressionbuilderwidget.h b/src/gui/qgsexpressionbuilderwidget.h
index 7ea188b..acd77f6 100644
--- a/src/gui/qgsexpressionbuilderwidget.h
+++ b/src/gui/qgsexpressionbuilderwidget.h
@@ -278,6 +278,20 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
void loadExpressionContext();
+ /** Registers a node item for the expression builder, adding multiple items when the function exists in multiple groups
+ * @param groups The groups the item will be show in the tree view. If a group doesn't exist it will be created.
+ * @param label The label that is show to the user for the item in the tree.
+ * @param expressionText The text that is inserted into the expression area when the user double clicks on the item.
+ * @param helpText The help text that the user will see when item is selected.
+ * @param type The type of the expression item.
+ * @param highlightedItem set to true to make the item highlighted, which inserts a bold copy of the item at the top level
+ * @param sortOrder sort ranking for item
+ */
+ void registerItemForAllGroups( const QStringList& groups, const QString& label, const QString& expressionText,
+ const QString& helpText = "",
+ QgsExpressionItem::ItemType type = QgsExpressionItem::ExpressionNode,
+ bool highlightedItem = false, int sortOrder = 1 );
+
bool mAutoSave;
QString mFunctionsPath;
QgsVectorLayer *mLayer;
diff --git a/src/gui/qgsexpressionlineedit.cpp b/src/gui/qgsexpressionlineedit.cpp
new file mode 100644
index 0000000..8662682
--- /dev/null
+++ b/src/gui/qgsexpressionlineedit.cpp
@@ -0,0 +1,214 @@
+/***************************************************************************
+ qgsexpressionlineedit.cpp
+ ------------------------
+ Date : 18.08.2016
+ Copyright : (C) 2016 Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+#include "qgsexpressionlineedit.h"
+#include "qgsfilterlineedit.h"
+#include "qgsexpressioncontext.h"
+#include "qgsapplication.h"
+#include "qgsexpressionbuilderdialog.h"
+#include "qgscodeeditorsql.h"
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QToolButton>
+
+
+QgsExpressionLineEdit::QgsExpressionLineEdit( QWidget *parent )
+ : QWidget( parent )
+ , mLineEdit( nullptr )
+ , mCodeEditor( nullptr )
+ , mExpressionDialogTitle( tr( "Expression dialog" ) )
+ , mDa( nullptr )
+ , mLayer( nullptr )
+{
+ mButton = new QToolButton();
+ mButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ mButton->setIcon( QgsApplication::getThemeIcon( "/mIconExpression.svg" ) );
+ connect( mButton, SIGNAL( clicked() ), this, SLOT( editExpression() ) );
+
+ //sets up layout
+ setMultiLine( false );
+
+ mExpressionContext = QgsExpressionContext();
+ mExpressionContext << QgsExpressionContextUtils::globalScope()
+ << QgsExpressionContextUtils::projectScope();
+}
+
+void QgsExpressionLineEdit::setExpressionDialogTitle( const QString& title )
+{
+ mExpressionDialogTitle = title;
+}
+
+void QgsExpressionLineEdit::setMultiLine( bool multiLine )
+{
+ QString exp = expression();
+
+ if ( multiLine && !mCodeEditor )
+ {
+ mCodeEditor = new QgsCodeEditorSQL();
+ mCodeEditor->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
+ delete mLineEdit;
+ mLineEdit = nullptr;
+
+ QHBoxLayout* newLayout = new QHBoxLayout();
+ newLayout->setContentsMargins( 0, 0, 0, 0 );
+ newLayout->addWidget( mCodeEditor );
+
+ QVBoxLayout* vLayout = new QVBoxLayout();
+ vLayout->addWidget( mButton );
+ vLayout->addStretch();
+ newLayout->addLayout( vLayout );
+
+ delete layout();
+ setLayout( newLayout );
+
+ setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
+
+ setFocusProxy( mCodeEditor );
+ connect( mCodeEditor, SIGNAL( textChanged() ), this, SLOT( expressionEdited() ) );
+
+ setExpression( exp );
+ }
+ else if ( !multiLine && !mLineEdit )
+ {
+ delete mCodeEditor;
+ mCodeEditor = nullptr;
+ mLineEdit = new QgsFilterLineEdit();
+ mLineEdit->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
+
+ QHBoxLayout* newLayout = new QHBoxLayout();
+ newLayout->setContentsMargins( 0, 0, 0, 0 );
+ newLayout->addWidget( mLineEdit );
+ newLayout->addWidget( mButton );
+
+ delete layout();
+ setLayout( newLayout );
+
+ setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
+
+ setFocusProxy( mLineEdit );
+ connect( mLineEdit, SIGNAL( textChanged( QString ) ), this, SLOT( expressionEdited( QString ) ) );
+
+ setExpression( exp );
+ }
+}
+
+void QgsExpressionLineEdit::setGeomCalculator( const QgsDistanceArea &da )
+{
+ mDa.reset( new QgsDistanceArea( da ) );
+}
+
+void QgsExpressionLineEdit::setLayer( QgsVectorLayer* layer )
+{
+ mLayer = layer;
+}
+
+QString QgsExpressionLineEdit::expression() const
+{
+ if ( mLineEdit )
+ return mLineEdit->text();
+ else if ( mCodeEditor )
+ return mCodeEditor->text();
+
+ return QString();
+}
+
+bool QgsExpressionLineEdit::isValidExpression( QString *expressionError ) const
+{
+ QString temp;
+ return QgsExpression::isValid( expression(), &mExpressionContext, expressionError ? *expressionError : temp );
+}
+
+void QgsExpressionLineEdit::setExpression( const QString& newExpression )
+{
+ if ( mLineEdit )
+ mLineEdit->setText( newExpression );
+ else if ( mCodeEditor )
+ mCodeEditor->setText( newExpression );
+}
+
+void QgsExpressionLineEdit::editExpression()
+{
+ QString currentExpression = expression();
+
+ QgsExpressionContext context = mExpressionContext;
+
+ QgsExpressionBuilderDialog dlg( mLayer, currentExpression, this, "generic", context );
+ if ( !mDa.isNull() )
+ {
+ dlg.setGeomCalculator( *mDa );
+ }
+ dlg.setWindowTitle( mExpressionDialogTitle );
+
+ if ( dlg.exec() )
+ {
+ QString newExpression = dlg.expressionText();
+ setExpression( newExpression );
+ }
+}
+
+void QgsExpressionLineEdit::expressionEdited()
+{
+ emit expressionChanged( expression() );
+}
+
+void QgsExpressionLineEdit::expressionEdited( const QString& expression )
+{
+ updateLineEditStyle( expression );
+ emit expressionChanged( expression );
+}
+
+void QgsExpressionLineEdit::changeEvent( QEvent* event )
+{
+ if ( event->type() == QEvent::EnabledChange )
+ {
+ updateLineEditStyle( expression() );
+ }
+}
+
+void QgsExpressionLineEdit::updateLineEditStyle( const QString& expression )
+{
+ if ( !mLineEdit )
+ return;
+
+ QPalette palette;
+ if ( !isEnabled() )
+ {
+ palette.setColor( QPalette::Text, Qt::gray );
+ }
+ else
+ {
+ bool isValid = true;
+ if ( !expression.isEmpty() )
+ {
+ isValid = isExpressionValid( expression );
+ }
+ if ( !isValid )
+ {
+ palette.setColor( QPalette::Text, Qt::red );
+ }
+ else
+ {
+ palette.setColor( QPalette::Text, Qt::black );
+ }
+ }
+ mLineEdit->setPalette( palette );
+}
+
+bool QgsExpressionLineEdit::isExpressionValid( const QString& expressionStr )
+{
+ QgsExpression expression( expressionStr );
+ expression.prepare( &mExpressionContext );
+ return !expression.hasParserError();
+}
diff --git a/src/gui/qgsexpressionlineedit.h b/src/gui/qgsexpressionlineedit.h
new file mode 100644
index 0000000..d251b2d
--- /dev/null
+++ b/src/gui/qgsexpressionlineedit.h
@@ -0,0 +1,143 @@
+/***************************************************************************
+ qgsexpressionlineedit.h
+ ----------------------
+ Date : 18.08.2016
+ Copyright : (C) 2016 Nyall Dawson
+ Email : nyall dot dawson at gmail dot com
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+#ifndef QGSEXPRESSIONLINEEDIT_H
+#define QGSEXPRESSIONLINEEDIT_H
+
+#include <QWidget>
+#include "qgsexpressioncontext.h"
+#include "qgsdistancearea.h"
+
+class QgsFilterLineEdit;
+class QToolButton;
+class QgsDistanceArea;
+class QgsExpressionContextGenerator;
+class QgsCodeEditorSQL;
+
+/** \ingroup gui
+ * @class QgsExpressionLineEdit
+ * @brief The QgsExpressionLineEdit widget includes a line edit for entering expressions
+ * together with a button to open the expression creation dialog.
+ *
+ * This widget is designed for use in contexts where no layer fields are available for
+ * use in an expression. In contexts where the expression is directly associated with
+ * a layer and fields can be used, then QgsFieldExpressionWidget is a more appropriate
+ * choice as it gives users direct access to select fields from a drop down list.
+ *
+ * QgsExpressionLineEdit also supports a multiline editor mode which is useful where
+ * more space is available for the widget, but where QgsExpressionBuilderWidget
+ * is too complex or large for use.
+ *
+ * @note added in QGIS 2.18
+ */
+class GUI_EXPORT QgsExpressionLineEdit : public QWidget
+{
+ Q_OBJECT
+
+ public:
+
+ /**
+ * Constructor for QgsExpressionLineEdit.
+ * @param parent parent widget
+ */
+ explicit QgsExpressionLineEdit( QWidget *parent = nullptr );
+
+ /** Sets the title used in the expression builder dialog
+ * @param title dialog title
+ * @see expressionDialogTitle()
+ */
+ void setExpressionDialogTitle( const QString& title );
+
+ /** Returns the title used for the expression dialog.
+ * @see setExpressionDialogTitle()
+ */
+ QString expressionDialogTitle() const { return mExpressionDialogTitle; }
+
+ /** Sets whether the widget should show a multiline text editor.
+ * @param multiLine set to true to show multiline editor, or false
+ * to show single line editor (the default).
+ */
+ void setMultiLine( bool multiLine );
+
+ /** Set the geometry calculator used in the expression dialog.
+ * @param distanceArea calculator
+ */
+ void setGeomCalculator( const QgsDistanceArea &distanceArea );
+
+ /** Sets a layer associated with the widget. Required in order to get the fields and values
+ * from the layer.
+ * @param layer vector layer
+ */
+ void setLayer( QgsVectorLayer* layer );
+
+ /** Returns the current expression shown in the widget.
+ * @see setExpression()
+ */
+ QString expression() const;
+
+ /**
+ * Returns true if the current expression is valid.
+ * @param expressionError will be set to any generated error message if specified
+ */
+ bool isValidExpression( QString *expressionError = nullptr ) const;
+
+ signals:
+
+ /** Emitted when the expression is changed.
+ * @param expression new expression
+ */
+ void expressionChanged( const QString& expression );
+
+ public slots:
+
+ /** Sets the current expression to show in the widget.
+ * @param expression expression string
+ * @see expression()
+ */
+ void setExpression( const QString& expression );
+
+ protected:
+ void changeEvent( QEvent* event ) override;
+
+ private slots:
+ //! When the expression is edited by the user in the line edit, it will be checked for validity
+ void expressionEdited( const QString& expression );
+ void expressionEdited();
+
+ //! Opens the expression editor dialog to edit the current expression or add a new expression
+ void editExpression();
+
+ /**
+ * @brief updateLineEditStyle will re-style (color/font) the line edit depending on content and status
+ * @param expression if expression is given it will be evaluated for the given string, otherwise it takes
+ * current expression from the model
+ */
+ void updateLineEditStyle( const QString& expression = QString() );
+
+ private:
+ QgsFilterLineEdit* mLineEdit;
+ QgsCodeEditorSQL* mCodeEditor;
+ QToolButton* mButton;
+ QString mExpressionDialogTitle;
+ QScopedPointer<QgsDistanceArea> mDa;
+ QgsExpressionContext mExpressionContext;
+ QgsVectorLayer* mLayer;
+
+ bool isExpressionValid( const QString& expressionStr );
+
+ friend class TestQgsFieldExpressionWidget;
+};
+
+#endif // QGSEXPRESSIONLINEEDIT_H
diff --git a/src/gui/qgsfieldexpressionwidget.cpp b/src/gui/qgsfieldexpressionwidget.cpp
index c0af008..7e577a4 100644
--- a/src/gui/qgsfieldexpressionwidget.cpp
+++ b/src/gui/qgsfieldexpressionwidget.cpp
@@ -108,6 +108,11 @@ QString QgsFieldExpressionWidget::asExpression() const
return isExpression() ? currentText() : QgsExpression::quotedColumnRef( currentText() );
}
+QString QgsFieldExpressionWidget::expression() const
+{
+ return asExpression();
+}
+
bool QgsFieldExpressionWidget::isValidExpression( QString *expressionError ) const
{
QString temp;
@@ -200,6 +205,11 @@ void QgsFieldExpressionWidget::setField( const QString &fieldName )
currentFieldChanged();
}
+void QgsFieldExpressionWidget::setExpression( const QString& expression )
+{
+ setField( expression );
+}
+
void QgsFieldExpressionWidget::editExpression()
{
QString currentExpression = currentText();
diff --git a/src/gui/qgsfieldexpressionwidget.h b/src/gui/qgsfieldexpressionwidget.h
index 3804eff..5c1144c 100644
--- a/src/gui/qgsfieldexpressionwidget.h
+++ b/src/gui/qgsfieldexpressionwidget.h
@@ -89,13 +89,25 @@ class GUI_EXPORT QgsFieldExpressionWidget : public QWidget
*/
QString currentText() const;
- /** Returns the currently selected field or expression. If a field is currently selected, the returned
+ /**
+ * Returns the currently selected field or expression. If a field is currently selected, the returned
* value will be converted to a valid expression referencing this field (ie enclosing the field name with
* appropriate quotations).
* @note added in QGIS 2.14
*/
QString asExpression() const;
+ /**
+ * Returns the currently selected field or expression. If a field is currently selected, the returned
+ * value will be converted to a valid expression referencing this field (ie enclosing the field name with
+ * appropriate quotations).
+ *
+ * Alias for asExpression()
+ *
+ * @note added in QGIS 2.18
+ */
+ QString expression() const;
+
//! Returns the currently used layer
QgsVectorLayer* layer() const;
@@ -133,6 +145,14 @@ class GUI_EXPORT QgsFieldExpressionWidget : public QWidget
//! sets the current field or expression in the widget
void setField( const QString &fieldName );
+ /**
+ * Sets the current expression text and if applicable also the field.
+ * Alias for setField.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setExpression( const QString& expression );
+
protected slots:
//! open the expression dialog to edit the current or add a new expression
void editExpression();
diff --git a/src/gui/qgsfilterlineedit.cpp b/src/gui/qgsfilterlineedit.cpp
index 57bff8d..c437338 100644
--- a/src/gui/qgsfilterlineedit.cpp
+++ b/src/gui/qgsfilterlineedit.cpp
@@ -21,31 +21,38 @@
#include <QToolButton>
#include <QStyle>
#include <QFocusEvent>
+#include <QPainter>
QgsFilterLineEdit::QgsFilterLineEdit( QWidget* parent, const QString& nullValue )
: QLineEdit( parent )
+ , mClearButtonVisible( true )
+ , mClearMode( ClearToNull )
, mNullValue( nullValue )
, mFocusInEvent( false )
+ , mClearHover( false )
{
- btnClear = new QToolButton( this );
- btnClear->setIcon( QgsApplication::getThemeIcon( "/mIconClear.svg" ) );
- btnClear->setCursor( Qt::ArrowCursor );
- btnClear->setFocusPolicy( Qt::NoFocus );
- btnClear->setStyleSheet( "QToolButton { border: none; padding: 0px; }" );
- btnClear->hide();
-
- connect( btnClear, SIGNAL( clicked() ), this, SLOT( clear() ) );
- connect( btnClear, SIGNAL( clicked() ), this, SIGNAL( cleared() ) );
+ // need mouse tracking to handle cursor changes
+ setMouseTracking( true );
+
+ QIcon clearIcon = QgsApplication::getThemeIcon( "/mIconClearText.svg" );
+ mClearIconSize = QSize( 16, 16 );
+ mClearIconPixmap = clearIcon.pixmap( mClearIconSize );
+ QIcon hoverIcon = QgsApplication::getThemeIcon( "/mIconClearTextHover.svg" );
+ mClearHoverPixmap = hoverIcon.pixmap( mClearIconSize );
+
connect( this, SIGNAL( textChanged( const QString& ) ), this,
SLOT( onTextChanged( const QString& ) ) );
+}
- int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
- mStyleSheet = QString( "QLineEdit { padding-right: %1px; } " )
- .arg( btnClear->sizeHint().width() + frameWidth + 1 );
+void QgsFilterLineEdit::setShowClearButton( bool visible )
+{
+ bool changed = mClearButtonVisible != visible;
+ mClearButtonVisible = visible;
+ if ( !visible )
+ mClearHover = false;
- QSize msz = minimumSizeHint();
- setMinimumSize( qMax( msz.width(), btnClear->sizeHint().height() + frameWidth * 2 + 2 ),
- qMax( msz.height(), btnClear->sizeHint().height() + frameWidth * 2 + 2 ) );
+ if ( changed )
+ update();
}
void QgsFilterLineEdit::mousePressEvent( QMouseEvent* e )
@@ -54,6 +61,31 @@ void QgsFilterLineEdit::mousePressEvent( QMouseEvent* e )
QLineEdit::mousePressEvent( e );
else
mFocusInEvent = false;
+
+ if ( shouldShowClear() && clearRect().contains( e->pos() ) )
+ {
+ clearValue();
+ }
+}
+
+void QgsFilterLineEdit::mouseMoveEvent( QMouseEvent* e )
+{
+ QLineEdit::mouseMoveEvent( e );
+ if ( shouldShowClear() && clearRect().contains( e->pos() ) )
+ {
+ if ( !mClearHover )
+ {
+ setCursor( Qt::ArrowCursor );
+ mClearHover = true;
+ update();
+ }
+ }
+ else if ( mClearHover )
+ {
+ setCursor( Qt::IBeamCursor );
+ mClearHover = false;
+ update();
+ }
}
void QgsFilterLineEdit::focusInEvent( QFocusEvent* e )
@@ -66,37 +98,57 @@ void QgsFilterLineEdit::focusInEvent( QFocusEvent* e )
}
}
-void QgsFilterLineEdit::resizeEvent( QResizeEvent * )
+void QgsFilterLineEdit::clearValue()
{
- QSize sz = btnClear->sizeHint();
- int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
- btnClear->move( rect().right() - frameWidth - sz.width(),
- ( rect().bottom() + 1 - sz.height() ) / 2 );
-}
+ switch ( mClearMode )
+ {
+ case ClearToNull:
+ setText( mNullValue );
+ selectAll();
+ break;
+
+ case ClearToDefault:
+ setText( mDefaultValue );
+ break;
+ }
-void QgsFilterLineEdit::clear()
-{
- setText( mNullValue );
- setModified( true );
-}
+ if ( mClearHover )
+ {
+ setCursor( Qt::IBeamCursor );
+ mClearHover = false;
+ }
-void QgsFilterLineEdit::changeEvent( QEvent *e )
-{
- QLineEdit::changeEvent( e );
- btnClear->setVisible( isEnabled() && !isReadOnly() && !isNull() );
+ setModified( true );
+ emit cleared();
}
void QgsFilterLineEdit::paintEvent( QPaintEvent* e )
{
QLineEdit::paintEvent( e );
- btnClear->setVisible( isEnabled() && !isReadOnly() && !isNull() );
+ if ( shouldShowClear() )
+ {
+ QRect r = clearRect();
+ QPainter p( this );
+ if ( mClearHover )
+ p.drawPixmap( r.left() , r.top() , mClearHoverPixmap );
+ else
+ p.drawPixmap( r.left() , r.top() , mClearIconPixmap );
+ }
}
+void QgsFilterLineEdit::leaveEvent( QEvent* e )
+{
+ if ( mClearHover )
+ {
+ mClearHover = false;
+ update();
+ }
+
+ QLineEdit::leaveEvent( e );
+}
void QgsFilterLineEdit::onTextChanged( const QString &text )
{
- btnClear->setVisible( isEnabled() && !isReadOnly() && !isNull() );
-
if ( isNull() )
{
setStyleSheet( QString( "QLineEdit { font: italic; color: gray; } %1" ).arg( mStyleSheet ) );
@@ -107,4 +159,35 @@ void QgsFilterLineEdit::onTextChanged( const QString &text )
setStyleSheet( mStyleSheet );
emit valueChanged( text );
}
+
+ if ( mClearHover && !shouldShowClear() )
+ {
+ setCursor( Qt::IBeamCursor );
+ mClearHover = false;
+ }
+}
+
+bool QgsFilterLineEdit::shouldShowClear() const
+{
+ if ( !isEnabled() || isReadOnly() || !mClearButtonVisible )
+ return false;
+
+ switch ( mClearMode )
+ {
+ case ClearToNull:
+ return !isNull();
+
+ case ClearToDefault:
+ return value() != mDefaultValue;
+ }
+ return false; //avoid warnings
+}
+
+QRect QgsFilterLineEdit::clearRect() const
+{
+ int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
+ return QRect( rect().right() - frameWidth * 2 - mClearIconSize.width(),
+ ( rect().bottom() + 1 - mClearIconSize.height() ) / 2,
+ mClearIconSize.width(),
+ mClearIconSize.height() );
}
diff --git a/src/gui/qgsfilterlineedit.h b/src/gui/qgsfilterlineedit.h
index af993d2..bdded3f 100644
--- a/src/gui/qgsfilterlineedit.h
+++ b/src/gui/qgsfilterlineedit.h
@@ -22,68 +22,208 @@
class QToolButton;
-/** \ingroup gui
- * Lineedit with builtin clear button
+/** \class QgsFilterLineEdit
+ * \ingroup gui
+ * QLineEdit subclass with built in support for clearing the widget's value and
+ * handling custom null value representations.
+ *
+ * When using QgsFilterLineEdit the value(), setValue() and clearValue() methods should be used
+ * instead of QLineEdit's text(), setText() and clear() methods, and the valueChanged()
+ * signal should be used instead of textChanged().
**/
class GUI_EXPORT QgsFilterLineEdit : public QLineEdit
{
Q_OBJECT
+ Q_ENUMS( ClearMode )
+ Q_PROPERTY( ClearMode clearMode READ clearMode WRITE setClearMode )
Q_PROPERTY( QString nullValue READ nullValue WRITE setNullValue )
+ Q_PROPERTY( QString defaultValue READ defaultValue WRITE setDefaultValue )
+ Q_PROPERTY( QString value READ value WRITE setValue NOTIFY valueChanged )
+ Q_PROPERTY( bool showClearButton READ showClearButton WRITE setShowClearButton )
public:
+
+ //! Behaviour when clearing value of widget
+ enum ClearMode
+ {
+ ClearToNull = 0, //!< Reset value to null
+ ClearToDefault, //!< Reset value to default value (see defaultValue() )
+ };
+
+ /** Constructor for QgsFilterLineEdit.
+ * @param parent parent widget
+ * @param nullValue string for representing null values
+ */
QgsFilterLineEdit( QWidget* parent = nullptr, const QString& nullValue = QString::null );
+ /** Returns true if the widget's clear button is visible.
+ * @see setShowClearButton()
+ * @note added in QGIS 2.18
+ */
+ bool showClearButton() const { return mClearButtonVisible; }
+
+ /** Sets whether the widget's clear button is visible.
+ * @param visible set to false to hide the clear button
+ * @see showClearButton()
+ * @note added in QGIS 2.18
+ */
+ void setShowClearButton( bool visible );
+
+ /** Returns the clear mode for the widget. The clear mode defines the behaviour of the
+ * widget when its value is cleared. This defaults to ClearToNull.
+ * @see setClearMode()
+ * @note added in QGIS 2.18
+ */
+ ClearMode clearMode() const { return mClearMode; }
+
+ /** Sets the clear mode for the widget. The clear mode defines the behaviour of the
+ * widget when its value is cleared. This defaults to ClearToNull.
+ * @see clearMode()
+ * @note added in QGIS 2.18
+ */
+ void setClearMode( ClearMode mode ) { mClearMode = mode; }
+
+ /** Sets the string representation for null values in the widget. This does not
+ * affect the values returned for null values by value(), rather it only affects
+ * the text that is shown to users when the widget's value is null.
+ * @param nullValue string to show when widget's value is null
+ * @see nullValue()
+ */
void setNullValue( const QString& nullValue ) { mNullValue = nullValue; }
+ /** Returns the string used for representating null values in the widget.
+ * @see setNullValue()
+ * @see isNull()
+ */
QString nullValue() const { return mNullValue; }
+ /** Sets the default value for the widget. The default value is a value
+ * which the widget will be reset to if it is cleared and the clearMode()
+ * is equal to ClearToDefault.
+ * @param defaultValue default value
+ * @see defaultValue()
+ * @see clearMode()
+ * @note added in QGIS 2.18
+ */
+ void setDefaultValue( const QString& defaultValue ) { mDefaultValue = defaultValue; }
+
+ /** Returns the default value for the widget. The default value is a value
+ * which the widget will be reset to if it is cleared and the clearMode()
+ * is equal to ClearToDefault.
+ * @see setDefaultValue()
+ * @see clearMode()
+ * @note added in QGIS 2.18
+ */
+ QString defaultValue() const { return mDefaultValue; }
+
/**
- * Sets the current text with NULL support
+ * Sets the current text for the widget with support for handling null values.
*
- * @param value The text to set. If a Null string is provided, the text will match the nullValue.
+ * @param value The text to set. If a null string is provided, the text shown in the
+ * widget will be set to the current nullValue().
+ * @see value()
*/
void setValue( const QString& value ) { setText( value.isNull() ? mNullValue : value ); }
/**
- * Returns the text of this edit with NULL support
+ * Returns the text of this edit with support for handling null values. If the text
+ * in the widget matches the current nullValue() then the returned value will be
+ * a null string.
*
- * @return Current text (Null string if it matches the nullValue property )
+ * @return Current text (or null string if it matches the nullValue() property )
+ * @see setValue()
*/
QString value() const { return isNull() ? QString::null : text(); }
/**
- * Determine if the current text represents Null.
+ * Determine if the current text represents null.
*
- * @return True if the value is Null.
+ * @return True if the widget's value is null.
+ * @see nullValue()
*/
inline bool isNull() const { return text() == mNullValue; }
+ public slots:
+
+ /** Clears the widget and resets it to the null value.
+ * @see nullValue()
+ * @note added in QGIS 2.18
+ */
+ virtual void clearValue();
+
signals:
+
+ /** Emitted when the widget is cleared
+ * @see clearValue()
+ */
void cleared();
/**
- * Same as textChanged(const QString& ) but with support for Null values.
+ * Same as textChanged() but with support for null values.
*
- * @param value The current text or Null string if it matches the nullValue property.
+ * @param value The current text or null string if it matches the nullValue() property.
*/
void valueChanged( const QString& value );
protected:
void mousePressEvent( QMouseEvent* e ) override;
+ void mouseMoveEvent( QMouseEvent* e ) override;
void focusInEvent( QFocusEvent* e ) override;
- void resizeEvent( QResizeEvent* e ) override;
- void changeEvent( QEvent* e ) override;
void paintEvent( QPaintEvent* e ) override;
+ void leaveEvent( QEvent* e ) override;
private slots:
- void clear();
void onTextChanged( const QString &text );
private:
+
+ bool mClearButtonVisible;
+
+ ClearMode mClearMode;
+
QString mNullValue;
- QToolButton *btnClear;
+ QString mDefaultValue;
QString mStyleSheet;
bool mFocusInEvent;
+ bool mClearHover;
+
+ QSize mClearIconSize;
+ QPixmap mClearIconPixmap;
+ QPixmap mClearHoverPixmap;
+
+ //! Returns true if clear button should be shown
+ bool shouldShowClear() const;
+
+ QRect clearRect() const;
+};
+
+/// @cond PRIVATE
+
+/** Private QgsFilterLineEdit subclass for use as a line edit in QgsSpinBox/QgsDoubleSpinBox
+ * we let QgsFilterLineEdit handle display of the clear button and detection
+ * of clicks, but override clearValue() and let Qgs(Double)SpinBox handle the clearing
+ * themselves.
+ */
+class QgsSpinBoxLineEdit : public QgsFilterLineEdit
+{
+ Q_OBJECT
+
+ public:
+
+ QgsSpinBoxLineEdit( QWidget* parent = nullptr )
+ : QgsFilterLineEdit( parent )
+ {}
+
+ public slots:
+
+ virtual void clearValue() override
+ {
+ // don't change the value - let spin boxes handle that by detecting cleared() signal
+ setCursor( Qt::IBeamCursor );
+ setModified( true );
+ emit cleared();
+ }
};
+/// @endcond
#endif // QGSFILTERLINEEDIT_H
diff --git a/src/gui/qgshighlight.cpp b/src/gui/qgshighlight.cpp
index 2b25cc9..93beefd 100644
--- a/src/gui/qgshighlight.cpp
+++ b/src/gui/qgshighlight.cpp
@@ -280,65 +280,62 @@ void QgsHighlight::paint( QPainter* p )
p->setPen( mPen );
p->setBrush( mBrush );
- switch ( mGeometry->wkbType() )
+ switch ( mGeometry->type() )
{
- case QGis::WKBPoint:
- case QGis::WKBPoint25D:
+ case QGis::Point:
{
- paintPoint( p, mGeometry->asPoint() );
- }
- break;
-
- case QGis::WKBMultiPoint:
- case QGis::WKBMultiPoint25D:
- {
- QgsMultiPoint m = mGeometry->asMultiPoint();
- for ( int i = 0; i < m.size(); i++ )
+ if ( !mGeometry->isMultipart() )
{
- paintPoint( p, m[i] );
+ paintPoint( p, mGeometry->asPoint() );
+ }
+ else
+ {
+ QgsMultiPoint m = mGeometry->asMultiPoint();
+ for ( int i = 0; i < m.size(); i++ )
+ {
+ paintPoint( p, m[i] );
+ }
}
}
break;
- case QGis::WKBLineString:
- case QGis::WKBLineString25D:
- {
- paintLine( p, mGeometry->asPolyline() );
- }
- break;
-
- case QGis::WKBMultiLineString:
- case QGis::WKBMultiLineString25D:
+ case QGis::Line:
{
- QgsMultiPolyline m = mGeometry->asMultiPolyline();
-
- for ( int i = 0; i < m.size(); i++ )
+ if ( !mGeometry->isMultipart() )
{
- paintLine( p, m[i] );
+ paintLine( p, mGeometry->asPolyline() );
}
- }
- break;
+ else
+ {
+ QgsMultiPolyline m = mGeometry->asMultiPolyline();
- case QGis::WKBPolygon:
- case QGis::WKBPolygon25D:
- {
- paintPolygon( p, mGeometry->asPolygon() );
+ for ( int i = 0; i < m.size(); i++ )
+ {
+ paintLine( p, m[i] );
+ }
+ }
+ break;
}
- break;
- case QGis::WKBMultiPolygon:
- case QGis::WKBMultiPolygon25D:
+ case QGis::Polygon:
{
- QgsMultiPolygon m = mGeometry->asMultiPolygon();
- for ( int i = 0; i < m.size(); i++ )
+ if ( !mGeometry->isMultipart() )
+ {
+ paintPolygon( p, mGeometry->asPolygon() );
+ }
+ else
{
- paintPolygon( p, m[i] );
+ QgsMultiPolygon m = mGeometry->asMultiPolygon();
+ for ( int i = 0; i < m.size(); i++ )
+ {
+ paintPolygon( p, m[i] );
+ }
}
+ break;
}
- break;
- case QGis::WKBUnknown:
- default:
+ case QGis::UnknownGeometry:
+ case QGis::NoGeometry:
return;
}
}
diff --git a/src/gui/qgshtmlannotationitem.cpp b/src/gui/qgshtmlannotationitem.cpp
index 7a8e02c..9600173 100644
--- a/src/gui/qgshtmlannotationitem.cpp
+++ b/src/gui/qgshtmlannotationitem.cpp
@@ -191,42 +191,44 @@ void QgsHtmlAnnotationItem::readXML( const QDomDocument& doc, const QDomElement&
void QgsHtmlAnnotationItem::setFeatureForMapPosition()
{
- if ( !mVectorLayer || !mMapCanvas )
+ QString newText;
+ if ( mVectorLayer && mMapCanvas )
{
- return;
- }
+ double halfIdentifyWidth = QgsMapTool::searchRadiusMU( mMapCanvas );
+ QgsRectangle searchRect( mMapPosition.x() - halfIdentifyWidth, mMapPosition.y() - halfIdentifyWidth,
+ mMapPosition.x() + halfIdentifyWidth, mMapPosition.y() + halfIdentifyWidth );
- QSettings settings;
- double halfIdentifyWidth = QgsMapTool::searchRadiusMU( mMapCanvas );
- QgsRectangle searchRect( mMapPosition.x() - halfIdentifyWidth, mMapPosition.y() - halfIdentifyWidth,
- mMapPosition.x() + halfIdentifyWidth, mMapPosition.y() + halfIdentifyWidth );
+ QgsFeatureIterator fit = mVectorLayer->getFeatures( QgsFeatureRequest().setFilterRect( searchRect ).setFlags( QgsFeatureRequest::NoGeometry | QgsFeatureRequest::ExactIntersect ) );
- QgsFeatureIterator fit = mVectorLayer->getFeatures( QgsFeatureRequest().setFilterRect( searchRect ).setFlags( QgsFeatureRequest::NoGeometry | QgsFeatureRequest::ExactIntersect ) );
+ QgsFeature currentFeature;
+ QgsFeatureId currentFeatureId = 0;
+ bool featureFound = false;
+
+ while ( fit.nextFeature( currentFeature ) )
+ {
+ currentFeatureId = currentFeature.id();
+ featureFound = true;
+ break;
+ }
- QgsFeature currentFeature;
- QgsFeatureId currentFeatureId = 0;
- bool featureFound = false;
+ mHasAssociatedFeature = featureFound;
+ mFeatureId = currentFeatureId;
+ mFeature = currentFeature;
- while ( fit.nextFeature( currentFeature ) )
+ QgsExpressionContext context;
+ context << QgsExpressionContextUtils::globalScope()
+ << QgsExpressionContextUtils::projectScope()
+ << QgsExpressionContextUtils::layerScope( mVectorLayer );
+ if ( mMapCanvas )
+ context.appendScope( QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() ) );
+ context.setFeature( mFeature );
+ newText = QgsExpression::replaceExpressionText( mHtmlSource, &context );
+ }
+ else
{
- currentFeatureId = currentFeature.id();
- featureFound = true;
- break;
+ newText = mHtmlSource;
}
-
- mHasAssociatedFeature = featureFound;
- mFeatureId = currentFeatureId;
- mFeature = currentFeature;
-
- QgsExpressionContext context;
- context << QgsExpressionContextUtils::globalScope()
- << QgsExpressionContextUtils::projectScope()
- << QgsExpressionContextUtils::layerScope( mVectorLayer );
- if ( mMapCanvas )
- context.appendScope( QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() ) );
- context.setFeature( mFeature );
- QString newtext = QgsExpression::replaceExpressionText( mHtmlSource, &context );
- mWebView->setHtml( newtext );
+ mWebView->setHtml( newText );
}
void QgsHtmlAnnotationItem::updateVisibility()
diff --git a/src/gui/qgsidentifymenu.cpp b/src/gui/qgsidentifymenu.cpp
index 04de0e0..f16ea0b 100644
--- a/src/gui/qgsidentifymenu.cpp
+++ b/src/gui/qgsidentifymenu.cpp
@@ -193,7 +193,7 @@ void QgsIdentifyMenu::addRasterLayer( QgsMapLayer* layer )
}
// add layer action to the top menu
- layerAction->setIcon( QgsApplication::getThemeIcon( "/mIconRasterLayer.png" ) );
+ layerAction->setIcon( QgsApplication::getThemeIcon( "/mIconRasterLayer.svg" ) );
layerAction->setData( QVariant::fromValue<ActionData>( ActionData( layer ) ) );
connect( layerAction, SIGNAL( hovered() ), this, SLOT( handleMenuHover() ) );
addAction( layerAction );
@@ -311,13 +311,13 @@ void QgsIdentifyMenu::addVectorLayer( QgsVectorLayer* layer, const QList<QgsMapT
switch ( layer->geometryType() )
{
case QGis::Point:
- layerAction->setIcon( QgsApplication::getThemeIcon( "/mIconPointLayer.png" ) );
+ layerAction->setIcon( QgsApplication::getThemeIcon( "/mIconPointLayer.svg" ) );
break;
case QGis::Line:
- layerAction->setIcon( QgsApplication::getThemeIcon( "/mIconLineLayer.png" ) );
+ layerAction->setIcon( QgsApplication::getThemeIcon( "/mIconLineLayer.svg" ) );
break;
case QGis::Polygon:
- layerAction->setIcon( QgsApplication::getThemeIcon( "/mIconPolygonLayer.png" ) );
+ layerAction->setIcon( QgsApplication::getThemeIcon( "/mIconPolygonLayer.svg" ) );
break;
default:
break;
diff --git a/src/gui/qgsmapcanvas.cpp b/src/gui/qgsmapcanvas.cpp
index fe4b285..4f13ca0 100644
--- a/src/gui/qgsmapcanvas.cpp
+++ b/src/gui/qgsmapcanvas.cpp
@@ -241,6 +241,7 @@ QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
mSettings.setFlag( QgsMapSettings::DrawEditingInfo );
mSettings.setFlag( QgsMapSettings::UseRenderingOptimization );
+ mSettings.setFlag( QgsMapSettings::RenderPartialOutput );
//segmentation parameters
QSettings settings;
@@ -705,9 +706,6 @@ void QgsMapCanvas::refreshMap()
stopRendering(); // if any...
- // from now on we can accept refresh requests again
- mRefreshScheduled = false;
-
//build the expression context
QgsExpressionContext expressionContext;
expressionContext << QgsExpressionContextUtils::globalScope()
@@ -740,6 +738,14 @@ void QgsMapCanvas::refreshMap()
mJob->start();
+ // from now on we can accept refresh requests again
+ // this must be reset only after the job has been started, because
+ // some providers (yes, it's you WCS and AMS!) during preparation
+ // do network requests and start an internal event loop, which may
+ // end up calling refresh() and would schedule another refresh,
+ // deleting the one we have just started.
+ mRefreshScheduled = false;
+
mMapUpdateTimer.start();
emit renderStarting();
diff --git a/src/gui/qgsmapoverviewcanvas.cpp b/src/gui/qgsmapoverviewcanvas.cpp
index 7a7d407..b6033c8 100644
--- a/src/gui/qgsmapoverviewcanvas.cpp
+++ b/src/gui/qgsmapoverviewcanvas.cpp
@@ -291,6 +291,11 @@ void QgsPanningWidget::setPolygon( const QPolygon& p )
{
if ( p == mPoly ) return;
mPoly = p;
+
+ //ensure polygon is closed
+ if ( mPoly.at( 0 ) != mPoly.at( mPoly.size() - 1 ) )
+ mPoly.append( mPoly.at( 0 ) );
+
setGeometry( p.boundingRect() );
update();
}
@@ -303,7 +308,13 @@ void QgsPanningWidget::paintEvent( QPaintEvent* pe )
p.begin( this );
p.setPen( Qt::red );
QPolygonF t = mPoly.translated( -mPoly.boundingRect().left(), -mPoly.boundingRect().top() );
- p.drawConvexPolygon( t );
+
+ // drawPolygon causes issues on windows - corners of path may be missing resulting in triangles being drawn
+ // instead of rectangles! (Same cause as #13343)
+ QPainterPath path;
+ path.addPolygon( t );
+ p.drawPath( path );
+
p.end();
}
diff --git a/src/gui/qgsmessagebar.cpp b/src/gui/qgsmessagebar.cpp
index c6ab2a7..23b8c52 100644
--- a/src/gui/qgsmessagebar.cpp
+++ b/src/gui/qgsmessagebar.cpp
@@ -80,7 +80,7 @@ QgsMessageBar::QgsMessageBar( QWidget *parent )
"QToolButton { background-color: rgba(0, 0, 0, 0); }"
"QToolButton::menu-button { background-color: rgba(0, 0, 0, 0); }" );
mCloseBtn->setCursor( Qt::PointingHandCursor );
- mCloseBtn->setIcon( QgsApplication::getThemeIcon( "/mIconClose.png" ) );
+ mCloseBtn->setIcon( QgsApplication::getThemeIcon( "/mIconClose.svg" ) );
mCloseBtn->setIconSize( QSize( 18, 18 ) );
mCloseBtn->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
mCloseBtn->setMenu( mCloseMenu );
diff --git a/src/gui/qgsmessagebaritem.cpp b/src/gui/qgsmessagebaritem.cpp
index 6ca7d15..5e4dda8 100644
--- a/src/gui/qgsmessagebaritem.cpp
+++ b/src/gui/qgsmessagebaritem.cpp
@@ -109,7 +109,7 @@ void QgsMessageBarItem::writeContent()
msgIcon = QString( "/mIconCritical.png" );
break;
case QgsMessageBar::WARNING:
- msgIcon = QString( "/mIconWarn.png" );
+ msgIcon = QString( "/mIconWarning.svg" );
break;
case QgsMessageBar::SUCCESS:
msgIcon = QString( "/mIconSuccess.png" );
diff --git a/src/gui/qgspanelwidget.cpp b/src/gui/qgspanelwidget.cpp
index fa009c3..1598ae0 100644
--- a/src/gui/qgspanelwidget.cpp
+++ b/src/gui/qgspanelwidget.cpp
@@ -47,8 +47,31 @@ void QgsPanelWidget::setDockMode( bool dockMode )
mDockMode = dockMode;
}
+QgsPanelWidget*QgsPanelWidget::findParentPanel( QWidget* widget )
+{
+ QWidget* p = widget;
+ while ( p )
+ {
+ if ( QgsPanelWidget* panel = qobject_cast< QgsPanelWidget* >( p ) )
+ return panel;
+
+ if ( p->window() == p )
+ {
+ // break on encountering a window - eg a dialog opened from a panel should not inline
+ // widgets inside the parent panel
+ return nullptr;
+ }
+
+ p = p->parentWidget();
+ }
+ return nullptr;
+}
+
void QgsPanelWidget::openPanel( QgsPanelWidget* panel )
{
+ //panel dock mode inherits from this panel
+ panel->setDockMode( dockMode() );
+
if ( mDockMode )
{
emit showPanel( panel );
@@ -68,7 +91,7 @@ void QgsPanelWidget::openPanel( QgsPanelWidget* panel )
dlg->layout()->addWidget( buttonBox );
dlg->exec();
settings.setValue( key, dlg->saveGeometry() );
- emit panelAccepted( panel );
+ panel->acceptPanel();
}
}
diff --git a/src/gui/qgspanelwidget.h b/src/gui/qgspanelwidget.h
index 6bd48c6..01c6fbe 100644
--- a/src/gui/qgspanelwidget.h
+++ b/src/gui/qgspanelwidget.h
@@ -79,7 +79,7 @@ class GUI_EXPORT QgsPanelWidget : public QWidget
/**
* The the auto delete property on the widget. True by default.
- * When auto delete is enabeld when a panel is removed from the stack
+ * When auto delete is enabled when a panel is removed from the stack
* it will be deleted.
* @param autoDelete Enable or disable auto delete on the panel.
*/
@@ -87,12 +87,20 @@ class GUI_EXPORT QgsPanelWidget : public QWidget
/**
* The the auto delete property on the widget. True by default.
- * When auto delete is enabeld when a panel is removed from the stack
+ * When auto delete is enabled when a panel is removed from the stack
* it will be deleted.
* @returns The auto delete value for the widget.
*/
bool autoDelete() { return mAutoDelete; }
+ /** Traces through the parents of a widget to find if it is contained within a QgsPanelWidget
+ * widget.
+ * @param widget widget which may be contained within a panel widget
+ * @returns parent panel widget if found, otherwise nullptr
+ * @note added in QGIS 2.18
+ */
+ static QgsPanelWidget* findParentPanel( QWidget* widget );
+
signals:
/**
@@ -100,6 +108,9 @@ class GUI_EXPORT QgsPanelWidget : public QWidget
* @param panel The panel widget that was accepted.
* @note This argument is normally raised with emit panelAccepted(this)
* so that callers can retrive the widget easier in calling code.
+ * @note this is emitted only when this panel is accepted, and is not emitted for
+ * child panels. Eg, if this panel opens a second stacked panel, then this panel
+ * will not emit panelAccepted when the second panel is accepted.
*/
void panelAccepted( QgsPanelWidget* panel );
diff --git a/src/gui/qgsprojectionselector.cpp b/src/gui/qgsprojectionselector.cpp
index abad6de..1597aa9 100644
--- a/src/gui/qgsprojectionselector.cpp
+++ b/src/gui/qgsprojectionselector.cpp
@@ -474,7 +474,7 @@ void QgsProjectionSelector::loadUserCrsList( QSet<QString> *crsFilter )
fontTemp.setItalic( true );
fontTemp.setBold( true );
mUserProjList->setFont( 0, fontTemp );
- mUserProjList->setIcon( 0, QIcon( QgsApplication::activeThemePath() + "user.png" ) );
+ mUserProjList->setIcon( 0, QgsApplication::getThemeIcon( "/user.png" ) );
//determine where the user proj database lives for this user. If none is found an empty
//now only will be shown
@@ -550,7 +550,7 @@ void QgsProjectionSelector::loadCrsList( QSet<QString> *crsFilter )
fontTemp.setItalic( true );
fontTemp.setBold( true );
mGeoList->setFont( 0, fontTemp );
- mGeoList->setIcon( 0, QIcon( QgsApplication::activeThemePath() + "geographic.png" ) );
+ mGeoList->setIcon( 0, QgsApplication::getThemeIcon( "/geographic.png" ) );
// Projected coordinate system node
mProjList = new QTreeWidgetItem( lstCoordinateSystems, QStringList( tr( "Projected Coordinate Systems" ) ) );
@@ -559,7 +559,7 @@ void QgsProjectionSelector::loadCrsList( QSet<QString> *crsFilter )
fontTemp.setItalic( true );
fontTemp.setBold( true );
mProjList->setFont( 0, fontTemp );
- mProjList->setIcon( 0, QIcon( QgsApplication::activeThemePath() + "transformed.png" ) );
+ mProjList->setIcon( 0, QgsApplication::getThemeIcon( "/transformed.svg" ) );
//bail out in case the projections db does not exist
//this is necessary in case the pc is running linux with a
diff --git a/src/gui/qgsrasterlayersaveasdialog.cpp b/src/gui/qgsrasterlayersaveasdialog.cpp
index 9cdbb0b..2149bdb 100644
--- a/src/gui/qgsrasterlayersaveasdialog.cpp
+++ b/src/gui/qgsrasterlayersaveasdialog.cpp
@@ -43,7 +43,7 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer* rasterLa
mAddNoDataManuallyToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionNewAttribute.svg" ) );
mLoadTransparentNoDataToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionCopySelected.png" ) );
mRemoveSelectedNoDataToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteAttribute.svg" ) );
- mRemoveAllNoDataToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionRemove.png" ) );
+ mRemoveAllNoDataToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionRemove.svg" ) );
mNoDataTableWidget->setColumnCount( 2 );
mNoDataTableWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "From" ) ) );
diff --git a/src/gui/qgsrelationeditorwidget.cpp b/src/gui/qgsrelationeditorwidget.cpp
index 1a67f95..8aa9fd1 100644
--- a/src/gui/qgsrelationeditorwidget.cpp
+++ b/src/gui/qgsrelationeditorwidget.cpp
@@ -33,6 +33,7 @@
QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget* parent )
: QgsCollapsibleGroupBox( parent )
, mViewMode( QgsDualView::AttributeEditor )
+ , mShowLabel( true )
, mVisible( false )
{
QVBoxLayout* topLayout = new QVBoxLayout( this );
@@ -92,7 +93,7 @@ QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget* parent )
mFormViewButton = new QToolButton( this );
mFormViewButton->setText( tr( "Form view" ) );
mFormViewButton->setToolTip( tr( "Switch to form view" ) );
- mFormViewButton->setIcon( QgsApplication::getThemeIcon( "/mActionPropertyItem.png" ) );
+ mFormViewButton->setIcon( QgsApplication::getThemeIcon( "/mActionPropertyItem.svg" ) );
mFormViewButton->setCheckable( true );
mFormViewButton->setChecked( mViewMode == QgsDualView::AttributeEditor );
buttonLayout->addWidget( mFormViewButton );
@@ -151,7 +152,8 @@ void QgsRelationEditorWidget::setRelationFeature( const QgsRelation& relation, c
connect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) );
connect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) );
- setTitle( relation.name() );
+ if ( mShowLabel )
+ setTitle( relation.name() );
QgsVectorLayer* lyr = relation.referencingLayer();
@@ -539,3 +541,38 @@ void QgsRelationEditorWidget::updateUi()
}
}
}
+
+bool QgsRelationEditorWidget::showLinkButton() const
+{
+ return mLinkFeatureButton->isVisible();
+}
+
+void QgsRelationEditorWidget::setShowLinkButton( bool showLinkButton )
+{
+ mLinkFeatureButton->setVisible( showLinkButton );
+}
+
+bool QgsRelationEditorWidget::showUnlinkButton() const
+{
+ return mUnlinkFeatureButton->isVisible();
+}
+
+void QgsRelationEditorWidget::setShowUnlinkButton( bool showUnlinkButton )
+{
+ mUnlinkFeatureButton->setVisible( showUnlinkButton );
+}
+
+bool QgsRelationEditorWidget::showLabel() const
+{
+ return mShowLabel;
+}
+
+void QgsRelationEditorWidget::setShowLabel( bool showLabel )
+{
+ mShowLabel = showLabel;
+
+ if ( mShowLabel && mRelation.isValid() )
+ setTitle( mRelation.name() );
+ else
+ setTitle( QString() );
+}
diff --git a/src/gui/qgsrelationeditorwidget.h b/src/gui/qgsrelationeditorwidget.h
index c84b56c..c6b6a12 100644
--- a/src/gui/qgsrelationeditorwidget.h
+++ b/src/gui/qgsrelationeditorwidget.h
@@ -38,6 +38,7 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox
{
Q_OBJECT
Q_PROPERTY( QgsDualView::ViewMode viewMode READ viewMode WRITE setViewMode )
+ Q_PROPERTY( bool showLabel READ showLabel WRITE setShowLabel )
public:
/**
@@ -74,6 +75,46 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox
*/
QgsIFeatureSelectionManager* featureSelectionManager();
+ /**
+ * Defines if a title label should be shown for this widget.
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLabel() const;
+
+ /**
+ * Defines if a title label should be shown for this widget.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLabel( bool showLabel );
+
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showLinkButton() const;
+ /**
+ * Determines if the "link feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowLinkButton( bool showLinkButton );
+
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ bool showUnlinkButton() const;
+ /**
+ * Determines if the "unlink feature" button should be shown
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setShowUnlinkButton( bool showUnlinkButton );
+
private slots:
void setViewMode( int mode ) {setViewMode( static_cast<QgsDualView::ViewMode>( mode ) );}
void updateButtons();
@@ -108,6 +149,7 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox
QGridLayout* mRelationLayout;
QButtonGroup* mViewModeButtonGroup;
+ bool mShowLabel;
bool mVisible;
};
diff --git a/src/gui/qgsscalecombobox.cpp b/src/gui/qgsscalecombobox.cpp
index 93fe61c..6694ccd 100644
--- a/src/gui/qgsscalecombobox.cpp
+++ b/src/gui/qgsscalecombobox.cpp
@@ -130,7 +130,7 @@ bool QgsScaleComboBox::setScaleString( const QString& scaleTxt )
bool ok;
double newScale = toDouble( scaleTxt, &ok );
double oldScale = mScale;
- if ( newScale < mMinScale )
+ if ( newScale < mMinScale && newScale != 0 )
{
newScale = mMinScale;
}
@@ -246,7 +246,7 @@ double QgsScaleComboBox::toDouble( const QString& scaleString, bool * returnOk )
void QgsScaleComboBox::setMinScale( double scale )
{
mMinScale = scale;
- if ( mScale < scale )
+ if ( mScale < scale && mScale != 0 )
{
setScale( scale );
}
diff --git a/src/gui/qgsscalecombobox.h b/src/gui/qgsscalecombobox.h
index 2e0046c..5171fe7 100644
--- a/src/gui/qgsscalecombobox.h
+++ b/src/gui/qgsscalecombobox.h
@@ -55,7 +55,13 @@ class GUI_EXPORT QgsScaleComboBox : public QComboBox
public slots:
void updateScales( const QStringList &scales = QStringList() );
- //! Function to set the min scale
+
+ /**
+ * Set the minimum allowed scale.
+ * Anything scale lower than the minimum scale will automatically
+ * be converted to the minimum scale.
+ * Except for 0 which is always allowed.
+ */
void setMinScale( double scale );
protected:
diff --git a/src/gui/qgsscalerangewidget.cpp b/src/gui/qgsscalerangewidget.cpp
index 5d57754..cf60fc6 100644
--- a/src/gui/qgsscalerangewidget.cpp
+++ b/src/gui/qgsscalerangewidget.cpp
@@ -90,6 +90,8 @@ void QgsScaleRangeWidget::setMapCanvas( QgsMapCanvas *mapCanvas )
void QgsScaleRangeWidget::setMinimumScale( double scale )
{
+ if ( qIsInf( scale ) )
+ scale = 0;
mMinimumScaleWidget->setScale( scale );
}
@@ -100,6 +102,8 @@ double QgsScaleRangeWidget::minimumScale()
void QgsScaleRangeWidget::setMaximumScale( double scale )
{
+ if ( qIsInf( scale ) )
+ scale = 0;
mMaximumScaleWidget->setScale( scale );
}
@@ -110,12 +114,20 @@ double QgsScaleRangeWidget::maximumScale()
double QgsScaleRangeWidget::minimumScaleDenom()
{
- return qRound( 1.0 / maximumScale() );
+ double scale = maximumScale();
+ if ( scale == 0 )
+ return 0;
+ else
+ return qRound( 1.0 / scale );
}
double QgsScaleRangeWidget::maximumScaleDenom()
{
- return qRound( 1.0 / minimumScale() );
+ double scale = minimumScale();
+ if ( scale == 0 )
+ return 0;
+ else
+ return qRound( 1.0 / scale );
}
void QgsScaleRangeWidget::setScaleRange( double min, double max )
diff --git a/src/gui/qgsscalerangewidget.h b/src/gui/qgsscalerangewidget.h
index d81b04b..5d75354 100644
--- a/src/gui/qgsscalerangewidget.h
+++ b/src/gui/qgsscalerangewidget.h
@@ -48,18 +48,30 @@ class GUI_EXPORT QgsScaleRangeWidget : public QWidget
//! return the maximum scale
double maximumScale();
- //! return the minimum scale denominator ( = 1 / maximum scale )
+ /**
+ * Returns the minimum scale denominator ( = 1 / maximum scale )
+ * In case of maximum scale = 0 it will also return 0
+ */
double minimumScaleDenom();
- //! return the maximum scale denominator ( = 1 / minimum scale )
+ /**
+ * Returns the maximum scale denominator ( = 1 / minimum scale )
+ * In case of minimum scale = 0 it will also return 0
+ */
double maximumScaleDenom();
//! call to reload the project scales and apply them to the 2 scales combo boxes
void reloadProjectScales();
public slots:
+ /**
+ * Set the minimum scale. Infinite will be handled equally to 0 internally.
+ */
void setMinimumScale( double scale );
+ /**
+ * Set the maximum scale. Infinite will be handled equally to 0 internally.
+ */
void setMaximumScale( double scale );
void setScaleRange( double min, double max );
diff --git a/src/gui/qgsscalewidget.cpp b/src/gui/qgsscalewidget.cpp
index 8f350dd..d5962f1 100644
--- a/src/gui/qgsscalewidget.cpp
+++ b/src/gui/qgsscalewidget.cpp
@@ -66,5 +66,7 @@ void QgsScaleWidget::setScaleFromCanvas()
setScale( 1 / mCanvas->scale() );
}
-
-
+void QgsScaleWidget::setScale( double scale )
+{
+ return mScaleComboBox->setScale( scale );
+}
diff --git a/src/gui/qgsscalewidget.h b/src/gui/qgsscalewidget.h
index f10c10d..534873a 100644
--- a/src/gui/qgsscalewidget.h
+++ b/src/gui/qgsscalewidget.h
@@ -55,7 +55,7 @@ class GUI_EXPORT QgsScaleWidget : public QWidget
//! Function to read the selected scale as double
double scale() const { return mScaleComboBox->scale();}
//! Function to set the selected scale from double
- void setScale( double scale ) { return mScaleComboBox->setScale( scale ); }
+ void setScale( double scale );
//! Function to read the min scale
double minScale() const { return mScaleComboBox->minScale(); }
diff --git a/src/gui/qgssourceselectdialog.cpp b/src/gui/qgssourceselectdialog.cpp
index 008082d..574ce04 100644
--- a/src/gui/qgssourceselectdialog.cpp
+++ b/src/gui/qgssourceselectdialog.cpp
@@ -413,27 +413,6 @@ void QgsSourceSelectDialog::on_cmbConnections_activated( int index )
QgsOWSConnection::setSelectedConnection( mServiceName, cmbConnections->currentText() );
}
-void QgsSourceSelectDialog::on_btnSave_clicked()
-{
- QgsManageConnectionsDialog dlg( this, QgsManageConnectionsDialog::Export, QgsManageConnectionsDialog::WFS );
- dlg.exec();
-}
-
-void QgsSourceSelectDialog::on_btnLoad_clicked()
-{
- QString fileName = QFileDialog::getOpenFileName( this, tr( "Load connections" ), ".",
- tr( "XML files (*.xml *XML)" ) );
- if ( fileName.isEmpty() )
- {
- return;
- }
-
- QgsManageConnectionsDialog dlg( this, QgsManageConnectionsDialog::Import, QgsManageConnectionsDialog::WFS, fileName );
- dlg.exec();
- populateConnectionList();
- emit connectionsChanged();
-}
-
void QgsSourceSelectDialog::treeWidgetItemDoubleClicked( const QModelIndex& index )
{
QgsDebugMsg( "double click called" );
diff --git a/src/gui/qgssourceselectdialog.h b/src/gui/qgssourceselectdialog.h
index e364843..6efea17 100644
--- a/src/gui/qgssourceselectdialog.h
+++ b/src/gui/qgssourceselectdialog.h
@@ -99,8 +99,6 @@ class GUI_EXPORT QgsSourceSelectDialog : public QDialog, protected Ui::QgsSource
void changeCRSFilter();
void connectToServer();
void filterChanged( QString text );
- void on_btnLoad_clicked();
- void on_btnSave_clicked();
void on_cmbConnections_activated( int index );
void on_buttonBox_helpRequested() const;
void treeWidgetItemDoubleClicked( const QModelIndex & index );
diff --git a/src/gui/qgstabwidget.cpp b/src/gui/qgstabwidget.cpp
new file mode 100644
index 0000000..9cf2a62
--- /dev/null
+++ b/src/gui/qgstabwidget.cpp
@@ -0,0 +1,159 @@
+/***************************************************************************
+ qgstabwidget.cpp - QgsTabWidget
+
+ ---------------------
+ begin : 8.9.2016
+ copyright : (C) 2016 by Matthias Kuhn
+ email : matthias at opengis.ch
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include "qgstabwidget.h"
+
+#include "qgslogger.h"
+
+QgsTabWidget::QgsTabWidget( QWidget* parent )
+ : QTabWidget( parent )
+ , mSetTabVisibleFlag( false )
+{
+}
+
+void QgsTabWidget::hideTab( QWidget* tab )
+{
+ QgsDebugMsg( "Hide" );
+ TabInformation& info = mTabs[ realTabIndex( tab )];
+ if ( info.visible )
+ {
+ mSetTabVisibleFlag = true;
+ removeTab( info.sourceIndex );
+ info.visible = false;
+ mSetTabVisibleFlag = false;
+ }
+}
+
+void QgsTabWidget::showTab( QWidget* tab )
+{
+ QgsDebugMsg( "Show" );
+ TabInformation& info = mTabs[ realTabIndex( tab )];
+ if ( ! info.visible )
+ {
+ mSetTabVisibleFlag = true;
+ insertTab( info.sourceIndex + 1, info.widget, info.label );
+ info.visible = true;
+ mSetTabVisibleFlag = false;
+ }
+}
+
+void QgsTabWidget::setTabVisible( QWidget* tab, bool visible )
+{
+ if ( visible )
+ showTab( tab );
+ else
+ hideTab( tab );
+}
+
+int QgsTabWidget::realTabIndex( QWidget* widget )
+{
+ int realIndex = 0;
+ Q_FOREACH ( const TabInformation& info, mTabs )
+ {
+ if ( info.widget == widget )
+ return realIndex;
+ ++realIndex;
+ }
+ return -1;
+}
+
+void QgsTabWidget::tabInserted( int index )
+{
+ if ( !mSetTabVisibleFlag )
+ {
+ QWidget* newWidget = widget( index );
+
+ if ( index == 0 )
+ {
+ mTabs.insert( 0, TabInformation( newWidget, tabText( index ) ) );
+ }
+ else
+ {
+ bool inserted = false;
+ QList<TabInformation>::iterator it;
+
+ for ( it = mTabs.begin(); it != mTabs.end(); ++it )
+ {
+ if ( it->sourceIndex == index )
+ {
+ mTabs.insert( it, TabInformation( newWidget, tabText( index ) ) );
+ inserted = true;
+ break;
+ }
+ }
+
+ if ( !inserted )
+ {
+ mTabs.append( TabInformation( newWidget, tabText( index ) ) );
+ }
+ }
+ }
+
+ synchronizeIndexes();
+}
+
+void QgsTabWidget::tabRemoved( int index )
+{
+ if ( !mSetTabVisibleFlag )
+ {
+ QList<TabInformation>::iterator it;
+
+ for ( it = mTabs.begin(); it != mTabs.end(); ++it )
+ {
+ if ( it->sourceIndex == index )
+ {
+ mTabs.removeOne( *it );
+ break;
+ }
+ }
+ }
+
+ synchronizeIndexes();
+}
+
+void QgsTabWidget::synchronizeIndexes()
+{
+ QgsDebugMsg( "---------" );
+ int i = -1;
+ QWidget* nextWidget = widget( 0 );
+
+ QList<TabInformation>::iterator it;
+
+ for ( it = mTabs.begin(); it != mTabs.end(); ++it )
+ {
+ if ( it->widget == nextWidget )
+ {
+ i++;
+ nextWidget = widget( i + 1 );
+ }
+ it->sourceIndex = i;
+ QgsDebugMsg( QString( "Tab %1 (%2): %3" ).arg( it->sourceIndex ).arg( it->label ).arg( i ) );
+ }
+}
+
+QgsTabWidget::TabInformation QgsTabWidget::tabInfo( QWidget* widget )
+{
+ Q_FOREACH ( const TabInformation& info, mTabs )
+ {
+ if ( info.widget == widget )
+ return info;
+ }
+ return TabInformation();
+}
+
+bool QgsTabWidget::TabInformation::operator ==( const QgsTabWidget::TabInformation& other )
+{
+ return other.widget == widget && other.sourceIndex == sourceIndex;
+}
diff --git a/src/gui/qgstabwidget.h b/src/gui/qgstabwidget.h
new file mode 100644
index 0000000..56ce91f
--- /dev/null
+++ b/src/gui/qgstabwidget.h
@@ -0,0 +1,119 @@
+/***************************************************************************
+ qgstabwidget.h - QgsTabWidget
+
+ ---------------------
+ begin : 8.9.2016
+ copyright : (C) 2016 by Matthias Kuhn
+ email : matthias at opengis.ch
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef QGSTABWIDGET_H
+#define QGSTABWIDGET_H
+
+#include <QTabWidget>
+
+/** \ingroup gui
+ * The QgsTabWidget class is the same as the QTabWidget but with additional methods to
+ * temporarily hide/show tabs.
+ *
+ * @note Added in QGIS 2.18
+ */
+class GUI_EXPORT QgsTabWidget : public QTabWidget
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Create a new QgsTabWidget with the optionally provided parent.
+ *
+ * @note Added in QGIS 2.18
+ */
+ QgsTabWidget( QWidget *parent = nullptr );
+
+ /**
+ * Hides the tab with the given widget
+ *
+ * @note Added in QGIS 2.18
+ */
+ void hideTab( QWidget* tab );
+
+ /**
+ * Shows the tab with the given widget
+ *
+ * @note Added in QGIS 2.18
+ */
+ void showTab( QWidget* tab );
+
+ /**
+ * Control the visibility for the tab with the given widget.
+ *
+ * @note Added in QGIS 2.18
+ */
+ void setTabVisible( QWidget* tab, bool visible );
+
+ /**
+ * Returns the index of the tab with the given widget.
+ * This index is not the same as the one provided to insertTab and removeTab
+ * since these methods are not aware of hidden tabs.
+ *
+ * @note Added in QGIS 2.18
+ */
+ int realTabIndex( QWidget* widget );
+
+ /**
+ * Is called internally whenever a new tab has been inserted.
+ *
+ * Is used to keep track of currently available and visible tabs.
+ *
+ * @note Added in QGIS 2.18
+ */
+ virtual void tabInserted( int index ) override;
+
+ /**
+ * Is called internally whenever a tab has been removed.
+ *
+ * Is used to keep track of currently available and visible tabs.
+ *
+ * @note Added in QGIS 2.18
+ */
+ virtual void tabRemoved( int index ) override;
+
+ private:
+ void synchronizeIndexes();
+
+ struct TabInformation
+ {
+ TabInformation( QWidget* wdg, const QString& lbl )
+ : sourceIndex( -1 )
+ , widget( wdg )
+ , label( lbl )
+ , visible( true )
+ {}
+
+ TabInformation()
+ : sourceIndex( -1 )
+ , widget( nullptr )
+ , visible( true )
+ {}
+
+ bool operator ==( const TabInformation& other );
+
+ int sourceIndex;
+ QWidget* widget;
+ QString label;
+ bool visible;
+ };
+
+ TabInformation tabInfo( QWidget* widget );
+
+ QList<TabInformation> mTabs;
+ bool mSetTabVisibleFlag;
+};
+
+#endif // QGSTABWIDGET_H
diff --git a/src/gui/raster/qgsrastertransparencywidget.cpp b/src/gui/raster/qgsrastertransparencywidget.cpp
index 787732f..c7a7900 100644
--- a/src/gui/raster/qgsrastertransparencywidget.cpp
+++ b/src/gui/raster/qgsrastertransparencywidget.cpp
@@ -64,10 +64,6 @@ QgsRasterTransparencyWidget::QgsRasterTransparencyWidget( QgsRasterLayer *layer,
QgsRasterTransparencyWidget::~QgsRasterTransparencyWidget()
{
- if ( mPixelSelectorTool )
- {
- delete mPixelSelectorTool;
- }
}
void QgsRasterTransparencyWidget::syncToLayer()
@@ -76,6 +72,13 @@ void QgsRasterTransparencyWidget::syncToLayer()
QgsRasterRenderer* renderer = mRasterLayer->renderer();
if ( provider )
{
+ if ( provider->dataType( 1 ) == QGis::ARGB32
+ || provider->dataType( 1 ) == QGis::ARGB32_Premultiplied )
+ {
+ gboxNoDataValue->setEnabled( false );
+ gboxCustomTransparency->setEnabled( false );
+ }
+
cboxTransparencyBand->addItem( tr( "None" ), -1 );
int nBands = provider->bandCount();
QString bandName;
diff --git a/src/gui/raster/qgsrendererrasterpropertieswidget.cpp b/src/gui/raster/qgsrendererrasterpropertieswidget.cpp
index dcac27a..15c03c4 100644
--- a/src/gui/raster/qgsrendererrasterpropertieswidget.cpp
+++ b/src/gui/raster/qgsrendererrasterpropertieswidget.cpp
@@ -91,6 +91,7 @@ QgsRendererRasterPropertiesWidget::QgsRendererRasterPropertiesWidget( QgsMapLaye
connect( mContrastSpinBox, SIGNAL( valueChanged( int ) ), this, SIGNAL( widgetChanged() ) );
connect( spinBoxSaturation, SIGNAL( valueChanged( int ) ), this, SIGNAL( widgetChanged() ) );
connect( spinColorizeStrength, SIGNAL( valueChanged( int ) ), this, SIGNAL( widgetChanged() ) );
+ connect( btnColorizeColor, SIGNAL( colorChanged( QColor ) ), this, SIGNAL( widgetChanged() ) );
connect( mBlendModeComboBox, SIGNAL( currentIndexChanged( int ) ), this, SIGNAL( widgetChanged() ) );
connect( mZoomedInResamplingComboBox, SIGNAL( currentIndexChanged( int ) ), this, SIGNAL( widgetChanged() ) );
diff --git a/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp b/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp
index 7466309..bc99e02 100644
--- a/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp
+++ b/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp
@@ -400,14 +400,23 @@ void QgsSingleBandPseudoColorRendererWidget::on_mClassifyButton_clicked()
{
for ( int i = 0; i < numberOfEntries; ++i )
{
- double value = colorRamp->value( i );
- entryValues.push_back( min + value * ( max - min ) );
+ if ( mInvertCheckBox->isChecked() )
+ {
+ double value = 1.0 - colorRamp->value( numberOfEntries - i - 1 );
+ entryValues.push_back( min + value * ( max - min ) );
+ }
+ else
+ {
+ double value = colorRamp->value( i );
+ entryValues.push_back( min + value * ( max - min ) );
+ }
}
}
// for continuous mode take original color map colors
for ( int i = 0; i < numberOfEntries; ++i )
{
- entryColors.push_back( colorRamp->color( colorRamp->value( i ) ) );
+ int idx = mInvertCheckBox->isChecked() ? numberOfEntries - i - 1 : i;
+ entryColors.push_back( colorRamp->color( colorRamp->value( idx ) ) );
}
}
}
diff --git a/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp b/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp
index 7997f14..f0bbe78 100644
--- a/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp
+++ b/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp
@@ -1007,11 +1007,11 @@ void QgsCategorizedSymbolRendererV2Widget::matchToSymbolsFromXml()
void QgsCategorizedSymbolRendererV2Widget::cleanUpSymbolSelector( QgsPanelWidget *container )
{
- if ( container )
- {
- QgsSymbolV2SelectorWidget* dlg = qobject_cast<QgsSymbolV2SelectorWidget*>( container );
- delete dlg->symbol();
- }
+ QgsSymbolV2SelectorWidget *dlg = qobject_cast<QgsSymbolV2SelectorWidget*>( container );
+ if ( !dlg )
+ return;
+
+ delete dlg->symbol();
}
void QgsCategorizedSymbolRendererV2Widget::updateSymbolsFromWidget()
diff --git a/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp b/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp
index f9c2898..3e45ad9 100644
--- a/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp
+++ b/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp
@@ -689,11 +689,11 @@ void QgsGraduatedSymbolRendererV2Widget::refreshRanges( bool reset )
void QgsGraduatedSymbolRendererV2Widget::cleanUpSymbolSelector( QgsPanelWidget *container )
{
- if ( container )
- {
- QgsSymbolV2SelectorWidget* dlg = qobject_cast<QgsSymbolV2SelectorWidget*>( container );
- delete dlg->symbol();
- }
+ QgsSymbolV2SelectorWidget *dlg = qobject_cast<QgsSymbolV2SelectorWidget*>( container );
+ if ( !dlg )
+ return;
+
+ delete dlg->symbol();
}
void QgsGraduatedSymbolRendererV2Widget::updateSymbolsFromWidget()
diff --git a/src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp b/src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp
index 9e5f1b9..5e7bf17 100644
--- a/src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp
+++ b/src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp
@@ -258,7 +258,6 @@ void QgsRuleBasedRendererV2Widget::refineRuleCategoriesGui( const QModelIndexLis
QgsCategorizedSymbolRendererV2Widget* w = new QgsCategorizedSymbolRendererV2Widget( mLayer, mStyle, nullptr );
w->setPanelTitle( tr( "Add categories to rules" ) );
connect( w, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( refineRuleCategoriesAccepted( QgsPanelWidget* ) ) );
- w->setDockMode( this->dockMode() );
w->setMapCanvas( mMapCanvas );
openPanel( w );
}
@@ -269,7 +268,6 @@ void QgsRuleBasedRendererV2Widget::refineRuleRangesGui( const QModelIndexList& )
w->setPanelTitle( tr( "Add ranges to rules" ) );
connect( w, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( refineRuleRangesAccepted( QgsPanelWidget* ) ) );
w->setMapCanvas( mMapCanvas );
- w->setDockMode( this->dockMode() );
openPanel( w );
}
@@ -483,7 +481,10 @@ void QgsRuleBasedRendererV2Widget::refineRuleRangesAccepted( QgsPanelWidget *pan
void QgsRuleBasedRendererV2Widget::ruleWidgetPanelAccepted( QgsPanelWidget *panel )
{
- QgsRendererRulePropsWidget* widget = qobject_cast<QgsRendererRulePropsWidget*>( panel );
+ QgsRendererRulePropsWidget *widget = qobject_cast<QgsRendererRulePropsWidget*>( panel );
+ if ( !widget )
+ return;
+
widget->apply();
// model should know about the change and emit dataChanged signal for the view
@@ -514,8 +515,6 @@ void QgsRuleBasedRendererV2Widget::countFeatures()
countMap[rule].duplicateCount = 0;
}
- QgsFeatureIterator fit = mLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ) );
-
QgsRenderContext renderContext;
renderContext.setRendererScale( 0 ); // ignore scale
@@ -537,6 +536,11 @@ void QgsRuleBasedRendererV2Widget::countFeatures()
renderContext.setExpressionContext( context );
mRenderer->startRender( renderContext, mLayer->fields() );
+ // QgsRuleBasedRenderer::filter must be called after startRender
+ QgsFeatureRequest req = QgsFeatureRequest().setFilterExpression( mRenderer->filter( mLayer->fields() ) );
+ req.setExpressionContext( context );
+ req.setSubsetOfAttributes( mRenderer->usedAttributes(), mLayer->fields() );
+ QgsFeatureIterator fit = mLayer->getFeatures( req );
int nFeatures = mLayer->featureCount();
QProgressDialog p( tr( "Calculating feature count." ), tr( "Abort" ), 0, nFeatures );
@@ -762,19 +766,18 @@ void QgsRendererRulePropsWidget::testFilter()
QApplication::setOverrideCursor( Qt::WaitCursor );
- QgsFeatureIterator fit = mLayer->getFeatures();
+ QgsFeatureRequest req = QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() )
+ .setFlags( QgsFeatureRequest::NoGeometry )
+ .setFilterExpression( editFilter->text() )
+ .setExpressionContext( context );
+
+ QgsFeatureIterator fit = mLayer->getFeatures( req );
int count = 0;
QgsFeature f;
while ( fit.nextFeature( f ) )
{
- context.setFeature( f );
-
- QVariant value = filter.evaluate( &context );
- if ( value.toInt() != 0 )
- count++;
- if ( filter.hasEvalError() )
- break;
+ count++;
}
QApplication::restoreOverrideCursor();
diff --git a/src/gui/symbology-ng/qgsstylev2managerdialog.cpp b/src/gui/symbology-ng/qgsstylev2managerdialog.cpp
index 86fd418..53295e6 100644
--- a/src/gui/symbology-ng/qgsstylev2managerdialog.cpp
+++ b/src/gui/symbology-ng/qgsstylev2managerdialog.cpp
@@ -1410,7 +1410,7 @@ void QgsStyleV2ManagerDialog::groupSelectedSymbols()
QgsStyleV2::StyleEntity type = ( currentItemType() < 3 ) ? QgsStyleV2::SymbolEntity : QgsStyleV2::ColorrampEntity;
if ( currentItemType() > 3 )
{
- QgsDebugMsg( "unknow entity type" );
+ QgsDebugMsg( "unknown entity type" );
return;
}
int groupId = selectedItem->data().toInt();
diff --git a/src/gui/symbology-ng/qgssvgselectorwidget.cpp b/src/gui/symbology-ng/qgssvgselectorwidget.cpp
index 0afe0bc..78f99e8 100644
--- a/src/gui/symbology-ng/qgssvgselectorwidget.cpp
+++ b/src/gui/symbology-ng/qgssvgselectorwidget.cpp
@@ -32,29 +32,238 @@
#include <QStyle>
#include <QTime>
+// QgsSvgSelectorLoader
-//--- QgsSvgSelectorListModel
+///@cond PRIVATE
+QgsSvgSelectorLoader::QgsSvgSelectorLoader( QObject* parent )
+ : QThread( parent )
+ , mCancelled( false )
+ , mTimerThreshold( 0 )
+{
+}
+
+QgsSvgSelectorLoader::~QgsSvgSelectorLoader()
+{
+ stop();
+}
+
+void QgsSvgSelectorLoader::run()
+{
+ mCancelled = false;
+ mQueuedSvgs.clear();
+ mTraversedPaths.clear();
+
+ // start with a small initial timeout (ms)
+ mTimerThreshold = 10;
+ mTimer.start();
+
+ loadPath( mPath );
+
+ if ( !mQueuedSvgs.isEmpty() )
+ {
+ // make sure we notify model of any remaining queued svgs (ie svgs added since last foundSvgs() signal was emitted)
+ emit foundSvgs( mQueuedSvgs );
+ }
+ mQueuedSvgs.clear();
+}
+
+void QgsSvgSelectorLoader::stop()
+{
+ mCancelled = true;
+ while ( isRunning() ) {}
+}
+
+void QgsSvgSelectorLoader::loadPath( const QString& path )
+{
+ if ( mCancelled )
+ return;
+
+ // QgsDebugMsg( QString( "loading path: %1" ).arg( path ) );
+
+ if ( path.isEmpty() )
+ {
+ QStringList svgPaths = QgsApplication::svgPaths();
+ Q_FOREACH ( const QString& svgPath, svgPaths )
+ {
+ if ( mCancelled )
+ return;
+
+ loadPath( svgPath );
+ }
+ }
+ else
+ {
+ QDir dir( path );
+
+ //guard against circular symbolic links
+ QString canonicalPath = dir.canonicalPath();
+ if ( mTraversedPaths.contains( canonicalPath ) )
+ return;
+
+ mTraversedPaths.insert( canonicalPath );
+
+ loadImages( path );
+
+ Q_FOREACH ( const QString& item, dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot ) )
+ {
+ if ( mCancelled )
+ return;
+
+ QString newPath = dir.path() + '/' + item;
+ loadPath( newPath );
+ // QgsDebugMsg( QString( "added path: %1" ).arg( newPath ) );
+ }
+ }
+}
+
+void QgsSvgSelectorLoader::loadImages( const QString& path )
+{
+ QDir dir( path );
+ Q_FOREACH ( const QString& item, dir.entryList( QStringList( "*.svg" ), QDir::Files ) )
+ {
+ if ( mCancelled )
+ return;
+
+ // TODO test if it is correct SVG
+ QString svgPath = dir.path() + '/' + item;
+ // QgsDebugMsg( QString( "adding svg: %1" ).arg( svgPath ) );
+
+ // add it to the list of queued SVGs
+ mQueuedSvgs << svgPath;
+
+ // we need to avoid spamming the model with notifications about new svgs, so foundSvgs
+ // is only emitted for blocks of SVGs (otherwise the view goes all flickery)
+ if ( mTimer.elapsed() > mTimerThreshold && !mQueuedSvgs.isEmpty() )
+ {
+ emit foundSvgs( mQueuedSvgs );
+ mQueuedSvgs.clear();
+
+ // increase the timer threshold - this ensures that the first lots of svgs loaded are added
+ // to the view quickly, but as the list grows new svgs are added at a slower rate.
+ // ie, good for initial responsiveness but avoid being spammy as the list grows.
+ if ( mTimerThreshold < 1000 )
+ mTimerThreshold *= 2;
+ mTimer.restart();
+ }
+ }
+}
+
+
+//
+// QgsSvgGroupLoader
+//
+
+QgsSvgGroupLoader::QgsSvgGroupLoader( QObject* parent )
+ : QThread( parent )
+ , mCancelled( false )
+{
+
+}
+
+QgsSvgGroupLoader::~QgsSvgGroupLoader()
+{
+ stop();
+}
+
+void QgsSvgGroupLoader::run()
+{
+ mCancelled = false;
+ mTraversedPaths.clear();
+
+ while ( !mCancelled && !mParentPaths.isEmpty() )
+ {
+ QString parentPath = mParentPaths.takeFirst();
+ loadGroup( parentPath );
+ }
+}
+
+void QgsSvgGroupLoader::stop()
+{
+ mCancelled = true;
+ while ( isRunning() ) {}
+}
+
+void QgsSvgGroupLoader::loadGroup( const QString& parentPath )
+{
+ QDir parentDir( parentPath );
+
+ //guard against circular symbolic links
+ QString canonicalPath = parentDir.canonicalPath();
+ if ( mTraversedPaths.contains( canonicalPath ) )
+ return;
+
+ mTraversedPaths.insert( canonicalPath );
+
+ Q_FOREACH ( const QString& item, parentDir.entryList( QDir::Dirs | QDir::NoDotAndDotDot ) )
+ {
+ if ( mCancelled )
+ return;
+
+ emit foundPath( parentPath, item );
+ mParentPaths.append( parentDir.path() + '/' + item );
+ }
+}
+
+///@endcond
+
+//,
+// QgsSvgSelectorListModel
+//
QgsSvgSelectorListModel::QgsSvgSelectorListModel( QObject* parent )
: QAbstractListModel( parent )
+ , mSvgLoader( new QgsSvgSelectorLoader( this ) )
{
- mSvgFiles = QgsSymbolLayerV2Utils::listSvgFiles();
+ mSvgLoader->setPath( QString() );
+ connect( mSvgLoader, SIGNAL( foundSvgs( QStringList ) ), this, SLOT( addSvgs( QStringList ) ) );
+ mSvgLoader->start();
}
-// Constructor to create model for icons in a specific path
QgsSvgSelectorListModel::QgsSvgSelectorListModel( QObject* parent, const QString& path )
: QAbstractListModel( parent )
+ , mSvgLoader( new QgsSvgSelectorLoader( this ) )
{
- mSvgFiles = QgsSymbolLayerV2Utils::listSvgFilesAt( path );
+ mSvgLoader->setPath( path );
+ connect( mSvgLoader, SIGNAL( foundSvgs( QStringList ) ), this, SLOT( addSvgs( QStringList ) ) );
+ mSvgLoader->start();
}
-int QgsSvgSelectorListModel::rowCount( const QModelIndex & parent ) const
+int QgsSvgSelectorListModel::rowCount( const QModelIndex& parent ) const
{
Q_UNUSED( parent );
return mSvgFiles.count();
}
-QVariant QgsSvgSelectorListModel::data( const QModelIndex & index, int role ) const
+QPixmap QgsSvgSelectorListModel::createPreview( const QString& entry ) const
+{
+ // render SVG file
+ QColor fill, outline;
+ double outlineWidth, fillOpacity, outlineOpacity;
+ bool fillParam, fillOpacityParam, outlineParam, outlineWidthParam, outlineOpacityParam;
+ bool hasDefaultFillColor = false, hasDefaultFillOpacity = false, hasDefaultOutlineColor = false,
+ hasDefaultOutlineWidth = false, hasDefaultOutlineOpacity = false;
+ QgsSvgCache::instance()->containsParams( entry, fillParam, hasDefaultFillColor, fill,
+ fillOpacityParam, hasDefaultFillOpacity, fillOpacity,
+ outlineParam, hasDefaultOutlineColor, outline,
+ outlineWidthParam, hasDefaultOutlineWidth, outlineWidth,
+ outlineOpacityParam, hasDefaultOutlineOpacity, outlineOpacity );
+
+ //if defaults not set in symbol, use these values
+ if ( !hasDefaultFillColor )
+ fill = QColor( 200, 200, 200 );
+ fill.setAlphaF( hasDefaultFillOpacity ? fillOpacity : 1.0 );
+ if ( !hasDefaultOutlineColor )
+ outline = Qt::black;
+ outline.setAlphaF( hasDefaultOutlineOpacity ? outlineOpacity : 1.0 );
+ if ( !hasDefaultOutlineWidth )
+ outlineWidth = 0.2;
+
+ bool fitsInCache; // should always fit in cache at these sizes (i.e. under 559 px ^ 2, or half cache size)
+ const QImage& img = QgsSvgCache::instance()->svgAsImage( entry, 30.0, fill, outline, outlineWidth, 3.5 /*appr. 88 dpi*/, 1.0, fitsInCache );
+ return QPixmap::fromImage( img );
+}
+
+QVariant QgsSvgSelectorListModel::data( const QModelIndex& index, int role ) const
{
QString entry = mSvgFiles.at( index.row() );
@@ -63,31 +272,7 @@ QVariant QgsSvgSelectorListModel::data( const QModelIndex & index, int role ) co
QPixmap pixmap;
if ( !QPixmapCache::find( entry, pixmap ) )
{
- // render SVG file
- QColor fill, outline;
- double outlineWidth, fillOpacity, outlineOpacity;
- bool fillParam, fillOpacityParam, outlineParam, outlineWidthParam, outlineOpacityParam;
- bool hasDefaultFillColor = false, hasDefaultFillOpacity = false, hasDefaultOutlineColor = false,
- hasDefaultOutlineWidth = false, hasDefaultOutlineOpacity = false;
- QgsSvgCache::instance()->containsParams( entry, fillParam, hasDefaultFillColor, fill,
- fillOpacityParam, hasDefaultFillOpacity, fillOpacity,
- outlineParam, hasDefaultOutlineColor, outline,
- outlineWidthParam, hasDefaultOutlineWidth, outlineWidth,
- outlineOpacityParam, hasDefaultOutlineOpacity, outlineOpacity );
-
- //if defaults not set in symbol, use these values
- if ( !hasDefaultFillColor )
- fill = QColor( 200, 200, 200 );
- fill.setAlphaF( hasDefaultFillOpacity ? fillOpacity : 1.0 );
- if ( !hasDefaultOutlineColor )
- outline = Qt::black;
- outline.setAlphaF( hasDefaultOutlineOpacity ? outlineOpacity : 1.0 );
- if ( !hasDefaultOutlineWidth )
- outlineWidth = 0.2;
-
- bool fitsInCache; // should always fit in cache at these sizes (i.e. under 559 px ^ 2, or half cache size)
- const QImage& img = QgsSvgCache::instance()->svgAsImage( entry, 30.0, fill, outline, outlineWidth, 3.5 /*appr. 88 dpi*/, 1.0, fitsInCache );
- pixmap = QPixmap::fromImage( img );
+ pixmap = createPreview( entry );
QPixmapCache::insert( entry, pixmap );
}
@@ -101,18 +286,30 @@ QVariant QgsSvgSelectorListModel::data( const QModelIndex & index, int role ) co
return QVariant();
}
+void QgsSvgSelectorListModel::addSvgs( const QStringList& svgs )
+{
+ beginInsertRows( QModelIndex(), mSvgFiles.count(), mSvgFiles.count() + svgs.size() - 1 );
+ mSvgFiles.append( svgs );
+ endInsertRows();
+}
+
+
+
+
//--- QgsSvgSelectorGroupsModel
QgsSvgSelectorGroupsModel::QgsSvgSelectorGroupsModel( QObject* parent )
: QStandardItemModel( parent )
+ , mLoader( new QgsSvgGroupLoader( this ) )
{
QStringList svgPaths = QgsApplication::svgPaths();
QStandardItem *parentItem = invisibleRootItem();
+ QStringList parentPaths;
for ( int i = 0; i < svgPaths.size(); i++ )
{
- QDir dir( svgPaths[i] );
+ QDir dir( svgPaths.at( i ) );
QStandardItem *baseGroup;
if ( dir.path().contains( QgsApplication::pkgDataPath() ) )
@@ -127,31 +324,41 @@ QgsSvgSelectorGroupsModel::QgsSvgSelectorGroupsModel( QObject* parent )
{
baseGroup = new QStandardItem( dir.dirName() );
}
- baseGroup->setData( QVariant( svgPaths[i] ) );
+ baseGroup->setData( QVariant( svgPaths.at( i ) ) );
baseGroup->setEditable( false );
baseGroup->setCheckable( false );
baseGroup->setIcon( QgsApplication::style()->standardIcon( QStyle::SP_DirIcon ) );
baseGroup->setToolTip( dir.path() );
parentItem->appendRow( baseGroup );
- createTree( baseGroup );
+ parentPaths << svgPaths.at( i );
+ mPathItemHash.insert( svgPaths.at( i ), baseGroup );
QgsDebugMsg( QString( "SVG base path %1: %2" ).arg( i ).arg( baseGroup->data().toString() ) );
}
+ mLoader->setParentPaths( parentPaths );
+ connect( mLoader, SIGNAL( foundPath( QString, QString ) ), this, SLOT( addPath( QString, QString ) ) );
+ mLoader->start();
}
-void QgsSvgSelectorGroupsModel::createTree( QStandardItem* &parentGroup )
+QgsSvgSelectorGroupsModel::~QgsSvgSelectorGroupsModel()
{
- QDir parentDir( parentGroup->data().toString() );
- Q_FOREACH ( const QString& item, parentDir.entryList( QDir::Dirs | QDir::NoDotAndDotDot ) )
- {
- QStandardItem* group = new QStandardItem( item );
- group->setData( QVariant( parentDir.path() + '/' + item ) );
- group->setEditable( false );
- group->setCheckable( false );
- group->setToolTip( parentDir.path() + '/' + item );
- group->setIcon( QgsApplication::style()->standardIcon( QStyle::SP_DirIcon ) );
- parentGroup->appendRow( group );
- createTree( group );
- }
+ mLoader->stop();
+}
+
+void QgsSvgSelectorGroupsModel::addPath( const QString& parentPath, const QString& item )
+{
+ QStandardItem* parentGroup = mPathItemHash.value( parentPath );
+ if ( !parentGroup )
+ return;
+
+ QString fullPath = parentPath + '/' + item;
+ QStandardItem* group = new QStandardItem( item );
+ group->setData( QVariant( fullPath ) );
+ group->setEditable( false );
+ group->setCheckable( false );
+ group->setToolTip( fullPath );
+ group->setIcon( QgsApplication::style()->standardIcon( QStyle::SP_DirIcon ) );
+ parentGroup->appendRow( group );
+ mPathItemHash.insert( fullPath, group );
}
@@ -250,11 +457,14 @@ void QgsSvgSelectorWidget::populateIcons( const QModelIndex& idx )
{
QString path = idx.data( Qt::UserRole + 1 ).toString();
+ QAbstractItemModel* oldModel = mImagesListView->model();
QgsSvgSelectorListModel* m = new QgsSvgSelectorListModel( mImagesListView, path );
mImagesListView->setModel( m );
+ delete oldModel; //explicitly delete old model to force any background threads to stop
connect( mImagesListView->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
this, SLOT( svgSelectionChanged( const QModelIndex& ) ) );
+
}
void QgsSvgSelectorWidget::on_mFilePushButton_clicked()
@@ -319,8 +529,10 @@ void QgsSvgSelectorWidget::populateList()
}
// Initally load the icons in the List view without any grouping
+ QAbstractItemModel* oldModel = mImagesListView->model();
QgsSvgSelectorListModel* m = new QgsSvgSelectorListModel( mImagesListView );
mImagesListView->setModel( m );
+ delete oldModel; //explicitly delete old model to force any background threads to stop
}
//-- QgsSvgSelectorDialog
diff --git a/src/gui/symbology-ng/qgssvgselectorwidget.h b/src/gui/symbology-ng/qgssvgselectorwidget.h
index 4bdd592..19c4e49 100644
--- a/src/gui/symbology-ng/qgssvgselectorwidget.h
+++ b/src/gui/symbology-ng/qgssvgselectorwidget.h
@@ -20,13 +20,14 @@
#include "ui_widget_svgselector.h"
#include "qgisgui.h"
-
#include <QAbstractListModel>
#include <QDialog>
#include <QDialogButtonBox>
#include <QLayout>
#include <QStandardItemModel>
#include <QWidget>
+#include <QThread>
+#include <QElapsedTimer>
class QCheckBox;
class QLayout;
@@ -35,29 +36,174 @@ class QListView;
class QPushButton;
class QTreeView;
+///@cond PRIVATE
+
+/** \ingroup gui
+ * \class QgsSvgSelectorLoader
+ * Recursively loads SVG images from a path in a background thread.
+ * \note added in QGIS 2.18
+ */
+class GUI_EXPORT QgsSvgSelectorLoader : public QThread
+{
+ Q_OBJECT
+
+ public:
+
+ /** Constructor for QgsSvgSelectorLoader
+ * @param parent parent object
+ */
+ QgsSvgSelectorLoader( QObject* parent = nullptr );
+
+ ~QgsSvgSelectorLoader();
+
+ /** Starts the loader finding and generating previews for SVG images. foundSvgs() will be
+ * emitted as the loader encounters SVG images.
+ * @brief run
+ */
+ virtual void run() override;
+
+ /** Cancels the current loading operation. Waits until the thread has finished operation
+ * before returning.
+ */
+ virtual void stop();
+
+ /** Sets the root path containing SVG images to load. If no path is set, the default SVG
+ * search paths will be used instead.
+ */
+ void setPath( const QString& path )
+ {
+ mPath = path;
+ }
+
+ signals:
+
+ /** Emitted when the loader has found a block of SVG images. This signal is emitted with blocks
+ * of SVG images to prevent spamming any connected model.
+ * @param svgs list of SVGs and preview images found.
+ */
+ void foundSvgs( QStringList svgs );
+
+ private:
+
+ QString mPath;
+ bool mCancelled;
+ QStringList mQueuedSvgs;
+
+ QElapsedTimer mTimer;
+ int mTimerThreshold;
+ QSet< QString > mTraversedPaths;
+
+ void loadPath( const QString& path );
+ void loadImages( const QString& path );
+
+};
+
+/** \ingroup gui
+ * \class QgsSvgGroupLoader
+ * Recursively loads SVG paths in a background thread.
+ * \note added in QGIS 2.18
+ */
+class GUI_EXPORT QgsSvgGroupLoader : public QThread
+{
+ Q_OBJECT
+
+ public:
+
+ /** Constructor for QgsSvgGroupLoader
+ * @param parent parent object
+ */
+ QgsSvgGroupLoader( QObject* parent = nullptr );
+
+ ~QgsSvgGroupLoader();
+
+ /** Starts the loader finding folders for SVG images.
+ * @brief run
+ */
+ virtual void run() override;
+
+ /** Cancels the current loading operation. Waits until the thread has finished operation
+ * before returning.
+ */
+ virtual void stop();
+
+ /** Sets the root path containing child paths to find. If no path is set, the default SVG
+ * search paths will be used instead.
+ */
+ void setParentPaths( const QStringList& parentPaths )
+ {
+ mParentPaths = parentPaths;
+ }
+
+ signals:
+
+ /** Emitted when the loader has found a block of SVG images. This signal is emitted with blocks
+ * of SVG images to prevent spamming any connected model.
+ * @param svgs list of SVGs and preview images found.
+ */
+ void foundPath( const QString& parentPath, const QString& path );
+
+ private:
+
+ QStringList mParentPaths;
+ bool mCancelled;
+ QSet< QString > mTraversedPaths;
+
+ void loadGroup( const QString& parentPath );
+
+};
+
+///@endcond
+///
+
/** \ingroup gui
* \class QgsSvgSelectorListModel
+ * A model for displaying SVG files with a preview icon. Population of the model is performed in
+ * a background thread to ensure that initial creation of the model is responsive and does
+ * not block the GUI.
*/
class GUI_EXPORT QgsSvgSelectorListModel : public QAbstractListModel
{
Q_OBJECT
public:
+
+ /** Constructor for QgsSvgSelectorListModel. All SVGs in folders from the application SVG
+ * search paths will be shown.
+ * @param parent parent object
+ */
QgsSvgSelectorListModel( QObject* parent );
- // Constructor to create model for icons in a specific path
+ /** Constructor for creating a model for SVG files in a specific path.
+ * @param parent parent object
+ * @param path initial path, which is recursively searched
+ */
QgsSvgSelectorListModel( QObject* parent, const QString& path );
int rowCount( const QModelIndex & parent = QModelIndex() ) const override;
-
QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const override;
protected:
QStringList mSvgFiles;
+
+ private:
+ QPixmap createPreview( const QString& entry ) const;
+ QgsSvgSelectorLoader* mSvgLoader;
+
+ private slots:
+
+ /** Called to add SVG files to the model.
+ * @param svgs list of SVG files to add to model.
+ */
+ void addSvgs( const QStringList& svgs );
+
};
+
/** \ingroup gui
* \class QgsSvgSelectorGroupsModel
+ * A model for displaying SVG search paths. Population of the model is performed in
+ * a background thread to ensure that initial creation of the model is responsive and does
+ * not block the GUI.
*/
class GUI_EXPORT QgsSvgSelectorGroupsModel : public QStandardItemModel
{
@@ -65,9 +211,15 @@ class GUI_EXPORT QgsSvgSelectorGroupsModel : public QStandardItemModel
public:
QgsSvgSelectorGroupsModel( QObject* parent );
+ ~QgsSvgSelectorGroupsModel();
private:
- void createTree( QStandardItem* &parentGroup );
+ QgsSvgGroupLoader* mLoader;
+ QHash< QString, QStandardItem* > mPathItemHash;
+
+ private slots:
+
+ void addPath( const QString& parentPath, const QString& path );
};
/** \ingroup gui
@@ -114,6 +266,7 @@ class GUI_EXPORT QgsSvgSelectorWidget : public QWidget, private Ui::WidgetSvgSel
private:
QString mCurrentSvgPath; // always stored as absolute path
+
};
/** \ingroup gui
diff --git a/src/gui/symbology-ng/qgssymbollayerv2widget.cpp b/src/gui/symbology-ng/qgssymbollayerv2widget.cpp
index 0bc557f..9966053 100644
--- a/src/gui/symbology-ng/qgssymbollayerv2widget.cpp
+++ b/src/gui/symbology-ng/qgssymbollayerv2widget.cpp
@@ -34,6 +34,7 @@
#include "qgsstylev2.h" //for symbol selector dialog
#include "qgsmapcanvas.h"
#include "qgsapplication.h"
+#include "qgssvgselectorwidget.h"
#include "qgslogger.h"
#include "qgssizescalewidget.h"
@@ -1821,8 +1822,11 @@ QgsSvgMarkerSymbolLayerV2Widget::~QgsSvgMarkerSymbolLayerV2Widget()
void QgsSvgMarkerSymbolLayerV2Widget::populateList()
{
- QgsSvgGroupsModel* g = new QgsSvgGroupsModel( viewGroups );
+ QAbstractItemModel* oldModel = viewGroups->model();
+ QgsSvgSelectorGroupsModel* g = new QgsSvgSelectorGroupsModel( viewGroups );
viewGroups->setModel( g );
+ delete oldModel;
+
// Set the tree expanded at the first level
int rows = g->rowCount( g->indexFromItem( g->invisibleRootItem() ) );
for ( int i = 0; i < rows; i++ )
@@ -1831,19 +1835,22 @@ void QgsSvgMarkerSymbolLayerV2Widget::populateList()
}
// Initally load the icons in the List view without any grouping
- QgsSvgListModel* m = new QgsSvgListModel( viewImages );
+ oldModel = viewImages->model();
+ QgsSvgSelectorListModel* m = new QgsSvgSelectorListModel( viewImages );
viewImages->setModel( m );
+ delete oldModel;
}
void QgsSvgMarkerSymbolLayerV2Widget::populateIcons( const QModelIndex& idx )
{
QString path = idx.data( Qt::UserRole + 1 ).toString();
- QgsSvgListModel* m = new QgsSvgListModel( viewImages, path );
+ QAbstractItemModel* oldModel = viewImages->model();
+ QgsSvgSelectorListModel* m = new QgsSvgSelectorListModel( viewImages, path );
viewImages->setModel( m );
+ delete oldModel;
connect( viewImages->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( setName( const QModelIndex& ) ) );
- emit changed();
}
void QgsSvgMarkerSymbolLayerV2Widget::setGuiForSvg( const QgsSvgMarkerSymbolLayerV2* layer )
@@ -2304,8 +2311,11 @@ void QgsSVGFillSymbolLayerWidget::setFile( const QModelIndex& item )
void QgsSVGFillSymbolLayerWidget::insertIcons()
{
- QgsSvgGroupsModel* g = new QgsSvgGroupsModel( mSvgTreeView );
+ QAbstractItemModel* oldModel = mSvgTreeView->model();
+ QgsSvgSelectorGroupsModel* g = new QgsSvgSelectorGroupsModel( mSvgTreeView );
mSvgTreeView->setModel( g );
+ delete oldModel;
+
// Set the tree expanded at the first level
int rows = g->rowCount( g->indexFromItem( g->invisibleRootItem() ) );
for ( int i = 0; i < rows; i++ )
@@ -2313,19 +2323,22 @@ void QgsSVGFillSymbolLayerWidget::insertIcons()
mSvgTreeView->setExpanded( g->indexFromItem( g->item( i ) ), true );
}
- QgsSvgListModel* m = new QgsSvgListModel( mSvgListView );
+ oldModel = mSvgListView->model();
+ QgsSvgSelectorListModel* m = new QgsSvgSelectorListModel( mSvgListView );
mSvgListView->setModel( m );
+ delete oldModel;
}
void QgsSVGFillSymbolLayerWidget::populateIcons( const QModelIndex& idx )
{
QString path = idx.data( Qt::UserRole + 1 ).toString();
- QgsSvgListModel* m = new QgsSvgListModel( mSvgListView, path );
+ QAbstractItemModel* oldModel = mSvgListView->model();
+ QgsSvgSelectorListModel* m = new QgsSvgSelectorListModel( mSvgListView, path );
mSvgListView->setModel( m );
+ delete oldModel;
connect( mSvgListView->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( setFile( const QModelIndex& ) ) );
- emit changed();
}
@@ -3222,129 +3235,6 @@ void QgsRasterFillSymbolLayerWidget::updatePreviewImage()
}
-/// @cond PRIVATE
-
-QgsSvgListModel::QgsSvgListModel( QObject* parent ) : QAbstractListModel( parent )
-{
- mSvgFiles = QgsSymbolLayerV2Utils::listSvgFiles();
-}
-
-QgsSvgListModel::QgsSvgListModel( QObject* parent, const QString& path ) : QAbstractListModel( parent )
-{
- mSvgFiles = QgsSymbolLayerV2Utils::listSvgFilesAt( path );
-}
-
-int QgsSvgListModel::rowCount( const QModelIndex& parent ) const
-{
- Q_UNUSED( parent );
- return mSvgFiles.count();
-}
-
-QVariant QgsSvgListModel::data( const QModelIndex& index, int role ) const
-{
- QString entry = mSvgFiles.at( index.row() );
-
- if ( role == Qt::DecorationRole ) // icon
- {
- QPixmap pixmap;
- if ( !QPixmapCache::find( entry, pixmap ) )
- {
- // render SVG file
- QColor fill, outline;
- double outlineWidth, fillOpacity, outlineOpacity;
- bool fillParam, fillOpacityParam, outlineParam, outlineWidthParam, outlineOpacityParam;
- bool hasDefaultFillColor = false, hasDefaultFillOpacity = false, hasDefaultOutlineColor = false,
- hasDefaultOutlineWidth = false, hasDefaultOutlineOpacity = false;
- QgsSvgCache::instance()->containsParams( entry, fillParam, hasDefaultFillColor, fill,
- fillOpacityParam, hasDefaultFillOpacity, fillOpacity,
- outlineParam, hasDefaultOutlineColor, outline,
- outlineWidthParam, hasDefaultOutlineWidth, outlineWidth,
- outlineOpacityParam, hasDefaultOutlineOpacity, outlineOpacity );
-
- //if defaults not set in symbol, use these values
- if ( !hasDefaultFillColor )
- fill = QColor( 200, 200, 200 );
- fill.setAlphaF( hasDefaultFillOpacity ? fillOpacity : 1.0 );
- if ( !hasDefaultOutlineColor )
- outline = Qt::black;
- outline.setAlphaF( hasDefaultOutlineOpacity ? outlineOpacity : 1.0 );
- if ( !hasDefaultOutlineWidth )
- outlineWidth = 0.6;
-
- bool fitsInCache; // should always fit in cache at these sizes (i.e. under 559 px ^ 2, or half cache size)
- const QImage& img = QgsSvgCache::instance()->svgAsImage( entry, 30.0, fill, outline, outlineWidth, 3.5 /*appr. 88 dpi*/, 1.0, fitsInCache );
- pixmap = QPixmap::fromImage( img );
- QPixmapCache::insert( entry, pixmap );
- }
-
- return pixmap;
- }
- else if ( role == Qt::UserRole || role == Qt::ToolTipRole )
- {
- return entry;
- }
-
- return QVariant();
-}
-
-
-QgsSvgGroupsModel::QgsSvgGroupsModel( QObject* parent ) : QStandardItemModel( parent )
-{
- QStringList svgPaths = QgsApplication::svgPaths();
- QStandardItem *parentItem = invisibleRootItem();
-
- for ( int i = 0; i < svgPaths.size(); i++ )
- {
- QDir dir( svgPaths[i] );
- QStandardItem *baseGroup;
-
- if ( dir.path().contains( QgsApplication::pkgDataPath() ) )
- {
- baseGroup = new QStandardItem( QString( "App Symbols" ) );
- }
- else if ( dir.path().contains( QgsApplication::qgisSettingsDirPath() ) )
- {
- baseGroup = new QStandardItem( QString( "User Symbols" ) );
- }
- else
- {
- baseGroup = new QStandardItem( dir.dirName() );
- }
- baseGroup->setData( QVariant( svgPaths[i] ) );
- baseGroup->setEditable( false );
- baseGroup->setCheckable( false );
- baseGroup->setIcon( QgsApplication::style()->standardIcon( QStyle::SP_DirIcon ) );
- baseGroup->setToolTip( dir.path() );
- parentItem->appendRow( baseGroup );
- createTree( baseGroup );
- QgsDebugMsg( QString( "SVG base path %1: %2" ).arg( i ).arg( baseGroup->data().toString() ) );
- }
-}
-
-void QgsSvgGroupsModel::createTree( QStandardItem*& parentGroup )
-{
- QDir parentDir( parentGroup->data().toString() );
- Q_FOREACH ( const QString& item, parentDir.entryList( QDir::Dirs | QDir::NoDotAndDotDot ) )
- {
- QStandardItem* group = new QStandardItem( item );
- group->setData( QVariant( parentDir.path() + '/' + item ) );
- group->setEditable( false );
- group->setCheckable( false );
- group->setToolTip( parentDir.path() + '/' + item );
- group->setIcon( QgsApplication::style()->standardIcon( QStyle::SP_DirIcon ) );
- parentGroup->appendRow( group );
- createTree( group );
- }
-}
-
-
-/// @endcond
-
-
-
-
-
-
QgsGeometryGeneratorSymbolLayerWidget::QgsGeometryGeneratorSymbolLayerWidget( const QgsVectorLayer* vl, QWidget* parent )
: QgsSymbolLayerV2Widget( parent, vl )
, mLayer( nullptr )
diff --git a/src/gui/symbology-ng/qgssymbollayerv2widget.h b/src/gui/symbology-ng/qgssymbollayerv2widget.h
index fed9859..1d01c97 100644
--- a/src/gui/symbology-ng/qgssymbollayerv2widget.h
+++ b/src/gui/symbology-ng/qgssymbollayerv2widget.h
@@ -734,39 +734,6 @@ class GUI_EXPORT QgsCentroidFillSymbolLayerV2Widget : public QgsSymbolLayerV2Wid
};
-///@cond PRIVATE
-
-class QgsSvgListModel : public QAbstractListModel
-{
- Q_OBJECT
-
- public:
- explicit QgsSvgListModel( QObject* parent );
-
- // Constructor to create model for icons in a specific path
- QgsSvgListModel( QObject* parent, const QString& path );
-
- int rowCount( const QModelIndex & parent = QModelIndex() ) const override;
-
- QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const override;
-
- protected:
- QStringList mSvgFiles;
-};
-
-class QgsSvgGroupsModel : public QStandardItemModel
-{
- Q_OBJECT
-
- public:
- explicit QgsSvgGroupsModel( QObject* parent );
-
- private:
- void createTree( QStandardItem* &parentGroup );
-};
-
-///@endcond
-
#include "ui_qgsgeometrygeneratorwidgetbase.h"
class QgsGeometryGeneratorSymbolLayerV2;
diff --git a/src/gui/symbology-ng/qgsvectorgradientcolorrampv2dialog.cpp b/src/gui/symbology-ng/qgsvectorgradientcolorrampv2dialog.cpp
index e5423c1..2e1c195 100644
--- a/src/gui/symbology-ng/qgsvectorgradientcolorrampv2dialog.cpp
+++ b/src/gui/symbology-ng/qgsvectorgradientcolorrampv2dialog.cpp
@@ -414,15 +414,15 @@ void QgsVectorGradientColorRampV2Dialog::plotMouseMove( QPointF point )
QColor newColor = mStopEditor->selectedStop().color;
if ( mCurrentPlotColorComponent == 0 )
- newColor = QColor::fromHslF( qBound( 0.0, point.y(), 1.0 ), newColor.hslSaturationF(), newColor.lightnessF(), newColor.alphaF() );
+ newColor = QColor::fromHslF( qBound( qreal( 0.0 ), point.y(), qreal( 1.0 ) ), newColor.hslSaturationF(), newColor.lightnessF(), newColor.alphaF() );
else if ( mCurrentPlotColorComponent == 1 )
- newColor = QColor::fromHslF( newColor.hslHueF(), newColor.hslSaturationF(), qBound( 0.0, point.y(), 1.0 ), newColor.alphaF() );
+ newColor = QColor::fromHslF( newColor.hslHueF(), newColor.hslSaturationF(), qBound( qreal( 0.0 ), point.y(), qreal( 1.0 ) ), newColor.alphaF() );
else if ( mCurrentPlotColorComponent == 2 )
- newColor = QColor::fromHslF( newColor.hslHueF(), qBound( 0.0, point.y(), 1.0 ), newColor.lightnessF(), newColor.alphaF() );
+ newColor = QColor::fromHslF( newColor.hslHueF(), qBound( qreal( 0.0 ), point.y(), qreal( 1.0 ) ), newColor.lightnessF(), newColor.alphaF() );
else if ( mCurrentPlotColorComponent == 3 )
- newColor = QColor::fromHslF( newColor.hslHueF(), newColor.hslSaturationF(), newColor.lightnessF(), qBound( 0.0, point.y(), 1.0 ) );
+ newColor = QColor::fromHslF( newColor.hslHueF(), newColor.hslSaturationF(), newColor.lightnessF(), qBound( qreal( 0.0 ), point.y(), qreal( 1.0 ) ) );
- mStopEditor->setSelectedStopDetails( newColor, qBound( 0.0, point.x(), 1.0 ) );
+ mStopEditor->setSelectedStopDetails( newColor, qBound( qreal( 0.0 ), point.x(), qreal( 1.0 ) ) );
}
bool byX( QPointF p1, QPointF p2 )
diff --git a/src/plugins/coordinate_capture/coordinatecapture.cpp b/src/plugins/coordinate_capture/coordinatecapture.cpp
index 1713f53..0c856b5 100644
--- a/src/plugins/coordinate_capture/coordinatecapture.cpp
+++ b/src/plugins/coordinate_capture/coordinatecapture.cpp
@@ -287,10 +287,10 @@ void CoordinateCapture::setCurrentTheme( const QString& theThemeName )
mQActionPointer->setIcon( QIcon( getIconPath( "coordinate_capture.png" ) ) );
if ( mpDockWidget )
{
- mpTrackMouseButton->setIcon( QIcon( getIconPath( "tracking.png" ) ) );
+ mpTrackMouseButton->setIcon( QIcon( getIconPath( "tracking.svg" ) ) );
mpCaptureButton->setIcon( QIcon( getIconPath( "coordinate_capture.png" ) ) );
mypUserCrsToolButton->setIcon( QIcon( getIconPath( "geographic.png" ) ) );
- mypCRSLabel->setPixmap( QPixmap( getIconPath( "transformed.png" ) ) );
+ mypCRSLabel->setPixmap( QPixmap( getIconPath( "transformed.svg" ) ) );
}
}
diff --git a/src/plugins/coordinate_capture/coordinatecapture.qrc b/src/plugins/coordinate_capture/coordinatecapture.qrc
index f098d25..6a50088 100644
--- a/src/plugins/coordinate_capture/coordinatecapture.qrc
+++ b/src/plugins/coordinate_capture/coordinatecapture.qrc
@@ -2,7 +2,7 @@
<qresource prefix="/coordinate_capture/" >
<file>coordinate_capture.png</file>
<file>geographic.png</file>
- <file>transformed.png</file>
- <file>tracking.png</file>
+ <file>transformed.svg</file>
+ <file>tracking.svg</file>
</qresource>
</RCC>
diff --git a/src/plugins/coordinate_capture/coordinatecapturemaptool.cpp b/src/plugins/coordinate_capture/coordinatecapturemaptool.cpp
index aaa03bd..9346a02 100644
--- a/src/plugins/coordinate_capture/coordinatecapturemaptool.cpp
+++ b/src/plugins/coordinate_capture/coordinatecapturemaptool.cpp
@@ -28,6 +28,7 @@
CoordinateCaptureMapTool::CoordinateCaptureMapTool( QgsMapCanvas* thepCanvas )
: QgsMapTool( thepCanvas )
+ , mpRubberBand( nullptr )
{
// set cursor
QPixmap myCursor = QPixmap(( const char ** ) capture_point_cursor );
@@ -40,7 +41,6 @@ CoordinateCaptureMapTool::CoordinateCaptureMapTool( QgsMapCanvas* thepCanvas )
CoordinateCaptureMapTool::~CoordinateCaptureMapTool()
{
- delete mpRubberBand;
}
void CoordinateCaptureMapTool::canvasMoveEvent( QgsMapMouseEvent * thepEvent )
diff --git a/src/plugins/coordinate_capture/tracking.png b/src/plugins/coordinate_capture/tracking.png
deleted file mode 100644
index 90d0e3c..0000000
Binary files a/src/plugins/coordinate_capture/tracking.png and /dev/null differ
diff --git a/src/plugins/coordinate_capture/transformed.png b/src/plugins/coordinate_capture/transformed.png
deleted file mode 100644
index 30f853d..0000000
Binary files a/src/plugins/coordinate_capture/transformed.png and /dev/null differ
diff --git a/src/plugins/dxf2shp_converter/dxflib/src/dl_entities.h b/src/plugins/dxf2shp_converter/dxflib/src/dl_entities.h
index dd2432d..654195b 100644
--- a/src/plugins/dxf2shp_converter/dxflib/src/dl_entities.h
+++ b/src/plugins/dxf2shp_converter/dxflib/src/dl_entities.h
@@ -697,7 +697,7 @@ struct DXFLIB_EXPORT DL_InsertData {
double sz;
/*! Rotation angle in degrees. */
double angle;
- /*! Number of colums if we insert an array of the block or 1. */
+ /*! Number of columns if we insert an array of the block or 1. */
int cols;
/*! Number of rows if we insert an array of the block or 1. */
int rows;
diff --git a/src/plugins/evis/README.TXT b/src/plugins/evis/README.TXT
index 1b394de..d09cad7 100644
--- a/src/plugins/evis/README.TXT
+++ b/src/plugins/evis/README.TXT
@@ -7,7 +7,7 @@ This plugin was originally written and distributed by the Center for Biodiversit
http://biodiversityinformatics.amnh.org/open_source/evis/
eVis was contributed to the QGIS project on 2009-07-01.
-eVis was started in 2007 with QGIS v0.7.0. It was our first experience with QGIS and QT. Since its early beginings, the QGIS API has under gone many changes and advances, and as a result there are still some old ideas in this code and much room for improvement. Were we to start this plugin now, we would have done it quite differently! There is still much room for imporovement. We hope the QGIS community will find eVis useful and extend its capabilities to make it even more robust.
+eVis was started in 2007 with QGIS v0.7.0. It was our first experience with QGIS and QT. Since its early beginnings, the QGIS API has under gone many changes and advances, and as a result there are still some old ideas in this code and much room for improvement. Were we to start this plugin now, we would have done it quite differently! There is still much room for imporovement. We hope the QGIS community will find eVis useful and extend its capabilities to make it even more robust.
diff --git a/src/plugins/evis/databaseconnection/evisdatabaseconnectiongui.cpp b/src/plugins/evis/databaseconnection/evisdatabaseconnectiongui.cpp
index 01a4a9d..8f87d4a 100644
--- a/src/plugins/evis/databaseconnection/evisdatabaseconnectiongui.cpp
+++ b/src/plugins/evis/databaseconnection/evisdatabaseconnectiongui.cpp
@@ -78,9 +78,9 @@ eVisDatabaseConnectionGui::eVisDatabaseConnectionGui( QList<QTemporaryFile*>* th
//set icons
QString myThemePath = QgsApplication::activeThemePath();
- pbtnOpenFile->setIcon( QIcon( QPixmap( myThemePath + "/mActionFolder.png" ) ) );
+ pbtnOpenFile->setIcon( QIcon( QPixmap( myThemePath + "/mActionFolder.svg" ) ) );
pbtnOpenFile->setToolTip( tr( "Open File" ) );
- pbtnLoadPredefinedQueries->setIcon( QIcon( QPixmap( myThemePath + "/mActionFolder.png" ) ) );
+ pbtnLoadPredefinedQueries->setIcon( QIcon( QPixmap( myThemePath + "/mActionFolder.svg" ) ) );
pbtnLoadPredefinedQueries->setToolTip( tr( "Open File" ) );
}
diff --git a/src/plugins/evis/eventbrowser/evisgenericeventbrowsergui.cpp b/src/plugins/evis/eventbrowser/evisgenericeventbrowsergui.cpp
index 80d3ab3..aedf7ee 100644
--- a/src/plugins/evis/eventbrowser/evisgenericeventbrowsergui.cpp
+++ b/src/plugins/evis/eventbrowser/evisgenericeventbrowsergui.cpp
@@ -195,8 +195,8 @@ bool eVisGenericEventBrowserGui::initBrowser()
chkboxSaveUseOnlyFilenameData->setChecked( false );
//Set up Configure External Application buttons
- pbtnAddFileType->setIcon( QIcon( QPixmap( myThemePath + "/mActionNewAttribute.png" ) ) );
- pbtnDeleteFileType->setIcon( QIcon( QPixmap( myThemePath + "/mActionDeleteAttribute.png" ) ) );
+ pbtnAddFileType->setIcon( QIcon( QPixmap( myThemePath + "/mActionNewAttribute.svg" ) ) );
+ pbtnDeleteFileType->setIcon( QIcon( QPixmap( myThemePath + "/mActionDeleteAttribute.svg" ) ) );
//Check to for interface, not null when launched from plugin toolbar, otherwise expect map canvas
if ( mInterface )
diff --git a/src/plugins/evis/ui/evisdatabaseconnectionguibase.ui b/src/plugins/evis/ui/evisdatabaseconnectionguibase.ui
index bed0435..d0d4cfa 100644
--- a/src/plugins/evis/ui/evisdatabaseconnectionguibase.ui
+++ b/src/plugins/evis/ui/evisdatabaseconnectionguibase.ui
@@ -72,7 +72,7 @@
</property>
<property name="icon" >
<iconset>
- <normaloff>../../../images/themes/default/mActionFolder.png</normaloff>../../../images/themes/default/mActionFolder.png</iconset>
+ <normaloff>../../../images/themes/default/mActionFolder.svg</normaloff>../../../images/themes/default/mActionFolder.svg</iconset>
</property>
</widget>
</item>
@@ -331,7 +331,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="icon" >
<iconset>
- <normaloff>../../../images/themes/default/mActionFolder.png</normaloff>../../../images/themes/default/mActionFolder.png</iconset>
+ <normaloff>../../../images/themes/default/mActionFolder.svg</normaloff>../../../images/themes/default/mActionFolder.svg</iconset>
</property>
</widget>
</item>
diff --git a/src/plugins/evis/ui/evisgenericeventbrowserguibase.ui b/src/plugins/evis/ui/evisgenericeventbrowserguibase.ui
index be4b688..016b129 100644
--- a/src/plugins/evis/ui/evisgenericeventbrowserguibase.ui
+++ b/src/plugins/evis/ui/evisgenericeventbrowserguibase.ui
@@ -906,7 +906,7 @@ Base Path (i.e. keep only filename from attribute)</string>
</property>
<property name="icon">
<iconset>
- <normaloff>../../../../raster_transparency_branch/images/themes/default/mActionNewAttribute.png</normaloff>../../../../raster_transparency_branch/images/themes/default/mActionNewAttribute.png</iconset>
+ <normaloff>../../../images/themes/default/mActionNewAttribute.svg</normaloff>../../../images/themes/default/mActionNewAttribute.svg</iconset>
</property>
</widget>
</item>
@@ -923,7 +923,7 @@ Base Path (i.e. keep only filename from attribute)</string>
</property>
<property name="icon">
<iconset>
- <normaloff>../../../../raster_transparency_branch/images/themes/default/mActionDeleteAttribute.png</normaloff>../../../../raster_transparency_branch/images/themes/default/mActionDeleteAttribute.png</iconset>
+ <normaloff>../../../images/themes/default/mActionDeleteAttribute.svg</normaloff>../../../images/themes/default/mActionDeleteAttribute.svg</iconset>
</property>
</widget>
</item>
diff --git a/src/plugins/georeferencer/qgsgeorefpluginguibase.ui b/src/plugins/georeferencer/qgsgeorefpluginguibase.ui
index c4b67d1..8d3c7ba 100644
--- a/src/plugins/georeferencer/qgsgeorefpluginguibase.ui
+++ b/src/plugins/georeferencer/qgsgeorefpluginguibase.ui
@@ -379,7 +379,7 @@
<action name="mActionReset">
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/mIconClear.png</normaloff>:/images/themes/default/mIconClear.png</iconset>
+ <normaloff>:/images/themes/default/mIconClear.svg</normaloff>:/images/themes/default/mIconClear.svg</iconset>
</property>
<property name="text">
<string>Reset Georeferencer</string>
diff --git a/src/plugins/globe/globe_plugin.cpp b/src/plugins/globe/globe_plugin.cpp
index aa5723e..efa25f6 100644
--- a/src/plugins/globe/globe_plugin.cpp
+++ b/src/plugins/globe/globe_plugin.cpp
@@ -342,7 +342,9 @@ void GlobePlugin::run()
}
else
{
- QString cacheDirectory = settings.value( "cache/directory", QgsApplication::qgisSettingsDirPath() + "cache" ).toString();
+ QString cacheDirectory = settings.value( "cache/directory" ).toString();
+ if ( cacheDirectory.isEmpty() )
+ cacheDirectory = QgsApplication::qgisSettingsDirPath() + "cache";
osgEarth::Drivers::FileSystemCacheOptions cacheOptions;
cacheOptions.rootPath() = cacheDirectory.toStdString();
diff --git a/src/plugins/grass/qgsgrassplugin.cpp b/src/plugins/grass/qgsgrassplugin.cpp
index 79db3d5..d93a173 100644
--- a/src/plugins/grass/qgsgrassplugin.cpp
+++ b/src/plugins/grass/qgsgrassplugin.cpp
@@ -203,11 +203,11 @@ void QgsGrassPlugin::initGui()
mToolBarPointer->addAction( mRegionAction );
// Editing
- mAddPointAction = new QAction( QgsApplication::getThemeIcon( "/mActionCapturePoint.png" ), tr( "Add Point" ), this );
+ mAddPointAction = new QAction( QgsApplication::getThemeIcon( "/mActionCapturePoint.svg" ), tr( "Add Point" ), this );
mAddPointAction->setObjectName( "mAddPointAction" );
mAddPointAction->setCheckable( true );
- mAddLineAction = new QAction( QgsApplication::getThemeIcon( "/mActionCaptureLine.png" ), tr( "Add Line" ), this );
+ mAddLineAction = new QAction( QgsApplication::getThemeIcon( "/mActionCaptureLine.svg" ), tr( "Add Line" ), this );
mAddLineAction->setObjectName( "mAddLineAction" );
mAddLineAction->setCheckable( true );
@@ -219,7 +219,7 @@ void QgsGrassPlugin::initGui()
mAddCentroidAction->setObjectName( "mAddCentroidAction" );
mAddCentroidAction->setCheckable( true );
- mAddAreaAction = new QAction( QgsApplication::getThemeIcon( "/mActionCapturePolygon.png" ), tr( "Add Closed Boundary" ), this );
+ mAddAreaAction = new QAction( QgsApplication::getThemeIcon( "/mActionCapturePolygon.svg" ), tr( "Add Closed Boundary" ), this );
mAddAreaAction->setObjectName( "mAddAreaAction" );
mAddAreaAction->setCheckable( true );
diff --git a/src/plugins/grass/qgsgrasstools.cpp b/src/plugins/grass/qgsgrasstools.cpp
index 46a4338..5bb840f 100644
--- a/src/plugins/grass/qgsgrasstools.cpp
+++ b/src/plugins/grass/qgsgrasstools.cpp
@@ -469,7 +469,7 @@ void QgsGrassTools::addModules( QStandardItem *parent, QDomElement &element, QSt
QStandardItem *item = new QStandardItem( label );
item->setData( label, Qt::UserRole + Label );
item->setData( label, Qt::UserRole + Search );
- item->setData( QgsApplication::getThemeIcon( "mIconWarn.png" ), Qt::DecorationRole );
+ item->setData( QgsApplication::getThemeIcon( "mIconWarning.svg" ), Qt::DecorationRole );
appendItem( treeModel, parent, item );
}
n = n.nextSibling();
@@ -739,7 +739,7 @@ int QgsGrassTools::debug( QStandardItem *item )
if ( errors > 0 )
{
label += " ( " + tr( "%1 errors" ).arg( errors ) + " )";
- item->setIcon( QgsApplication::getThemeIcon( "mIconWarn.png" ) );
+ item->setIcon( QgsApplication::getThemeIcon( "mIconWarning.svg" ) );
}
else
{
diff --git a/src/plugins/interpolation/interpolator.qrc b/src/plugins/interpolation/interpolator.qrc
index 00ef6fa..4bbd237 100644
--- a/src/plugins/interpolation/interpolator.qrc
+++ b/src/plugins/interpolation/interpolator.qrc
@@ -1,6 +1,5 @@
<RCC>
- <qresource prefix="/" >
- <file>options.png</file>
+ <qresource prefix="/">
<file>raster-interpolate.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/interpolation/options.png b/src/plugins/interpolation/options.png
deleted file mode 100644
index 96ba433..0000000
Binary files a/src/plugins/interpolation/options.png and /dev/null differ
diff --git a/src/plugins/interpolation/qgsinterpolationdialogbase.ui b/src/plugins/interpolation/qgsinterpolationdialogbase.ui
index 5890189..1910d50 100644
--- a/src/plugins/interpolation/qgsinterpolationdialogbase.ui
+++ b/src/plugins/interpolation/qgsinterpolationdialogbase.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>772</width>
- <height>382</height>
+ <width>858</width>
+ <height>389</height>
</rect>
</property>
<property name="sizePolicy">
@@ -147,7 +147,7 @@
</property>
<property name="icon">
<iconset resource="interpolator.qrc">
- <normaloff>:/options.png</normaloff>:/options.png</iconset>
+ <normaloff>:/mActionOptions.svg</normaloff>:/mActionOptions.svg</iconset>
</property>
</widget>
</item>
diff --git a/src/plugins/offline_editing/offline_editing_plugin.cpp b/src/plugins/offline_editing/offline_editing_plugin.cpp
index 8e40608..4ce62bb 100644
--- a/src/plugins/offline_editing/offline_editing_plugin.cpp
+++ b/src/plugins/offline_editing/offline_editing_plugin.cpp
@@ -109,7 +109,7 @@ void QgsOfflineEditingPlugin::convertProject()
}
mProgressDialog->setTitle( tr( "Converting to offline project" ) );
- if ( mOfflineEditing->convertToOfflineProject( myPluginGui->offlineDataPath(), myPluginGui->offlineDbFile(), selectedLayerIds ) )
+ if ( mOfflineEditing->convertToOfflineProject( myPluginGui->offlineDataPath(), myPluginGui->offlineDbFile(), selectedLayerIds, myPluginGui->onlySelected() ) )
{
updateActions();
// Redraw, to make the offline layer visible
diff --git a/src/plugins/offline_editing/offline_editing_plugin_gui.cpp b/src/plugins/offline_editing/offline_editing_plugin_gui.cpp
index 0dc47d0..7e99407 100644
--- a/src/plugins/offline_editing/offline_editing_plugin_gui.cpp
+++ b/src/plugins/offline_editing/offline_editing_plugin_gui.cpp
@@ -102,11 +102,16 @@ QString QgsOfflineEditingPluginGui::offlineDbFile()
return mOfflineDbFile;
}
-QStringList& QgsOfflineEditingPluginGui::selectedLayerIds()
+QStringList QgsOfflineEditingPluginGui::selectedLayerIds()
{
return mSelectedLayerIds;
}
+bool QgsOfflineEditingPluginGui::onlySelected() const
+{
+ return mOnlySelectedCheckBox->checkState() == Qt::Checked;
+}
+
void QgsOfflineEditingPluginGui::on_mBrowseButton_clicked()
{
QString fileName = QFileDialog::getSaveFileName( this,
diff --git a/src/plugins/offline_editing/offline_editing_plugin_gui.h b/src/plugins/offline_editing/offline_editing_plugin_gui.h
index 3bd8863..2a0b08e 100644
--- a/src/plugins/offline_editing/offline_editing_plugin_gui.h
+++ b/src/plugins/offline_editing/offline_editing_plugin_gui.h
@@ -46,7 +46,8 @@ class QgsOfflineEditingPluginGui : public QDialog, private Ui::QgsOfflineEditing
QString offlineDataPath();
QString offlineDbFile();
- QStringList& selectedLayerIds();
+ QStringList selectedLayerIds();
+ bool onlySelected() const;
public slots:
/** Change the selection of layers in the list */
diff --git a/src/plugins/offline_editing/offline_editing_plugin_guibase.ui b/src/plugins/offline_editing/offline_editing_plugin_guibase.ui
index 6f5d8ee..191b06d 100644
--- a/src/plugins/offline_editing/offline_editing_plugin_guibase.ui
+++ b/src/plugins/offline_editing/offline_editing_plugin_guibase.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>435</width>
- <height>270</height>
+ <width>590</width>
+ <height>570</height>
</rect>
</property>
<property name="windowTitle">
@@ -93,6 +93,13 @@
</layout>
</item>
<item>
+ <widget class="QCheckBox" name="mOnlySelectedCheckBox">
+ <property name="text">
+ <string>Only synchronize selected features if a selection is present</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QDialogButtonBox" name="buttonBox">
diff --git a/src/plugins/roadgraph/shortestpathwidget.cpp b/src/plugins/roadgraph/shortestpathwidget.cpp
index 5cd6a50..adfa9e8 100644
--- a/src/plugins/roadgraph/shortestpathwidget.cpp
+++ b/src/plugins/roadgraph/shortestpathwidget.cpp
@@ -174,12 +174,6 @@ RgShortestPathWidget::RgShortestPathWidget( QWidget* theParent, RoadGraphPlugin
} //RgShortestPathWidget::RgShortestPathWidget()
RgShortestPathWidget::~RgShortestPathWidget()
{
- delete mFrontPointMapTool;
- delete mBackPointMapTool;
-
- delete mrbFrontPoint;
- delete mrbBackPoint;
- delete mrbPath;
} //RgShortestPathWidget::~RgShortestPathWidget()
void RgShortestPathWidget::mapCanvasExtentsChanged()
diff --git a/src/providers/arcgisrest/qgsafssourceselect.cpp b/src/providers/arcgisrest/qgsafssourceselect.cpp
index 0ceb3fa..c761eda 100644
--- a/src/providers/arcgisrest/qgsafssourceselect.cpp
+++ b/src/providers/arcgisrest/qgsafssourceselect.cpp
@@ -32,6 +32,10 @@ QgsAfsSourceSelect::QgsAfsSourceSelect( QWidget* parent, Qt::WindowFlags fl, boo
{
buttonBox->button( QDialogButtonBox::Close )->hide();
}
+
+ // import/export of connections not supported yet
+ btnLoad->hide();
+ btnSave->hide();
}
bool QgsAfsSourceSelect::connectToService( const QgsOWSConnection &connection )
diff --git a/src/providers/arcgisrest/qgsamsprovider.cpp b/src/providers/arcgisrest/qgsamsprovider.cpp
index 9aab793..be4eed9 100644
--- a/src/providers/arcgisrest/qgsamsprovider.cpp
+++ b/src/providers/arcgisrest/qgsamsprovider.cpp
@@ -437,8 +437,10 @@ QgsRasterIdentifyResult QgsAmsProvider::identify( const QgsPoint & thePoint, Qgs
return QgsRasterIdentifyResult( theFormat, entries );
}
-void QgsAmsProvider::readBlock( int /*bandNo*/, const QgsRectangle & viewExtent, int width, int height, void *data )
+void QgsAmsProvider::readBlock( int /*bandNo*/, const QgsRectangle & viewExtent, int width, int height, void *data, QgsRasterBlockFeedback* feedback )
{
+ Q_UNUSED( feedback ); // TODO: make use of the feedback object
+
// TODO: optimize to avoid writing to QImage
// returned image is actually mCachedImage, no need to delete
QImage *image = draw( viewExtent, width, height );
diff --git a/src/providers/arcgisrest/qgsamsprovider.h b/src/providers/arcgisrest/qgsamsprovider.h
index f6b05f9..95499d9 100644
--- a/src/providers/arcgisrest/qgsamsprovider.h
+++ b/src/providers/arcgisrest/qgsamsprovider.h
@@ -86,7 +86,7 @@ class QgsAmsProvider : public QgsRasterDataProvider
QgsRasterIdentifyResult identify( const QgsPoint & thePoint, QgsRaster::IdentifyFormat theFormat, const QgsRectangle &theExtent = QgsRectangle(), int theWidth = 0, int theHeight = 0, int theDpi = 96 ) override;
protected:
- void readBlock( int bandNo, const QgsRectangle & viewExtent, int width, int height, void *data ) override;
+ void readBlock( int bandNo, const QgsRectangle & viewExtent, int width, int height, void *data, QgsRasterBlockFeedback* feedback = nullptr ) override;
private:
bool mValid;
diff --git a/src/providers/arcgisrest/qgsamssourceselect.cpp b/src/providers/arcgisrest/qgsamssourceselect.cpp
index 6504f8b..0b6875c 100644
--- a/src/providers/arcgisrest/qgsamssourceselect.cpp
+++ b/src/providers/arcgisrest/qgsamssourceselect.cpp
@@ -32,6 +32,10 @@ QgsAmsSourceSelect::QgsAmsSourceSelect( QWidget* parent, Qt::WindowFlags fl, boo
{
buttonBox->button( QDialogButtonBox::Close )->hide();
}
+
+ // import/export of connections not supported yet
+ btnLoad->hide();
+ btnSave->hide();
}
bool QgsAmsSourceSelect::connectToService( const QgsOWSConnection &connection )
diff --git a/src/providers/db2/qgsdb2tablemodel.cpp b/src/providers/db2/qgsdb2tablemodel.cpp
index 63206f1..d823093 100644
--- a/src/providers/db2/qgsdb2tablemodel.cpp
+++ b/src/providers/db2/qgsdb2tablemodel.cpp
@@ -315,7 +315,7 @@ QIcon QgsDb2TableModel::iconForWkbType( QGis::WkbType type )
case QGis::WKBMultiPolygon25D:
return QgsApplication::getThemeIcon( "/mIconPolygonLayer.svg" );
case QGis::WKBNoGeometry:
- return QgsApplication::getThemeIcon( "/mIconTableLayer.png" );
+ return QgsApplication::getThemeIcon( "/mIconTableLayer.svg" );
case QGis::WKBUnknown:
break;
}
diff --git a/src/providers/gdal/qgsgdalprovider.cpp b/src/providers/gdal/qgsgdalprovider.cpp
index fc89065..3817dd6 100644
--- a/src/providers/gdal/qgsgdalprovider.cpp
+++ b/src/providers/gdal/qgsgdalprovider.cpp
@@ -390,6 +390,11 @@ QImage* QgsGdalProvider::draw( QgsRectangle const & viewExtent, int pixelWidth,
QgsRasterBlock* QgsGdalProvider::block( int theBandNo, const QgsRectangle &theExtent, int theWidth, int theHeight )
{
+ return block2( theBandNo, theExtent, theWidth, theHeight );
+}
+
+QgsRasterBlock* QgsGdalProvider::block2( int theBandNo, const QgsRectangle &theExtent, int theWidth, int theHeight, QgsRasterBlockFeedback* feedback )
+{
//QgsRasterBlock *block = new QgsRasterBlock( dataType( theBandNo ), theWidth, theHeight, noDataValue( theBandNo ) );
QgsRasterBlock *block;
if ( srcHasNoDataValue( theBandNo ) && useSrcNoDataValue( theBandNo ) )
@@ -411,7 +416,7 @@ QgsRasterBlock* QgsGdalProvider::block( int theBandNo, const QgsRectangle &theEx
QRect subRect = QgsRasterBlock::subRect( theExtent, theWidth, theHeight, mExtent );
block->setIsNoDataExcept( subRect );
}
- readBlock( theBandNo, theExtent, theWidth, theHeight, block->bits() );
+ readBlock( theBandNo, theExtent, theWidth, theHeight, block->bits(), feedback );
// apply scale and offset
block->applyScaleOffset( bandScale( theBandNo ), bandOffset( theBandNo ) );
block->applyNoDataValues( userNoDataValues( theBandNo ) );
@@ -435,7 +440,7 @@ void QgsGdalProvider::readBlock( int theBandNo, int xBlock, int yBlock, void *bl
gdalRasterIO( myGdalBand, GF_Read, xOff, yOff, mXBlockSize, mYBlockSize, block, mXBlockSize, mYBlockSize, ( GDALDataType ) mGdalDataType.at( theBandNo - 1 ), 0, 0 );
}
-void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent, int thePixelWidth, int thePixelHeight, void *theBlock )
+void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent, int thePixelWidth, int thePixelHeight, void *theBlock, QgsRasterBlockFeedback* feedback )
{
QgsDebugMsg( "thePixelWidth = " + QString::number( thePixelWidth ) );
QgsDebugMsg( "thePixelHeight = " + QString::number( thePixelHeight ) );
@@ -601,17 +606,18 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,
char *tmpBlock = ( char * )qgsMalloc( dataSize * tmpWidth * tmpHeight );
if ( ! tmpBlock )
{
- QgsDebugMsg( QString( "Coudn't allocate temporary buffer of %1 bytes" ).arg( dataSize * tmpWidth * tmpHeight ) );
+ QgsDebugMsg( QString( "Couldn't allocate temporary buffer of %1 bytes" ).arg( dataSize * tmpWidth * tmpHeight ) );
return;
}
GDALRasterBandH gdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
GDALDataType type = ( GDALDataType )mGdalDataType.at( theBandNo - 1 );
CPLErrorReset();
+
CPLErr err = gdalRasterIO( gdalBand, GF_Read,
srcLeft, srcTop, srcWidth, srcHeight,
( void * )tmpBlock,
tmpWidth, tmpHeight, type,
- 0, 0 );
+ 0, 0, feedback );
if ( err != CPLE_None )
{
diff --git a/src/providers/gdal/qgsgdalprovider.h b/src/providers/gdal/qgsgdalprovider.h
index fc27b5e..09156c1 100644
--- a/src/providers/gdal/qgsgdalprovider.h
+++ b/src/providers/gdal/qgsgdalprovider.h
@@ -171,9 +171,10 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase
/** Reimplemented from QgsRasterDataProvider to bypass second resampling (more efficient for local file based sources)*/
QgsRasterBlock *block( int theBandNo, const QgsRectangle &theExtent, int theWidth, int theHeight ) override;
+ QgsRasterBlock *block2( int theBandNo, const QgsRectangle &theExtent, int theWidth, int theHeight, QgsRasterBlockFeedback* feedback = nullptr ) override;
void readBlock( int bandNo, int xBlock, int yBlock, void *data ) override;
- void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data ) override;
+ void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data, QgsRasterBlockFeedback* feedback = nullptr ) override;
/** Read band scale for raster value
* @@note added in 2.3 */
diff --git a/src/providers/gdal/qgsgdalproviderbase.cpp b/src/providers/gdal/qgsgdalproviderbase.cpp
index 63b764f..b91e353 100644
--- a/src/providers/gdal/qgsgdalproviderbase.cpp
+++ b/src/providers/gdal/qgsgdalproviderbase.cpp
@@ -280,7 +280,17 @@ GDALDatasetH QgsGdalProviderBase::gdalOpen( const char *pszFilename, GDALAccess
return hDS;
}
-CPLErr QgsGdalProviderBase::gdalRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace )
+int CPL_STDCALL _gdalProgressFnWithFeedback( double dfComplete, const char *pszMessage, void *pProgressArg )
+{
+ Q_UNUSED( dfComplete );
+ Q_UNUSED( pszMessage );
+
+ QgsRasterBlockFeedback* feedback = static_cast<QgsRasterBlockFeedback*>( pProgressArg );
+ return !feedback->isCancelled();
+}
+
+
+CPLErr QgsGdalProviderBase::gdalRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace, QgsRasterBlockFeedback* feedback )
{
// See http://hub.qgis.org/issues/8356 and http://trac.osgeo.org/gdal/ticket/5170
#if GDAL_VERSION_MAJOR == 1 && ( (GDAL_VERSION_MINOR == 9 && GDAL_VERSION_REV <= 2) || (GDAL_VERSION_MINOR == 10 && GDAL_VERSION_REV <= 0) )
@@ -289,7 +299,24 @@ CPLErr QgsGdalProviderBase::gdalRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWF
QgsDebugMsg( "Disabled VSI_CACHE" );
#endif
+#if GDAL_VERSION_MAJOR >= 2
+ GDALRasterIOExtraArg extra;
+ INIT_RASTERIO_EXTRA_ARG( extra );
+ if ( 0 && feedback ) // disabled!
+ {
+ // Currently the cancellation is disabled... When RasterIO call is cancelled,
+ // GDAL returns CE_Failure with error code = 0 (CPLE_None), however one would
+ // expect to get CPLE_UserInterrupt to clearly identify that the failure was
+ // caused by the cancellation and not that something dodgy is going on.
+ // Are both error codes acceptable?
+ extra.pfnProgress = _gdalProgressFnWithFeedback;
+ extra.pProgressData = ( void* ) feedback;
+ }
+ CPLErr err = GDALRasterIOEx( hBand, eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace, &extra );
+#else
+ Q_UNUSED( feedback );
CPLErr err = GDALRasterIO( hBand, eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace );
+#endif
#if GDAL_VERSION_MAJOR == 1 && ( (GDAL_VERSION_MINOR == 9 && GDAL_VERSION_REV <= 2) || (GDAL_VERSION_MINOR == 10 && GDAL_VERSION_REV <= 0) )
CPLSetThreadLocalConfigOption( "VSI_CACHE", pszOldVal );
diff --git a/src/providers/gdal/qgsgdalproviderbase.h b/src/providers/gdal/qgsgdalproviderbase.h
index 4c3bb97..5da6cd2 100644
--- a/src/providers/gdal/qgsgdalproviderbase.h
+++ b/src/providers/gdal/qgsgdalproviderbase.h
@@ -49,7 +49,7 @@ class QgsGdalProviderBase
static GDALDatasetH gdalOpen( const char *pszFilename, GDALAccess eAccess );
/** Wrapper function for GDALRasterIO to get around possible bugs in GDAL */
- static CPLErr gdalRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace );
+ static CPLErr gdalRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace, QgsRasterBlockFeedback* feedback = nullptr );
/** Wrapper function for GDALRasterIO to get around possible bugs in GDAL */
static int gdalGetOverviewCount( GDALRasterBandH hBand );
diff --git a/src/providers/grass/qgsgrassrasterprovider.cpp b/src/providers/grass/qgsgrassrasterprovider.cpp
index aebdc6d..5015504 100644
--- a/src/providers/grass/qgsgrassrasterprovider.cpp
+++ b/src/providers/grass/qgsgrassrasterprovider.cpp
@@ -278,8 +278,9 @@ void QgsGrassRasterProvider::readBlock( int bandNo, int xBlock, int yBlock, void
memcpy( block, data.data(), size );
}
-void QgsGrassRasterProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight, void *block )
+void QgsGrassRasterProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight, void *block, QgsRasterBlockFeedback* feedback )
{
+ Q_UNUSED( feedback );
QgsDebugMsg( "pixelWidth = " + QString::number( pixelWidth ) );
QgsDebugMsg( "pixelHeight = " + QString::number( pixelHeight ) );
QgsDebugMsg( "viewExtent: " + viewExtent.toString() );
diff --git a/src/providers/grass/qgsgrassrasterprovider.h b/src/providers/grass/qgsgrassrasterprovider.h
index 7c3680f..adf3534 100644
--- a/src/providers/grass/qgsgrassrasterprovider.h
+++ b/src/providers/grass/qgsgrassrasterprovider.h
@@ -192,7 +192,7 @@ class GRASS_LIB_EXPORT QgsGrassRasterProvider : public QgsRasterDataProvider
int ySize() const override;
void readBlock( int bandNo, int xBlock, int yBlock, void *data ) override;
- void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data ) override;
+ void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data, QgsRasterBlockFeedback* feedback = nullptr ) override;
QgsRasterBandStats bandStatistics( int theBandNo,
int theStats = QgsRasterBandStats::All,
diff --git a/src/providers/mssql/qgsmssqltablemodel.cpp b/src/providers/mssql/qgsmssqltablemodel.cpp
index bdbc5c1..3bcf19f 100644
--- a/src/providers/mssql/qgsmssqltablemodel.cpp
+++ b/src/providers/mssql/qgsmssqltablemodel.cpp
@@ -315,7 +315,7 @@ QIcon QgsMssqlTableModel::iconForWkbType( QGis::WkbType type )
case QGis::WKBMultiPolygon25D:
return QgsApplication::getThemeIcon( "/mIconPolygonLayer.svg" );
case QGis::WKBNoGeometry:
- return QgsApplication::getThemeIcon( "/mIconTableLayer.png" );
+ return QgsApplication::getThemeIcon( "/mIconTableLayer.svg" );
case QGis::WKBUnknown:
break;
}
diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp
index 4dd6a33..61964c6 100644
--- a/src/providers/ogr/qgsogrfeatureiterator.cpp
+++ b/src/providers/ogr/qgsogrfeatureiterator.cpp
@@ -313,8 +313,13 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )
else
feature.setGeometry( nullptr );
- if (( useIntersect && ( !feature.constGeometry() || !feature.constGeometry()->intersects( mRequest.filterRect() ) ) )
- || ( geometryTypeFilter && ( !feature.constGeometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.constGeometry()->wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) )
+ if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection &&
+ geom && wkbFlatten( OGR_G_GetGeometryType( geom ) ) == wkbGeometryCollection )
+ {
+ // OK
+ }
+ else if (( useIntersect && ( !feature.constGeometry() || !feature.constGeometry()->intersects( mRequest.filterRect() ) ) )
+ || ( geometryTypeFilter && ( !feature.constGeometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.constGeometry()->wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) )
{
OGR_F_Destroy( fet );
return false;
@@ -361,7 +366,7 @@ QgsOgrFeatureSource::QgsOgrFeatureSource( const QgsOgrProvider* p )
mFieldsWithoutFid.append( mFields.at( i ) );
mDriverName = p->ogrDriverName;
mFirstFieldIsFid = p->mFirstFieldIsFid;
- mOgrGeometryTypeFilter = wkbFlatten( p->mOgrGeometryTypeFilter );
+ mOgrGeometryTypeFilter = QgsOgrProvider::ogrWkbSingleFlatten( p->mOgrGeometryTypeFilter );
QgsOgrConnPool::instance()->ref( mDataSource );
}
diff --git a/src/providers/ogr/qgsogrprovider.cpp b/src/providers/ogr/qgsogrprovider.cpp
index b5fb39a..9fc0b46 100644
--- a/src/providers/ogr/qgsogrprovider.cpp
+++ b/src/providers/ogr/qgsogrprovider.cpp
@@ -155,7 +155,12 @@ void QgsOgrProvider::repack()
// run REPACK on shape files
QByteArray sql = QByteArray( "REPACK " ) + layerName; // don't quote the layer name as it works with spaces in the name and won't work if the name is quoted
QgsDebugMsg( QString( "SQL: %1" ).arg( FROM8( sql ) ) );
+ CPLErrorReset();
OGR_DS_ExecuteSQL( ogrDataSource, sql.constData(), nullptr, nullptr );
+ if ( CPLGetLastErrorType() != CE_None )
+ {
+ pushError( tr( "OGR[%1] error %2: %3" ).arg( CPLGetLastErrorType() ).arg( CPLGetLastErrorNo() ).arg( CPLGetLastErrorMsg() ) );
+ }
if ( mFilePath.endsWith( ".shp", Qt::CaseInsensitive ) || mFilePath.endsWith( ".dbf", Qt::CaseInsensitive ) )
{
@@ -282,6 +287,7 @@ QgsOgrProvider::QgsOgrProvider( QString const & uri )
, mFirstFieldIsFid( false )
, ogrDataSource( nullptr )
, mExtent( nullptr )
+ , mForceRecomputeExtent( false )
, ogrLayer( nullptr )
, ogrOrigLayer( nullptr )
, mLayerIndex( 0 )
@@ -478,7 +484,7 @@ bool QgsOgrProvider::setSubsetString( const QString& theSQL, bool updateFeatureC
loadFields();
QgsDebugMsg( "Done checking validity" );
- updateExtents();
+ invalidateCachedExtent( false );
emit dataChanged();
@@ -973,6 +979,17 @@ QgsRectangle QgsOgrProvider::extent()
// get the extent_ (envelope) of the layer
QgsDebugMsg( "Starting get extent" );
+#if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,1,2)
+ if ( mForceRecomputeExtent && mValid && ogrDriverName == "GPKG" && ogrDataSource && ogrOrigLayer )
+ {
+ QByteArray layerName = OGR_FD_GetName( OGR_L_GetLayerDefn( ogrOrigLayer ) );
+ // works with unquoted layerName
+ QByteArray sql = QByteArray( "RECOMPUTE EXTENT ON " ) + layerName;
+ QgsDebugMsg( QString( "SQL: %1" ).arg( FROM8( sql ) ) );
+ OGR_DS_ExecuteSQL( ogrDataSource, sql.constData(), nullptr, nullptr );
+ }
+#endif
+
// TODO: This can be expensive, do we really need it!
if ( ogrLayer == ogrOrigLayer )
{
@@ -1016,6 +1033,12 @@ QgsRectangle QgsOgrProvider::extent()
void QgsOgrProvider::updateExtents()
{
+ invalidateCachedExtent( true );
+}
+
+void QgsOgrProvider::invalidateCachedExtent( bool bForceRecomputeExtent )
+{
+ mForceRecomputeExtent = bForceRecomputeExtent;
delete mExtent;
mExtent = nullptr;
}
@@ -1660,6 +1683,8 @@ bool QgsOgrProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
}
mShapefileMayBeCorrupted = true;
+ invalidateCachedExtent( true );
+
OGR_F_Destroy( theOGRFeature );
}
QgsOgrConnPool::instance()->invalidateConnections( dataSourceUri() );
@@ -1729,7 +1754,7 @@ bool QgsOgrProvider::deleteFeatures( const QgsFeatureIds & id )
clearMinMaxCache();
- updateExtents();
+ invalidateCachedExtent( true );
return returnvalue;
}
@@ -3152,13 +3177,16 @@ void QgsOgrProvider::recalculateFeatureCount()
setRelevantFields( ogrLayer, true, QgsAttributeList() );
OGR_L_ResetReading( ogrLayer );
OGRFeatureH fet;
+ const OGRwkbGeometryType flattenGeomTypeFilter =
+ QgsOgrProvider::ogrWkbSingleFlatten( mOgrGeometryTypeFilter );
while (( fet = OGR_L_GetNextFeature( ogrLayer ) ) )
{
OGRGeometryH geom = OGR_F_GetGeometryRef( fet );
if ( geom )
{
OGRwkbGeometryType gType = OGR_G_GetGeometryType( geom );
- if ( gType == mOgrGeometryTypeFilter ) mFeaturesCounted++;
+ gType = QgsOgrProvider::ogrWkbSingleFlatten( gType );
+ if ( gType == flattenGeomTypeFilter ) mFeaturesCounted++;
}
OGR_F_Destroy( fet );
}
@@ -3362,6 +3390,18 @@ void QgsOgrProvider::open( OpenMode mode )
ogrLayer = ogrOrigLayer = nullptr;
mValid = false;
+#if defined(GDAL_COMPUTE_VERSION)
+ // In the case where we deal with a shapefile, it is possible that it has
+ // pre-existing holes in the DBF (see #15407), so if using a GDAL version
+ // recent enough to have reliable packing, do a packing at the first edit
+ // action.
+ if ( ogrDriverName == "ESRI Shapefile" &&
+ atoi( GDALVersionInfo( "VERSION_NUM" ) ) >= GDAL_COMPUTE_VERSION( 2, 1, 2 ) )
+ {
+ mShapefileMayBeCorrupted = true;
+ }
+#endif
+
ogrDataSource = QgsOgrProviderUtils::OGROpenWrapper( TO8F( mFilePath ), false, &ogrDriver );
mWriteAccess = false;
@@ -3422,7 +3462,7 @@ void QgsOgrProvider::close()
mValid = false;
setProperty( "_debug_open_mode", "invalid" );
- updateExtents();
+ invalidateCachedExtent( false );
}
void QgsOgrProvider::reloadData()
diff --git a/src/providers/ogr/qgsogrprovider.h b/src/providers/ogr/qgsogrprovider.h
index 6b2b534..cd63608 100644
--- a/src/providers/ogr/qgsogrprovider.h
+++ b/src/providers/ogr/qgsogrprovider.h
@@ -286,6 +286,9 @@ class QgsOgrProvider : public QgsVectorDataProvider
/** Clean shapefile from features which are marked as deleted */
void repack();
+ /** Invalidate extent and optionnaly force its low level recomputation */
+ void invalidateCachedExtent( bool bForceRecomputeExtent );
+
enum OpenMode
{
OpenModeInitial,
@@ -305,6 +308,7 @@ class QgsOgrProvider : public QgsVectorDataProvider
bool mFirstFieldIsFid;
OGRDataSourceH ogrDataSource;
OGREnvelope* mExtent;
+ bool mForceRecomputeExtent;
/** This member variable receives the same value as extent_
in the method QgsOgrProvider::extent(). The purpose is to prevent a memory leak*/
diff --git a/src/providers/oracle/qgsoracleprovider.cpp b/src/providers/oracle/qgsoracleprovider.cpp
index 0d5dc6c..b3d8321 100644
--- a/src/providers/oracle/qgsoracleprovider.cpp
+++ b/src/providers/oracle/qgsoracleprovider.cpp
@@ -1743,7 +1743,7 @@ bool QgsOracleProvider::changeAttributeValues( const QgsChangedAttributesMap &at
QString sql = QString( "UPDATE %1 SET " ).arg( mQuery );
bool pkChanged = false;
- QList<int> geometryParams;
+ QList<int> params;
// cycle through the changed attributes of the feature
QString delim;
@@ -1764,10 +1764,15 @@ bool QgsOracleProvider::changeAttributeValues( const QgsChangedAttributesMap &at
sql += QString( "SDO_UTIL.FROM_WKTGEOMETRY(%1)" ).arg( quotedValue( siter->toString() ) );
else
{
- geometryParams << siter.key();
+ params << siter.key();
sql += "?";
}
}
+ else if ( fld.typeName().endsWith( "LOB" ) )
+ {
+ params << siter.key();
+ sql += "?";
+ }
else
{
sql += quotedValue( *siter, fld.type() );
@@ -1786,21 +1791,30 @@ bool QgsOracleProvider::changeAttributeValues( const QgsChangedAttributesMap &at
throw OracleException( tr( "Could not prepare update statement." ), qry );
}
- Q_FOREACH ( int idx, geometryParams )
+ Q_FOREACH ( int idx, params )
{
- QgsGeometry *g;
- if ( !attrs[idx].isNull() )
+ const QgsField &fld = field( idx );
+
+ if ( fld.typeName().endsWith( ".SDO_GEOMETRY" ) )
{
- g = QgsGeometry::fromWkt( attrs[ idx ].toString() );
+ QgsGeometry *g;
+ if ( !attrs[idx].isNull() )
+ {
+ g = QgsGeometry::fromWkt( attrs[ idx ].toString() );
+ }
+ else
+ {
+ g = new QgsGeometry();
+ }
+
+ appendGeomParam( g, qry );
+
+ delete g;
}
- else
+ else if ( fld.typeName().endsWith( "LOB" ) )
{
- g = new QgsGeometry();
+ qry.addBindValue( attrs[ idx ] );
}
-
- appendGeomParam( g, qry );
-
- delete g;
}
if ( !qry.exec() )
diff --git a/src/providers/oracle/qgsoracletablemodel.cpp b/src/providers/oracle/qgsoracletablemodel.cpp
index 446b55c..e2188a0 100644
--- a/src/providers/oracle/qgsoracletablemodel.cpp
+++ b/src/providers/oracle/qgsoracletablemodel.cpp
@@ -244,7 +244,7 @@ QIcon QgsOracleTableModel::iconForWkbType( QGis::WkbType type )
case QGis::WKBMultiPolygon25D:
return QgsApplication::getThemeIcon( "/mIconPolygonLayer.svg" );
case QGis::WKBNoGeometry:
- return QgsApplication::getThemeIcon( "/mIconTableLayer.png" );
+ return QgsApplication::getThemeIcon( "/mIconTableLayer.svg" );
case QGis::WKBUnknown:
break;
}
diff --git a/src/providers/postgres/qgspgtablemodel.cpp b/src/providers/postgres/qgspgtablemodel.cpp
index bc65993..1d19e47 100644
--- a/src/providers/postgres/qgspgtablemodel.cpp
+++ b/src/providers/postgres/qgspgtablemodel.cpp
@@ -138,7 +138,7 @@ void QgsPgTableModel::addTableEntry( const QgsPostgresLayerProperty& layerProper
item->setFlags( item->flags() & ~Qt::ItemIsSelectable );
if ( item == schemaNameItem )
- item->setData( QgsApplication::getThemeIcon( "/mIconWarn.png" ), Qt::DecorationRole );
+ item->setData( QgsApplication::getThemeIcon( "/mIconWarning.svg" ), Qt::DecorationRole );
if ( item == schemaNameItem || item == tableItem || item == geomItem )
{
@@ -300,7 +300,7 @@ bool QgsPgTableModel::setData( const QModelIndex &idx, const QVariant &value, in
item->setFlags( item->flags() & ~Qt::ItemIsSelectable );
if ( i == dbtmSchema )
- item->setData( QgsApplication::getThemeIcon( "/mIconWarn.png" ), Qt::DecorationRole );
+ item->setData( QgsApplication::getThemeIcon( "/mIconWarning.svg" ), Qt::DecorationRole );
if ( i == dbtmSchema || i == dbtmTable || i == dbtmGeomCol )
{
diff --git a/src/providers/postgres/qgspostgresprovider.cpp b/src/providers/postgres/qgspostgresprovider.cpp
index e4dc1d8..7a1f1ed 100644
--- a/src/providers/postgres/qgspostgresprovider.cpp
+++ b/src/providers/postgres/qgspostgresprovider.cpp
@@ -235,7 +235,7 @@ QgsPostgresProvider::QgsPostgresProvider( QString const & uri )
QString delim;
Q_FOREACH ( int idx, mPrimaryKeyAttrs )
{
- key += delim + quotedIdentifier( mAttributeFields.at( idx ).name() );
+ key += delim + mAttributeFields.at( idx ).name();
delim = ',';
}
}
@@ -1377,56 +1377,73 @@ bool QgsPostgresProvider::determinePrimaryKey()
return mValid;
}
-void QgsPostgresProvider::determinePrimaryKeyFromUriKeyColumn()
+/* static */
+QStringList QgsPostgresProvider::parseUriKey( const QString& key )
{
- QString primaryKey = mUri.keyColumn();
- mPrimaryKeyType = pktUnknown;
+ if ( key.isEmpty() ) return QStringList();
- if ( !primaryKey.isEmpty() )
- {
- QStringList cols;
+ QStringList cols;
- // remove quotes from key list
- if ( primaryKey.startsWith( '"' ) && primaryKey.endsWith( '"' ) )
+ // remove quotes from key list
+ if ( key.startsWith( '"' ) && key.endsWith( '"' ) )
+ {
+ int i = 1;
+ QString col;
+ while ( i < key.size() )
{
- int i = 1;
- QString col;
- while ( i < primaryKey.size() )
+ if ( key[i] == '"' )
{
- if ( primaryKey[i] == '"' )
+ if ( i + 1 < key.size() && key[i+1] == '"' )
{
- if ( i + 1 < primaryKey.size() && primaryKey[i+1] == '"' )
- {
- i++;
- }
- else
- {
- cols << col;
- col = "";
+ i++;
+ }
+ else
+ {
+ cols << col;
+ col = "";
- if ( ++i == primaryKey.size() )
- break;
+ if ( ++i == key.size() )
+ break;
- Q_ASSERT( primaryKey[i] == ',' );
- i++;
- Q_ASSERT( primaryKey[i] == '"' );
- i++;
- col = "";
- continue;
- }
+ Q_ASSERT( key[i] == ',' );
+ i++;
+ Q_ASSERT( key[i] == '"' );
+ i++;
+ col = "";
+ continue;
}
-
- col += primaryKey[i++];
}
+
+ col += key[i++];
}
- else if ( primaryKey.contains( ',' ) )
- {
- cols = primaryKey.split( ',' );
- }
- else
+ }
+ else if ( key.contains( ',' ) )
+ {
+ cols = key.split( ',' );
+ }
+ else
+ {
+ cols << key;
+ }
+
+ return cols;
+}
+
+void QgsPostgresProvider::determinePrimaryKeyFromUriKeyColumn()
+{
+ QString primaryKey = mUri.keyColumn();
+ mPrimaryKeyType = pktUnknown;
+
+ if ( !primaryKey.isEmpty() )
+ {
+ QStringList cols = parseUriKey( primaryKey );
+
+ primaryKey = "";
+ QString del = "";
+ Q_FOREACH ( const QString& col, cols )
{
- cols << primaryKey;
- primaryKey = quotedIdentifier( primaryKey );
+ primaryKey += del + quotedIdentifier( col );
+ del = ",";
}
Q_FOREACH ( const QString& col, cols )
@@ -1707,7 +1724,13 @@ QVariant QgsPostgresProvider::defaultValue( int fieldId )
QgsPostgresResult res( connectionRO()->PQexec( QString( "SELECT %1" ).arg( defVal.toString() ) ) );
- return convertValue( fld.type(), res.PQgetvalue( 0, 0 ) );
+ if ( res.result() )
+ return convertValue( fld.type(), res.PQgetvalue( 0, 0 ) );
+ else
+ {
+ pushError( tr( "Could not execute query" ) );
+ return QVariant();
+ }
}
return defVal;
@@ -3440,16 +3463,16 @@ bool QgsPostgresProvider::convertField( QgsField &field, const QMap<QString, QVa
break;
case QVariant::Double:
- if ( fieldPrec > 0 )
+ if ( fieldSize > 18 )
{
fieldType = "numeric";
+ fieldSize = -1;
}
else
{
fieldType = "float8";
- fieldSize = -1;
- fieldPrec = -1;
}
+ fieldPrec = -1;
break;
default:
@@ -3483,6 +3506,9 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
QString primaryKey = dsUri.keyColumn();
QString primaryKeyType;
+ QStringList pkList;
+ QStringList pkType;
+
QString schemaTableName = "";
if ( !schemaName.isEmpty() )
{
@@ -3520,48 +3546,45 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
fldIdx = -1; // it is incremented in the for loop, i.e. restarts at 0
}
}
+
+ pkList = QStringList( primaryKey );
+ pkType = QStringList( "serial" );
}
else
{
- // search for the passed field
- for ( int fldIdx = 0; fldIdx < fields.count(); ++fldIdx )
+ pkList = parseUriKey( primaryKey );
+ Q_FOREACH ( const QString& col, pkList )
{
- if ( fields[fldIdx].name() == primaryKey )
+ // search for the passed field
+ QString type;
+ for ( int fldIdx = 0; fldIdx < fields.count(); ++fldIdx )
{
- // found, get the field type
- QgsField fld = fields[fldIdx];
- if ( convertField( fld, options ) )
+ if ( fields[fldIdx].name() == col )
{
- primaryKeyType = fld.typeName();
+ // found, get the field type
+ QgsField fld = fields[fldIdx];
+ if ( convertField( fld, options ) )
+ {
+ type = fld.typeName();
+ break;
+ }
}
}
- }
- }
-
- // if the pk field doesn't exist yet, create a serial pk field
- // as it's autoincremental
- if ( primaryKeyType.isEmpty() )
- {
- primaryKeyType = "serial";
-#if 0
- // TODO: check the feature count to choose if create a serial8 pk field
- if ( layer->featureCount() > 0xffffffff )
- {
- primaryKeyType = "serial8";
- }
-#endif
- }
- else
- {
- // if the pk field's type is one of the postgres integer types,
- // use the equivalent autoincremental type (serialN)
- if ( primaryKeyType == "int2" || primaryKeyType == "int4" )
- {
- primaryKeyType = "serial";
- }
- else if ( primaryKeyType == "int8" )
- {
- primaryKeyType = "serial8";
+ if ( type.isEmpty() ) type = "serial";
+ else
+ {
+ // if the pk field's type is one of the postgres integer types,
+ // use the equivalent autoincremental type (serialN)
+ if ( primaryKeyType == "int2" || primaryKeyType == "int4" )
+ {
+ primaryKeyType = "serial";
+ }
+ else if ( primaryKeyType == "int8" )
+ {
+ primaryKeyType = "serial8";
+ }
+ }
+ pkType << type;
}
}
@@ -3597,17 +3620,32 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
throw PGException( result );
}
- if ( options && options->value( "lowercaseFieldNames", false ).toBool() )
+ sql = QString( "CREATE TABLE %1(" ) .arg( schemaTableName );
+ QString pk;
+ for ( int i = 0; i < pkList.size(); ++i )
{
- //convert primary key name to lowercase
- //this must happen after determining the field type of the primary key
- primaryKey = primaryKey.toLower();
- }
+ QString col = pkList[i];
+ const QString& type = pkType[i];
- sql = QString( "CREATE TABLE %1(%2 %3 PRIMARY KEY)" )
- .arg( schemaTableName,
- quotedIdentifier( primaryKey ),
- primaryKeyType );
+ if ( options && options->value( "lowercaseFieldNames", false ).toBool() )
+ {
+ col = col.toLower();
+ }
+ else
+ {
+ col = quotedIdentifier( col ); // no need to quote lowercase field
+ }
+
+ if ( i )
+ {
+ pk += ",";
+ sql += ",";
+ }
+
+ pk += col;
+ sql += col + " " + type;
+ }
+ sql += QString( ", PRIMARY KEY (%1) )" ) .arg( pk );
result = conn->PQexec( sql );
if ( result.PQresultStatus() != PGRES_COMMAND_OK )
@@ -3698,9 +3736,25 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
fld.setName( fld.name().toLower() );
}
- if ( fld.name() == primaryKey )
+ int pkIdx = -1;
+ for ( int i = 0; i < pkList.size(); ++i )
+ {
+ QString col = pkList[i];
+ if ( options && options->value( "lowercaseFieldNames", false ).toBool() )
+ {
+ //convert field name to lowercase (TODO: avoid doing this
+ //over and over)
+ col = col.toLower();
+ }
+ if ( fld.name() == col )
+ {
+ pkIdx = i;
+ break;
+ }
+ }
+ if ( pkIdx >= 0 )
{
- oldToNewAttrIdxMap->insert( fldIdx, 0 );
+ oldToNewAttrIdxMap->insert( fldIdx, pkIdx );
continue;
}
diff --git a/src/providers/postgres/qgspostgresprovider.h b/src/providers/postgres/qgspostgresprovider.h
index a058b95..3b55a11 100644
--- a/src/providers/postgres/qgspostgresprovider.h
+++ b/src/providers/postgres/qgspostgresprovider.h
@@ -119,6 +119,11 @@ class QgsPostgresProvider : public QgsVectorDataProvider
static QString endianString();
/**
+ * Returns a list of unquoted column names from an uri key
+ */
+ static QStringList parseUriKey( const QString& key );
+
+ /**
* Changes the stored extent for this layer to the supplied extent.
* For example, this is called when the extent worker thread has a result.
*/
@@ -132,11 +137,16 @@ class QgsPostgresProvider : public QgsVectorDataProvider
*/
virtual void updateExtents() override;
- /** Determine the fields making up the primary key
+ /**
+ * Determine the fields making up the primary key
*/
bool determinePrimaryKey();
- /** Determine the fields making up the primary key from the uri attribute keyColumn
+ /**
+ * Determine the fields making up the primary key from the uri attribute keyColumn
+ *
+ * Fills mPrimaryKeyType and mPrimaryKeyAttrs
+ * from mUri
*/
void determinePrimaryKeyFromUriKeyColumn();
diff --git a/src/providers/virtual/qgsvirtuallayersourceselectbase.ui b/src/providers/virtual/qgsvirtuallayersourceselectbase.ui
index f56c8de..ed38209 100644
--- a/src/providers/virtual/qgsvirtuallayersourceselectbase.ui
+++ b/src/providers/virtual/qgsvirtuallayersourceselectbase.ui
@@ -165,7 +165,7 @@ In particular, saving a virtual layer with embedded layers to a QLR file can be
<item>
<widget class="QgsCodeEditorSQL" name="mQueryEdit" native="true">
<property name="toolTip">
- <string><html><head/><body><p>This is the SQL query editor. You can edit here an SQL query refering to any existing vector layers or embedded layers.</p><p>Virtual layers rely on SQLite and Spatialite. Any functions from SQLite or Spatialite can then be used in the query. To add or access geometries of a table, you can use "tablename.geometry", regardless of original geometry column's name.</p><p><span style=" fon [...]
+ <string><html><head/><body><p>This is the SQL query editor. You can edit here an SQL query referring to any existing vector layers or embedded layers.</p><p>Virtual layers rely on SQLite and Spatialite. Any functions from SQLite or Spatialite can then be used in the query. To add or access geometries of a table, you can use "tablename.geometry", regardless of original geometry column's name.</p><p><span style=" fo [...]
</property>
</widget>
</item>
diff --git a/src/providers/wcs/qgswcscapabilities.cpp b/src/providers/wcs/qgswcscapabilities.cpp
index 6d9854a..f2723c1 100644
--- a/src/providers/wcs/qgswcscapabilities.cpp
+++ b/src/providers/wcs/qgswcscapabilities.cpp
@@ -158,6 +158,14 @@ bool QgsWcsCapabilities::sendRequest( QString const & url )
QgsDebugMsg( QString( "getcapabilities: %1" ).arg( url ) );
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+ if ( !setAuthorizationReply( mCapabilitiesReply ) )
+ {
+ mCapabilitiesReply->deleteLater();
+ mCapabilitiesReply = nullptr;
+ mError = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+ QgsMessageLog::logMessage( mError, tr( "WCS" ) );
+ return false;
+ }
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
@@ -368,6 +376,15 @@ void QgsWcsCapabilities::capabilitiesReplyFinished()
mCapabilitiesReply->deleteLater();
QgsDebugMsg( QString( "redirected getcapabilities: %1" ).arg( redirect.toString() ) );
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+ if ( !setAuthorizationReply( mCapabilitiesReply ) )
+ {
+ mCapabilitiesResponse.clear();
+ mCapabilitiesReply->deleteLater();
+ mCapabilitiesReply = nullptr;
+ mError = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+ QgsMessageLog::logMessage( mError, tr( "WCS" ) );
+ return;
+ }
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
@@ -394,6 +411,15 @@ void QgsWcsCapabilities::capabilitiesReplyFinished()
mCapabilitiesReply->deleteLater();
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+ if ( !setAuthorizationReply( mCapabilitiesReply ) )
+ {
+ mCapabilitiesResponse.clear();
+ mCapabilitiesReply->deleteLater();
+ mCapabilitiesReply = nullptr;
+ mError = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+ QgsMessageLog::logMessage( mError, tr( "WCS" ) );
+ return;
+ }
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
return;
@@ -1179,6 +1205,15 @@ bool QgsWcsCapabilities::setAuthorization( QNetworkRequest &request ) const
return true;
}
+bool QgsWcsCapabilities::setAuthorizationReply( QNetworkReply *reply ) const
+{
+ if ( mUri.hasParam( "authcfg" ) && !mUri.param( "authcfg" ).isEmpty() )
+ {
+ return QgsAuthManager::instance()->updateNetworkReply( reply, mUri.param( "authcfg" ) );
+ }
+ return true;
+}
+
void QgsWcsCapabilities::showMessageBox( const QString& title, const QString& text )
{
QgsMessageOutput *message = QgsMessageOutput::createMessageOutput();
diff --git a/src/providers/wcs/qgswcscapabilities.h b/src/providers/wcs/qgswcscapabilities.h
index d5ad6bc..dd95cd9 100644
--- a/src/providers/wcs/qgswcscapabilities.h
+++ b/src/providers/wcs/qgswcscapabilities.h
@@ -162,6 +162,9 @@ class QgsWcsCapabilities : public QObject
//! set authorization header
bool setAuthorization( QNetworkRequest &request ) const;
+ //! set authorization reply
+ bool setAuthorizationReply( QNetworkReply * reply ) const;
+
QString version() const { return mCapabilities.version; }
/**
diff --git a/src/providers/wcs/qgswcsprovider.cpp b/src/providers/wcs/qgswcsprovider.cpp
index 947fff9..542e993 100644
--- a/src/providers/wcs/qgswcsprovider.cpp
+++ b/src/providers/wcs/qgswcsprovider.cpp
@@ -508,9 +508,8 @@ void QgsWcsProvider::setQueryItem( QUrl &url, const QString& item, const QString
url.addQueryItem( item, value );
}
-void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight, void *block )
+void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight, void *block, QgsRasterBlockFeedback* feedback )
{
-
// TODO: set block to null values, move that to function and call only if fails
memset( block, 0, pixelWidth * pixelHeight * QgsRasterBlock::typeSize( dataType( bandNo ) ) );
@@ -528,7 +527,7 @@ void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
mCachedViewWidth != pixelWidth ||
mCachedViewHeight != pixelHeight )
{
- getCache( bandNo, viewExtent, pixelWidth, pixelHeight );
+ getCache( bandNo, viewExtent, pixelWidth, pixelHeight, QString(), feedback );
}
if ( mCachedGdalDataset )
@@ -627,7 +626,7 @@ void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
}
}
-void QgsWcsProvider::getCache( int bandNo, QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight, QString crs )
+void QgsWcsProvider::getCache( int bandNo, QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight, QString crs, QgsRasterBlockFeedback* feedback )
{
Q_UNUSED( bandNo );
// delete cached data
@@ -780,7 +779,7 @@ void QgsWcsProvider::getCache( int bandNo, QgsRectangle const & viewExtent, int
emit statusChanged( tr( "Getting map via WCS." ) );
- QgsWcsDownloadHandler handler( url, mAuth, mCacheLoadControl, mCachedData, mCapabilities.version(), mCachedError );
+ QgsWcsDownloadHandler handler( url, mAuth, mCacheLoadControl, mCachedData, mCapabilities.version(), mCachedError, feedback );
handler.blockingDownload();
QgsDebugMsg( QString( "%1 bytes received" ).arg( mCachedData.size() ) );
@@ -848,7 +847,7 @@ void QgsWcsProvider::readBlock( int theBandNo, int xBlock, int yBlock, void *blo
QgsRectangle extent( xMin, yMin, xMax, yMax );
- readBlock( theBandNo, extent, mXBlockSize, mYBlockSize, block );
+ readBlock( theBandNo, extent, mXBlockSize, mYBlockSize, block, nullptr );
}
@@ -1657,14 +1656,25 @@ QGISEXTERN bool isProvider()
int QgsWcsDownloadHandler::sErrors = 0;
-QgsWcsDownloadHandler::QgsWcsDownloadHandler( const QUrl& url, QgsWcsAuthorization& auth, QNetworkRequest::CacheLoadControl cacheLoadControl, QByteArray& cachedData, const QString& wcsVersion, QgsError& cachedError )
+QgsWcsDownloadHandler::QgsWcsDownloadHandler( const QUrl& url, QgsWcsAuthorization& auth, QNetworkRequest::CacheLoadControl cacheLoadControl, QByteArray& cachedData, const QString& wcsVersion, QgsError& cachedError, QgsRasterBlockFeedback* feedback )
: mAuth( auth )
, mEventLoop( new QEventLoop )
, mCacheReply( nullptr )
, mCachedData( cachedData )
, mWcsVersion( wcsVersion )
, mCachedError( cachedError )
+ , mFeedback( feedback )
{
+ if ( feedback )
+ {
+ connect( feedback, SIGNAL( cancelled() ), this, SLOT( cancelled() ), Qt::QueuedConnection );
+
+ // rendering could have been cancelled before we started to listen to cancelled() signal
+ // so let's check before doing the download and maybe quit prematurely
+ if ( feedback->isCancelled() )
+ return;
+ }
+
QNetworkRequest request( url );
if ( !mAuth.setAuthorization( request ) )
{
@@ -1676,6 +1686,15 @@ QgsWcsDownloadHandler::QgsWcsDownloadHandler( const QUrl& url, QgsWcsAuthorizati
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, cacheLoadControl );
mCacheReply = QgsNetworkAccessManager::instance()->get( request );
+ if ( !mAuth.setAuthorizationReply( mCacheReply ) )
+ {
+ mCacheReply->deleteLater();
+ mCacheReply = nullptr;
+ QgsMessageLog::logMessage( tr( "Network reply update failed for authentication config" ),
+ tr( "WCS" ) );
+ finish();
+ return;
+ }
connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ) );
connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ) );
}
@@ -1687,6 +1706,9 @@ QgsWcsDownloadHandler::~QgsWcsDownloadHandler()
void QgsWcsDownloadHandler::blockingDownload()
{
+ if ( mFeedback && mFeedback->isCancelled() )
+ return; // nothing to do
+
mEventLoop->exec( QEventLoop::ExcludeUserInputEvents );
Q_ASSERT( !mCacheReply );
@@ -1711,6 +1733,15 @@ void QgsWcsDownloadHandler::cacheReplyFinished()
return;
}
mCacheReply = QgsNetworkAccessManager::instance()->get( request );
+ if ( !mAuth.setAuthorizationReply( mCacheReply ) )
+ {
+ mCacheReply->deleteLater();
+ mCacheReply = nullptr;
+ QgsMessageLog::logMessage( tr( "Network reply update failed for authentication config" ),
+ tr( "WCS" ) );
+ finish();
+ return;
+ }
connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ) );
connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ) );
@@ -1865,30 +1896,43 @@ void QgsWcsDownloadHandler::cacheReplyFinished()
}
else
{
- // Resend request if AlwaysCache
- QNetworkRequest request = mCacheReply->request();
- if ( request.attribute( QNetworkRequest::CacheLoadControlAttribute ).toInt() == QNetworkRequest::AlwaysCache )
+ // report any errors except for the one we have caused by cancelling the request
+ if ( mCacheReply->error() != QNetworkReply::OperationCanceledError )
{
- QgsDebugMsg( "Resend request with PreferCache" );
- request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
+ // Resend request if AlwaysCache
+ QNetworkRequest request = mCacheReply->request();
+ if ( request.attribute( QNetworkRequest::CacheLoadControlAttribute ).toInt() == QNetworkRequest::AlwaysCache )
+ {
+ QgsDebugMsg( "Resend request with PreferCache" );
+ request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
- mCacheReply->deleteLater();
+ mCacheReply->deleteLater();
- mCacheReply = QgsNetworkAccessManager::instance()->get( request );
- connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ), Qt::DirectConnection );
- connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );
+ mCacheReply = QgsNetworkAccessManager::instance()->get( request );
+ if ( !mAuth.setAuthorizationReply( mCacheReply ) )
+ {
+ mCacheReply->deleteLater();
+ mCacheReply = nullptr;
+ QgsMessageLog::logMessage( tr( "Network reply update failed for authentication config" ),
+ tr( "WCS" ) );
+ finish();
+ return;
+ }
+ connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ), Qt::DirectConnection );
+ connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );
- return;
- }
+ return;
+ }
- sErrors++;
- if ( sErrors < 100 )
- {
- QgsMessageLog::logMessage( tr( "Map request failed [error:%1 url:%2]" ).arg( mCacheReply->errorString(), mCacheReply->url().toString() ), tr( "WCS" ) );
- }
- else if ( sErrors == 100 )
- {
- QgsMessageLog::logMessage( tr( "Not logging more than 100 request errors." ), tr( "WCS" ) );
+ sErrors++;
+ if ( sErrors < 100 )
+ {
+ QgsMessageLog::logMessage( tr( "Map request failed [error:%1 url:%2]" ).arg( mCacheReply->errorString(), mCacheReply->url().toString() ), tr( "WCS" ) );
+ }
+ else if ( sErrors == 100 )
+ {
+ QgsMessageLog::logMessage( tr( "Not logging more than 100 request errors." ), tr( "WCS" ) );
+ }
}
mCacheReply->deleteLater();
@@ -1904,3 +1948,13 @@ void QgsWcsDownloadHandler::cacheReplyProgress( qint64 bytesReceived, qint64 byt
Q_UNUSED( bytesTotal );
QgsDebugMsgLevel( tr( "%1 of %2 bytes of map downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QString( "unknown number of" ) : QString::number( bytesTotal ) ), 3 );
}
+
+void QgsWcsDownloadHandler::cancelled()
+{
+ QgsDebugMsg( "Caught cancelled() signal" );
+ if ( mCacheReply )
+ {
+ QgsDebugMsg( "Aborting WCS network request" );
+ mCacheReply->abort();
+ }
+}
diff --git a/src/providers/wcs/qgswcsprovider.h b/src/providers/wcs/qgswcsprovider.h
index f2c3342..5880868 100644
--- a/src/providers/wcs/qgswcsprovider.h
+++ b/src/providers/wcs/qgswcsprovider.h
@@ -71,6 +71,16 @@ struct QgsWcsAuthorization
return true;
}
+ //! set authorization reply
+ bool setAuthorizationReply( QNetworkReply * reply ) const
+ {
+ if ( !mAuthCfg.isEmpty() )
+ {
+ return QgsAuthManager::instance()->updateNetworkReply( reply, mAuthCfg );
+ }
+ return true;
+ }
+
//! Username for basic http authentication
QString mUserName;
@@ -149,12 +159,12 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
*/
QImage *draw( QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight ) override;
- void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data ) override;
+ void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data, QgsRasterBlockFeedback* feedback = nullptr ) override;
void readBlock( int theBandNo, int xBlock, int yBlock, void *block ) override;
/** Download cache */
- void getCache( int bandNo, QgsRectangle const & viewExtent, int width, int height, QString crs = "" );
+ void getCache( int bandNo, QgsRectangle const & viewExtent, int width, int height, QString crs = "", QgsRasterBlockFeedback* feedback = nullptr );
/** Return the extent for this data layer
*/
@@ -419,7 +429,7 @@ class QgsWcsDownloadHandler : public QObject
{
Q_OBJECT
public:
- QgsWcsDownloadHandler( const QUrl& url, QgsWcsAuthorization& auth, QNetworkRequest::CacheLoadControl cacheLoadControl, QByteArray& cachedData, const QString& wcsVersion, QgsError& cachedError );
+ QgsWcsDownloadHandler( const QUrl& url, QgsWcsAuthorization& auth, QNetworkRequest::CacheLoadControl cacheLoadControl, QByteArray& cachedData, const QString& wcsVersion, QgsError& cachedError, QgsRasterBlockFeedback* feedback );
~QgsWcsDownloadHandler();
void blockingDownload();
@@ -427,6 +437,7 @@ class QgsWcsDownloadHandler : public QObject
protected slots:
void cacheReplyFinished();
void cacheReplyProgress( qint64, qint64 );
+ void cancelled();
protected:
void finish() { QMetaObject::invokeMethod( mEventLoop, "quit", Qt::QueuedConnection ); }
@@ -440,6 +451,8 @@ class QgsWcsDownloadHandler : public QObject
QString mWcsVersion;
QgsError& mCachedError;
+ QgsRasterBlockFeedback* mFeedback;
+
static int sErrors; // this should be ideally per-provider...?
};
diff --git a/src/providers/wfs/qgswfscapabilities.cpp b/src/providers/wfs/qgswfscapabilities.cpp
index ec83cd2..4934226 100644
--- a/src/providers/wfs/qgswfscapabilities.cpp
+++ b/src/providers/wfs/qgswfscapabilities.cpp
@@ -36,7 +36,7 @@ QgsWFSCapabilities::~QgsWFSCapabilities()
{
}
-bool QgsWFSCapabilities::requestCapabilities( bool synchronous )
+bool QgsWFSCapabilities::requestCapabilities( bool synchronous, bool forceRefresh )
{
QUrl url( baseURL() );
url.addQueryItem( "REQUEST", "GetCapabilities" );
@@ -48,7 +48,7 @@ bool QgsWFSCapabilities::requestCapabilities( bool synchronous )
else
url.addQueryItem( "VERSION", version );
- if ( !sendGET( url, synchronous, false ) )
+ if ( !sendGET( url, synchronous, forceRefresh ) )
{
emit gotCapabilities();
return false;
diff --git a/src/providers/wfs/qgswfscapabilities.h b/src/providers/wfs/qgswfscapabilities.h
index 4b51a1c..9b67e56 100644
--- a/src/providers/wfs/qgswfscapabilities.h
+++ b/src/providers/wfs/qgswfscapabilities.h
@@ -30,7 +30,7 @@ class QgsWFSCapabilities : public QgsWFSRequest
virtual ~QgsWFSCapabilities();
//! start network connection to get capabilities
- bool requestCapabilities( bool synchronous );
+ bool requestCapabilities( bool synchronous, bool forceRefresh );
//! description of a vector layer
struct FeatureType
diff --git a/src/providers/wfs/qgswfsconstants.cpp b/src/providers/wfs/qgswfsconstants.cpp
index 2aecf3e..87ff72f 100644
--- a/src/providers/wfs/qgswfsconstants.cpp
+++ b/src/providers/wfs/qgswfsconstants.cpp
@@ -31,7 +31,7 @@ const QString QgsWFSConstants::URI_PARAM_TYPENAME( "typename" );
const QString QgsWFSConstants::URI_PARAM_SRSNAME( "srsname" );
const QString QgsWFSConstants::URI_PARAM_BBOX( "bbox" );
const QString QgsWFSConstants::URI_PARAM_FILTER( "filter" );
-const QString QgsWFSConstants::URI_PARAM_RESTRICT_TO_REQUEST_BBOX( "retrictToRequestBBOX" );
+const QString QgsWFSConstants::URI_PARAM_RESTRICT_TO_REQUEST_BBOX( "restrictToRequestBBOX" );
const QString QgsWFSConstants::URI_PARAM_MAXNUMFEATURES( "maxNumFeatures" );
const QString QgsWFSConstants::URI_PARAM_IGNOREAXISORIENTATION( "IgnoreAxisOrientation" );
const QString QgsWFSConstants::URI_PARAM_INVERTAXISORIENTATION( "InvertAxisOrientation" );
diff --git a/src/providers/wfs/qgswfsdataitems.cpp b/src/providers/wfs/qgswfsdataitems.cpp
index a2acbd1..e8b53a6 100644
--- a/src/providers/wfs/qgswfsdataitems.cpp
+++ b/src/providers/wfs/qgswfsdataitems.cpp
@@ -62,7 +62,9 @@ QVector<QgsDataItem*> QgsWFSConnectionItem::createChildren()
QgsWFSCapabilities capabilities( mUri );
- capabilities.requestCapabilities( true );
+ const bool synchronous = true;
+ const bool forceRefresh = false;
+ capabilities.requestCapabilities( synchronous, forceRefresh );
QVector<QgsDataItem*> layers;
if ( capabilities.errorCode() == QgsWFSCapabilities::NoError )
diff --git a/src/providers/wfs/qgswfsdatasourceuri.cpp b/src/providers/wfs/qgswfsdatasourceuri.cpp
index 337563b..67d21cc 100644
--- a/src/providers/wfs/qgswfsdatasourceuri.cpp
+++ b/src/providers/wfs/qgswfsdatasourceuri.cpp
@@ -41,14 +41,19 @@ QgsWFSDataSourceURI::QgsWFSDataSourceURI( const QString& uri )
QString typeName = url.queryItemValue( QgsWFSConstants::URI_PARAM_TYPENAME );
QString version = url.queryItemValue( QgsWFSConstants::URI_PARAM_VERSION );
QString filter = url.queryItemValue( QgsWFSConstants::URI_PARAM_FILTER );
- mAuth.mUserName = url.queryItemValue( QgsWFSConstants::URI_PARAM_USERNAME );
- // In QgsDataSourceURI, the "username" param is named "user", check it
- if ( mAuth.mUserName.isEmpty() )
+ mAuth.mAuthCfg = url.queryItemValue( QgsWFSConstants::URI_PARAM_AUTHCFG );
+ // NOTE: A defined authcfg overrides any older username/password auth
+ // Only check for older auth if it is undefined
+ if ( mAuth.mAuthCfg.isEmpty() )
{
- mAuth.mUserName = url.queryItemValue( QgsWFSConstants::URI_PARAM_USER );
+ mAuth.mUserName = url.queryItemValue( QgsWFSConstants::URI_PARAM_USERNAME );
+ // In QgsDataSourceURI, the "username" param is named "user", check it
+ if ( mAuth.mUserName.isEmpty() )
+ {
+ mAuth.mUserName = url.queryItemValue( QgsWFSConstants::URI_PARAM_USER );
+ }
+ mAuth.mPassword = url.queryItemValue( QgsWFSConstants::URI_PARAM_PASSWORD );
}
- mAuth.mPassword = url.queryItemValue( QgsWFSConstants::URI_PARAM_PASSWORD );
- mAuth.mAuthCfg = url.queryItemValue( QgsWFSConstants::URI_PARAM_AUTHCFG );
// Now remove all stuff that is not the core URL
url.removeQueryItem( "SERVICE" );
@@ -90,19 +95,24 @@ QgsWFSDataSourceURI::QgsWFSDataSourceURI( const QString& uri )
const QString QgsWFSDataSourceURI::uri( bool expandAuthConfig ) const
{
QgsDataSourceURI theURI( mURI );
- // Add auth params back into the uri
+ // Add authcfg param back into the uri (must be non-empty value)
if ( ! mAuth.mAuthCfg.isEmpty() )
{
theURI.setAuthConfigId( mAuth.mAuthCfg );
}
- if ( ! mAuth.mUserName.isEmpty() )
- {
- theURI.setUsername( mAuth.mUserName );
- }
- if ( ! mAuth.mPassword.isEmpty() )
+ else
{
- theURI.setPassword( mAuth.mPassword );
+ // Add any older username/password auth params back in (allow empty values)
+ if ( ! mAuth.mUserName.isNull() )
+ {
+ theURI.setUsername( mAuth.mUserName );
+ }
+ if ( ! mAuth.mPassword.isNull() )
+ {
+ theURI.setPassword( mAuth.mPassword );
+ }
}
+ // NOTE: avoid expanding authcfg here; it is handled during network access
return theURI.uri( expandAuthConfig );
}
@@ -193,8 +203,15 @@ void QgsWFSDataSourceURI::setSql( const QString& sql )
bool QgsWFSDataSourceURI::isRestrictedToRequestBBOX() const
{
- return mURI.hasParam( QgsWFSConstants::URI_PARAM_RESTRICT_TO_REQUEST_BBOX ) &&
- mURI.param( QgsWFSConstants::URI_PARAM_RESTRICT_TO_REQUEST_BBOX ).toInt() == 1;
+ if ( mURI.hasParam( QgsWFSConstants::URI_PARAM_RESTRICT_TO_REQUEST_BBOX ) &&
+ mURI.param( QgsWFSConstants::URI_PARAM_RESTRICT_TO_REQUEST_BBOX ).toInt() == 1 )
+ return true;
+
+ // accept previously used version with typo
+ if ( mURI.hasParam( "retrictToRequestBBOX" ) && mURI.param( "retrictToRequestBBOX" ).toInt() == 1 )
+ return true;
+
+ return false;
}
bool QgsWFSDataSourceURI::ignoreAxisOrientation() const
diff --git a/src/providers/wfs/qgswfsdatasourceuri.h b/src/providers/wfs/qgswfsdatasourceuri.h
index 7375068..d703fa9 100644
--- a/src/providers/wfs/qgswfsdatasourceuri.h
+++ b/src/providers/wfs/qgswfsdatasourceuri.h
@@ -32,20 +32,30 @@ struct QgsWFSAuthorization
, mAuthCfg( authcfg )
{}
- //! set authorization header
+ //! update authorization for request
bool setAuthorization( QNetworkRequest &request ) const
{
- if ( !mAuthCfg.isEmpty() )
+ if ( !mAuthCfg.isEmpty() ) // must be non-empty value
{
return QgsAuthManager::instance()->updateNetworkRequest( request, mAuthCfg );
}
- else if ( !mUserName.isNull() || !mPassword.isNull() )
+ else if ( !mUserName.isNull() || !mPassword.isNull() ) // allow empty values
{
request.setRawHeader( "Authorization", "Basic " + QString( "%1:%2" ).arg( mUserName, mPassword ).toAscii().toBase64() );
}
return true;
}
+ //! update authorization for reply
+ bool setAuthorizationReply( QNetworkReply *reply ) const
+ {
+ if ( !mAuthCfg.isEmpty() )
+ {
+ return QgsAuthManager::instance()->updateNetworkReply( reply, mAuthCfg );
+ }
+ return true;
+ }
+
//! Username for basic http authentication
QString mUserName;
@@ -65,8 +75,8 @@ class QgsWFSDataSourceURI
explicit QgsWFSDataSourceURI( const QString& uri );
- /** Return the URI */
- const QString uri( bool expandAuthConfig = true ) const;
+ /** Return the URI, avoiding expansion of authentication configuration, which is handled during network access */
+ const QString uri( bool expandAuthConfig = false ) const;
/** Return base URL (with SERVICE=WFS parameter if bIncludeServiceWFS=true) */
QUrl baseURL( bool bIncludeServiceWFS = true ) const;
diff --git a/src/providers/wfs/qgswfsfeatureiterator.cpp b/src/providers/wfs/qgswfsfeatureiterator.cpp
index f208c92..356aa7e 100644
--- a/src/providers/wfs/qgswfsfeatureiterator.cpp
+++ b/src/providers/wfs/qgswfsfeatureiterator.cpp
@@ -310,7 +310,12 @@ QUrl QgsWFSFeatureDownloader::buildURL( int startIndex, int maxFeatures, bool fo
qgsDoubleToString( mShared->mRect.yMaximum() ) ) );
// Some servers like Geomedia need the srsname to be explictly appended
// otherwise they are confused and do not interpret it properly
- bbox += "," + mShared->srsName();
+ if ( !mShared->mWFSVersion.startsWith( "1.0" ) )
+ {
+ // but it is illegal in WFS 1.0 and some servers definitely not like
+ // it. See #15464
+ bbox += "," + mShared->srsName();
+ }
getFeatureUrl.addQueryItem( "BBOX", bbox );
}
else if ( !mShared->mWFSFilter.isEmpty() )
diff --git a/src/providers/wfs/qgswfsprovider.cpp b/src/providers/wfs/qgswfsprovider.cpp
index 17617ac..0bc9f07 100644
--- a/src/providers/wfs/qgswfsprovider.cpp
+++ b/src/providers/wfs/qgswfsprovider.cpp
@@ -1101,7 +1101,7 @@ bool QgsWFSProvider::describeFeatureType( QString& geometryAttribute, QgsFields&
{
fields.clear();
- QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI.uri( false ) );
+ QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI.uri() );
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
mShared->mURI.typeName() ) )
{
@@ -1246,8 +1246,15 @@ bool QgsWFSProvider::readAttributesFromSchema( QDomDocument& schemaDoc,
for ( int i = 0; i < attributeNodeList.size(); ++i )
{
QDomElement attributeElement = attributeNodeList.at( i ).toElement();
+
//attribute name
QString name = attributeElement.attribute( "name" );
+ // Some servers like http://ogi.state.ok.us/geoserver/wfs on layer ogi:doq_centroids
+ // return attribute names padded with spaces. See http://hub.qgis.org/issues/3426
+ // I'm not completely sure how legal this
+ // is but this validates with Xerces 3.1, and its schema analyzer does also the trimming.
+ name = name.trimmed();
+
//attribute type
QString type = attributeElement.attribute( "type" );
if ( type.isEmpty() )
@@ -1330,7 +1337,7 @@ bool QgsWFSProvider::sendTransactionDocument( const QDomDocument& doc, QDomDocum
return false;
}
- QgsWFSTransactionRequest request( mShared->mURI.uri( false ) );
+ QgsWFSTransactionRequest request( mShared->mURI.uri() );
return request.send( doc, serverResponse );
}
@@ -1433,8 +1440,10 @@ bool QgsWFSProvider::getCapabilities()
if ( mShared->mCaps.version.isEmpty() )
{
- QgsWFSCapabilities getCapabilities( mShared->mURI.uri( false ) );
- if ( !getCapabilities.requestCapabilities( true ) )
+ QgsWFSCapabilities getCapabilities( mShared->mURI.uri() );
+ const bool synchronous = true;
+ const bool forceRefresh = false;
+ if ( !getCapabilities.requestCapabilities( synchronous, forceRefresh ) )
{
QgsMessageLog::logMessage( tr( "GetCapabilities failed for url %1: %2" ).
arg( dataSourceUri() ).arg( getCapabilities.errorMessage() ), tr( "WFS" ) );
diff --git a/src/providers/wfs/qgswfsrequest.cpp b/src/providers/wfs/qgswfsrequest.cpp
index 237f6cd..b725fbb 100644
--- a/src/providers/wfs/qgswfsrequest.cpp
+++ b/src/providers/wfs/qgswfsrequest.cpp
@@ -116,6 +116,13 @@ bool QgsWFSRequest::sendGET( const QUrl& url, bool synchronous, bool forceRefres
}
mReply = QgsNetworkAccessManager::instance()->get( request );
+ if ( !mUri.auth().setAuthorizationReply( mReply ) )
+ {
+ mErrorCode = QgsWFSRequest::NetworkError;
+ mErrorMessage = errorMessageFailedAuth();
+ QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
+ return false;
+ }
connect( mReply, SIGNAL( finished() ), this, SLOT( replyFinished() ) );
connect( mReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( replyProgress( qint64, qint64 ) ) );
@@ -160,6 +167,13 @@ bool QgsWFSRequest::sendPOST( const QUrl& url, const QString& contentTypeHeader,
request.setHeader( QNetworkRequest::ContentTypeHeader, contentTypeHeader );
mReply = QgsNetworkAccessManager::instance()->post( request, data );
+ if ( !mUri.auth().setAuthorizationReply( mReply ) )
+ {
+ mErrorCode = QgsWFSRequest::NetworkError;
+ mErrorMessage = errorMessageFailedAuth();
+ QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
+ return false;
+ }
connect( mReply, SIGNAL( finished() ), this, SLOT( replyFinished() ) );
connect( mReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( replyProgress( qint64, qint64 ) ) );
@@ -243,6 +257,15 @@ void QgsWFSRequest::replyFinished()
QgsDebugMsg( QString( "redirected: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ) );
mReply = QgsNetworkAccessManager::instance()->get( request );
+ if ( !mUri.auth().setAuthorizationReply( mReply ) )
+ {
+ mResponse.clear();
+ mErrorMessage = errorMessageFailedAuth();
+ mErrorCode = QgsWFSRequest::NetworkError;
+ QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
+ emit downloadFinished();
+ return;
+ }
connect( mReply, SIGNAL( finished() ), this, SLOT( replyFinished() ) );
connect( mReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( replyProgress( qint64, qint64 ) ) );
return;
diff --git a/src/providers/wfs/qgswfssourceselect.cpp b/src/providers/wfs/qgswfssourceselect.cpp
index e269e12..6c00cd2 100644
--- a/src/providers/wfs/qgswfssourceselect.cpp
+++ b/src/providers/wfs/qgswfssourceselect.cpp
@@ -354,7 +354,9 @@ void QgsWFSSourceSelect::connectToServer()
}
if ( mCapabilities )
{
- mCapabilities->requestCapabilities( false );
+ const bool synchronous = false;
+ const bool forceRefresh = true;
+ mCapabilities->requestCapabilities( synchronous, forceRefresh );
}
}
diff --git a/src/providers/wfs/qgswfsutils.cpp b/src/providers/wfs/qgswfsutils.cpp
index 8a635b0..92aa995 100644
--- a/src/providers/wfs/qgswfsutils.cpp
+++ b/src/providers/wfs/qgswfsutils.cpp
@@ -37,7 +37,9 @@ int QgsWFSUtils::gmCounter = 0;
QString QgsWFSUtils::getBaseCacheDirectory( bool createIfNotExisting )
{
QSettings settings;
- QString cacheDirectory = settings.value( "cache/directory", QgsApplication::qgisSettingsDirPath() + "cache" ).toString();
+ QString cacheDirectory = settings.value( "cache/directory" ).toString();
+ if ( cacheDirectory.isEmpty() )
+ cacheDirectory = QgsApplication::qgisSettingsDirPath() + "cache";
if ( createIfNotExisting )
{
QMutexLocker locker( &gmMutex );
diff --git a/src/providers/wms/CMakeLists.txt b/src/providers/wms/CMakeLists.txt
index bc19de4..7a57c85 100644
--- a/src/providers/wms/CMakeLists.txt
+++ b/src/providers/wms/CMakeLists.txt
@@ -9,8 +9,10 @@ SET (WMS_SRCS
qgswmssourceselect.cpp
qgswmsconnection.cpp
qgswmsdataitems.cpp
+ qgstilecache.cpp
qgstilescalewidget.cpp
qgswmtsdimensions.cpp
+ qgsxyzconnection.cpp
)
SET (WMS_MOC_HDRS
qgswmscapabilities.h
diff --git a/src/providers/wms/qgstilecache.cpp b/src/providers/wms/qgstilecache.cpp
new file mode 100644
index 0000000..2cc94ef
--- /dev/null
+++ b/src/providers/wms/qgstilecache.cpp
@@ -0,0 +1,57 @@
+/***************************************************************************
+ qgstilecache.h
+ --------------------------------------
+ Date : September 2016
+ Copyright : (C) 2016 by Martin Dobias
+ Email : wonder dot sk at gmail dot com
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "qgstilecache.h"
+
+#include "qgsnetworkaccessmanager.h"
+
+#include <QAbstractNetworkCache>
+#include <QImage>
+
+QCache<QUrl, QImage> QgsTileCache::sTileCache( 256 );
+QMutex QgsTileCache::sTileCacheMutex;
+
+
+void QgsTileCache::insertTile( const QUrl& url, const QImage& image )
+{
+ QMutexLocker locker( &sTileCacheMutex );
+ sTileCache.insert( url, new QImage( image ) );
+}
+
+bool QgsTileCache::tile( const QUrl& url, QImage& image )
+{
+ QMutexLocker locker( &sTileCacheMutex );
+ if ( QImage* i = sTileCache.object( url ) )
+ {
+ image = *i;
+ return true;
+ }
+ else if ( QgsNetworkAccessManager::instance()->cache()->metaData( url ).isValid() )
+ {
+ if ( QIODevice* data = QgsNetworkAccessManager::instance()->cache()->data( url ) )
+ {
+ QByteArray imageData = data->readAll();
+ delete data;
+
+ image = QImage::fromData( imageData );
+
+ // cache it as well (mutex is already locked)
+ sTileCache.insert( url, new QImage( image ) );
+
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/src/providers/wms/qgstilecache.h b/src/providers/wms/qgstilecache.h
new file mode 100644
index 0000000..39e5496
--- /dev/null
+++ b/src/providers/wms/qgstilecache.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ qgstilecache.h
+ --------------------------------------
+ Date : September 2016
+ Copyright : (C) 2016 by Martin Dobias
+ Email : wonder dot sk at gmail dot com
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSTILECACHE_H
+#define QGSTILECACHE_H
+
+
+#include <QCache>
+#include <QMutex>
+
+class QImage;
+class QUrl;
+
+/** A simple tile cache implementation. Tiles are cached according to their URL.
+ * There is a small in-memory cache and a secondary caching in the local disk.
+ * The in-memory cache is there to save CPU time otherwise wasted to read and
+ * uncompress data saved on the disk.
+ *
+ * The class is thread safe (its methods can be called from any thread).
+ */
+class QgsTileCache
+{
+ public:
+
+ //! Add a tile image with given URL to the cache
+ static void insertTile( const QUrl& url, const QImage& image );
+
+ //! Try to access a tile and load it into "image" argument
+ //! @returns true if the tile exists in the cache
+ static bool tile( const QUrl& url, QImage& image );
+
+ //! how many tiles are stored in the in-memory cache
+ static int totalCost() { return sTileCache.totalCost(); }
+ //! how many tiles can be stored in the in-memory cache
+ static int maxCost() { return sTileCache.maxCost(); }
+
+ private:
+ //! in-memory cache
+ static QCache<QUrl, QImage> sTileCache;
+ //! mutex to protect the in-memory cache
+ static QMutex sTileCacheMutex;
+};
+
+#endif // QGSTILECACHE_H
diff --git a/src/providers/wms/qgswmscapabilities.cpp b/src/providers/wms/qgswmscapabilities.cpp
index 387ec48..9b5f12b 100644
--- a/src/providers/wms/qgswmscapabilities.cpp
+++ b/src/providers/wms/qgswmscapabilities.cpp
@@ -41,6 +41,37 @@ bool QgsWmsSettings::parseUri( const QString& uriString )
QgsDataSourceURI uri;
uri.setEncodedUri( uriString );
+ mXyz = false; // assume WMS / WMTS
+
+ if ( uri.param( "type" ) == "xyz" )
+ {
+ // for XYZ tiles most of the things do not apply
+ mTiled = true;
+ mXyz = true;
+ mTileDimensionValues.clear();
+ mTileMatrixSetId = "tms0";
+ mMaxWidth = 0;
+ mMaxHeight = 0;
+ mHttpUri = uri.param( "url" );
+ mBaseUrl = mHttpUri;
+ mAuth.mUserName.clear();
+ mAuth.mPassword.clear();
+ mAuth.mReferer.clear();
+ mAuth.mAuthCfg.clear();
+ mIgnoreGetMapUrl = false;
+ mIgnoreGetFeatureInfoUrl = false;
+ mSmoothPixmapTransform = true;
+ mDpiMode = dpiNone; // does not matter what we set here
+ mActiveSubLayers = QStringList( "xyz" ); // just a placeholder to have one sub-layer
+ mActiveSubStyles = QStringList( "xyz" ); // just a placeholder to have one sub-style
+ mActiveSubLayerVisibility.clear();
+ mFeatureCount = 0;
+ mImageMimeType.clear();
+ mCrsId = "EPSG:3857";
+ mEnableContextualLegend = false;
+ return true;
+ }
+
mTiled = false;
mTileDimensionValues.clear();
@@ -1259,6 +1290,7 @@ void QgsWmsCapabilities::parseTileSetProfile( QDomElement const &e )
m.matrixWidth = ceil( l.boundingBoxes.at( 0 ).box.width() / m.tileWidth / r );
m.matrixHeight = ceil( l.boundingBoxes.at( 0 ).box.height() / m.tileHeight / r );
m.topLeft = QgsPoint( l.boundingBoxes.at( 0 ).box.xMinimum(), l.boundingBoxes.at( 0 ).box.yMinimum() + m.matrixHeight * m.tileHeight * r );
+ m.tres = r;
ms.tileMatrices.insert( r, m );
i++;
}
@@ -1341,17 +1373,19 @@ void QgsWmsCapabilities::parseWMTSContents( QDomElement const &e )
m.matrixWidth = e1.firstChildElement( "MatrixWidth" ).text().toInt();
m.matrixHeight = e1.firstChildElement( "MatrixHeight" ).text().toInt();
- double res = m.scaleDenom * 0.00028 / metersPerUnit;
+ // the magic number below is "standardized rendering pixel size" defined
+ // in WMTS (and WMS 1.3) standard, being 0.28 pixel
+ m.tres = m.scaleDenom * 0.00028 / metersPerUnit;
QgsDebugMsg( QString( " %1: scale=%2 res=%3 tile=%4x%5 matrix=%6x%7 topLeft=%8" )
.arg( m.identifier )
- .arg( m.scaleDenom ).arg( res )
+ .arg( m.scaleDenom ).arg( m.tres )
.arg( m.tileWidth ).arg( m.tileHeight )
.arg( m.matrixWidth ).arg( m.matrixHeight )
.arg( m.topLeft.toString() )
);
- s.tileMatrices.insert( res, m );
+ s.tileMatrices.insert( m.tres, m );
}
mTileMatrixSets.insert( s.identifier, s );
@@ -1798,6 +1832,8 @@ bool QgsWmsCapabilities::detectTileLayerBoundingBox( QgsWmtsTileLayer& l )
const QgsWmtsTileMatrix& tm = *tmIt;
double metersPerUnit = QgsUnitTypes::fromUnitToUnitFactor( crs.mapUnits(), QGis::Meters );
+ // the magic number below is "standardized rendering pixel size" defined
+ // in WMTS (and WMS 1.3) standard, being 0.28 pixel
double res = tm.scaleDenom * 0.00028 / metersPerUnit;
QgsPoint bottomRight( tm.topLeft.x() + res * tm.tileWidth * tm.matrixWidth,
tm.topLeft.y() - res * tm.tileHeight * tm.matrixHeight );
@@ -1920,6 +1956,14 @@ bool QgsWmsCapabilitiesDownload::downloadCapabilities()
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+ if ( !mAuth.setAuthorizationReply( mCapabilitiesReply ) )
+ {
+ mCapabilitiesReply->deleteLater();
+ mCapabilitiesReply = nullptr;
+ mError = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+ QgsMessageLog::logMessage( mError, tr( "WMS" ) );
+ return false;
+ }
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ), Qt::DirectConnection );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );
@@ -1986,6 +2030,18 @@ void QgsWmsCapabilitiesDownload::capabilitiesReplyFinished()
QgsDebugMsg( QString( "redirected getcapabilities: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ) );
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
+
+ if ( !mAuth.setAuthorizationReply( mCapabilitiesReply ) )
+ {
+ mHttpCapabilitiesResponse.clear();
+ mCapabilitiesReply->deleteLater();
+ mCapabilitiesReply = nullptr;
+ mError = tr( "Download of capabilities failed: network reply update failed for authentication config" );
+ QgsMessageLog::logMessage( mError, tr( "WMS" ) );
+ emit downloadFinished();
+ return;
+ }
+
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ), Qt::DirectConnection );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );
return;
@@ -2050,3 +2106,97 @@ void QgsWmsCapabilitiesDownload::capabilitiesReplyFinished()
emit downloadFinished();
}
+
+QRectF QgsWmtsTileMatrix::tileRect( int col, int row ) const
+{
+ double twMap = tileWidth * tres;
+ double thMap = tileHeight * tres;
+ return QRectF( topLeft.x() + col * twMap, topLeft.y() - ( row + 1 ) * thMap, twMap, thMap );
+}
+
+QgsRectangle QgsWmtsTileMatrix::tileBBox( int col, int row ) const
+{
+ double twMap = tileWidth * tres;
+ double thMap = tileHeight * tres;
+ return QgsRectangle(
+ topLeft.x() + col * twMap,
+ topLeft.y() - ( row + 1 ) * thMap,
+ topLeft.x() + ( col + 1 ) * twMap,
+ topLeft.y() - row * thMap );
+}
+
+void QgsWmtsTileMatrix::viewExtentIntersection( const QgsRectangle &viewExtent, const QgsWmtsTileMatrixLimits* tml, int &col0, int &row0, int &col1, int &row1 ) const
+{
+ double twMap = tileWidth * tres;
+ double thMap = tileHeight * tres;
+
+ int minTileCol = 0;
+ int maxTileCol = matrixWidth - 1;
+ int minTileRow = 0;
+ int maxTileRow = matrixHeight - 1;
+
+ if ( tml )
+ {
+ minTileCol = tml->minTileCol;
+ maxTileCol = tml->maxTileCol;
+ minTileRow = tml->minTileRow;
+ maxTileRow = tml->maxTileRow;
+ //QgsDebugMsg( QString( "%1 %2: TileMatrixLimits col %3-%4 row %5-%6" )
+ // .arg( tileMatrixSet->identifier, identifier )
+ // .arg( minTileCol ).arg( maxTileCol )
+ // .arg( minTileRow ).arg( maxTileRow ) );
+ }
+
+ col0 = qBound( minTileCol, ( int ) floor(( viewExtent.xMinimum() - topLeft.x() ) / twMap ), maxTileCol );
+ row0 = qBound( minTileRow, ( int ) floor(( topLeft.y() - viewExtent.yMaximum() ) / thMap ), maxTileRow );
+ col1 = qBound( minTileCol, ( int ) floor(( viewExtent.xMaximum() - topLeft.x() ) / twMap ), maxTileCol );
+ row1 = qBound( minTileRow, ( int ) floor(( topLeft.y() - viewExtent.yMinimum() ) / thMap ), maxTileRow );
+}
+
+const QgsWmtsTileMatrix* QgsWmtsTileMatrixSet::findNearestResolution( double vres ) const
+{
+ QMap<double, QgsWmtsTileMatrix>::const_iterator prev, it = tileMatrices.constBegin();
+ while ( it != tileMatrices.constEnd() && it.key() < vres )
+ {
+ //QgsDebugMsg( QString( "res:%1 >= %2" ).arg( it.key() ).arg( vres ) );
+ prev = it;
+ ++it;
+ }
+
+ if ( it == tileMatrices.constEnd() ||
+ ( it != tileMatrices.constBegin() && vres - prev.key() < it.key() - vres ) )
+ {
+ //QgsDebugMsg( "back to previous res" );
+ it = prev;
+ }
+
+ return &it.value();
+}
+
+const QgsWmtsTileMatrix *QgsWmtsTileMatrixSet::findOtherResolution( double tres, int offset ) const
+{
+ QMap<double, QgsWmtsTileMatrix>::const_iterator it = tileMatrices.constFind( tres );
+ if ( it == tileMatrices.constEnd() )
+ return nullptr;
+ while ( 1 )
+ {
+ if ( offset > 0 )
+ {
+ ++it;
+ --offset;
+ }
+ else if ( offset < 0 )
+ {
+ if ( it == tileMatrices.constBegin() )
+ return nullptr;
+ --it;
+ ++offset;
+ }
+ else
+ break;
+
+ if ( it == tileMatrices.constEnd() )
+ return nullptr;
+ }
+ return &it.value();
+}
diff --git a/src/providers/wms/qgswmscapabilities.h b/src/providers/wms/qgswmscapabilities.h
index 66f8b25..f219a10 100644
--- a/src/providers/wms/qgswmscapabilities.h
+++ b/src/providers/wms/qgswmscapabilities.h
@@ -308,30 +308,54 @@ struct QgsWmtsTheme
~QgsWmtsTheme() { delete subTheme; }
};
+struct QgsWmtsTileMatrixLimits;
+
struct QgsWmtsTileMatrix
{
QString identifier;
QString title, abstract;
QStringList keywords;
double scaleDenom;
- QgsPoint topLeft;
- int tileWidth;
- int tileHeight;
- int matrixWidth;
- int matrixHeight;
+ QgsPoint topLeft; //!< top-left corner of the tile matrix in map units
+ int tileWidth; //!< width of a tile in pixels
+ int tileHeight; //!< height of a tile in pixels
+ int matrixWidth; //!< number of tiles horizontally
+ int matrixHeight; //!< number of tiles vertically
+ double tres; //!< pixel span in map units
+
+ //! Returns extent of a tile in map coordinates.
+ //! (same function as tileBBox() but returns QRectF instead of QgsRectangle)
+ QRectF tileRect( int col, int row ) const;
+
+ //! Returns extent of a tile in map coordinates
+ //! (same function as tileRect() but returns QgsRectangle instead of QRectF)
+ QgsRectangle tileBBox( int col, int row ) const;
+
+ //! Returns range of tiles that intersects with the view extent
+ //! (tml may be null)
+ void viewExtentIntersection( const QgsRectangle& viewExtent, const QgsWmtsTileMatrixLimits* tml, int& col0, int& row0, int& col1, int& row1 ) const;
+
};
struct QgsWmtsTileMatrixSet
{
- QString identifier;
- QString title, abstract;
- QStringList keywords;
- QString crs;
- QString wkScaleSet;
+ QString identifier; //!< tile matrix set identifier
+ QString title; //!< human readable tile matrix set name
+ QString abstract; //!< brief description of the tile matrix set
+ QStringList keywords; //!< list of words/phrases to describe the dataset
+ QString crs; //!< CRS of the tile matrix set
+ QString wkScaleSet; //!< optional reference to a well-known scale set
+ //! available tile matrixes (key = pixel span in map units)
QMap<double, QgsWmtsTileMatrix> tileMatrices;
+
+ //! Returns closest tile resolution to the requested one. (resolution = width [map units] / with [pixels])
+ const QgsWmtsTileMatrix* findNearestResolution( double vres ) const;
+
+ //! Return tile matrix for other near resolution from given tres (positive offset = lower resolution tiles)
+ const QgsWmtsTileMatrix* findOtherResolution( double tres, int offset ) const;
};
-enum QgsTileMode { WMTS, WMSC };
+enum QgsTileMode { WMTS, WMSC, XYZ };
struct QgsWmtsTileMatrixLimits
{
@@ -363,16 +387,22 @@ struct QgsWmtsStyle
QList<QgsWmtsLegendURL> legendURLs;
};
+/**
+ * In case of multi-dimensional data, the service metadata can describe their multi-
+ * dimensionality and tiles can be requested at specific values in these dimensions.
+ * Examples of dimensions are Time, Elevation and Band.
+ */
struct QgsWmtsDimension
{
- QString identifier;
- QString title, abstract;
- QStringList keywords;
- QString UOM;
- QString unitSymbol;
- QString defaultValue;
- bool current;
- QStringList values;
+ QString identifier; //!< name of the dimensional axis
+ QString title; //!< human readable name
+ QString abstract; //!< brief description of the dimension
+ QStringList keywords; //!< list of words/phrases to describe the dataset
+ QString UOM; //!< units of measure of dimensional axis
+ QString unitSymbol; //!< symbol of the units
+ QString defaultValue; //!< default value to be used if value is not specified in request
+ bool current; //!< indicates whether temporal data are normally kept current
+ QStringList values; //!< available values for this dimension
};
struct QgsWmtsTileLayer
@@ -385,6 +415,7 @@ struct QgsWmtsTileLayer
QStringList formats;
QStringList infoFormats;
QString defaultStyle;
+ //! available dimensions (optional, for multi-dimensional data)
QHash<QString, QgsWmtsDimension> dimensions;
QHash<QString, QgsWmtsStyle> styles;
QHash<QString, QgsWmtsTileMatrixSetLink> setLinks;
@@ -481,6 +512,15 @@ struct QgsWmsAuthorization
}
return true;
}
+ //! set authorization reply
+ bool setAuthorizationReply( QNetworkReply * reply ) const
+ {
+ if ( !mAuthCfg.isEmpty() )
+ {
+ return QgsAuthManager::instance()->updateNetworkReply( reply, mAuthCfg );
+ }
+ return true;
+ }
//! Username for basic http authentication
QString mUserName;
@@ -513,7 +553,11 @@ class QgsWmsSettings
//! layer is tiled, tile layer and active matrix set
bool mTiled;
+ //! whether we actually work with XYZ tiles instead of WMS / WMTS
+ bool mXyz;
+ //! chosen values for dimensions in case of multi-dimensional data (key=dim id, value=dim value)
QHash<QString, QString> mTileDimensionValues;
+ //! name of the chosen tile matrix set
QString mTileMatrixSetId;
/**
diff --git a/src/providers/wms/qgswmsdataitems.cpp b/src/providers/wms/qgswmsdataitems.cpp
index 31a04a1..0f35488 100644
--- a/src/providers/wms/qgswmsdataitems.cpp
+++ b/src/providers/wms/qgswmsdataitems.cpp
@@ -16,6 +16,7 @@
#include "qgslogger.h"
+#include "qgsdataitemproviderregistry.h"
#include "qgsdatasourceuri.h"
#include "qgswmscapabilities.h"
#include "qgswmsconnection.h"
@@ -23,6 +24,9 @@
#include "qgsnewhttpconnection.h"
#include "qgstilescalewidget.h"
#include "qgscrscache.h"
+#include "qgsxyzconnection.h"
+
+#include <QInputDialog>
// ---------------------------------------------------------------------------
QgsWMSConnectionItem::QgsWMSConnectionItem( QgsDataItem* parent, QString name, QString path, QString uri )
@@ -131,46 +135,61 @@ QVector<QgsDataItem*> QgsWMSConnectionItem::createChildren()
QgsDataItem *layerItem = l.styles.size() == 1 ? this : new QgsDataCollectionItem( this, title, mPath + '/' + l.identifier );
if ( layerItem != this )
{
+ layerItem->setCapabilities( layerItem->capabilities2() & ~QgsDataItem::Fertile );
+ layerItem->setState( QgsDataItem::Populated );
layerItem->setToolTip( title );
- addChildItem( layerItem );
+ children << layerItem;
}
Q_FOREACH ( const QgsWmtsStyle &style, l.styles )
{
QString styleName = style.title.isEmpty() ? style.identifier : style.title;
if ( layerItem == this )
- styleName.prepend( title + " - " );
+ styleName = title; // just one style so no need to display it
QgsDataItem *styleItem = l.setLinks.size() == 1 ? layerItem : new QgsDataCollectionItem( layerItem, styleName, layerItem->path() + '/' + style.identifier );
if ( styleItem != layerItem )
{
+ styleItem->setCapabilities( styleItem->capabilities2() & ~QgsDataItem::Fertile );
+ styleItem->setState( QgsDataItem::Populated );
styleItem->setToolTip( styleName );
- layerItem->addChildItem( styleItem );
+ if ( layerItem == this )
+ children << styleItem;
+ else
+ layerItem->addChildItem( styleItem );
}
Q_FOREACH ( const QgsWmtsTileMatrixSetLink &setLink, l.setLinks )
{
QString linkName = setLink.tileMatrixSet;
if ( styleItem == layerItem )
- linkName.prepend( styleName + " - " );
+ linkName = styleName; // just one link so no need to display it
QgsDataItem *linkItem = l.formats.size() == 1 ? styleItem : new QgsDataCollectionItem( styleItem, linkName, styleItem->path() + '/' + setLink.tileMatrixSet );
if ( linkItem != styleItem )
{
+ linkItem->setCapabilities( linkItem->capabilities2() & ~QgsDataItem::Fertile );
+ linkItem->setState( QgsDataItem::Populated );
linkItem->setToolTip( linkName );
- styleItem->addChildItem( linkItem );
+ if ( styleItem == this )
+ children << linkItem;
+ else
+ styleItem->addChildItem( linkItem );
}
Q_FOREACH ( const QString& format, l.formats )
{
QString name = format;
if ( linkItem == styleItem )
- name.prepend( linkName + " - " );
+ name = linkName; // just one format so no need to display it
- QgsDataItem *layerItem = new QgsWMTSLayerItem( linkItem, name, linkItem->path() + '/' + name, uri,
+ QgsDataItem *tileLayerItem = new QgsWMTSLayerItem( linkItem, name, linkItem->path() + '/' + name, uri,
l.identifier, format, style.identifier, setLink.tileMatrixSet, tileMatrixSets[ setLink.tileMatrixSet ].crs, title );
- layerItem->setToolTip( name );
- linkItem->addChildItem( layerItem );
+ tileLayerItem->setToolTip( name );
+ if ( linkItem == this )
+ children << tileLayerItem;
+ else
+ linkItem->addChildItem( tileLayerItem );
}
}
}
@@ -424,12 +443,8 @@ QGISEXTERN QgsWMSSourceSelect * selectWidget( QWidget * parent, Qt::WindowFlags
return new QgsWMSSourceSelect( parent, fl );
}
-QGISEXTERN int dataCapabilities()
-{
- return QgsDataProvider::Net;
-}
-QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
+QgsDataItem* QgsWmsDataItemProvider::createDataItem( const QString& thePath, QgsDataItem *parentItem )
{
QgsDebugMsg( "thePath = " + thePath );
if ( thePath.isEmpty() )
@@ -451,3 +466,87 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
return nullptr;
}
+QGISEXTERN QList<QgsDataItemProvider*> dataItemProviders()
+{
+ return QList<QgsDataItemProvider*>()
+ << new QgsWmsDataItemProvider
+ << new QgsXyzTileDataItemProvider;
+}
+
+// ---------------------------------------------------------------------------
+
+
+QgsXyzTileRootItem::QgsXyzTileRootItem( QgsDataItem *parent, QString name, QString path )
+ : QgsDataCollectionItem( parent, name, path )
+{
+ mCapabilities |= Fast;
+ mIconName = "mIconWms.svg";
+ populate();
+}
+
+QVector<QgsDataItem *> QgsXyzTileRootItem::createChildren()
+{
+ QVector<QgsDataItem*> connections;
+ Q_FOREACH ( const QString& connName, QgsXyzConnectionUtils::connectionList() )
+ {
+ QgsXyzConnection connection( QgsXyzConnectionUtils::connection( connName ) );
+ QgsDataItem * conn = new QgsXyzLayerItem( this, connName, mPath + '/' + connName, connection.encodedUri() );
+ connections.append( conn );
+ }
+ return connections;
+}
+
+QList<QAction *> QgsXyzTileRootItem::actions()
+{
+ QAction* actionNew = new QAction( tr( "New Connection..." ), this );
+ connect( actionNew, SIGNAL( triggered() ), this, SLOT( newConnection() ) );
+ return QList<QAction*>() << actionNew;
+}
+
+void QgsXyzTileRootItem::newConnection()
+{
+ QString url = QInputDialog::getText( nullptr, tr( "New XYZ tile layer" ),
+ tr( "Please enter XYZ tile layer URL. {x}, {y}, {z} will be replaced by actual tile coordinates." ) );
+ if ( url.isEmpty() )
+ return;
+
+ QString name = QInputDialog::getText( nullptr, tr( "New XYZ tile layer" ),
+ tr( "Please enter name of the tile layer:" ) );
+ if ( name.isEmpty() )
+ return;
+
+ QgsXyzConnection conn;
+ conn.name = name;
+ conn.url = url;
+ QgsXyzConnectionUtils::addConnection( conn );
+
+ refresh();
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+QgsXyzLayerItem::QgsXyzLayerItem( QgsDataItem *parent, QString name, QString path, const QString &encodedUri )
+ : QgsLayerItem( parent, name, path, encodedUri, QgsLayerItem::Raster, "wms" )
+{
+ setState( Populated );
+}
+
+QList<QAction *> QgsXyzLayerItem::actions()
+{
+ QList<QAction*> lst = QgsLayerItem::actions();
+
+ QAction* actionDelete = new QAction( tr( "Delete" ), this );
+ connect( actionDelete, SIGNAL( triggered() ), this, SLOT( deleteConnection() ) );
+ lst << actionDelete;
+
+ return lst;
+}
+
+void QgsXyzLayerItem::deleteConnection()
+{
+ QgsXyzConnectionUtils::deleteConnection( mName );
+
+ mParent->refresh();
+}
diff --git a/src/providers/wms/qgswmsdataitems.h b/src/providers/wms/qgswmsdataitems.h
index 39270c5..0ed3fa2 100644
--- a/src/providers/wms/qgswmsdataitems.h
+++ b/src/providers/wms/qgswmsdataitems.h
@@ -16,6 +16,7 @@
#define QGSWMSDATAITEMS_H
#include "qgsdataitem.h"
+#include "qgsdataitemprovider.h"
#include "qgsdatasourceuri.h"
#include "qgswmsprovider.h"
@@ -105,4 +106,63 @@ class QgsWMSRootItem : public QgsDataCollectionItem
void newConnection();
};
+
+//! Provider for WMS root data item
+class QgsWmsDataItemProvider : public QgsDataItemProvider
+{
+ public:
+ virtual QString name() override { return "WMS"; }
+
+ virtual int capabilities() override { return QgsDataProvider::Net; }
+
+ virtual QgsDataItem* createDataItem( const QString& path, QgsDataItem* parentItem ) override;
+};
+
+
+//! Root item for XYZ tile layers
+class QgsXyzTileRootItem : public QgsDataCollectionItem
+{
+ Q_OBJECT
+ public:
+ QgsXyzTileRootItem( QgsDataItem* parent, QString name, QString path );
+
+ QVector<QgsDataItem*> createChildren() override;
+
+ virtual QList<QAction*> actions() override;
+
+ private slots:
+ void newConnection();
+};
+
+//! Item implementation for XYZ tile layers
+class QgsXyzLayerItem : public QgsLayerItem
+{
+ Q_OBJECT
+ public:
+ QgsXyzLayerItem( QgsDataItem* parent, QString name, QString path, const QString& encodedUri );
+
+ virtual QList<QAction*> actions() override;
+
+ public slots:
+ void deleteConnection();
+};
+
+
+//! Provider for XYZ root data item
+class QgsXyzTileDataItemProvider : public QgsDataItemProvider
+{
+ public:
+ virtual QString name() override { return "XYZ Tiles"; }
+
+ virtual int capabilities() override { return QgsDataProvider::Net; }
+
+ virtual QgsDataItem* createDataItem( const QString& path, QgsDataItem* parentItem ) override
+ {
+ if ( path.isEmpty() )
+ return new QgsXyzTileRootItem( parentItem, "Tile Server (XYZ)", "xyz:" );
+ return nullptr;
+ }
+};
+
+
#endif // QGSWMSDATAITEMS_H
diff --git a/src/providers/wms/qgswmsprovider.cpp b/src/providers/wms/qgswmsprovider.cpp
index 2cf2fbb..d4b8c20 100644
--- a/src/providers/wms/qgswmsprovider.cpp
+++ b/src/providers/wms/qgswmsprovider.cpp
@@ -39,6 +39,7 @@
#include "qgsmessagelog.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsnetworkreplyparser.h"
+#include "qgstilecache.h"
#include "qgsgml.h"
#include "qgsgmlschema.h"
#include "qgswmscapabilities.h"
@@ -78,18 +79,29 @@ static QString DEFAULT_LATLON_CRS = "CRS:84";
QMap<QString, QgsWmsStatistics::Stat> QgsWmsStatistics::sData;
+//! a helper class for ordering tile requests according to the distance from view center
+struct LessThanTileRequest
+{
+ QgsPoint center;
+ bool operator()( const QgsWmsProvider::TileRequest &req1, const QgsWmsProvider::TileRequest &req2 )
+ {
+ QPointF p1 = req1.rect.center();
+ QPointF p2 = req2.rect.center();
+ // using chessboard distance (loading order more natural than euclidean/manhattan distance)
+ double d1 = qMax( qAbs( center.x() - p1.x() ), qAbs( center.y() - p1.y() ) );
+ double d2 = qMax( qAbs( center.x() - p2.x() ), qAbs( center.y() - p2.y() ) );
+ return d1 < d2;
+ }
+};
+
+
QgsWmsProvider::QgsWmsProvider( QString const& uri, const QgsWmsCapabilities* capabilities )
: QgsRasterDataProvider( uri )
, mHttpGetLegendGraphicResponse( nullptr )
, mGetLegendGraphicImage()
, mGetLegendGraphicScale( 0.0 )
, mImageCrs( DEFAULT_LATLON_CRS )
- , mCachedImage( nullptr )
, mIdentifyReply( nullptr )
- , mCachedViewExtent( 0 )
- , mCachedViewWidth( 0 )
- , mCachedViewHeight( 0 )
- , mCoordinateTransform( nullptr )
, mExtentDirty( true )
, mTileReqNo( 0 )
, mTileLayer( nullptr )
@@ -114,14 +126,26 @@ QgsWmsProvider::QgsWmsProvider( QString const& uri, const QgsWmsCapabilities* ca
if ( !addLayers() )
return;
- // if there are already parsed capabilities, use them!
- if ( capabilities )
- mCaps = *capabilities;
-
- // Make sure we have capabilities - other functions here may need them
- if ( !retrieveServerCapabilities() )
+ if ( mSettings.mXyz )
{
- return;
+ // we are working with XYZ tiles
+ // no need to get capabilities, the whole definition is in URI
+ // so we just generate a dummy WMTS definition
+ setupXyzCapabilities( uri );
+ }
+ else
+ {
+ // we are working with WMS / WMTS server
+
+ // if there are already parsed capabilities, use them!
+ if ( capabilities )
+ mCaps = *capabilities;
+
+ // Make sure we have capabilities - other functions here may need them
+ if ( !retrieveServerCapabilities() )
+ {
+ return;
+ }
}
// setImageCrs is using mTiled !!!
@@ -170,13 +194,6 @@ QString QgsWmsProvider::prepareUri( QString uri )
QgsWmsProvider::~QgsWmsProvider()
{
QgsDebugMsg( "deconstructing." );
-
- // Dispose of any cached image as created by draw()
- if ( mCachedImage )
- {
- delete mCachedImage;
- mCachedImage = nullptr;
- }
}
QgsWmsProvider* QgsWmsProvider::clone() const
@@ -481,106 +498,136 @@ void QgsWmsProvider::setFormatQueryItem( QUrl &url )
QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, int pixelHeight )
{
- QgsDebugMsg( "Entering." );
-
- // Can we reuse the previously cached image?
- if ( mCachedImage &&
- mCachedViewExtent == viewExtent &&
- mCachedViewWidth == pixelWidth &&
- mCachedViewHeight == pixelHeight )
- {
- return mCachedImage;
- }
-
- // delete cached image and create network request(s) to fill it
- if ( mCachedImage )
- {
- delete mCachedImage;
- mCachedImage = nullptr;
- }
+ return draw( viewExtent, pixelWidth, pixelHeight, nullptr );
+}
- bool changeXY = mCaps.shouldInvertAxisOrientation( mImageCrs );
+static bool _fuzzyContainsRect( const QRectF& r1, const QRectF& r2 )
+{
+ double significantDigits = log10( qMax( r1.width(), r1.height() ) );
+ double epsilon = pow( 10.0, significantDigits - 5 ); // floats have 6-9 significant digits
+ return r1.contains( r2.adjusted( epsilon, epsilon, -epsilon, -epsilon ) );
+}
- // compose the URL query string for the WMS server.
+void QgsWmsProvider::fetchOtherResTiles( QgsTileMode tileMode, const QgsRectangle& viewExtent, int imageWidth, QList<QRectF>& missingRects, double tres, int resOffset, QList<TileImage>& otherResTiles )
+{
+ const QgsWmtsTileMatrix* tmOther = mTileMatrixSet->findOtherResolution( tres, resOffset );
+ if ( !tmOther )
+ return;
- QString bbox = toParamValue( viewExtent, changeXY );
+ QSet<TilePosition> tilesSet;
+ Q_FOREACH ( const QRectF& missingTileRect, missingRects )
+ {
+ int c0, r0, c1, r1;
+ tmOther->viewExtentIntersection( QgsRectangle( missingTileRect ), nullptr, c0, r0, c1, r1 );
- mCachedImage = new QImage( pixelWidth, pixelHeight, QImage::Format_ARGB32 );
- mCachedImage->fill( 0 );
- mCachedViewExtent = viewExtent;
- mCachedViewWidth = pixelWidth;
- mCachedViewHeight = pixelHeight;
+ for ( int row = r0; row <= r1; row++ )
+ {
+ for ( int col = c0; col <= c1; col++ )
+ {
+ tilesSet << TilePosition( row, col );
+ }
+ }
+ }
- if ( !mSettings.mTiled && mSettings.mMaxWidth == 0 && mSettings.mMaxHeight == 0 )
+ // get URLs of tiles because their URLs are used as keys in the tile cache
+ TilePositions tiles = tilesSet.toList();
+ TileRequests requests;
+ switch ( tileMode )
{
- // Calculate active layers that are also visible.
+ case WMSC:
+ createTileRequestsWMSC( tmOther, tiles, requests );
+ break;
- QgsDebugMsg( "Active layer list of " + mSettings.mActiveSubLayers.join( ", " )
- + " and style list of " + mSettings.mActiveSubStyles.join( ", " ) );
+ case WMTS:
+ createTileRequestsWMTS( tmOther, tiles, requests );
+ break;
- QStringList visibleLayers = QStringList();
- QStringList visibleStyles = QStringList();
+ case XYZ:
+ createTileRequestsXYZ( tmOther, tiles, requests );
+ break;
+ }
- QStringList::const_iterator it2 = mSettings.mActiveSubStyles.constBegin();
+ QList<QRectF> missingRectsToDelete;
+ Q_FOREACH ( const TileRequest& r, requests )
+ {
+ QImage localImage;
+ if ( ! QgsTileCache::tile( r.url, localImage ) )
+ continue;
- for ( QStringList::const_iterator it = mSettings.mActiveSubLayers.constBegin();
- it != mSettings.mActiveSubLayers.constEnd();
- ++it )
+ double cr = viewExtent.width() / imageWidth;
+ QRectF dst(( r.rect.left() - viewExtent.xMinimum() ) / cr,
+ ( viewExtent.yMaximum() - r.rect.bottom() ) / cr,
+ r.rect.width() / cr,
+ r.rect.height() / cr );
+ otherResTiles << TileImage( dst, localImage );
+
+ // see if there are any missing rects that are completely covered by this tile
+ Q_FOREACH ( const QRectF& missingRect, missingRects )
{
- if ( mActiveSubLayerVisibility.constFind( *it ).value() )
+ // we need to do a fuzzy "contains" check because the coordinates may not align perfectly
+ // due to numerical errors and/or transform of coords from double to floats
+ if ( _fuzzyContainsRect( r.rect, missingRect ) )
{
- visibleLayers += *it;
- visibleStyles += *it2;
+ missingRectsToDelete << missingRect;
}
-
- ++it2;
}
+ }
- QString layers = visibleLayers.join( "," );
- layers = layers.isNull() ? "" : layers;
- QString styles = visibleStyles.join( "," );
- styles = styles.isNull() ? "" : styles;
+ // remove all the rectangles we have completely covered by tiles from this resolution
+ // so we will not use tiles from multiple resolutions for one missing tile (to save time)
+ Q_FOREACH ( const QRectF& rectToDelete, missingRectsToDelete )
+ {
+ missingRects.removeOne( rectToDelete );
+ }
- QgsDebugMsg( "Visible layer list of " + layers + " and style list of " + styles );
+ QgsDebugMsg( QString( "Other resolution tiles: offset %1, res %2, missing rects %3, remaining rects %4, added tiles %5" )
+ .arg( resOffset )
+ .arg( tmOther->tres )
+ .arg( missingRects.count() + missingRectsToDelete.count() )
+ .arg( missingRects.count() )
+ .arg( otherResTiles.count() ) );
+}
- QUrl url( mSettings.mIgnoreGetMapUrl ? mSettings.mBaseUrl : getMapUrl() );
- setQueryItem( url, "SERVICE", "WMS" );
- setQueryItem( url, "VERSION", mCaps.mCapabilities.version );
- setQueryItem( url, "REQUEST", "GetMap" );
- setQueryItem( url, "BBOX", bbox );
- setSRSQueryItem( url );
- setQueryItem( url, "WIDTH", QString::number( pixelWidth ) );
- setQueryItem( url, "HEIGHT", QString::number( pixelHeight ) );
- setQueryItem( url, "LAYERS", layers );
- setQueryItem( url, "STYLES", styles );
- setFormatQueryItem( url );
+uint qHash( const QgsWmsProvider::TilePosition& tp )
+{
+ return ( uint ) tp.col + (( uint ) tp.row << 16 );
+}
- if ( mDpi != -1 )
- {
- if ( mSettings.mDpiMode & dpiQGIS )
- setQueryItem( url, "DPI", QString::number( mDpi ) );
- if ( mSettings.mDpiMode & dpiUMN )
- setQueryItem( url, "MAP_RESOLUTION", QString::number( mDpi ) );
- if ( mSettings.mDpiMode & dpiGeoServer )
- setQueryItem( url, "FORMAT_OPTIONS", QString( "dpi:%1" ).arg( mDpi ) );
- }
+static void _drawDebugRect( QPainter& p, const QRectF& rect, const QColor& color )
+{
+#if 0 // good for debugging how tiles from various resolutions are used
+ QPainter::CompositionMode oldMode = p.compositionMode();
+ p.setCompositionMode( QPainter::CompositionMode_SourceOver );
+ QColor c = color;
+ c.setAlpha( 100 );
+ p.fillRect( rect, QBrush( c, Qt::DiagCrossPattern ) );
+ p.setCompositionMode( oldMode );
+#else
+ Q_UNUSED( p );
+ Q_UNUSED( rect );
+ Q_UNUSED( color );
+#endif
+}
- //MH: jpeg does not support transparency and some servers complain if jpg and transparent=true
- if ( mSettings.mImageMimeType == "image/x-jpegorpng" ||
- ( !mSettings.mImageMimeType.contains( "jpeg", Qt::CaseInsensitive ) &&
- !mSettings.mImageMimeType.contains( "jpg", Qt::CaseInsensitive ) ) )
- {
- setQueryItem( url, "TRANSPARENT", "TRUE" ); // some servers giving error for 'true' (lowercase)
- }
+QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight, QgsRasterBlockFeedback* feedback )
+{
+ QgsDebugMsg( "Entering." );
+
+ // compose the URL query string for the WMS server.
- QgsDebugMsg( QString( "getmap: %1" ).arg( url.toString() ) );
+ QImage* image = new QImage( pixelWidth, pixelHeight, QImage::Format_ARGB32 );
+ image->fill( 0 );
+
+ if ( !mSettings.mTiled && mSettings.mMaxWidth == 0 && mSettings.mMaxHeight == 0 )
+ {
+ QUrl url = createRequestUrlWMS( viewExtent, pixelWidth, pixelHeight );
// cache some details for if the user wants to do an identifyAsHtml() later
emit statusChanged( tr( "Getting map via WMS." ) );
- QgsWmsImageDownloadHandler handler( dataSourceUri(), url, mSettings.authorization(), mCachedImage );
+ QgsWmsImageDownloadHandler handler( dataSourceUri(), url, mSettings.authorization(), image, feedback );
handler.downloadBlocking();
}
else
@@ -588,9 +635,9 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, in
mTileReqNo++;
double vres = viewExtent.width() / pixelWidth;
- double tres = vres;
const QgsWmtsTileMatrix *tm = nullptr;
+ QScopedPointer<QgsWmtsTileMatrix> tempTm;
enum QgsTileMode tileMode;
if ( mSettings.mTiled )
@@ -599,45 +646,29 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, in
Q_ASSERT( mTileMatrixSet );
Q_ASSERT( !mTileMatrixSet->tileMatrices.isEmpty() );
- QMap<double, QgsWmtsTileMatrix> &m = mTileMatrixSet->tileMatrices;
-
// find nearest resolution
- QMap<double, QgsWmtsTileMatrix>::const_iterator prev, it = m.constBegin();
- while ( it != m.constEnd() && it.key() < vres )
- {
- QgsDebugMsg( QString( "res:%1 >= %2" ).arg( it.key() ).arg( vres ) );
- prev = it;
- ++it;
- }
-
- if ( it == m.constEnd() ||
- ( it != m.constBegin() && vres - prev.key() < it.key() - vres ) )
- {
- QgsDebugMsg( "back to previous res" );
- it = prev;
- }
-
- tres = it.key();
- tm = &it.value();
+ tm = mTileMatrixSet->findNearestResolution( vres );
+ Q_ASSERT( tm );
tileMode = mTileLayer->tileMode;
}
else if ( mSettings.mMaxWidth != 0 && mSettings.mMaxHeight != 0 )
{
- static QgsWmtsTileMatrix tempTm;
- tempTm.topLeft = QgsPoint( mLayerExtent.xMinimum(), mLayerExtent.yMaximum() );
- tempTm.tileWidth = mSettings.mMaxWidth;
- tempTm.tileHeight = mSettings.mMaxHeight;
- tempTm.matrixWidth = ceil( mLayerExtent.width() / mSettings.mMaxWidth / vres );
- tempTm.matrixHeight = ceil( mLayerExtent.height() / mSettings.mMaxHeight / vres );
- tm = &tempTm;
+ tempTm.reset( new QgsWmtsTileMatrix );
+ tempTm->topLeft = QgsPoint( mLayerExtent.xMinimum(), mLayerExtent.yMaximum() );
+ tempTm->tileWidth = mSettings.mMaxWidth;
+ tempTm->tileHeight = mSettings.mMaxHeight;
+ tempTm->matrixWidth = ceil( mLayerExtent.width() / mSettings.mMaxWidth / vres );
+ tempTm->matrixHeight = ceil( mLayerExtent.height() / mSettings.mMaxHeight / vres );
+ tempTm->tres = vres;
+ tm = tempTm.data();
tileMode = WMSC;
}
else
{
QgsDebugMsg( "empty tile size" );
- return mCachedImage;
+ return image;
}
QgsDebugMsg( QString( "layer extent: %1,%2 %3x%4" )
@@ -656,199 +687,171 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, in
);
QgsDebugMsg( QString( "tile matrix %1,%2 res:%3 tilesize:%4x%5 matrixsize:%6x%7 id:%8" )
- .arg( tm->topLeft.x() ).arg( tm->topLeft.y() ).arg( tres )
+ .arg( tm->topLeft.x() ).arg( tm->topLeft.y() ).arg( tm->tres )
.arg( tm->tileWidth ).arg( tm->tileHeight )
.arg( tm->matrixWidth ).arg( tm->matrixHeight )
.arg( tm->identifier )
);
- // calculate tile coordinates
- double twMap = tm->tileWidth * tres;
- double thMap = tm->tileHeight * tres;
- QgsDebugMsg( QString( "tile map size: %1,%2" ).arg( qgsDoubleToString( twMap ), qgsDoubleToString( thMap ) ) );
-
- int minTileCol = 0;
- int maxTileCol = tm->matrixWidth - 1;
- int minTileRow = 0;
- int maxTileRow = tm->matrixHeight - 1;
-
+ const QgsWmtsTileMatrixLimits *tml = nullptr;
if ( mTileLayer &&
mTileLayer->setLinks.contains( mTileMatrixSet->identifier ) &&
mTileLayer->setLinks[ mTileMatrixSet->identifier ].limits.contains( tm->identifier ) )
{
- const QgsWmtsTileMatrixLimits &tml = mTileLayer->setLinks[ mTileMatrixSet->identifier ].limits[ tm->identifier ];
- minTileCol = tml.minTileCol;
- maxTileCol = tml.maxTileCol;
- minTileRow = tml.minTileRow;
- maxTileRow = tml.maxTileRow;
- QgsDebugMsg( QString( "%1 %2: TileMatrixLimits col %3-%4 row %5-%6" )
- .arg( mTileMatrixSet->identifier,
- tm->identifier )
- .arg( minTileCol ).arg( maxTileCol )
- .arg( minTileRow ).arg( maxTileRow ) );
+ tml = &mTileLayer->setLinks[ mTileMatrixSet->identifier ].limits[ tm->identifier ];
}
- int col0 = qBound( minTileCol, ( int ) floor(( viewExtent.xMinimum() - tm->topLeft.x() ) / twMap ), maxTileCol );
- int row0 = qBound( minTileRow, ( int ) floor(( tm->topLeft.y() - viewExtent.yMaximum() ) / thMap ), maxTileRow );
- int col1 = qBound( minTileCol, ( int ) floor(( viewExtent.xMaximum() - tm->topLeft.x() ) / twMap ), maxTileCol );
- int row1 = qBound( minTileRow, ( int ) floor(( tm->topLeft.y() - viewExtent.yMinimum() ) / thMap ), maxTileRow );
+ // calculate tile coordinates
+ int col0, col1, row0, row1;
+ tm->viewExtentIntersection( viewExtent, tml, col0, row0, col1, row1 );
#if QGISDEBUG
int n = ( col1 - col0 + 1 ) * ( row1 - row0 + 1 );
QgsDebugMsg( QString( "tile number: %1x%2 = %3" ).arg( col1 - col0 + 1 ).arg( row1 - row0 + 1 ).arg( n ) );
- if ( n > 100 )
+ if ( n > 256 )
{
- emit statusChanged( QString( "current view would need %1 tiles. tile request per draw limited to 100." ).arg( n ) );
- return mCachedImage;
+ emit statusChanged( QString( "current view would need %1 tiles. tile request per draw limited to 256." ).arg( n ) );
+ return image;
}
#endif
- QList<QgsWmsTiledImageDownloadHandler::TileRequest> requests;
+ TilePositions tiles;
+ for ( int row = row0; row <= row1; row++ )
+ {
+ for ( int col = col0; col <= col1; col++ )
+ {
+ tiles << TilePosition( row, col );
+ }
+ }
+ TileRequests requests;
switch ( tileMode )
{
case WMSC:
- {
- // add WMS request
- QUrl url( mSettings.mIgnoreGetMapUrl ? mSettings.mBaseUrl : getMapUrl() );
- setQueryItem( url, "SERVICE", "WMS" );
- setQueryItem( url, "VERSION", mCaps.mCapabilities.version );
- setQueryItem( url, "REQUEST", "GetMap" );
- setQueryItem( url, "WIDTH", QString::number( tm->tileWidth ) );
- setQueryItem( url, "HEIGHT", QString::number( tm->tileHeight ) );
- setQueryItem( url, "LAYERS", mSettings.mActiveSubLayers.join( "," ) );
- setQueryItem( url, "STYLES", mSettings.mActiveSubStyles.join( "," ) );
- setFormatQueryItem( url );
-
- setSRSQueryItem( url );
-
- if ( mSettings.mTiled )
- {
- setQueryItem( url, "TILED", "true" );
- }
+ createTileRequestsWMSC( tm, tiles, requests );
+ break;
- if ( mDpi != -1 )
- {
- if ( mSettings.mDpiMode & dpiQGIS )
- setQueryItem( url, "DPI", QString::number( mDpi ) );
- if ( mSettings.mDpiMode & dpiUMN )
- setQueryItem( url, "MAP_RESOLUTION", QString::number( mDpi ) );
- if ( mSettings.mDpiMode & dpiGeoServer )
- setQueryItem( url, "FORMAT_OPTIONS", QString( "dpi:%1" ).arg( mDpi ) );
- }
+ case WMTS:
+ createTileRequestsWMTS( tm, tiles, requests );
+ break;
- if ( mSettings.mImageMimeType == "image/x-jpegorpng" ||
- ( !mSettings.mImageMimeType.contains( "jpeg", Qt::CaseInsensitive ) &&
- !mSettings.mImageMimeType.contains( "jpg", Qt::CaseInsensitive ) ) )
- {
- setQueryItem( url, "TRANSPARENT", "TRUE" ); // some servers giving error for 'true' (lowercase)
- }
+ case XYZ:
+ createTileRequestsXYZ( tm, tiles, requests );
+ break;
- int i = 0;
- for ( int row = row0; row <= row1; row++ )
- {
- for ( int col = col0; col <= col1; col++ )
- {
- QString turl;
- turl += url.toString();
- turl += QString( changeXY ? "&BBOX=%2,%1,%4,%3" : "&BBOX=%1,%2,%3,%4" )
- .arg( qgsDoubleToString( tm->topLeft.x() + col * twMap /* + twMap * 0.001 */ ),
- qgsDoubleToString( tm->topLeft.y() - ( row + 1 ) * thMap /* - thMap * 0.001 */ ),
- qgsDoubleToString( tm->topLeft.x() + ( col + 1 ) * twMap /* - twMap * 0.001 */ ),
- qgsDoubleToString( tm->topLeft.y() - row * thMap /* + thMap * 0.001 */ ) );
-
- QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i++ ).arg( n ).arg( row ).arg( col ).arg( turl ) );
- QRectF rect( tm->topLeft.x() + col * twMap, tm->topLeft.y() - ( row + 1 ) * thMap, twMap, thMap );
- requests << QgsWmsTiledImageDownloadHandler::TileRequest( turl, rect, i );
- }
- }
- }
- break;
+ default:
+ QgsDebugMsg( QString( "unexpected tile mode %1" ).arg( mTileLayer->tileMode ) );
+ return image;
+ }
- case WMTS:
+ emit statusChanged( tr( "Getting tiles." ) );
+
+ QList<TileImage> tileImages; // in the correct resolution
+ QList<QRectF> missing; // rectangles (in map coords) of missing tiles for this view
+
+ QTime t;
+ t.start();
+ TileRequests requestsFinal;
+ Q_FOREACH ( const TileRequest& r, requests )
+ {
+ QImage localImage;
+ if ( QgsTileCache::tile( r.url, localImage ) )
{
- if ( !getTileUrl().isNull() )
- {
- // KVP
- QUrl url( mSettings.mIgnoreGetMapUrl ? mSettings.mBaseUrl : getTileUrl() );
-
- // compose static request arguments.
- setQueryItem( url, "SERVICE", "WMTS" );
- setQueryItem( url, "REQUEST", "GetTile" );
- setQueryItem( url, "VERSION", mCaps.mCapabilities.version );
- setQueryItem( url, "LAYER", mSettings.mActiveSubLayers[0] );
- setQueryItem( url, "STYLE", mSettings.mActiveSubStyles[0] );
- setQueryItem( url, "FORMAT", mSettings.mImageMimeType );
- setQueryItem( url, "TILEMATRIXSET", mTileMatrixSet->identifier );
- setQueryItem( url, "TILEMATRIX", tm->identifier );
-
- for ( QHash<QString, QString>::const_iterator it = mSettings.mTileDimensionValues.constBegin(); it != mSettings.mTileDimensionValues.constEnd(); ++it )
- {
- setQueryItem( url, it.key(), it.value() );
- }
+ double cr = viewExtent.width() / image->width();
- url.removeQueryItem( "TILEROW" );
- url.removeQueryItem( "TILECOL" );
+ QRectF dst(( r.rect.left() - viewExtent.xMinimum() ) / cr,
+ ( viewExtent.yMaximum() - r.rect.bottom() ) / cr,
+ r.rect.width() / cr,
+ r.rect.height() / cr );
+ tileImages << TileImage( dst, localImage );
+ }
+ else
+ {
+ missing << r.rect;
- int i = 0;
- for ( int row = row0; row <= row1; row++ )
- {
- for ( int col = col0; col <= col1; col++ )
- {
- QString turl;
- turl += url.toString();
- turl += QString( "&TILEROW=%1&TILECOL=%2" ).arg( row ).arg( col );
+ // need to make a request
+ requestsFinal << r;
+ }
+ }
+ int t0 = t.elapsed();
- QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i++ ).arg( n ).arg( row ).arg( col ).arg( turl ) );
- QRectF rect( tm->topLeft.x() + col * twMap, tm->topLeft.y() - ( row + 1 ) * thMap, twMap, thMap );
- requests << QgsWmsTiledImageDownloadHandler::TileRequest( turl, rect, i );
- }
- }
- }
- else
- {
- // REST
- QString url = mTileLayer->getTileURLs[ mSettings.mImageMimeType ];
- url.replace( "{layer}", mSettings.mActiveSubLayers[0], Qt::CaseInsensitive );
- url.replace( "{style}", mSettings.mActiveSubStyles[0], Qt::CaseInsensitive );
- url.replace( "{tilematrixset}", mTileMatrixSet->identifier, Qt::CaseInsensitive );
- url.replace( "{tilematrix}", tm->identifier, Qt::CaseInsensitive );
+ // draw other res tiles if preview
+ QPainter p( image );
+ if ( feedback && feedback->isPreviewOnly() && missing.count() > 0 )
+ {
+ // some tiles are still missing, so let's see if we have any cached tiles
+ // from lower or higher resolution available to give the user a bit of context
+ // while loading the right resolution
+
+ p.setCompositionMode( QPainter::CompositionMode_Source );
+ p.setRenderHint( QPainter::SmoothPixmapTransform, false ); // let's not waste time with bilinear filtering
+
+ QList<TileImage> lowerResTiles, lowerResTiles2, higherResTiles;
+ // first we check lower resolution tiles: one level back, then two levels back (if there is still some are not covered),
+ // finally (in the worst case we use one level higher resolution tiles). This heuristic should give
+ // good overviews while not spending too much time drawing cached tiles from resolutions far away.
+ fetchOtherResTiles( tileMode, viewExtent, image->width(), missing, tm->tres, 1, lowerResTiles );
+ fetchOtherResTiles( tileMode, viewExtent, image->width(), missing, tm->tres, 2, lowerResTiles2 );
+ fetchOtherResTiles( tileMode, viewExtent, image->width(), missing, tm->tres, -1, higherResTiles );
+
+ // draw the cached tiles lowest to highest resolution
+ Q_FOREACH ( const TileImage& ti, lowerResTiles2 )
+ {
+ p.drawImage( ti.rect, ti.img );
+ _drawDebugRect( p, ti.rect, Qt::blue );
+ }
+ Q_FOREACH ( const TileImage& ti, lowerResTiles )
+ {
+ p.drawImage( ti.rect, ti.img );
+ _drawDebugRect( p, ti.rect, Qt::yellow );
+ }
+ Q_FOREACH ( const TileImage& ti, higherResTiles )
+ {
+ p.drawImage( ti.rect, ti.img );
+ _drawDebugRect( p, ti.rect, Qt::red );
+ }
+ }
- for ( QHash<QString, QString>::const_iterator it = mSettings.mTileDimensionValues.constBegin(); it != mSettings.mTileDimensionValues.constEnd(); ++it )
- {
- url.replace( "{" + it.key() + "}", it.value(), Qt::CaseInsensitive );
- }
+ int t1 = t.elapsed() - t0;
- int i = 0;
- for ( int row = row0; row <= row1; row++ )
- {
- for ( int col = col0; col <= col1; col++ )
- {
- QString turl( url );
- turl.replace( "{tilerow}", QString::number( row ), Qt::CaseInsensitive );
- turl.replace( "{tilecol}", QString::number( col ), Qt::CaseInsensitive );
+ // draw composite in this resolution
+ Q_FOREACH ( const TileImage& ti, tileImages )
+ {
+ if ( mSettings.mSmoothPixmapTransform )
+ p.setRenderHint( QPainter::SmoothPixmapTransform, true );
+ p.drawImage( ti.rect, ti.img );
- QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i++ ).arg( n ).arg( row ).arg( col ).arg( turl ) );
- QRectF rect( tm->topLeft.x() + col * twMap, tm->topLeft.y() - ( row + 1 ) * thMap, twMap, thMap );
- requests << QgsWmsTiledImageDownloadHandler::TileRequest( turl, rect, i );
- }
- }
- }
- }
- break;
+ if ( feedback && feedback->isPreviewOnly() )
+ _drawDebugRect( p, ti.rect, Qt::green );
+ }
+ p.end();
- default:
- QgsDebugMsg( QString( "unexpected tile mode %1" ).arg( mTileLayer->tileMode ) );
- return mCachedImage;
+ int t2 = t.elapsed() - t1;
+ Q_UNUSED( t2 ); // only used in debug build
+
+ if ( feedback && feedback->isPreviewOnly() )
+ {
+ QgsDebugMsg( QString( "PREVIEW - CACHED: %1 / MISSING: %2" ).arg( tileImages.count() ).arg( requests.count() - tileImages.count() ) );
+ QgsDebugMsg( QString( "PREVIEW - TIME: this res %1 ms | other res %2 ms | TOTAL %3 ms" ).arg( t0 + t2 ).arg( t1 ).arg( t0 + t1 + t2 ) );
}
+ else if ( !requestsFinal.isEmpty() )
+ {
+ // let the feedback object know about the tiles we have already
+ if ( feedback && feedback->renderPartialOutput() )
+ feedback->onNewData();
- emit statusChanged( tr( "Getting tiles." ) );
+ // order tile requests according to the distance from view center
+ LessThanTileRequest cmp;
+ cmp.center = viewExtent.center();
+ qSort( requestsFinal.begin(), requestsFinal.end(), cmp );
- QgsWmsTiledImageDownloadHandler handler( dataSourceUri(), mSettings.authorization(), mTileReqNo, requests, mCachedImage, mCachedViewExtent, mSettings.mSmoothPixmapTransform );
- handler.downloadBlocking();
+ QgsWmsTiledImageDownloadHandler handler( dataSourceUri(), mSettings.authorization(), mTileReqNo, requestsFinal, image, viewExtent, mSettings.mSmoothPixmapTransform, feedback );
+ handler.downloadBlocking();
+ }
+ QgsDebugMsg( QString( "TILE CACHE total: %1 / %2" ).arg( QgsTileCache::totalCost() ).arg( QgsTileCache::maxCost() ) );
#if 0
const QgsWmsStatistics::Stat& stat = QgsWmsStatistics::statForUri( dataSourceUri() );
@@ -860,14 +863,14 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, in
#endif
}
- return mCachedImage;
+ return image;
}
-void QgsWmsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight, void *block )
+void QgsWmsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight, void *block, QgsRasterBlockFeedback* feedback )
{
Q_UNUSED( bandNo );
// TODO: optimize to avoid writing to QImage
- QImage *image = draw( viewExtent, pixelWidth, pixelHeight );
+ QImage *image = draw( viewExtent, pixelWidth, pixelHeight, feedback );
if ( !image ) // should not happen
{
QgsMessageLog::logMessage( tr( "image is NULL" ), tr( "WMS" ) );
@@ -880,6 +883,7 @@ void QgsWmsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
if ( myExpectedSize != myImageSize ) // should not happen
{
QgsMessageLog::logMessage( tr( "unexpected image size" ), tr( "WMS" ) );
+ delete image;
return;
}
@@ -889,8 +893,245 @@ void QgsWmsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
// If image is too large, ptr can be NULL
memcpy( block, ptr, myExpectedSize );
}
- // do not delete the image, it is handled by draw()
- //delete image;
+
+ delete image;
+}
+
+QUrl QgsWmsProvider::createRequestUrlWMS( const QgsRectangle& viewExtent, int pixelWidth, int pixelHeight )
+{
+ // Calculate active layers that are also visible.
+
+ bool changeXY = mCaps.shouldInvertAxisOrientation( mImageCrs );
+
+ QgsDebugMsg( "Active layer list of " + mSettings.mActiveSubLayers.join( ", " )
+ + " and style list of " + mSettings.mActiveSubStyles.join( ", " ) );
+
+ QStringList visibleLayers = QStringList();
+ QStringList visibleStyles = QStringList();
+
+ QStringList::const_iterator it2 = mSettings.mActiveSubStyles.constBegin();
+
+ for ( QStringList::const_iterator it = mSettings.mActiveSubLayers.constBegin();
+ it != mSettings.mActiveSubLayers.constEnd();
+ ++it )
+ {
+ if ( mActiveSubLayerVisibility.constFind( *it ).value() )
+ {
+ visibleLayers += *it;
+ visibleStyles += *it2;
+ }
+
+ ++it2;
+ }
+
+ QString layers = visibleLayers.join( "," );
+ layers = layers.isNull() ? "" : layers;
+ QString styles = visibleStyles.join( "," );
+ styles = styles.isNull() ? "" : styles;
+
+ QgsDebugMsg( "Visible layer list of " + layers + " and style list of " + styles );
+
+ QString bbox = toParamValue( viewExtent, changeXY );
+
+ QUrl url( mSettings.mIgnoreGetMapUrl ? mSettings.mBaseUrl : getMapUrl() );
+ setQueryItem( url, "SERVICE", "WMS" );
+ setQueryItem( url, "VERSION", mCaps.mCapabilities.version );
+ setQueryItem( url, "REQUEST", "GetMap" );
+ setQueryItem( url, "BBOX", bbox );
+ setSRSQueryItem( url );
+ setQueryItem( url, "WIDTH", QString::number( pixelWidth ) );
+ setQueryItem( url, "HEIGHT", QString::number( pixelHeight ) );
+ setQueryItem( url, "LAYERS", layers );
+ setQueryItem( url, "STYLES", styles );
+ setFormatQueryItem( url );
+
+ if ( mDpi != -1 )
+ {
+ if ( mSettings.mDpiMode & dpiQGIS )
+ setQueryItem( url, "DPI", QString::number( mDpi ) );
+ if ( mSettings.mDpiMode & dpiUMN )
+ setQueryItem( url, "MAP_RESOLUTION", QString::number( mDpi ) );
+ if ( mSettings.mDpiMode & dpiGeoServer )
+ setQueryItem( url, "FORMAT_OPTIONS", QString( "dpi:%1" ).arg( mDpi ) );
+ }
+
+ //MH: jpeg does not support transparency and some servers complain if jpg and transparent=true
+ if ( mSettings.mImageMimeType == "image/x-jpegorpng" ||
+ ( !mSettings.mImageMimeType.contains( "jpeg", Qt::CaseInsensitive ) &&
+ !mSettings.mImageMimeType.contains( "jpg", Qt::CaseInsensitive ) ) )
+ {
+ setQueryItem( url, "TRANSPARENT", "TRUE" ); // some servers giving error for 'true' (lowercase)
+ }
+
+ QgsDebugMsg( QString( "getmap: %1" ).arg( url.toString() ) );
+ return url;
+}
+
+
+void QgsWmsProvider::createTileRequestsWMSC( const QgsWmtsTileMatrix* tm, const QgsWmsProvider::TilePositions& tiles, QgsWmsProvider::TileRequests& requests )
+{
+ bool changeXY = mCaps.shouldInvertAxisOrientation( mImageCrs );
+
+ // add WMS request
+ QUrl url( mSettings.mIgnoreGetMapUrl ? mSettings.mBaseUrl : getMapUrl() );
+ setQueryItem( url, "SERVICE", "WMS" );
+ setQueryItem( url, "VERSION", mCaps.mCapabilities.version );
+ setQueryItem( url, "REQUEST", "GetMap" );
+ setQueryItem( url, "LAYERS", mSettings.mActiveSubLayers.join( "," ) );
+ setQueryItem( url, "STYLES", mSettings.mActiveSubStyles.join( "," ) );
+ setQueryItem( url, "WIDTH", QString::number( tm->tileWidth ) );
+ setQueryItem( url, "HEIGHT", QString::number( tm->tileHeight ) );
+ setFormatQueryItem( url );
+
+ setSRSQueryItem( url );
+
+ if ( mSettings.mTiled )
+ {
+ setQueryItem( url, "TILED", "true" );
+ }
+
+ if ( mDpi != -1 )
+ {
+ if ( mSettings.mDpiMode & dpiQGIS )
+ setQueryItem( url, "DPI", QString::number( mDpi ) );
+ if ( mSettings.mDpiMode & dpiUMN )
+ setQueryItem( url, "MAP_RESOLUTION", QString::number( mDpi ) );
+ if ( mSettings.mDpiMode & dpiGeoServer )
+ setQueryItem( url, "FORMAT_OPTIONS", QString( "dpi:%1" ).arg( mDpi ) );
+ }
+
+ if ( mSettings.mImageMimeType == "image/x-jpegorpng" ||
+ ( !mSettings.mImageMimeType.contains( "jpeg", Qt::CaseInsensitive ) &&
+ !mSettings.mImageMimeType.contains( "jpg", Qt::CaseInsensitive ) ) )
+ {
+ setQueryItem( url, "TRANSPARENT", "TRUE" ); // some servers giving error for 'true' (lowercase)
+ }
+
+ int i = 0;
+ Q_FOREACH ( const TilePosition& tile, tiles )
+ {
+ QgsRectangle bbox( tm->tileBBox( tile.col, tile.row ) );
+ QString turl;
+ turl += url.toString();
+ turl += QString( changeXY ? "&BBOX=%2,%1,%4,%3" : "&BBOX=%1,%2,%3,%4" )
+ .arg( qgsDoubleToString( bbox.xMinimum() ),
+ qgsDoubleToString( bbox.yMinimum() ),
+ qgsDoubleToString( bbox.xMaximum() ),
+ qgsDoubleToString( bbox.yMaximum() ) );
+
+ QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i ).arg( tiles.count() ).arg( tile.row ).arg( tile.col ).arg( turl ) );
+ requests << TileRequest( turl, tm->tileRect( tile.col, tile.row ), i );
+ ++i;
+ }
+}
+
+
+void QgsWmsProvider::createTileRequestsWMTS( const QgsWmtsTileMatrix* tm, const QgsWmsProvider::TilePositions& tiles, QgsWmsProvider::TileRequests& requests )
+{
+ if ( !getTileUrl().isNull() )
+ {
+ // KVP
+ QUrl url( mSettings.mIgnoreGetMapUrl ? mSettings.mBaseUrl : getTileUrl() );
+
+ // compose static request arguments.
+ setQueryItem( url, "SERVICE", "WMTS" );
+ setQueryItem( url, "REQUEST", "GetTile" );
+ setQueryItem( url, "VERSION", mCaps.mCapabilities.version );
+ setQueryItem( url, "LAYER", mSettings.mActiveSubLayers[0] );
+ setQueryItem( url, "STYLE", mSettings.mActiveSubStyles[0] );
+ setQueryItem( url, "FORMAT", mSettings.mImageMimeType );
+ setQueryItem( url, "TILEMATRIXSET", mTileMatrixSet->identifier );
+ setQueryItem( url, "TILEMATRIX", tm->identifier );
+
+ for ( QHash<QString, QString>::const_iterator it = mSettings.mTileDimensionValues.constBegin(); it != mSettings.mTileDimensionValues.constEnd(); ++it )
+ {
+ setQueryItem( url, it.key(), it.value() );
+ }
+
+ url.removeQueryItem( "TILEROW" );
+ url.removeQueryItem( "TILECOL" );
+
+ int i = 0;
+ Q_FOREACH ( const TilePosition& tile, tiles )
+ {
+ QString turl;
+ turl += url.toString();
+ turl += QString( "&TILEROW=%1&TILECOL=%2" ).arg( tile.row ).arg( tile.col );
+
+ QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i ).arg( tiles.count() ).arg( tile.row ).arg( tile.col ).arg( turl ) );
+ requests << TileRequest( turl, tm->tileRect( tile.col, tile.row ), i );
+ ++i;
+ }
+ }
+ else
+ {
+ // REST
+ QString url = mTileLayer->getTileURLs[ mSettings.mImageMimeType ];
+
+ url.replace( "{layer}", mSettings.mActiveSubLayers[0], Qt::CaseInsensitive );
+ url.replace( "{style}", mSettings.mActiveSubStyles[0], Qt::CaseInsensitive );
+ url.replace( "{tilematrixset}", mTileMatrixSet->identifier, Qt::CaseInsensitive );
+ url.replace( "{tilematrix}", tm->identifier, Qt::CaseInsensitive );
+
+ for ( QHash<QString, QString>::const_iterator it = mSettings.mTileDimensionValues.constBegin(); it != mSettings.mTileDimensionValues.constEnd(); ++it )
+ {
+ url.replace( "{" + it.key() + "}", it.value(), Qt::CaseInsensitive );
+ }
+
+ int i = 0;
+ Q_FOREACH ( const TilePosition& tile, tiles )
+ {
+ QString turl( url );
+ turl.replace( "{tilerow}", QString::number( tile.row ), Qt::CaseInsensitive );
+ turl.replace( "{tilecol}", QString::number( tile.col ), Qt::CaseInsensitive );
+
+ QgsDebugMsgLevel( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i ).arg( tiles.count() ).arg( tile.row ).arg( tile.col ).arg( turl ), 2 );
+ requests << TileRequest( turl, tm->tileRect( tile.col, tile.row ), i );
+ ++i;
+ }
+ }
+}
+
+
+// support for Bing Maps tile system
+// https://msdn.microsoft.com/en-us/library/bb259689.aspx
+static QString _tile2quadkey( int tileX, int tileY, int z )
+{
+ QString quadKey;
+ for ( int i = z; i > 0; i-- )
+ {
+ char digit = '0';
+ int mask = 1 << ( i - 1 );
+ if ( tileX & mask )
+ digit++;
+ if ( tileY & mask )
+ digit += 2;
+ quadKey.append( QChar( digit ) );
+ }
+ return quadKey;
+}
+
+
+void QgsWmsProvider::createTileRequestsXYZ( const QgsWmtsTileMatrix* tm, const QgsWmsProvider::TilePositions& tiles, QgsWmsProvider::TileRequests& requests )
+{
+ int z = tm->identifier.toInt();
+ QString url = mSettings.mBaseUrl;
+ int i = 0;
+ Q_FOREACH ( const TilePosition& tile, tiles )
+ {
+ ++i;
+ QString turl( url );
+
+ if ( turl.contains( "{q}" ) ) // used in Bing maps
+ turl.replace( "{q}", _tile2quadkey( tile.col, tile.row, z ) );
+
+ turl.replace( "{x}", QString::number( tile.col ), Qt::CaseInsensitive );
+ turl.replace( "{y}", QString::number( tile.row ), Qt::CaseInsensitive );
+ turl.replace( "{z}", QString::number( z ), Qt::CaseInsensitive );
+
+ QgsDebugMsgLevel( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i ).arg( tiles.count() ).arg( tile.row ).arg( tile.col ).arg( turl ), 2 );
+ requests << TileRequest( turl, tm->tileRect( tile.col, tile.row ), i );
+ }
}
@@ -927,6 +1168,58 @@ bool QgsWmsProvider::retrieveServerCapabilities( bool forceRefresh )
}
+void QgsWmsProvider::setupXyzCapabilities( const QString &uri )
+{
+ QgsDataSourceURI parsedUri;
+ parsedUri.setEncodedUri( uri );
+
+ QgsCoordinateTransform ct( QgsCoordinateReferenceSystem( "EPSG:4326" ), QgsCoordinateReferenceSystem( mSettings.mCrsId ) );
+ // the whole world is projected to a square:
+ // X going from 180 W to 180 E
+ // Y going from ~85 N to ~85 S (=atan(sinh(pi)) ... to get a square)
+ QgsPoint topLeftLonLat( -180, 180.0 / M_PI * atan( sinh( M_PI ) ) );
+ QgsPoint bottomRightLonLat( 180, 180.0 / M_PI * atan( sinh( -M_PI ) ) );
+ QgsPoint topLeft = ct.transform( topLeftLonLat );
+ QgsPoint bottomRight = ct.transform( bottomRightLonLat );
+ double xspan = ( bottomRight.x() - topLeft.x() );
+
+ QgsWmsBoundingBoxProperty bbox;
+ bbox.crs = mSettings.mCrsId;
+ bbox.box = QgsRectangle( topLeft.x(), bottomRight.y(), bottomRight.x(), topLeft.y() );
+
+ QgsWmtsTileLayer tl;
+ tl.tileMode = XYZ;
+ tl.identifier = "xyz"; // as set in parseUri
+ tl.boundingBoxes << bbox;
+ mCaps.mTileLayersSupported.append( tl );
+
+ QgsWmtsTileMatrixSet tms;
+ tms.identifier = "tms0"; // as set in parseUri
+ tms.crs = mSettings.mCrsId;
+ mCaps.mTileMatrixSets[tms.identifier] = tms;
+
+ int minZoom = 0;
+ int maxZoom = 18;
+ if ( parsedUri.hasParam( "zmin" ) )
+ minZoom = parsedUri.param( "zmin" ).toInt();
+ if ( parsedUri.hasParam( "zmax" ) )
+ maxZoom = parsedUri.param( "zmax" ).toInt();
+
+ // zoom 0 is one tile for the whole world
+ for ( int zoom = minZoom; zoom <= maxZoom; ++zoom )
+ {
+ QgsWmtsTileMatrix tm;
+ tm.identifier = QString::number( zoom );
+ tm.topLeft = topLeft;
+ tm.tileWidth = tm.tileHeight = 256;
+ tm.matrixWidth = tm.matrixHeight = 1 << zoom;
+ tm.tres = xspan / ( tm.tileWidth * tm.matrixWidth );
+
+ mCaps.mTileMatrixSets[tms.identifier].tileMatrices[tm.tres] = tm;
+ }
+}
+
+
QGis::DataType QgsWmsProvider::dataType( int bandNo ) const
{
return srcDataType( bandNo );
@@ -1827,6 +2120,10 @@ QString QgsWmsProvider::metadata()
{
metadata += tr( "WMS-C" );
}
+ else if ( l.tileMode == XYZ )
+ {
+ metadata += tr( "XYZ" );
+ }
else
{
metadata += tr( "Invalid tile mode" );
@@ -2680,7 +2977,7 @@ QgsRasterIdentifyResult QgsWmsProvider::identify( const QgsPoint & thePoint, Qgs
QString crsType = result.property( "crs" ).property( "type" ).toString();
QString crsText;
if ( crsType == "name" )
- crsText = result.property( "crs" ).property( "name" ).toString();
+ crsText = result.property( "crs" ).property( "properties" ).property( "name" ).toString();
else if ( crsType == "EPSG" )
crsText = QString( "%1:%2" ).arg( crsType, result.property( "crs" ).property( "properties" ).property( "code" ).toString() );
else
@@ -2775,6 +3072,7 @@ QgsRasterIdentifyResult QgsWmsProvider::identify( const QgsPoint & thePoint, Qgs
catch ( const QString &err )
{
QgsDebugMsg( QString( "JSON error: %1\nResult: %2" ).arg( err, QString::fromUtf8( mIdentifyResultBodies.value( jsonPart ) ) ) );
+ results.insert( results.size(), err ); // string returned for format type "feature" means error
}
delete coordinateTransform;
@@ -2807,6 +3105,7 @@ void QgsWmsProvider::identifyReplyFinished()
QgsDebugMsg( QString( "redirected getfeatureinfo: %1" ).arg( redirect.toString() ) );
mIdentifyReply = QgsNetworkAccessManager::instance()->get( QNetworkRequest( redirect.toUrl() ) );
+ mSettings.authorization().setAuthorizationReply( mIdentifyReply );
mIdentifyReply->setProperty( "eventLoop", QVariant::fromValue( qobject_cast<QObject *>( loop ) ) );
connect( mIdentifyReply, SIGNAL( finished() ), this, SLOT( identifyReplyFinished() ) );
return;
@@ -2889,8 +3188,6 @@ QString QgsWmsProvider::description() const
void QgsWmsProvider::reloadData()
{
- delete mCachedImage;
- mCachedImage = nullptr;
}
@@ -3216,11 +3513,22 @@ QGISEXTERN bool isProvider()
// -----------------
-QgsWmsImageDownloadHandler::QgsWmsImageDownloadHandler( const QString& providerUri, const QUrl& url, const QgsWmsAuthorization& auth, QImage* image )
+QgsWmsImageDownloadHandler::QgsWmsImageDownloadHandler( const QString& providerUri, const QUrl& url, const QgsWmsAuthorization& auth, QImage* image, QgsRasterBlockFeedback* feedback )
: mProviderUri( providerUri )
, mCachedImage( image )
, mEventLoop( new QEventLoop )
+ , mFeedback( feedback )
{
+ if ( feedback )
+ {
+ connect( feedback, SIGNAL( cancelled() ), this, SLOT( cancelled() ), Qt::QueuedConnection );
+
+ // rendering could have been cancelled before we started to listen to cancelled() signal
+ // so let's check before doing the download and maybe quit prematurely
+ if ( feedback->isCancelled() )
+ return;
+ }
+
QNetworkRequest request( url );
auth.setAuthorization( request );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
@@ -3229,7 +3537,6 @@ QgsWmsImageDownloadHandler::QgsWmsImageDownloadHandler( const QString& providerU
connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ) );
Q_ASSERT( mCacheReply->thread() == QThread::currentThread() );
-
}
QgsWmsImageDownloadHandler::~QgsWmsImageDownloadHandler()
@@ -3239,6 +3546,9 @@ QgsWmsImageDownloadHandler::~QgsWmsImageDownloadHandler()
void QgsWmsImageDownloadHandler::downloadBlocking()
{
+ if ( mFeedback && mFeedback->isCancelled() )
+ return; // nothing to do
+
mEventLoop->exec( QEventLoop::ExcludeUserInputEvents );
Q_ASSERT( !mCacheReply );
@@ -3323,16 +3633,20 @@ void QgsWmsImageDownloadHandler::cacheReplyFinished()
}
else
{
- QgsWmsStatistics::Stat& stat = QgsWmsStatistics::statForUri( mProviderUri );
-
- stat.errors++;
- if ( stat.errors < 100 )
+ // report any errors except for the one we have caused by cancelling the request
+ if ( mCacheReply->error() != QNetworkReply::OperationCanceledError )
{
- QgsMessageLog::logMessage( tr( "Map request failed [error:%1 url:%2]" ).arg( mCacheReply->errorString(), mCacheReply->url().toString() ), tr( "WMS" ) );
- }
- else if ( stat.errors == 100 )
- {
- QgsMessageLog::logMessage( tr( "Not logging more than 100 request errors." ), tr( "WMS" ) );
+ QgsWmsStatistics::Stat& stat = QgsWmsStatistics::statForUri( mProviderUri );
+
+ stat.errors++;
+ if ( stat.errors < 100 )
+ {
+ QgsMessageLog::logMessage( tr( "Map request failed [error:%1 url:%2]" ).arg( mCacheReply->errorString(), mCacheReply->url().toString() ), tr( "WMS" ) );
+ }
+ else if ( stat.errors == 100 )
+ {
+ QgsMessageLog::logMessage( tr( "Not logging more than 100 request errors." ), tr( "WMS" ) );
+ }
}
mCacheReply->deleteLater();
@@ -3349,20 +3663,42 @@ void QgsWmsImageDownloadHandler::cacheReplyProgress( qint64 bytesReceived, qint6
QgsDebugMsg( tr( "%1 of %2 bytes of map downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QString( "unknown number of" ) : QString::number( bytesTotal ) ) );
}
+void QgsWmsImageDownloadHandler::cancelled()
+{
+ QgsDebugMsg( "Caught cancelled() signal" );
+ if ( mCacheReply )
+ {
+ // abort the reply if it is still active
+ QgsDebugMsg( "Aborting WMS network request" );
+ mCacheReply->abort();
+ }
+}
+
// ----------
-QgsWmsTiledImageDownloadHandler::QgsWmsTiledImageDownloadHandler( const QString& providerUri, const QgsWmsAuthorization& auth, int tileReqNo, const QList<QgsWmsTiledImageDownloadHandler::TileRequest>& requests, QImage* cachedImage, const QgsRectangle& cachedViewExtent, bool smoothPixmapTransform )
+QgsWmsTiledImageDownloadHandler::QgsWmsTiledImageDownloadHandler( const QString& providerUri, const QgsWmsAuthorization& auth, int tileReqNo, const QgsWmsProvider::TileRequests& requests, QImage* image, const QgsRectangle& viewExtent, bool smoothPixmapTransform, QgsRasterBlockFeedback* feedback )
: mProviderUri( providerUri )
, mAuth( auth )
- , mCachedImage( cachedImage )
- , mCachedViewExtent( cachedViewExtent )
+ , mImage( image )
+ , mViewExtent( viewExtent )
, mEventLoop( new QEventLoop )
, mTileReqNo( tileReqNo )
, mSmoothPixmapTransform( smoothPixmapTransform )
+ , mFeedback( feedback )
{
- Q_FOREACH ( const TileRequest& r, requests )
+ if ( feedback )
+ {
+ connect( feedback, SIGNAL( cancelled() ), this, SLOT( cancelled() ), Qt::QueuedConnection );
+
+ // rendering could have been cancelled before we started to listen to cancelled() signal
+ // so let's check before doing the download and maybe quit prematurely
+ if ( feedback->isCancelled() )
+ return;
+ }
+
+ Q_FOREACH ( const QgsWmsProvider::TileRequest& r, requests )
{
QNetworkRequest request( r.url );
auth.setAuthorization( request );
@@ -3387,6 +3723,9 @@ QgsWmsTiledImageDownloadHandler::~QgsWmsTiledImageDownloadHandler()
void QgsWmsTiledImageDownloadHandler::downloadBlocking()
{
+ if ( mFeedback && mFeedback->isCancelled() )
+ return; // nothing to do
+
mEventLoop->exec( QEventLoop::ExcludeUserInputEvents );
Q_ASSERT( mReplies.isEmpty() );
@@ -3536,10 +3875,10 @@ void QgsWmsTiledImageDownloadHandler::tileReplyFinished()
// only take results from current request number
if ( mTileReqNo == tileReqNo )
{
- double cr = mCachedViewExtent.width() / mCachedImage->width();
+ double cr = mViewExtent.width() / mImage->width();
- QRectF dst(( r.left() - mCachedViewExtent.xMinimum() ) / cr,
- ( mCachedViewExtent.yMaximum() - r.bottom() ) / cr,
+ QRectF dst(( r.left() - mViewExtent.xMinimum() ) / cr,
+ ( mViewExtent.yMaximum() - r.bottom() ) / cr,
r.width() / cr,
r.height() / cr );
@@ -3549,7 +3888,7 @@ void QgsWmsTiledImageDownloadHandler::tileReplyFinished()
if ( !myLocalImage.isNull() )
{
- QPainter p( mCachedImage );
+ QPainter p( mImage );
if ( mSmoothPixmapTransform )
p.setRenderHint( QPainter::SmoothPixmapTransform, true );
p.drawImage( dst, myLocalImage );
@@ -3562,6 +3901,11 @@ void QgsWmsTiledImageDownloadHandler::tileReplyFinished()
.arg( r.right() ).arg( r.top() )
.arg( r.width() ).arg( r.height() ) );
#endif
+
+ QgsTileCache::insertTile( reply->url(), myLocalImage );
+
+ if ( mFeedback )
+ mFeedback->onNewData();
}
else
{
@@ -3585,10 +3929,17 @@ void QgsWmsTiledImageDownloadHandler::tileReplyFinished()
}
else
{
- QgsWmsStatistics::Stat& stat = QgsWmsStatistics::statForUri( mProviderUri );
- stat.errors++;
+ if ( !( mFeedback && mFeedback->isPreviewOnly() ) )
+ {
+ // report any errors except for the one we have caused by cancelling the request
+ if ( reply->error() != QNetworkReply::OperationCanceledError )
+ {
+ QgsWmsStatistics::Stat& stat = QgsWmsStatistics::statForUri( mProviderUri );
+ stat.errors++;
- repeatTileRequest( reply->request() );
+ repeatTileRequest( reply->request() );
+ }
+ }
mReplies.removeOne( reply );
reply->deleteLater();
@@ -3607,6 +3958,16 @@ void QgsWmsTiledImageDownloadHandler::tileReplyFinished()
#endif
}
+void QgsWmsTiledImageDownloadHandler::cancelled()
+{
+ QgsDebugMsg( "Caught cancelled() signal" );
+ Q_FOREACH ( QNetworkReply* reply, mReplies )
+ {
+ QgsDebugMsg( "Aborting tiled network request" );
+ reply->abort();
+ }
+}
+
void QgsWmsTiledImageDownloadHandler::repeatTileRequest( QNetworkRequest const &oldRequest )
{
@@ -3734,6 +4095,7 @@ QgsWmsLegendDownloadHandler::startUrl( const QUrl& url )
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
mReply = mNetworkAccessManager.get( request );
+ mSettings.authorization().setAuthorizationReply( mReply );
connect( mReply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( errored( QNetworkReply::NetworkError ) ) );
connect( mReply, SIGNAL( finished() ), this, SLOT( finished() ) );
connect( mReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( progressed( qint64, qint64 ) ) );
diff --git a/src/providers/wms/qgswmsprovider.h b/src/providers/wms/qgswmsprovider.h
index 5e10654..8320d98 100644
--- a/src/providers/wms/qgswmsprovider.h
+++ b/src/providers/wms/qgswmsprovider.h
@@ -168,7 +168,7 @@ class QgsWmsProvider : public QgsRasterDataProvider
*/
QImage *draw( QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight ) override;
- void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data ) override;
+ void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data, QgsRasterBlockFeedback* feedback = nullptr ) override;
//void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, QgsCoordinateReferenceSystem theSrcCRS, QgsCoordinateReferenceSystem theDestCRS, void *data );
@@ -358,6 +358,30 @@ class QgsWmsProvider : public QgsRasterDataProvider
*/
static QString prepareUri( QString uri );
+ //! Helper struct for tile requests
+ struct TileRequest
+ {
+ TileRequest( const QUrl& u, const QRectF& r, int i )
+ : url( u )
+ , rect( r )
+ , index( i )
+ {}
+ QUrl url;
+ QRectF rect;
+ int index;
+ };
+ typedef QList<TileRequest> TileRequests;
+
+ //! Tile identifier within a tile source
+ typedef struct TilePosition
+ {
+ TilePosition( int r, int c ): row( r ), col( c ) {}
+ bool operator==( const TilePosition& other ) const { return row == other.row && col == other.col; }
+ int row;
+ int col;
+ } TilePosition;
+ typedef QList<TilePosition> TilePositions;
+
signals:
/** \brief emit a signal to notify of a progress event */
@@ -373,6 +397,11 @@ class QgsWmsProvider : public QgsRasterDataProvider
private:
+ //! In case of XYZ tile layer, setup capabilities from its URI
+ void setupXyzCapabilities( const QString& uri );
+
+ QImage *draw( QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight, QgsRasterBlockFeedback* feedback );
+
/**
* Try to get best extent for the layer in given CRS. Returns true on success, false otherwise (layer not found, invalid CRS, transform failed)
*/
@@ -432,6 +461,21 @@ class QgsWmsProvider : public QgsRasterDataProvider
private:
+ QUrl createRequestUrlWMS( const QgsRectangle& viewExtent, int pixelWidth, int pixelHeight );
+ void createTileRequestsWMSC( const QgsWmtsTileMatrix* tm, const QgsWmsProvider::TilePositions& tiles, QgsWmsProvider::TileRequests& requests );
+ void createTileRequestsWMTS( const QgsWmtsTileMatrix* tm, const QgsWmsProvider::TilePositions& tiles, QgsWmsProvider::TileRequests& requests );
+ void createTileRequestsXYZ( const QgsWmtsTileMatrix* tm, const QgsWmsProvider::TilePositions& tiles, QgsWmsProvider::TileRequests& requests );
+
+ //! Helper structure to store a cached tile image with its rectangle
+ typedef struct TileImage
+ {
+ TileImage( QRectF r, QImage i ): rect( r ), img( i ) {}
+ QRectF rect; //!< destination rectangle for a tile (in screen coordinates)
+ QImage img; //!< cached tile to be drawn
+ } TileImage;
+ //! Get tiles from a different resolution to cover the missing areas
+ void fetchOtherResTiles( QgsTileMode tileMode, const QgsRectangle& viewExtent, int imageWidth, QList<QRectF>& missing, double tres, int resOffset, QList<TileImage> &otherResTiles );
+
/** Return the full url to request legend graphic
* The visibleExtent isi only used if provider supports contextual
* legends according to the QgsWmsSettings
@@ -497,13 +541,6 @@ class QgsWmsProvider : public QgsRasterDataProvider
QString mImageCrs;
/**
- * The previously retrieved image from the WMS server.
- * This can be reused if draw() is called consecutively
- * with the same parameters.
- */
- QImage *mCachedImage;
-
- /**
* The reply to the capabilities request
*/
QNetworkReply *mIdentifyReply;
@@ -519,13 +556,6 @@ class QgsWmsProvider : public QgsRasterDataProvider
QString mIdentifyResultXsd;
/**
- * The previous parameters to draw().
- */
- QgsRectangle mCachedViewExtent;
- int mCachedViewWidth;
- int mCachedViewHeight;
-
- /**
* The error caption associated with the last WMS error.
*/
QString mErrorCaption;
@@ -540,9 +570,6 @@ class QgsWmsProvider : public QgsRasterDataProvider
*/
QString mErrorFormat;
- //! A QgsCoordinateTransform is used for transformation of WMS layer extents
- QgsCoordinateTransform *mCoordinateTransform;
-
//! See if calculateExtents() needs to be called before extent() returns useful data
bool mExtentDirty;
@@ -574,7 +601,7 @@ class QgsWmsImageDownloadHandler : public QObject
{
Q_OBJECT
public:
- QgsWmsImageDownloadHandler( const QString& providerUri, const QUrl& url, const QgsWmsAuthorization& auth, QImage* image );
+ QgsWmsImageDownloadHandler( const QString& providerUri, const QUrl& url, const QgsWmsAuthorization& auth, QImage* image, QgsRasterBlockFeedback* feedback );
~QgsWmsImageDownloadHandler();
void downloadBlocking();
@@ -582,6 +609,7 @@ class QgsWmsImageDownloadHandler : public QObject
protected slots:
void cacheReplyFinished();
void cacheReplyProgress( qint64 bytesReceived, qint64 bytesTotal );
+ void cancelled();
protected:
void finish() { QMetaObject::invokeMethod( mEventLoop, "quit", Qt::QueuedConnection ); }
@@ -592,6 +620,8 @@ class QgsWmsImageDownloadHandler : public QObject
QImage* mCachedImage;
QEventLoop* mEventLoop;
+
+ QgsRasterBlockFeedback* mFeedback;
};
@@ -601,25 +631,14 @@ class QgsWmsTiledImageDownloadHandler : public QObject
Q_OBJECT
public:
- struct TileRequest
- {
- TileRequest( const QUrl& u, const QRectF& r, int i )
- : url( u )
- , rect( r )
- , index( i )
- {}
- QUrl url;
- QRectF rect;
- int index;
- };
-
- QgsWmsTiledImageDownloadHandler( const QString& providerUri, const QgsWmsAuthorization& auth, int reqNo, const QList<TileRequest>& requests, QImage* cachedImage, const QgsRectangle& cachedViewExtent, bool smoothPixmapTransform );
+ QgsWmsTiledImageDownloadHandler( const QString& providerUri, const QgsWmsAuthorization& auth, int reqNo, const QgsWmsProvider::TileRequests& requests, QImage* image, const QgsRectangle& viewExtent, bool smoothPixmapTransform, QgsRasterBlockFeedback* feedback );
~QgsWmsTiledImageDownloadHandler();
void downloadBlocking();
protected slots:
void tileReplyFinished();
+ void cancelled();
protected:
/**
@@ -637,8 +656,8 @@ class QgsWmsTiledImageDownloadHandler : public QObject
QgsWmsAuthorization mAuth;
- QImage* mCachedImage;
- QgsRectangle mCachedViewExtent;
+ QImage* mImage;
+ QgsRectangle mViewExtent;
QEventLoop* mEventLoop;
@@ -647,6 +666,8 @@ class QgsWmsTiledImageDownloadHandler : public QObject
//! Running tile requests
QList<QNetworkReply*> mReplies;
+
+ QgsRasterBlockFeedback* mFeedback;
};
diff --git a/src/providers/wms/qgsxyzconnection.cpp b/src/providers/wms/qgsxyzconnection.cpp
new file mode 100644
index 0000000..c0f410b
--- /dev/null
+++ b/src/providers/wms/qgsxyzconnection.cpp
@@ -0,0 +1,59 @@
+/***************************************************************************
+ qgsxyzconnection.h
+ ---------------------
+ begin : August 2016
+ copyright : (C) 2016 by Martin Dobias
+ email : wonder dot sk at gmail dot com
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "qgsxyzconnection.h"
+
+#include "qgsdatasourceuri.h"
+
+#include <QSettings>
+
+QString QgsXyzConnection::encodedUri() const
+{
+ QgsDataSourceURI uri;
+ uri.setParam( "type", "xyz" );
+ uri.setParam( "url", url );
+ return uri.encodedUri();
+}
+
+QStringList QgsXyzConnectionUtils::connectionList()
+{
+ QSettings settings;
+ settings.beginGroup( "/Qgis/connections-xyz" );
+ return settings.childGroups();
+}
+
+QgsXyzConnection QgsXyzConnectionUtils::connection( const QString &name )
+{
+ QSettings settings;
+ settings.beginGroup( "/Qgis/connections-xyz/" + name );
+
+ QgsXyzConnection conn;
+ conn.name = name;
+ conn.url = settings.value( "url" ).toString();
+ return conn;
+}
+
+void QgsXyzConnectionUtils::deleteConnection( const QString& name )
+{
+ QSettings settings;
+ settings.remove( "/Qgis/connections-xyz/" + name );
+}
+
+void QgsXyzConnectionUtils::addConnection( const QgsXyzConnection &conn )
+{
+ QSettings settings;
+ settings.beginGroup( "/Qgis/connections-xyz/" + conn.name );
+ settings.setValue( "url", conn.url );
+}
diff --git a/src/providers/wms/qgsxyzconnection.h b/src/providers/wms/qgsxyzconnection.h
new file mode 100644
index 0000000..ba18825
--- /dev/null
+++ b/src/providers/wms/qgsxyzconnection.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ qgsxyzconnection.h
+ ---------------------
+ begin : August 2016
+ copyright : (C) 2016 by Martin Dobias
+ email : wonder dot sk at gmail dot com
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSXYZCONNECTION_H
+#define QGSXYZCONNECTION_H
+
+#include <QStringList>
+
+struct QgsXyzConnection
+{
+ QString name;
+ QString url;
+
+ QString encodedUri() const;
+};
+
+/** Utility class for handling list of connections to XYZ tile layers */
+class QgsXyzConnectionUtils
+{
+ public:
+ //! Returns list of existing connections
+ static QStringList connectionList();
+
+ //! Returns connection details
+ static QgsXyzConnection connection( const QString& name );
+
+ //! Removes a connection from the list
+ static void deleteConnection( const QString& name );
+
+ //! Adds a new connection to the list
+ static void addConnection( const QgsXyzConnection& conn );
+};
+
+
+#endif // QGSXYZCONNECTION_H
diff --git a/src/python/qgspythonutilsimpl.cpp b/src/python/qgspythonutilsimpl.cpp
index 372ad3c..736f0ee 100644
--- a/src/python/qgspythonutilsimpl.cpp
+++ b/src/python/qgspythonutilsimpl.cpp
@@ -28,6 +28,7 @@
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgsmessageoutput.h"
+#include "qgsmessagelog.h"
#include <QMessageBox>
#include <QStringList>
@@ -35,11 +36,17 @@
#include <QDebug>
#if (PY_VERSION_HEX < 0x03000000)
-#define PYOBJ2QSTRING(obj) PyString_AsString( obj )
+QString PY_UNICODE2QSTRING( PyObject* obj )
+{
+ PyObject* utf8 = PyUnicode_AsUTF8String( obj );
+ QString result = utf8 ? QString::fromUtf8( PyString_AS_STRING( utf8 ) ) : "(qgis error)";
+ Py_XDECREF( utf8 );
+ return result;
+}
#elif (PY_VERSION_HEX < 0x03030000)
-#define PYOBJ2QSTRING(obj) QString::fromUtf8( PyBytes_AsString(PyUnicode_AsUTF8String( obj ) ) )
+#define PY_UNICODE2QSTRING(obj) QString::fromUtf8( PyBytes_AsString(PyUnicode_AsUTF8String( obj ) ) )
#else
-#define PYOBJ2QSTRING(obj) QString::fromUtf8( PyUnicode_AsUTF8( obj ) )
+#define PY_UNICODE2QSTRING(obj) QString::fromUtf8( PyUnicode_AsUTF8( obj ) )
#endif
PyThreadState* _mainState;
@@ -408,7 +415,7 @@ QString QgsPythonUtilsImpl::getTraceback()
)
TRACEBACK_FETCH_ERROR( "getvalue() did not return a string" );
- result = PYOBJ2QSTRING( obResult );
+ result = PyObjectToQString( obResult );
done:
@@ -512,7 +519,7 @@ QString QgsPythonUtilsImpl::PyObjectToQString( PyObject* obj )
// check whether the object is already a unicode string
if ( PyUnicode_Check( obj ) )
{
- result = PYOBJ2QSTRING( obj );
+ result = PY_UNICODE2QSTRING( obj );
return result;
}
@@ -528,15 +535,7 @@ QString QgsPythonUtilsImpl::PyObjectToQString( PyObject* obj )
PyObject* obj_uni = PyObject_Unicode( obj ); // obj_uni is new reference
if ( obj_uni )
{
- // get utf-8 representation of unicode string (new reference)
- PyObject* obj_utf8 = PyUnicode_AsUTF8String( obj_uni );
- // convert from utf-8 to QString
- if ( obj_utf8 )
- result = QString::fromUtf8( PyString_AsString( obj_utf8 ) );
- else
- result = "(qgis error)";
-
- Py_XDECREF( obj_utf8 );
+ result = PY_UNICODE2QSTRING( obj_uni );
Py_XDECREF( obj_uni );
return result;
}
@@ -546,7 +545,11 @@ QString QgsPythonUtilsImpl::PyObjectToQString( PyObject* obj )
PyObject* obj_str = PyObject_Str( obj ); // new reference
if ( obj_str )
{
- result = PYOBJ2QSTRING( obj_str );
+#if (PY_VERSION_HEX < 0x03000000)
+ result = QString::fromUtf8( PyString_AS_STRING( obj ) );
+#else
+ result = PY_UNICODE2QSTRING( obj_str );
+#endif
Py_XDECREF( obj_str );
return result;
}
@@ -556,7 +559,6 @@ QString QgsPythonUtilsImpl::PyObjectToQString( PyObject* obj )
return "(qgis error)";
}
-
bool QgsPythonUtilsImpl::evalString( const QString& command, QString& result )
{
// acquire global interpreter lock to ensure we are in a consistent state
@@ -566,7 +568,11 @@ bool QgsPythonUtilsImpl::evalString( const QString& command, QString& result )
PyObject* res = PyRun_String( command.toUtf8().data(), Py_eval_input, mMainDict, mMainDict );
bool success = nullptr != res;
- // TODO: error handling
+ if ( PyErr_Occurred() )
+ {
+ QString traceback = getTraceback();
+ QgsMessageLog::logMessage( QString( "evalString()) error!\nCommand:\n%1\nError:\n%2" ).arg( command ).arg( traceback ), "Python" );
+ }
if ( success )
result = PyObjectToQString( res );
diff --git a/src/server/qgsconfigparserutils.cpp b/src/server/qgsconfigparserutils.cpp
index ed20634..6788970 100644
--- a/src/server/qgsconfigparserutils.cpp
+++ b/src/server/qgsconfigparserutils.cpp
@@ -193,7 +193,15 @@ void QgsConfigParserUtils::appendLayerBoundingBox( QDomElement& layerElem, QDomD
if ( !layerExtent.isNull() )
{
QgsCoordinateTransform crsTransform( layerCRS, crs );
- crsExtent = crsTransform.transformBoundingBox( layerExtent );
+ try
+ {
+ crsExtent = crsTransform.transformBoundingBox( layerExtent );
+ }
+ catch ( QgsCsException &cse )
+ {
+ Q_UNUSED( cse );
+ return;
+ }
}
//BoundingBox element
diff --git a/src/server/qgshostedrdsbuilder.cpp b/src/server/qgshostedrdsbuilder.cpp
index 7ae417c..b347afc 100644
--- a/src/server/qgshostedrdsbuilder.cpp
+++ b/src/server/qgshostedrdsbuilder.cpp
@@ -60,7 +60,7 @@ QgsMapLayer* QgsHostedRDSBuilder::createMapLayer( const QDomElement& elem,
QgsRasterLayer* rl = nullptr;
if ( allowCaching )
{
- rl = dynamic_cast<QgsRasterLayer*>( QgsMSLayerCache::instance()->searchLayer( uri, layerName ) );
+ rl = qobject_cast<QgsRasterLayer*>( QgsMSLayerCache::instance()->searchLayer( uri, layerName ) );
}
if ( !rl )
{
diff --git a/src/server/qgsowsserver.cpp b/src/server/qgsowsserver.cpp
index 3532698..5768aa0 100644
--- a/src/server/qgsowsserver.cpp
+++ b/src/server/qgsowsserver.cpp
@@ -25,7 +25,7 @@
/** Apply filter from AccessControl */
void QgsOWSServer::applyAccessControlLayerFilters( QgsMapLayer* mapLayer, QHash<QgsMapLayer*, QString>& originalLayerFilters ) const
{
- if ( QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( mapLayer ) )
+ if ( QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( mapLayer ) )
{
QString sql = mAccessControl->extraSubsetString( layer );
if ( !sql.isEmpty() )
@@ -54,7 +54,7 @@ void QgsOWSServer::restoreLayerFilters( const QHash<QgsMapLayer*, QString>& filt
QHash<QgsMapLayer*, QString>::const_iterator filterIt = filterMap.constBegin();
for ( ; filterIt != filterMap.constEnd(); ++filterIt )
{
- QgsVectorLayer* filteredLayer = dynamic_cast<QgsVectorLayer*>( filterIt.key() );
+ QgsVectorLayer* filteredLayer = qobject_cast<QgsVectorLayer*>( filterIt.key() );
if ( filteredLayer )
{
QgsVectorDataProvider* dp = filteredLayer->dataProvider();
diff --git a/src/server/qgsremoteowsbuilder.cpp b/src/server/qgsremoteowsbuilder.cpp
index b2596ce..6b7bc2b 100644
--- a/src/server/qgsremoteowsbuilder.cpp
+++ b/src/server/qgsremoteowsbuilder.cpp
@@ -162,7 +162,7 @@ QgsRasterLayer* QgsRemoteOWSBuilder::wmsLayerFromUrl( const QString& url, const
if ( allowCaching )
{
- result = dynamic_cast<QgsRasterLayer*>( QgsMSLayerCache::instance()->searchLayer( url, layerName ) );
+ result = qobject_cast<QgsRasterLayer*>( QgsMSLayerCache::instance()->searchLayer( url, layerName ) );
}
if ( result )
@@ -414,7 +414,7 @@ QgsVectorLayer* QgsRemoteOWSBuilder::sosLayer( const QDomElement& remoteOWSElem,
QgsVectorLayer* sosLayer = nullptr;
if ( allowCaching )
{
- sosLayer = dynamic_cast<QgsVectorLayer*>( QgsMSLayerCache::instance()->searchLayer( providerUrl, layerName ) );
+ sosLayer = qobject_cast<QgsVectorLayer*>( QgsMSLayerCache::instance()->searchLayer( providerUrl, layerName ) );
if ( sosLayer )
{
return sosLayer;
diff --git a/src/server/qgsserver.cpp b/src/server/qgsserver.cpp
index 88c6823..906d604 100644
--- a/src/server/qgsserver.cpp
+++ b/src/server/qgsserver.cpp
@@ -115,7 +115,9 @@ void QgsServer::setupNetworkAccessManager()
QSettings settings;
QgsNetworkAccessManager *nam = QgsNetworkAccessManager::instance();
QNetworkDiskCache *cache = new QNetworkDiskCache( nullptr );
- QString cacheDirectory = settings.value( "cache/directory", QgsApplication::qgisSettingsDirPath() + "cache" ).toString();
+ QString cacheDirectory = settings.value( "cache/directory" ).toString();
+ if ( cacheDirectory.isEmpty() )
+ cacheDirectory = QgsApplication::qgisSettingsDirPath() + "cache";
qint64 cacheSize = settings.value( "cache/size", 50 * 1024 * 1024 ).toULongLong();
QgsMessageLog::logMessage( QString( "setCacheDirectory: %1" ).arg( cacheDirectory ), "Server", QgsMessageLog::INFO );
QgsMessageLog::logMessage( QString( "setMaximumCacheSize: %1" ).arg( cacheSize ), "Server", QgsMessageLog::INFO );
diff --git a/src/server/qgsserverlogger.cpp b/src/server/qgsserverlogger.cpp
index 3e8fb81..6e7edeb 100644
--- a/src/server/qgsserverlogger.cpp
+++ b/src/server/qgsserverlogger.cpp
@@ -38,6 +38,9 @@ QgsServerLogger::QgsServerLogger(): mLogFile( nullptr )
{
//logfile
QString filePath = getenv( "QGIS_SERVER_LOG_FILE" );
+ if ( filePath.isEmpty() )
+ return;
+
mLogFile.setFileName( filePath );
if ( mLogFile.open( QIODevice::Append ) )
{
diff --git a/src/server/qgsserverprojectparser.cpp b/src/server/qgsserverprojectparser.cpp
index 38e98cd..f2f240b 100644
--- a/src/server/qgsserverprojectparser.cpp
+++ b/src/server/qgsserverprojectparser.cpp
@@ -25,6 +25,7 @@
#include "qgsmaplayerregistry.h"
#include "qgsmslayercache.h"
#include "qgsrasterlayer.h"
+#include "qgsvectorlayerjoinbuffer.h"
#include "qgseditorwidgetregistry.h"
#include "qgslayertreegroup.h"
@@ -234,7 +235,12 @@ QgsMapLayer* QgsServerProjectParser::createLayerFromElement( const QDomElement&
if ( !QgsMapLayerRegistry::instance()->mapLayer( id ) )
QgsMapLayerRegistry::instance()->addMapLayer( layer, false, false );
if ( layer->type() == QgsMapLayer::VectorLayer )
- addValueRelationLayersForLayer( dynamic_cast<QgsVectorLayer *>( layer ) );
+ {
+ QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( layer );
+ addValueRelationLayersForLayer( vlayer );
+ QgsVectorLayerJoinBuffer* joinBuffer = vlayer->joinBuffer();
+ joinBuffer->readXml( const_cast<QDomElement&>( elem ) );
+ }
return layer;
}
@@ -287,7 +293,7 @@ QgsMapLayer* QgsServerProjectParser::createLayerFromElement( const QDomElement&
if ( layer->type() == QgsMapLayer::VectorLayer )
{
- addValueRelationLayersForLayer( dynamic_cast<QgsVectorLayer *>( layer ) );
+ addValueRelationLayersForLayer( qobject_cast<QgsVectorLayer *>( layer ) );
}
}
return layer;
@@ -797,7 +803,7 @@ void QgsServerProjectParser::addLayerProjectSettings( QDomElement& layerElem, QD
attributeElem.setAttribute( "name", field.name() );
attributeElem.setAttribute( "type", QVariant::typeToName( field.type() ) );
attributeElem.setAttribute( "typeName", field.typeName() );
- QString alias = vLayer->attributeAlias( idx );
+ QString alias = field.alias();
if ( !alias.isEmpty() )
{
attributeElem.setAttribute( "alias", alias );
@@ -1535,7 +1541,7 @@ void QgsServerProjectParser::addJoinLayersForElement( const QDomElement& layerEl
{
QString id = joinNodeList.at( i ).toElement().attribute( "joinLayerId" );
QgsMapLayer* layer = mapLayerFromLayerId( id );
- if ( layer )
+ if ( layer && !QgsMapLayerRegistry::instance()->mapLayer( id ) )
{
QgsMapLayerRegistry::instance()->addMapLayer( layer, false, false );
}
diff --git a/src/server/qgsserverprojectparser.h b/src/server/qgsserverprojectparser.h
index 2dd88ba..e42b68b 100644
--- a/src/server/qgsserverprojectparser.h
+++ b/src/server/qgsserverprojectparser.h
@@ -111,6 +111,7 @@ class SERVER_EXPORT QgsServerProjectParser
QStringList wfsLayers() const;
QStringList wcsLayers() const;
+ /** Add layers for vector joins */
void addJoinLayersForElement( const QDomElement& layerElem ) const;
void addValueRelationLayersForLayer( const QgsVectorLayer *vl ) const;
diff --git a/src/server/qgssldconfigparser.cpp b/src/server/qgssldconfigparser.cpp
index 3891e68..6f81893 100644
--- a/src/server/qgssldconfigparser.cpp
+++ b/src/server/qgssldconfigparser.cpp
@@ -515,6 +515,15 @@ bool QgsSLDConfigParser::featureInfoWithWktGeometry() const
return false;
}
+bool QgsSLDConfigParser::segmentizeFeatureInfoWktGeometry() const
+{
+ if ( mFallbackParser )
+ {
+ return mFallbackParser->segmentizeFeatureInfoWktGeometry();
+ }
+ return false;
+}
+
QHash<QString, QString> QgsSLDConfigParser::featureInfoLayerAliasMap() const
{
diff --git a/src/server/qgssldconfigparser.h b/src/server/qgssldconfigparser.h
index 50f00d0..6688109 100644
--- a/src/server/qgssldconfigparser.h
+++ b/src/server/qgssldconfigparser.h
@@ -64,6 +64,9 @@ class QgsSLDConfigParser : public QgsWMSConfigParser
/** True if the feature info response should contain the wkt geometry for vector features*/
bool featureInfoWithWktGeometry() const override;
+ /** True if the feature info wkt geometry is delivered with segmentized curve types*/
+ bool segmentizeFeatureInfoWktGeometry() const override;
+
/** Returns map with layer aliases for GetFeatureInfo (or 0 pointer if not supported). Key: layer name, Value: layer alias*/
QHash<QString, QString> featureInfoLayerAliasMap() const override;
diff --git a/src/server/qgswcsprojectparser.cpp b/src/server/qgswcsprojectparser.cpp
index a07393c..797ac0f 100644
--- a/src/server/qgswcsprojectparser.cpp
+++ b/src/server/qgswcsprojectparser.cpp
@@ -221,7 +221,7 @@ void QgsWCSProjectParser::describeCoverage( const QString& aCoveName, QDomElemen
QString type = elem.attribute( "type" );
if ( type == "raster" )
{
- QgsRasterLayer *rLayer = dynamic_cast<QgsRasterLayer *>( mProjectParser->createLayerFromElement( elem ) );
+ QgsRasterLayer *rLayer = qobject_cast<QgsRasterLayer *>( mProjectParser->createLayerFromElement( elem ) );
if ( !rLayer )
continue;
@@ -436,7 +436,7 @@ QList<QgsMapLayer*> QgsWCSProjectParser::mapLayerFromCoverage( const QString& cN
if ( type == "raster" )
{
QgsMapLayer *mLayer = mProjectParser->createLayerFromElement( elem, useCache );
- QgsRasterLayer* layer = dynamic_cast<QgsRasterLayer*>( mLayer );
+ QgsRasterLayer* layer = qobject_cast<QgsRasterLayer*>( mLayer );
if ( !layer || !wcsLayersId.contains( layer->id() ) )
return layerList;
diff --git a/src/server/qgswcsserver.cpp b/src/server/qgswcsserver.cpp
index 1a8f97a..57f954b 100644
--- a/src/server/qgswcsserver.cpp
+++ b/src/server/qgswcsserver.cpp
@@ -377,7 +377,7 @@ QByteArray* QgsWCSServer::getCoverage()
QgsRectangle rect( minx, miny, maxx, maxy );
QgsMapLayer* layer = layerList.at( 0 );
- QgsRasterLayer* rLayer = dynamic_cast<QgsRasterLayer*>( layer );
+ QgsRasterLayer* rLayer = qobject_cast<QgsRasterLayer*>( layer );
if ( rLayer && wcsLayersId.contains( rLayer->id() ) )
{
#ifdef HAVE_SERVER_PYTHON_PLUGINS
diff --git a/src/server/qgswfsprojectparser.cpp b/src/server/qgswfsprojectparser.cpp
index 75caafb..50a21a0 100644
--- a/src/server/qgswfsprojectparser.cpp
+++ b/src/server/qgswfsprojectparser.cpp
@@ -346,7 +346,7 @@ void QgsWFSProjectParser::describeFeatureType( const QString& aTypeName, QDomEle
if ( type == "vector" )
{
QgsMapLayer *mLayer = mProjectParser->createLayerFromElement( elem );
- QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( mLayer );
+ QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( mLayer );
if ( !layer )
continue;
@@ -485,7 +485,7 @@ void QgsWFSProjectParser::describeFeatureType( const QString& aTypeName, QDomEle
sequenceElem.appendChild( attElem );
- QString alias = layer->attributeAlias( idx );
+ QString alias = fields.at( idx ).alias();
if ( !alias.isEmpty() )
{
attElem.setAttribute( "alias", alias );
@@ -565,7 +565,7 @@ QList<QgsMapLayer*> QgsWFSProjectParser::mapLayerFromTypeName( const QString& aT
if ( type == "vector" )
{
QgsMapLayer *mLayer = mProjectParser->createLayerFromElement( elem );
- QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( mLayer );
+ QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( mLayer );
if ( !layer )
continue;
diff --git a/src/server/qgswfsserver.cpp b/src/server/qgswfsserver.cpp
index 660b161..a503d01 100644
--- a/src/server/qgswfsserver.cpp
+++ b/src/server/qgswfsserver.cpp
@@ -470,7 +470,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
}
currentLayer = layerList.at( 0 );
- QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( currentLayer );
+ QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( currentLayer );
if ( layer && wfsLayersId.contains( layer->id() ) )
{
#ifdef HAVE_SERVER_PYTHON_PLUGINS
@@ -485,8 +485,8 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
//is there alias info for this vector layer?
QMap< int, QString > layerAliasInfo;
- const QMap< QString, QString >& aliasMap = layer->attributeAliases();
- QMap< QString, QString >::const_iterator aliasIt = aliasMap.constBegin();
+ QgsStringMap aliasMap = layer->attributeAliases();
+ QgsStringMap::const_iterator aliasIt = aliasMap.constBegin();
for ( ; aliasIt != aliasMap.constEnd(); ++aliasIt )
{
int attrIndex = layer->fieldNameIndex( aliasIt.key() );
@@ -865,15 +865,15 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
currentLayer = layerList.at( 0 );
- QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( currentLayer );
+ QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( currentLayer );
if ( layer && wfsLayersId.contains( layer->id() ) )
{
expressionContext << QgsExpressionContextUtils::layerScope( layer );
//is there alias info for this vector layer?
QMap< int, QString > layerAliasInfo;
- const QMap< QString, QString >& aliasMap = layer->attributeAliases();
- QMap< QString, QString >::const_iterator aliasIt = aliasMap.constBegin();
+ QgsStringMap aliasMap = layer->attributeAliases();
+ QgsStringMap::const_iterator aliasIt = aliasMap.constBegin();
for ( ; aliasIt != aliasMap.constEnd(); ++aliasIt )
{
int attrIndex = layer->fieldNameIndex( aliasIt.key() );
diff --git a/src/server/qgswmsconfigparser.h b/src/server/qgswmsconfigparser.h
index cac84d4..5128e4b 100644
--- a/src/server/qgswmsconfigparser.h
+++ b/src/server/qgswmsconfigparser.h
@@ -64,6 +64,9 @@ class SERVER_EXPORT QgsWMSConfigParser
/** True if the feature info response should contain the wkt geometry for vector features*/
virtual bool featureInfoWithWktGeometry() const = 0;
+ /** True if the feature info wkt geometry is delivered with segmentized curve types*/
+ virtual bool segmentizeFeatureInfoWktGeometry() const = 0;
+
/** Returns map with layer aliases for GetFeatureInfo (or 0 pointer if not supported). Key: layer name, Value: layer alias*/
virtual QHash<QString, QString> featureInfoLayerAliasMap() const = 0;
diff --git a/src/server/qgswmsprojectparser.cpp b/src/server/qgswmsprojectparser.cpp
index cc5808c..8746e92 100644
--- a/src/server/qgswmsprojectparser.cpp
+++ b/src/server/qgswmsprojectparser.cpp
@@ -503,19 +503,19 @@ QgsComposition* QgsWMSProjectParser::initComposition( const QString& composerTem
QList<QgsComposerItem *>::iterator itemIt = itemList.begin();
for ( ; itemIt != itemList.end(); ++itemIt )
{
- QgsComposerLabel* label = dynamic_cast< QgsComposerLabel *>( *itemIt );
+ QgsComposerLabel* label = qobject_cast< QgsComposerLabel *>( *itemIt );
if ( label )
{
labelList.push_back( label );
continue;
}
- QgsComposerMap* map = dynamic_cast< QgsComposerMap *>( *itemIt );
+ QgsComposerMap* map = qobject_cast< QgsComposerMap *>( *itemIt );
if ( map )
{
mapList.push_back( map );
continue;
}
- QgsComposerLegend* legend = dynamic_cast< QgsComposerLegend *>( *itemIt );
+ QgsComposerLegend* legend = qobject_cast< QgsComposerLegend *>( *itemIt );
if ( legend )
{
QgsLegendModelV2* model = legend->modelV2();
@@ -567,7 +567,7 @@ QgsComposition* QgsWMSProjectParser::initComposition( const QString& composerTem
legendList.push_back( legend );
continue;
}
- QgsComposerPicture* pic = dynamic_cast< QgsComposerPicture *>( *itemIt );
+ QgsComposerPicture* pic = qobject_cast< QgsComposerPicture *>( *itemIt );
if ( pic )
{
pic->setPicturePath( mProjectParser->convertToAbsolutePath(( pic )->picturePath() ) );
@@ -576,11 +576,11 @@ QgsComposition* QgsWMSProjectParser::initComposition( const QString& composerTem
// an html item will be a composer frame and if it is we can try to get
// its multiframe parent and then try to cast that to a composer html
- const QgsComposerFrame* frame = dynamic_cast<const QgsComposerFrame *>( *itemIt );
+ const QgsComposerFrame* frame = qobject_cast<const QgsComposerFrame *>( *itemIt );
if ( frame )
{
const QgsComposerMultiFrame * multiFrame = frame->multiFrame();
- const QgsComposerHtml* composerHtml = dynamic_cast<const QgsComposerHtml *>( multiFrame );
+ const QgsComposerHtml* composerHtml = qobject_cast<const QgsComposerHtml *>( multiFrame );
if ( composerHtml )
{
htmlList.push_back( composerHtml );
@@ -1332,7 +1332,7 @@ void QgsWMSProjectParser::addLayers( QDomDocument &doc,
bool geometryLayer = true;
if ( currentLayer->type() == QgsMapLayer::VectorLayer )
{
- QgsVectorLayer* vLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
+ QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( currentLayer );
if ( vLayer )
{
if ( vLayer->wkbType() == QGis::WKBNoGeometry )
@@ -1841,7 +1841,7 @@ QDomDocument QgsWMSProjectParser::getStyles( QStringList& layerList ) const
for ( int j = 0; j < currentLayerList.size(); j++ )
{
QgsMapLayer* currentLayer = currentLayerList.at( j );
- QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( currentLayer );
+ QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( currentLayer );
if ( !layer )
{
throw QgsMapServiceException( "Error", QString( "Could not get style because:\n%1" ).arg( "Non-vector layers not supported yet" ) );
@@ -2011,6 +2011,28 @@ bool QgsWMSProjectParser::featureInfoWithWktGeometry() const
return ( wktElem.text().compare( "true", Qt::CaseInsensitive ) == 0 );
}
+bool QgsWMSProjectParser::segmentizeFeatureInfoWktGeometry() const
+{
+ if ( !mProjectParser->xmlDocument() )
+ {
+ return false;
+ }
+
+ QDomElement propertiesElem = mProjectParser->propertiesElem();
+ if ( propertiesElem.isNull() )
+ {
+ return false;
+ }
+
+ QDomElement segmentizeElem = propertiesElem.firstChildElement( "WMSSegmentizeFeatureInfoGeometry" );
+ if ( segmentizeElem.isNull() )
+ {
+ return false;
+ }
+
+ return( segmentizeElem.text().compare( "true", Qt::CaseInsensitive ) == 0 );
+}
+
QHash<QString, QString> QgsWMSProjectParser::featureInfoLayerAliasMap() const
{
QHash<QString, QString> aliasMap;
diff --git a/src/server/qgswmsprojectparser.h b/src/server/qgswmsprojectparser.h
index cd363d3..cb6af21 100644
--- a/src/server/qgswmsprojectparser.h
+++ b/src/server/qgswmsprojectparser.h
@@ -100,6 +100,9 @@ class SERVER_EXPORT QgsWMSProjectParser : public QgsWMSConfigParser
/** True if the feature info response should contain the wkt geometry for vector features*/
bool featureInfoWithWktGeometry() const override;
+ /** True if the feature info wkt geometry is delivered with segmentized curve types*/
+ bool segmentizeFeatureInfoWktGeometry() const override;
+
/** Returns map with layer aliases for GetFeatureInfo (or 0 pointer if not supported). Key: layer name, Value: layer alias*/
QHash<QString, QString> featureInfoLayerAliasMap() const override;
diff --git a/src/server/qgswmsserver.cpp b/src/server/qgswmsserver.cpp
index 616e0f4..a75cc17 100644
--- a/src/server/qgswmsserver.cpp
+++ b/src/server/qgswmsserver.cpp
@@ -939,6 +939,14 @@ QImage* QgsWMSServer::getLegendGraphics()
legendNode->setUserLabel( " " ); // empty string = no override, so let's use one space
}
}
+ else if ( !mDrawLegendLayerLabel )
+ {
+ Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, legendModel.layerLegendNodes( nodeLayer ) )
+ {
+ if ( legendNode->isEmbeddedInParent() )
+ legendNode->setEmbeddedInParent( false );
+ }
+ }
}
}
@@ -1738,7 +1746,7 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, const QString& version )
}
//switch depending on vector or raster
- QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
+ QgsVectorLayer* vectorLayer = qobject_cast<QgsVectorLayer*>( currentLayer );
QDomElement layerElement;
if ( infoFormat.startsWith( "application/vnd.ogc.gml" ) )
@@ -1784,7 +1792,7 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, const QString& version )
getFeatureInfoElement.appendChild( layerElement );
}
- QgsRasterLayer* rasterLayer = dynamic_cast<QgsRasterLayer*>( currentLayer );
+ QgsRasterLayer* rasterLayer = qobject_cast<QgsRasterLayer*>( currentLayer );
if ( rasterLayer )
{
if ( !infoPoint.data() )
@@ -2191,6 +2199,7 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
layer->updateFields();
const QgsFields& fields = layer->pendingFields();
bool addWktGeometry = mConfigParser && mConfigParser->featureInfoWithWktGeometry();
+ bool segmentizeWktGeometry = mConfigParser && mConfigParser->segmentizeFeatureInfoWktGeometry();
const QSet<QString>& excludedAttributes = layer->excludeAttributesWMS();
QgsFeatureRequest fReq;
@@ -2220,35 +2229,46 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
#endif
QgsFeatureIterator fit = layer->getFeatures( fReq );
+ QgsFeatureRendererV2* r2 = layer->rendererV2();
+ if ( r2 )
+ {
+ r2->startRender( renderContext, layer->pendingFields() );
+ }
bool featureBBoxInitialized = false;
while ( fit.nextFeature( feature ) )
{
+ if ( layer->wkbType() == QGis::WKBNoGeometry && ! searchRect.isEmpty() )
+ {
+ break;
+ }
+
++featureCounter;
if ( featureCounter > nFeatures )
{
break;
}
- QgsFeatureRendererV2* r2 = layer->rendererV2();
- if ( !r2 )
+ if ( layer->wkbType() != QGis::WKBNoGeometry && ! searchRect.isEmpty() )
{
- continue;
- }
+ if ( !r2 )
+ {
+ continue;
+ }
- renderContext.expressionContext().setFeature( feature );
+ renderContext.expressionContext().setFeature( feature );
- //check if feature is rendered at all
- r2->startRender( renderContext, layer->pendingFields() );
- bool renderV2 = r2->willRenderFeature( feature, renderContext );
- r2->stopRender( renderContext );
- if ( !renderV2 )
- {
- continue;
+
+ //check if feature is rendered at all
+ bool render = r2->willRenderFeature( feature, renderContext );
+ if ( !render )
+ {
+ continue;
+ }
}
QgsRectangle box;
- if ( hasGeometry )
+ if ( layer->wkbType() != QGis::WKBNoGeometry && hasGeometry )
{
box = mapRender->layerExtentToOutputExtent( layer, feature.constGeometry()->boundingBox() );
if ( featureBBox ) //extend feature info bounding box if requested
@@ -2342,7 +2362,7 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
}
//append feature bounding box to feature info xml
- if ( hasGeometry && mapRender && mConfigParser )
+ if ( layer->wkbType() != QGis::WKBNoGeometry && hasGeometry && mapRender && mConfigParser )
{
QDomElement bBoxElem = infoDocument.createElement( "BoundingBox" );
bBoxElem.setAttribute( version == "1.1.1" ? "SRS" : "CRS", outputCrs.authid() );
@@ -2354,7 +2374,7 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
}
//also append the wkt geometry as an attribute
- if ( addWktGeometry && hasGeometry )
+ if ( layer->wkbType() != QGis::WKBNoGeometry && addWktGeometry && hasGeometry )
{
QgsGeometry *geom = feature.geometry();
if ( geom )
@@ -2365,6 +2385,19 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
if ( transform )
geom->transform( *transform );
}
+
+ if ( segmentizeWktGeometry )
+ {
+ QgsAbstractGeometryV2* abstractGeom = geom->geometry();
+ if ( abstractGeom )
+ {
+ if ( QgsWKBTypes::isCurvedType( abstractGeom->wkbType() ) )
+ {
+ QgsAbstractGeometryV2* segmentizedGeom = abstractGeom-> segmentize();
+ geom->setGeometry( segmentizedGeom );
+ }
+ }
+ }
QDomElement geometryElement = infoDocument.createElement( "Attribute" );
geometryElement.setAttribute( "name", "geometry" );
geometryElement.setAttribute( "value", geom->exportToWkt( getWMSPrecision( 8 ) ) );
@@ -2374,6 +2407,10 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
}
}
}
+ if ( r2 )
+ {
+ r2->stopRender( renderContext );
+ }
return 0;
}
@@ -2564,7 +2601,7 @@ void QgsWMSServer::applyRequestedLayerFilters( const QStringList& layerList , QH
Q_FOREACH ( QgsMapLayer *filter, layersToFilter )
{
- QgsVectorLayer* filteredLayer = dynamic_cast<QgsVectorLayer*>( filter );
+ QgsVectorLayer* filteredLayer = qobject_cast<QgsVectorLayer*>( filter );
if ( filteredLayer )
{
originalFilters.insert( filteredLayer, filteredLayer->subsetString() );
diff --git a/src/ui/auth/qgsauthauthoritieseditor.ui b/src/ui/auth/qgsauthauthoritieseditor.ui
index fe0855c..8e29ed4 100644
--- a/src/ui/auth/qgsauthauthoritieseditor.ui
+++ b/src/ui/auth/qgsauthauthoritieseditor.ui
@@ -99,7 +99,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/mIconClose.png</normaloff>:/images/themes/default/mIconClose.png</iconset>
+ <normaloff>:/images/themes/default/mIconClose.svg</normaloff>:/images/themes/default/mIconClose.svg</iconset>
</property>
<property name="iconSize">
<size>
@@ -159,7 +159,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
<property name="iconSize">
<size>
@@ -185,7 +185,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
+ <normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
<property name="iconSize">
<size>
diff --git a/src/ui/auth/qgsauthconfigeditor.ui b/src/ui/auth/qgsauthconfigeditor.ui
index b420221..7c10de7 100644
--- a/src/ui/auth/qgsauthconfigeditor.ui
+++ b/src/ui/auth/qgsauthconfigeditor.ui
@@ -64,7 +64,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
<property name="iconSize">
<size>
@@ -87,7 +87,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
+ <normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
<property name="iconSize">
<size>
diff --git a/src/ui/auth/qgsauthconfigselect.ui b/src/ui/auth/qgsauthconfigselect.ui
index 8bf18d0..99ffe0e 100644
--- a/src/ui/auth/qgsauthconfigselect.ui
+++ b/src/ui/auth/qgsauthconfigselect.ui
@@ -104,7 +104,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/mIconClose.png</normaloff>:/images/themes/default/mIconClose.png</iconset>
+ <normaloff>:/images/themes/default/mIconClose.svg</normaloff>:/images/themes/default/mIconClose.svg</iconset>
</property>
<property name="iconSize">
<size>
diff --git a/src/ui/auth/qgsauthidentitieseditor.ui b/src/ui/auth/qgsauthidentitieseditor.ui
index 9b355d3..0b55e4d 100644
--- a/src/ui/auth/qgsauthidentitieseditor.ui
+++ b/src/ui/auth/qgsauthidentitieseditor.ui
@@ -77,7 +77,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
<property name="iconSize">
<size>
@@ -103,7 +103,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
+ <normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
<property name="iconSize">
<size>
diff --git a/src/ui/auth/qgsauthserverseditor.ui b/src/ui/auth/qgsauthserverseditor.ui
index 4b0e095..58e365f 100644
--- a/src/ui/auth/qgsauthserverseditor.ui
+++ b/src/ui/auth/qgsauthserverseditor.ui
@@ -74,7 +74,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
<property name="iconSize">
<size>
@@ -97,7 +97,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
+ <normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
<property name="iconSize">
<size>
diff --git a/src/ui/composer/qgsattributeselectiondialogbase.ui b/src/ui/composer/qgsattributeselectiondialogbase.ui
index c9081f3..5d3e868 100644
--- a/src/ui/composer/qgsattributeselectiondialogbase.ui
+++ b/src/ui/composer/qgsattributeselectiondialogbase.ui
@@ -194,7 +194,7 @@
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyDown.png</normaloff>:/images/themes/default/symbologyDown.png</iconset>
+ <normaloff>:/images/themes/default/symbologyDown.svg</normaloff>:/images/themes/default/symbologyDown.svg</iconset>
</property>
</widget>
</item>
diff --git a/src/ui/composer/qgscomposerpicturewidgetbase.ui b/src/ui/composer/qgscomposerpicturewidgetbase.ui
index 338d8a9..8168aad 100644
--- a/src/ui/composer/qgscomposerpicturewidgetbase.ui
+++ b/src/ui/composer/qgscomposerpicturewidgetbase.ui
@@ -60,9 +60,9 @@
<property name="geometry">
<rect>
<x>0</x>
- <y>-166</y>
- <width>313</width>
- <height>719</height>
+ <y>-312</y>
+ <width>314</width>
+ <height>871</height>
</rect>
</property>
<layout class="QVBoxLayout" name="mainLayout">
@@ -463,6 +463,16 @@
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
+ <item row="2" column="1">
+ <widget class="QComboBox" name="mNorthTypeComboBox"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>North alignment</string>
+ </property>
+ </widget>
+ </item>
<item row="1" column="0">
<widget class="QCheckBox" name="mRotationFromComposerMapCheckBox">
<property name="text">
@@ -478,6 +488,29 @@
<property name="suffix">
<string> °</string>
</property>
+ <property name="minimum">
+ <double>-360.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>360.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>Offset</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QgsDoubleSpinBox" name="mPictureRotationOffsetSpinBox">
+ <property name="suffix">
+ <string> °</string>
+ </property>
+ <property name="minimum">
+ <double>-360.000000000000000</double>
+ </property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
diff --git a/src/ui/qgisapp.ui b/src/ui/qgisapp.ui
index 91d70db..255a649 100644
--- a/src/ui/qgisapp.ui
+++ b/src/ui/qgisapp.ui
@@ -1394,11 +1394,14 @@
<action name="mActionOpenTable">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionOpenTable.png</normaloff>:/images/themes/default/mActionOpenTable.png</iconset>
+ <normaloff>:/images/themes/default/mActionOpenTable.svg</normaloff>:/images/themes/default/mActionOpenTable.svg</iconset>
</property>
<property name="text">
<string>Open &Attribute Table</string>
</property>
+ <property name="shortcut">
+ <string>F6</string>
+ </property>
</action>
<action name="mActionToggleEditing">
<property name="checkable">
@@ -1503,7 +1506,7 @@
<action name="mActionShowAllLayers">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionShowAllLayers.png</normaloff>:/images/themes/default/mActionShowAllLayers.png</iconset>
+ <normaloff>:/images/themes/default/mActionShowAllLayers.svg</normaloff>:/images/themes/default/mActionShowAllLayers.svg</iconset>
</property>
<property name="text">
<string>Show All Layers</string>
@@ -1515,7 +1518,7 @@
<action name="mActionHideAllLayers">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionHideAllLayers.png</normaloff>:/images/themes/default/mActionHideAllLayers.png</iconset>
+ <normaloff>:/images/themes/default/mActionHideAllLayers.svg</normaloff>:/images/themes/default/mActionHideAllLayers.svg</iconset>
</property>
<property name="text">
<string>Hide All Layers</string>
@@ -1681,7 +1684,7 @@
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionRotateLabel.png</normaloff>:/images/themes/default/mActionRotateLabel.png</iconset>
+ <normaloff>:/images/themes/default/mActionRotateLabel.svg</normaloff>:/images/themes/default/mActionRotateLabel.svg</iconset>
</property>
<property name="text">
<string>Rotate Label</string>
@@ -1910,7 +1913,7 @@ Ctl (Cmd) increments by 15 deg.</string>
<action name="mActionDecorationGrid">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/transformed.png</normaloff>:/images/themes/default/transformed.png</iconset>
+ <normaloff>:/images/themes/default/transformed.svg</normaloff>:/images/themes/default/transformed.svg</iconset>
</property>
<property name="text">
<string>&Grid</string>
@@ -2279,7 +2282,7 @@ Acts on currently active editable layer</string>
</action>
<action name="mActionPasteAsNewMemoryVector">
<property name="text">
- <string>New Temporary Scratch Layer...</string>
+ <string>Temporary Scratch Layer...</string>
</property>
<property name="toolTip">
<string>Paste features in clipboard into a new temporary scratch layer.</string>
diff --git a/src/ui/qgsattributeactiondialogbase.ui b/src/ui/qgsattributeactiondialogbase.ui
index 72b3810..5ba933a 100644
--- a/src/ui/qgsattributeactiondialogbase.ui
+++ b/src/ui/qgsattributeactiondialogbase.ui
@@ -203,7 +203,7 @@
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
diff --git a/src/ui/qgsattributetabledialog.ui b/src/ui/qgsattributetabledialog.ui
index c9c0aac..4887bb9 100644
--- a/src/ui/qgsattributetabledialog.ui
+++ b/src/ui/qgsattributetabledialog.ui
@@ -53,7 +53,7 @@
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
+ <normaloff>:/images/themes/default/mActionFilter.svg</normaloff>:/images/themes/default/mActionFilter.svg</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
@@ -261,7 +261,7 @@
<action name="mActionAdvancedFilter">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
+ <normaloff>:/images/themes/default/mActionFilter.svg</normaloff>:/images/themes/default/mActionFilter.svg</iconset>
</property>
<property name="text">
<string>Advanced Filter (Expression)</string>
@@ -273,7 +273,7 @@
<action name="mActionShowAllFilter">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
+ <normaloff>:/images/themes/default/mActionFilter.svg</normaloff>:/images/themes/default/mActionFilter.svg</iconset>
</property>
<property name="text">
<string>Show All Features</string>
@@ -282,7 +282,7 @@
<action name="mActionSelectedFilter">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
+ <normaloff>:/images/themes/default/mActionFilter.svg</normaloff>:/images/themes/default/mActionFilter.svg</iconset>
</property>
<property name="text">
<string>Show Selected Features</string>
@@ -291,7 +291,7 @@
<action name="mActionVisibleFilter">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
+ <normaloff>:/images/themes/default/mActionFilter.svg</normaloff>:/images/themes/default/mActionFilter.svg</iconset>
</property>
<property name="text">
<string>Show Features Visible On Map</string>
@@ -305,7 +305,7 @@
<action name="mActionEditedFilter">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
+ <normaloff>:/images/themes/default/mActionFilter.svg</normaloff>:/images/themes/default/mActionFilter.svg</iconset>
</property>
<property name="text">
<string>Show Edited and New Features</string>
diff --git a/src/ui/qgsattributetypeedit.ui b/src/ui/qgsattributetypeedit.ui
index 9023885..39f5ed6 100644
--- a/src/ui/qgsattributetypeedit.ui
+++ b/src/ui/qgsattributetypeedit.ui
@@ -14,6 +14,63 @@
<string>Edit Widget Properties</string>
</property>
<layout class="QGridLayout" name="gridLayout">
+ <item row="5" column="1">
+ <widget class="QStackedWidget" name="stackedWidget"/>
+ </item>
+ <item row="4" column="1">
+ <widget class="QgsCollapsibleGroupBox" name="groupBox">
+ <property name="title">
+ <string>Constraints</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QCheckBox" name="notNullCheckBox">
+ <property name="text">
+ <string>Not null</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Constraint</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QgsFieldExpressionWidget" name="constraintExpressionWidget" native="true">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Constraint description</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="leConstraintExpressionDescription"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
<item row="0" column="1">
<widget class="QCheckBox" name="isFieldEditableCheckBox">
<property name="text">
@@ -24,6 +81,43 @@
</property>
</widget>
</item>
+ <item row="2" column="1">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Defaults</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Default value</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Preview</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QgsExpressionLineEdit" name="mExpressionWidget" native="true">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="mDefaultPreviewLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
<item row="1" column="1">
<widget class="QCheckBox" name="labelOnTopCheckBox">
<property name="text">
@@ -34,10 +128,10 @@
</property>
</widget>
</item>
- <item row="0" column="0" rowspan="11">
+ <item row="0" column="0" rowspan="7">
<widget class="QListWidget" name="selectionListWidget"/>
</item>
- <item row="10" column="1">
+ <item row="6" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -47,54 +141,22 @@
</property>
</widget>
</item>
- <item row="6" column="1">
- <widget class="QStackedWidget" name="stackedWidget"/>
- </item>
- <item row="2" column="1">
- <widget class="QCheckBox" name="notNullCheckBox">
- <property name="text">
- <string>Not null</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="topMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Constraint</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QgsFieldExpressionWidget" name="constraintExpression" native="true"/>
- </item>
- </layout>
- </item>
- <item row="5" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Constraint description</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="constraintExpressionDescription"/>
- </item>
- </layout>
- </item>
</layout>
</widget>
<customwidgets>
<customwidget>
+ <class>QgsExpressionLineEdit</class>
+ <extends>QWidget</extends>
+ <header>qgsexpressionlineedit.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>QgsCollapsibleGroupBox</class>
+ <extends>QGroupBox</extends>
+ <header>qgscollapsiblegroupbox.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
<class>QgsFieldExpressionWidget</class>
<extends>QWidget</extends>
<header>qgsfieldexpressionwidget.h</header>
@@ -105,7 +167,10 @@
<tabstop>selectionListWidget</tabstop>
<tabstop>isFieldEditableCheckBox</tabstop>
<tabstop>labelOnTopCheckBox</tabstop>
- <tabstop>buttonBox</tabstop>
+ <tabstop>mExpressionWidget</tabstop>
+ <tabstop>notNullCheckBox</tabstop>
+ <tabstop>constraintExpressionWidget</tabstop>
+ <tabstop>leConstraintExpressionDescription</tabstop>
</tabstops>
<resources/>
<connections>
diff --git a/src/ui/qgscategorizedsymbolrendererv2widget.ui b/src/ui/qgscategorizedsymbolrendererv2widget.ui
index a3151cb..01758ff 100644
--- a/src/ui/qgscategorizedsymbolrendererv2widget.ui
+++ b/src/ui/qgscategorizedsymbolrendererv2widget.ui
@@ -157,7 +157,7 @@
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
@@ -168,7 +168,7 @@
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
+ <normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
</widget>
</item>
diff --git a/src/ui/qgscompoundcolorwidget.ui b/src/ui/qgscompoundcolorwidget.ui
index 0f1ca30..cb6702c 100644
--- a/src/ui/qgscompoundcolorwidget.ui
+++ b/src/ui/qgscompoundcolorwidget.ui
@@ -28,492 +28,10 @@
<property name="horizontalSpacing">
<number>6</number>
</property>
- <item row="0" column="1">
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="0,0,1">
- <item>
- <widget class="QRadioButton" name="mHueRadio">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>H</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QgsColorSliderWidget" name="mHueSlider" native="true"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="0,0,1">
- <item>
- <widget class="QRadioButton" name="mSaturationRadio">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>S</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QgsColorSliderWidget" name="mSaturationSlider" native="true"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="0,0,1">
- <item>
- <widget class="QRadioButton" name="mValueRadio">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>V</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QgsColorSliderWidget" name="mValueSlider" native="true"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,1">
- <item>
- <widget class="QRadioButton" name="mRedRadio">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>R</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QgsColorSliderWidget" name="mRedSlider" native="true"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,1">
- <item>
- <widget class="QRadioButton" name="mGreenRadio">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_9">
- <property name="text">
- <string>G</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QgsColorSliderWidget" name="mGreenSlider" native="true"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,0,1">
- <item>
- <widget class="QRadioButton" name="mBlueRadio">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_10">
- <property name="text">
- <string>B</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QgsColorSliderWidget" name="mBlueSlider" native="true"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="mAlphaLayout">
- <item>
- <widget class="QLabel" name="mAlphaLabel">
- <property name="text">
- <string>Opacity</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QgsColorSliderWidget" name="mAlphaSlider" native="true"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_8">
- <item>
- <widget class="QLabel" name="label">
- <property name="text">
- <string>HTML notation</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QgsColorTextWidget" name="mColorText" native="true"/>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="1" column="1">
- <layout class="QGridLayout" name="gridLayout_4">
- <property name="spacing">
- <number>1</number>
- </property>
- <item row="1" column="0">
- <widget class="QgsColorButtonV2" name="mSwatchButton9">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QgsColorButtonV2" name="mSwatchButton11">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <widget class="QgsColorButtonV2" name="mSwatchButton12">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="4">
- <widget class="QgsColorButtonV2" name="mSwatchButton5">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QgsColorButtonV2" name="mSwatchButton2">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QgsColorButtonV2" name="mSwatchButton3">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QgsColorButtonV2" name="mSwatchButton1">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="4">
- <widget class="QgsColorButtonV2" name="mSwatchButton13">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="5">
- <widget class="QgsColorButtonV2" name="mSwatchButton6">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="6">
- <widget class="QgsColorButtonV2" name="mSwatchButton7">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="5">
- <widget class="QgsColorButtonV2" name="mSwatchButton14">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="6">
- <widget class="QgsColorButtonV2" name="mSwatchButton15">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="7">
- <widget class="QgsColorButtonV2" name="mSwatchButton8">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="7">
- <widget class="QgsColorButtonV2" name="mSwatchButton16">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="QgsColorButtonV2" name="mSwatchButton4">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QgsColorButtonV2" name="mSwatchButton10">
- <property name="minimumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>38</width>
- <height>30</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </item>
<item row="0" column="0">
<widget class="QTabWidget" name="mTabWidget">
<property name="currentIndex">
- <number>0</number>
+ <number>2</number>
</property>
<property name="iconSize">
<size>
@@ -747,98 +265,586 @@
</widget>
</widget>
</item>
- <item row="1" column="0">
- <layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0">
- <item row="0" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Current</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="mOldColorLabel">
- <property name="text">
- <string>Old</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="0" column="2" rowspan="2">
- <widget class="QPushButton" name="mAddCustomColorButton">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>28</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>28</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionAtlasNext.svg</normaloff>:/images/themes/default/mActionAtlasNext.svg</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- </item>
- <item row="0" column="1" rowspan="2">
- <widget class="QFrame" name="frame_2">
- <property name="frameShape">
- <enum>QFrame::StyledPanel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout_13">
- <property name="leftMargin">
- <number>1</number>
- </property>
- <property name="topMargin">
- <number>1</number>
- </property>
- <property name="rightMargin">
- <number>1</number>
- </property>
- <property name="bottomMargin">
- <number>1</number>
- </property>
+ <item row="0" column="1">
+ <widget class="QWidget" name="mSlidersWidget" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="0,0,1">
+ <item>
+ <widget class="QRadioButton" name="mHueRadio">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>H</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QgsColorSliderWidget" name="mHueSlider" native="true"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="0,0,1">
+ <item>
+ <widget class="QRadioButton" name="mSaturationRadio">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>S</string>
+ </property>
+ </widget>
+ </item>
<item>
- <widget class="QgsColorPreviewWidget" name="mColorPreview" native="true">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>40</height>
- </size>
+ <widget class="QgsColorSliderWidget" name="mSaturationSlider" native="true"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="0,0,1">
+ <item>
+ <widget class="QRadioButton" name="mValueRadio">
+ <property name="text">
+ <string/>
</property>
</widget>
</item>
+ <item>
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>V</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QgsColorSliderWidget" name="mValueSlider" native="true"/>
+ </item>
</layout>
- </widget>
- </item>
- </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,1">
+ <item>
+ <widget class="QRadioButton" name="mRedRadio">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>R</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QgsColorSliderWidget" name="mRedSlider" native="true"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,1">
+ <item>
+ <widget class="QRadioButton" name="mGreenRadio">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>G</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QgsColorSliderWidget" name="mGreenSlider" native="true"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,0,1">
+ <item>
+ <widget class="QRadioButton" name="mBlueRadio">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_10">
+ <property name="text">
+ <string>B</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QgsColorSliderWidget" name="mBlueSlider" native="true"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="mAlphaLayout">
+ <item>
+ <widget class="QLabel" name="mAlphaLabel">
+ <property name="text">
+ <string>Opacity</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QgsColorSliderWidget" name="mAlphaSlider" native="true"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_8">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>HTML notation</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QgsColorTextWidget" name="mColorText" native="true"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QWidget" name="mPreviewWidget" native="true">
+ <layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Current</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="mOldColorLabel">
+ <property name="text">
+ <string>Old</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" rowspan="2">
+ <widget class="QPushButton" name="mAddCustomColorButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>28</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>28</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/mActionAtlasNext.svg</normaloff>:/images/themes/default/mActionAtlasNext.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" rowspan="2">
+ <widget class="QFrame" name="frame_2">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_13">
+ <property name="leftMargin">
+ <number>1</number>
+ </property>
+ <property name="topMargin">
+ <number>1</number>
+ </property>
+ <property name="rightMargin">
+ <number>1</number>
+ </property>
+ <property name="bottomMargin">
+ <number>1</number>
+ </property>
+ <item>
+ <widget class="QgsColorPreviewWidget" name="mColorPreview" native="true">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>40</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QWidget" name="mSwatchesWidget" native="true">
+ <layout class="QGridLayout" name="gridLayout_4">
+ <property name="spacing">
+ <number>1</number>
+ </property>
+ <item row="1" column="0">
+ <widget class="QgsColorButtonV2" name="mSwatchButton9">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QgsColorButtonV2" name="mSwatchButton11">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QgsColorButtonV2" name="mSwatchButton12">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="4">
+ <widget class="QgsColorButtonV2" name="mSwatchButton5">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QgsColorButtonV2" name="mSwatchButton2">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QgsColorButtonV2" name="mSwatchButton3">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QgsColorButtonV2" name="mSwatchButton1">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4">
+ <widget class="QgsColorButtonV2" name="mSwatchButton13">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="5">
+ <widget class="QgsColorButtonV2" name="mSwatchButton6">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="6">
+ <widget class="QgsColorButtonV2" name="mSwatchButton7">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="5">
+ <widget class="QgsColorButtonV2" name="mSwatchButton14">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="6">
+ <widget class="QgsColorButtonV2" name="mSwatchButton15">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="7">
+ <widget class="QgsColorButtonV2" name="mSwatchButton8">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="7">
+ <widget class="QgsColorButtonV2" name="mSwatchButton16">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QgsColorButtonV2" name="mSwatchButton4">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QgsColorButtonV2" name="mSwatchButton10">
+ <property name="minimumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</item>
</layout>
</item>
@@ -899,6 +905,14 @@
<string>Copy selected colors</string>
</property>
</action>
+ <action name="mActionShowInButtons">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show in Color Buttons</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>
diff --git a/src/ui/qgsdualviewbase.ui b/src/ui/qgsdualviewbase.ui
index ca0690c..f521beb 100644
--- a/src/ui/qgsdualviewbase.ui
+++ b/src/ui/qgsdualviewbase.ui
@@ -156,7 +156,7 @@
<action name="mActionExpressionPreview">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
+ <normaloff>:/images/themes/default/mActionFilter.svg</normaloff>:/images/themes/default/mActionFilter.svg</iconset>
</property>
<property name="text">
<string>Expression</string>
diff --git a/src/ui/qgsdxfexportdialogbase.ui b/src/ui/qgsdxfexportdialogbase.ui
index c5519b6..119ffa1 100644
--- a/src/ui/qgsdxfexportdialogbase.ui
+++ b/src/ui/qgsdxfexportdialogbase.ui
@@ -6,24 +6,14 @@
<rect>
<x>0</x>
<y>0</y>
- <width>402</width>
- <height>534</height>
+ <width>1049</width>
+ <height>680</height>
</rect>
</property>
<property name="windowTitle">
<string>DXF export</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
- <item row="2" column="1" colspan="2">
- <widget class="QgsScaleWidget" name="mScaleWidget" native="true">
- <property name="showCurrentScaleButton" stdset="0">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="3" column="1" colspan="2">
- <widget class="QComboBox" name="mEncoding"/>
- </item>
<item row="0" column="2">
<widget class="QToolButton" name="mFileSelectionButton">
<property name="text">
@@ -31,16 +21,6 @@
</property>
</widget>
</item>
- <item row="5" column="0" colspan="3">
- <widget class="QgsLayerTreeView" name="mTreeView">
- <property name="selectionMode">
- <enum>QAbstractItemView::ExtendedSelection</enum>
- </property>
- <attribute name="headerDefaultSectionSize">
- <number>0</number>
- </attribute>
- </widget>
- </item>
<item row="0" column="0">
<widget class="QLabel" name="mSaveAsLabel">
<property name="text">
@@ -82,6 +62,26 @@
</widget>
</item>
<item row="7" column="0" colspan="3">
+ <widget class="QgsLayerTreeView" name="mTreeView">
+ <property name="selectionMode">
+ <enum>QAbstractItemView::ExtendedSelection</enum>
+ </property>
+ <attribute name="headerDefaultSectionSize">
+ <number>0</number>
+ </attribute>
+ </widget>
+ </item>
+ <item row="2" column="1" colspan="2">
+ <widget class="QgsScaleWidget" name="mScaleWidget">
+ <property name="showCurrentScaleButton">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" colspan="2">
+ <widget class="QComboBox" name="mEncoding"/>
+ </item>
+ <item row="9" column="0" colspan="3">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QPushButton" name="mSelectAllButton">
@@ -115,14 +115,14 @@
<item row="0" column="1">
<widget class="QLineEdit" name="mFileLineEdit"/>
</item>
- <item row="9" column="0" colspan="3">
+ <item row="11" column="0" colspan="3">
<widget class="QCheckBox" name="mMapExtentCheckBox">
<property name="text">
<string>Export features intersecting the current map extent</string>
</property>
</widget>
</item>
- <item row="10" column="0" colspan="3">
+ <item row="12" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -149,17 +149,37 @@
</property>
</widget>
</item>
- <item row="8" column="0" colspan="3">
+ <item row="10" column="0" colspan="3">
<widget class="QCheckBox" name="mLayerTitleAsName">
<property name="text">
<string>Use layer title as name if set</string>
</property>
</widget>
</item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>CRS</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="2">
+ <widget class="QgsProjectionSelectionWidget" name="mCrsSelector">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<customwidgets>
<customwidget>
+ <class>QgsProjectionSelectionWidget</class>
+ <extends>QWidget</extends>
+ <header>qgsprojectionselectionwidget.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
<class>QgsScaleWidget</class>
<extends>QWidget</extends>
<header>qgsscalewidget.h</header>
diff --git a/src/ui/qgserrordialogbase.ui b/src/ui/qgserrordialogbase.ui
index 2ea93a3..9eecef3 100644
--- a/src/ui/qgserrordialogbase.ui
+++ b/src/ui/qgserrordialogbase.ui
@@ -28,7 +28,7 @@
<string/>
</property>
<property name="pixmap">
- <pixmap>../../images/themes/default/mIconWarn.png</pixmap>
+ <pixmap>:/images/themes/default/mIconWarning.svg</pixmap>
</property>
</widget>
</item>
diff --git a/src/ui/qgsfieldconditionalformatwidget.ui b/src/ui/qgsfieldconditionalformatwidget.ui
index f3f8a7a..64f1b88 100644
--- a/src/ui/qgsfieldconditionalformatwidget.ui
+++ b/src/ui/qgsfieldconditionalformatwidget.ui
@@ -101,7 +101,7 @@
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
diff --git a/src/ui/qgsformannotationdialogbase.ui b/src/ui/qgsformannotationdialogbase.ui
index cc3b83c..fc88a22 100644
--- a/src/ui/qgsformannotationdialogbase.ui
+++ b/src/ui/qgsformannotationdialogbase.ui
@@ -40,7 +40,7 @@
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
diff --git a/src/ui/qgsgraduatedsymbolrendererv2widget.ui b/src/ui/qgsgraduatedsymbolrendererv2widget.ui
index e76978a..e9b6775 100644
--- a/src/ui/qgsgraduatedsymbolrendererv2widget.ui
+++ b/src/ui/qgsgraduatedsymbolrendererv2widget.ui
@@ -109,7 +109,7 @@ Positive is number of decimal places
Negative rounds to powers of 10</string>
</property>
<property name="prefix">
- <string>Precison </string>
+ <string>Precision </string>
</property>
<property name="minimum">
<number>0</number>
@@ -440,7 +440,7 @@ Negative rounds to powers of 10</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
@@ -451,7 +451,7 @@ Negative rounds to powers of 10</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
+ <normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
</widget>
</item>
diff --git a/src/ui/qgslabelingguibase.ui b/src/ui/qgslabelingguibase.ui
index eed9649..2d8de91 100644
--- a/src/ui/qgslabelingguibase.ui
+++ b/src/ui/qgslabelingguibase.ui
@@ -14,7 +14,16 @@
<string>Layer labeling settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_8">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
@@ -35,7 +44,16 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_23">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
@@ -94,7 +112,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>487</width>
+ <width>482</width>
<height>300</height>
</rect>
</property>
@@ -314,10 +332,19 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_17">
- <property name="horizontalSpacing">
+ <property name="leftMargin">
<number>0</number>
</property>
- <property name="margin">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="horizontalSpacing">
<number>0</number>
</property>
<item row="0" column="0">
@@ -591,11 +618,20 @@
<item>
<widget class="QStackedWidget" name="mLabelStackedWidget">
<property name="currentIndex">
- <number>0</number>
+ <number>5</number>
</property>
<widget class="QWidget" name="mLabelPage_Text">
<layout class="QVBoxLayout" name="verticalLayout_6">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -611,8 +647,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>465</width>
- <height>385</height>
+ <width>448</width>
+ <height>411</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
@@ -643,7 +679,16 @@
</size>
</property>
<layout class="QGridLayout" name="gridLayout_6">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="10" column="1" colspan="2">
@@ -856,7 +901,16 @@
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_23">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -937,9 +991,6 @@
<property name="text">
<string>Color</string>
</property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
</widget>
</item>
<item row="5" column="2">
@@ -1245,7 +1296,16 @@
<item row="2" column="1">
<widget class="QFrame" name="mFontFamilyFrame">
<layout class="QHBoxLayout" name="horizontalLayout_5">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -1271,6 +1331,29 @@ font-style: italic;</string>
</layout>
</widget>
</item>
+<item row="13" column="0" colspan="2">
+ <widget class="QCheckBox" name="mCheckBoxSubstituteText">
+ <property name="toolTip">
+ <string>If enabled, the label text will automatically be modified using a preset list of substitutes</string>
+ </property>
+ <property name="text">
+ <string>Apply label text substitutes</string>
+ </property>
+ </widget>
+ </item>
+ <item row="13" column="2">
+ <widget class="QToolButton" name="mToolButtonConfigureSubstitutes">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>Configure substitutes</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
<item row="1" column="1">
<widget class="QFontComboBox" name="mFontFamilyCmbBx">
<property name="editable">
@@ -1321,7 +1404,16 @@ font-style: italic;</string>
</widget>
<widget class="QWidget" name="mLabelPage_Formatting">
<layout class="QVBoxLayout" name="verticalLayout_15">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -1344,8 +1436,8 @@ font-style: italic;</string>
<rect>
<x>0</x>
<y>0</y>
- <width>465</width>
- <height>366</height>
+ <width>448</width>
+ <height>389</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_14">
@@ -1528,7 +1620,16 @@ font-style: italic;</string>
<item>
<widget class="QFrame" name="mDirectSymbolsFrame">
<layout class="QGridLayout" name="gridLayout_33">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
@@ -1594,7 +1695,16 @@ font-style: italic;</string>
<property name="spacing">
<number>0</number>
</property>
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -1696,7 +1806,16 @@ font-style: italic;</string>
<property name="spacing">
<number>0</number>
</property>
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -1741,7 +1860,16 @@ font-style: italic;</string>
<item row="2" column="1">
<widget class="QFrame" name="mDirectSymbPlacementFrame">
<layout class="QHBoxLayout" name="horizontalLayout_17">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -1918,7 +2046,16 @@ font-style: italic;</string>
</widget>
<widget class="QWidget" name="mLabelPage_Buffer">
<layout class="QVBoxLayout" name="verticalLayout_7">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -1934,8 +2071,8 @@ font-style: italic;</string>
<rect>
<x>0</x>
<y>0</y>
- <width>465</width>
- <height>385</height>
+ <width>464</width>
+ <height>364</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
@@ -2088,7 +2225,16 @@ font-style: italic;</string>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_10">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -2127,9 +2273,6 @@ font-style: italic;</string>
<property name="enabled">
<bool>true</bool>
</property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
<property name="suffix">
<string> %</string>
</property>
@@ -2285,7 +2428,16 @@ font-style: italic;</string>
</widget>
<widget class="QWidget" name="mLabelPage_Background">
<layout class="QVBoxLayout" name="verticalLayout_20">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -2301,8 +2453,8 @@ font-style: italic;</string>
<rect>
<x>0</x>
<y>0</y>
- <width>448</width>
- <height>589</height>
+ <width>454</width>
+ <height>720</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_21">
@@ -2506,7 +2658,16 @@ font-style: italic;</string>
<item row="6" column="1" colspan="2">
<widget class="QFrame" name="mShapeRotationFrame">
<layout class="QHBoxLayout" name="horizontalLayout_36">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
</layout>
@@ -2589,9 +2750,6 @@ font-style: italic;</string>
<property name="enabled">
<bool>true</bool>
</property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
<property name="suffix">
<string> %</string>
</property>
@@ -2829,15 +2987,20 @@ font-style: italic;</string>
<item row="1" column="1" colspan="2">
<widget class="QFrame" name="mShapeSVGPathFrame">
<layout class="QHBoxLayout" name="horizontalLayout_26">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
- <widget class="QLineEdit" name="mShapeSVGPathLineEdit">
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
+ <widget class="QLineEdit" name="mShapeSVGPathLineEdit"/>
</item>
<item>
<widget class="QPushButton" name="mShapeSVGSelectorBtn">
@@ -3085,7 +3248,16 @@ font-style: italic;</string>
</widget>
<widget class="QWidget" name="mLabelPage_Shadow">
<layout class="QVBoxLayout" name="verticalLayout_18">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -3101,8 +3273,8 @@ font-style: italic;</string>
<rect>
<x>0</x>
<y>0</y>
- <width>465</width>
- <height>385</height>
+ <width>448</width>
+ <height>447</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_22">
@@ -3441,9 +3613,6 @@ font-style: italic;</string>
<property name="enabled">
<bool>true</bool>
</property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
<property name="suffix">
<string> %</string>
</property>
@@ -3563,7 +3732,16 @@ font-style: italic;</string>
</widget>
<widget class="QWidget" name="mLabelPage_Placement">
<layout class="QVBoxLayout" name="verticalLayout_10">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -3593,7 +3771,7 @@ font-style: italic;</string>
<x>0</x>
<y>0</y>
<width>448</width>
- <height>758</height>
+ <height>917</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_11">
@@ -3624,7 +3802,16 @@ font-style: italic;</string>
<enum>QFrame::Sunken</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -3636,11 +3823,20 @@ font-style: italic;</string>
<enum>QFrame::Sunken</enum>
</property>
<property name="currentIndex">
- <number>1</number>
+ <number>2</number>
</property>
<widget class="QWidget" name="pagePoint">
<layout class="QGridLayout" name="gridLayout_13" columnstretch="0,0,0,0">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="1">
@@ -3693,7 +3889,16 @@ font-style: italic;</string>
</widget>
<widget class="QWidget" name="pageLine">
<layout class="QGridLayout" name="gridLayout_14">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="1">
@@ -3736,9 +3941,6 @@ font-style: italic;</string>
</widget>
<widget class="QWidget" name="pagePolygon">
<layout class="QGridLayout" name="gridLayout_18">
- <property name="margin">
- <number>0</number>
- </property>
<item row="0" column="0">
<widget class="QRadioButton" name="radOverCentroid">
<property name="sizePolicy">
@@ -3755,6 +3957,13 @@ font-style: italic;</string>
</property>
</widget>
</item>
+ <item row="0" column="1">
+ <widget class="QRadioButton" name="radPolygonHorizontal">
+ <property name="text">
+ <string>Horizontal (slow)</string>
+ </property>
+ </widget>
+ </item>
<item row="1" column="0">
<widget class="QRadioButton" name="radAroundCentroid">
<property name="sizePolicy">
@@ -3768,13 +3977,6 @@ font-style: italic;</string>
</property>
</widget>
</item>
- <item row="0" column="1">
- <widget class="QRadioButton" name="radPolygonHorizontal">
- <property name="text">
- <string>Horizontal (slow)</string>
- </property>
- </widget>
- </item>
<item row="1" column="1">
<widget class="QRadioButton" name="radPolygonFree">
<property name="text">
@@ -3782,7 +3984,7 @@ font-style: italic;</string>
</property>
</widget>
</item>
- <item row="2" column="0" colspan="2">
+ <item row="2" column="0">
<widget class="QRadioButton" name="radPolygonPerimeter">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
@@ -3795,6 +3997,32 @@ font-style: italic;</string>
</property>
</widget>
</item>
+ <item row="2" column="1">
+ <widget class="QRadioButton" name="radPolygonPerimeterCurved">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Using perimeter (curved)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <spacer name="horizontalSpacer_26">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
</layout>
</widget>
</widget>
@@ -3820,7 +4048,16 @@ font-style: italic;</string>
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_10">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
@@ -3895,7 +4132,16 @@ font-style: italic;</string>
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_25">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
@@ -3975,12 +4221,21 @@ font-style: italic;</string>
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_27">
- <property name="verticalSpacing">
- <number>12</number>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
</property>
- <property name="margin">
+ <property name="rightMargin">
<number>0</number>
</property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>12</number>
+ </property>
<item row="0" column="1">
<widget class="QgsDoubleSpinBox" name="mLineDistanceSpnBx">
<property name="decimals">
@@ -4045,12 +4300,21 @@ font-style: italic;</string>
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_40">
- <property name="verticalSpacing">
- <number>12</number>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
</property>
- <property name="margin">
+ <property name="bottomMargin">
<number>0</number>
</property>
+ <property name="verticalSpacing">
+ <number>12</number>
+ </property>
<item row="0" column="0">
<widget class="QLabel" name="label_42">
<property name="sizePolicy">
@@ -4076,7 +4340,16 @@ font-style: italic;</string>
<item>
<widget class="QFrame" name="mPlacementQuadrantFrame">
<layout class="QGridLayout" name="gridLayout_19">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="2">
@@ -4089,7 +4362,16 @@ font-style: italic;</string>
<item row="0" column="1" rowspan="3">
<widget class="QFrame" name="mPlacementFixedQuadrantFrame">
<layout class="QGridLayout" name="gridLayout_3">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
@@ -4345,7 +4627,16 @@ font-style: italic;</string>
<item>
<widget class="QFrame" name="mPlacementCartographicFrame">
<layout class="QGridLayout" name="gridLayout_39">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="2">
@@ -4358,7 +4649,16 @@ font-style: italic;</string>
<item row="0" column="1" rowspan="2">
<widget class="QFrame" name="mPlacementFixedQuadrantFrame_2">
<layout class="QGridLayout" name="gridLayout_11">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
@@ -4411,12 +4711,21 @@ font-style: italic;</string>
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_15">
- <property name="verticalSpacing">
- <number>12</number>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
</property>
- <property name="margin">
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
+ <property name="verticalSpacing">
+ <number>12</number>
+ </property>
<item row="0" column="2">
<widget class="QgsDoubleSpinBox" name="mPointOffsetYSpinBox">
<property name="sizePolicy">
@@ -4521,7 +4830,16 @@ font-style: italic;</string>
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_26">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
@@ -4581,12 +4899,21 @@ font-style: italic;</string>
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_24">
- <property name="verticalSpacing">
- <number>12</number>
+ <property name="leftMargin">
+ <number>0</number>
</property>
- <property name="margin">
+ <property name="topMargin">
<number>0</number>
</property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>12</number>
+ </property>
<item row="0" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
@@ -4636,12 +4963,21 @@ font-style: italic;</string>
<item>
<widget class="QFrame" name="mPlacementMaxCharAngleFrame">
<layout class="QGridLayout" name="gridLayout_22">
- <property name="verticalSpacing">
- <number>12</number>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
</property>
- <property name="margin">
+ <property name="bottomMargin">
<number>0</number>
</property>
+ <property name="verticalSpacing">
+ <number>12</number>
+ </property>
<item row="1" column="0">
<spacer name="horizontalSpacer_19">
<property name="orientation">
@@ -4878,7 +5214,16 @@ font-style: italic;</string>
<item row="1" column="1">
<widget class="QFrame" name="mCoordAlignmentFrame">
<layout class="QHBoxLayout" name="horizontalLayout_27">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -5019,7 +5364,16 @@ font-style: italic;</string>
</widget>
<widget class="QWidget" name="mLabelPage_Rendering">
<layout class="QVBoxLayout" name="verticalLayout_13">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -5043,7 +5397,7 @@ font-style: italic;</string>
<x>0</x>
<y>0</y>
<width>448</width>
- <height>668</height>
+ <height>799</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
@@ -5409,7 +5763,16 @@ font-style: italic;</string>
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_5">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
@@ -5507,7 +5870,16 @@ font-style: italic;</string>
<item>
<widget class="QFrame" name="mUpsidedownFrame">
<layout class="QGridLayout" name="gridLayout">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
@@ -5610,7 +5982,16 @@ font-style: italic;</string>
<item>
<widget class="QFrame" name="mLimitLabelFrame">
<layout class="QGridLayout" name="gridLayout_20">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
@@ -5667,7 +6048,16 @@ font-style: italic;</string>
<item>
<widget class="QFrame" name="mMinSizeFrame">
<layout class="QGridLayout" name="gridLayout_21">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
@@ -5715,7 +6105,16 @@ font-style: italic;</string>
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -5787,7 +6186,16 @@ font-style: italic;</string>
<item>
<widget class="QFrame" name="mObstaclePriorityFrame">
<layout class="QHBoxLayout" name="horizontalLayout_18">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -5848,7 +6256,16 @@ font-style: italic;</string>
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_11">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -5902,7 +6319,16 @@ font-style: italic;</string>
<item row="5" column="0">
<widget class="QFrame" name="frameLabelWith">
<layout class="QHBoxLayout" name="horizontalLayout_3">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -6162,6 +6588,7 @@ font-style: italic;</string>
<tabstop>radOverCentroid</tabstop>
<tabstop>radAroundCentroid</tabstop>
<tabstop>radPolygonPerimeter</tabstop>
+ <tabstop>radPolygonPerimeterCurved</tabstop>
<tabstop>radPolygonHorizontal</tabstop>
<tabstop>radPolygonFree</tabstop>
<tabstop>chkLineAbove</tabstop>
@@ -6239,6 +6666,7 @@ font-style: italic;</string>
<tabstop>mObstacleFactorSlider</tabstop>
<tabstop>mObstacleFactorDDBtn</tabstop>
<tabstop>mObstacleTypeComboBox</tabstop>
+ <tabstop>mOptionsTab</tabstop>
</tabstops>
<resources>
<include location="../../images/images.qrc"/>
diff --git a/src/ui/qgsnewgeopackagelayerdialogbase.ui b/src/ui/qgsnewgeopackagelayerdialogbase.ui
index 8ea992a..2da55c8 100644
--- a/src/ui/qgsnewgeopackagelayerdialogbase.ui
+++ b/src/ui/qgsnewgeopackagelayerdialogbase.ui
@@ -127,7 +127,7 @@
</property>
<property name="icon">
<iconset>
- <normaloff>../../images/themes/default/mActionNewAttribute.svg</normaloff>../../images/themes/default/mActionNewAttribute.svg</iconset>
+ <normaloff>:/images/themes/default/mActionNewAttribute.svg</normaloff>:/images/themes/default/mActionNewAttribute.svg</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
@@ -377,7 +377,7 @@
</property>
<property name="icon">
<iconset>
- <normaloff>../../images/themes/default/mActionDeleteAttribute.svg</normaloff>../../images/themes/default/mActionDeleteAttribute.svg</iconset>
+ <normaloff>:/images/themes/default/mActionDeleteAttribute.svg</normaloff>:/images/themes/default/mActionDeleteAttribute.svg</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
diff --git a/src/ui/qgsnewspatialitelayerdialogbase.ui b/src/ui/qgsnewspatialitelayerdialogbase.ui
index 614684d..8ea7bad 100644
--- a/src/ui/qgsnewspatialitelayerdialogbase.ui
+++ b/src/ui/qgsnewspatialitelayerdialogbase.ui
@@ -336,7 +336,7 @@
</property>
<property name="icon">
<iconset>
- <normaloff>../../images/themes/default/mActionNewAttribute.svg</normaloff>../../images/themes/default/mActionNewAttribute.svg</iconset>
+ <normaloff>:/images/themes/default/mActionNewAttribute.svg</normaloff>:/images/themes/default/mActionNewAttribute.svg</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
@@ -410,7 +410,7 @@
</property>
<property name="icon">
<iconset>
- <normaloff>../../images/themes/default/mActionDeleteAttribute.svg</normaloff>../../images/themes/default/mActionDeleteAttribute.svg</iconset>
+ <normaloff>:/images/themes/default/mActionDeleteAttribute.svg</normaloff>:/images/themes/default/mActionDeleteAttribute.svg</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
diff --git a/src/ui/qgsnewvectorlayerdialogbase.ui b/src/ui/qgsnewvectorlayerdialogbase.ui
index ee3b4f9..bdd97ea 100644
--- a/src/ui/qgsnewvectorlayerdialogbase.ui
+++ b/src/ui/qgsnewvectorlayerdialogbase.ui
@@ -181,7 +181,7 @@
</property>
<property name="icon">
<iconset>
- <normaloff>../../images/themes/default/mActionNewAttribute.svg</normaloff>../../images/themes/default/mActionNewAttribute.svg</iconset>
+ <normaloff>:/images/themes/default/mActionNewAttribute.svg</normaloff>:/images/themes/default/mActionNewAttribute.svg</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
@@ -265,7 +265,7 @@
</property>
<property name="icon">
<iconset>
- <normaloff>../../images/themes/default/mActionDeleteAttribute.svg</normaloff>../../images/themes/default/mActionDeleteAttribute.svg</iconset>
+ <normaloff>:/images/themes/default/mActionDeleteAttribute.svg</normaloff>:/images/themes/default/mActionDeleteAttribute.svg</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
diff --git a/src/ui/qgsprojectpropertiesbase.ui b/src/ui/qgsprojectpropertiesbase.ui
index 2c3bb5e..b7bd2e7 100644
--- a/src/ui/qgsprojectpropertiesbase.ui
+++ b/src/ui/qgsprojectpropertiesbase.ui
@@ -42,16 +42,7 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
<item>
@@ -206,16 +197,7 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
<item>
@@ -231,16 +213,7 @@
</property>
<widget class="QWidget" name="mProjOpts_01">
<layout class="QVBoxLayout" name="verticalLayout_6">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
<item>
@@ -256,7 +229,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>683</width>
+ <width>694</width>
<height>779</height>
</rect>
</property>
@@ -721,16 +694,7 @@
</widget>
<widget class="QWidget" name="mProjOpts_02">
<layout class="QVBoxLayout" name="verticalLayout_5">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
<item>
@@ -746,8 +710,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>368</width>
- <height>46</height>
+ <width>694</width>
+ <height>779</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
@@ -780,16 +744,7 @@
</widget>
<widget class="QWidget" name="mProjOpts_03">
<layout class="QVBoxLayout" name="verticalLayout_9">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
<item>
@@ -805,8 +760,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>133</width>
- <height>100</height>
+ <width>694</width>
+ <height>779</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
@@ -866,16 +821,7 @@
</widget>
<widget class="QWidget" name="mProjOpts_04">
<layout class="QVBoxLayout" name="verticalLayout_11">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
<item>
@@ -891,8 +837,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>379</width>
- <height>564</height>
+ <width>694</width>
+ <height>779</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
@@ -1333,16 +1279,7 @@
</widget>
<widget class="QWidget" name="mProjOpts_05">
<layout class="QVBoxLayout" name="verticalLayout_14">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
<item>
@@ -1357,9 +1294,9 @@
<property name="geometry">
<rect>
<x>0</x>
- <y>0</y>
- <width>663</width>
- <height>2249</height>
+ <y>-961</y>
+ <width>674</width>
+ <height>2470</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
@@ -1908,7 +1845,7 @@
</property>
</widget>
</item>
- <item row="10" column="0" colspan="2">
+ <item row="11" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="mWMSImageQualityLabel">
@@ -1942,7 +1879,7 @@
</property>
</widget>
</item>
- <item row="9" column="0" colspan="2">
+ <item row="10" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="1">
<widget class="QLabel" name="mMaxWidthLabel">
@@ -1989,7 +1926,7 @@
</item>
</layout>
</item>
- <item row="7" column="0" colspan="2">
+ <item row="8" column="0" colspan="2">
<layout class="QHBoxLayout" name="grpWMSPrecision">
<item>
<widget class="QLabel" name="label_5">
@@ -2013,7 +1950,7 @@
</item>
</layout>
</item>
- <item row="8" column="0" colspan="2">
+ <item row="9" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="mWMSUrlLabel">
@@ -2159,6 +2096,13 @@
</layout>
</widget>
</item>
+ <item row="7" column="0">
+ <widget class="QCheckBox" name="mSegmentizeFeatureInfoGeometryCheckBox">
+ <property name="text">
+ <string>Segmentize feature info geometry</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
@@ -2399,16 +2343,7 @@
</widget>
<widget class="QWidget" name="mProjOpts_06">
<layout class="QVBoxLayout" name="verticalLayout_15">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
<item>
@@ -2424,8 +2359,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>168</width>
- <height>46</height>
+ <width>694</width>
+ <height>779</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_17">
@@ -2461,16 +2396,7 @@
</widget>
<widget class="QWidget" name="mTabRelations">
<layout class="QGridLayout" name="gridLayout_16">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
</layout>
@@ -2540,16 +2466,7 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
<item>
diff --git a/src/ui/qgssqlcomposerdialogbase.ui b/src/ui/qgssqlcomposerdialogbase.ui
index 346200a..9e72bd0 100644
--- a/src/ui/qgssqlcomposerdialogbase.ui
+++ b/src/ui/qgssqlcomposerdialogbase.ui
@@ -139,7 +139,7 @@
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
@@ -150,7 +150,7 @@
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
+ <normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
</widget>
</item>
diff --git a/src/ui/qgsstylev2managerdialogbase.ui b/src/ui/qgsstylev2managerdialogbase.ui
index 39a5dd1..da07fbb 100644
--- a/src/ui/qgsstylev2managerdialogbase.ui
+++ b/src/ui/qgsstylev2managerdialogbase.ui
@@ -117,7 +117,7 @@ QMenu::item:selected { background-color: gray; } */
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionChangeLabelProperties.png</normaloff>:/images/themes/default/mActionChangeLabelProperties.png</iconset>
+ <normaloff>:/images/themes/default/mActionChangeLabelProperties.svg</normaloff>:/images/themes/default/mActionChangeLabelProperties.svg</iconset>
</property>
<property name="autoDefault">
<bool>false</bool>
@@ -426,7 +426,7 @@ QMenu::item:selected { background-color: gray; } */
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
+ <normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
<property name="text">
<string>Remove item(s)</string>
@@ -469,7 +469,7 @@ QMenu::item:selected { background-color: gray; } */
<action name="actnAddGroup">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
<property name="text">
<string>Add group</string>
@@ -478,7 +478,7 @@ QMenu::item:selected { background-color: gray; } */
<action name="actnRemoveGroup">
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
+ <normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
<property name="text">
<string>Remove group</string>
diff --git a/src/ui/qgssubstitutionlistwidgetbase.ui b/src/ui/qgssubstitutionlistwidgetbase.ui
new file mode 100644
index 0000000..aa186d5
--- /dev/null
+++ b/src/ui/qgssubstitutionlistwidgetbase.ui
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QgsSubstitutionListWidgetBase</class>
+ <widget class="QgsPanelWidget" name="QgsSubstitutionListWidgetBase">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>291</width>
+ <height>416</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTableWidget" name="mTableSubstitutions">
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <column>
+ <property name="text">
+ <string>Text</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Substitution</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Case Sensitive</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Whole Word</string>
+ </property>
+ <property name="toolTip">
+ <string>If checked, only whole word matches are replaced</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QToolButton" name="mButtonAdd">
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="mButtonRemove">
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="mButtonImport">
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/mActionFileOpen.svg</normaloff>:/images/themes/default/mActionFileOpen.svg</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="mButtonExport">
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/mActionFileSave.svg</normaloff>:/images/themes/default/mActionFileSave.svg</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QgsPanelWidget</class>
+ <extends>QWidget</extends>
+ <header>qgspanelwidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="../../images/images.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/ui/qgstextannotationdialogbase.ui b/src/ui/qgstextannotationdialogbase.ui
index 9a04c9e..8a4df70 100644
--- a/src/ui/qgstextannotationdialogbase.ui
+++ b/src/ui/qgstextannotationdialogbase.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>517</width>
+ <width>519</width>
<height>364</height>
</rect>
</property>
@@ -97,7 +97,7 @@
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
diff --git a/src/ui/qgsunitselectionwidget.ui b/src/ui/qgsunitselectionwidget.ui
index 7545525..0560162 100644
--- a/src/ui/qgsunitselectionwidget.ui
+++ b/src/ui/qgsunitselectionwidget.ui
@@ -60,15 +60,15 @@
<string notr="true"/>
</property>
<property name="icon">
- <iconset resource="../plugins/interpolation/interpolator.qrc">
- <normaloff>:/options.png</normaloff>:/options.png</iconset>
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/mActionOptions.svg</normaloff>:/images/themes/default/mActionOptions.svg</iconset>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
- <include location="../plugins/interpolation/interpolator.qrc"/>
+ <include location="../../images/images.qrc"/>
</resources>
<connections/>
</ui>
diff --git a/src/ui/qgsvectorlayerpropertiesbase.ui b/src/ui/qgsvectorlayerpropertiesbase.ui
index 59c9c70..d1ac319 100644
--- a/src/ui/qgsvectorlayerpropertiesbase.ui
+++ b/src/ui/qgsvectorlayerpropertiesbase.ui
@@ -1357,7 +1357,7 @@
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/mActionToggleEditing.png</normaloff>:/images/themes/default/mActionToggleEditing.png</iconset>
+ <normaloff>:/images/themes/default/mActionToggleEditing.svg</normaloff>:/images/themes/default/mActionToggleEditing.svg</iconset>
</property>
</widget>
</item>
diff --git a/src/ui/symbollayer/widget_svgfill.ui b/src/ui/symbollayer/widget_svgfill.ui
index 98c8e11..6f07b0e 100644
--- a/src/ui/symbollayer/widget_svgfill.ui
+++ b/src/ui/symbollayer/widget_svgfill.ui
@@ -280,12 +280,27 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
+ <property name="iconSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
<property name="flow">
<enum>QListView::LeftToRight</enum>
</property>
+ <property name="resizeMode">
+ <enum>QListView::Adjust</enum>
+ </property>
<property name="layoutMode">
<enum>QListView::Batched</enum>
</property>
+ <property name="gridSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
diff --git a/tests/src/app/testqgisapppython.cpp b/tests/src/app/testqgisapppython.cpp
index b75c6d9..fd4d24f 100644
--- a/tests/src/app/testqgisapppython.cpp
+++ b/tests/src/app/testqgisapppython.cpp
@@ -89,6 +89,10 @@ void TestQgisAppPython::evalString()
QVERIFY( mQgisApp->mPythonUtils->evalString( "1+1", result ) );
QCOMPARE( result, QString( "2" ) );
+ // unicode handling test
+ QVERIFY( mQgisApp->mPythonUtils->evalString( QString::fromUtf8( "'čerešne'" ), result ) );
+ QCOMPARE( result, QString::fromUtf8( "čerešne" ) );
+
//bad string
QVERIFY( !mQgisApp->mPythonUtils->evalString( "1+", result ) );
}
diff --git a/tests/src/core/testqgs25drenderer.cpp b/tests/src/core/testqgs25drenderer.cpp
index 790dee6..d7a3476 100644
--- a/tests/src/core/testqgs25drenderer.cpp
+++ b/tests/src/core/testqgs25drenderer.cpp
@@ -146,6 +146,7 @@ bool TestQgs25DRenderer::imageCheck( const QString& theTestType )
//use the QgsRenderChecker test utility class to
//ensure the rendered output matches our control image
mMapSettings.setExtent( mpPolysLayer->extent() );
+ mMapSettings.setOutputSize( QSize( 400, 400 ) );
mMapSettings.setOutputDpi( 96 );
QgsExpressionContext context;
context << QgsExpressionContextUtils::mapSettingsScope( mMapSettings );
diff --git a/tests/src/core/testqgsexpression.cpp b/tests/src/core/testqgsexpression.cpp
index b5ab69d..63e4ff9 100644
--- a/tests/src/core/testqgsexpression.cpp
+++ b/tests/src/core/testqgsexpression.cpp
@@ -482,9 +482,13 @@ class TestQgsExpression: public QObject
// regexp, like
QTest::newRow( "like 1" ) << "'hello' like '%ll_'" << false << QVariant( 1 );
- QTest::newRow( "like 2" ) << "'hello' like 'lo'" << false << QVariant( 0 );
- QTest::newRow( "like 3" ) << "'hello' like '%LO'" << false << QVariant( 0 );
+ QTest::newRow( "like 2" ) << "'hello' like '_el%'" << false << QVariant( 1 );
+ QTest::newRow( "like 3" ) << "'hello' like 'lo'" << false << QVariant( 0 );
+ QTest::newRow( "like 4" ) << "'hello' like '%LO'" << false << QVariant( 0 );
QTest::newRow( "ilike" ) << "'hello' ilike '%LO'" << false << QVariant( 1 );
+ // the \\\\ is like \\ in the interface
+ QTest::newRow( "like escape 1" ) << "'1%' like '1\\\\%'" << false << QVariant( 1 );
+ QTest::newRow( "like escape 2" ) << "'1_' like '1\\\\%'" << false << QVariant( 0 );
QTest::newRow( "regexp 1" ) << "'hello' ~ 'll'" << false << QVariant( 1 );
QTest::newRow( "regexp 2" ) << "'hello' ~ '^ll'" << false << QVariant( 0 );
QTest::newRow( "regexp 3" ) << "'hello' ~ 'llo$'" << false << QVariant( 1 );
@@ -665,6 +669,16 @@ class TestQgsExpression: public QObject
QTest::newRow( "geometry_n collection" ) << "geom_to_wkt(geometry_n(geom_from_wkt('GEOMETRYCOLLECTION(POINT(0 1), POINT(0 0), POINT(1 0), POINT(1 1))'),3))" << false << QVariant( QString( "Point (1 0)" ) );
QTest::newRow( "geometry_n collection bad index 1" ) << "geometry_n(geom_from_wkt('GEOMETRYCOLLECTION(POINT(0 1), POINT(0 0), POINT(1 0), POINT(1 1))'),0)" << false << QVariant();
QTest::newRow( "geometry_n collection bad index 2" ) << "geometry_n(geom_from_wkt('GEOMETRYCOLLECTION(POINT(0 1), POINT(0 0), POINT(1 0), POINT(1 1))'),5)" << false << QVariant();
+ QTest::newRow( "boundary not geom" ) << "boundary('g')" << true << QVariant();
+ QTest::newRow( "boundary null" ) << "boundary(NULL)" << false << QVariant();
+ QTest::newRow( "boundary point" ) << "boundary(geom_from_wkt('POINT(1 2)'))" << false << QVariant();
+ QTest::newRow( "boundary polygon" ) << "geom_to_wkt(boundary(geometry:=geom_from_wkt('POLYGON((-1 -1, 4 0, 4 2, 0 2, -1 -1))')))" << false << QVariant( "LineString (-1 -1, 4 0, 4 2, 0 2, -1 -1)" );
+ QTest::newRow( "boundary line" ) << "geom_to_wkt(boundary(geom_from_wkt('LINESTRING(0 0, 1 1, 2 2)')))" << false << QVariant( "MultiPoint ((0 0),(2 2))" );
+ QTest::newRow( "line_merge not geom" ) << "line_merge('g')" << true << QVariant();
+ QTest::newRow( "line_merge null" ) << "line_merge(NULL)" << false << QVariant();
+ QTest::newRow( "line_merge point" ) << "line_merge(geom_from_wkt('POINT(1 2)'))" << false << QVariant();
+ QTest::newRow( "line_merge line" ) << "geom_to_wkt(line_merge(geometry:=geom_from_wkt('LineString(0 0, 10 10)')))" << false << QVariant( "LineString (0 0, 10 10)" );
+ QTest::newRow( "line_merge multiline" ) << "geom_to_wkt(line_merge(geom_from_wkt('MultiLineString((0 0, 10 10),(10 10, 20 20))')))" << false << QVariant( "LineString (0 0, 10 10, 20 20)" );
QTest::newRow( "start_point point" ) << "geom_to_wkt(start_point(geom_from_wkt('POINT(2 0)')))" << false << QVariant( "Point (2 0)" );
QTest::newRow( "start_point multipoint" ) << "geom_to_wkt(start_point(geom_from_wkt('MULTIPOINT((3 3), (1 1), (2 2))')))" << false << QVariant( "Point (3 3)" );
QTest::newRow( "start_point line" ) << "geom_to_wkt(start_point(geom_from_wkt('LINESTRING(4 1, 1 1, 2 2)')))" << false << QVariant( "Point (4 1)" );
@@ -748,6 +762,26 @@ class TestQgsExpression: public QObject
QTest::newRow( "shortest_line geom" ) << "geom_to_wkt(shortest_line( geom_from_wkt('LineString( 1 1, 5 1, 5 5 )'),geom_from_wkt('Point( 6 3 )')))" << false << QVariant( "LineString (5 3, 6 3)" );
QTest::newRow( "shortest_line not geom" ) << "shortest_line('g','a')" << true << QVariant();
QTest::newRow( "shortest_line null" ) << "shortest_line(NULL,NULL)" << false << QVariant();
+ QTest::newRow( "line_interpolate_point not geom" ) << "line_interpolate_point('g', 5)" << true << QVariant();
+ QTest::newRow( "line_interpolate_point null" ) << "line_interpolate_point(NULL, 5)" << false << QVariant();
+ QTest::newRow( "line_interpolate_point point" ) << "line_interpolate_point(geom_from_wkt('POINT(1 2)'),5)" << false << QVariant();
+ QTest::newRow( "line_interpolate_point line" ) << "geom_to_wkt(line_interpolate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),distance:=5))" << false << QVariant( "Point (5 0)" );
+ QTest::newRow( "line_locate_point not geom" ) << "line_locate_point('g', geom_from_wkt('Point 5 0'))" << false << QVariant();
+ QTest::newRow( "line_locate_point null" ) << "line_locate_point(NULL, geom_from_wkt('Point 5 0'))" << false << QVariant();
+ QTest::newRow( "line_locate_point point" ) << "line_locate_point(geom_from_wkt('POINT(1 2)'),geom_from_wkt('Point 5 0'))" << false << QVariant();
+ QTest::newRow( "line_locate_point line" ) << "line_locate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),point:=geom_from_wkt('Point(5 0)'))" << false << QVariant( 5.0 );
+ QTest::newRow( "line_interpolate_angle not geom" ) << "line_interpolate_angle('g', 5)" << true << QVariant();
+ QTest::newRow( "line_interpolate_angle null" ) << "line_interpolate_angle(NULL, 5)" << false << QVariant();
+ QTest::newRow( "line_interpolate_angle point" ) << "line_interpolate_angle(geom_from_wkt('POINT(1 2)'),5)" << false << QVariant( 0.0 );
+ QTest::newRow( "line_interpolate_angle line" ) << "line_interpolate_angle(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),distance:=5)" << false << QVariant( 90.0 );
+ QTest::newRow( "angle_at_vertex not geom" ) << "angle_at_vertex('g', 5)" << true << QVariant();
+ QTest::newRow( "angle_at_vertex null" ) << "angle_at_vertex(NULL, 0)" << false << QVariant();
+ QTest::newRow( "angle_at_vertex point" ) << "angle_at_vertex(geom_from_wkt('POINT(1 2)'),0)" << false << QVariant( 0.0 );
+ QTest::newRow( "angle_at_vertex line" ) << "angle_at_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)" << false << QVariant( 45.0 );
+ QTest::newRow( "distance_to_vertex not geom" ) << "distance_to_vertex('g', 5)" << true << QVariant();
+ QTest::newRow( "distance_to_vertex null" ) << "distance_to_vertex(NULL, 0)" << false << QVariant();
+ QTest::newRow( "distance_to_vertex point" ) << "distance_to_vertex(geom_from_wkt('POINT(1 2)'),0)" << false << QVariant( 0.0 );
+ QTest::newRow( "distance_to_vertex line" ) << "distance_to_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)" << false << QVariant( 10.0 );
QTest::newRow( "transform invalid" ) << "transform(make_point(0,0),'EPSG:4326','EPSG:28356')" << false << QVariant();
// string functions
diff --git a/tests/src/core/testqgsfield.cpp b/tests/src/core/testqgsfield.cpp
index 1a7b53f..6d142a7 100644
--- a/tests/src/core/testqgsfield.cpp
+++ b/tests/src/core/testqgsfield.cpp
@@ -34,11 +34,13 @@ class TestQgsField: public QObject
void copy();// test cpy destruction (double delete)
void assignment();
void gettersSetters(); //test getters and setters
+ void isNumeric(); //test isNumeric
void equality(); //test equality operators
void asVariant(); //test conversion to and from a QVariant
void displayString();
void convertCompatible();
void dataStream();
+ void displayName();
private:
};
@@ -115,6 +117,33 @@ void TestQgsField::gettersSetters()
QCOMPARE( field.precision(), 2 );
field.setComment( "comment" );
QCOMPARE( field.comment(), QString( "comment" ) );
+ field.setAlias( "alias" );
+ QCOMPARE( field.alias(), QString( "alias" ) );
+ field.setDefaultValueExpression( "1+2" );
+ QCOMPARE( field.defaultValueExpression(), QString( "1+2" ) );
+}
+
+void TestQgsField::isNumeric()
+{
+ QgsField field;
+ field.setType( QVariant::Int );
+ QVERIFY( field.isNumeric() );
+ field.setType( QVariant::UInt );
+ QVERIFY( field.isNumeric() );
+ field.setType( QVariant::Double );
+ QVERIFY( field.isNumeric() );
+ field.setType( QVariant::LongLong );
+ QVERIFY( field.isNumeric() );
+ field.setType( QVariant::ULongLong );
+ QVERIFY( field.isNumeric() );
+ field.setType( QVariant::String );
+ QVERIFY( !field.isNumeric() );
+ field.setType( QVariant::DateTime );
+ QVERIFY( !field.isNumeric() );
+ field.setType( QVariant::Bool );
+ QVERIFY( !field.isNumeric() );
+ field.setType( QVariant::Invalid );
+ QVERIFY( !field.isNumeric() );
}
void TestQgsField::equality()
@@ -153,6 +182,14 @@ void TestQgsField::equality()
QVERIFY( !( field1 == field2 ) );
QVERIFY( field1 != field2 );
field2.setPrecision( 2 );
+ field2.setAlias( "alias " );
+ QVERIFY( !( field1 == field2 ) );
+ QVERIFY( field1 != field2 );
+ field2.setAlias( QString() );
+ field2.setDefaultValueExpression( "1+2" );
+ QVERIFY( !( field1 == field2 ) );
+ QVERIFY( field1 != field2 );
+ field2.setDefaultValueExpression( QString() );
}
void TestQgsField::asVariant()
@@ -334,6 +371,8 @@ void TestQgsField::dataStream()
original.setPrecision( 2 );
original.setTypeName( "typename1" );
original.setComment( "comment1" );
+ original.setAlias( "alias" );
+ original.setDefaultValueExpression( "default" );
QByteArray ba;
QDataStream ds( &ba, QIODevice::ReadWrite );
@@ -348,5 +387,16 @@ void TestQgsField::dataStream()
QCOMPARE( result.comment(), original.comment() ); //comment is NOT required for equality
}
+void TestQgsField::displayName()
+{
+ QgsField field;
+ field.setName( "name" );
+ QCOMPARE( field.displayName(), QString( "name" ) );
+ field.setAlias( "alias" );
+ QCOMPARE( field.displayName(), QString( "alias" ) );
+ field.setAlias( QString() );
+ QCOMPARE( field.displayName(), QString( "name" ) );
+}
+
QTEST_MAIN( TestQgsField )
#include "testqgsfield.moc"
diff --git a/tests/src/core/testqgsgeometry.cpp b/tests/src/core/testqgsgeometry.cpp
index 55187ee..2fe4646 100644
--- a/tests/src/core/testqgsgeometry.cpp
+++ b/tests/src/core/testqgsgeometry.cpp
@@ -33,6 +33,9 @@
#include "qgspointv2.h"
#include "qgslinestringv2.h"
#include "qgspolygonv2.h"
+#include "qgsmultipointv2.h"
+#include "qgsmultilinestringv2.h"
+#include "qgsmultipolygonv2.h"
#include "qgscircularstringv2.h"
#include "qgsgeometrycollectionv2.h"
#include "qgsgeometryfactory.h"
@@ -60,9 +63,15 @@ class TestQgsGeometry : public QObject
void assignment();
void asVariant(); //test conversion to and from a QVariant
void isEmpty();
+
+ // geometry types
void pointV2(); //test QgsPointV2
void lineStringV2(); //test QgsLineStringV2
void polygonV2(); //test QgsPolygonV2
+ void multiPoint();
+ void multiLineString();
+ void multiPolygon();
+ void geometryCollection();
void fromQgsPoint();
void fromQPoint();
@@ -666,12 +675,11 @@ void TestQgsGeometry::pointV2()
p20.deleteVertex( QgsVertexId( 0, 0, 0 ) );
QCOMPARE( p20, QgsPointV2( 2.0, 3.0 ) );
- //closestSegment
+ // closestSegment
QgsPointV2 closest;
QgsVertexId after;
- QCOMPARE( p20.closestSegment( QgsPointV2( 4.0, 6.0 ), closest, after, 0, 0 ), 13.0 );
- QCOMPARE( closest, p20 );
- QCOMPARE( after, QgsVertexId( 0, 0, 0 ) );
+ // return error - points have no segments
+ QVERIFY( p20.closestSegment( QgsPointV2( 4.0, 6.0 ), closest, after, 0, 0 ) < 0 );
//nextVertex
QgsPointV2 p21( 3.0, 4.0 );
@@ -771,6 +779,10 @@ void TestQgsGeometry::pointV2()
QCOMPARE( p29.z(), 0.0 );
QCOMPARE( p29.m(), 0.0 );
QVERIFY( !p29.convertTo( QgsWKBTypes::Polygon ) );
+
+ //boundary
+ QgsPointV2 p30( 1.0, 2.0 );
+ QVERIFY( !p30.boundary() );
}
void TestQgsGeometry::lineStringV2()
@@ -2026,11 +2038,10 @@ void TestQgsGeometry::lineStringV2()
//closest segment
QgsLineStringV2 l35;
bool leftOf = false;
+ p = QgsPointV2(); // reset all coords to zero
( void )l35.closestSegment( QgsPointV2( 1, 2 ), p, v, 0, 0 ); //empty line, just want no crash
l35.setPoints( QgsPointSequenceV2() << QgsPointV2( 5, 10 ) );
- QVERIFY( qgsDoubleNear( l35.closestSegment( QgsPointV2( 5, 10 ), p, v, 0, 0 ), 0 ) );
- QCOMPARE( p, QgsPointV2( 5, 10 ) );
- QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
+ QVERIFY( l35.closestSegment( QgsPointV2( 5, 10 ), p, v, 0, 0 ) < 0 );
l35.setPoints( QgsPointSequenceV2() << QgsPointV2( 5, 10 ) << QgsPointV2( 10, 10 ) );
QVERIFY( qgsDoubleNear( l35.closestSegment( QgsPointV2( 4, 11 ), p, v, &leftOf, 0 ), 2.0 ) );
QCOMPARE( p, QgsPointV2( 5, 10 ) );
@@ -2155,6 +2166,38 @@ void TestQgsGeometry::lineStringV2()
QVERIFY( l39.numPoints() == 2 );
l39.deleteVertex( QgsVertexId( 0, 0, 1 ) );
QVERIFY( l39.numPoints() == 0 );
+
+ //boundary
+ QgsLineStringV2 boundary1;
+ QVERIFY( !boundary1.boundary() );
+ boundary1.setPoints( QList<QgsPointV2>() << QgsPointV2( 0, 0 ) << QgsPointV2( 1, 0 ) << QgsPointV2( 1, 1 ) );
+ QgsAbstractGeometryV2* boundary = boundary1.boundary();
+ QgsMultiPointV2* mpBoundary = dynamic_cast< QgsMultiPointV2* >( boundary );
+ QVERIFY( mpBoundary );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
+ delete boundary;
+
+ // closed string = no boundary
+ boundary1.setPoints( QList<QgsPointV2>() << QgsPointV2( 0, 0 ) << QgsPointV2( 1, 0 ) << QgsPointV2( 1, 1 ) << QgsPointV2( 0, 0 ) );
+ QVERIFY( !boundary1.boundary() );
+ \
+
+ //boundary with z
+ boundary1.setPoints( QList<QgsPointV2>() << QgsPointV2( QgsWKBTypes::PointZ, 0, 0, 10 ) << QgsPointV2( QgsWKBTypes::PointZ, 1, 0, 15 ) << QgsPointV2( QgsWKBTypes::PointZ, 1, 1, 20 ) );
+ boundary = boundary1.boundary();
+ mpBoundary = dynamic_cast< QgsMultiPointV2* >( boundary );
+ QVERIFY( mpBoundary );
+ QCOMPARE( mpBoundary->geometryN( 0 )->wkbType(), QgsWKBTypes::PointZ );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->z(), 10.0 );
+ QCOMPARE( mpBoundary->geometryN( 1 )->wkbType(), QgsWKBTypes::PointZ );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->z(), 20.0 );
}
void TestQgsGeometry::polygonV2()
@@ -2879,6 +2922,283 @@ void TestQgsGeometry::polygonV2()
QVERIFY( p20.exteriorRing() );
p20.deleteVertex( QgsVertexId( 0, 0, 2 ) );
QVERIFY( !p20.exteriorRing() );
+
+ //boundary
+ QgsLineStringV2 boundary1;
+ boundary1.setPoints( QList<QgsPointV2>() << QgsPointV2( 0, 0 ) << QgsPointV2( 1, 0 ) << QgsPointV2( 1, 1 ) << QgsPointV2( 0, 0 ) );
+ QgsPolygonV2 boundaryPolygon;
+ QVERIFY( !boundaryPolygon.boundary() );
+
+ boundaryPolygon.setExteriorRing( boundary1.clone() );
+ QgsAbstractGeometryV2* boundary = boundaryPolygon.boundary();
+ QgsLineStringV2* lineBoundary = dynamic_cast< QgsLineStringV2* >( boundary );
+ QVERIFY( lineBoundary );
+ QCOMPARE( lineBoundary->numPoints(), 4 );
+ QCOMPARE( lineBoundary->xAt( 0 ), 0.0 );
+ QCOMPARE( lineBoundary->xAt( 1 ), 1.0 );
+ QCOMPARE( lineBoundary->xAt( 2 ), 1.0 );
+ QCOMPARE( lineBoundary->xAt( 3 ), 0.0 );
+ QCOMPARE( lineBoundary->yAt( 0 ), 0.0 );
+ QCOMPARE( lineBoundary->yAt( 1 ), 0.0 );
+ QCOMPARE( lineBoundary->yAt( 2 ), 1.0 );
+ QCOMPARE( lineBoundary->yAt( 3 ), 0.0 );
+ delete boundary;
+
+ // add interior rings
+ QgsLineStringV2 boundaryRing1;
+ boundaryRing1.setPoints( QList<QgsPointV2>() << QgsPointV2( 0.1, 0.1 ) << QgsPointV2( 0.2, 0.1 ) << QgsPointV2( 0.2, 0.2 ) << QgsPointV2( 0.1, 0.1 ) );
+ QgsLineStringV2 boundaryRing2;
+ boundaryRing2.setPoints( QList<QgsPointV2>() << QgsPointV2( 0.8, 0.8 ) << QgsPointV2( 0.9, 0.8 ) << QgsPointV2( 0.9, 0.9 ) << QgsPointV2( 0.8, 0.8 ) );
+ boundaryPolygon.setInteriorRings( QList< QgsCurveV2* >() << boundaryRing1.clone() << boundaryRing2.clone() );
+ boundary = boundaryPolygon.boundary();
+ QgsMultiLineStringV2* multiLineBoundary = dynamic_cast< QgsMultiLineStringV2* >( boundary );
+ QVERIFY( multiLineBoundary );
+ QCOMPARE( multiLineBoundary->numGeometries(), 3 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->numPoints(), 4 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->xAt( 0 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->xAt( 1 ), 1.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->xAt( 2 ), 1.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->xAt( 3 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->yAt( 0 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->yAt( 1 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->yAt( 2 ), 1.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->yAt( 3 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->numPoints(), 4 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->xAt( 0 ), 0.1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->xAt( 1 ), 0.2 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->xAt( 2 ), 0.2 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->xAt( 3 ), 0.1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->yAt( 0 ), 0.1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->yAt( 1 ), 0.1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->yAt( 2 ), 0.2 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->yAt( 3 ), 0.1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->numPoints(), 4 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->xAt( 0 ), 0.8 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->xAt( 1 ), 0.9 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->xAt( 2 ), 0.9 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->xAt( 3 ), 0.8 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->yAt( 0 ), 0.8 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->yAt( 1 ), 0.8 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->yAt( 2 ), 0.9 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->yAt( 3 ), 0.8 );
+ boundaryPolygon.setInteriorRings( QList< QgsCurveV2* >() );
+ delete boundary;
+
+ //test boundary with z
+ boundary1.setPoints( QList<QgsPointV2>() << QgsPointV2( QgsWKBTypes::PointZ, 0, 0, 10 ) << QgsPointV2( QgsWKBTypes::PointZ, 1, 0, 15 )
+ << QgsPointV2( QgsWKBTypes::PointZ, 1, 1, 20 ) << QgsPointV2( QgsWKBTypes::PointZ, 0, 0, 10 ) );
+ boundaryPolygon.setExteriorRing( boundary1.clone() );
+ boundary = boundaryPolygon.boundary();
+ lineBoundary = dynamic_cast< QgsLineStringV2* >( boundary );
+ QVERIFY( lineBoundary );
+ QCOMPARE( lineBoundary->numPoints(), 4 );
+ QCOMPARE( lineBoundary->wkbType(), QgsWKBTypes::LineStringZ );
+ QCOMPARE( lineBoundary->zAt( 0 ), 10.0 );
+ QCOMPARE( lineBoundary->zAt( 1 ), 15.0 );
+ QCOMPARE( lineBoundary->zAt( 2 ), 20.0 );
+ QCOMPARE( lineBoundary->zAt( 3 ), 10.0 );
+ delete boundary;
+
+}
+
+void TestQgsGeometry::multiPoint()
+{
+ //boundary
+
+ //multipoints have no boundary defined
+ QgsMultiPointV2 boundaryMP;
+ QVERIFY( !boundaryMP.boundary() );
+ // add some points and retest, should still be undefined
+ boundaryMP.addGeometry( new QgsPointV2( 0, 0 ) );
+ boundaryMP.addGeometry( new QgsPointV2( 1, 1 ) );
+ QVERIFY( !boundaryMP.boundary() );
+
+ // closestSegment
+ QgsPointV2 closest;
+ QgsVertexId after;
+ // return error - points have no segments
+ QVERIFY( boundaryMP.closestSegment( QgsPointV2( 0.5, 0.5 ), closest, after, 0, 0 ) < 0 );
+}
+
+void TestQgsGeometry::multiLineString()
+{
+ //boundary
+ QgsMultiLineStringV2 multiLine1;
+ QVERIFY( !multiLine1.boundary() );
+ QgsLineStringV2 boundaryLine1;
+ boundaryLine1.setPoints( QList<QgsPointV2>() << QgsPointV2( 0, 0 ) << QgsPointV2( 1, 0 ) << QgsPointV2( 1, 1 ) );
+ multiLine1.addGeometry( boundaryLine1.clone() );
+ QgsAbstractGeometryV2* boundary = multiLine1.boundary();
+ QgsMultiPointV2* mpBoundary = dynamic_cast< QgsMultiPointV2* >( boundary );
+ QVERIFY( mpBoundary );
+ QCOMPARE( mpBoundary->numGeometries(), 2 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
+ delete boundary;
+ // add another linestring
+ QgsLineStringV2 boundaryLine2;
+ boundaryLine2.setPoints( QList<QgsPointV2>() << QgsPointV2( 10, 10 ) << QgsPointV2( 11, 10 ) << QgsPointV2( 11, 11 ) );
+ multiLine1.addGeometry( boundaryLine2.clone() );
+ boundary = multiLine1.boundary();
+ mpBoundary = dynamic_cast< QgsMultiPointV2* >( boundary );
+ QVERIFY( mpBoundary );
+ QCOMPARE( mpBoundary->numGeometries(), 4 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 2 ) )->x(), 10.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 2 ) )->y(), 10.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 3 ) )->x(), 11.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 3 ) )->y(), 11.0 );
+ delete boundary;
+
+ // add a closed string = no boundary
+ QgsLineStringV2 boundaryLine3;
+ boundaryLine3.setPoints( QList<QgsPointV2>() << QgsPointV2( 20, 20 ) << QgsPointV2( 21, 20 ) << QgsPointV2( 21, 21 ) << QgsPointV2( 20, 20 ) );
+ multiLine1.addGeometry( boundaryLine3.clone() );
+ boundary = multiLine1.boundary();
+ mpBoundary = dynamic_cast< QgsMultiPointV2* >( boundary );
+ QVERIFY( mpBoundary );
+ QCOMPARE( mpBoundary->numGeometries(), 4 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 2 ) )->x(), 10.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 2 ) )->y(), 10.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 3 ) )->x(), 11.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 3 ) )->y(), 11.0 );
+ delete boundary;
+
+ //boundary with z
+ QgsLineStringV2 boundaryLine4;
+ boundaryLine4.setPoints( QList<QgsPointV2>() << QgsPointV2( QgsWKBTypes::PointZ, 0, 0, 10 ) << QgsPointV2( QgsWKBTypes::PointZ, 1, 0, 15 ) << QgsPointV2( QgsWKBTypes::PointZ, 1, 1, 20 ) );
+ QgsLineStringV2 boundaryLine5;
+ boundaryLine5.setPoints( QList<QgsPointV2>() << QgsPointV2( QgsWKBTypes::PointZ, 10, 10, 100 ) << QgsPointV2( QgsWKBTypes::PointZ, 10, 20, 150 ) << QgsPointV2( QgsWKBTypes::PointZ, 20, 20, 200 ) );
+ QgsMultiLineStringV2 multiLine2;
+ multiLine2.addGeometry( boundaryLine4.clone() );
+ multiLine2.addGeometry( boundaryLine5.clone() );
+
+ boundary = multiLine2.boundary();
+ mpBoundary = dynamic_cast< QgsMultiPointV2* >( boundary );
+ QVERIFY( mpBoundary );
+ QCOMPARE( mpBoundary->numGeometries(), 4 );
+ QCOMPARE( mpBoundary->geometryN( 0 )->wkbType(), QgsWKBTypes::PointZ );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 0 ) )->z(), 10.0 );
+ QCOMPARE( mpBoundary->geometryN( 1 )->wkbType(), QgsWKBTypes::PointZ );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 1 ) )->z(), 20.0 );
+ QCOMPARE( mpBoundary->geometryN( 2 )->wkbType(), QgsWKBTypes::PointZ );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 2 ) )->x(), 10.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 2 ) )->y(), 10.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 2 ) )->z(), 100.0 );
+ QCOMPARE( mpBoundary->geometryN( 3 )->wkbType(), QgsWKBTypes::PointZ );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 3 ) )->x(), 20.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 3 ) )->y(), 20.0 );
+ QCOMPARE( static_cast< QgsPointV2*>( mpBoundary->geometryN( 3 ) )->z(), 200.0 );
+}
+
+void TestQgsGeometry::multiPolygon()
+{
+ //boundary
+ QgsMultiPolygonV2 multiPolygon1;
+ QVERIFY( !multiPolygon1.boundary() );
+
+ QgsLineStringV2 ring1;
+ ring1.setPoints( QList<QgsPointV2>() << QgsPointV2( 0, 0 ) << QgsPointV2( 1, 0 ) << QgsPointV2( 1, 1 ) << QgsPointV2( 0, 0 ) );
+ QgsPolygonV2 polygon1;
+ polygon1.setExteriorRing( ring1.clone() );
+ multiPolygon1.addGeometry( polygon1.clone() );
+
+ QgsAbstractGeometryV2* boundary = multiPolygon1.boundary();
+ QgsMultiLineStringV2* lineBoundary = dynamic_cast< QgsMultiLineStringV2* >( boundary );
+ QVERIFY( lineBoundary );
+ QCOMPARE( lineBoundary->numGeometries(), 1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( lineBoundary->geometryN( 0 ) )->numPoints(), 4 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( lineBoundary->geometryN( 0 ) )->xAt( 0 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( lineBoundary->geometryN( 0 ) )->xAt( 1 ), 1.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( lineBoundary->geometryN( 0 ) )->xAt( 2 ), 1.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( lineBoundary->geometryN( 0 ) )->xAt( 3 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( lineBoundary->geometryN( 0 ) )->yAt( 0 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( lineBoundary->geometryN( 0 ) )->yAt( 1 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( lineBoundary->geometryN( 0 ) )->yAt( 2 ), 1.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( lineBoundary->geometryN( 0 ) )->yAt( 3 ), 0.0 );
+ delete boundary;
+
+ // add polygon with interior rings
+ QgsLineStringV2 ring2;
+ ring2.setPoints( QList<QgsPointV2>() << QgsPointV2( 10, 10 ) << QgsPointV2( 11, 10 ) << QgsPointV2( 11, 11 ) << QgsPointV2( 10, 10 ) );
+ QgsPolygonV2 polygon2;
+ polygon2.setExteriorRing( ring2.clone() );
+ QgsLineStringV2 boundaryRing1;
+ boundaryRing1.setPoints( QList<QgsPointV2>() << QgsPointV2( 10.1, 10.1 ) << QgsPointV2( 10.2, 10.1 ) << QgsPointV2( 10.2, 10.2 ) << QgsPointV2( 10.1, 10.1 ) );
+ QgsLineStringV2 boundaryRing2;
+ boundaryRing2.setPoints( QList<QgsPointV2>() << QgsPointV2( 10.8, 10.8 ) << QgsPointV2( 10.9, 10.8 ) << QgsPointV2( 10.9, 10.9 ) << QgsPointV2( 10.8, 10.8 ) );
+ polygon2.setInteriorRings( QList< QgsCurveV2* >() << boundaryRing1.clone() << boundaryRing2.clone() );
+ multiPolygon1.addGeometry( polygon2.clone() );
+
+ boundary = multiPolygon1.boundary();
+ QgsMultiLineStringV2* multiLineBoundary = dynamic_cast< QgsMultiLineStringV2* >( boundary );
+ QVERIFY( multiLineBoundary );
+ QCOMPARE( multiLineBoundary->numGeometries(), 4 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->numPoints(), 4 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->xAt( 0 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->xAt( 1 ), 1.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->xAt( 2 ), 1.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->xAt( 3 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->yAt( 0 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->yAt( 1 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->yAt( 2 ), 1.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 0 ) )->yAt( 3 ), 0.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->numPoints(), 4 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->xAt( 0 ), 10.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->xAt( 1 ), 11.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->xAt( 2 ), 11.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->xAt( 3 ), 10.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->yAt( 0 ), 10.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->yAt( 1 ), 10.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->yAt( 2 ), 11.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 1 ) )->yAt( 3 ), 10.0 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->numPoints(), 4 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->xAt( 0 ), 10.1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->xAt( 1 ), 10.2 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->xAt( 2 ), 10.2 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->xAt( 3 ), 10.1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->yAt( 0 ), 10.1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->yAt( 1 ), 10.1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->yAt( 2 ), 10.2 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 2 ) )->yAt( 3 ), 10.1 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 3 ) )->numPoints(), 4 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 3 ) )->xAt( 0 ), 10.8 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 3 ) )->xAt( 1 ), 10.9 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 3 ) )->xAt( 2 ), 10.9 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 3 ) )->xAt( 3 ), 10.8 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 3 ) )->yAt( 0 ), 10.8 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 3 ) )->yAt( 1 ), 10.8 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 3 ) )->yAt( 2 ), 10.9 );
+ QCOMPARE( dynamic_cast< QgsLineStringV2* >( multiLineBoundary->geometryN( 3 ) )->yAt( 3 ), 10.8 );
+ delete boundary;
+}
+
+void TestQgsGeometry::geometryCollection()
+{
+
+ //boundary
+
+ // collections have no boundary defined
+ QgsGeometryCollectionV2 boundaryCollection;
+ QVERIFY( !boundaryCollection.boundary() );
+ // add a geometry and retest, should still be undefined
+ QgsLineStringV2* lineBoundary = new QgsLineStringV2();
+ lineBoundary->setPoints( QList<QgsPointV2>() << QgsPointV2( 0, 0 ) << QgsPointV2( 1, 0 ) );
+ boundaryCollection.addGeometry( lineBoundary );
+ QVERIFY( !boundaryCollection.boundary() );
}
void TestQgsGeometry::fromQgsPoint()
diff --git a/tests/src/core/testqgsgeometryutils.cpp b/tests/src/core/testqgsgeometryutils.cpp
index 0b597a8..c2c6b7f 100644
--- a/tests/src/core/testqgsgeometryutils.cpp
+++ b/tests/src/core/testqgsgeometryutils.cpp
@@ -44,7 +44,9 @@ class TestQgsGeometryUtils: public QObject
void testLinePerpendicularAngle();
void testAverageAngle_data();
void testAverageAngle();
+ void testAdjacentVertices();
void testDistanceToVertex();
+ void testVerticesAtDistance();
void testCircleCenterRadius_data();
void testCircleCenterRadius();
void testSqrDistToLine();
@@ -335,6 +337,27 @@ void TestQgsGeometryUtils::testAverageAngle()
QVERIFY( qgsDoubleNear( averageAngle, expected, 0.0000000001 ) );
}
+void TestQgsGeometryUtils::testAdjacentVertices()
+{
+ // test polygon - should wrap around!
+ QgsLineStringV2* closedRing1 = new QgsLineStringV2();
+ closedRing1->setPoints( QList<QgsPointV2>() << QgsPointV2( 1, 1 ) << QgsPointV2( 1, 2 ) << QgsPointV2( 2, 2 ) << QgsPointV2( 2, 1 ) << QgsPointV2( 1, 1 ) );
+ QgsPolygonV2 polygon1;
+ polygon1.setExteriorRing( closedRing1 );
+ QgsVertexId previous;
+ QgsVertexId next;
+
+ QgsGeometryUtils::adjacentVertices( polygon1, QgsVertexId( 0, 0, 0 ), previous, next );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 3 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
+
+ // test point - both vertices should be invalid
+ QgsPointV2 point( 1, 2 );
+ QgsGeometryUtils::adjacentVertices( point, QgsVertexId( 0, 0, 0 ), previous, next );
+ QVERIFY( !previous.isValid() );
+ QVERIFY( !next.isValid() );
+}
+
void TestQgsGeometryUtils::testDistanceToVertex()
{
//test with linestring
@@ -365,6 +388,84 @@ void TestQgsGeometryUtils::testDistanceToVertex()
QCOMPARE( QgsGeometryUtils::distanceToVertex( point, QgsVertexId( 0, 0, 1 ) ), -1.0 );
}
+void TestQgsGeometryUtils::testVerticesAtDistance()
+{
+ //test with linestring
+ QgsLineStringV2* outerRing1 = new QgsLineStringV2();
+ QgsVertexId previous;
+ QgsVertexId next;
+ QVERIFY( !QgsGeometryUtils::verticesAtDistance( *outerRing1, .5, previous, next ) );
+
+ outerRing1->setPoints( QList<QgsPointV2>() << QgsPointV2( 1, 1 ) << QgsPointV2( 1, 2 ) << QgsPointV2( 2, 2 ) << QgsPointV2( 2, 1 ) << QgsPointV2( 3, 1 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, .5, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 1.5, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 1 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 2 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 2.5, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 2 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 3 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 3.5, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 3 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
+ QVERIFY( ! QgsGeometryUtils::verticesAtDistance( *outerRing1, 4.5, previous, next ) );
+
+ // test exact hits
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 0, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 0 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 1, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 1 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 2, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 2 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 2 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 3, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 3 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 3 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 4, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 4 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
+
+ // test closed line
+ QgsLineStringV2* closedRing1 = new QgsLineStringV2();
+ closedRing1->setPoints( QList<QgsPointV2>() << QgsPointV2( 1, 1 ) << QgsPointV2( 1, 2 ) << QgsPointV2( 2, 2 ) << QgsPointV2( 2, 1 ) << QgsPointV2( 1, 1 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *closedRing1, 0, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 0 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( *closedRing1, 4, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 4 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
+
+ // test with polygon
+ QgsPolygonV2 polygon1;
+ polygon1.setExteriorRing( closedRing1 );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, .5, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 1.5, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 1 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 2 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 2.5, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 2 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 3 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 3.5, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 3 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
+ QVERIFY( ! QgsGeometryUtils::verticesAtDistance( polygon1, 4.5, previous, next ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 0, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 0 ) );
+ QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 4, previous, next ) );
+ QCOMPARE( previous, QgsVertexId( 0, 0, 4 ) );
+ QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
+
+ //test with point
+ QgsPointV2 point( 1, 2 );
+ QVERIFY( !QgsGeometryUtils::verticesAtDistance( point, .5, previous, next ) );
+}
+
void TestQgsGeometryUtils::testCircleCenterRadius_data()
{
QTest::addColumn<double>( "x1" );
diff --git a/tests/src/core/testqgslabelingenginev2.cpp b/tests/src/core/testqgslabelingenginev2.cpp
index 2a1fc76..8d08ddb 100644
--- a/tests/src/core/testqgslabelingenginev2.cpp
+++ b/tests/src/core/testqgslabelingenginev2.cpp
@@ -43,6 +43,7 @@ class TestQgsLabelingEngineV2 : public QObject
void testRuleBased();
void zOrder(); //test that labels are stacked correctly
void testEncodeDecodePositionOrder();
+ void testSubstitutions();
void testCapitalization();
private:
@@ -414,6 +415,46 @@ void TestQgsLabelingEngineV2::testEncodeDecodePositionOrder()
QCOMPARE( decoded, expected );
}
+void TestQgsLabelingEngineV2::testSubstitutions()
+{
+ QgsPalLayerSettings settings;
+ settings.useSubstitutions = false;
+ QgsStringReplacementCollection collection( QList< QgsStringReplacement >() << QgsStringReplacement( "aa", "bb" ) );
+ settings.substitutions = collection;
+ settings.fieldName = QString( "'aa label'" );
+ settings.isExpression = true;
+
+ QgsVectorLayerLabelProvider* provider = new QgsVectorLayerLabelProvider( vl, "test", true, &settings );
+ QgsFeature f( vl->fields(), 1 );
+ f.setGeometry( QgsGeometry::fromPoint( QgsPoint( 1, 2 ) ) );
+
+ // make a fake render context
+ QSize size( 640, 480 );
+ QgsMapSettings mapSettings;
+ mapSettings.setOutputSize( size );
+ mapSettings.setExtent( vl->extent() );
+ mapSettings.setLayers( QStringList() << vl->id() );
+ mapSettings.setOutputDpi( 96 );
+ QgsRenderContext context = QgsRenderContext::fromMapSettings( mapSettings );
+ QStringList attributes;
+ QgsLabelingEngineV2 engine;
+ engine.setMapSettings( mapSettings );
+ engine.addProvider( provider );
+ provider->prepare( context, attributes );
+
+ provider->registerFeature( f, context );
+ QCOMPARE( provider->mLabels.at( 0 )->labelText(), QString( "aa label" ) );
+
+ //with substitution
+ settings.useSubstitutions = true;
+ QgsVectorLayerLabelProvider* provider2 = new QgsVectorLayerLabelProvider( vl, "test2", true, &settings );
+ engine.addProvider( provider2 );
+ provider2->prepare( context, attributes );
+
+ provider2->registerFeature( f, context );
+ QCOMPARE( provider2->mLabels.at( 0 )->labelText(), QString( "bb label" ) );
+}
+
void TestQgsLabelingEngineV2::testCapitalization()
{
QgsFeature f( vl->fields(), 1 );
@@ -473,6 +514,7 @@ void TestQgsLabelingEngineV2::testCapitalization()
QCOMPARE( provider4->mLabels.at( 0 )->labelText(), QString( "A TeSt LABEL" ) );
}
+
bool TestQgsLabelingEngineV2::imageCheck( const QString& testName, QImage &image, int mismatchCount )
{
//draw background
diff --git a/tests/src/core/testqgslegendrenderer.cpp b/tests/src/core/testqgslegendrenderer.cpp
index 38acd4d..ff6e552 100644
--- a/tests/src/core/testqgslegendrenderer.cpp
+++ b/tests/src/core/testqgslegendrenderer.cpp
@@ -115,6 +115,7 @@ class TestQgsLegendRenderer : public QObject
void testBasic();
void testBigMarker();
void testMapUnits();
+ void testTallSymbol();
void testLongSymbolText();
void testThreeColumns();
void testFilterByMap();
@@ -336,6 +337,28 @@ void TestQgsLegendRenderer::testMapUnits()
QVERIFY( _verifyImage( testName, mReport ) );
}
+void TestQgsLegendRenderer::testTallSymbol()
+{
+ QString testName = "legend_tall_symbol";
+
+ QgsCategorizedSymbolRendererV2* catRenderer = dynamic_cast<QgsCategorizedSymbolRendererV2*>( mVL3->rendererV2() );
+ QVERIFY( catRenderer );
+ catRenderer->updateCategoryLabel( 1, "This is\nthree lines\nlong label" );
+
+ mVL2->setName( "This is a two lines\nlong label" );
+
+ QgsLayerTreeModel legendModel( mRoot );
+
+ QgsLegendSettings settings;
+ settings.setWrapChar( "\n" );
+ settings.setSymbolSize( QSizeF( 10.0, 10.0 ) );
+ _setStandardTestFont( settings );
+ _renderLegend( testName, &legendModel, settings );
+ QVERIFY( _verifyImage( testName, mReport ) );
+
+ mVL2->setName( "Polygon Layer" );
+}
+
void TestQgsLegendRenderer::testLongSymbolText()
{
QString testName = "legend_long_symbol_text";
diff --git a/tests/src/core/testqgsmarkerlinesymbol.cpp b/tests/src/core/testqgsmarkerlinesymbol.cpp
index 8f6bec0..c269ead 100644
--- a/tests/src/core/testqgsmarkerlinesymbol.cpp
+++ b/tests/src/core/testqgsmarkerlinesymbol.cpp
@@ -29,6 +29,10 @@
#include "qgsmaprenderer.h"
#include "qgspallabeling.h"
#include "qgsfontutils.h"
+#include "qgslinesymbollayerv2.h"
+#include "qgssinglesymbolrendererv2.h"
+#include "qgsmarkersymbollayerv2.h"
+#include "qgsdatadefined.h"
//qgis unit test includes
#include <qgsrenderchecker.h>
@@ -56,6 +60,8 @@ class TestQgsMarkerLineSymbol : public QObject
void cleanup() {} // will be called after every testfunction.
void lineOffset();
+ void pointNumInterval();
+ void pointNumVertex();
private:
bool render( const QString& theFileName );
@@ -137,6 +143,65 @@ void TestQgsMarkerLineSymbol::lineOffset()
// http://hub.qgis.org/issues/13811#note-1
}
+void TestQgsMarkerLineSymbol::pointNumInterval()
+{
+ mMapSettings->setLayers( QStringList() << mLinesLayer->id() );
+
+ QgsMarkerLineSymbolLayerV2* ml = new QgsMarkerLineSymbolLayerV2();
+ ml->setPlacement( QgsMarkerLineSymbolLayerV2::Interval );
+ ml->setInterval( 4 );
+ QgsLineSymbolV2* lineSymbol = new QgsLineSymbolV2();
+ lineSymbol->changeSymbolLayer( 0, ml );
+ QgsSingleSymbolRendererV2* r = new QgsSingleSymbolRendererV2( lineSymbol );
+
+ // make sub-symbol
+ QgsStringMap props;
+ props["color"] = "255,0,0";
+ props["size"] = "2";
+ props["outline_style"] = "no";
+ QgsSimpleMarkerSymbolLayerV2* marker = static_cast< QgsSimpleMarkerSymbolLayerV2* >( QgsSimpleMarkerSymbolLayerV2::create( props ) );
+
+ marker->setDataDefinedProperty( "size", new QgsDataDefined( true, true, "@geometry_point_num * 2" ) );
+
+ QgsMarkerSymbolV2* subSymbol = new QgsMarkerSymbolV2();
+ subSymbol->changeSymbolLayer( 0, marker );
+ ml->setSubSymbol( subSymbol );
+
+ mLinesLayer->setRendererV2( r );
+
+ mMapSettings->setExtent( QgsRectangle( -140, -140, 140, 140 ) );
+ QVERIFY( render( "point_num_interval" ) );
+}
+
+void TestQgsMarkerLineSymbol::pointNumVertex()
+{
+ mMapSettings->setLayers( QStringList() << mLinesLayer->id() );
+
+ QgsMarkerLineSymbolLayerV2* ml = new QgsMarkerLineSymbolLayerV2();
+ ml->setPlacement( QgsMarkerLineSymbolLayerV2::Vertex );
+ QgsLineSymbolV2* lineSymbol = new QgsLineSymbolV2();
+ lineSymbol->changeSymbolLayer( 0, ml );
+ QgsSingleSymbolRendererV2* r = new QgsSingleSymbolRendererV2( lineSymbol );
+
+ // make sub-symbol
+ QgsStringMap props;
+ props["color"] = "255,0,0";
+ props["size"] = "2";
+ props["outline_style"] = "no";
+ QgsSimpleMarkerSymbolLayerV2* marker = static_cast< QgsSimpleMarkerSymbolLayerV2* >( QgsSimpleMarkerSymbolLayerV2::create( props ) );
+
+ marker->setDataDefinedProperty( "size", new QgsDataDefined( true, true, "@geometry_point_num * 2" ) );
+
+ QgsMarkerSymbolV2* subSymbol = new QgsMarkerSymbolV2();
+ subSymbol->changeSymbolLayer( 0, marker );
+ ml->setSubSymbol( subSymbol );
+
+ mLinesLayer->setRendererV2( r );
+
+ mMapSettings->setExtent( QgsRectangle( -140, -140, 140, 140 ) );
+ QVERIFY( render( "point_num_vertex" ) );
+}
+
bool TestQgsMarkerLineSymbol::render( const QString& theTestType )
{
mReport += "<h2>" + theTestType + "</h2>\n";
diff --git a/tests/src/core/testqgsogcutils.cpp b/tests/src/core/testqgsogcutils.cpp
index fee973b..2f8acf4 100644
--- a/tests/src/core/testqgsogcutils.cpp
+++ b/tests/src/core/testqgsogcutils.cpp
@@ -93,12 +93,126 @@ void TestQgsOgcUtils::testGeometryFromGML()
QVERIFY( geomBox->wkbType() == QGis::WKBPolygon );
}
+static bool compareElements( QDomElement& element1, QDomElement& element2 )
+{
+ QString tag1 = element1.tagName();
+ tag1.replace( QRegExp( ".*:" ), "" );
+ QString tag2 = element2.tagName();
+ tag2.replace( QRegExp( ".*:" ), "" );
+ if ( tag1 != tag2 )
+ {
+ qDebug( "Different tag names: %s, %s", tag1.toAscii().data(), tag2.toAscii().data() );
+ return false ;
+ }
+
+ if ( element1.hasAttributes() != element2.hasAttributes() )
+ {
+ qDebug( "Different hasAttributes: %s, %s", tag1.toAscii().data(), tag2.toAscii().data() );
+ return false;
+ }
+
+ if ( element1.hasAttributes() )
+ {
+ QDomNamedNodeMap attrs1 = element1.attributes();
+ QDomNamedNodeMap attrs2 = element2.attributes();
+
+ if ( attrs1.size() != attrs2.size() )
+ {
+ qDebug( "Different attributes size: %s, %s", tag1.toAscii().data(), tag2.toAscii().data() );
+ return false;
+ }
+
+ for ( int i = 0 ; i < attrs1.size() ; ++i )
+ {
+ QDomNode node1 = attrs1.item( i );
+ QDomAttr attr1 = node1.toAttr();
+
+ if ( !element2.hasAttribute( attr1.name() ) )
+ {
+ qDebug( "Element2 has not attribute: %s, %s, %s", tag1.toAscii().data(), tag2.toAscii().data(), attr1.name().toAscii().data() );
+ return false;
+ }
+
+ if ( element2.attribute( attr1.name() ) != attr1.value() )
+ {
+ qDebug( "Element2 attribute has not the same value: %s, %s, %s", tag1.toAscii().data(), tag2.toAscii().data(), attr1.name().toAscii().data() );
+ return false;
+ }
+ }
+ }
+
+ if ( element1.hasChildNodes() != element2.hasChildNodes() )
+ {
+ qDebug( "Different childNodes: %s, %s", tag1.toAscii().data(), tag2.toAscii().data() );
+ return false;
+ }
+
+ if ( element1.hasChildNodes() )
+ {
+ QDomNodeList nodes1 = element1.childNodes();
+ QDomNodeList nodes2 = element2.childNodes();
+
+ if ( nodes1.size() != nodes2.size() )
+ {
+ qDebug( "Different childNodes size: %s, %s", tag1.toAscii().data(), tag2.toAscii().data() );
+ return false;
+ }
+
+ for ( int i = 0 ; i < nodes1.size() ; ++i )
+ {
+ QDomNode node1 = nodes1.at( i );
+ QDomNode node2 = nodes2.at( i );
+ if ( node1.isElement() && node2.isElement() )
+ {
+ QDomElement elt1 = node1.toElement();
+ QDomElement elt2 = node2.toElement();
+
+ if ( !compareElements( elt1, elt2 ) )
+ return false;
+ }
+ else if ( node1.isText() && node2.isText() )
+ {
+ QDomText txt1 = node1.toText();
+ QDomText txt2 = node2.toText();
+
+ if ( txt1.data() != txt2.data() )
+ {
+ qDebug( "Different text data: %s %s", tag1.toAscii().data(), txt1.data().toAscii().data() );
+ qDebug( "Different text data: %s %s", tag2.toAscii().data(), txt2.data().toAscii().data() );
+ return false;
+ }
+ }
+ }
+ }
+
+ if ( element1.text() != element2.text() )
+ {
+ qDebug( "Different text: %s %s", tag1.toAscii().data(), element1.text().toAscii().data() );
+ qDebug( "Different text: %s %s", tag2.toAscii().data(), element2.text().toAscii().data() );
+ return false;
+ }
+
+ return true;
+}
+static QDomElement comparableElement( const QString& xmlText )
+{
+ QDomDocument doc;
+ if ( !doc.setContent( xmlText ) )
+ return QDomElement();
+ return doc.documentElement();
+}
+
+
void TestQgsOgcUtils::testGeometryToGML()
{
QDomDocument doc;
QSharedPointer<QgsGeometry> geomPoint( QgsGeometry::fromPoint( QgsPoint( 111, 222 ) ) );
QSharedPointer<QgsGeometry> geomLine( QgsGeometry::fromWkt( "LINESTRING(111 222, 222 222)" ) );
+ // Elements to compare
+ QDomElement xmlElem;
+ QDomElement ogcElem;
+
// Test GML2
QDomElement elemInvalid = QgsOgcUtils::geometryToGML( 0, doc );
QVERIFY( elemInvalid.isNull() );
@@ -107,14 +221,18 @@ void TestQgsOgcUtils::testGeometryToGML()
QVERIFY( !elemPoint.isNull() );
doc.appendChild( elemPoint );
- QCOMPARE( doc.toString( -1 ), QString( "<gml:Point><gml:coordinates cs=\",\" ts=\" \">111,222</gml:coordinates></gml:Point>" ) );
+ xmlElem = comparableElement( QString( "<gml:Point><gml:coordinates ts=\" \" cs=\",\">111,222</gml:coordinates></gml:Point>" ) );
+ ogcElem = comparableElement( doc.toString( -1 ) );
+ QVERIFY( compareElements( xmlElem, ogcElem ) );
doc.removeChild( elemPoint );
QDomElement elemLine = QgsOgcUtils::geometryToGML( geomLine.data(), doc );
QVERIFY( !elemLine.isNull() );
doc.appendChild( elemLine );
- QCOMPARE( doc.toString( -1 ), QString( "<gml:LineString><gml:coordinates cs=\",\" ts=\" \">111,222 222,222</gml:coordinates></gml:LineString>" ) );
+ xmlElem = comparableElement( QString( "<gml:LineString><gml:coordinates ts=\" \" cs=\",\">111,222 222,222</gml:coordinates></gml:LineString>" ) );
+ ogcElem = comparableElement( doc.toString( -1 ) );
+ QVERIFY( compareElements( xmlElem, ogcElem ) );
doc.removeChild( elemLine );
// Test GML3
@@ -125,14 +243,18 @@ void TestQgsOgcUtils::testGeometryToGML()
QVERIFY( !elemPoint.isNull() );
doc.appendChild( elemPoint );
- QCOMPARE( doc.toString( -1 ), QString( "<gml:Point><gml:pos srsDimension=\"2\">111 222</gml:pos></gml:Point>" ) );
+ xmlElem = comparableElement( QString( "<gml:Point><gml:pos srsDimension=\"2\">111 222</gml:pos></gml:Point>" ) );
+ ogcElem = comparableElement( doc.toString( -1 ) );
+ QVERIFY( compareElements( xmlElem, ogcElem ) );
doc.removeChild( elemPoint );
elemLine = QgsOgcUtils::geometryToGML( geomLine.data(), doc, "GML3" );
QVERIFY( !elemLine.isNull() );
doc.appendChild( elemLine );
- QCOMPARE( doc.toString( -1 ), QString( "<gml:LineString><gml:posList srsDimension=\"2\">111 222 222 222</gml:posList></gml:LineString>" ) );
+ xmlElem = comparableElement( QString( "<gml:LineString><gml:posList srsDimension=\"2\">111 222 222 222</gml:posList></gml:LineString>" ) );
+ ogcElem = comparableElement( doc.toString( -1 ) );
+ QVERIFY( compareElements( xmlElem, ogcElem ) );
doc.removeChild( elemLine );
}
@@ -180,13 +302,41 @@ void TestQgsOgcUtils::testExpressionFromOgcFilter_data()
"</Filter>" )
<< QString( "POPULATION >= 100 AND POPULATION <= 200" );
- // TODO: needs to handle different wildcards, single chars, escape chars
+ // handle different wildcards, single chars, escape chars
QTest::newRow( "like" ) << QString(
"<Filter>"
- "<PropertyIsLike wildcard='*' singleChar='.' escape='!'>"
+ "<PropertyIsLike wildCard=\"%\" singleChar=\"_\" escape=\"\\\">"
"<PropertyName>NAME</PropertyName><Literal>*QGIS*</Literal></PropertyIsLike>"
"</Filter>" )
<< QString( "NAME LIKE '*QGIS*'" );
+ QTest::newRow( "ilike" ) << QString(
+ "<Filter>"
+ "<PropertyIsLike matchCase=\"false\" wildCard=\"%\" singleChar=\"_\" escape=\"\\\">"
+ "<PropertyName>NAME</PropertyName><Literal>*QGIS*</Literal></PropertyIsLike>"
+ "</Filter>" )
+ << QString( "NAME ILIKE '*QGIS*'" );
+
+ // different wildCards
+ QTest::newRow( "like wildCard" ) << QString(
+ "<Filter>"
+ "<PropertyIsLike wildCard='*' singleChar='.' escape=\"\\\">"
+ "<PropertyName>NAME</PropertyName><Literal>*%QGIS*\\*</Literal></PropertyIsLike>"
+ "</Filter>" )
+ << QString( "NAME LIKE '%\\\\%QGIS%*'" );
+ // different single chars
+ QTest::newRow( "like single char" ) << QString(
+ "<Filter>"
+ "<PropertyIsLike wildCard='*' singleChar='.' escape=\"\\\">"
+ "<PropertyName>NAME</PropertyName><Literal>._QGIS.\\.</Literal></PropertyIsLike>"
+ "</Filter>" )
+ << QString( "NAME LIKE '_\\\\_QGIS_.'" );
+ // different single chars
+ QTest::newRow( "like escape char" ) << QString(
+ "<Filter>"
+ "<PropertyIsLike wildCard=\"*\" singleChar=\".\" escape=\"!\">"
+ "<PropertyName>NAME</PropertyName><Literal>_QGIS.!.!!%QGIS*!*</Literal></PropertyIsLike>"
+ "</Filter>" )
+ << QString( "NAME LIKE '\\\\_QGIS_.!\\\\%QGIS%*'" );
QTest::newRow( "is null" ) << QString(
"<Filter>"
@@ -259,7 +409,10 @@ void TestQgsOgcUtils::testExpressionToOgcFilter()
qDebug( "EXPR: %s", exp.expression().toAscii().data() );
qDebug( "OGC : %s", doc.toString( -1 ).toAscii().data() );
- QCOMPARE( xmlText, doc.toString( -1 ) );
+
+ QDomElement xmlElem = comparableElement( xmlText );
+ QDomElement ogcElem = comparableElement( doc.toString( -1 ) );
+ QVERIFY( compareElements( xmlElem, ogcElem ) );
}
void TestQgsOgcUtils::testExpressionToOgcFilter_data()
@@ -301,6 +454,22 @@ void TestQgsOgcUtils::testExpressionToOgcFilter_data()
"</ogc:And>"
"</ogc:Filter>" );
+ QTest::newRow( "like" ) << QString( "NAME LIKE '*QGIS*'" ) << QString(
+ "<ogc:Filter xmlns:ogc=\"http://www.opengis.net/ogc\">"
+ "<ogc:PropertyIsLike singleChar=\"_\" escape=\"\\\" wildCard=\"%\">"
+ "<ogc:PropertyName>NAME</ogc:PropertyName>"
+ "<ogc:Literal>*QGIS*</ogc:Literal>"
+ "</ogc:PropertyIsLike>"
+ "</ogc:Filter>" );
+
+ QTest::newRow( "ilike" ) << QString( "NAME ILIKE '*QGIS*'" ) << QString(
+ "<ogc:Filter xmlns:ogc=\"http://www.opengis.net/ogc\">"
+ "<ogc:PropertyIsLike matchCase=\"false\" singleChar=\"_\" escape=\"\\\" wildCard=\"%\">"
+ "<ogc:PropertyName>NAME</ogc:PropertyName>"
+ "<ogc:Literal>*QGIS*</ogc:Literal>"
+ "</ogc:PropertyIsLike>"
+ "</ogc:Filter>" );
+
QTest::newRow( "is null" ) << QString( "A IS NULL" ) << QString(
"<ogc:Filter xmlns:ogc=\"http://www.opengis.net/ogc\">"
"<ogc:PropertyIsNull>"
@@ -405,7 +574,10 @@ void TestQgsOgcUtils::testExpressionToOgcFilterWFS11()
qDebug( "SRSNAME: %s", srsName.toAscii().data() );
qDebug( "OGC : %s", doc.toString( -1 ).toAscii().data() );
- QCOMPARE( xmlText, doc.toString( -1 ) );
+
+ QDomElement xmlElem = comparableElement( xmlText );
+ QDomElement ogcElem = comparableElement( doc.toString( -1 ) );
+ QVERIFY( compareElements( xmlElem, ogcElem ) );
}
void TestQgsOgcUtils::testExpressionToOgcFilterWFS11_data()
@@ -429,14 +601,6 @@ void TestQgsOgcUtils::testExpressionToOgcFilterWFS11_data()
"</ogc:Filter>" );
}
-static QString normalizeXML( const QString& xmlText )
-{
- QDomDocument doc;
- if ( !doc.setContent( xmlText, true ) )
- return QString();
- return doc.toString( -1 );
-}
-
void TestQgsOgcUtils::testExpressionToOgcFilterWFS20()
{
QFETCH( QString, exprText );
@@ -462,15 +626,9 @@ void TestQgsOgcUtils::testExpressionToOgcFilterWFS20()
qDebug( "SRSNAME: %s", srsName.toAscii().data() );
qDebug( "OGC : %s", doc.toString( -1 ).toAscii().data() );
- QString normalizedExpected( normalizeXML( xmlText ) );
- QString normalizedGot( normalizeXML( doc.toString( -1 ) ) );
-
- if ( normalizedExpected != normalizedGot )
- {
- qDebug( "Normalized expected: %s", normalizedExpected.toAscii().data() );
- qDebug( "Normalized got: %s", normalizedGot.toAscii().data() );
- }
- QCOMPARE( normalizedExpected, normalizedGot );
+ QDomElement xmlElem = comparableElement( xmlText );
+ QDomElement ogcElem = comparableElement( doc.toString( -1 ) );
+ QVERIFY( compareElements( xmlElem, ogcElem ) );
}
void TestQgsOgcUtils::testExpressionToOgcFilterWFS20_data()
@@ -570,15 +728,9 @@ void TestQgsOgcUtils::testSQLStatementToOgcFilter()
filterVersion == QgsOgcUtils::FILTER_FES_2_0 ? "FES 2.0" : "unknown" );
qDebug( "OGC : %s", doc.toString( -1 ).toAscii().data() );
- QString normalizedExpected( normalizeXML( xmlText ) );
- QString normalizedGot( normalizeXML( doc.toString( -1 ) ) );
-
- if ( normalizedExpected != normalizedGot )
- {
- qDebug( "Normalized expected: %s", normalizedExpected.toAscii().data() );
- qDebug( "Normalized got: %s", normalizedGot.toAscii().data() );
- }
- QCOMPARE( normalizedExpected, normalizedGot );
+ QDomElement xmlElem = comparableElement( xmlText );
+ QDomElement ogcElem = comparableElement( doc.toString( -1 ) );
+ QVERIFY( compareElements( xmlElem, ogcElem ) );
}
void TestQgsOgcUtils::testSQLStatementToOgcFilter_data()
diff --git a/tests/src/core/testqgspointlocator.cpp b/tests/src/core/testqgspointlocator.cpp
index a945d46..396029f 100644
--- a/tests/src/core/testqgspointlocator.cpp
+++ b/tests/src/core/testqgspointlocator.cpp
@@ -23,6 +23,7 @@
#include "qgsgeometry.h"
#include "qgsmaplayerregistry.h"
#include "qgspointlocator.h"
+#include "qgspolygonv2.h"
struct FilterExcludePoint : public QgsPointLocator::MatchFilter
@@ -259,6 +260,48 @@ class TestQgsPointLocator : public QObject
QVERIFY( m2.isValid() );
QCOMPARE( m2.point(), QgsPoint( 1, 1 ) );
}
+
+ void testNullGeometries()
+ {
+ QgsVectorLayer* vlNullGeom = new QgsVectorLayer( "Polygon", "x", "memory" );
+ QgsFeature ff( 0 );
+ ff.setGeometry( QgsGeometry() );
+ QgsFeatureList flist;
+ flist << ff;
+ vlNullGeom->dataProvider()->addFeatures( flist );
+
+ QgsPointLocator loc( vlNullGeom, 0, nullptr );
+
+ QgsPointLocator::Match m1 = loc.nearestVertex( QgsPoint( 2, 2 ), std::numeric_limits<double>::max() );
+ QVERIFY( !m1.isValid() );
+
+ QgsPointLocator::Match m2 = loc.nearestEdge( QgsPoint( 2, 2 ), std::numeric_limits<double>::max() );
+ QVERIFY( !m2.isValid() );
+
+ delete vlNullGeom;
+ }
+
+ void testEmptyGeometries()
+ {
+ QgsVectorLayer* vlEmptyGeom = new QgsVectorLayer( "Polygon", "x", "memory" );
+ QgsFeature ff( 0 );
+ QgsGeometry g;
+ g.setGeometry( new QgsPolygonV2() );
+ ff.setGeometry( g );
+ QgsFeatureList flist;
+ flist << ff;
+ vlEmptyGeom->dataProvider()->addFeatures( flist );
+
+ QgsPointLocator loc( vlEmptyGeom, 0, nullptr );
+
+ QgsPointLocator::Match m1 = loc.nearestVertex( QgsPoint( 2, 2 ), std::numeric_limits<double>::max() );
+ QVERIFY( !m1.isValid() );
+
+ QgsPointLocator::Match m2 = loc.nearestEdge( QgsPoint( 2, 2 ), std::numeric_limits<double>::max() );
+ QVERIFY( !m2.isValid() );
+
+ delete vlEmptyGeom;
+ }
};
QTEST_MAIN( TestQgsPointLocator )
diff --git a/tests/src/core/testqgsstringutils.cpp b/tests/src/core/testqgsstringutils.cpp
index 2d275ad..63490c0 100644
--- a/tests/src/core/testqgsstringutils.cpp
+++ b/tests/src/core/testqgsstringutils.cpp
@@ -33,6 +33,7 @@ class TestQgsStringUtils : public QObject
void longestCommonSubstring();
void hammingDistance();
void soundex();
+ void insertLinks();
};
@@ -118,6 +119,41 @@ void TestQgsStringUtils::soundex()
QCOMPARE( QgsStringUtils::soundex( "ashcroft" ), QString( "A261" ) );
}
+void TestQgsStringUtils::insertLinks()
+{
+ QCOMPARE( QgsStringUtils::insertLinks( QString() ), QString() );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "not a link!" ) ), QString( "not a link!" ) );
+ bool found = true;
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "not a link!" ), &found ), QString( "not a link!" ) );
+ QVERIFY( !found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "this www.north-road.com is a link" ), &found ), QString( "this <a href=\"http://www.north-road.com\">www.north-road.com</a> is a link" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "this www.north-road.com.au is a link" ), &found ), QString( "this <a href=\"http://www.north-road.com.au\">www.north-road.com.au</a> is a link" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "this www.north-road.sucks is not a good link" ), &found ), QString( "this <a href=\"http://www.north-road.sucks\">www.north-road.sucks</a> is not a good link" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "this http://www.north-road.com is a link" ), &found ), QString( "this <a href=\"http://www.north-road.com\">http://www.north-road.com</a> is a link" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "this http://north-road.com is a link" ), &found ), QString( "this <a href=\"http://north-road.com\">http://north-road.com</a> is a link" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "this http://north-road.com is a link, so is http://qgis.org, ok?" ), &found ), QString( "this <a href=\"http://north-road.com\">http://north-road.com</a> is a link, so is <a href=\"http://qgis.org\">http://qgis.org</a>, ok?" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "this north-road.com might not be a link" ), &found ), QString( "this north-road.com might not be a link" ) );
+ QVERIFY( !found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "please ftp to ftp://droopbox.ru and submit stuff" ), &found ), QString( "please ftp to <a href=\"ftp://droopbox.ru\">ftp://droopbox.ru</a> and submit stuff" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "please visit https://fsociety.org" ), &found ), QString( "please visit <a href=\"https://fsociety.org\">https://fsociety.org</a>" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "send your credit card number to qgis at qgis.org today!" ), &found ), QString( "send your credit card number to <a href=\"mailto:qgis at qgis.org\">qgis at qgis.org</a> today!" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "send your credit card number to qgis at qgis.org.nz today!" ), &found ), QString( "send your credit card number to <a href=\"mailto:qgis at qgis.org.nz\">qgis at qgis.org.nz</a> today!" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "visit http://qgis.org or email qgis at qgis.org" ), &found ), QString( "visit <a href=\"http://qgis.org\">http://qgis.org</a> or email <a href=\"mailto:qgis at qgis.org\">qgis at qgis.org</a>" ) );
+ QVERIFY( found );
+ QCOMPARE( QgsStringUtils::insertLinks( QString( "is a at a an email?" ), &found ), QString( "is a at a an email?" ) );
+ QVERIFY( !found );
+}
+
QTEST_MAIN( TestQgsStringUtils )
#include "testqgsstringutils.moc"
diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt
index bd4ca14..c93f17b 100644
--- a/tests/src/python/CMakeLists.txt
+++ b/tests/src/python/CMakeLists.txt
@@ -17,6 +17,7 @@ ADD_PYTHON_TEST(PyQgsAttributeFormEditorWidget test_qgsattributeformeditorwidget
ADD_PYTHON_TEST(PyQgsAttributeTableConfig test_qgsattributetableconfig.py)
ADD_PYTHON_TEST(PyQgsAttributeTableModel test_qgsattributetablemodel.py)
#ADD_PYTHON_TEST(PyQgsAuthenticationSystem test_qgsauthsystem.py)
+ADD_PYTHON_TEST(PyQgsBearingUtils test_qgsbearingutils.py)
ADD_PYTHON_TEST(PyQgsBlendModes test_qgsblendmodes.py)
ADD_PYTHON_TEST(PyQgsCategorizedSymbolRendererV2 test_qgscategorizedsymbolrendererv2.py)
ADD_PYTHON_TEST(PyQgsColorButtonV2 test_qgscolorbuttonv2.py)
@@ -42,14 +43,17 @@ ADD_PYTHON_TEST(PyQgsDelimitedTextProvider test_qgsdelimitedtextprovider.py)
ADD_PYTHON_TEST(PyQgsDistanceArea test_qgsdistancearea.py)
ADD_PYTHON_TEST(PyQgsEditWidgets test_qgseditwidgets.py)
ADD_PYTHON_TEST(PyQgsExpression test_qgsexpression.py)
+ADD_PYTHON_TEST(PyQgsExpressionLineEdit test_qgsexpressionlineedit.py)
ADD_PYTHON_TEST(PyQgsFeature test_qgsfeature.py)
ADD_PYTHON_TEST(PyQgsProject test_qgsproject.py)
ADD_PYTHON_TEST(PyQgsFeatureIterator test_qgsfeatureiterator.py)
ADD_PYTHON_TEST(PyQgsField test_qgsfield.py)
+ADD_PYTHON_TEST(PyQgsFilterLineEdit test_qgsfilterlineedit.py)
ADD_PYTHON_TEST(PyQgsFontUtils test_qgsfontutils.py)
ADD_PYTHON_TEST(PyQgsGeometryAvoidIntersections test_qgsgeometry_avoid_intersections.py)
ADD_PYTHON_TEST(PyQgsGeometryGeneratorSymbolLayerV2 test_qgsgeometrygeneratorsymbollayerv2.py)
ADD_PYTHON_TEST(PyQgsGeometryTest test_qgsgeometry.py)
+ADD_PYTHON_TEST(PyQgsGeometryValidator test_qgsgeometryvalidator.py)
ADD_PYTHON_TEST(PyQgsGraduatedSymbolRendererV2 test_qgsgraduatedsymbolrendererv2.py)
ADD_PYTHON_TEST(PyQgsInterval test_qgsinterval.py)
ADD_PYTHON_TEST(PyQgsJSONUtils test_qgsjsonutils.py)
@@ -61,10 +65,12 @@ ADD_PYTHON_TEST(PyQgsNullSymbolRenderer test_qgsnullsymbolrenderer.py)
ADD_PYTHON_TEST(PyQgsNewGeoPackageLayerDialog test_qgsnewgeopackagelayerdialog.py)
ADD_PYTHON_TEST(PyQgsOGRProviderGpkg test_provider_ogr_gpkg.py)
ADD_PYTHON_TEST(PyQgsOGRProviderSqlite test_provider_ogr_sqlite.py)
+ADD_PYTHON_TEST(PyQgsOptional test_qgsoptional.py)
ADD_PYTHON_TEST(PyQgsPalLabelingBase test_qgspallabeling_base.py)
ADD_PYTHON_TEST(PyQgsPalLabelingCanvas test_qgspallabeling_canvas.py)
ADD_PYTHON_TEST(PyQgsPalLabelingComposer test_qgspallabeling_composer.py)
ADD_PYTHON_TEST(PyQgsPalLabelingPlacement test_qgspallabeling_placement.py)
+ADD_PYTHON_TEST(PyQgsPanelWidget test_qgspanelwidget.py)
ADD_PYTHON_TEST(PyQgsPoint test_qgspoint.py)
ADD_PYTHON_TEST(PyQgsRangeWidgets test_qgsrangewidgets.py)
ADD_PYTHON_TEST(PyQgsRasterFileWriter test_qgsrasterfilewriter.py)
@@ -78,6 +84,7 @@ ADD_PYTHON_TEST(PyQgsRulebasedRenderer test_qgsrulebasedrenderer.py)
ADD_PYTHON_TEST(PyQgsSingleSymbolRenderer test_qgssinglesymbolrenderer.py)
ADD_PYTHON_TEST(PyQgsShapefileProvider test_provider_shapefile.py)
ADD_PYTHON_TEST(PyQgsTabfileProvider test_provider_tabfile.py)
+ADD_PYTHON_TEST(PyQgsTabWidget test_qgstabwidget.py)
ADD_PYTHON_TEST(PyQgsOGRProvider test_provider_ogr.py)
ADD_PYTHON_TEST(PyQgsSearchWidgetToolButton test_qgssearchwidgettoolbutton.py)
ADD_PYTHON_TEST(PyQgsSearchWidgetWrapper test_qgssearchwidgetwrapper.py)
@@ -91,6 +98,7 @@ ADD_PYTHON_TEST(PyQgsSymbolLayerV2CreateSld test_qgssymbollayerv2_createsld.py)
ADD_PYTHON_TEST(PyQgsArrowSymbolLayer test_qgsarrowsymbollayer.py)
ADD_PYTHON_TEST(PyQgsSymbolExpressionVariables test_qgssymbolexpressionvariables.py)
ADD_PYTHON_TEST(PyQgsSyntacticSugar test_syntactic_sugar.py)
+ADD_PYTHON_TEST(PyQgsStringUtils test_qgsstringutils.py)
ADD_PYTHON_TEST(PyQgsSymbolV2 test_qgssymbolv2.py)
ADD_PYTHON_TEST(PyQgsUnitTypes test_qgsunittypes.py)
ADD_PYTHON_TEST(PyQgsVectorColorRamp test_qgsvectorcolorramp.py)
@@ -141,4 +149,5 @@ IF (WITH_SERVER)
ADD_PYTHON_TEST(PyQgsServerAccessControl test_qgsserver_accesscontrol.py)
ADD_PYTHON_TEST(PyQgsServerWFST test_qgsserver_wfst.py)
ADD_PYTHON_TEST(PyQgsOfflineEditingWFS test_offline_editing_wfs.py)
+ ADD_PYTHON_TEST(PyQgsAuthManagerEndpointTest test_authmanager_endpoint.py)
ENDIF (WITH_SERVER)
diff --git a/tests/src/python/offlineditingtestbase.py b/tests/src/python/offlineditingtestbase.py
index dc37d5a..bd60847 100644
--- a/tests/src/python/offlineditingtestbase.py
+++ b/tests/src/python/offlineditingtestbase.py
@@ -62,7 +62,7 @@ class OfflineTestBase(object):
def _tearDown(self):
"""Called by tearDown: run after each test."""
# Clear test layers
- self._clearLayer('test_point')
+ self._clearLayer(self._getLayer('test_point'))
@classmethod
def _compareFeature(cls, layer, attributes):
@@ -71,11 +71,10 @@ class OfflineTestBase(object):
return f['name'] == attributes[1] and f.geometry().asPoint().toString() == attributes[2].toString()
@classmethod
- def _clearLayer(cls, layer_name):
+ def _clearLayer(cls, layer):
"""
Delete all features from the backend layer
"""
- layer = cls._getLayer(layer_name)
layer.startEditing()
layer.deleteFeatures([f.id() for f in layer.getFeatures()])
layer.commitChanges()
diff --git a/tests/src/python/qgis_wrapped_server.py b/tests/src/python/qgis_wrapped_server.py
index 592de67..b270428 100644
--- a/tests/src/python/qgis_wrapped_server.py
+++ b/tests/src/python/qgis_wrapped_server.py
@@ -3,7 +3,15 @@
QGIS Server HTTP wrapper
This script launches a QGIS Server listening on port 8081 or on the port
-specified on the environment variable QGIS_SERVER_DEFAULT_PORT
+specified on the environment variable QGIS_SERVER_PORT.
+QGIS_SERVER_HOST (defaults to 127.0.0.1)
+
+For testing purposes, HTTP Basic can be enabled by setting the following
+environment variables:
+
+ * QGIS_SERVER_HTTP_BASIC_AUTH (default not set, set to anything to enable)
+ * QGIS_SERVER_USERNAME (default ="username")
+ * QGIS_SERVER_PASSWORD (default ="password")
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,24 +30,56 @@ __revision__ = '$Format:%H$'
import os
+import sys
import urllib.parse
from http.server import BaseHTTPRequestHandler, HTTPServer
-from qgis.server import QgsServer
+from qgis.server import QgsServer, QgsServerFilter
+
+QGIS_SERVER_PORT = int(os.environ.get('QGIS_SERVER_PORT', '8081'))
+QGIS_SERVER_HOST = os.environ.get('QGIS_SERVER_HOST', '127.0.0.1')
+
+qgs_server = QgsServer()
+
+if os.environ.get('QGIS_SERVER_HTTP_BASIC_AUTH') is not None:
+ import base64
+
+ class HTTPBasicFilter(QgsServerFilter):
+
+ def responseComplete(self):
+ request = self.serverInterface().requestHandler()
+ if self.serverInterface().getEnv('HTTP_AUTHORIZATION'):
+ username, password = base64.b64decode(self.serverInterface().getEnv('HTTP_AUTHORIZATION')[6:]).split(':')
+ if (username == os.environ.get('QGIS_SERVER_USERNAME', 'username')
+ and password == os.environ.get('QGIS_SERVER_PASSWORD', 'password')):
+ return
+ # No auth ...
+ request.clearHeaders()
+ request.setHeader('Status', '401 Authorization required')
+ request.setHeader('WWW-Authenticate', 'Basic realm="QGIS Server"')
+ request.clearBody()
+ request.appendBody('<h1>Authorization required</h1>')
-try:
- QGIS_SERVER_DEFAULT_PORT = int(os.environ['QGIS_SERVER_DEFAULT_PORT'])
-except KeyError:
- QGIS_SERVER_DEFAULT_PORT = 8081
+ filter = HTTPBasicFilter(qgs_server.serverInterface())
+ qgs_server.serverInterface().registerFilter(filter)
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
+ # CGI vars:
+ for k, v in self.headers.items():
+ qgs_server.putenv('HTTP_%s' % k.replace(' ', '-').replace('-', '_').replace(' ', '-').upper(), v)
+ qgs_server.putenv('SERVER_PORT', str(self.server.server_port))
+ qgs_server.putenv('SERVER_NAME', self.server.server_name)
+ qgs_server.putenv('REQUEST_URI', self.path)
parsed_path = urllib.parse.urlparse(self.path)
- s = QgsServer()
- headers, body = s.handleRequest(parsed_path.query)
- self.send_response(200)
- for k, v in [h.split(':') for h in headers.decode().split('\n') if h]:
+ headers, body = qgs_server.handleRequest(parsed_path.query)
+ headers_dict = dict(h.split(': ', 1) for h in headers.decode().split('\n') if h)
+ try:
+ self.send_response(int(headers_dict['Status'].split(' ')[0]))
+ except:
+ self.send_response(200)
+ for k, v in headers_dict.items():
self.send_header(k, v)
self.end_headers()
self.wfile.write(body)
@@ -55,7 +95,8 @@ class Handler(BaseHTTPRequestHandler):
if __name__ == '__main__':
- server = HTTPServer(('localhost', QGIS_SERVER_DEFAULT_PORT), Handler)
- print('Starting server on localhost:%s, use <Ctrl-C> to stop' %
- QGIS_SERVER_DEFAULT_PORT)
+ server = HTTPServer((QGIS_SERVER_HOST, QGIS_SERVER_PORT), Handler)
+ print('Starting server on %s:%s, use <Ctrl-C> to stop' %
+ (QGIS_SERVER_HOST, server.server_port))
+ sys.stdout.flush()
server.serve_forever()
diff --git a/tests/src/python/test_authmanager_endpoint.py b/tests/src/python/test_authmanager_endpoint.py
new file mode 100644
index 0000000..25a0a74
--- /dev/null
+++ b/tests/src/python/test_authmanager_endpoint.py
@@ -0,0 +1,182 @@
+# -*- coding: utf-8 -*-
+"""
+Tests for auth manager WMS/WFS using QGIS Server through HTTP Basic
+enabled qgis_wrapped_server.py.
+
+This is an integration test for QGIS Desktop Auth Manager WFS and WMS provider
+and QGIS Server WFS/WMS that check if QGIS can use a stored auth manager auth
+configuration to access an HTTP Basic protected endpoint.
+
+
+From build dir, run: ctest -R PyQgsAuthManagerEnpointTest -V
+
+.. note:: This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+"""
+import os
+import sys
+import re
+import subprocess
+import tempfile
+import random
+import string
+import urllib
+
+__author__ = 'Alessandro Pasotti'
+__date__ = '18/09/2016'
+__copyright__ = 'Copyright 2016, The QGIS Project'
+# This will get replaced with a git SHA1 when you do a git archive
+__revision__ = '$Format:%H$'
+
+from shutil import rmtree
+
+from utilities import unitTestDataPath, waitServer
+from qgis.core import (
+ QgsAuthManager,
+ QgsAuthMethodConfig,
+ QgsVectorLayer,
+ QgsRasterLayer,
+)
+from qgis.testing import (
+ start_app,
+ unittest,
+)
+
+try:
+ QGIS_SERVER_ENDPOINT_PORT = os.environ['QGIS_SERVER_ENDPOINT_PORT']
+except:
+ QGIS_SERVER_ENDPOINT_PORT = '0' # Auto
+
+
+QGIS_AUTH_DB_DIR_PATH = tempfile.mkdtemp()
+
+os.environ['QGIS_AUTH_DB_DIR_PATH'] = QGIS_AUTH_DB_DIR_PATH
+
+qgis_app = start_app()
+
+
+class TestAuthManager(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ """Run before all tests:
+ Creates an auth configuration"""
+ cls.port = QGIS_SERVER_ENDPOINT_PORT
+ # Clean env just to be sure
+ env_vars = ['QUERY_STRING', 'QGIS_PROJECT_FILE']
+ for ev in env_vars:
+ try:
+ del os.environ[ev]
+ except KeyError:
+ pass
+ cls.testdata_path = unitTestDataPath('qgis_server') + '/'
+ cls.project_path = cls.testdata_path + "test_project.qgs"
+ # Enable auth
+ #os.environ['QGIS_AUTH_PASSWORD_FILE'] = QGIS_AUTH_PASSWORD_FILE
+ authm = QgsAuthManager.instance()
+ assert (authm.setMasterPassword('masterpassword', True))
+ cls.auth_config = QgsAuthMethodConfig('Basic')
+ cls.auth_config.setName('test_auth_config')
+ cls.username = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
+ cls.password = cls.username[::-1] # reversed
+ cls.auth_config.setConfig('username', cls.username)
+ cls.auth_config.setConfig('password', cls.password)
+ assert (authm.storeAuthenticationConfig(cls.auth_config)[0])
+
+ os.environ['QGIS_SERVER_HTTP_BASIC_AUTH'] = '1'
+ os.environ['QGIS_SERVER_USERNAME'] = cls.username
+ os.environ['QGIS_SERVER_PASSWORD'] = cls.password
+ os.environ['QGIS_SERVER_PORT'] = str(cls.port)
+ server_path = os.path.dirname(os.path.realpath(__file__)) + \
+ '/qgis_wrapped_server.py'
+ cls.server = subprocess.Popen([sys.executable, server_path],
+ env=os.environ, stdout=subprocess.PIPE)
+
+ line = cls.server.stdout.readline()
+ cls.port = int(re.findall(b':(\d+)', line)[0])
+ assert cls.port != 0
+ # Wait for the server process to start
+ assert waitServer('http://127.0.0.1:%s' % cls.port), "Server is not responding! http://127.0.0.1:%s" % cls.port
+
+ @classmethod
+ def tearDownClass(cls):
+ """Run after all tests"""
+ cls.server.terminate()
+ rmtree(QGIS_AUTH_DB_DIR_PATH)
+ del cls.server
+
+ def setUp(self):
+ """Run before each test."""
+ pass
+
+ def tearDown(self):
+ """Run after each test."""
+ pass
+
+ @classmethod
+ def _getWFSLayer(cls, type_name, layer_name=None, authcfg=None):
+ """
+ WFS layer factory
+ """
+ if layer_name is None:
+ layer_name = 'wfs_' + type_name
+ parms = {
+ 'srsname': 'EPSG:4326',
+ 'typename': type_name,
+ 'url': 'http://127.0.0.1:%s/?map=%s' % (cls.port, cls.project_path),
+ 'version': 'auto',
+ 'table': '',
+ }
+ if authcfg is not None:
+ parms.update({'authcfg': authcfg})
+ uri = ' '.join([("%s='%s'" % (k, v.decode('utf-8'))) for k, v in list(parms.items())])
+ wfs_layer = QgsVectorLayer(uri, layer_name, 'WFS')
+ return wfs_layer
+
+ @classmethod
+ def _getWMSLayer(cls, layers, layer_name=None, authcfg=None):
+ """
+ WMS layer factory
+ """
+ if layer_name is None:
+ layer_name = 'wms_' + layers.replace(',', '')
+ parms = {
+ 'crs': 'EPSG:4326',
+ 'url': 'http://127.0.0.1:%s/?map=%s' % (cls.port, cls.project_path),
+ 'format': 'image/png',
+ # This is needed because of a really weird implementation in QGIS Server, that
+ # replaces _ in the the real layer name with spaces
+ 'layers': urllib.quote(layers.replace('_', ' ')),
+ 'styles': '',
+ 'version': 'auto',
+ #'sql': '',
+ }
+ if authcfg is not None:
+ parms.update({'authcfg': authcfg})
+ uri = '&'.join([("%s=%s" % (k, v.replace('=', '%3D'))) for k, v in list(parms.items())])
+ wms_layer = QgsRasterLayer(uri, layer_name, 'wms')
+ return wms_layer
+
+ def testValidAuthAccess(self):
+ """
+ Access the HTTP Basic protected layer with valid credentials
+ """
+ wfs_layer = self._getWFSLayer('testlayer_èé', authcfg=self.auth_config.id())
+ self.assertTrue(wfs_layer.isValid())
+ wms_layer = self._getWMSLayer('testlayer_èé', authcfg=self.auth_config.id())
+ self.assertTrue(wms_layer.isValid())
+
+ def testInvalidAuthAccess(self):
+ """
+ Access the HTTP Basic protected layer with no credentials
+ """
+ wfs_layer = self._getWFSLayer('testlayer èé')
+ self.assertFalse(wfs_layer.isValid())
+ wms_layer = self._getWMSLayer('testlayer_èé')
+ self.assertFalse(wms_layer.isValid())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/src/python/test_offline_editing_wfs.py b/tests/src/python/test_offline_editing_wfs.py
index bd73ddc..1f3ae15 100644
--- a/tests/src/python/test_offline_editing_wfs.py
+++ b/tests/src/python/test_offline_editing_wfs.py
@@ -1,20 +1,14 @@
# -*- coding: utf-8 -*-
"""
Offline editing Tests.
-
WFS-T tests need using QGIS Server through
qgis_wrapped_server.py.
-
This is an integration test for QGIS Desktop WFS-T provider and QGIS Server
WFS-T that check if QGIS offline editing works with a WFS-T endpoint.
-
The test uses testdata/wfs_transactional/wfs_transactional.qgs and three
initially empty shapefiles layers with points, lines and polygons.
-
The point layer is used in the test
-
From build dir, run: ctest -R PyQgsOfflineEditingWFS -V
-
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -31,15 +25,13 @@ __revision__ = '$Format:%H$'
import os
import sys
+import re
import subprocess
from shutil import copytree, rmtree
import tempfile
from time import sleep
-from utilities import unitTestDataPath
-from qgis.core import (
- QgsVectorLayer,
- QgsProject,
-)
+from utilities import unitTestDataPath, waitServer
+from qgis.core import QgsVectorLayer
from qgis.testing import (
start_app,
@@ -48,23 +40,24 @@ from qgis.testing import (
from offlineditingtestbase import OfflineTestBase
-from qgis.PyQt.QtCore import QFileInfo
try:
- QGIS_SERVER_WFST_DEFAULT_PORT = os.environ['QGIS_SERVER_WFST_DEFAULT_PORT']
+ QGIS_SERVER_OFFLINE_PORT = os.environ['QGIS_SERVER_OFFLINE_PORT']
except:
- QGIS_SERVER_WFST_DEFAULT_PORT = 8081
-
+ QGIS_SERVER_OFFLINE_PORT = '0' # Auto
qgis_app = start_app()
class TestWFST(unittest.TestCase, OfflineTestBase):
+ # To fake the WFS cache!
+ counter = 0
+
@classmethod
def setUpClass(cls):
"""Run before all tests"""
- cls.port = QGIS_SERVER_WFST_DEFAULT_PORT
+ cls.port = QGIS_SERVER_OFFLINE_PORT
# Create tmp folder
cls.temp_path = tempfile.mkdtemp()
cls.testdata_path = cls.temp_path + '/' + 'wfs_transactional' + '/'
@@ -82,48 +75,57 @@ class TestWFST(unittest.TestCase, OfflineTestBase):
except KeyError:
pass
# Clear all test layers
- cls._clearLayer('test_point')
- os.environ['QGIS_SERVER_DEFAULT_PORT'] = str(cls.port)
- server_path = os.path.dirname(os.path.realpath(__file__)) + \
+ cls._clearLayer(cls._getLayer('test_point'))
+ os.environ['QGIS_SERVER_PORT'] = str(cls.port)
+ cls.server_path = os.path.dirname(os.path.realpath(__file__)) + \
'/qgis_wrapped_server.py'
- cls.server = subprocess.Popen([sys.executable, server_path],
- env=os.environ)
- sleep(2)
@classmethod
def tearDownClass(cls):
"""Run after all tests"""
- cls.server.terminate()
- del cls.server
- # Clear test layer
- cls._clearLayer('test_point')
rmtree(cls.temp_path)
def setUp(self):
"""Run before each test."""
+ self.server = subprocess.Popen([sys.executable, self.server_path],
+ env=os.environ, stdout=subprocess.PIPE)
+ line = self.server.stdout.readline()
+ self.port = int(re.findall(b':(\d+)', line)[0])
+ assert self.port != 0
+ # Wait for the server process to start
+ assert waitServer('http://127.0.0.1:%s' % self.port), "Server is not responding!"
self._setUp()
def tearDown(self):
"""Run after each test."""
+ # Clear test layer
+ self._clearLayer(self._getOnlineLayer('test_point'))
+ # Kill the server
+ self.server.terminate()
+ self.server.wait()
+ del self.server
+ # Delete the sqlite db
+ os.unlink(os.path.join(self.temp_path, 'offlineDbFile.sqlite'))
self._tearDown()
- @classmethod
- def _getOnlineLayer(cls, type_name, layer_name=None):
+ def _getOnlineLayer(self, type_name, layer_name=None):
"""
- Layer factory (return the online layer), provider specific
+ Return a new WFS layer, overriding the WFS cache
"""
if layer_name is None:
layer_name = 'wfs_' + type_name
parms = {
'srsname': 'EPSG:4326',
'typename': type_name,
- 'url': 'http://127.0.0.1:%s/?map=%s' % (cls.port,
- cls.project_path),
+ 'url': 'http://127.0.0.1:%s/%s/?map=%s' % (self.port,
+ self.counter,
+ self.project_path),
'version': 'auto',
'table': '',
#'sql': '',
}
- uri = ' '.join([("%s='%s'" % (k, v)) for k, v in parms.items()])
+ self.counter += 1
+ uri = ' '.join([("%s='%s'" % (k, v)) for k, v in list(parms.items())])
wfs_layer = QgsVectorLayer(uri, layer_name, 'WFS')
assert wfs_layer.isValid()
return wfs_layer
diff --git a/tests/src/python/test_provider_ogr.py b/tests/src/python/test_provider_ogr.py
index a60f41d..485b3b4 100644
--- a/tests/src/python/test_provider_ogr.py
+++ b/tests/src/python/test_provider_ogr.py
@@ -221,5 +221,24 @@ class PyQgsOGRProvider(unittest.TestCase):
os.unlink(datasource)
self.assertFalse(os.path.exists(datasource))
+ def testGeometryCollection(self):
+ ''' Test that we can at least retrieves attribute of features with geometry collection '''
+
+ datasource = os.path.join(self.basetestpath, 'testGeometryCollection.csv')
+ with open(datasource, 'wt') as f:
+ f.write('id,WKT\n')
+ f.write('1,POINT Z(2 49 0)\n')
+ f.write('2,GEOMETRYCOLLECTION Z (POINT Z (2 49 0))\n')
+
+ vl = QgsVectorLayer('{}|layerid=0|geometrytype=GeometryCollection'.format(datasource), 'test', 'ogr')
+ self.assertTrue(vl.isValid())
+ self.assertTrue(vl.featureCount(), 1)
+ values = [f['id'] for f in vl.getFeatures()]
+ self.assertEqual(values, ['2'])
+ del vl
+
+ os.unlink(datasource)
+ self.assertFalse(os.path.exists(datasource))
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/src/python/test_provider_ogr_gpkg.py b/tests/src/python/test_provider_ogr_gpkg.py
index 94e1155..3024ab5 100644
--- a/tests/src/python/test_provider_ogr_gpkg.py
+++ b/tests/src/python/test_provider_ogr_gpkg.py
@@ -20,7 +20,7 @@ import shutil
import glob
from osgeo import gdal, ogr
-from qgis.core import QgsVectorLayer, QgsFeature, QgsGeometry, QgsFeatureRequest
+from qgis.core import QgsVectorLayer, QgsFeature, QgsGeometry, QgsFeatureRequest, QgsRectangle
from qgis.testing import start_app, unittest
from utilities import unitTestDataPath
@@ -156,5 +156,49 @@ class TestPyQgsOGRProviderGpkg(unittest.TestCase):
def testBug15351_commit_closeIter_closeProvider(self):
self.internalTestBug15351('commit_closeIter_closeProvider')
+ def testGeopackageExtentUpdate(self):
+ ''' test http://hub.qgis.org/issues/15273 '''
+ tmpfile = os.path.join(self.basetestpath, 'testGeopackageExtentUpdate.gpkg')
+ ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
+ lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint)
+ f = ogr.Feature(lyr.GetLayerDefn())
+ f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 0)'))
+ lyr.CreateFeature(f)
+ f = ogr.Feature(lyr.GetLayerDefn())
+ f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(1 1)'))
+ lyr.CreateFeature(f)
+ f = None
+ f = ogr.Feature(lyr.GetLayerDefn())
+ f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(1 0.5)'))
+ lyr.CreateFeature(f)
+ f = None
+ gdal.ErrorReset()
+ ds.ExecuteSQL('RECOMPUTE EXTENT ON test')
+ has_error = gdal.GetLastErrorMsg() != ''
+ ds = None
+ if has_error:
+ print('Too old GDAL trunk version. Please update')
+ return
+
+ vl = QgsVectorLayer(u'{}'.format(tmpfile), u'test', u'ogr')
+
+ # Test moving a geometry that touches the bbox
+ self.assertTrue(vl.startEditing())
+ self.assertTrue(vl.changeGeometry(1, QgsGeometry.fromWkt('Point (0.5 0)')))
+ self.assertTrue(vl.commitChanges())
+ reference = QgsGeometry.fromRect(QgsRectangle(0.5, 0.0, 1.0, 1.0))
+ provider_extent = QgsGeometry.fromRect(vl.extent())
+ self.assertTrue(QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001),
+ provider_extent.asPolygon()[0])
+
+ # Test deleting a geometry that touches the bbox
+ self.assertTrue(vl.startEditing())
+ self.assertTrue(vl.deleteFeature(2))
+ self.assertTrue(vl.commitChanges())
+ reference = QgsGeometry.fromRect(QgsRectangle(0.5, 0.0, 1.0, 0.5))
+ provider_extent = QgsGeometry.fromRect(vl.extent())
+ self.assertTrue(QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001),
+ provider_extent.asPolygon()[0])
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/src/python/test_provider_postgres.py b/tests/src/python/test_provider_postgres.py
index 3c5571d..d6fdb1e 100644
--- a/tests/src/python/test_provider_postgres.py
+++ b/tests/src/python/test_provider_postgres.py
@@ -14,11 +14,15 @@ __copyright__ = 'Copyright 2015, The QGIS Project'
__revision__ = '$Format:%H$'
import qgis # NOQA
+import psycopg2
import os
from qgis.core import (
+ QgsGeometry,
+ QgsPoint,
QgsVectorLayer,
+ QgsVectorLayerImport,
QgsFeatureRequest,
QgsFeature,
QgsTransactionGroup,
@@ -48,11 +52,20 @@ class TestPyQgsPostgresProvider(unittest.TestCase, ProviderTestCase):
cls.poly_vl = QgsVectorLayer(cls.dbconn + ' sslmode=disable key=\'pk\' srid=4326 type=POLYGON table="qgis_test"."some_poly_data" (geom) sql=', 'test', 'postgres')
assert cls.poly_vl.isValid()
cls.poly_provider = cls.poly_vl.dataProvider()
+ cls.con = psycopg2.connect(cls.dbconn)
@classmethod
def tearDownClass(cls):
"""Run after all tests"""
+ def execSQLCommand(self, sql):
+ self.assertTrue(self.con)
+ cur = self.con.cursor()
+ self.assertTrue(cur)
+ cur.execute(sql)
+ cur.close()
+ self.con.commit()
+
def enableCompiler(self):
QSettings().setValue(u'/qgis/compileExpressions', True)
@@ -312,5 +325,72 @@ class TestPyQgsPostgresProvider(unittest.TestCase, ProviderTestCase):
self.assertEqual(fet.fields()[1].name(), 'newname2')
self.assertEqual(fet.fields()[2].name(), 'another')
+ # See http://hub.qgis.org/issues/15188
+ def testNumericPrecision(self):
+ uri = 'point?field=f1:int'
+ uri += '&field=f2:double(6,4)'
+ uri += '&field=f3:string(20)'
+ lyr = QgsVectorLayer(uri, "x", "memory")
+ self.assertTrue(lyr.isValid())
+ f = QgsFeature(lyr.fields())
+ f['f1'] = 1
+ f['f2'] = 123.456
+ f['f3'] = '12345678.90123456789'
+ lyr.dataProvider().addFeatures([f])
+ uri = '%s table="qgis_test"."b18155" (g) key=\'f1\'' % (self.dbconn)
+ self.execSQLCommand('DROP TABLE IF EXISTS qgis_test.b18155')
+ err = QgsVectorLayerImport.importLayer(lyr, uri, "postgres", lyr.crs())
+ self.assertEqual(err[0], QgsVectorLayerImport.NoError,
+ 'unexpected import error {0}'.format(err))
+ lyr = QgsVectorLayer(uri, "y", "postgres")
+ self.assertTrue(lyr.isValid())
+ f = next(lyr.getFeatures())
+ self.assertEqual(f['f1'], 1)
+ self.assertEqual(f['f2'], 123.456)
+ self.assertEqual(f['f3'], '12345678.90123456789')
+
+ # See http://hub.qgis.org/issues/15226
+ def testImportKey(self):
+ uri = 'point?field=f1:int'
+ uri += '&field=F2:double(6,4)'
+ uri += '&field=f3:string(20)'
+ lyr = QgsVectorLayer(uri, "x", "memory")
+ self.assertTrue(lyr.isValid())
+
+ def testKey(lyr, key, kfnames):
+ self.execSQLCommand('DROP TABLE IF EXISTS qgis_test.import_test')
+ uri = '%s table="qgis_test"."import_test" (g)' % self.dbconn
+ if key is not None:
+ uri += ' key=\'%s\'' % key
+ err = QgsVectorLayerImport.importLayer(lyr, uri, "postgres", lyr.crs())
+ self.assertEqual(err[0], QgsVectorLayerImport.NoError,
+ 'unexpected import error {0}'.format(err))
+ olyr = QgsVectorLayer(uri, "y", "postgres")
+ self.assertTrue(olyr.isValid())
+ flds = lyr.fields()
+ oflds = olyr.fields()
+ if key is None:
+ # if the pkey was not given, it will create a pkey
+ self.assertEquals(oflds.size(), flds.size() + 1)
+ self.assertEquals(oflds[0].name(), kfnames[0])
+ for i in range(flds.size()):
+ self.assertEqual(oflds[i + 1].name(), flds[i].name())
+ else:
+ # pkey was given, no extra field generated
+ self.assertEquals(oflds.size(), flds.size())
+ for i in range(oflds.size()):
+ self.assertEqual(oflds[i].name(), flds[i].name())
+ pks = olyr.pkAttributeList()
+ self.assertEquals(len(pks), len(kfnames))
+ for i in range(0, len(kfnames)):
+ self.assertEqual(oflds[pks[i]].name(), kfnames[i])
+
+ testKey(lyr, 'f1', ['f1'])
+ testKey(lyr, '"f1"', ['f1'])
+ testKey(lyr, '"f1","F2"', ['f1', 'F2'])
+ testKey(lyr, '"f1","F2","f3"', ['f1', 'F2', 'f3'])
+ testKey(lyr, None, ['id'])
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/src/python/test_provider_shapefile.py b/tests/src/python/test_provider_shapefile.py
index 0029904..bcb5772 100644
--- a/tests/src/python/test_provider_shapefile.py
+++ b/tests/src/python/test_provider_shapefile.py
@@ -30,6 +30,19 @@ start_app()
TEST_DATA_DIR = unitTestDataPath()
+def GDAL_COMPUTE_VERSION(maj, min, rev):
+ return ((maj) * 1000000 + (min) * 10000 + (rev) * 100)
+
+
+class ErrorReceiver():
+
+ def __init__(self):
+ self.msg = None
+
+ def receiveError(self, msg):
+ self.msg = msg
+
+
class TestPyQgsShapefileProvider(unittest.TestCase, ProviderTestCase):
@classmethod
@@ -380,5 +393,93 @@ class TestPyQgsShapefileProvider(unittest.TestCase, ProviderTestCase):
vl = None
+ def testRepackUnderFileLocks(self):
+ ''' Test fix for #15570 and #15393 '''
+
+ # This requires a GDAL fix done per https://trac.osgeo.org/gdal/ticket/6672
+ # but on non-Windows version the test would succeed
+ if int(osgeo.gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(2, 1, 2):
+ return
+
+ tmpdir = tempfile.mkdtemp()
+ self.dirs_to_cleanup.append(tmpdir)
+ srcpath = os.path.join(TEST_DATA_DIR, 'provider')
+ for file in glob.glob(os.path.join(srcpath, 'shapefile.*')):
+ shutil.copy(os.path.join(srcpath, file), tmpdir)
+ datasource = os.path.join(tmpdir, 'shapefile.shp')
+
+ vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
+ feature_count = vl.featureCount()
+
+ # Keep a file descriptor opened on the .dbf, .shp and .shx
+ f_shp = open(os.path.join(tmpdir, 'shapefile.shp'), 'rb')
+ f_shx = open(os.path.join(tmpdir, 'shapefile.shx'), 'rb')
+ f_dbf = open(os.path.join(tmpdir, 'shapefile.dbf'), 'rb')
+
+ # Delete a feature
+ self.assertTrue(vl.startEditing())
+ self.assertTrue(vl.deleteFeature(1))
+
+ # Commit changes and check no error is emitted
+ cbk = ErrorReceiver()
+ vl.dataProvider().raiseError.connect(cbk.receiveError)
+ self.assertTrue(vl.commitChanges())
+ self.assertIsNone(cbk.msg)
+
+ vl = None
+
+ del f_shp
+ del f_shx
+ del f_dbf
+
+ # Test repacking has been done
+ ds = osgeo.ogr.Open(datasource)
+ self.assertTrue(ds.GetLayer(0).GetFeatureCount(), feature_count - 1)
+ ds = None
+
+ def testRepackAtFirstSave(self):
+ ''' Test fix for #15407 '''
+
+ # This requires a GDAL fix done per https://trac.osgeo.org/gdal/ticket/6672
+ # but on non-Windows version the test would succeed
+ if int(osgeo.gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(2, 1, 2):
+ return
+
+ tmpdir = tempfile.mkdtemp()
+ self.dirs_to_cleanup.append(tmpdir)
+ srcpath = os.path.join(TEST_DATA_DIR, 'provider')
+ for file in glob.glob(os.path.join(srcpath, 'shapefile.*')):
+ shutil.copy(os.path.join(srcpath, file), tmpdir)
+ datasource = os.path.join(tmpdir, 'shapefile.shp')
+
+ ds = osgeo.ogr.Open(datasource)
+ lyr = ds.GetLayer(0)
+ original_feature_count = lyr.GetFeatureCount()
+ lyr.DeleteFeature(2)
+ ds = None
+
+ vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
+
+ self.assertTrue(vl.featureCount(), original_feature_count)
+
+ # Edit a feature (attribute change only)
+ self.assertTrue(vl.startEditing())
+ self.assertTrue(vl.dataProvider().changeAttributeValues({0: {0: 100}}))
+
+ # Commit changes and check no error is emitted
+ cbk = ErrorReceiver()
+ vl.dataProvider().raiseError.connect(cbk.receiveError)
+ self.assertTrue(vl.commitChanges())
+ self.assertIsNone(cbk.msg)
+
+ self.assertTrue(vl.featureCount(), original_feature_count - 1)
+
+ vl = None
+
+ # Test repacking has been done
+ ds = osgeo.ogr.Open(datasource)
+ self.assertTrue(ds.GetLayer(0).GetFeatureCount(), original_feature_count - 1)
+ ds = None
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/src/python/test_provider_wfs.py b/tests/src/python/test_provider_wfs.py
index 07da9ad..1f8c72f 100644
--- a/tests/src/python/test_provider_wfs.py
+++ b/tests/src/python/test_provider_wfs.py
@@ -111,7 +111,8 @@ class TestPyQgsWFSProvider(unittest.TestCase, ProviderTestCase):
<xsd:complexContent>
<xsd:extension base="gml:AbstractFeatureType">
<xsd:sequence>
- <xsd:element maxOccurs="1" minOccurs="0" name="pk" nillable="true" type="xsd:long"/>
+ <!-- add a trailing space to the name to test http://hub.qgis.org/issues/3426 -->
+ <xsd:element maxOccurs="1" minOccurs="0" name="pk " nillable="true" type="xsd:long"/>
<xsd:element maxOccurs="1" minOccurs="0" name="cnt" nillable="true" type="xsd:long"/>
<xsd:element maxOccurs="1" minOccurs="0" name="name" nillable="true" type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="0" name="name2" nillable="true" type="xsd:string"/>
@@ -462,6 +463,31 @@ class TestPyQgsWFSProvider(unittest.TestCase, ProviderTestCase):
assert not vl.dataProvider().deleteFeatures([0])
+ # Test with restrictToRequestBBOX=1
+ with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:32631&BBOX=400000,5400000,450000,5500000'), 'wb') as f:
+ f.write("""
+<wfs:FeatureCollection
+ xmlns:wfs="http://www.opengis.net/wfs"
+ xmlns:gml="http://www.opengis.net/gml"
+ xmlns:my="http://my">
+ <gml:boundedBy><gml:null>unknown</gml:null></gml:boundedBy>
+ <gml:featureMember>
+ <my:typename fid="typename.0">
+ <my:geometry>
+ <gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"><gml:coordinates decimal="." cs="," ts=" ">426858,5427937</gml:coordinates></gml:Point>
+ </my:geometry>
+ <my:INTFIELD>100</my:INTFIELD>
+ </my:typename>
+ </gml:featureMember>
+</wfs:FeatureCollection>""".encode('UTF-8'))
+
+ vl = QgsVectorLayer("url='http://" + endpoint + "' typename='my:typename' version='1.0.0' restrictToRequestBBOX=1", 'test', 'WFS')
+
+ extent = QgsRectangle(400000.0, 5400000.0, 450000.0, 5500000.0)
+ request = QgsFeatureRequest().setFilterRect(extent)
+ values = [f['INTFIELD'] for f in vl.getFeatures(request)]
+ self.assertEqual(values, [100])
+
def testWFS10_latlongboundingbox_in_WGS84(self):
"""Test WFS 1.0 with non conformatn LatLongBoundingBox"""
@@ -892,7 +918,7 @@ class TestPyQgsWFSProvider(unittest.TestCase, ProviderTestCase):
""".encode('UTF-8'))
# Create test layer
- vl = QgsVectorLayer(u"url='http://" + endpoint + u"' typename='my:typename' retrictToRequestBBOX=1", u'test', u'WFS')
+ vl = QgsVectorLayer(u"url='http://" + endpoint + u"' typename='my:typename' restrictToRequestBBOX=1", u'test', u'WFS')
assert vl.isValid()
self.assertEqual(vl.wkbType(), QgsWKBTypes.Point)
@@ -1872,8 +1898,8 @@ class TestPyQgsWFSProvider(unittest.TestCase, ProviderTestCase):
vl_extent = QgsGeometry.fromRect(vl.extent())
assert QgsGeometry.compare(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt())
- # Same with retrictToRequestBBOX=1
- vl = QgsVectorLayer(u"url='http://" + endpoint + u"' typename='my:typename' version='2.0.0' retrictToRequestBBOX=1", u'test', u'WFS')
+ # Same with restrictToRequestBBOX=1
+ vl = QgsVectorLayer(u"url='http://" + endpoint + u"' typename='my:typename' version='2.0.0' restrictToRequestBBOX=1", u'test', u'WFS')
assert vl.isValid()
# First request that will be attempted
diff --git a/tests/src/python/test_provider_wfs_gui.py b/tests/src/python/test_provider_wfs_gui.py
index 12b8907..e25ab5a 100644
--- a/tests/src/python/test_provider_wfs_gui.py
+++ b/tests/src/python/test_provider_wfs_gui.py
@@ -225,7 +225,7 @@ class TestPyQgsWFSProviderGUI(unittest.TestCase):
self.addWfsLayer_layer_name = None
main_dialog.addWfsLayer.connect(self.slotAddWfsLayer)
QTest.mouseClick(buttonAdd, Qt.LeftButton)
- self.assertEqual(self.addWfsLayer_uri, ' retrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=')
+ self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=')
self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
# Click on Build Query
@@ -298,7 +298,7 @@ class TestPyQgsWFSProviderGUI(unittest.TestCase):
self.addWfsLayer_layer_name = None
main_dialog.addWfsLayer.connect(self.slotAddWfsLayer)
QTest.mouseClick(buttonAdd, Qt.LeftButton)
- self.assertEqual(self.addWfsLayer_uri, ' retrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=SELECT * FROM typename WHERE 1 = 1')
+ self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=SELECT * FROM typename WHERE 1 = 1')
self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
#main_dialog.setProperty("hideDialogs", None)
diff --git a/tests/src/python/test_qgsbearingutils.py b/tests/src/python/test_qgsbearingutils.py
new file mode 100644
index 0000000..da3ed99
--- /dev/null
+++ b/tests/src/python/test_qgsbearingutils.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+"""QGIS Unit tests for QgsBearingUtils.
+
+.. note:: This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+"""
+__author__ = 'Nyall Dawson'
+__date__ = '18/10/2016'
+__copyright__ = 'Copyright 2016, The QGIS Project'
+# This will get replaced with a git SHA1 when you do a git archive
+__revision__ = '$Format:%H$'
+
+import qgis # switch sip api
+
+from qgis.core import (QgsBearingUtils,
+ QgsCoordinateReferenceSystem,
+ QgsPoint
+ )
+
+from qgis.testing import (start_app,
+ unittest
+ )
+
+
+start_app()
+
+
+class TestQgsBearingUtils(unittest.TestCase):
+
+ def testTrueNorth(self):
+ """ test calculating bearing to true north"""
+
+ # short circuit - already a geographic crs
+ crs = QgsCoordinateReferenceSystem()
+ crs.createFromOgcWmsCrs('EPSG:4326')
+ self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(0, 0)), 0)
+ self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(44, 0)), 0)
+ self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(44, -43)), 0)
+ self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(44, 43)), 0)
+
+ self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(44, 200)), 0)
+ self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(44, -200)), 0)
+
+ # no short circuit
+ crs.createFromOgcWmsCrs('EPSG:3111')
+ self.assertAlmostEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(2508807, 2423425)), 0.06, 2)
+
+ # try a south-up crs
+ crs.createFromOgcWmsCrs('EPSG:2053')
+ self.assertAlmostEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(29, -27.55)), -180.0, 1)
+
+ # try a north pole crs
+ crs.createFromOgcWmsCrs('EPSG:3575')
+ self.assertAlmostEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(-780770, 652329)), 129.9, 1)
+ self.assertAlmostEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(513480, 873173)), -149.5, 1)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/src/python/test_qgscolorscheme.py b/tests/src/python/test_qgscolorscheme.py
index f268be8..a3e31c9 100644
--- a/tests/src/python/test_qgscolorscheme.py
+++ b/tests/src/python/test_qgscolorscheme.py
@@ -14,8 +14,9 @@ __revision__ = '$Format:%H$'
import qgis # NOQA
-from qgis.testing import unittest
-from qgis.core import QgsColorScheme
+from qgis.testing import unittest, start_app
+from qgis.core import QgsColorScheme, QgsUserColorScheme
+from qgis.PyQt.QtCore import QCoreApplication, QSettings
from qgis.PyQt.QtGui import QColor
# Make a dummy color scheme for testing
@@ -43,6 +44,15 @@ class DummyColorScheme(QgsColorScheme):
class TestQgsColorScheme(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ """Run before all tests"""
+ QCoreApplication.setOrganizationName("QGIS_Test")
+ QCoreApplication.setOrganizationDomain("QGIS_TestPyQgsColorScheme.com")
+ QCoreApplication.setApplicationName("QGIS_TestPyQgsColorScheme")
+ QSettings().clear()
+ start_app()
+
def testCreateScheme(self):
"""Test creating a new color scheme"""
dummyScheme = DummyColorScheme()
@@ -88,6 +98,21 @@ class TestQgsColorScheme(unittest.TestCase):
colorsClone = dummySchemeClone.fetchColors()
self.assertEqual(colors, colorsClone)
+ def testUserScheme(self):
+ """ Tests for user color schemes """
+
+ scheme = QgsUserColorScheme("user_test.gpl")
+ self.assertEqual(scheme.schemeName(), 'user_test.gpl')
+ self.assertTrue(scheme.isEditable())
+
+ self.assertFalse(scheme.flags() & QgsColorScheme.ShowInColorButtonMenu)
+ scheme.setShowSchemeInMenu(True)
+ self.assertTrue(scheme.flags() & QgsColorScheme.ShowInColorButtonMenu)
+ scheme.setShowSchemeInMenu(False)
+ self.assertFalse(scheme.flags() & QgsColorScheme.ShowInColorButtonMenu)
+
+ scheme.erase()
+
if __name__ == "__main__":
unittest.main()
diff --git a/tests/src/python/test_qgscomposerpicture.py b/tests/src/python/test_qgscomposerpicture.py
index e64d3d0..ce376b0 100644
--- a/tests/src/python/test_qgscomposerpicture.py
+++ b/tests/src/python/test_qgscomposerpicture.py
@@ -22,7 +22,10 @@ from qgis.PyQt.QtCore import QRectF
from qgis.core import (QgsComposerPicture,
QgsComposition,
- QgsMapSettings
+ QgsMapSettings,
+ QgsComposerMap,
+ QgsRectangle,
+ QgsCoordinateReferenceSystem
)
from qgis.testing import start_app, unittest
from utilities import unitTestDataPath
@@ -86,5 +89,63 @@ class TestQgsComposerPicture(unittest.TestCase):
self.composerPicture.setPicturePath(self.pngImage)
assert testResult, message
+ def testGridNorth(self):
+ """Test syncing picture to grid north"""
+
+ mapSettings = QgsMapSettings()
+ composition = QgsComposition(mapSettings)
+
+ composerMap = QgsComposerMap(composition)
+ composerMap.setNewExtent(QgsRectangle(0, -256, 256, 0))
+ composition.addComposerMap(composerMap)
+
+ composerPicture = QgsComposerPicture(composition)
+ composition.addComposerPicture(composerPicture)
+
+ composerPicture.setRotationMap(composerMap.id())
+ self.assertTrue(composerPicture.rotationMap() >= 0)
+
+ composerPicture.setNorthMode(QgsComposerPicture.GridNorth)
+ composerMap.setMapRotation(45)
+ self.assertEqual(composerPicture.pictureRotation(), 45)
+
+ # add an offset
+ composerPicture.setNorthOffset(-10)
+ self.assertEqual(composerPicture.pictureRotation(), 35)
+
+ def testTrueNorth(self):
+ """Test syncing picture to true north"""
+
+ mapSettings = QgsMapSettings()
+ crs = QgsCoordinateReferenceSystem()
+ crs.createFromOgcWmsCrs('EPSG:3575')
+ mapSettings.setDestinationCrs(crs)
+ composition = QgsComposition(mapSettings)
+
+ composerMap = QgsComposerMap(composition)
+ composerMap.setNewExtent(QgsRectangle(-2126029.962, -2200807.749, -119078.102, -757031.156))
+ composition.addComposerMap(composerMap)
+
+ composerPicture = QgsComposerPicture(composition)
+ composition.addComposerPicture(composerPicture)
+
+ composerPicture.setRotationMap(composerMap.id())
+ self.assertTrue(composerPicture.rotationMap() >= 0)
+
+ composerPicture.setNorthMode(QgsComposerPicture.TrueNorth)
+ self.assertAlmostEqual(composerPicture.pictureRotation(), 37.20, 1)
+
+ # shift map
+ composerMap.setNewExtent(QgsRectangle(2120672.293, -3056394.691, 2481640.226, -2796718.780))
+ self.assertAlmostEqual(composerPicture.pictureRotation(), -38.18, 1)
+
+ # rotate map
+ composerMap.setMapRotation(45)
+ self.assertAlmostEqual(composerPicture.pictureRotation(), -38.18 + 45, 1)
+
+ # add an offset
+ composerPicture.setNorthOffset(-10)
+ self.assertAlmostEqual(composerPicture.pictureRotation(), -38.18 + 35, 1)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/src/python/test_qgseditwidgets.py b/tests/src/python/test_qgseditwidgets.py
index da0d3a7..da51948 100644
--- a/tests/src/python/test_qgseditwidgets.py
+++ b/tests/src/python/test_qgseditwidgets.py
@@ -14,10 +14,13 @@ __revision__ = '$Format:%H$'
import qgis # NOQA
-from qgis.core import QgsMapLayerRegistry, QgsFeature, QgsGeometry, QgsPoint, QgsProject, QgsRelation, QgsVectorLayer, NULL
+from qgis.core import (QgsMapLayerRegistry, QgsFeature, QgsGeometry, QgsPoint, QgsProject, QgsRelation, QgsVectorLayer, NULL,
+ QgsField)
from qgis.gui import QgsEditorWidgetRegistry
from qgis.testing import start_app, unittest
+from qgis.PyQt.QtCore import QVariant
+from qgis.PyQt.QtWidgets import QTextEdit
start_app()
@@ -63,6 +66,33 @@ class TestQgsTextEditWidget(unittest.TestCase):
self.doAttributeTest(0, ['value', '123', NULL, NULL])
self.doAttributeTest(1, [NULL, 123, NULL, NULL])
+ def testStringWithMaxLen(self):
+ """ tests that text edit wrappers correctly handle string fields with a maximum length """
+ layer = QgsVectorLayer("none?field=fldint:integer", "layer", "memory")
+ assert layer.isValid()
+ layer.dataProvider().addAttributes([QgsField('max', QVariant.String, 'string', 10),
+ QgsField('nomax', QVariant.String, 'string', 0)])
+ layer.updateFields()
+ QgsMapLayerRegistry.instance().addMapLayer(layer)
+
+ reg = QgsEditorWidgetRegistry.instance()
+ config = {'IsMultiline': 'True'}
+
+ # first test for field without character limit
+ editor = QTextEdit()
+ editor.setPlainText('this_is_a_long_string')
+ w = reg.create('TextEdit', layer, 2, config, editor, None)
+ self.assertEqual(w.value(), 'this_is_a_long_string')
+
+ # next test for field with character limit
+ editor = QTextEdit()
+ editor.setPlainText('this_is_a_long_string')
+ w = reg.create('TextEdit', layer, 1, config, editor, None)
+
+ self.assertEqual(w.value(), 'this_is_a_')
+
+ QgsMapLayerRegistry.instance().removeAllMapLayers()
+
def test_ValueRelation_representValue(self):
first_layer = QgsVectorLayer("none?field=foreign_key:integer",
diff --git a/tests/src/python/test_qgsexpression.py b/tests/src/python/test_qgsexpression.py
index f4973e1..3472c8b 100644
--- a/tests/src/python/test_qgsexpression.py
+++ b/tests/src/python/test_qgsexpression.py
@@ -187,5 +187,13 @@ class TestQgsExpressionCustomFunctions(unittest.TestCase):
result = exp.evaluate()
self.assertEqual(exp_res, result)
+ def testValid(self):
+ e = QgsExpression()
+ self.assertFalse(e.isValid())
+ e.setExpression('asdf||#@¼')
+ self.assertFalse(e.isValid())
+ e.setExpression('1')
+ self.assertTrue(e.isValid())
+
if __name__ == "__main__":
unittest.main()
diff --git a/tests/src/python/test_qgsexpressionlineedit.py b/tests/src/python/test_qgsexpressionlineedit.py
new file mode 100644
index 0000000..7dc8b44
--- /dev/null
+++ b/tests/src/python/test_qgsexpressionlineedit.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+"""QGIS Unit tests for QgsExpressionLineEdit
+
+.. note:: This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+"""
+__author__ = 'Nyall Dawson'
+__date__ = '20/08/2016'
+__copyright__ = 'Copyright 2016, The QGIS Project'
+# This will get replaced with a git SHA1 when you do a git archive
+__revision__ = '$Format:%H$'
+
+import qgis # NOQA
+
+import os
+
+from qgis.gui import QgsExpressionLineEdit
+
+try:
+ from qgis.PyQt.QtTest import QSignalSpy
+ use_signal_spy = True
+except:
+ use_signal_spy = False
+
+from qgis.testing import start_app, unittest
+
+start_app()
+
+
+class TestQgsExpressionLineEdit(unittest.TestCase):
+
+ def testDialog(self):
+ """ test dialog related methods """
+ w = qgis.gui.QgsExpressionLineEdit()
+ w.setExpressionDialogTitle('test')
+ self.assertEqual(w.expressionDialogTitle(), 'test')
+
+ def testSetGetExpression(self):
+ """ test setting and getting expression """
+ w = qgis.gui.QgsExpressionLineEdit()
+ self.assertFalse(w.expression())
+ w.setExpression('1+2')
+ self.assertEqual(w.expression(), '1+2')
+ result, error = w.isValidExpression()
+ self.assertTrue(result)
+ w.setExpression('1+')
+ self.assertEqual(w.expression(), '1+')
+ result, error = w.isValidExpression()
+ self.assertFalse(result)
+ self.assertTrue(error)
+
+ # try with a multiline widget too
+ w.setMultiLine(True)
+ self.assertEqual(w.expression(), '1+')
+ w.setExpression('1+3')
+ self.assertEqual(w.expression(), '1+3')
+
+ # and flip back again...
+ w.setMultiLine(False)
+ self.assertEqual(w.expression(), '1+3')
+
+ @unittest.skipIf(not use_signal_spy, "No QSignalSpy available")
+ def test_ChangedSignals(self):
+ """ test that signals are correctly emitted when changing expressions"""
+
+ w = qgis.gui.QgsExpressionLineEdit()
+
+ expression_changed_spy = QSignalSpy(w.expressionChanged)
+ w.setExpression('1+1')
+
+ self.assertEqual(len(expression_changed_spy), 1)
+ self.assertEqual(expression_changed_spy[0][0], '1+1')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/src/python/test_qgsfilterlineedit.py b/tests/src/python/test_qgsfilterlineedit.py
new file mode 100644
index 0000000..f530c3f
--- /dev/null
+++ b/tests/src/python/test_qgsfilterlineedit.py
@@ -0,0 +1,136 @@
+# -*- coding: utf-8 -*-
+"""QGIS Unit tests for QgsFilterLineEdit
+
+.. note:: This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+"""
+__author__ = 'Nyall Dawson'
+__date__ = '20/08/2016'
+__copyright__ = 'Copyright 2016, The QGIS Project'
+# This will get replaced with a git SHA1 when you do a git archive
+__revision__ = '$Format:%H$'
+
+import qgis # NOQA
+
+from qgis.gui import QgsFilterLineEdit
+
+try:
+ from qgis.PyQt.QtTest import QSignalSpy
+ use_signal_spy = True
+except:
+ use_signal_spy = False
+
+from qgis.testing import start_app, unittest
+
+start_app()
+
+
+class TestQgsFilterLineEdit(unittest.TestCase):
+
+ def testGettersSetters(self):
+ """ test widget getters/setters """
+ w = qgis.gui.QgsFilterLineEdit()
+
+ w.setNullValue('null')
+ self.assertEqual(w.nullValue(), 'null')
+ w.setValue('value')
+ self.assertEqual(w.value(), 'value')
+ self.assertEqual(w.text(), 'value')
+ w.setDefaultValue('default')
+ self.assertEqual(w.defaultValue(), 'default')
+ w.setClearMode(QgsFilterLineEdit.ClearToDefault)
+ self.assertEqual(w.clearMode(), QgsFilterLineEdit.ClearToDefault)
+ w.setShowClearButton(False)
+ self.assertFalse(w.showClearButton())
+ w.setShowClearButton(True)
+ self.assertTrue(w.showClearButton())
+
+ def testNullValueHandling(self):
+ """ test widget handling of null values """
+ w = qgis.gui.QgsFilterLineEdit()
+
+ # start with no null value
+ w.setValue(None)
+ self.assertTrue(w.isNull())
+ w.setValue('a')
+ self.assertEqual(w.text(), 'a')
+ self.assertFalse(w.isNull())
+
+ # set a null value
+ w.setNullValue('null')
+ self.assertEqual(w.value(), 'a')
+ self.assertEqual(w.text(), 'a')
+ self.assertFalse(w.isNull())
+
+ w.setValue(None)
+ self.assertTrue(w.isNull())
+ self.assertFalse(w.value())
+ self.assertEqual(w.text(), 'null')
+
+ w.setValue('null')
+ self.assertEqual(w.text(), 'null')
+ # ND: I don't think this following logic is correct - should be a distinction between
+ # the widget's representation of null and the actual value. Ie isNull()
+ # should be false and value() should return 'null'
+ # in other words - if you break this test to match my desired behaviour, feel free to remove it!
+ self.assertTrue(w.isNull())
+ self.assertFalse(w.value())
+
+ def testClearToNull(self):
+ """ test clearing widget """
+ w = qgis.gui.QgsFilterLineEdit()
+
+ w.setValue('abc')
+ w.clearValue()
+ self.assertTrue(w.isNull())
+ self.assertFalse(w.value())
+ w.clearValue()
+ self.assertTrue(w.isNull())
+ self.assertFalse(w.value())
+
+ w.setNullValue('def')
+ w.setValue('abc')
+ self.assertFalse(w.isNull())
+ w.clearValue()
+ self.assertEqual(w.text(), 'def')
+ self.assertTrue(w.isNull())
+ self.assertFalse(w.value())
+
+ def testClearToDefault(self):
+ # test clearing to default value
+ w = qgis.gui.QgsFilterLineEdit()
+ w.setClearMode(QgsFilterLineEdit.ClearToDefault)
+
+ w.setValue('abc')
+ w.clearValue()
+ self.assertTrue(w.isNull())
+ self.assertFalse(w.value())
+ w.clearValue()
+ self.assertTrue(w.isNull())
+ self.assertFalse(w.value())
+
+ w.setDefaultValue('def')
+ w.setValue('abc')
+ self.assertFalse(w.isNull())
+ w.clearValue()
+ self.assertEqual(w.value(), 'def')
+ self.assertEqual(w.text(), 'def')
+ self.assertFalse(w.isNull())
+
+ @unittest.skipIf(not use_signal_spy, "No QSignalSpy available")
+ def test_ChangedSignals(self):
+ """ test that signals are correctly emitted when clearing"""
+
+ w = qgis.gui.QgsFilterLineEdit()
+
+ cleared_spy = QSignalSpy(w.cleared)
+ w.setValue('1')
+ w.clearValue()
+
+ self.assertEqual(len(cleared_spy), 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/src/python/test_qgsgeometry.py b/tests/src/python/test_qgsgeometry.py
index 16b7f74..d805fb9 100644
--- a/tests/src/python/test_qgsgeometry.py
+++ b/tests/src/python/test_qgsgeometry.py
@@ -14,6 +14,7 @@ __revision__ = '$Format:%H$'
import os
import csv
+import math
from qgis.core import (
QgsGeometry,
@@ -3360,5 +3361,159 @@ class TestQgsGeometry(unittest.TestCase):
wkb2 = geom.asWkb()
self.assertEqual(wkb1, wkb2)
+ def testMergeLines(self):
+ """ test merging linestrings """
+
+ # not a (multi)linestring
+ geom = QgsGeometry.fromWkt('Point(1 2)')
+ result = geom.mergeLines()
+ self.assertTrue(result.isEmpty())
+
+ # linestring should be returned intact
+ geom = QgsGeometry.fromWkt('LineString(0 0, 10 10)')
+ result = geom.mergeLines().exportToWkt()
+ exp = 'LineString(0 0, 10 10)'
+ self.assertTrue(compareWkt(result, exp, 0.00001), "Merge lines: mismatch Expected:\n{}\nGot:\n{}\n".format(exp, result))
+
+ # multilinestring
+ geom = QgsGeometry.fromWkt('MultiLineString((0 0, 10 10),(10 10, 20 20))')
+ result = geom.mergeLines().exportToWkt()
+ exp = 'LineString(0 0, 10 10, 20 20)'
+ self.assertTrue(compareWkt(result, exp, 0.00001), "Merge lines: mismatch Expected:\n{}\nGot:\n{}\n".format(exp, result))
+
+ geom = QgsGeometry.fromWkt('MultiLineString((0 0, 10 10),(12 2, 14 4),(10 10, 20 20))')
+ result = geom.mergeLines().exportToWkt()
+ exp = 'MultiLineString((0 0, 10 10, 20 20),(12 2, 14 4))'
+ self.assertTrue(compareWkt(result, exp, 0.00001), "Merge lines: mismatch Expected:\n{}\nGot:\n{}\n".format(exp, result))
+
+ geom = QgsGeometry.fromWkt('MultiLineString((0 0, 10 10),(12 2, 14 4))')
+ result = geom.mergeLines().exportToWkt()
+ exp = 'MultiLineString((0 0, 10 10),(12 2, 14 4))'
+ self.assertTrue(compareWkt(result, exp, 0.00001), "Merge lines: mismatch Expected:\n{}\nGot:\n{}\n".format(exp, result))
+
+ def testLineLocatePoint(self):
+ """ test QgsGeometry.lineLocatePoint() """
+
+ # not a linestring
+ point = QgsGeometry.fromWkt('Point(1 2)')
+ self.assertEqual(point.lineLocatePoint(point), -1)
+
+ # not a point
+ linestring = QgsGeometry.fromWkt('LineString(0 0, 10 0)')
+ self.assertEqual(linestring.lineLocatePoint(linestring), -1)
+
+ # valid
+ self.assertEqual(linestring.lineLocatePoint(point), 1)
+ point = QgsGeometry.fromWkt('Point(9 -2)')
+ self.assertEqual(linestring.lineLocatePoint(point), 9)
+
+ # circular string
+ geom = QgsGeometry.fromWkt('CircularString (1 5, 6 2, 7 3)')
+ point = QgsGeometry.fromWkt('Point(9 -2)')
+ self.assertAlmostEqual(geom.lineLocatePoint(point), 7.372, places=3)
+
+ def testInterpolateAngle(self):
+ """ test QgsGeometry.interpolateAngle() """
+
+ empty = QgsGeometry()
+ # just test no crash
+ self.assertEqual(empty.interpolateAngle(5), 0)
+
+ # not a linestring
+ point = QgsGeometry.fromWkt('Point(1 2)')
+ # no meaning, just test no crash!
+ self.assertEqual(point.interpolateAngle(5), 0)
+
+ # linestring
+ linestring = QgsGeometry.fromWkt('LineString(0 0, 10 0, 20 10, 20 20, 10 20)')
+ self.assertAlmostEqual(linestring.interpolateAngle(0), math.radians(90), places=3)
+ self.assertAlmostEqual(linestring.interpolateAngle(5), math.radians(90), places=3)
+ self.assertAlmostEqual(linestring.interpolateAngle(10), math.radians(67.5), places=3)
+ self.assertAlmostEqual(linestring.interpolateAngle(15), math.radians(45), places=3)
+ self.assertAlmostEqual(linestring.interpolateAngle(25), math.radians(0), places=3)
+ self.assertAlmostEqual(linestring.interpolateAngle(35), math.radians(270), places=3)
+
+ # test first and last points in a linestring - angle should be angle of
+ # first/last segment
+ linestring = QgsGeometry.fromWkt('LineString(20 0, 10 0, 10 -10)')
+ self.assertAlmostEqual(linestring.interpolateAngle(0), math.radians(270), places=3)
+ self.assertAlmostEqual(linestring.interpolateAngle(20), math.radians(180), places=3)
+
+ # polygon
+ polygon = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 20 10, 20 20, 10 20, 0 0))')
+ self.assertAlmostEqual(polygon.interpolateAngle(5), math.radians(90), places=3)
+ self.assertAlmostEqual(polygon.interpolateAngle(10), math.radians(67.5), places=3)
+ self.assertAlmostEqual(polygon.interpolateAngle(15), math.radians(45), places=3)
+ self.assertAlmostEqual(polygon.interpolateAngle(25), math.radians(0), places=3)
+ self.assertAlmostEqual(polygon.interpolateAngle(35), math.radians(270), places=3)
+
+ # test first/last vertex in polygon
+ polygon = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 10 10, 0 10, 0 0))')
+ self.assertAlmostEqual(polygon.interpolateAngle(0), math.radians(135), places=3)
+ self.assertAlmostEqual(polygon.interpolateAngle(40), math.radians(135), places=3)
+
+ # circular string
+ geom = QgsGeometry.fromWkt('CircularString (1 5, 6 2, 7 3)')
+ self.assertAlmostEqual(geom.interpolateAngle(5), 1.69120, places=3)
+
+ def testInterpolate(self):
+ """ test QgsGeometry.interpolate() """
+
+ empty = QgsGeometry()
+ # just test no crash
+ self.assertFalse(empty.interpolate(5))
+
+ # not a linestring
+ point = QgsGeometry.fromWkt('Point(1 2)')
+ # no meaning, just test no crash!
+ self.assertFalse(empty.interpolate(5))
+
+ # linestring
+ linestring = QgsGeometry.fromWkt('LineString(0 0, 10 0, 10 10)')
+ exp = 'Point(5 0)'
+ result = linestring.interpolate(5).exportToWkt()
+ self.assertTrue(compareWkt(result, exp, 0.00001), "Interpolate: mismatch Expected:\n{}\nGot:\n{}\n".format(exp, result))
+
+ # polygon
+ polygon = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 10 10, 20 20, 10 20, 0 0))')
+ exp = 'Point(10 5)'
+ result = linestring.interpolate(15).exportToWkt()
+ self.assertTrue(compareWkt(result, exp, 0.00001),
+ "Interpolate: mismatch Expected:\n{}\nGot:\n{}\n".format(exp, result))
+
+ def testAngleAtVertex(self):
+ """ test QgsGeometry.angleAtVertex """
+
+ empty = QgsGeometry()
+ # just test no crash
+ self.assertEqual(empty.angleAtVertex(0), 0)
+
+ # not a linestring
+ point = QgsGeometry.fromWkt('Point(1 2)')
+ # no meaning, just test no crash!
+ self.assertEqual(point.angleAtVertex(0), 0)
+
+ # linestring
+ linestring = QgsGeometry.fromWkt('LineString(0 0, 10 0, 20 10, 20 20, 10 20)')
+ self.assertAlmostEqual(linestring.angleAtVertex(1), math.radians(67.5), places=3)
+ self.assertAlmostEqual(linestring.angleAtVertex(2), math.radians(22.5), places=3)
+ self.assertAlmostEqual(linestring.angleAtVertex(3), math.radians(315.0), places=3)
+ self.assertAlmostEqual(linestring.angleAtVertex(5), 0, places=3)
+ self.assertAlmostEqual(linestring.angleAtVertex(-1), 0, places=3)
+
+ # test first and last points in a linestring - angle should be angle of
+ # first/last segment
+ linestring = QgsGeometry.fromWkt('LineString(20 0, 10 0, 10 -10)')
+ self.assertAlmostEqual(linestring.angleAtVertex(0), math.radians(270), places=3)
+ self.assertAlmostEqual(linestring.angleAtVertex(2), math.radians(180), places=3)
+
+ # polygon
+ polygon = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 10 10, 0 10, 0 0))')
+ self.assertAlmostEqual(polygon.angleAtVertex(0), math.radians(135.0), places=3)
+ self.assertAlmostEqual(polygon.angleAtVertex(1), math.radians(45.0), places=3)
+ self.assertAlmostEqual(polygon.angleAtVertex(2), math.radians(315.0), places=3)
+ self.assertAlmostEqual(polygon.angleAtVertex(3), math.radians(225.0), places=3)
+ self.assertAlmostEqual(polygon.angleAtVertex(4), math.radians(135.0), places=3)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/src/python/test_qgsgeometryvalidator.py b/tests/src/python/test_qgsgeometryvalidator.py
new file mode 100644
index 0000000..661817f
--- /dev/null
+++ b/tests/src/python/test_qgsgeometryvalidator.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+"""QGIS Unit tests for QgsGeometryValidator.
+
+.. note:: This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+"""
+__author__ = 'Nyall Dawson'
+__date__ = '03/10/2016'
+__copyright__ = 'Copyright 2016, The QGIS Project'
+# This will get replaced with a git SHA1 when you do a git archive
+__revision__ = '$Format:%H$'
+
+import os
+import csv
+import math
+
+from qgis.core import (
+ QgsGeometry,
+ QgsGeometryValidator
+)
+
+from qgis.testing import (
+ unittest
+)
+
+
+class TestQgsGeometryValidator(unittest.TestCase):
+
+ def testIssue15660(self):
+ """ Test crash when validating geometry (#15660) """
+ g = QgsGeometry.fromWkt(
+ "Polygon ((0.44256348235389709 -47.87645625696347906, -2.88231630340906797 -47.90003919913998232,"
+ "-2.88589842578005751 -48.91215450743293047, -2.8858984257800584 -48.91215450743293047,"
+ "-2.88589842578005751 -48.91215450743292337, -2.88589842632776516 -48.9121545074024624,"
+ "-3.24858148608664266 -48.89198543875494352, -3.27689849271356159 -49.40119850743292318,"
+ "-4.37689842578006072 -49.40119850743292318, -4.3768984257800625 -49.40119850743293739,"
+ "-6.11689842578005738 -49.40119850743293739, -6.11689842578006093 -49.40119850743292318,"
+ "-7.03689842578006086 -49.40119850743292318, -7.02239489567359776 -48.93302358132471852,"
+ "-7.02177188091450688 -48.91291272055079276, -7.02177188393206286 -48.91291272045731375,"
+ "-7.02141642578006309 -48.9014385074329212, -7.7002102410998674 -48.88041051649613422,"
+ "-7.70077301577442341 -48.89187793078160382, -7.70077301577442341 -48.89187793078160382,"
+ "-7.70233865095334291 -48.92378019651650334, -7.72576842578006051 -49.40119850743292318,"
+ "-9.26576842578005966 -49.40119850743292318, -9.26576842578006321 -49.40119850743293739,"
+ "-13.28076842578006023 -49.40119850743293739, -13.04700849136197149 -44.82717853953759857,"
+ "-12.22739168108193297 -44.85224022031006541, -12.22501286465108805 -44.774446133668377,"
+ "-12.22288921611744783 -44.774511069530881, -12.2155540445085915 -44.53462318893357264,"
+ "-13.0310217329353506 -44.50968822589503304, -12.87640859053235687 -41.29089836691012749,"
+ "-7.83390711693117936 -41.74840291007100745, -7.88211379129075596 -42.99075321817508666,"
+ "-7.43245210877673657 -43.00820115628285123, -7.50410812906098013 -44.67868742523263847,"
+ "-7.52086717830689011 -44.67817497540850979, -7.52820234991574644 -44.91806285600581816,"
+ "-7.51439432253991058 -44.91848507095944854, -7.57421591980290287 -46.3130804785479242,"
+ "-8.32385639731993621 -46.28985691678211367, -8.44985043007881842 -48.85718773355701217,"
+ "-6.26478736265246283 -48.92487774800262912, -6.18500945357052245 -46.35611749220839073,"
+ "-6.94163842159974198 -46.33267751510010157, -6.82382190915497944 -40.77447960826383166,"
+ "-5.48772831582523146 -40.77837853452808758, -5.48973219643841759 -39.92687558952010107,"
+ "-2.75658441771447116 -40.04490036239724304, -3.1241861109063862 -46.6551270968877958,"
+ "-2.78977790434136885 -46.6737244011090695, -2.78977790434136796 -46.6737244011090695,"
+ "-2.71083842578005996 -44.83541850743291945, -2.71083842578005729 -44.83541850743291945,"
+ "-0.86779302740823816 -44.89143693883772812, -0.86745855610774569 -44.87743669555854353,"
+ "0.29843811058281489 -44.90401226269042922, 0.20437651721061911 -46.69301920907949466,"
+ "0.50389019278376956 -46.71008040893148916, 0.44256348235389709 -47.87645625696347906))")
+
+ self.assertTrue(g)
+ # make sure validating this geometry doesn't crash QGIS
+ QgsGeometryValidator.validateGeometry(g)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/src/python/test_qgsoptional.py b/tests/src/python/test_qgsoptional.py
new file mode 100644
index 0000000..ed28fc7
--- /dev/null
+++ b/tests/src/python/test_qgsoptional.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+'''
+test_qgsoptional.py
+ --------------------------------------
+ Date : September 2016
+ Copyright : (C) 2016 Matthias Kuhn
+ email : matthias at opengis.ch
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+'''
+
+import qgis # NOQA
+
+from qgis.testing import unittest
+from qgis.core import QgsOptionalExpression, QgsExpression
+
+
+class TestQgsOptional(unittest.TestCase):
+
+ def setUp(self):
+ """Run before each test."""
+ pass
+
+ def tearDown(self):
+ """Run after each test."""
+ pass
+
+ def testQgsOptionalExpression(self):
+ opt = QgsOptionalExpression()
+ self.assertFalse(opt.enabled())
+
+ opt = QgsOptionalExpression(QgsExpression('true'))
+ self.assertTrue(opt.enabled())
+ self.assertEquals(opt.data().expression(), 'true')
+ opt.setEnabled(False)
+ self.assertFalse(opt.enabled())
+ # boolean operator not yet working in python
+ # self.assertFalse(opt)
+ self.assertEquals(opt.data().expression(), 'true')
+ opt.setEnabled(True)
+ self.assertTrue(opt.enabled())
+ # self.assertTrue(opt)
+ self.assertEquals(opt.data().expression(), 'true')
+ opt.setData(QgsExpression('xyz'))
+ self.assertTrue(opt.enabled())
+ self.assertEquals(opt.data().expression(), 'xyz')
+
+ opt = QgsOptionalExpression(QgsExpression('true'), False)
+ self.assertFalse(opt.enabled())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/src/python/test_qgspallabeling_base.py b/tests/src/python/test_qgspallabeling_base.py
index fbc0fcf..3c49914 100644
--- a/tests/src/python/test_qgspallabeling_base.py
+++ b/tests/src/python/test_qgspallabeling_base.py
@@ -29,7 +29,7 @@ import glob
import shutil
import tempfile
-from qgis.PyQt.QtCore import QSize, qDebug
+from qgis.PyQt.QtCore import QSize, qDebug, Qt
from qgis.PyQt.QtGui import QFont, QColor
from qgis.core import (
@@ -266,6 +266,7 @@ class TestQgsPalLabeling(unittest.TestCase):
font.setPointSize(32)
lyr.textFont = font
lyr.textNamedStyle = 'Roman'
+ lyr.bufferJoinStyle = Qt.BevelJoin # handle change of default join style
return lyr
@staticmethod
diff --git a/tests/src/python/test_qgspallabeling_placement.py b/tests/src/python/test_qgspallabeling_placement.py
index 5b32792..caa5103 100644
--- a/tests/src/python/test_qgspallabeling_placement.py
+++ b/tests/src/python/test_qgspallabeling_placement.py
@@ -272,6 +272,167 @@ class TestPointPlacement(TestPlacementBase):
self.removeMapLayer(self.layer)
self.layer = None
+ def test_polygon_placement_perimeter(self):
+ # Default polygon perimeter placement
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('polygon_perimeter')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.lyr.placementFlags = QgsPalLayerSettings.AboveLine
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_small_polygon_placement_perimeter(self):
+ # Default polygon perimeter placement for small polygon
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('polygon_small')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_small_polygon_perimeter_only_fit(self):
+ # Polygon perimeter placement for small polygon when set to only show labels which fit in polygon
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('polygon_small')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.lyr.fitInPolygonOnly = True
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_small_polygon_curvedperimeter_only_fit(self):
+ # Polygon perimeter placement for small polygon when set to only show labels which fit in polygon
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('polygon_small')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.PerimeterCurved
+ self.lyr.fitInPolygonOnly = True
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_small_polygon_over_point_only_fit(self):
+ # Polygon over point placement for small polygon when set to only show labels which fit in polygon
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('polygon_small')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.OverPoint
+ self.lyr.fitInPolygonOnly = True
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_prefer_line_curved_above_instead_of_below(self):
+ # Test that labeling a line using curved labels when both above and below placement are allowed that above
+ # is preferred
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Curved
+ self.lyr.placementFlags = QgsPalLayerSettings.AboveLine | QgsPalLayerSettings.BelowLine | QgsPalLayerSettings.MapOrientation
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_prefer_line_curved_above_instead_of_online(self):
+ # Test that labeling a line using curved labels when both above and online placement are allowed that above
+ # is preferred
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Curved
+ self.lyr.placementFlags = QgsPalLayerSettings.AboveLine | QgsPalLayerSettings.OnLine | QgsPalLayerSettings.MapOrientation
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_prefer_line_curved_below_instead_of_online(self):
+ # Test that labeling a line using curved labels when both below and online placement are allowed that below
+ # is preferred
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Curved
+ self.lyr.placementFlags = QgsPalLayerSettings.BelowLine | QgsPalLayerSettings.OnLine | QgsPalLayerSettings.MapOrientation
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_prefer_line_above_instead_of_below(self):
+ # Test that labeling a line using parallel labels when both above and below placement are allowed that above
+ # is preferred
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.lyr.placementFlags = QgsPalLayerSettings.AboveLine | QgsPalLayerSettings.BelowLine | QgsPalLayerSettings.MapOrientation
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_prefer_line_above_instead_of_online(self):
+ # Test that labeling a line using parallel labels when both above and online placement are allowed that above
+ # is preferred
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.lyr.placementFlags = QgsPalLayerSettings.AboveLine | QgsPalLayerSettings.OnLine | QgsPalLayerSettings.MapOrientation
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_prefer_line_below_instead_of_online(self):
+ # Test that labeling a line using parallel labels when both below and online placement are allowed that below
+ # is preferred
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.lyr.placementFlags = QgsPalLayerSettings.BelowLine | QgsPalLayerSettings.OnLine | QgsPalLayerSettings.MapOrientation
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_prefer_longer_lines_over_shorter(self):
+ # Test that labeling a line using parallel labels will tend to place the labels over the longer straight parts of
+ # the line
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line_placement_1')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_prefer_more_horizontal_lines(self):
+ # Test that labeling a line using parallel labels will tend to place the labels over more horizontal sections
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line_placement_2')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_label_line_over_small_angles(self):
+ # Test that labeling a line using parallel labels will place labels near center of straightish line
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line_placement_3')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_label_line_toward_center(self):
+ # Test that labeling a line using parallel labels will try to place labels as close to center of line as possible
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line_placement_4')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
+ def test_label_line_avoid_jaggy(self):
+ # Test that labeling a line using parallel labels won't place labels over jaggy bits of line
+ self.layer = TestQgsPalLabeling.loadFeatureLayer('line_placement_5')
+ self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
+ self.lyr.placement = QgsPalLayerSettings.Line
+ self.checkTest()
+ self.removeMapLayer(self.layer)
+ self.layer = None
+
if __name__ == '__main__':
# NOTE: unless PAL_SUITE env var is set all test class methods will be run
# SEE: test_qgspallabeling_tests.suiteTests() to define suite
diff --git a/tests/src/python/test_qgspanelwidget.py b/tests/src/python/test_qgspanelwidget.py
new file mode 100644
index 0000000..6870052
--- /dev/null
+++ b/tests/src/python/test_qgspanelwidget.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+"""QGIS Unit tests for QgsPanelWidget.
+
+.. note:: This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+"""
+__author__ = 'Nyall Dawson'
+__date__ = '16/08/2016'
+__copyright__ = 'Copyright 2016, The QGIS Project'
+# This will get replaced with a git SHA1 when you do a git archive
+__revision__ = '$Format:%H$'
+
+import qgis # NOQA
+
+from qgis.PyQt.QtWidgets import QWidget, QDialog
+from qgis.gui import QgsPanelWidget
+from qgis.testing import start_app, unittest
+
+start_app()
+
+
+class TestQgsPanelWidget(unittest.TestCase):
+
+ def testFindParentPanel(self):
+ """ test QgsPanelWidget.findParentPanel """
+
+ # no widget
+ self.assertFalse(QgsPanelWidget.findParentPanel(None))
+
+ # widget with no parent
+ w = QWidget()
+ self.assertFalse(QgsPanelWidget.findParentPanel(w))
+
+ # widget with no panel parent
+ w2 = QWidget(w)
+ self.assertFalse(QgsPanelWidget.findParentPanel(w2))
+
+ # panel widget itself
+ w3 = QgsPanelWidget()
+ self.assertEqual(QgsPanelWidget.findParentPanel(w3), w3)
+
+ # widget with direct QgsPanelWidget parent
+ w4 = QWidget(w3)
+ self.assertEqual(QgsPanelWidget.findParentPanel(w4), w3)
+
+ # widget with QgsPanelWidget grandparent
+ w5 = QWidget(w4)
+ self.assertEqual(QgsPanelWidget.findParentPanel(w5), w3)
+
+ # chain should be broken when a new window is encountered
+ n = QgsPanelWidget()
+ n2 = QDialog(n)
+ n3 = QWidget(n2)
+ self.assertFalse(QgsPanelWidget.findParentPanel(n3))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/src/python/test_qgsserver.py b/tests/src/python/test_qgsserver.py
index 0d2ed4a..a41692b 100644
--- a/tests/src/python/test_qgsserver.py
+++ b/tests/src/python/test_qgsserver.py
@@ -19,13 +19,16 @@ import urllib
from mimetools import Message
from StringIO import StringIO
from qgis.server import QgsServer
-from qgis.core import QgsMessageLog
+from qgis.core import QgsMessageLog, QgsRenderChecker
from qgis.testing import unittest
+from qgis.PyQt.QtCore import QSize
from utilities import unitTestDataPath
import osgeo.gdal
+import tempfile
+import base64
# Strip path and content length because path may vary
-RE_STRIP_PATH = r'MAP=[^&]+|Content-Length: \d+'
+RE_STRIP_PATH = r'MAP=[^&]+|Content-Length: \d+|<Attribute typeName="[^>]+'
class TestQgsServer(unittest.TestCase):
@@ -150,7 +153,7 @@ class TestQgsServer(unittest.TestCase):
# WMS tests
def wms_request_compare(self, request, extra=None, reference_file=None):
- project = self.testdata_path + "test+project.qgs"
+ project = self.testdata_path + "test_project.qgs"
assert os.path.exists(project), "Project file not found: " + project
query_string = 'MAP=%s&SERVICE=WMS&VERSION=1.3&REQUEST=%s' % (urllib.quote(project), request)
@@ -158,20 +161,25 @@ class TestQgsServer(unittest.TestCase):
query_string += extra
header, body = [str(_v) for _v in self.server.handleRequest(query_string)]
response = header + body
- f = open(self.testdata_path + (request.lower() if not reference_file else reference_file) + '.txt')
+ reference_path = self.testdata_path + (request.lower() if not reference_file else reference_file) + '.txt'
+ f = open(reference_path)
expected = f.read()
f.close()
# Store the output for debug or to regenerate the reference documents:
"""
+ f = open(reference_path, 'wb+')
+ f.write(response)
+ f.close()
+
f = open(os.path.dirname(__file__) + '/expected.txt', 'w+')
f.write(expected)
f.close()
f = open(os.path.dirname(__file__) + '/response.txt', 'w+')
f.write(response)
f.close()
- #"""
- response = re.sub(RE_STRIP_PATH, '', response)
- expected = re.sub(RE_STRIP_PATH, '', expected)
+ """
+ response = re.sub(RE_STRIP_PATH, '*****', response)
+ expected = re.sub(RE_STRIP_PATH, '*****', expected)
# for older GDAL versions (<2.0), id field will be integer type
if int(osgeo.gdal.VersionInfo()[:1]) < 2:
@@ -214,7 +222,7 @@ class TestQgsServer(unittest.TestCase):
def wms_inspire_request_compare(self, request):
"""WMS INSPIRE tests"""
- project = self.testdata_path + "test+project_inspire.qgs"
+ project = self.testdata_path + "test_project_inspire.qgs"
assert os.path.exists(project), "Project file not found: " + project
query_string = 'MAP=%s&SERVICE=WMS&VERSION=1.3.0&REQUEST=%s' % (urllib.quote(project), request)
@@ -243,7 +251,7 @@ class TestQgsServer(unittest.TestCase):
# WFS tests
def wfs_request_compare(self, request):
- project = self.testdata_path + "test+project_wfs.qgs"
+ project = self.testdata_path + "test_project_wfs.qgs"
assert os.path.exists(project), "Project file not found: " + project
query_string = 'MAP=%s&SERVICE=WFS&VERSION=1.0.0&REQUEST=%s' % (urllib.quote(project), request)
@@ -277,7 +285,7 @@ class TestQgsServer(unittest.TestCase):
self.wfs_request_compare(request)
def wfs_getfeature_compare(self, requestid, request):
- project = self.testdata_path + "test+project_wfs.qgs"
+ project = self.testdata_path + "test_project_wfs.qgs"
assert os.path.exists(project), "Project file not found: " + project
query_string = 'MAP=%s&SERVICE=WFS&VERSION=1.0.0&REQUEST=%s' % (urllib.quote(project), request)
@@ -324,7 +332,7 @@ class TestQgsServer(unittest.TestCase):
self.wfs_getfeature_compare(id, req)
def wfs_getfeature_post_compare(self, requestid, request):
- project = self.testdata_path + "test+project_wfs.qgs"
+ project = self.testdata_path + "test_project_wfs.qgs"
assert os.path.exists(project), "Project file not found: " + project
query_string = 'MAP={}'.format(urllib.quote(project))
@@ -369,7 +377,7 @@ class TestQgsServer(unittest.TestCase):
def test_getLegendGraphics(self):
"""Test that does not return an exception but an image"""
parms = {
- 'MAP': self.testdata_path + "test%2Bproject.qgs",
+ 'MAP': self.testdata_path + "test_project.qgs",
'SERVICE': 'WMS',
'VERSION': '1.0.0',
'REQUEST': 'GetLegendGraphic',
@@ -383,6 +391,81 @@ class TestQgsServer(unittest.TestCase):
self.assertEqual(-1, h.find('Content-Type: text/xml; charset=utf-8'), "Header: %s\nResponse:\n%s" % (h, r))
self.assertNotEquals(-1, h.find('Content-Type: image/png'), "Header: %s\nResponse:\n%s" % (h, r))
+ def test_getLegendGraphics_layertitle(self):
+ """Test that does not return an exception but an image"""
+ parms = {
+ 'MAP': self.testdata_path + "test_project.qgs",
+ 'SERVICE': 'WMS',
+ 'VERSION': '1.3.0',
+ 'REQUEST': 'GetLegendGraphic',
+ 'FORMAT': 'image/png',
+ #'WIDTH': '20', # optional
+ #'HEIGHT': '20', # optional
+ 'LAYER': u'testlayer%20èé',
+ 'LAYERTITLE': 'TRUE',
+ }
+ qs = '&'.join([u"%s=%s" % (k, v) for k, v in parms.items()])
+ r, h = self._result(self.server.handleRequest(qs))
+ self._img_diff_error(r, h, "WMS_GetLegendGraphic_test", 250, QSize(10, 10))
+
+ parms = {
+ 'MAP': self.testdata_path + "test_project.qgs",
+ 'SERVICE': 'WMS',
+ 'VERSION': '1.3.0',
+ 'REQUEST': 'GetLegendGraphic',
+ 'FORMAT': 'image/png',
+ #'WIDTH': '20', # optional
+ #'HEIGHT': '20', # optional
+ 'LAYER': u'testlayer%20èé',
+ 'LAYERTITLE': 'FALSE',
+ }
+ qs = '&'.join([u"%s=%s" % (k, v) for k, v in parms.items()])
+ r, h = self._result(self.server.handleRequest(qs))
+ self._img_diff_error(r, h, "WMS_GetLegendGraphic_test_layertitle_false", 250, QSize(10, 10))
+
+ def _result(self, data):
+ headers = {}
+ for line in data[0].decode('UTF-8').split("\n"):
+ if line != "":
+ header = line.split(":")
+ self.assertEqual(len(header), 2, line)
+ headers[str(header[0])] = str(header[1]).strip()
+
+ return data[1], headers
+
+ def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize()):
+ temp_image = os.path.join(tempfile.gettempdir(), "%s_result.png" % control_image)
+
+ with open(temp_image, "wb") as f:
+ f.write(image)
+
+ control = QgsRenderChecker()
+ control.setControlPathPrefix("qgis_server")
+ control.setControlName(control_image)
+ control.setRenderedImage(temp_image)
+ if max_size_diff.isValid():
+ control.setSizeTolerance(max_size_diff.width(), max_size_diff.height())
+ return control.compareImages(control_image), control.report()
+
+ def _img_diff_error(self, response, headers, image, max_diff=10, max_size_diff=QSize()):
+ self.assertEqual(
+ headers.get("Content-Type"), "image/png",
+ "Content type is wrong: %s" % headers.get("Content-Type"))
+ test, report = self._img_diff(response, image, max_diff, max_size_diff)
+
+ with open(os.path.join(tempfile.gettempdir(), image + "_result.png"), "rb") as rendered_file:
+ encoded_rendered_file = base64.b64encode(rendered_file.read())
+ message = "Image is wrong\n%s\nImage:\necho '%s' | base64 -d >%s/%s_result.png" % (
+ report, encoded_rendered_file.strip(), tempfile.gettempdir(), image
+ )
+
+ with open(os.path.join(tempfile.gettempdir(), image + "_result_diff.png"), "rb") as diff_file:
+ encoded_diff_file = base64.b64encode(diff_file.read())
+ message += "\nDiff:\necho '%s' | base64 -d > %s/%s_result_diff.png" % (
+ encoded_diff_file.strip(), tempfile.gettempdir(), image
+ )
+
+ self.assertTrue(test, message)
if __name__ == '__main__':
unittest.main()
diff --git a/tests/src/python/test_qgsserver_wfst.py b/tests/src/python/test_qgsserver_wfst.py
index 5801f54..d707a4a 100644
--- a/tests/src/python/test_qgsserver_wfst.py
+++ b/tests/src/python/test_qgsserver_wfst.py
@@ -1,3 +1,4 @@
+
# -*- coding: utf-8 -*-
"""
Tests for WFS-T provider using QGIS Server through qgis_wrapped_server.py.
@@ -36,11 +37,12 @@ __revision__ = '$Format:%H$'
import os
import sys
+import re
import subprocess
from shutil import copytree, rmtree
import tempfile
from time import sleep
-from utilities import unitTestDataPath
+from utilities import unitTestDataPath, waitServer
from qgis.core import (
QgsVectorLayer,
QgsFeature,
@@ -56,9 +58,9 @@ from qgis.testing import (
)
try:
- QGIS_SERVER_WFST_DEFAULT_PORT = os.environ['QGIS_SERVER_WFST_DEFAULT_PORT']
+ QGIS_SERVER_WFST_PORT = os.environ['QGIS_SERVER_WFST_PORT']
except:
- QGIS_SERVER_WFST_DEFAULT_PORT = 8081
+ QGIS_SERVER_WFST_PORT = '0' # Auto
qgis_app = start_app()
@@ -69,7 +71,7 @@ class TestWFST(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""Run before all tests"""
- cls.port = QGIS_SERVER_WFST_DEFAULT_PORT
+ cls.port = QGIS_SERVER_WFST_PORT
# Create tmp folder
cls.temp_path = tempfile.mkdtemp()
cls.testdata_path = cls.temp_path + '/' + 'wfs_transactional' + '/'
@@ -89,17 +91,22 @@ class TestWFST(unittest.TestCase):
# Clear all test layers
for ln in ['test_point', 'test_polygon', 'test_linestring']:
cls._clearLayer(ln)
- os.environ['QGIS_SERVER_DEFAULT_PORT'] = str(cls.port)
+ os.environ['QGIS_SERVER_PORT'] = str(cls.port)
server_path = os.path.dirname(os.path.realpath(__file__)) + \
'/qgis_wrapped_server.py'
cls.server = subprocess.Popen([sys.executable, server_path],
- env=os.environ)
- sleep(2)
+ env=os.environ, stdout=subprocess.PIPE)
+ line = cls.server.stdout.readline()
+ cls.port = int(re.findall(b':(\d+)', line)[0])
+ assert cls.port != 0
+ # Wait for the server process to start
+ assert waitServer('http://127.0.0.1:%s' % cls.port), "Server is not responding! http://127.0.0.1:%s" % cls.port
@classmethod
def tearDownClass(cls):
"""Run after all tests"""
cls.server.terminate()
+ cls.server.wait()
del cls.server
# Clear all test layers
for ln in ['test_point', 'test_polygon', 'test_linestring']:
@@ -152,7 +159,7 @@ class TestWFST(unittest.TestCase):
'table': '',
#'sql': '',
}
- uri = ' '.join([("%s='%s'" % (k, v)) for k, v in parms.items()])
+ uri = ' '.join([("%s='%s'" % (k, v)) for k, v in list(parms.items())])
wfs_layer = QgsVectorLayer(uri, layer_name, 'WFS')
assert wfs_layer.isValid()
return wfs_layer
diff --git a/tests/src/python/test_qgsstringutils.py b/tests/src/python/test_qgsstringutils.py
new file mode 100644
index 0000000..a007886
--- /dev/null
+++ b/tests/src/python/test_qgsstringutils.py
@@ -0,0 +1,181 @@
+# -*- coding: utf-8 -*-
+"""QGIS Unit tests for QgsStringUtils.
+
+.. note:: This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+"""
+__author__ = 'Nyall Dawson'
+__date__ = '30/08/2016'
+__copyright__ = 'Copyright 2016, The QGIS Project'
+# This will get replaced with a git SHA1 when you do a git archive
+__revision__ = '$Format:%H$'
+
+import qgis # NOQA
+
+from qgis.PyQt.QtXml import (QDomDocument, QDomElement)
+
+from qgis.core import (QgsStringUtils,
+ QgsStringReplacement,
+ QgsStringReplacementCollection
+ )
+from qgis.testing import unittest
+
+
+class PyQgsStringReplacement(unittest.TestCase):
+
+ def testBasic(self):
+ """ basic tests for QgsStringReplacement"""
+ r = QgsStringReplacement('match', 'replace')
+ self.assertEqual(r.match(), 'match')
+ self.assertEqual(r.replacement(), 'replace')
+
+ r = QgsStringReplacement('match', 'replace', True, True)
+ self.assertTrue(r.wholeWordOnly())
+ self.assertTrue(r.caseSensitive())
+
+ def testReplace(self):
+ """ test applying replacements"""
+
+ # case insensitive
+ r = QgsStringReplacement('match', 'replace', False, False)
+ self.assertEqual(r.process('one MaTch only'), 'one replace only')
+ self.assertEqual(r.process('more then one MaTch here match two'), 'more then one replace here replace two')
+ self.assertEqual(r.process('match start and end MaTch'), 'replace start and end replace')
+ self.assertEqual(r.process('no hits'), 'no hits')
+ self.assertEqual(r.process('some exmatches here'), 'some exreplacees here')
+ self.assertEqual(r.process(''), '')
+
+ # case sensitive
+ r = QgsStringReplacement('match', 'replace', True, False)
+ self.assertEqual(r.process('one MaTch only'), 'one MaTch only')
+ self.assertEqual(r.process('one match only'), 'one replace only')
+
+ # whole word only, case insensitive
+ r = QgsStringReplacement('match', 'replace', False, True)
+ self.assertEqual(r.process('some exmatches here'), 'some exmatches here')
+ self.assertEqual(r.process('some match here'), 'some replace here')
+ self.assertEqual(r.process('some exmatches MaTch here'), 'some exmatches replace here')
+ self.assertEqual(r.process('some match maTCh here'), 'some replace replace here')
+ self.assertEqual(r.process('some -match. here'), 'some -replace. here')
+ self.assertEqual(r.process('match here'), 'replace here')
+ self.assertEqual(r.process('some match'), 'some replace')
+
+ # whole word only, case sensitive
+ r = QgsStringReplacement('match', 'replace', True, True)
+ self.assertEqual(r.process('some exmatches here'), 'some exmatches here')
+ self.assertEqual(r.process('some match here'), 'some replace here')
+ self.assertEqual(r.process('some exmatches MaTch here'), 'some exmatches MaTch here')
+ self.assertEqual(r.process('some match maTCh here'), 'some replace maTCh here')
+
+ def testEquality(self):
+ """ test equality operator"""
+ r1 = QgsStringReplacement('a', 'b', True, True)
+ r2 = QgsStringReplacement('a', 'b', True, True)
+ self.assertEqual(r1, r2)
+ r2 = QgsStringReplacement('c', 'b')
+ self.assertNotEqual(r1, r2)
+ r2 = QgsStringReplacement('a', 'c')
+ self.assertNotEqual(r1, r2)
+ r2 = QgsStringReplacement('a', 'b', False, True)
+ self.assertNotEqual(r1, r2)
+ r2 = QgsStringReplacement('c', 'b', True, False)
+ self.assertNotEqual(r1, r2)
+
+ def testSaveRestore(self):
+ """ test saving/restoring replacement to map"""
+ r1 = QgsStringReplacement('a', 'b', True, True)
+ props = r1.properties()
+ r2 = QgsStringReplacement.fromProperties(props)
+ self.assertEqual(r1, r2)
+ r1 = QgsStringReplacement('a', 'b', False, False)
+ props = r1.properties()
+ r2 = QgsStringReplacement.fromProperties(props)
+ self.assertEqual(r1, r2)
+
+
+class PyQgsStringReplacementCollection(unittest.TestCase):
+
+ def testBasic(self):
+ """ basic QgsStringReplacementCollection tests"""
+ list = [QgsStringReplacement('aa', '11'),
+ QgsStringReplacement('bb', '22')]
+ c = QgsStringReplacementCollection(list)
+ self.assertEqual(c.replacements(), list)
+
+ def testReplacements(self):
+ """ test replacing using collection of replacements """
+ c = QgsStringReplacementCollection()
+ c.setReplacements([QgsStringReplacement('aa', '11'),
+ QgsStringReplacement('bb', '22')])
+ self.assertEqual(c.process('here aa bb is aa string bb'), 'here 11 22 is 11 string 22')
+ self.assertEqual(c.process('no matches'), 'no matches')
+ self.assertEqual(c.process(''), '')
+
+ # test replacements are done in order
+ c.setReplacements([QgsStringReplacement('aa', '11'),
+ QgsStringReplacement('11', '22')])
+ self.assertEqual(c.process('string aa'), 'string 22')
+ # no replacements
+ c.setReplacements([])
+ self.assertEqual(c.process('string aa'), 'string aa')
+
+ def testSaveRestore(self):
+ """ test saving and restoring collections """
+ c = QgsStringReplacementCollection([QgsStringReplacement('aa', '11', False, False),
+ QgsStringReplacement('bb', '22', True, True)])
+ doc = QDomDocument("testdoc")
+ elem = doc.createElement("replacements")
+ c.writeXml(elem, doc)
+ c2 = QgsStringReplacementCollection()
+ c2.readXml(elem)
+ self.assertEqual(c2.replacements(), c.replacements())
+
+
+class PyQgsStringUtils(unittest.TestCase):
+
+ def testMixed(self):
+ """ test mixed capitalization - ie, no change! """
+ self.assertFalse(QgsStringUtils.capitalize(None, QgsStringUtils.MixedCase))
+ self.assertEqual(QgsStringUtils.capitalize('', QgsStringUtils.MixedCase), '')
+ self.assertEqual(QgsStringUtils.capitalize('testing 123', QgsStringUtils.MixedCase), 'testing 123')
+ self.assertEqual(QgsStringUtils.capitalize(' tESTinG 123 ', QgsStringUtils.MixedCase), ' tESTinG 123 ')
+ self.assertEqual(QgsStringUtils.capitalize(' TESTING ABC', QgsStringUtils.MixedCase), ' TESTING ABC')
+
+ def testUpperCase(self):
+ """ test uppercase """
+ self.assertFalse(QgsStringUtils.capitalize(None, QgsStringUtils.AllUppercase))
+ self.assertEqual(QgsStringUtils.capitalize('', QgsStringUtils.AllUppercase), '')
+ self.assertEqual(QgsStringUtils.capitalize('testing 123', QgsStringUtils.AllUppercase), 'TESTING 123')
+ self.assertEqual(QgsStringUtils.capitalize(' tESTinG abc ', QgsStringUtils.AllUppercase), ' TESTING ABC ')
+ self.assertEqual(QgsStringUtils.capitalize(' TESTING ABC', QgsStringUtils.AllUppercase), ' TESTING ABC')
+
+ def testLowerCase(self):
+ """ test lowercase """
+ self.assertFalse(QgsStringUtils.capitalize(None, QgsStringUtils.AllLowercase))
+ self.assertEqual(QgsStringUtils.capitalize('', QgsStringUtils.AllLowercase), '')
+ self.assertEqual(QgsStringUtils.capitalize('testing 123', QgsStringUtils.AllLowercase), 'testing 123')
+ self.assertEqual(QgsStringUtils.capitalize(' tESTinG abc ', QgsStringUtils.AllLowercase),
+ ' testing abc ')
+ self.assertEqual(QgsStringUtils.capitalize(' TESTING ABC', QgsStringUtils.AllLowercase), ' testing abc')
+
+ def testCapitalizeFirst(self):
+ """ test capitalize first """
+ self.assertFalse(QgsStringUtils.capitalize(None, QgsStringUtils.ForceFirstLetterToCapital))
+ self.assertEqual(QgsStringUtils.capitalize('', QgsStringUtils.ForceFirstLetterToCapital), '')
+ self.assertEqual(QgsStringUtils.capitalize('testing 123', QgsStringUtils.ForceFirstLetterToCapital), 'Testing 123')
+ self.assertEqual(QgsStringUtils.capitalize('testing', QgsStringUtils.ForceFirstLetterToCapital),
+ 'Testing')
+ self.assertEqual(QgsStringUtils.capitalize('Testing', QgsStringUtils.ForceFirstLetterToCapital),
+ 'Testing')
+ self.assertEqual(QgsStringUtils.capitalize('TESTING', QgsStringUtils.ForceFirstLetterToCapital),
+ 'TESTING')
+ self.assertEqual(QgsStringUtils.capitalize(' tESTinG abc ', QgsStringUtils.ForceFirstLetterToCapital),
+ ' TESTinG Abc ')
+ self.assertEqual(QgsStringUtils.capitalize(' TESTING ABC', QgsStringUtils.ForceFirstLetterToCapital), ' TESTING ABC')
+ self.assertEqual(QgsStringUtils.capitalize(' testing abc', QgsStringUtils.ForceFirstLetterToCapital),
+ ' Testing Abc')
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/src/python/test_qgstabwidget.py b/tests/src/python/test_qgstabwidget.py
new file mode 100644
index 0000000..fb1b2ec
--- /dev/null
+++ b/tests/src/python/test_qgstabwidget.py
@@ -0,0 +1,88 @@
+# -*- coding: utf-8 -*-
+'''
+test_qgstabwidget.py
+ --------------------------------------
+ Date : September 2016
+ Copyright : (C) 2016 Matthias Kuhn
+ email : matthias at opengis.ch
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+'''
+
+import qgis # NOQA
+
+from qgis.testing import unittest, start_app
+from qgis.gui import QgsTabWidget
+from qgis.PyQt.QtWidgets import QWidget
+
+start_app()
+
+
+class TestQgsTabWidget(unittest.TestCase):
+
+ def setUp(self):
+ """Run before each test."""
+ pass
+
+ def tearDown(self):
+ """Run after each test."""
+ pass
+
+ def testQgsTabWidget(self):
+ tabWidget = QgsTabWidget()
+
+ wdg1 = QWidget()
+ wdg2 = QWidget()
+ wdg3 = QWidget()
+ wdg4 = QWidget()
+
+ tabWidget.addTab(wdg1, '1')
+ tabWidget.addTab(wdg2, '2')
+ tabWidget.addTab(wdg3, '3')
+
+ tabWidget.hideTab(wdg2)
+ self.assertEquals(tabWidget.count(), 2)
+ tabWidget.showTab(wdg2)
+ self.assertEquals(tabWidget.count(), 3)
+
+ self.assertEquals(tabWidget.tabText(0), '1')
+ self.assertEquals(tabWidget.tabText(1), '2')
+ self.assertEquals(tabWidget.tabText(2), '3')
+
+ tabWidget.hideTab(wdg2)
+ tabWidget.removeTab(1)
+ self.assertEquals(tabWidget.tabText(0), '1')
+ tabWidget.showTab(wdg2)
+ self.assertEquals(tabWidget.tabText(1), '2')
+ self.assertEquals(tabWidget.count(), 2)
+
+ # Show an already visible tab
+ tabWidget.showTab(wdg2)
+ self.assertEquals(tabWidget.count(), 2)
+
+ # Hide twice
+ tabWidget.hideTab(wdg2)
+ self.assertEquals(tabWidget.count(), 1)
+ tabWidget.hideTab(wdg2)
+ self.assertEquals(tabWidget.count(), 1)
+
+ tabWidget.hideTab(wdg1)
+ self.assertEquals(tabWidget.count(), 0)
+
+ tabWidget.showTab(wdg1)
+ tabWidget.showTab(wdg2)
+ self.assertEquals(tabWidget.count(), 2)
+
+ tabWidget.removeTab(0)
+ self.assertEquals(tabWidget.count(), 1)
+ tabWidget.hideTab(wdg2)
+ self.assertEquals(tabWidget.count(), 0)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/src/python/test_qgsvectorlayer.py b/tests/src/python/test_qgsvectorlayer.py
index c817981..f3300a2 100644
--- a/tests/src/python/test_qgsvectorlayer.py
+++ b/tests/src/python/test_qgsvectorlayer.py
@@ -18,6 +18,7 @@ import os
from qgis.PyQt.QtCore import QVariant
from qgis.PyQt.QtGui import QPainter
+from qgis.PyQt.QtXml import (QDomDocument, QDomElement)
from qgis.core import (QGis,
QgsVectorLayer,
@@ -35,7 +36,11 @@ from qgis.core import (QGis,
QgsCoordinateReferenceSystem,
QgsProject,
QgsUnitTypes,
- QgsAggregateCalculator)
+ QgsAggregateCalculator,
+ QgsPointV2,
+ QgsExpressionContext,
+ QgsExpressionContextScope,
+ QgsExpressionContextUtils)
from qgis.testing import start_app, unittest
from utilities import unitTestDataPath
start_app()
@@ -1028,6 +1033,16 @@ class TestQgsVectorLayer(unittest.TestCase):
#layer.undoStack().redo()
#checkFieldNames(['fldint'])
+ def test_RenameExpressionField(self):
+ layer = createLayerWithOnePoint()
+ exp_field_idx = layer.addExpressionField('1+1', QgsField('math_is_hard', QVariant.Int))
+
+ #rename and check
+ self.assertTrue(layer.renameAttribute(exp_field_idx, 'renamed'))
+ self.assertEqual(layer.fields()[exp_field_idx].name(), 'renamed')
+ f = next(layer.getFeatures())
+ self.assertEqual(f.fields()[exp_field_idx].name(), 'renamed')
+
def test_fields(self):
layer = createLayerWithOnePoint()
@@ -1455,6 +1470,204 @@ class TestQgsVectorLayer(unittest.TestCase):
self.assertTrue(self.rendererChanged)
self.assertEqual(layer.rendererV2(), r)
+ def testGetSetAliases(self):
+ """ test getting and setting aliases """
+ layer = createLayerWithOnePoint()
+
+ self.assertFalse(layer.attributeAlias(0))
+ self.assertFalse(layer.attributeAlias(1))
+ self.assertFalse(layer.attributeAlias(2))
+
+ layer.addAttributeAlias(0, "test")
+ self.assertEqual(layer.attributeAlias(0), "test")
+ self.assertFalse(layer.attributeAlias(1))
+ self.assertFalse(layer.attributeAlias(2))
+ self.assertEqual(layer.fields().at(0).alias(), "test")
+
+ layer.addAttributeAlias(1, "test2")
+ self.assertEqual(layer.attributeAlias(0), "test")
+ self.assertEqual(layer.attributeAlias(1), "test2")
+ self.assertFalse(layer.attributeAlias(2))
+ self.assertEqual(layer.fields().at(0).alias(), "test")
+ self.assertEqual(layer.fields().at(1).alias(), "test2")
+
+ layer.addAttributeAlias(1, None)
+ self.assertEqual(layer.attributeAlias(0), "test")
+ self.assertFalse(layer.attributeAlias(1))
+ self.assertFalse(layer.attributeAlias(2))
+ self.assertEqual(layer.fields().at(0).alias(), "test")
+ self.assertFalse(layer.fields().at(1).alias())
+
+ layer.remAttributeAlias(0)
+ self.assertFalse(layer.attributeAlias(0))
+ self.assertFalse(layer.attributeAlias(1))
+ self.assertFalse(layer.attributeAlias(2))
+ self.assertFalse(layer.fields().at(0).alias())
+ self.assertFalse(layer.fields().at(1).alias())
+
+ def testSaveRestoreAliases(self):
+ """ test saving and restoring aliases from xml"""
+ layer = createLayerWithOnePoint()
+
+ # no default expressions
+ doc = QDomDocument("testdoc")
+ elem = doc.createElement("maplayer")
+ self.assertTrue(layer.writeXml(elem, doc))
+
+ layer2 = createLayerWithOnePoint()
+ self.assertTrue(layer2.readXml(elem))
+ self.assertFalse(layer2.attributeAlias(0))
+ self.assertFalse(layer2.attributeAlias(1))
+
+ # set some aliases
+ layer.addAttributeAlias(0, "test")
+ layer.addAttributeAlias(1, "test2")
+
+ doc = QDomDocument("testdoc")
+ elem = doc.createElement("maplayer")
+ self.assertTrue(layer.writeXml(elem, doc))
+
+ layer3 = createLayerWithOnePoint()
+ self.assertTrue(layer3.readXml(elem))
+ self.assertEqual(layer3.attributeAlias(0), "test")
+ self.assertEqual(layer3.attributeAlias(1), "test2")
+ self.assertEqual(layer3.fields().at(0).alias(), "test")
+ self.assertEqual(layer3.fields().at(1).alias(), "test2")
+
+ def testGetSetDefaults(self):
+ """ test getting and setting default expressions """
+ layer = createLayerWithOnePoint()
+
+ self.assertFalse(layer.defaultValueExpression(0))
+ self.assertFalse(layer.defaultValueExpression(1))
+ self.assertFalse(layer.defaultValueExpression(2))
+
+ layer.setDefaultValueExpression(0, "'test'")
+ self.assertEqual(layer.defaultValueExpression(0), "'test'")
+ self.assertFalse(layer.defaultValueExpression(1))
+ self.assertFalse(layer.defaultValueExpression(2))
+ self.assertEqual(layer.fields().at(0).defaultValueExpression(), "'test'")
+
+ layer.setDefaultValueExpression(1, "2+2")
+ self.assertEqual(layer.defaultValueExpression(0), "'test'")
+ self.assertEqual(layer.defaultValueExpression(1), "2+2")
+ self.assertFalse(layer.defaultValueExpression(2))
+ self.assertEqual(layer.fields().at(0).defaultValueExpression(), "'test'")
+ self.assertEqual(layer.fields().at(1).defaultValueExpression(), "2+2")
+
+ def testSaveRestoreDefaults(self):
+ """ test saving and restoring default expressions from xml"""
+ layer = createLayerWithOnePoint()
+
+ # no default expressions
+ doc = QDomDocument("testdoc")
+ elem = doc.createElement("maplayer")
+ self.assertTrue(layer.writeXml(elem, doc))
+
+ layer2 = createLayerWithOnePoint()
+ self.assertTrue(layer2.readXml(elem))
+ self.assertFalse(layer2.defaultValueExpression(0))
+ self.assertFalse(layer2.defaultValueExpression(1))
+
+ # set some default expressions
+ layer.setDefaultValueExpression(0, "'test'")
+ layer.setDefaultValueExpression(1, "2+2")
+
+ doc = QDomDocument("testdoc")
+ elem = doc.createElement("maplayer")
+ self.assertTrue(layer.writeXml(elem, doc))
+
+ layer3 = createLayerWithOnePoint()
+ self.assertTrue(layer3.readXml(elem))
+ self.assertEqual(layer3.defaultValueExpression(0), "'test'")
+ self.assertEqual(layer3.defaultValueExpression(1), "2+2")
+ self.assertEqual(layer3.fields().at(0).defaultValueExpression(), "'test'")
+ self.assertEqual(layer3.fields().at(1).defaultValueExpression(), "2+2")
+
+ def testEvaluatingDefaultExpressions(self):
+ """ tests calculation of default values"""
+ layer = createLayerWithOnePoint()
+ layer.setDefaultValueExpression(0, "'test'")
+ layer.setDefaultValueExpression(1, "2+2")
+ self.assertEqual(layer.defaultValue(0), 'test')
+ self.assertEqual(layer.defaultValue(1), 4)
+
+ # using feature
+ layer.setDefaultValueExpression(1, '$id * 2')
+ feature = QgsFeature(4)
+ feature.setValid(True)
+ feature.setFields(layer.fields())
+ # no feature:
+ self.assertFalse(layer.defaultValue(1))
+ # with feature:
+ self.assertEqual(layer.defaultValue(0, feature), 'test')
+ self.assertEqual(layer.defaultValue(1, feature), 8)
+
+ # using feature geometry
+ layer.setDefaultValueExpression(1, '$x * 2')
+ feature.setGeometry(QgsGeometry(QgsPointV2(6, 7)))
+ self.assertEqual(layer.defaultValue(1, feature), 12)
+
+ # using contexts
+ scope = QgsExpressionContextScope()
+ scope.setVariable('var1', 16)
+ context = QgsExpressionContext()
+ context.appendScope(scope)
+ layer.setDefaultValueExpression(1, '$id + @var1')
+ self.assertEqual(layer.defaultValue(1, feature, context), 20)
+
+ # if no scope passed, should use a default constructed one including layer variables
+ QgsExpressionContextUtils.setLayerVariable(layer, 'var2', 4)
+ QgsExpressionContextUtils.setProjectVariable('var3', 8)
+ layer.setDefaultValueExpression(1, 'to_int(@var2) + to_int(@var3) + $id')
+ self.assertEqual(layer.defaultValue(1, feature), 16)
+
+ # bad expression
+ layer.setDefaultValueExpression(1, 'not a valid expression')
+ self.assertFalse(layer.defaultValue(1))
+
+ def testGetFeatureLimitWithEdits(self):
+ """ test getting features with a limit, when edits are present """
+ layer = createLayerWithOnePoint()
+ # now has one feature with id 0
+
+ pr = layer.dataProvider()
+
+ f1 = QgsFeature(1)
+ f1.setAttributes(["test", 3])
+ f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(300, 200)))
+ f2 = QgsFeature(2)
+ f2.setAttributes(["test", 3])
+ f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
+ f3 = QgsFeature(3)
+ f3.setAttributes(["test", 3])
+ f3.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
+ self.assertTrue(pr.addFeatures([f1, f2, f3]))
+
+ req = QgsFeatureRequest().setLimit(2)
+ self.assertEqual(len(list(layer.getFeatures(req))), 2)
+
+ # now delete feature f1
+ layer.startEditing()
+ self.assertTrue(layer.deleteFeature(1))
+ req = QgsFeatureRequest().setLimit(2)
+ self.assertEqual(len(list(layer.getFeatures(req))), 2)
+ layer.rollBack()
+
+ # change an attribute value required by filter
+ layer.startEditing()
+ req = QgsFeatureRequest().setFilterExpression('fldint=3').setLimit(2)
+ self.assertTrue(layer.changeAttributeValue(2, 1, 4))
+ self.assertEqual(len(list(layer.getFeatures(req))), 2)
+ layer.rollBack()
+
+ layer.startEditing()
+ req = QgsFeatureRequest().setFilterRect(QgsRectangle(50, 100, 150, 300)).setLimit(2)
+ self.assertTrue(layer.changeGeometry(2, QgsGeometry.fromPoint(QgsPoint(500, 600))))
+ self.assertEqual(len(list(layer.getFeatures(req))), 2)
+ layer.rollBack()
+
+
# TODO:
# - fetch rect: feat with changed geometry: 1. in rect, 2. out of rect
# - more join tests
diff --git a/tests/src/python/utilities.py b/tests/src/python/utilities.py
index c950265..4189ca3 100644
--- a/tests/src/python/utilities.py
+++ b/tests/src/python/utilities.py
@@ -18,6 +18,10 @@ import sys
import glob
import platform
import tempfile
+try:
+ from urllib2 import urlopen, HTTPError
+except ImportError:
+ from urllib.request import urlopen, HTTPError
from qgis.PyQt.QtCore import QDir
@@ -530,12 +534,15 @@ class DoxygenParser():
# test for "added in QGIS xxx" string
d = e.find('detaileddescription')
found_version_added = False
- if d.find('para'):
- for s in d.find('para').getiterator('simplesect'):
+ for para in d.getiterator('para'):
+ for s in para.getiterator('simplesect'):
if s.get('kind') == 'note':
for p in s.getiterator('para'):
if p.text and p.text.lower().startswith('added in'):
found_version_added = True
+ break
+ if found_version_added:
+ break
return documentable_members, documented_members, undocumented_members, bindable_members, found_version_added
@@ -812,3 +819,22 @@ class DoxygenParser():
if doc is not None and list(doc):
return True
return False
+
+
+def waitServer(url, timeout=10):
+ """ Wait for a server to be online and to respond
+ HTTP errors are ignored
+ @param timeout: in seconds
+ @return: True of False
+ """
+ from time import time as now
+ end = now() + timeout
+ while True:
+ try:
+ urlopen(url, timeout=1)
+ return True
+ except HTTPError:
+ return True
+ except Exception as e:
+ if now() > end:
+ return False
diff --git a/tests/testdata/control_images/composer_paper/expected_composerpaper_markerborder/expected_composerpaper_markerborder_mask.png b/tests/testdata/control_images/composer_paper/expected_composerpaper_markerborder/expected_composerpaper_markerborder_mask.png
index 9f7c30a..c56c2cf 100644
Binary files a/tests/testdata/control_images/composer_paper/expected_composerpaper_markerborder/expected_composerpaper_markerborder_mask.png and b/tests/testdata/control_images/composer_paper/expected_composerpaper_markerborder/expected_composerpaper_markerborder_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas/sp_letter_spacing/sp_letter_spacing_mask.png b/tests/testdata/control_images/expected_pal_canvas/sp_letter_spacing/sp_letter_spacing_mask.png
index c3493bd..7afa1ab 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas/sp_letter_spacing/sp_letter_spacing_mask.png and b/tests/testdata/control_images/expected_pal_canvas/sp_letter_spacing/sp_letter_spacing_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas/sp_word_spacing/sp_word_spacing_mask.png b/tests/testdata/control_images/expected_pal_canvas/sp_word_spacing/sp_word_spacing_mask.png
index f7db90a..e13a958 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas/sp_word_spacing/sp_word_spacing_mask.png and b/tests/testdata/control_images/expected_pal_canvas/sp_word_spacing/sp_word_spacing_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_above/sp_curved_placement_above.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_above/sp_curved_placement_above.png
index 08aecbf..eaf368d 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_above/sp_curved_placement_above.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_above/sp_curved_placement_above.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_above/sp_curved_placement_above_mask.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_above/sp_curved_placement_above_mask.png
index 015aa4b..b4d7d50 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_above/sp_curved_placement_above_mask.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_above/sp_curved_placement_above_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_below/sp_curved_placement_below.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_below/sp_curved_placement_below.png
index c036e7ec..e6a6c21 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_below/sp_curved_placement_below.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_below/sp_curved_placement_below.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_below/sp_curved_placement_below_mask.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_below/sp_curved_placement_below_mask.png
index 57d1b24..1753ad1 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_below/sp_curved_placement_below_mask.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_below/sp_curved_placement_below_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_online/sp_curved_placement_online.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_online/sp_curved_placement_online.png
index a60b0bb..1ce2c61 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_online/sp_curved_placement_online.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_online/sp_curved_placement_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_online/sp_curved_placement_online_mask.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_online/sp_curved_placement_online_mask.png
index c41b629..972938d 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_online/sp_curved_placement_online_mask.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_curved_placement_online/sp_curved_placement_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation.png
index 9b19628..2091321 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation_mask.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation_mask.png
index 8fd3490..6be09aa 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation_mask.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation.png
index 061bd3a..d16f117 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation_mask.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation_mask.png
index 82921e0..1b95faf 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation_mask.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation.png
index 061bd3a..d16f117 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation_mask.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation_mask.png
index 4e1fe22..e5f0ac9 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation_mask.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation.png
index 9b19628..2091321 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation_mask.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation_mask.png
index 6a58ceb..bda5090 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation_mask.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_online/sp_line_placement_online.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_online/sp_line_placement_online.png
index 449ae4d..5f7fdd1 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_online/sp_line_placement_online.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_online/sp_line_placement_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_online/sp_line_placement_online_mask.png b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_online/sp_line_placement_online_mask.png
index 721a2f7..2033d45 100644
Binary files a/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_online/sp_line_placement_online_mask.png and b/tests/testdata/control_images/expected_pal_canvas_line/sp_line_placement_online/sp_line_placement_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer/sp_img_letter_spacing/sp_img_letter_spacing_mask.png b/tests/testdata/control_images/expected_pal_composer/sp_img_letter_spacing/sp_img_letter_spacing_mask.png
index 91577fd..8ee736e 100644
Binary files a/tests/testdata/control_images/expected_pal_composer/sp_img_letter_spacing/sp_img_letter_spacing_mask.png and b/tests/testdata/control_images/expected_pal_composer/sp_img_letter_spacing/sp_img_letter_spacing_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer/sp_img_word_spacing/sp_img_word_spacing_mask.png b/tests/testdata/control_images/expected_pal_composer/sp_img_word_spacing/sp_img_word_spacing_mask.png
index f60d864..176d985 100644
Binary files a/tests/testdata/control_images/expected_pal_composer/sp_img_word_spacing/sp_img_word_spacing_mask.png and b/tests/testdata/control_images/expected_pal_composer/sp_img_word_spacing/sp_img_word_spacing_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_above/sp_img_curved_placement_above.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_above/sp_img_curved_placement_above.png
index 08aecbf..eaf368d 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_above/sp_img_curved_placement_above.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_above/sp_img_curved_placement_above.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_above/sp_img_curved_placement_above_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_above/sp_img_curved_placement_above_mask.png
index 6d4e6e1..8ee8456 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_above/sp_img_curved_placement_above_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_above/sp_img_curved_placement_above_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_below/sp_img_curved_placement_below.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_below/sp_img_curved_placement_below.png
index c036e7ec..e6a6c21 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_below/sp_img_curved_placement_below.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_below/sp_img_curved_placement_below.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_below/sp_img_curved_placement_below_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_below/sp_img_curved_placement_below_mask.png
index 4579f23..55101b4 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_below/sp_img_curved_placement_below_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_below/sp_img_curved_placement_below_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_online/sp_img_curved_placement_online.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_online/sp_img_curved_placement_online.png
index a60b0bb..1ce2c61 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_online/sp_img_curved_placement_online.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_online/sp_img_curved_placement_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_online/sp_img_curved_placement_online_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_online/sp_img_curved_placement_online_mask.png
index 8b38ff0..32a5030 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_online/sp_img_curved_placement_online_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_curved_placement_online/sp_img_curved_placement_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_line_orientation/sp_img_line_placement_above_line_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_line_orientation/sp_img_line_placement_above_line_orientation.png
index 9b19628..2091321 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_line_orientation/sp_img_line_placement_above_line_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_line_orientation/sp_img_line_placement_above_line_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_line_orientation/sp_img_line_placement_above_line_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_line_orientation/sp_img_line_placement_above_line_orientation_mask.png
index ed948bd..f1d8e61 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_line_orientation/sp_img_line_placement_above_line_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_line_orientation/sp_img_line_placement_above_line_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_map_orientation/sp_img_line_placement_above_map_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_map_orientation/sp_img_line_placement_above_map_orientation.png
index 061bd3a..d16f117 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_map_orientation/sp_img_line_placement_above_map_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_map_orientation/sp_img_line_placement_above_map_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_map_orientation/sp_img_line_placement_above_map_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_map_orientation/sp_img_line_placement_above_map_orientation_mask.png
index 9f0bbe7..013719c 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_map_orientation/sp_img_line_placement_above_map_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_above_map_orientation/sp_img_line_placement_above_map_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_line_orientation/sp_img_line_placement_below_line_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_line_orientation/sp_img_line_placement_below_line_orientation.png
index 061bd3a..d16f117 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_line_orientation/sp_img_line_placement_below_line_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_line_orientation/sp_img_line_placement_below_line_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_line_orientation/sp_img_line_placement_below_line_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_line_orientation/sp_img_line_placement_below_line_orientation_mask.png
index 8981253..133f1b1 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_line_orientation/sp_img_line_placement_below_line_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_line_orientation/sp_img_line_placement_below_line_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_map_orientation/sp_img_line_placement_below_map_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_map_orientation/sp_img_line_placement_below_map_orientation.png
index 9b19628..2091321 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_map_orientation/sp_img_line_placement_below_map_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_map_orientation/sp_img_line_placement_below_map_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_map_orientation/sp_img_line_placement_below_map_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_map_orientation/sp_img_line_placement_below_map_orientation_mask.png
index a879564..6c47ca5 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_map_orientation/sp_img_line_placement_below_map_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_below_map_orientation/sp_img_line_placement_below_map_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_online/sp_img_line_placement_online.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_online/sp_img_line_placement_online.png
index 449ae4d..5f7fdd1 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_online/sp_img_line_placement_online.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_online/sp_img_line_placement_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_online/sp_img_line_placement_online_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_online/sp_img_line_placement_online_mask.png
index bd31c4a..9103cb0 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_online/sp_img_line_placement_online_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_img_line_placement_online/sp_img_line_placement_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_above/sp_pdf_curved_placement_above.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_above/sp_pdf_curved_placement_above.png
index fd53058..770154d 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_above/sp_pdf_curved_placement_above.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_above/sp_pdf_curved_placement_above.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_above/sp_pdf_curved_placement_above_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_above/sp_pdf_curved_placement_above_mask.png
index d2bd597..563e849 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_above/sp_pdf_curved_placement_above_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_above/sp_pdf_curved_placement_above_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_below/sp_pdf_curved_placement_below.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_below/sp_pdf_curved_placement_below.png
index 383d378..50a2849 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_below/sp_pdf_curved_placement_below.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_below/sp_pdf_curved_placement_below.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_below/sp_pdf_curved_placement_below_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_below/sp_pdf_curved_placement_below_mask.png
index 5a3a681..113e265 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_below/sp_pdf_curved_placement_below_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_below/sp_pdf_curved_placement_below_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_online/sp_pdf_curved_placement_online.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_online/sp_pdf_curved_placement_online.png
index 9c44172..73d8a68 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_online/sp_pdf_curved_placement_online.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_online/sp_pdf_curved_placement_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_online/sp_pdf_curved_placement_online_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_online/sp_pdf_curved_placement_online_mask.png
index 13363c2..8040119 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_online/sp_pdf_curved_placement_online_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_curved_placement_online/sp_pdf_curved_placement_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_line_orientation/sp_pdf_line_placement_above_line_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_line_orientation/sp_pdf_line_placement_above_line_orientation.png
index 62394fa..228ede1 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_line_orientation/sp_pdf_line_placement_above_line_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_line_orientation/sp_pdf_line_placement_above_line_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_line_orientation/sp_pdf_line_placement_above_line_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_line_orientation/sp_pdf_line_placement_above_line_orientation_mask.png
index b14e257..1433eab 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_line_orientation/sp_pdf_line_placement_above_line_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_line_orientation/sp_pdf_line_placement_above_line_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_map_orientation/sp_pdf_line_placement_above_map_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_map_orientation/sp_pdf_line_placement_above_map_orientation.png
index 870d680..8744921 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_map_orientation/sp_pdf_line_placement_above_map_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_map_orientation/sp_pdf_line_placement_above_map_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_map_orientation/sp_pdf_line_placement_above_map_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_map_orientation/sp_pdf_line_placement_above_map_orientation_mask.png
index f7a6819..9098e83 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_map_orientation/sp_pdf_line_placement_above_map_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_above_map_orientation/sp_pdf_line_placement_above_map_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_line_orientation/sp_pdf_line_placement_below_line_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_line_orientation/sp_pdf_line_placement_below_line_orientation.png
index 870d680..8744921 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_line_orientation/sp_pdf_line_placement_below_line_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_line_orientation/sp_pdf_line_placement_below_line_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_line_orientation/sp_pdf_line_placement_below_line_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_line_orientation/sp_pdf_line_placement_below_line_orientation_mask.png
index f7a6819..3851364 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_line_orientation/sp_pdf_line_placement_below_line_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_line_orientation/sp_pdf_line_placement_below_line_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_map_orientation/sp_pdf_line_placement_below_map_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_map_orientation/sp_pdf_line_placement_below_map_orientation.png
index 62394fa..228ede1 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_map_orientation/sp_pdf_line_placement_below_map_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_map_orientation/sp_pdf_line_placement_below_map_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_map_orientation/sp_pdf_line_placement_below_map_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_map_orientation/sp_pdf_line_placement_below_map_orientation_mask.png
index b14e257..4007eaa 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_map_orientation/sp_pdf_line_placement_below_map_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_below_map_orientation/sp_pdf_line_placement_below_map_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_online/sp_pdf_line_placement_online.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_online/sp_pdf_line_placement_online.png
index 203181b..f0a590c 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_online/sp_pdf_line_placement_online.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_online/sp_pdf_line_placement_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_online/sp_pdf_line_placement_online_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_online/sp_pdf_line_placement_online_mask.png
index 59a2149..7bdf047 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_online/sp_pdf_line_placement_online_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_pdf_line_placement_online/sp_pdf_line_placement_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_above/sp_svg_curved_placement_above.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_above/sp_svg_curved_placement_above.png
index 0360eb4..92fac11 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_above/sp_svg_curved_placement_above.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_above/sp_svg_curved_placement_above.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_above/sp_svg_curved_placement_above_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_above/sp_svg_curved_placement_above_mask.png
index 7daa9d8..b0b52fc 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_above/sp_svg_curved_placement_above_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_above/sp_svg_curved_placement_above_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_below/sp_svg_curved_placement_below.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_below/sp_svg_curved_placement_below.png
index 2d3db48..e5637c8 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_below/sp_svg_curved_placement_below.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_below/sp_svg_curved_placement_below.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_below/sp_svg_curved_placement_below_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_below/sp_svg_curved_placement_below_mask.png
index 6821d03..ad72e64 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_below/sp_svg_curved_placement_below_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_below/sp_svg_curved_placement_below_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_online/sp_svg_curved_placement_online.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_online/sp_svg_curved_placement_online.png
index 693293b..95abd04 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_online/sp_svg_curved_placement_online.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_online/sp_svg_curved_placement_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_online/sp_svg_curved_placement_online_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_online/sp_svg_curved_placement_online_mask.png
index 3511a94..68f73c7 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_online/sp_svg_curved_placement_online_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_curved_placement_online/sp_svg_curved_placement_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_line_orientation/sp_svg_line_placement_above_line_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_line_orientation/sp_svg_line_placement_above_line_orientation.png
index 30e13a5..30e2b82 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_line_orientation/sp_svg_line_placement_above_line_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_line_orientation/sp_svg_line_placement_above_line_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_line_orientation/sp_svg_line_placement_above_line_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_line_orientation/sp_svg_line_placement_above_line_orientation_mask.png
index c538861..5ceca29 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_line_orientation/sp_svg_line_placement_above_line_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_line_orientation/sp_svg_line_placement_above_line_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_map_orientation/sp_svg_line_placement_above_map_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_map_orientation/sp_svg_line_placement_above_map_orientation.png
index e9f1883..36d35a7 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_map_orientation/sp_svg_line_placement_above_map_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_map_orientation/sp_svg_line_placement_above_map_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_map_orientation/sp_svg_line_placement_above_map_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_map_orientation/sp_svg_line_placement_above_map_orientation_mask.png
index 6b055a0..2e3d235 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_map_orientation/sp_svg_line_placement_above_map_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_above_map_orientation/sp_svg_line_placement_above_map_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_line_orientation/sp_svg_line_placement_below_line_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_line_orientation/sp_svg_line_placement_below_line_orientation.png
index e9f1883..36d35a7 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_line_orientation/sp_svg_line_placement_below_line_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_line_orientation/sp_svg_line_placement_below_line_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_line_orientation/sp_svg_line_placement_below_line_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_line_orientation/sp_svg_line_placement_below_line_orientation_mask.png
index 911e465..e3783d2 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_line_orientation/sp_svg_line_placement_below_line_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_line_orientation/sp_svg_line_placement_below_line_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_map_orientation/sp_svg_line_placement_below_map_orientation.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_map_orientation/sp_svg_line_placement_below_map_orientation.png
index 30e13a5..30e2b82 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_map_orientation/sp_svg_line_placement_below_map_orientation.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_map_orientation/sp_svg_line_placement_below_map_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_map_orientation/sp_svg_line_placement_below_map_orientation_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_map_orientation/sp_svg_line_placement_below_map_orientation_mask.png
index 7787aed..db5b003 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_map_orientation/sp_svg_line_placement_below_map_orientation_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_below_map_orientation/sp_svg_line_placement_below_map_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_online/sp_svg_line_placement_online.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_online/sp_svg_line_placement_online.png
index efdbefd..1aebaf7 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_online/sp_svg_line_placement_online.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_online/sp_svg_line_placement_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_online/sp_svg_line_placement_online_mask.png b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_online/sp_svg_line_placement_online_mask.png
index f9fc805..1721692 100644
Binary files a/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_online/sp_svg_line_placement_online_mask.png and b/tests/testdata/control_images/expected_pal_composer_line/sp_svg_line_placement_online/sp_svg_line_placement_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_label_line_avoid_jaggy/sp_label_line_avoid_jaggy.png b/tests/testdata/control_images/expected_pal_placement/sp_label_line_avoid_jaggy/sp_label_line_avoid_jaggy.png
new file mode 100644
index 0000000..66de17c
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_label_line_avoid_jaggy/sp_label_line_avoid_jaggy.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_label_line_avoid_jaggy/sp_label_line_avoid_jaggy_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_label_line_avoid_jaggy/sp_label_line_avoid_jaggy_mask.png
new file mode 100644
index 0000000..4258f1e
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_label_line_avoid_jaggy/sp_label_line_avoid_jaggy_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_label_line_over_small_angles/sp_label_line_over_small_angles.png b/tests/testdata/control_images/expected_pal_placement/sp_label_line_over_small_angles/sp_label_line_over_small_angles.png
new file mode 100644
index 0000000..868505d
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_label_line_over_small_angles/sp_label_line_over_small_angles.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_label_line_over_small_angles/sp_label_line_over_small_angles_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_label_line_over_small_angles/sp_label_line_over_small_angles_mask.png
new file mode 100644
index 0000000..f1d862c
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_label_line_over_small_angles/sp_label_line_over_small_angles_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_label_line_toward_center/sp_label_line_toward_center.png b/tests/testdata/control_images/expected_pal_placement/sp_label_line_toward_center/sp_label_line_toward_center.png
new file mode 100644
index 0000000..13bb1ee
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_label_line_toward_center/sp_label_line_toward_center.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_label_line_toward_center/sp_label_line_toward_center_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_label_line_toward_center/sp_label_line_toward_center_mask.png
new file mode 100644
index 0000000..fc2b3a2
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_label_line_toward_center/sp_label_line_toward_center_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_point_placement_around_obstacle_large_symbol/sp_point_placement_around_obstacle_large_symbol_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_point_placement_around_obstacle_large_symbol/sp_point_placement_around_obstacle_large_symbol_mask.png
index 5c47597..162a909 100644
Binary files a/tests/testdata/control_images/expected_pal_placement/sp_point_placement_around_obstacle_large_symbol/sp_point_placement_around_obstacle_large_symbol_mask.png and b/tests/testdata/control_images/expected_pal_placement/sp_point_placement_around_obstacle_large_symbol/sp_point_placement_around_obstacle_large_symbol_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_perimeter/sp_polygon_placement_perimeter.png b/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_perimeter/sp_polygon_placement_perimeter.png
new file mode 100644
index 0000000..00ceee3
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_perimeter/sp_polygon_placement_perimeter.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_perimeter/sp_polygon_placement_perimeter_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_perimeter/sp_polygon_placement_perimeter_mask.png
new file mode 100644
index 0000000..34b0bf6
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_perimeter/sp_polygon_placement_perimeter_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_with_hole_and_point/sp_polygon_placement_with_hole_and_point_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_with_hole_and_point/sp_polygon_placement_with_hole_and_point_mask.png
index e44b218..e5883d4 100644
Binary files a/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_with_hole_and_point/sp_polygon_placement_with_hole_and_point_mask.png and b/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_with_hole_and_point/sp_polygon_placement_with_hole_and_point_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_below/sp_prefer_line_above_instead_of_below.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_below/sp_prefer_line_above_instead_of_below.png
new file mode 100644
index 0000000..c10e33e
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_below/sp_prefer_line_above_instead_of_below.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_below/sp_prefer_line_above_instead_of_below_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_below/sp_prefer_line_above_instead_of_below_mask.png
new file mode 100644
index 0000000..446817a
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_below/sp_prefer_line_above_instead_of_below_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_online/sp_prefer_line_above_instead_of_online.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_online/sp_prefer_line_above_instead_of_online.png
new file mode 100644
index 0000000..c10e33e
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_online/sp_prefer_line_above_instead_of_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_online/sp_prefer_line_above_instead_of_online_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_online/sp_prefer_line_above_instead_of_online_mask.png
new file mode 100644
index 0000000..d94d400
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_online/sp_prefer_line_above_instead_of_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_below_instead_of_online/sp_prefer_line_below_instead_of_online.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_below_instead_of_online/sp_prefer_line_below_instead_of_online.png
new file mode 100644
index 0000000..fef806e
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_below_instead_of_online/sp_prefer_line_below_instead_of_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_below_instead_of_online/sp_prefer_line_below_instead_of_online_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_below_instead_of_online/sp_prefer_line_below_instead_of_online_mask.png
new file mode 100644
index 0000000..a09bad6
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_below_instead_of_online/sp_prefer_line_below_instead_of_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_below/sp_prefer_line_curved_above_instead_of_below.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_below/sp_prefer_line_curved_above_instead_of_below.png
new file mode 100644
index 0000000..8edc793
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_below/sp_prefer_line_curved_above_instead_of_below.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_below/sp_prefer_line_curved_above_instead_of_below_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_below/sp_prefer_line_curved_above_instead_of_below_mask.png
new file mode 100644
index 0000000..48e669e
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_below/sp_prefer_line_curved_above_instead_of_below_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_online/sp_prefer_line_curved_above_instead_of_online.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_online/sp_prefer_line_curved_above_instead_of_online.png
new file mode 100644
index 0000000..8edc793
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_online/sp_prefer_line_curved_above_instead_of_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_online/sp_prefer_line_curved_above_instead_of_online_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_online/sp_prefer_line_curved_above_instead_of_online_mask.png
new file mode 100644
index 0000000..d328a95
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_above_instead_of_online/sp_prefer_line_curved_above_instead_of_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_below_instead_of_online/sp_prefer_line_curved_below_instead_of_online.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_below_instead_of_online/sp_prefer_line_curved_below_instead_of_online.png
new file mode 100644
index 0000000..017f2ef
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_below_instead_of_online/sp_prefer_line_curved_below_instead_of_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_below_instead_of_online/sp_prefer_line_curved_below_instead_of_online_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_below_instead_of_online/sp_prefer_line_curved_below_instead_of_online_mask.png
new file mode 100644
index 0000000..ee8e133
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_curved_below_instead_of_online/sp_prefer_line_curved_below_instead_of_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_longer_lines_over_shorter/sp_prefer_longer_lines_over_shorter.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_longer_lines_over_shorter/sp_prefer_longer_lines_over_shorter.png
new file mode 100644
index 0000000..763edda
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_longer_lines_over_shorter/sp_prefer_longer_lines_over_shorter.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_longer_lines_over_shorter/sp_prefer_longer_lines_over_shorter_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_longer_lines_over_shorter/sp_prefer_longer_lines_over_shorter_mask.png
new file mode 100644
index 0000000..051a1f5
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_longer_lines_over_shorter/sp_prefer_longer_lines_over_shorter_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_more_horizontal_lines/sp_prefer_more_horizontal_lines.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_more_horizontal_lines/sp_prefer_more_horizontal_lines.png
new file mode 100644
index 0000000..fc10a15
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_more_horizontal_lines/sp_prefer_more_horizontal_lines.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_more_horizontal_lines/sp_prefer_more_horizontal_lines_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_more_horizontal_lines/sp_prefer_more_horizontal_lines_mask.png
new file mode 100644
index 0000000..6e39f8e
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_prefer_more_horizontal_lines/sp_prefer_more_horizontal_lines_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_curvedperimeter_only_fit/sp_small_polygon_curvedperimeter_only_fit.png b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_curvedperimeter_only_fit/sp_small_polygon_curvedperimeter_only_fit.png
new file mode 100644
index 0000000..448e3fd
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_curvedperimeter_only_fit/sp_small_polygon_curvedperimeter_only_fit.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_curvedperimeter_only_fit/sp_small_polygon_curvedperimeter_only_fit_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_curvedperimeter_only_fit/sp_small_polygon_curvedperimeter_only_fit_mask.png
new file mode 100644
index 0000000..f0d6e9e
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_curvedperimeter_only_fit/sp_small_polygon_curvedperimeter_only_fit_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_over_point_only_fit/sp_small_polygon_over_point_only_fit.png b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_over_point_only_fit/sp_small_polygon_over_point_only_fit.png
new file mode 100644
index 0000000..448e3fd
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_over_point_only_fit/sp_small_polygon_over_point_only_fit.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_over_point_only_fit/sp_small_polygon_over_point_only_fit_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_over_point_only_fit/sp_small_polygon_over_point_only_fit_mask.png
new file mode 100644
index 0000000..52110bb
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_over_point_only_fit/sp_small_polygon_over_point_only_fit_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_perimeter_only_fit/sp_small_polygon_perimeter_only_fit.png b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_perimeter_only_fit/sp_small_polygon_perimeter_only_fit.png
new file mode 100644
index 0000000..448e3fd
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_perimeter_only_fit/sp_small_polygon_perimeter_only_fit.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_perimeter_only_fit/sp_small_polygon_perimeter_only_fit_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_perimeter_only_fit/sp_small_polygon_perimeter_only_fit_mask.png
new file mode 100644
index 0000000..579c385
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_perimeter_only_fit/sp_small_polygon_perimeter_only_fit_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_placement_perimeter/sp_small_polygon_placement_perimeter.png b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_placement_perimeter/sp_small_polygon_placement_perimeter.png
new file mode 100644
index 0000000..8dae494
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_placement_perimeter/sp_small_polygon_placement_perimeter.png differ
diff --git a/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_placement_perimeter/sp_small_polygon_placement_perimeter_mask.png b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_placement_perimeter/sp_small_polygon_placement_perimeter_mask.png
new file mode 100644
index 0000000..ba1244e
Binary files /dev/null and b/tests/testdata/control_images/expected_pal_placement/sp_small_polygon_placement_perimeter/sp_small_polygon_placement_perimeter_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_server/sp_letter_spacing/sp_letter_spacing_mask.png b/tests/testdata/control_images/expected_pal_server/sp_letter_spacing/sp_letter_spacing_mask.png
index 300ec88..3cfb8f8 100644
Binary files a/tests/testdata/control_images/expected_pal_server/sp_letter_spacing/sp_letter_spacing_mask.png and b/tests/testdata/control_images/expected_pal_server/sp_letter_spacing/sp_letter_spacing_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_server/sp_word_spacing/sp_word_spacing_mask.png b/tests/testdata/control_images/expected_pal_server/sp_word_spacing/sp_word_spacing_mask.png
index 091ec72..7540017 100644
Binary files a/tests/testdata/control_images/expected_pal_server/sp_word_spacing/sp_word_spacing_mask.png and b/tests/testdata/control_images/expected_pal_server/sp_word_spacing/sp_word_spacing_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_above/sp_curved_placement_above.png b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_above/sp_curved_placement_above.png
index b3dd3e2..8267a27 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_above/sp_curved_placement_above.png and b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_above/sp_curved_placement_above.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_above/sp_curved_placement_above_mask.png b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_above/sp_curved_placement_above_mask.png
index 8382fe3..081ee31 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_above/sp_curved_placement_above_mask.png and b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_above/sp_curved_placement_above_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_below/sp_curved_placement_below.png b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_below/sp_curved_placement_below.png
index abf8a8d..7d0f159 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_below/sp_curved_placement_below.png and b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_below/sp_curved_placement_below.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_below/sp_curved_placement_below_mask.png b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_below/sp_curved_placement_below_mask.png
index d3eaebd..629c5af 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_below/sp_curved_placement_below_mask.png and b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_below/sp_curved_placement_below_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_online/sp_curved_placement_online.png b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_online/sp_curved_placement_online.png
index 785ae18..4767a8f 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_online/sp_curved_placement_online.png and b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_online/sp_curved_placement_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_online/sp_curved_placement_online_mask.png b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_online/sp_curved_placement_online_mask.png
index 726c704..26ba3f6 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_online/sp_curved_placement_online_mask.png and b/tests/testdata/control_images/expected_pal_server_line/sp_curved_placement_online/sp_curved_placement_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation.png b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation.png
index 9b19628..604649f 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation.png and b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation_mask.png b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation_mask.png
index 00316d1..53d1c30 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation_mask.png and b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_line_orientation/sp_line_placement_above_line_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation.png b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation.png
index 061bd3a..b972291 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation.png and b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation_mask.png b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation_mask.png
index 140307c..e6aff5d 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation_mask.png and b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_above_map_orientation/sp_line_placement_above_map_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation.png b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation.png
index 061bd3a..b972291 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation.png and b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation_mask.png b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation_mask.png
index 140307c..be80f58 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation_mask.png and b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_line_orientation/sp_line_placement_below_line_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation.png b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation.png
index 9b19628..604649f 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation.png and b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation_mask.png b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation_mask.png
index 00316d1..f50f957 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation_mask.png and b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_below_map_orientation/sp_line_placement_below_map_orientation_mask.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_online/sp_line_placement_online.png b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_online/sp_line_placement_online.png
index 449ae4d..d2d2587 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_online/sp_line_placement_online.png and b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_online/sp_line_placement_online.png differ
diff --git a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_online/sp_line_placement_online_mask.png b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_online/sp_line_placement_online_mask.png
index a9faf77..97e94dd 100644
Binary files a/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_online/sp_line_placement_online_mask.png and b/tests/testdata/control_images/expected_pal_server_line/sp_line_placement_online/sp_line_placement_online_mask.png differ
diff --git a/tests/testdata/control_images/expected_vector_layertransparency/default/expected_vector_layertransparency_mask.png b/tests/testdata/control_images/expected_vector_layertransparency/default/expected_vector_layertransparency_mask.png
index 97a4ae9..16070fb 100644
Binary files a/tests/testdata/control_images/expected_vector_layertransparency/default/expected_vector_layertransparency_mask.png and b/tests/testdata/control_images/expected_vector_layertransparency/default/expected_vector_layertransparency_mask.png differ
diff --git a/tests/testdata/control_images/labelingenginev2/expected_labeling_basic/expected_labeling_basic.png b/tests/testdata/control_images/labelingenginev2/expected_labeling_basic/expected_labeling_basic.png
index cd79ce2..f40bc7e 100644
Binary files a/tests/testdata/control_images/labelingenginev2/expected_labeling_basic/expected_labeling_basic.png and b/tests/testdata/control_images/labelingenginev2/expected_labeling_basic/expected_labeling_basic.png differ
diff --git a/tests/testdata/control_images/labelingenginev2/expected_labeling_basic/expected_labeling_basic_mask.png b/tests/testdata/control_images/labelingenginev2/expected_labeling_basic/expected_labeling_basic_mask.png
index 3d2d470..b1027d3 100644
Binary files a/tests/testdata/control_images/labelingenginev2/expected_labeling_basic/expected_labeling_basic_mask.png and b/tests/testdata/control_images/labelingenginev2/expected_labeling_basic/expected_labeling_basic_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_3_by_2/expected_legend_3_by_2_mask.png b/tests/testdata/control_images/legend/expected_legend_3_by_2/expected_legend_3_by_2_mask.png
index 26a6e24..f109e11 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_3_by_2/expected_legend_3_by_2_mask.png and b/tests/testdata/control_images/legend/expected_legend_3_by_2/expected_legend_3_by_2_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_3_by_3/expected_legend_3_by_3_mask.png b/tests/testdata/control_images/legend/expected_legend_3_by_3/expected_legend_3_by_3_mask.png
index 619c13d..4bf649b 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_3_by_3/expected_legend_3_by_3_mask.png and b/tests/testdata/control_images/legend/expected_legend_3_by_3/expected_legend_3_by_3_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_4_by_2/expected_legend_4_by_2_mask.png b/tests/testdata/control_images/legend/expected_legend_4_by_2/expected_legend_4_by_2_mask.png
index 5f83169..6c728a4 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_4_by_2/expected_legend_4_by_2_mask.png and b/tests/testdata/control_images/legend/expected_legend_4_by_2/expected_legend_4_by_2_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_4_by_3/expected_legend_4_by_3_mask.png b/tests/testdata/control_images/legend/expected_legend_4_by_3/expected_legend_4_by_3_mask.png
index eb17139..8ffd9c4 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_4_by_3/expected_legend_4_by_3_mask.png and b/tests/testdata/control_images/legend/expected_legend_4_by_3/expected_legend_4_by_3_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_5_by_2/expected_legend_5_by_2_mask.png b/tests/testdata/control_images/legend/expected_legend_5_by_2/expected_legend_5_by_2_mask.png
index b7c9aa4..13e98d3 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_5_by_2/expected_legend_5_by_2_mask.png and b/tests/testdata/control_images/legend/expected_legend_5_by_2/expected_legend_5_by_2_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_5_by_3/expected_legend_5_by_3_mask.png b/tests/testdata/control_images/legend/expected_legend_5_by_3/expected_legend_5_by_3_mask.png
index 8fabd8d..9276166 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_5_by_3/expected_legend_5_by_3_mask.png and b/tests/testdata/control_images/legend/expected_legend_5_by_3/expected_legend_5_by_3_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_6_by_3/expected_legend_6_by_3_mask.png b/tests/testdata/control_images/legend/expected_legend_6_by_3/expected_legend_6_by_3_mask.png
index 0228bfc..12b69ac 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_6_by_3/expected_legend_6_by_3_mask.png and b/tests/testdata/control_images/legend/expected_legend_6_by_3/expected_legend_6_by_3_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_7_by_3/expected_legend_7_by_3_mask.png b/tests/testdata/control_images/legend/expected_legend_7_by_3/expected_legend_7_by_3_mask.png
index 63ef7e9..1a5ba7e 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_7_by_3/expected_legend_7_by_3_mask.png and b/tests/testdata/control_images/legend/expected_legend_7_by_3/expected_legend_7_by_3_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes.png b/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes.png
index a4e6bbb..3492fd6 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes.png and b/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes_mask.png b/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes_mask.png
index bfd2fc9..150ab33 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes_mask.png and b/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_diagram_size/expected_legend_diagram_size.png b/tests/testdata/control_images/legend/expected_legend_diagram_size/expected_legend_diagram_size.png
index ddd22ff..d36d4f5 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_diagram_size/expected_legend_diagram_size.png and b/tests/testdata/control_images/legend/expected_legend_diagram_size/expected_legend_diagram_size.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_diagram_size/expected_legend_diagram_size_mask.png b/tests/testdata/control_images/legend/expected_legend_diagram_size/expected_legend_diagram_size_mask.png
index 2e81976..68077b6 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_diagram_size/expected_legend_diagram_size_mask.png and b/tests/testdata/control_images/legend/expected_legend_diagram_size/expected_legend_diagram_size_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_filter_by_map/expected_legend_filter_by_map_mask.png b/tests/testdata/control_images/legend/expected_legend_filter_by_map/expected_legend_filter_by_map_mask.png
index d91b7a2..d953067 100644
Binary files a/tests/testdata/control_images/legend/expected_legend_filter_by_map/expected_legend_filter_by_map_mask.png and b/tests/testdata/control_images/legend/expected_legend_filter_by_map/expected_legend_filter_by_map_mask.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_tall_symbol/expected_legend_tall_symbol.png b/tests/testdata/control_images/legend/expected_legend_tall_symbol/expected_legend_tall_symbol.png
new file mode 100644
index 0000000..39b5a3b
Binary files /dev/null and b/tests/testdata/control_images/legend/expected_legend_tall_symbol/expected_legend_tall_symbol.png differ
diff --git a/tests/testdata/control_images/legend/expected_legend_tall_symbol/expected_legend_tall_symbol_mask.png b/tests/testdata/control_images/legend/expected_legend_tall_symbol/expected_legend_tall_symbol_mask.png
new file mode 100644
index 0000000..e52f1ed
Binary files /dev/null and b/tests/testdata/control_images/legend/expected_legend_tall_symbol/expected_legend_tall_symbol_mask.png differ
diff --git a/tests/testdata/control_images/maprotation/expected_lines-parallel-label+45/expected_lines-parallel-label+45.png b/tests/testdata/control_images/maprotation/expected_lines-parallel-label+45/expected_lines-parallel-label+45.png
index 004413c..ee15613 100644
Binary files a/tests/testdata/control_images/maprotation/expected_lines-parallel-label+45/expected_lines-parallel-label+45.png and b/tests/testdata/control_images/maprotation/expected_lines-parallel-label+45/expected_lines-parallel-label+45.png differ
diff --git a/tests/testdata/control_images/maprotation/expected_lines-parallel-label+45/expected_lines-parallel-label+45_mask.png b/tests/testdata/control_images/maprotation/expected_lines-parallel-label+45/expected_lines-parallel-label+45_mask.png
index 6b80aaf..dffdedb 100644
Binary files a/tests/testdata/control_images/maprotation/expected_lines-parallel-label+45/expected_lines-parallel-label+45_mask.png and b/tests/testdata/control_images/maprotation/expected_lines-parallel-label+45/expected_lines-parallel-label+45_mask.png differ
diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test/WMS_GetLegendGraphic_test.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test/WMS_GetLegendGraphic_test.png
new file mode 100644
index 0000000..163ae4e
Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test/WMS_GetLegendGraphic_test.png differ
diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test/WMS_GetLegendGraphic_test_mask.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test/WMS_GetLegendGraphic_test_mask.png
new file mode 100644
index 0000000..a02f45b
Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test/WMS_GetLegendGraphic_test_mask.png differ
diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test_layertitle_false/WMS_GetLegendGraphic_test_layertitle_false.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test_layertitle_false/WMS_GetLegendGraphic_test_layertitle_false.png
new file mode 100644
index 0000000..69cb22e
Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test_layertitle_false/WMS_GetLegendGraphic_test_layertitle_false.png differ
diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test_layertitle_false/WMS_GetLegendGraphic_test_layertitle_false_mask.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test_layertitle_false/WMS_GetLegendGraphic_test_layertitle_false_mask.png
new file mode 100644
index 0000000..4b118d9
Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_test_layertitle_false/WMS_GetLegendGraphic_test_layertitle_false_mask.png differ
diff --git a/tests/testdata/control_images/symbol_filledmarker/expected_filledmarker/expected_filledmarker_mask.png b/tests/testdata/control_images/symbol_filledmarker/expected_filledmarker/expected_filledmarker_mask.png
index 62d2745..2c5631a 100644
Binary files a/tests/testdata/control_images/symbol_filledmarker/expected_filledmarker/expected_filledmarker_mask.png and b/tests/testdata/control_images/symbol_filledmarker/expected_filledmarker/expected_filledmarker_mask.png differ
diff --git a/tests/testdata/control_images/symbol_filledmarker/expected_filledmarker_bounds/expected_filledmarker_bounds_mask.png b/tests/testdata/control_images/symbol_filledmarker/expected_filledmarker_bounds/expected_filledmarker_bounds_mask.png
index 9e6a580..850e8f7 100644
Binary files a/tests/testdata/control_images/symbol_filledmarker/expected_filledmarker_bounds/expected_filledmarker_bounds_mask.png and b/tests/testdata/control_images/symbol_filledmarker/expected_filledmarker_bounds/expected_filledmarker_bounds_mask.png differ
diff --git a/tests/testdata/control_images/symbol_markerline/expected_point_num_interval/expected_point_num_interval.png b/tests/testdata/control_images/symbol_markerline/expected_point_num_interval/expected_point_num_interval.png
new file mode 100644
index 0000000..777dc1c
Binary files /dev/null and b/tests/testdata/control_images/symbol_markerline/expected_point_num_interval/expected_point_num_interval.png differ
diff --git a/tests/testdata/control_images/symbol_markerline/expected_point_num_interval/expected_point_num_interval_mask.png b/tests/testdata/control_images/symbol_markerline/expected_point_num_interval/expected_point_num_interval_mask.png
new file mode 100644
index 0000000..28e7dc4
Binary files /dev/null and b/tests/testdata/control_images/symbol_markerline/expected_point_num_interval/expected_point_num_interval_mask.png differ
diff --git a/tests/testdata/control_images/symbol_markerline/expected_point_num_vertex/expected_point_num_vertex.png b/tests/testdata/control_images/symbol_markerline/expected_point_num_vertex/expected_point_num_vertex.png
new file mode 100644
index 0000000..5ded20a
Binary files /dev/null and b/tests/testdata/control_images/symbol_markerline/expected_point_num_vertex/expected_point_num_vertex.png differ
diff --git a/tests/testdata/control_images/symbol_markerline/expected_point_num_vertex/expected_point_num_vertex_mask.png b/tests/testdata/control_images/symbol_markerline/expected_point_num_vertex/expected_point_num_vertex_mask.png
new file mode 100644
index 0000000..aaf49c1
Binary files /dev/null and b/tests/testdata/control_images/symbol_markerline/expected_point_num_vertex/expected_point_num_vertex_mask.png differ
diff --git a/tests/testdata/labeling/line_placement_1.qml b/tests/testdata/labeling/line_placement_1.qml
new file mode 100644
index 0000000..f050ae9
--- /dev/null
+++ b/tests/testdata/labeling/line_placement_1.qml
@@ -0,0 +1,272 @@
+<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
+<qgis version="2.99.0-Master" simplifyAlgorithm="0" minimumScale="100000" maximumScale="1e+08" simplifyDrawingHints="1" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1">
+ <edittypes>
+ <edittype widgetv2type="TextEdit" name="pkuid">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ <edittype widgetv2type="TextEdit" name="text">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ </edittypes>
+ <renderer-v2 forceraster="0" symbollevels="0" type="singleSymbol" enableorderby="0">
+ <symbols>
+ <symbol alpha="1" clip_to_extent="1" type="line" name="0">
+ <layer pass="0" class="SimpleLine" locked="0">
+ <prop k="capstyle" v="square"/>
+ <prop k="customdash" v="5;2"/>
+ <prop k="customdash_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="customdash_unit" v="MM"/>
+ <prop k="draw_inside_polygon" v="0"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="line_color" v="227,26,28,255"/>
+ <prop k="line_style" v="solid"/>
+ <prop k="line_width" v="0.5"/>
+ <prop k="line_width_unit" v="MM"/>
+ <prop k="offset" v="0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="use_custom_dash" v="0"/>
+ <prop k="width_map_unit_scale" v="0,0,0,0,0,0"/>
+ </layer>
+ </symbol>
+ </symbols>
+ <rotation/>
+ <sizescale scalemethod="diameter"/>
+ </renderer-v2>
+ <labeling type="simple"/>
+ <customproperties>
+ <property key="embeddedWidgets/count" value="0"/>
+ <property key="labeling" value="pal"/>
+ <property key="labeling/addDirectionSymbol" value="false"/>
+ <property key="labeling/angleOffset" value="0"/>
+ <property key="labeling/blendMode" value="0"/>
+ <property key="labeling/bufferBlendMode" value="0"/>
+ <property key="labeling/bufferColorA" value="255"/>
+ <property key="labeling/bufferColorB" value="255"/>
+ <property key="labeling/bufferColorG" value="255"/>
+ <property key="labeling/bufferColorR" value="255"/>
+ <property key="labeling/bufferDraw" value="false"/>
+ <property key="labeling/bufferJoinStyle" value="64"/>
+ <property key="labeling/bufferNoFill" value="false"/>
+ <property key="labeling/bufferSize" value="1"/>
+ <property key="labeling/bufferSizeInMapUnits" value="false"/>
+ <property key="labeling/bufferSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/bufferTransp" value="0"/>
+ <property key="labeling/centroidInside" value="false"/>
+ <property key="labeling/centroidWhole" value="false"/>
+ <property key="labeling/decimals" value="3"/>
+ <property key="labeling/displayAll" value="false"/>
+ <property key="labeling/dist" value="0"/>
+ <property key="labeling/distInMapUnits" value="false"/>
+ <property key="labeling/distMapUnitMaxScale" value="0"/>
+ <property key="labeling/distMapUnitMinScale" value="0"/>
+ <property key="labeling/distMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/drawLabels" value="false"/>
+ <property key="labeling/enabled" value="false"/>
+ <property key="labeling/fieldName" value=""/>
+ <property key="labeling/fitInPolygonOnly" value="false"/>
+ <property key="labeling/fontBold" value="false"/>
+ <property key="labeling/fontCapitals" value="0"/>
+ <property key="labeling/fontFamily" value="Ubuntu"/>
+ <property key="labeling/fontItalic" value="false"/>
+ <property key="labeling/fontLetterSpacing" value="0"/>
+ <property key="labeling/fontLimitPixelSize" value="false"/>
+ <property key="labeling/fontMaxPixelSize" value="10000"/>
+ <property key="labeling/fontMinPixelSize" value="3"/>
+ <property key="labeling/fontSize" value="11"/>
+ <property key="labeling/fontSizeInMapUnits" value="false"/>
+ <property key="labeling/fontSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/fontStrikeout" value="false"/>
+ <property key="labeling/fontUnderline" value="false"/>
+ <property key="labeling/fontWeight" value="63"/>
+ <property key="labeling/fontWordSpacing" value="0"/>
+ <property key="labeling/formatNumbers" value="false"/>
+ <property key="labeling/isExpression" value="true"/>
+ <property key="labeling/labelOffsetInMapUnits" value="true"/>
+ <property key="labeling/labelOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/labelPerPart" value="false"/>
+ <property key="labeling/leftDirectionSymbol" value="<"/>
+ <property key="labeling/limitNumLabels" value="false"/>
+ <property key="labeling/maxCurvedCharAngleIn" value="20"/>
+ <property key="labeling/maxCurvedCharAngleOut" value="-20"/>
+ <property key="labeling/maxNumLabels" value="2000"/>
+ <property key="labeling/mergeLines" value="false"/>
+ <property key="labeling/minFeatureSize" value="0"/>
+ <property key="labeling/multilineAlign" value="0"/>
+ <property key="labeling/multilineHeight" value="1"/>
+ <property key="labeling/namedStyle" value="Medium"/>
+ <property key="labeling/obstacle" value="true"/>
+ <property key="labeling/obstacleFactor" value="1"/>
+ <property key="labeling/obstacleType" value="0"/>
+ <property key="labeling/offsetType" value="0"/>
+ <property key="labeling/placeDirectionSymbol" value="0"/>
+ <property key="labeling/placement" value="2"/>
+ <property key="labeling/placementFlags" value="10"/>
+ <property key="labeling/plussign" value="false"/>
+ <property key="labeling/predefinedPositionOrder" value="TR,TL,BR,BL,R,L,TSR,BSR"/>
+ <property key="labeling/preserveRotation" value="true"/>
+ <property key="labeling/previewBkgrdColor" value="#ffffff"/>
+ <property key="labeling/priority" value="5"/>
+ <property key="labeling/quadOffset" value="4"/>
+ <property key="labeling/repeatDistance" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMaxScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMinScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/repeatDistanceUnit" value="1"/>
+ <property key="labeling/reverseDirectionSymbol" value="false"/>
+ <property key="labeling/rightDirectionSymbol" value=">"/>
+ <property key="labeling/scaleMax" value="10000000"/>
+ <property key="labeling/scaleMin" value="1"/>
+ <property key="labeling/scaleVisibility" value="false"/>
+ <property key="labeling/shadowBlendMode" value="6"/>
+ <property key="labeling/shadowColorB" value="0"/>
+ <property key="labeling/shadowColorG" value="0"/>
+ <property key="labeling/shadowColorR" value="0"/>
+ <property key="labeling/shadowDraw" value="false"/>
+ <property key="labeling/shadowOffsetAngle" value="135"/>
+ <property key="labeling/shadowOffsetDist" value="1"/>
+ <property key="labeling/shadowOffsetGlobal" value="true"/>
+ <property key="labeling/shadowOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowOffsetUnits" value="1"/>
+ <property key="labeling/shadowRadius" value="1.5"/>
+ <property key="labeling/shadowRadiusAlphaOnly" value="false"/>
+ <property key="labeling/shadowRadiusMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowRadiusUnits" value="1"/>
+ <property key="labeling/shadowScale" value="100"/>
+ <property key="labeling/shadowTransparency" value="30"/>
+ <property key="labeling/shadowUnder" value="0"/>
+ <property key="labeling/shapeBlendMode" value="0"/>
+ <property key="labeling/shapeBorderColorA" value="255"/>
+ <property key="labeling/shapeBorderColorB" value="128"/>
+ <property key="labeling/shapeBorderColorG" value="128"/>
+ <property key="labeling/shapeBorderColorR" value="128"/>
+ <property key="labeling/shapeBorderWidth" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeBorderWidthUnits" value="1"/>
+ <property key="labeling/shapeDraw" value="false"/>
+ <property key="labeling/shapeFillColorA" value="255"/>
+ <property key="labeling/shapeFillColorB" value="255"/>
+ <property key="labeling/shapeFillColorG" value="255"/>
+ <property key="labeling/shapeFillColorR" value="255"/>
+ <property key="labeling/shapeJoinStyle" value="64"/>
+ <property key="labeling/shapeOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeOffsetUnits" value="1"/>
+ <property key="labeling/shapeOffsetX" value="0"/>
+ <property key="labeling/shapeOffsetY" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeRadiiUnits" value="1"/>
+ <property key="labeling/shapeRadiiX" value="0"/>
+ <property key="labeling/shapeRadiiY" value="0"/>
+ <property key="labeling/shapeRotation" value="0"/>
+ <property key="labeling/shapeRotationType" value="0"/>
+ <property key="labeling/shapeSVGFile" value=""/>
+ <property key="labeling/shapeSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeSizeType" value="0"/>
+ <property key="labeling/shapeSizeUnits" value="1"/>
+ <property key="labeling/shapeSizeX" value="0"/>
+ <property key="labeling/shapeSizeY" value="0"/>
+ <property key="labeling/shapeTransparency" value="0"/>
+ <property key="labeling/shapeType" value="0"/>
+ <property key="labeling/textColorA" value="255"/>
+ <property key="labeling/textColorB" value="0"/>
+ <property key="labeling/textColorG" value="0"/>
+ <property key="labeling/textColorR" value="0"/>
+ <property key="labeling/textTransp" value="0"/>
+ <property key="labeling/upsidedownLabels" value="0"/>
+ <property key="labeling/wrapChar" value=""/>
+ <property key="labeling/xOffset" value="0"/>
+ <property key="labeling/yOffset" value="0"/>
+ <property key="labeling/zIndex" value="0"/>
+ <property key="variableNames" value="_fields_"/>
+ <property key="variableValues" value=""/>
+ </customproperties>
+ <blendMode>0</blendMode>
+ <featureBlendMode>0</featureBlendMode>
+ <layerTransparency>0</layerTransparency>
+ <SingleCategoryDiagramRenderer diagramType="Histogram" sizeLegend="0" attributeLegend="1">
+ <DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" sizeScale="0,0,0,0,0,0" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="0,0,0,0,0,0" sizeType="MM" lineSizeType="MM" minScaleDenominator="100000">
+ <fontProperties description="Ubuntu,11,-1,5,50,0,0,0,0,0" style=""/>
+ </DiagramCategory>
+ <symbol alpha="1" clip_to_extent="1" type="marker" name="sizeSymbol">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_color" v="0,0,0,255"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0"/>
+ <prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="diameter"/>
+ <prop k="size" v="2"/>
+ <prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ </SingleCategoryDiagramRenderer>
+ <DiagramLayerSettings yPosColumn="-1" showColumn="-1" linePlacementFlags="10" placement="2" dist="0" xPosColumn="-1" priority="0" obstacle="0" zIndex="0" showAll="1"/>
+ <annotationform></annotationform>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions default="-1"/>
+ <attributetableconfig actionWidgetStyle="dropDown" sortExpression="" sortOrder="0">
+ <columns>
+ <column width="-1" hidden="0" type="field" name="pkuid"/>
+ <column width="-1" hidden="0" type="field" name="text"/>
+ <column width="-1" hidden="1" type="actions"/>
+ </columns>
+ </attributetableconfig>
+ <editform></editform>
+ <editforminit/>
+ <editforminitcodesource>0</editforminitcodesource>
+ <editforminitfilepath></editforminitfilepath>
+ <editforminitcode><![CDATA[# -*- coding: utf-8 -*-
+"""
+QGIS forms can have a Python function that is called when the form is
+opened.
+
+Use this function to add extra logic to your forms.
+
+Enter the name of the function in the "Python Init function"
+field.
+An example follows:
+"""
+from qgis.PyQt.QtWidgets import QWidget
+
+def my_form_open(dialog, layer, feature):
+ geom = feature.geometry()
+ control = dialog.findChild(QWidget, "MyLineEdit")
+]]></editforminitcode>
+ <featformsuppress>0</featformsuppress>
+ <editorlayout>generatedlayout</editorlayout>
+ <widgets/>
+ <conditionalstyles>
+ <rowstyles/>
+ <fieldstyles/>
+ </conditionalstyles>
+ <layerGeometryType>1</layerGeometryType>
+</qgis>
diff --git a/tests/testdata/labeling/line_placement_2.qml b/tests/testdata/labeling/line_placement_2.qml
new file mode 100644
index 0000000..1292061
--- /dev/null
+++ b/tests/testdata/labeling/line_placement_2.qml
@@ -0,0 +1,273 @@
+<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
+<qgis version="2.99.0-Master" simplifyAlgorithm="0" minimumScale="100000" maximumScale="1e+08" simplifyDrawingHints="1" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1">
+ <edittypes>
+ <edittype widgetv2type="TextEdit" name="pkuid">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ <edittype widgetv2type="TextEdit" name="text">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ </edittypes>
+ <renderer-v2 forceraster="0" symbollevels="0" type="singleSymbol" enableorderby="0">
+ <symbols>
+ <symbol alpha="1" clip_to_extent="1" type="line" name="0">
+ <layer pass="0" class="SimpleLine" locked="0">
+ <prop k="capstyle" v="square"/>
+ <prop k="customdash" v="5;2"/>
+ <prop k="customdash_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="customdash_unit" v="MM"/>
+ <prop k="draw_inside_polygon" v="0"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="line_color" v="227,26,28,255"/>
+ <prop k="line_style" v="solid"/>
+ <prop k="line_width" v="0.5"/>
+ <prop k="line_width_unit" v="MM"/>
+ <prop k="offset" v="0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="use_custom_dash" v="0"/>
+ <prop k="width_map_unit_scale" v="0,0,0,0,0,0"/>
+ </layer>
+ </symbol>
+ </symbols>
+ <rotation/>
+ <sizescale scalemethod="diameter"/>
+ </renderer-v2>
+ <labeling type="simple"/>
+ <customproperties>
+ <property key="embeddedWidgets/count" value="0"/>
+ <property key="labeling" value="pal"/>
+ <property key="labeling/addDirectionSymbol" value="false"/>
+ <property key="labeling/angleOffset" value="0"/>
+ <property key="labeling/blendMode" value="0"/>
+ <property key="labeling/bufferBlendMode" value="0"/>
+ <property key="labeling/bufferColorA" value="255"/>
+ <property key="labeling/bufferColorB" value="255"/>
+ <property key="labeling/bufferColorG" value="255"/>
+ <property key="labeling/bufferColorR" value="255"/>
+ <property key="labeling/bufferDraw" value="false"/>
+ <property key="labeling/bufferJoinStyle" value="64"/>
+ <property key="labeling/bufferNoFill" value="false"/>
+ <property key="labeling/bufferSize" value="1"/>
+ <property key="labeling/bufferSizeInMapUnits" value="false"/>
+ <property key="labeling/bufferSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/bufferTransp" value="0"/>
+ <property key="labeling/centroidInside" value="false"/>
+ <property key="labeling/centroidWhole" value="false"/>
+ <property key="labeling/decimals" value="3"/>
+ <property key="labeling/displayAll" value="false"/>
+ <property key="labeling/dist" value="0"/>
+ <property key="labeling/distInMapUnits" value="false"/>
+ <property key="labeling/distMapUnitMaxScale" value="0"/>
+ <property key="labeling/distMapUnitMinScale" value="0"/>
+ <property key="labeling/distMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/drawLabels" value="false"/>
+ <property key="labeling/enabled" value="false"/>
+ <property key="labeling/fieldName" value=""/>
+ <property key="labeling/fitInPolygonOnly" value="false"/>
+ <property key="labeling/fontBold" value="false"/>
+ <property key="labeling/fontCapitals" value="0"/>
+ <property key="labeling/fontFamily" value="Ubuntu"/>
+ <property key="labeling/fontItalic" value="false"/>
+ <property key="labeling/fontLetterSpacing" value="0"/>
+ <property key="labeling/fontLimitPixelSize" value="false"/>
+ <property key="labeling/fontMaxPixelSize" value="10000"/>
+ <property key="labeling/fontMinPixelSize" value="3"/>
+ <property key="labeling/fontSize" value="11"/>
+ <property key="labeling/fontSizeInMapUnits" value="false"/>
+ <property key="labeling/fontSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/fontStrikeout" value="false"/>
+ <property key="labeling/fontUnderline" value="false"/>
+ <property key="labeling/fontWeight" value="63"/>
+ <property key="labeling/fontWordSpacing" value="0"/>
+ <property key="labeling/formatNumbers" value="false"/>
+ <property key="labeling/isExpression" value="true"/>
+ <property key="labeling/labelOffsetInMapUnits" value="true"/>
+ <property key="labeling/labelOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/labelPerPart" value="false"/>
+ <property key="labeling/leftDirectionSymbol" value="<"/>
+ <property key="labeling/limitNumLabels" value="false"/>
+ <property key="labeling/maxCurvedCharAngleIn" value="20"/>
+ <property key="labeling/maxCurvedCharAngleOut" value="-20"/>
+ <property key="labeling/maxNumLabels" value="2000"/>
+ <property key="labeling/mergeLines" value="false"/>
+ <property key="labeling/minFeatureSize" value="0"/>
+ <property key="labeling/multilineAlign" value="0"/>
+ <property key="labeling/multilineHeight" value="1"/>
+ <property key="labeling/namedStyle" value="Medium"/>
+ <property key="labeling/obstacle" value="true"/>
+ <property key="labeling/obstacleFactor" value="1"/>
+ <property key="labeling/obstacleType" value="0"/>
+ <property key="labeling/offsetType" value="0"/>
+ <property key="labeling/placeDirectionSymbol" value="0"/>
+ <property key="labeling/placement" value="2"/>
+ <property key="labeling/placementFlags" value="10"/>
+ <property key="labeling/plussign" value="false"/>
+ <property key="labeling/predefinedPositionOrder" value="TR,TL,BR,BL,R,L,TSR,BSR"/>
+ <property key="labeling/preserveRotation" value="true"/>
+ <property key="labeling/previewBkgrdColor" value="#ffffff"/>
+ <property key="labeling/priority" value="5"/>
+ <property key="labeling/quadOffset" value="4"/>
+ <property key="labeling/repeatDistance" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMaxScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMinScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/repeatDistanceUnit" value="1"/>
+ <property key="labeling/reverseDirectionSymbol" value="false"/>
+ <property key="labeling/rightDirectionSymbol" value=">"/>
+ <property key="labeling/scaleMax" value="10000000"/>
+ <property key="labeling/scaleMin" value="1"/>
+ <property key="labeling/scaleVisibility" value="false"/>
+ <property key="labeling/shadowBlendMode" value="6"/>
+ <property key="labeling/shadowColorB" value="0"/>
+ <property key="labeling/shadowColorG" value="0"/>
+ <property key="labeling/shadowColorR" value="0"/>
+ <property key="labeling/shadowDraw" value="false"/>
+ <property key="labeling/shadowOffsetAngle" value="135"/>
+ <property key="labeling/shadowOffsetDist" value="1"/>
+ <property key="labeling/shadowOffsetGlobal" value="true"/>
+ <property key="labeling/shadowOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowOffsetUnits" value="1"/>
+ <property key="labeling/shadowRadius" value="1.5"/>
+ <property key="labeling/shadowRadiusAlphaOnly" value="false"/>
+ <property key="labeling/shadowRadiusMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowRadiusUnits" value="1"/>
+ <property key="labeling/shadowScale" value="100"/>
+ <property key="labeling/shadowTransparency" value="30"/>
+ <property key="labeling/shadowUnder" value="0"/>
+ <property key="labeling/shapeBlendMode" value="0"/>
+ <property key="labeling/shapeBorderColorA" value="255"/>
+ <property key="labeling/shapeBorderColorB" value="128"/>
+ <property key="labeling/shapeBorderColorG" value="128"/>
+ <property key="labeling/shapeBorderColorR" value="128"/>
+ <property key="labeling/shapeBorderWidth" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeBorderWidthUnits" value="1"/>
+ <property key="labeling/shapeDraw" value="false"/>
+ <property key="labeling/shapeFillColorA" value="255"/>
+ <property key="labeling/shapeFillColorB" value="255"/>
+ <property key="labeling/shapeFillColorG" value="255"/>
+ <property key="labeling/shapeFillColorR" value="255"/>
+ <property key="labeling/shapeJoinStyle" value="64"/>
+ <property key="labeling/shapeOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeOffsetUnits" value="1"/>
+ <property key="labeling/shapeOffsetX" value="0"/>
+ <property key="labeling/shapeOffsetY" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeRadiiUnits" value="1"/>
+ <property key="labeling/shapeRadiiX" value="0"/>
+ <property key="labeling/shapeRadiiY" value="0"/>
+ <property key="labeling/shapeRotation" value="0"/>
+ <property key="labeling/shapeRotationType" value="0"/>
+ <property key="labeling/shapeSVGFile" value=""/>
+ <property key="labeling/shapeSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeSizeType" value="0"/>
+ <property key="labeling/shapeSizeUnits" value="1"/>
+ <property key="labeling/shapeSizeX" value="0"/>
+ <property key="labeling/shapeSizeY" value="0"/>
+ <property key="labeling/shapeTransparency" value="0"/>
+ <property key="labeling/shapeType" value="0"/>
+ <property key="labeling/textColorA" value="255"/>
+ <property key="labeling/textColorB" value="0"/>
+ <property key="labeling/textColorG" value="0"/>
+ <property key="labeling/textColorR" value="0"/>
+ <property key="labeling/textTransp" value="0"/>
+ <property key="labeling/upsidedownLabels" value="0"/>
+ <property key="labeling/wrapChar" value=""/>
+ <property key="labeling/xOffset" value="0"/>
+ <property key="labeling/yOffset" value="0"/>
+ <property key="labeling/zIndex" value="0"/>
+ <property key="variableNames" value="_fields_"/>
+ <property key="variableValues" value=""/>
+ </customproperties>
+ <blendMode>0</blendMode>
+ <featureBlendMode>0</featureBlendMode>
+ <layerTransparency>0</layerTransparency>
+ <SingleCategoryDiagramRenderer diagramType="Histogram" sizeLegend="0" attributeLegend="1">
+ <DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" sizeScale="0,0,0,0,0,0" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="0,0,0,0,0,0" sizeType="MM" lineSizeType="MM" minScaleDenominator="100000">
+ <fontProperties description="Ubuntu,11,-1,5,50,0,0,0,0,0" style=""/>
+ <attribute field="" color="#000000" label=""/>
+ </DiagramCategory>
+ <symbol alpha="1" clip_to_extent="1" type="marker" name="sizeSymbol">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_color" v="0,0,0,255"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0"/>
+ <prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="diameter"/>
+ <prop k="size" v="2"/>
+ <prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ </SingleCategoryDiagramRenderer>
+ <DiagramLayerSettings yPosColumn="-1" showColumn="-1" linePlacementFlags="10" placement="2" dist="0" xPosColumn="-1" priority="0" obstacle="0" zIndex="0" showAll="1"/>
+ <annotationform></annotationform>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions default="-1"/>
+ <attributetableconfig actionWidgetStyle="dropDown" sortExpression="" sortOrder="0">
+ <columns>
+ <column width="-1" hidden="0" type="field" name="pkuid"/>
+ <column width="-1" hidden="0" type="field" name="text"/>
+ <column width="-1" hidden="1" type="actions"/>
+ </columns>
+ </attributetableconfig>
+ <editform></editform>
+ <editforminit/>
+ <editforminitcodesource>0</editforminitcodesource>
+ <editforminitfilepath></editforminitfilepath>
+ <editforminitcode><![CDATA[# -*- coding: utf-8 -*-
+"""
+QGIS forms can have a Python function that is called when the form is
+opened.
+
+Use this function to add extra logic to your forms.
+
+Enter the name of the function in the "Python Init function"
+field.
+An example follows:
+"""
+from qgis.PyQt.QtWidgets import QWidget
+
+def my_form_open(dialog, layer, feature):
+ geom = feature.geometry()
+ control = dialog.findChild(QWidget, "MyLineEdit")
+]]></editforminitcode>
+ <featformsuppress>0</featformsuppress>
+ <editorlayout>generatedlayout</editorlayout>
+ <widgets/>
+ <conditionalstyles>
+ <rowstyles/>
+ <fieldstyles/>
+ </conditionalstyles>
+ <layerGeometryType>1</layerGeometryType>
+</qgis>
diff --git a/tests/testdata/labeling/line_placement_3.qml b/tests/testdata/labeling/line_placement_3.qml
new file mode 100644
index 0000000..1292061
--- /dev/null
+++ b/tests/testdata/labeling/line_placement_3.qml
@@ -0,0 +1,273 @@
+<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
+<qgis version="2.99.0-Master" simplifyAlgorithm="0" minimumScale="100000" maximumScale="1e+08" simplifyDrawingHints="1" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1">
+ <edittypes>
+ <edittype widgetv2type="TextEdit" name="pkuid">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ <edittype widgetv2type="TextEdit" name="text">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ </edittypes>
+ <renderer-v2 forceraster="0" symbollevels="0" type="singleSymbol" enableorderby="0">
+ <symbols>
+ <symbol alpha="1" clip_to_extent="1" type="line" name="0">
+ <layer pass="0" class="SimpleLine" locked="0">
+ <prop k="capstyle" v="square"/>
+ <prop k="customdash" v="5;2"/>
+ <prop k="customdash_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="customdash_unit" v="MM"/>
+ <prop k="draw_inside_polygon" v="0"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="line_color" v="227,26,28,255"/>
+ <prop k="line_style" v="solid"/>
+ <prop k="line_width" v="0.5"/>
+ <prop k="line_width_unit" v="MM"/>
+ <prop k="offset" v="0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="use_custom_dash" v="0"/>
+ <prop k="width_map_unit_scale" v="0,0,0,0,0,0"/>
+ </layer>
+ </symbol>
+ </symbols>
+ <rotation/>
+ <sizescale scalemethod="diameter"/>
+ </renderer-v2>
+ <labeling type="simple"/>
+ <customproperties>
+ <property key="embeddedWidgets/count" value="0"/>
+ <property key="labeling" value="pal"/>
+ <property key="labeling/addDirectionSymbol" value="false"/>
+ <property key="labeling/angleOffset" value="0"/>
+ <property key="labeling/blendMode" value="0"/>
+ <property key="labeling/bufferBlendMode" value="0"/>
+ <property key="labeling/bufferColorA" value="255"/>
+ <property key="labeling/bufferColorB" value="255"/>
+ <property key="labeling/bufferColorG" value="255"/>
+ <property key="labeling/bufferColorR" value="255"/>
+ <property key="labeling/bufferDraw" value="false"/>
+ <property key="labeling/bufferJoinStyle" value="64"/>
+ <property key="labeling/bufferNoFill" value="false"/>
+ <property key="labeling/bufferSize" value="1"/>
+ <property key="labeling/bufferSizeInMapUnits" value="false"/>
+ <property key="labeling/bufferSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/bufferTransp" value="0"/>
+ <property key="labeling/centroidInside" value="false"/>
+ <property key="labeling/centroidWhole" value="false"/>
+ <property key="labeling/decimals" value="3"/>
+ <property key="labeling/displayAll" value="false"/>
+ <property key="labeling/dist" value="0"/>
+ <property key="labeling/distInMapUnits" value="false"/>
+ <property key="labeling/distMapUnitMaxScale" value="0"/>
+ <property key="labeling/distMapUnitMinScale" value="0"/>
+ <property key="labeling/distMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/drawLabels" value="false"/>
+ <property key="labeling/enabled" value="false"/>
+ <property key="labeling/fieldName" value=""/>
+ <property key="labeling/fitInPolygonOnly" value="false"/>
+ <property key="labeling/fontBold" value="false"/>
+ <property key="labeling/fontCapitals" value="0"/>
+ <property key="labeling/fontFamily" value="Ubuntu"/>
+ <property key="labeling/fontItalic" value="false"/>
+ <property key="labeling/fontLetterSpacing" value="0"/>
+ <property key="labeling/fontLimitPixelSize" value="false"/>
+ <property key="labeling/fontMaxPixelSize" value="10000"/>
+ <property key="labeling/fontMinPixelSize" value="3"/>
+ <property key="labeling/fontSize" value="11"/>
+ <property key="labeling/fontSizeInMapUnits" value="false"/>
+ <property key="labeling/fontSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/fontStrikeout" value="false"/>
+ <property key="labeling/fontUnderline" value="false"/>
+ <property key="labeling/fontWeight" value="63"/>
+ <property key="labeling/fontWordSpacing" value="0"/>
+ <property key="labeling/formatNumbers" value="false"/>
+ <property key="labeling/isExpression" value="true"/>
+ <property key="labeling/labelOffsetInMapUnits" value="true"/>
+ <property key="labeling/labelOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/labelPerPart" value="false"/>
+ <property key="labeling/leftDirectionSymbol" value="<"/>
+ <property key="labeling/limitNumLabels" value="false"/>
+ <property key="labeling/maxCurvedCharAngleIn" value="20"/>
+ <property key="labeling/maxCurvedCharAngleOut" value="-20"/>
+ <property key="labeling/maxNumLabels" value="2000"/>
+ <property key="labeling/mergeLines" value="false"/>
+ <property key="labeling/minFeatureSize" value="0"/>
+ <property key="labeling/multilineAlign" value="0"/>
+ <property key="labeling/multilineHeight" value="1"/>
+ <property key="labeling/namedStyle" value="Medium"/>
+ <property key="labeling/obstacle" value="true"/>
+ <property key="labeling/obstacleFactor" value="1"/>
+ <property key="labeling/obstacleType" value="0"/>
+ <property key="labeling/offsetType" value="0"/>
+ <property key="labeling/placeDirectionSymbol" value="0"/>
+ <property key="labeling/placement" value="2"/>
+ <property key="labeling/placementFlags" value="10"/>
+ <property key="labeling/plussign" value="false"/>
+ <property key="labeling/predefinedPositionOrder" value="TR,TL,BR,BL,R,L,TSR,BSR"/>
+ <property key="labeling/preserveRotation" value="true"/>
+ <property key="labeling/previewBkgrdColor" value="#ffffff"/>
+ <property key="labeling/priority" value="5"/>
+ <property key="labeling/quadOffset" value="4"/>
+ <property key="labeling/repeatDistance" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMaxScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMinScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/repeatDistanceUnit" value="1"/>
+ <property key="labeling/reverseDirectionSymbol" value="false"/>
+ <property key="labeling/rightDirectionSymbol" value=">"/>
+ <property key="labeling/scaleMax" value="10000000"/>
+ <property key="labeling/scaleMin" value="1"/>
+ <property key="labeling/scaleVisibility" value="false"/>
+ <property key="labeling/shadowBlendMode" value="6"/>
+ <property key="labeling/shadowColorB" value="0"/>
+ <property key="labeling/shadowColorG" value="0"/>
+ <property key="labeling/shadowColorR" value="0"/>
+ <property key="labeling/shadowDraw" value="false"/>
+ <property key="labeling/shadowOffsetAngle" value="135"/>
+ <property key="labeling/shadowOffsetDist" value="1"/>
+ <property key="labeling/shadowOffsetGlobal" value="true"/>
+ <property key="labeling/shadowOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowOffsetUnits" value="1"/>
+ <property key="labeling/shadowRadius" value="1.5"/>
+ <property key="labeling/shadowRadiusAlphaOnly" value="false"/>
+ <property key="labeling/shadowRadiusMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowRadiusUnits" value="1"/>
+ <property key="labeling/shadowScale" value="100"/>
+ <property key="labeling/shadowTransparency" value="30"/>
+ <property key="labeling/shadowUnder" value="0"/>
+ <property key="labeling/shapeBlendMode" value="0"/>
+ <property key="labeling/shapeBorderColorA" value="255"/>
+ <property key="labeling/shapeBorderColorB" value="128"/>
+ <property key="labeling/shapeBorderColorG" value="128"/>
+ <property key="labeling/shapeBorderColorR" value="128"/>
+ <property key="labeling/shapeBorderWidth" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeBorderWidthUnits" value="1"/>
+ <property key="labeling/shapeDraw" value="false"/>
+ <property key="labeling/shapeFillColorA" value="255"/>
+ <property key="labeling/shapeFillColorB" value="255"/>
+ <property key="labeling/shapeFillColorG" value="255"/>
+ <property key="labeling/shapeFillColorR" value="255"/>
+ <property key="labeling/shapeJoinStyle" value="64"/>
+ <property key="labeling/shapeOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeOffsetUnits" value="1"/>
+ <property key="labeling/shapeOffsetX" value="0"/>
+ <property key="labeling/shapeOffsetY" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeRadiiUnits" value="1"/>
+ <property key="labeling/shapeRadiiX" value="0"/>
+ <property key="labeling/shapeRadiiY" value="0"/>
+ <property key="labeling/shapeRotation" value="0"/>
+ <property key="labeling/shapeRotationType" value="0"/>
+ <property key="labeling/shapeSVGFile" value=""/>
+ <property key="labeling/shapeSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeSizeType" value="0"/>
+ <property key="labeling/shapeSizeUnits" value="1"/>
+ <property key="labeling/shapeSizeX" value="0"/>
+ <property key="labeling/shapeSizeY" value="0"/>
+ <property key="labeling/shapeTransparency" value="0"/>
+ <property key="labeling/shapeType" value="0"/>
+ <property key="labeling/textColorA" value="255"/>
+ <property key="labeling/textColorB" value="0"/>
+ <property key="labeling/textColorG" value="0"/>
+ <property key="labeling/textColorR" value="0"/>
+ <property key="labeling/textTransp" value="0"/>
+ <property key="labeling/upsidedownLabels" value="0"/>
+ <property key="labeling/wrapChar" value=""/>
+ <property key="labeling/xOffset" value="0"/>
+ <property key="labeling/yOffset" value="0"/>
+ <property key="labeling/zIndex" value="0"/>
+ <property key="variableNames" value="_fields_"/>
+ <property key="variableValues" value=""/>
+ </customproperties>
+ <blendMode>0</blendMode>
+ <featureBlendMode>0</featureBlendMode>
+ <layerTransparency>0</layerTransparency>
+ <SingleCategoryDiagramRenderer diagramType="Histogram" sizeLegend="0" attributeLegend="1">
+ <DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" sizeScale="0,0,0,0,0,0" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="0,0,0,0,0,0" sizeType="MM" lineSizeType="MM" minScaleDenominator="100000">
+ <fontProperties description="Ubuntu,11,-1,5,50,0,0,0,0,0" style=""/>
+ <attribute field="" color="#000000" label=""/>
+ </DiagramCategory>
+ <symbol alpha="1" clip_to_extent="1" type="marker" name="sizeSymbol">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_color" v="0,0,0,255"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0"/>
+ <prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="diameter"/>
+ <prop k="size" v="2"/>
+ <prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ </SingleCategoryDiagramRenderer>
+ <DiagramLayerSettings yPosColumn="-1" showColumn="-1" linePlacementFlags="10" placement="2" dist="0" xPosColumn="-1" priority="0" obstacle="0" zIndex="0" showAll="1"/>
+ <annotationform></annotationform>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions default="-1"/>
+ <attributetableconfig actionWidgetStyle="dropDown" sortExpression="" sortOrder="0">
+ <columns>
+ <column width="-1" hidden="0" type="field" name="pkuid"/>
+ <column width="-1" hidden="0" type="field" name="text"/>
+ <column width="-1" hidden="1" type="actions"/>
+ </columns>
+ </attributetableconfig>
+ <editform></editform>
+ <editforminit/>
+ <editforminitcodesource>0</editforminitcodesource>
+ <editforminitfilepath></editforminitfilepath>
+ <editforminitcode><![CDATA[# -*- coding: utf-8 -*-
+"""
+QGIS forms can have a Python function that is called when the form is
+opened.
+
+Use this function to add extra logic to your forms.
+
+Enter the name of the function in the "Python Init function"
+field.
+An example follows:
+"""
+from qgis.PyQt.QtWidgets import QWidget
+
+def my_form_open(dialog, layer, feature):
+ geom = feature.geometry()
+ control = dialog.findChild(QWidget, "MyLineEdit")
+]]></editforminitcode>
+ <featformsuppress>0</featformsuppress>
+ <editorlayout>generatedlayout</editorlayout>
+ <widgets/>
+ <conditionalstyles>
+ <rowstyles/>
+ <fieldstyles/>
+ </conditionalstyles>
+ <layerGeometryType>1</layerGeometryType>
+</qgis>
diff --git a/tests/testdata/labeling/line_placement_4.qml b/tests/testdata/labeling/line_placement_4.qml
new file mode 100644
index 0000000..1292061
--- /dev/null
+++ b/tests/testdata/labeling/line_placement_4.qml
@@ -0,0 +1,273 @@
+<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
+<qgis version="2.99.0-Master" simplifyAlgorithm="0" minimumScale="100000" maximumScale="1e+08" simplifyDrawingHints="1" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1">
+ <edittypes>
+ <edittype widgetv2type="TextEdit" name="pkuid">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ <edittype widgetv2type="TextEdit" name="text">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ </edittypes>
+ <renderer-v2 forceraster="0" symbollevels="0" type="singleSymbol" enableorderby="0">
+ <symbols>
+ <symbol alpha="1" clip_to_extent="1" type="line" name="0">
+ <layer pass="0" class="SimpleLine" locked="0">
+ <prop k="capstyle" v="square"/>
+ <prop k="customdash" v="5;2"/>
+ <prop k="customdash_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="customdash_unit" v="MM"/>
+ <prop k="draw_inside_polygon" v="0"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="line_color" v="227,26,28,255"/>
+ <prop k="line_style" v="solid"/>
+ <prop k="line_width" v="0.5"/>
+ <prop k="line_width_unit" v="MM"/>
+ <prop k="offset" v="0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="use_custom_dash" v="0"/>
+ <prop k="width_map_unit_scale" v="0,0,0,0,0,0"/>
+ </layer>
+ </symbol>
+ </symbols>
+ <rotation/>
+ <sizescale scalemethod="diameter"/>
+ </renderer-v2>
+ <labeling type="simple"/>
+ <customproperties>
+ <property key="embeddedWidgets/count" value="0"/>
+ <property key="labeling" value="pal"/>
+ <property key="labeling/addDirectionSymbol" value="false"/>
+ <property key="labeling/angleOffset" value="0"/>
+ <property key="labeling/blendMode" value="0"/>
+ <property key="labeling/bufferBlendMode" value="0"/>
+ <property key="labeling/bufferColorA" value="255"/>
+ <property key="labeling/bufferColorB" value="255"/>
+ <property key="labeling/bufferColorG" value="255"/>
+ <property key="labeling/bufferColorR" value="255"/>
+ <property key="labeling/bufferDraw" value="false"/>
+ <property key="labeling/bufferJoinStyle" value="64"/>
+ <property key="labeling/bufferNoFill" value="false"/>
+ <property key="labeling/bufferSize" value="1"/>
+ <property key="labeling/bufferSizeInMapUnits" value="false"/>
+ <property key="labeling/bufferSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/bufferTransp" value="0"/>
+ <property key="labeling/centroidInside" value="false"/>
+ <property key="labeling/centroidWhole" value="false"/>
+ <property key="labeling/decimals" value="3"/>
+ <property key="labeling/displayAll" value="false"/>
+ <property key="labeling/dist" value="0"/>
+ <property key="labeling/distInMapUnits" value="false"/>
+ <property key="labeling/distMapUnitMaxScale" value="0"/>
+ <property key="labeling/distMapUnitMinScale" value="0"/>
+ <property key="labeling/distMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/drawLabels" value="false"/>
+ <property key="labeling/enabled" value="false"/>
+ <property key="labeling/fieldName" value=""/>
+ <property key="labeling/fitInPolygonOnly" value="false"/>
+ <property key="labeling/fontBold" value="false"/>
+ <property key="labeling/fontCapitals" value="0"/>
+ <property key="labeling/fontFamily" value="Ubuntu"/>
+ <property key="labeling/fontItalic" value="false"/>
+ <property key="labeling/fontLetterSpacing" value="0"/>
+ <property key="labeling/fontLimitPixelSize" value="false"/>
+ <property key="labeling/fontMaxPixelSize" value="10000"/>
+ <property key="labeling/fontMinPixelSize" value="3"/>
+ <property key="labeling/fontSize" value="11"/>
+ <property key="labeling/fontSizeInMapUnits" value="false"/>
+ <property key="labeling/fontSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/fontStrikeout" value="false"/>
+ <property key="labeling/fontUnderline" value="false"/>
+ <property key="labeling/fontWeight" value="63"/>
+ <property key="labeling/fontWordSpacing" value="0"/>
+ <property key="labeling/formatNumbers" value="false"/>
+ <property key="labeling/isExpression" value="true"/>
+ <property key="labeling/labelOffsetInMapUnits" value="true"/>
+ <property key="labeling/labelOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/labelPerPart" value="false"/>
+ <property key="labeling/leftDirectionSymbol" value="<"/>
+ <property key="labeling/limitNumLabels" value="false"/>
+ <property key="labeling/maxCurvedCharAngleIn" value="20"/>
+ <property key="labeling/maxCurvedCharAngleOut" value="-20"/>
+ <property key="labeling/maxNumLabels" value="2000"/>
+ <property key="labeling/mergeLines" value="false"/>
+ <property key="labeling/minFeatureSize" value="0"/>
+ <property key="labeling/multilineAlign" value="0"/>
+ <property key="labeling/multilineHeight" value="1"/>
+ <property key="labeling/namedStyle" value="Medium"/>
+ <property key="labeling/obstacle" value="true"/>
+ <property key="labeling/obstacleFactor" value="1"/>
+ <property key="labeling/obstacleType" value="0"/>
+ <property key="labeling/offsetType" value="0"/>
+ <property key="labeling/placeDirectionSymbol" value="0"/>
+ <property key="labeling/placement" value="2"/>
+ <property key="labeling/placementFlags" value="10"/>
+ <property key="labeling/plussign" value="false"/>
+ <property key="labeling/predefinedPositionOrder" value="TR,TL,BR,BL,R,L,TSR,BSR"/>
+ <property key="labeling/preserveRotation" value="true"/>
+ <property key="labeling/previewBkgrdColor" value="#ffffff"/>
+ <property key="labeling/priority" value="5"/>
+ <property key="labeling/quadOffset" value="4"/>
+ <property key="labeling/repeatDistance" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMaxScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMinScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/repeatDistanceUnit" value="1"/>
+ <property key="labeling/reverseDirectionSymbol" value="false"/>
+ <property key="labeling/rightDirectionSymbol" value=">"/>
+ <property key="labeling/scaleMax" value="10000000"/>
+ <property key="labeling/scaleMin" value="1"/>
+ <property key="labeling/scaleVisibility" value="false"/>
+ <property key="labeling/shadowBlendMode" value="6"/>
+ <property key="labeling/shadowColorB" value="0"/>
+ <property key="labeling/shadowColorG" value="0"/>
+ <property key="labeling/shadowColorR" value="0"/>
+ <property key="labeling/shadowDraw" value="false"/>
+ <property key="labeling/shadowOffsetAngle" value="135"/>
+ <property key="labeling/shadowOffsetDist" value="1"/>
+ <property key="labeling/shadowOffsetGlobal" value="true"/>
+ <property key="labeling/shadowOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowOffsetUnits" value="1"/>
+ <property key="labeling/shadowRadius" value="1.5"/>
+ <property key="labeling/shadowRadiusAlphaOnly" value="false"/>
+ <property key="labeling/shadowRadiusMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowRadiusUnits" value="1"/>
+ <property key="labeling/shadowScale" value="100"/>
+ <property key="labeling/shadowTransparency" value="30"/>
+ <property key="labeling/shadowUnder" value="0"/>
+ <property key="labeling/shapeBlendMode" value="0"/>
+ <property key="labeling/shapeBorderColorA" value="255"/>
+ <property key="labeling/shapeBorderColorB" value="128"/>
+ <property key="labeling/shapeBorderColorG" value="128"/>
+ <property key="labeling/shapeBorderColorR" value="128"/>
+ <property key="labeling/shapeBorderWidth" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeBorderWidthUnits" value="1"/>
+ <property key="labeling/shapeDraw" value="false"/>
+ <property key="labeling/shapeFillColorA" value="255"/>
+ <property key="labeling/shapeFillColorB" value="255"/>
+ <property key="labeling/shapeFillColorG" value="255"/>
+ <property key="labeling/shapeFillColorR" value="255"/>
+ <property key="labeling/shapeJoinStyle" value="64"/>
+ <property key="labeling/shapeOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeOffsetUnits" value="1"/>
+ <property key="labeling/shapeOffsetX" value="0"/>
+ <property key="labeling/shapeOffsetY" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeRadiiUnits" value="1"/>
+ <property key="labeling/shapeRadiiX" value="0"/>
+ <property key="labeling/shapeRadiiY" value="0"/>
+ <property key="labeling/shapeRotation" value="0"/>
+ <property key="labeling/shapeRotationType" value="0"/>
+ <property key="labeling/shapeSVGFile" value=""/>
+ <property key="labeling/shapeSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeSizeType" value="0"/>
+ <property key="labeling/shapeSizeUnits" value="1"/>
+ <property key="labeling/shapeSizeX" value="0"/>
+ <property key="labeling/shapeSizeY" value="0"/>
+ <property key="labeling/shapeTransparency" value="0"/>
+ <property key="labeling/shapeType" value="0"/>
+ <property key="labeling/textColorA" value="255"/>
+ <property key="labeling/textColorB" value="0"/>
+ <property key="labeling/textColorG" value="0"/>
+ <property key="labeling/textColorR" value="0"/>
+ <property key="labeling/textTransp" value="0"/>
+ <property key="labeling/upsidedownLabels" value="0"/>
+ <property key="labeling/wrapChar" value=""/>
+ <property key="labeling/xOffset" value="0"/>
+ <property key="labeling/yOffset" value="0"/>
+ <property key="labeling/zIndex" value="0"/>
+ <property key="variableNames" value="_fields_"/>
+ <property key="variableValues" value=""/>
+ </customproperties>
+ <blendMode>0</blendMode>
+ <featureBlendMode>0</featureBlendMode>
+ <layerTransparency>0</layerTransparency>
+ <SingleCategoryDiagramRenderer diagramType="Histogram" sizeLegend="0" attributeLegend="1">
+ <DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" sizeScale="0,0,0,0,0,0" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="0,0,0,0,0,0" sizeType="MM" lineSizeType="MM" minScaleDenominator="100000">
+ <fontProperties description="Ubuntu,11,-1,5,50,0,0,0,0,0" style=""/>
+ <attribute field="" color="#000000" label=""/>
+ </DiagramCategory>
+ <symbol alpha="1" clip_to_extent="1" type="marker" name="sizeSymbol">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_color" v="0,0,0,255"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0"/>
+ <prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="diameter"/>
+ <prop k="size" v="2"/>
+ <prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ </SingleCategoryDiagramRenderer>
+ <DiagramLayerSettings yPosColumn="-1" showColumn="-1" linePlacementFlags="10" placement="2" dist="0" xPosColumn="-1" priority="0" obstacle="0" zIndex="0" showAll="1"/>
+ <annotationform></annotationform>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions default="-1"/>
+ <attributetableconfig actionWidgetStyle="dropDown" sortExpression="" sortOrder="0">
+ <columns>
+ <column width="-1" hidden="0" type="field" name="pkuid"/>
+ <column width="-1" hidden="0" type="field" name="text"/>
+ <column width="-1" hidden="1" type="actions"/>
+ </columns>
+ </attributetableconfig>
+ <editform></editform>
+ <editforminit/>
+ <editforminitcodesource>0</editforminitcodesource>
+ <editforminitfilepath></editforminitfilepath>
+ <editforminitcode><![CDATA[# -*- coding: utf-8 -*-
+"""
+QGIS forms can have a Python function that is called when the form is
+opened.
+
+Use this function to add extra logic to your forms.
+
+Enter the name of the function in the "Python Init function"
+field.
+An example follows:
+"""
+from qgis.PyQt.QtWidgets import QWidget
+
+def my_form_open(dialog, layer, feature):
+ geom = feature.geometry()
+ control = dialog.findChild(QWidget, "MyLineEdit")
+]]></editforminitcode>
+ <featformsuppress>0</featformsuppress>
+ <editorlayout>generatedlayout</editorlayout>
+ <widgets/>
+ <conditionalstyles>
+ <rowstyles/>
+ <fieldstyles/>
+ </conditionalstyles>
+ <layerGeometryType>1</layerGeometryType>
+</qgis>
diff --git a/tests/testdata/labeling/line_placement_5.qml b/tests/testdata/labeling/line_placement_5.qml
new file mode 100644
index 0000000..2721989
--- /dev/null
+++ b/tests/testdata/labeling/line_placement_5.qml
@@ -0,0 +1,249 @@
+<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
+<qgis version="2.99.0-Master" simplifyAlgorithm="0" minimumScale="100000" maximumScale="1e+08" simplifyDrawingHints="1" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1">
+ <edittypes>
+ <edittype widgetv2type="TextEdit" name="pkuid">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ <edittype widgetv2type="TextEdit" name="text">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ </edittypes>
+ <renderer-v2 forceraster="0" symbollevels="0" type="singleSymbol" enableorderby="0">
+ <symbols>
+ <symbol alpha="1" clip_to_extent="1" type="line" name="0">
+ <layer pass="0" class="SimpleLine" locked="0">
+ <prop k="capstyle" v="square"/>
+ <prop k="customdash" v="5;2"/>
+ <prop k="customdash_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="customdash_unit" v="MM"/>
+ <prop k="draw_inside_polygon" v="0"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="line_color" v="243,2,47,255"/>
+ <prop k="line_style" v="solid"/>
+ <prop k="line_width" v="0.26"/>
+ <prop k="line_width_unit" v="MM"/>
+ <prop k="offset" v="0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="use_custom_dash" v="0"/>
+ <prop k="width_map_unit_scale" v="0,0,0,0,0,0"/>
+ </layer>
+ </symbol>
+ </symbols>
+ <rotation/>
+ <sizescale scalemethod="diameter"/>
+ </renderer-v2>
+ <labeling type="simple"/>
+ <customproperties>
+ <property key="embeddedWidgets/count" value="0"/>
+ <property key="labeling" value="pal"/>
+ <property key="labeling/addDirectionSymbol" value="false"/>
+ <property key="labeling/angleOffset" value="0"/>
+ <property key="labeling/blendMode" value="0"/>
+ <property key="labeling/bufferBlendMode" value="0"/>
+ <property key="labeling/bufferColorA" value="255"/>
+ <property key="labeling/bufferColorB" value="255"/>
+ <property key="labeling/bufferColorG" value="255"/>
+ <property key="labeling/bufferColorR" value="255"/>
+ <property key="labeling/bufferDraw" value="false"/>
+ <property key="labeling/bufferJoinStyle" value="64"/>
+ <property key="labeling/bufferNoFill" value="false"/>
+ <property key="labeling/bufferSize" value="1"/>
+ <property key="labeling/bufferSizeInMapUnits" value="false"/>
+ <property key="labeling/bufferSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/bufferTransp" value="0"/>
+ <property key="labeling/centroidInside" value="false"/>
+ <property key="labeling/centroidWhole" value="false"/>
+ <property key="labeling/decimals" value="3"/>
+ <property key="labeling/displayAll" value="false"/>
+ <property key="labeling/dist" value="0"/>
+ <property key="labeling/distInMapUnits" value="false"/>
+ <property key="labeling/distMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/drawLabels" value="false"/>
+ <property key="labeling/enabled" value="false"/>
+ <property key="labeling/fieldName" value=""/>
+ <property key="labeling/fitInPolygonOnly" value="false"/>
+ <property key="labeling/fontCapitals" value="0"/>
+ <property key="labeling/fontFamily" value="Ubuntu"/>
+ <property key="labeling/fontItalic" value="false"/>
+ <property key="labeling/fontLetterSpacing" value="0"/>
+ <property key="labeling/fontLimitPixelSize" value="false"/>
+ <property key="labeling/fontMaxPixelSize" value="10000"/>
+ <property key="labeling/fontMinPixelSize" value="3"/>
+ <property key="labeling/fontSize" value="11"/>
+ <property key="labeling/fontSizeInMapUnits" value="false"/>
+ <property key="labeling/fontSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/fontStrikeout" value="false"/>
+ <property key="labeling/fontUnderline" value="false"/>
+ <property key="labeling/fontWeight" value="50"/>
+ <property key="labeling/fontWordSpacing" value="0"/>
+ <property key="labeling/formatNumbers" value="false"/>
+ <property key="labeling/isExpression" value="true"/>
+ <property key="labeling/labelOffsetInMapUnits" value="true"/>
+ <property key="labeling/labelOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/labelPerPart" value="false"/>
+ <property key="labeling/leftDirectionSymbol" value="<"/>
+ <property key="labeling/limitNumLabels" value="false"/>
+ <property key="labeling/maxCurvedCharAngleIn" value="25"/>
+ <property key="labeling/maxCurvedCharAngleOut" value="-25"/>
+ <property key="labeling/maxNumLabels" value="2000"/>
+ <property key="labeling/mergeLines" value="false"/>
+ <property key="labeling/minFeatureSize" value="0"/>
+ <property key="labeling/multilineAlign" value="4294967295"/>
+ <property key="labeling/multilineHeight" value="1"/>
+ <property key="labeling/namedStyle" value="Medium Italic"/>
+ <property key="labeling/obstacle" value="true"/>
+ <property key="labeling/obstacleFactor" value="1"/>
+ <property key="labeling/obstacleType" value="0"/>
+ <property key="labeling/offsetType" value="0"/>
+ <property key="labeling/placeDirectionSymbol" value="0"/>
+ <property key="labeling/placement" value="2"/>
+ <property key="labeling/placementFlags" value="10"/>
+ <property key="labeling/plussign" value="false"/>
+ <property key="labeling/predefinedPositionOrder" value="TR,TL,BR,BL,R,L,TSR,BSR"/>
+ <property key="labeling/preserveRotation" value="true"/>
+ <property key="labeling/previewBkgrdColor" value="#ffffff"/>
+ <property key="labeling/priority" value="5"/>
+ <property key="labeling/quadOffset" value="4"/>
+ <property key="labeling/repeatDistance" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/repeatDistanceUnit" value="1"/>
+ <property key="labeling/reverseDirectionSymbol" value="false"/>
+ <property key="labeling/rightDirectionSymbol" value=">"/>
+ <property key="labeling/scaleMax" value="10000000"/>
+ <property key="labeling/scaleMin" value="1"/>
+ <property key="labeling/scaleVisibility" value="false"/>
+ <property key="labeling/shadowBlendMode" value="6"/>
+ <property key="labeling/shadowColorB" value="0"/>
+ <property key="labeling/shadowColorG" value="0"/>
+ <property key="labeling/shadowColorR" value="0"/>
+ <property key="labeling/shadowDraw" value="false"/>
+ <property key="labeling/shadowOffsetAngle" value="135"/>
+ <property key="labeling/shadowOffsetDist" value="1"/>
+ <property key="labeling/shadowOffsetGlobal" value="true"/>
+ <property key="labeling/shadowOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowOffsetUnits" value="1"/>
+ <property key="labeling/shadowRadius" value="1.5"/>
+ <property key="labeling/shadowRadiusAlphaOnly" value="false"/>
+ <property key="labeling/shadowRadiusMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowRadiusUnits" value="1"/>
+ <property key="labeling/shadowScale" value="100"/>
+ <property key="labeling/shadowTransparency" value="30"/>
+ <property key="labeling/shadowUnder" value="0"/>
+ <property key="labeling/shapeBlendMode" value="0"/>
+ <property key="labeling/shapeBorderColorA" value="255"/>
+ <property key="labeling/shapeBorderColorB" value="128"/>
+ <property key="labeling/shapeBorderColorG" value="128"/>
+ <property key="labeling/shapeBorderColorR" value="128"/>
+ <property key="labeling/shapeBorderWidth" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeBorderWidthUnits" value="1"/>
+ <property key="labeling/shapeDraw" value="false"/>
+ <property key="labeling/shapeFillColorA" value="255"/>
+ <property key="labeling/shapeFillColorB" value="255"/>
+ <property key="labeling/shapeFillColorG" value="255"/>
+ <property key="labeling/shapeFillColorR" value="255"/>
+ <property key="labeling/shapeJoinStyle" value="64"/>
+ <property key="labeling/shapeOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeOffsetUnits" value="1"/>
+ <property key="labeling/shapeOffsetX" value="0"/>
+ <property key="labeling/shapeOffsetY" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeRadiiUnits" value="1"/>
+ <property key="labeling/shapeRadiiX" value="0"/>
+ <property key="labeling/shapeRadiiY" value="0"/>
+ <property key="labeling/shapeRotation" value="0"/>
+ <property key="labeling/shapeRotationType" value="0"/>
+ <property key="labeling/shapeSVGFile" value=""/>
+ <property key="labeling/shapeSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeSizeType" value="0"/>
+ <property key="labeling/shapeSizeUnits" value="1"/>
+ <property key="labeling/shapeSizeX" value="0"/>
+ <property key="labeling/shapeSizeY" value="0"/>
+ <property key="labeling/shapeTransparency" value="0"/>
+ <property key="labeling/shapeType" value="0"/>
+ <property key="labeling/textColorA" value="255"/>
+ <property key="labeling/textColorB" value="0"/>
+ <property key="labeling/textColorG" value="0"/>
+ <property key="labeling/textColorR" value="0"/>
+ <property key="labeling/textTransp" value="0"/>
+ <property key="labeling/upsidedownLabels" value="0"/>
+ <property key="labeling/wrapChar" value=""/>
+ <property key="labeling/xOffset" value="0"/>
+ <property key="labeling/yOffset" value="0"/>
+ <property key="labeling/zIndex" value="0"/>
+ <property key="variableNames" value="_fields_"/>
+ <property key="variableValues" value=""/>
+ </customproperties>
+ <blendMode>0</blendMode>
+ <featureBlendMode>0</featureBlendMode>
+ <layerTransparency>0</layerTransparency>
+ <SingleCategoryDiagramRenderer diagramType="Histogram" sizeLegend="0" attributeLegend="1">
+ <DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" sizeScale="0,0,0,0,0,0" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="0,0,0,0,0,0" sizeType="MM" lineSizeType="MM" minScaleDenominator="100000">
+ <fontProperties description="Ubuntu,11,-1,5,50,0,0,0,0,0" style=""/>
+ </DiagramCategory>
+ <symbol alpha="1" clip_to_extent="1" type="marker" name="sizeSymbol">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_color" v="0,0,0,255"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0"/>
+ <prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="diameter"/>
+ <prop k="size" v="2"/>
+ <prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ </SingleCategoryDiagramRenderer>
+ <DiagramLayerSettings yPosColumn="-1" showColumn="-1" linePlacementFlags="10" placement="2" dist="0" xPosColumn="-1" priority="0" obstacle="0" zIndex="0" showAll="1"/>
+ <annotationform></annotationform>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions default="-1"/>
+ <attributetableconfig actionWidgetStyle="dropDown" sortExpression="" sortOrder="0">
+ <columns>
+ <column width="-1" hidden="0" type="field" name="pkuid"/>
+ <column width="-1" hidden="0" type="field" name="text"/>
+ <column width="-1" hidden="1" type="actions"/>
+ </columns>
+ </attributetableconfig>
+ <editform></editform>
+ <editforminit/>
+ <editforminitcodesource>0</editforminitcodesource>
+ <editforminitfilepath></editforminitfilepath>
+ <editforminitcode><![CDATA[# -*- coding: utf-8 -*-
+"""
+QGIS forms can have a Python function that is called when the form is
+opened.
+
+Use this function to add extra logic to your forms.
+
+Enter the name of the function in the "Python Init function"
+field.
+An example follows:
+"""
+from qgis.PyQt.QtWidgets import QWidget
+
+def my_form_open(dialog, layer, feature):
+ geom = feature.geometry()
+ control = dialog.findChild(QWidget, "MyLineEdit")
+]]></editforminitcode>
+ <featformsuppress>0</featformsuppress>
+ <editorlayout>generatedlayout</editorlayout>
+ <widgets/>
+ <conditionalstyles>
+ <rowstyles/>
+ <fieldstyles/>
+ </conditionalstyles>
+ <layerGeometryType>1</layerGeometryType>
+</qgis>
diff --git a/tests/testdata/labeling/pal_features_v3.sqlite b/tests/testdata/labeling/pal_features_v3.sqlite
index 2dc50ce..2deaa81 100644
Binary files a/tests/testdata/labeling/pal_features_v3.sqlite and b/tests/testdata/labeling/pal_features_v3.sqlite differ
diff --git a/tests/testdata/labeling/polygon_perimeter.qml b/tests/testdata/labeling/polygon_perimeter.qml
new file mode 100644
index 0000000..6f166d0
--- /dev/null
+++ b/tests/testdata/labeling/polygon_perimeter.qml
@@ -0,0 +1,272 @@
+<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
+<qgis version="2.99.0-Master" simplifyAlgorithm="0" minimumScale="100000" maximumScale="1e+08" simplifyDrawingHints="1" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1">
+ <edittypes>
+ <edittype widgetv2type="TextEdit" name="pkuid">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ <edittype widgetv2type="TextEdit" name="ftype">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ <edittype widgetv2type="TextEdit" name="text">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ </edittypes>
+ <renderer-v2 forceraster="0" symbollevels="0" type="singleSymbol" enableorderby="0">
+ <symbols>
+ <symbol alpha="1" clip_to_extent="1" type="fill" name="0">
+ <layer pass="0" class="SimpleFill" locked="0">
+ <prop k="border_width_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="color" v="133,149,161,255"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_color" v="0,0,0,255"/>
+ <prop k="outline_style" v="no"/>
+ <prop k="outline_width" v="0.26"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="style" v="solid"/>
+ </layer>
+ </symbol>
+ </symbols>
+ <rotation/>
+ <sizescale scalemethod="diameter"/>
+ </renderer-v2>
+ <labeling type="simple"/>
+ <customproperties>
+ <property key="embeddedWidgets/count" value="0"/>
+ <property key="labeling" value="pal"/>
+ <property key="labeling/addDirectionSymbol" value="false"/>
+ <property key="labeling/angleOffset" value="0"/>
+ <property key="labeling/blendMode" value="0"/>
+ <property key="labeling/bufferBlendMode" value="0"/>
+ <property key="labeling/bufferColorA" value="255"/>
+ <property key="labeling/bufferColorB" value="255"/>
+ <property key="labeling/bufferColorG" value="255"/>
+ <property key="labeling/bufferColorR" value="255"/>
+ <property key="labeling/bufferDraw" value="false"/>
+ <property key="labeling/bufferJoinStyle" value="64"/>
+ <property key="labeling/bufferNoFill" value="false"/>
+ <property key="labeling/bufferSize" value="1"/>
+ <property key="labeling/bufferSizeInMapUnits" value="false"/>
+ <property key="labeling/bufferSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/bufferTransp" value="0"/>
+ <property key="labeling/centroidInside" value="false"/>
+ <property key="labeling/centroidWhole" value="false"/>
+ <property key="labeling/decimals" value="3"/>
+ <property key="labeling/displayAll" value="false"/>
+ <property key="labeling/dist" value="0"/>
+ <property key="labeling/distInMapUnits" value="false"/>
+ <property key="labeling/distMapUnitMaxScale" value="0"/>
+ <property key="labeling/distMapUnitMinScale" value="0"/>
+ <property key="labeling/distMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/drawLabels" value="true"/>
+ <property key="labeling/enabled" value="true"/>
+ <property key="labeling/fieldName" value="text"/>
+ <property key="labeling/fitInPolygonOnly" value="false"/>
+ <property key="labeling/fontCapitals" value="0"/>
+ <property key="labeling/fontFamily" value="Ubuntu"/>
+ <property key="labeling/fontItalic" value="true"/>
+ <property key="labeling/fontLetterSpacing" value="0"/>
+ <property key="labeling/fontLimitPixelSize" value="false"/>
+ <property key="labeling/fontMaxPixelSize" value="10000"/>
+ <property key="labeling/fontMinPixelSize" value="3"/>
+ <property key="labeling/fontSize" value="11"/>
+ <property key="labeling/fontSizeInMapUnits" value="false"/>
+ <property key="labeling/fontSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/fontStrikeout" value="false"/>
+ <property key="labeling/fontUnderline" value="false"/>
+ <property key="labeling/fontWeight" value="63"/>
+ <property key="labeling/fontWordSpacing" value="0"/>
+ <property key="labeling/formatNumbers" value="false"/>
+ <property key="labeling/isExpression" value="false"/>
+ <property key="labeling/labelOffsetInMapUnits" value="true"/>
+ <property key="labeling/labelOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/labelPerPart" value="false"/>
+ <property key="labeling/leftDirectionSymbol" value="<"/>
+ <property key="labeling/limitNumLabels" value="false"/>
+ <property key="labeling/maxCurvedCharAngleIn" value="20"/>
+ <property key="labeling/maxCurvedCharAngleOut" value="-20"/>
+ <property key="labeling/maxNumLabels" value="2000"/>
+ <property key="labeling/mergeLines" value="false"/>
+ <property key="labeling/minFeatureSize" value="0"/>
+ <property key="labeling/multilineAlign" value="0"/>
+ <property key="labeling/multilineHeight" value="1"/>
+ <property key="labeling/namedStyle" value="Medium Italic"/>
+ <property key="labeling/obstacle" value="true"/>
+ <property key="labeling/obstacleFactor" value="1"/>
+ <property key="labeling/obstacleType" value="0"/>
+ <property key="labeling/offsetType" value="0"/>
+ <property key="labeling/placeDirectionSymbol" value="0"/>
+ <property key="labeling/placement" value="1"/>
+ <property key="labeling/placementFlags" value="10"/>
+ <property key="labeling/plussign" value="false"/>
+ <property key="labeling/predefinedPositionOrder" value="TR,TL,BR,BL,R,L,TSR,BSR"/>
+ <property key="labeling/preserveRotation" value="true"/>
+ <property key="labeling/previewBkgrdColor" value="#ffffff"/>
+ <property key="labeling/priority" value="5"/>
+ <property key="labeling/quadOffset" value="4"/>
+ <property key="labeling/repeatDistance" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMaxScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMinScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/repeatDistanceUnit" value="1"/>
+ <property key="labeling/reverseDirectionSymbol" value="false"/>
+ <property key="labeling/rightDirectionSymbol" value=">"/>
+ <property key="labeling/scaleMax" value="10000000"/>
+ <property key="labeling/scaleMin" value="1"/>
+ <property key="labeling/scaleVisibility" value="false"/>
+ <property key="labeling/shadowBlendMode" value="6"/>
+ <property key="labeling/shadowColorB" value="0"/>
+ <property key="labeling/shadowColorG" value="0"/>
+ <property key="labeling/shadowColorR" value="0"/>
+ <property key="labeling/shadowDraw" value="false"/>
+ <property key="labeling/shadowOffsetAngle" value="135"/>
+ <property key="labeling/shadowOffsetDist" value="1"/>
+ <property key="labeling/shadowOffsetGlobal" value="true"/>
+ <property key="labeling/shadowOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowOffsetUnits" value="1"/>
+ <property key="labeling/shadowRadius" value="1.5"/>
+ <property key="labeling/shadowRadiusAlphaOnly" value="false"/>
+ <property key="labeling/shadowRadiusMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowRadiusUnits" value="1"/>
+ <property key="labeling/shadowScale" value="100"/>
+ <property key="labeling/shadowTransparency" value="30"/>
+ <property key="labeling/shadowUnder" value="0"/>
+ <property key="labeling/shapeBlendMode" value="0"/>
+ <property key="labeling/shapeBorderColorA" value="255"/>
+ <property key="labeling/shapeBorderColorB" value="128"/>
+ <property key="labeling/shapeBorderColorG" value="128"/>
+ <property key="labeling/shapeBorderColorR" value="128"/>
+ <property key="labeling/shapeBorderWidth" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeBorderWidthUnits" value="1"/>
+ <property key="labeling/shapeDraw" value="false"/>
+ <property key="labeling/shapeFillColorA" value="255"/>
+ <property key="labeling/shapeFillColorB" value="255"/>
+ <property key="labeling/shapeFillColorG" value="255"/>
+ <property key="labeling/shapeFillColorR" value="255"/>
+ <property key="labeling/shapeJoinStyle" value="64"/>
+ <property key="labeling/shapeOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeOffsetUnits" value="1"/>
+ <property key="labeling/shapeOffsetX" value="0"/>
+ <property key="labeling/shapeOffsetY" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeRadiiUnits" value="1"/>
+ <property key="labeling/shapeRadiiX" value="0"/>
+ <property key="labeling/shapeRadiiY" value="0"/>
+ <property key="labeling/shapeRotation" value="0"/>
+ <property key="labeling/shapeRotationType" value="0"/>
+ <property key="labeling/shapeSVGFile" value=""/>
+ <property key="labeling/shapeSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeSizeType" value="0"/>
+ <property key="labeling/shapeSizeUnits" value="1"/>
+ <property key="labeling/shapeSizeX" value="0"/>
+ <property key="labeling/shapeSizeY" value="0"/>
+ <property key="labeling/shapeTransparency" value="0"/>
+ <property key="labeling/shapeType" value="0"/>
+ <property key="labeling/textColorA" value="255"/>
+ <property key="labeling/textColorB" value="0"/>
+ <property key="labeling/textColorG" value="0"/>
+ <property key="labeling/textColorR" value="0"/>
+ <property key="labeling/textTransp" value="0"/>
+ <property key="labeling/upsidedownLabels" value="0"/>
+ <property key="labeling/wrapChar" value=""/>
+ <property key="labeling/xOffset" value="0"/>
+ <property key="labeling/yOffset" value="0"/>
+ <property key="labeling/zIndex" value="0"/>
+ <property key="variableNames" value="_fields_"/>
+ <property key="variableValues" value=""/>
+ </customproperties>
+ <blendMode>0</blendMode>
+ <featureBlendMode>0</featureBlendMode>
+ <layerTransparency>0</layerTransparency>
+ <SingleCategoryDiagramRenderer diagramType="Histogram" sizeLegend="0" attributeLegend="1">
+ <DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" sizeScale="0,0,0,0,0,0" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="0,0,0,0,0,0" sizeType="MM" lineSizeType="MM" minScaleDenominator="100000">
+ <fontProperties description="Ubuntu,11,-1,5,50,0,0,0,0,0" style=""/>
+ <attribute field="" color="#000000" label=""/>
+ </DiagramCategory>
+ <symbol alpha="1" clip_to_extent="1" type="marker" name="sizeSymbol">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_color" v="0,0,0,255"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0"/>
+ <prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="diameter"/>
+ <prop k="size" v="2"/>
+ <prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ </SingleCategoryDiagramRenderer>
+ <DiagramLayerSettings yPosColumn="-1" showColumn="-1" linePlacementFlags="10" placement="0" dist="0" xPosColumn="-1" priority="0" obstacle="0" zIndex="0" showAll="1"/>
+ <annotationform></annotationform>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions default="-1"/>
+ <attributetableconfig actionWidgetStyle="dropDown" sortExpression="" sortOrder="0">
+ <columns>
+ <column width="-1" hidden="0" type="field" name="pkuid"/>
+ <column width="-1" hidden="0" type="field" name="ftype"/>
+ <column width="-1" hidden="0" type="field" name="text"/>
+ <column width="-1" hidden="1" type="actions"/>
+ </columns>
+ </attributetableconfig>
+ <editform></editform>
+ <editforminit/>
+ <editforminitcodesource>0</editforminitcodesource>
+ <editforminitfilepath></editforminitfilepath>
+ <editforminitcode><![CDATA[# -*- coding: utf-8 -*-
+"""
+QGIS forms can have a Python function that is called when the form is
+opened.
+
+Use this function to add extra logic to your forms.
+
+Enter the name of the function in the "Python Init function"
+field.
+An example follows:
+"""
+from PyQt4.QtGui import QWidget
+
+def my_form_open(dialog, layer, feature):
+ geom = feature.geometry()
+ control = dialog.findChild(QWidget, "MyLineEdit")
+]]></editforminitcode>
+ <featformsuppress>0</featformsuppress>
+ <editorlayout>generatedlayout</editorlayout>
+ <widgets/>
+ <conditionalstyles>
+ <rowstyles/>
+ <fieldstyles/>
+ </conditionalstyles>
+ <layerGeometryType>2</layerGeometryType>
+</qgis>
diff --git a/tests/testdata/labeling/polygon_small.qml b/tests/testdata/labeling/polygon_small.qml
new file mode 100644
index 0000000..84c31bd
--- /dev/null
+++ b/tests/testdata/labeling/polygon_small.qml
@@ -0,0 +1,272 @@
+<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
+<qgis version="2.99.0-Master" simplifyAlgorithm="0" minimumScale="100000" maximumScale="1e+08" simplifyDrawingHints="1" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1">
+ <edittypes>
+ <edittype widgetv2type="TextEdit" name="pkuid">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ <edittype widgetv2type="TextEdit" name="ftype">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ <edittype widgetv2type="TextEdit" name="text">
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
+ </edittype>
+ </edittypes>
+ <renderer-v2 forceraster="0" symbollevels="0" type="singleSymbol" enableorderby="0">
+ <symbols>
+ <symbol alpha="1" clip_to_extent="1" type="fill" name="0">
+ <layer pass="0" class="SimpleFill" locked="0">
+ <prop k="border_width_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="color" v="133,149,161,255"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_color" v="0,0,0,255"/>
+ <prop k="outline_style" v="no"/>
+ <prop k="outline_width" v="0.26"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="style" v="solid"/>
+ </layer>
+ </symbol>
+ </symbols>
+ <rotation/>
+ <sizescale scalemethod="diameter"/>
+ </renderer-v2>
+ <labeling type="simple"/>
+ <customproperties>
+ <property key="embeddedWidgets/count" value="0"/>
+ <property key="labeling" value="pal"/>
+ <property key="labeling/addDirectionSymbol" value="false"/>
+ <property key="labeling/angleOffset" value="0"/>
+ <property key="labeling/blendMode" value="0"/>
+ <property key="labeling/bufferBlendMode" value="0"/>
+ <property key="labeling/bufferColorA" value="255"/>
+ <property key="labeling/bufferColorB" value="255"/>
+ <property key="labeling/bufferColorG" value="255"/>
+ <property key="labeling/bufferColorR" value="255"/>
+ <property key="labeling/bufferDraw" value="false"/>
+ <property key="labeling/bufferJoinStyle" value="64"/>
+ <property key="labeling/bufferNoFill" value="false"/>
+ <property key="labeling/bufferSize" value="1"/>
+ <property key="labeling/bufferSizeInMapUnits" value="false"/>
+ <property key="labeling/bufferSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/bufferSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/bufferTransp" value="0"/>
+ <property key="labeling/centroidInside" value="false"/>
+ <property key="labeling/centroidWhole" value="false"/>
+ <property key="labeling/decimals" value="3"/>
+ <property key="labeling/displayAll" value="false"/>
+ <property key="labeling/dist" value="0"/>
+ <property key="labeling/distInMapUnits" value="false"/>
+ <property key="labeling/distMapUnitMaxScale" value="0"/>
+ <property key="labeling/distMapUnitMinScale" value="0"/>
+ <property key="labeling/distMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/drawLabels" value="true"/>
+ <property key="labeling/enabled" value="true"/>
+ <property key="labeling/fieldName" value="text"/>
+ <property key="labeling/fitInPolygonOnly" value="false"/>
+ <property key="labeling/fontCapitals" value="0"/>
+ <property key="labeling/fontFamily" value="Ubuntu"/>
+ <property key="labeling/fontItalic" value="true"/>
+ <property key="labeling/fontLetterSpacing" value="0"/>
+ <property key="labeling/fontLimitPixelSize" value="false"/>
+ <property key="labeling/fontMaxPixelSize" value="10000"/>
+ <property key="labeling/fontMinPixelSize" value="3"/>
+ <property key="labeling/fontSize" value="11"/>
+ <property key="labeling/fontSizeInMapUnits" value="false"/>
+ <property key="labeling/fontSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/fontSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/fontStrikeout" value="false"/>
+ <property key="labeling/fontUnderline" value="false"/>
+ <property key="labeling/fontWeight" value="63"/>
+ <property key="labeling/fontWordSpacing" value="0"/>
+ <property key="labeling/formatNumbers" value="false"/>
+ <property key="labeling/isExpression" value="false"/>
+ <property key="labeling/labelOffsetInMapUnits" value="true"/>
+ <property key="labeling/labelOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/labelOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/labelPerPart" value="false"/>
+ <property key="labeling/leftDirectionSymbol" value="<"/>
+ <property key="labeling/limitNumLabels" value="false"/>
+ <property key="labeling/maxCurvedCharAngleIn" value="20"/>
+ <property key="labeling/maxCurvedCharAngleOut" value="-20"/>
+ <property key="labeling/maxNumLabels" value="2000"/>
+ <property key="labeling/mergeLines" value="false"/>
+ <property key="labeling/minFeatureSize" value="0"/>
+ <property key="labeling/multilineAlign" value="0"/>
+ <property key="labeling/multilineHeight" value="1"/>
+ <property key="labeling/namedStyle" value="Medium Italic"/>
+ <property key="labeling/obstacle" value="true"/>
+ <property key="labeling/obstacleFactor" value="1"/>
+ <property key="labeling/obstacleType" value="0"/>
+ <property key="labeling/offsetType" value="0"/>
+ <property key="labeling/placeDirectionSymbol" value="0"/>
+ <property key="labeling/placement" value="2"/>
+ <property key="labeling/placementFlags" value="10"/>
+ <property key="labeling/plussign" value="false"/>
+ <property key="labeling/predefinedPositionOrder" value="TR,TL,BR,BL,R,L,TSR,BSR"/>
+ <property key="labeling/preserveRotation" value="true"/>
+ <property key="labeling/previewBkgrdColor" value="#ffffff"/>
+ <property key="labeling/priority" value="5"/>
+ <property key="labeling/quadOffset" value="4"/>
+ <property key="labeling/repeatDistance" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMaxScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitMinScale" value="0"/>
+ <property key="labeling/repeatDistanceMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/repeatDistanceUnit" value="1"/>
+ <property key="labeling/reverseDirectionSymbol" value="false"/>
+ <property key="labeling/rightDirectionSymbol" value=">"/>
+ <property key="labeling/scaleMax" value="10000000"/>
+ <property key="labeling/scaleMin" value="1"/>
+ <property key="labeling/scaleVisibility" value="false"/>
+ <property key="labeling/shadowBlendMode" value="6"/>
+ <property key="labeling/shadowColorB" value="0"/>
+ <property key="labeling/shadowColorG" value="0"/>
+ <property key="labeling/shadowColorR" value="0"/>
+ <property key="labeling/shadowDraw" value="false"/>
+ <property key="labeling/shadowOffsetAngle" value="135"/>
+ <property key="labeling/shadowOffsetDist" value="1"/>
+ <property key="labeling/shadowOffsetGlobal" value="true"/>
+ <property key="labeling/shadowOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowOffsetUnits" value="1"/>
+ <property key="labeling/shadowRadius" value="1.5"/>
+ <property key="labeling/shadowRadiusAlphaOnly" value="false"/>
+ <property key="labeling/shadowRadiusMapUnitMaxScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitMinScale" value="0"/>
+ <property key="labeling/shadowRadiusMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shadowRadiusUnits" value="1"/>
+ <property key="labeling/shadowScale" value="100"/>
+ <property key="labeling/shadowTransparency" value="30"/>
+ <property key="labeling/shadowUnder" value="0"/>
+ <property key="labeling/shapeBlendMode" value="0"/>
+ <property key="labeling/shapeBorderColorA" value="255"/>
+ <property key="labeling/shapeBorderColorB" value="128"/>
+ <property key="labeling/shapeBorderColorG" value="128"/>
+ <property key="labeling/shapeBorderColorR" value="128"/>
+ <property key="labeling/shapeBorderWidth" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeBorderWidthMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeBorderWidthUnits" value="1"/>
+ <property key="labeling/shapeDraw" value="false"/>
+ <property key="labeling/shapeFillColorA" value="255"/>
+ <property key="labeling/shapeFillColorB" value="255"/>
+ <property key="labeling/shapeFillColorG" value="255"/>
+ <property key="labeling/shapeFillColorR" value="255"/>
+ <property key="labeling/shapeJoinStyle" value="64"/>
+ <property key="labeling/shapeOffsetMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeOffsetMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeOffsetUnits" value="1"/>
+ <property key="labeling/shapeOffsetX" value="0"/>
+ <property key="labeling/shapeOffsetY" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeRadiiMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeRadiiUnits" value="1"/>
+ <property key="labeling/shapeRadiiX" value="0"/>
+ <property key="labeling/shapeRadiiY" value="0"/>
+ <property key="labeling/shapeRotation" value="0"/>
+ <property key="labeling/shapeRotationType" value="0"/>
+ <property key="labeling/shapeSVGFile" value=""/>
+ <property key="labeling/shapeSizeMapUnitMaxScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitMinScale" value="0"/>
+ <property key="labeling/shapeSizeMapUnitScale" value="0,0,0,0,0,0"/>
+ <property key="labeling/shapeSizeType" value="0"/>
+ <property key="labeling/shapeSizeUnits" value="1"/>
+ <property key="labeling/shapeSizeX" value="0"/>
+ <property key="labeling/shapeSizeY" value="0"/>
+ <property key="labeling/shapeTransparency" value="0"/>
+ <property key="labeling/shapeType" value="0"/>
+ <property key="labeling/textColorA" value="255"/>
+ <property key="labeling/textColorB" value="0"/>
+ <property key="labeling/textColorG" value="0"/>
+ <property key="labeling/textColorR" value="0"/>
+ <property key="labeling/textTransp" value="0"/>
+ <property key="labeling/upsidedownLabels" value="0"/>
+ <property key="labeling/wrapChar" value=""/>
+ <property key="labeling/xOffset" value="0"/>
+ <property key="labeling/yOffset" value="0"/>
+ <property key="labeling/zIndex" value="0"/>
+ <property key="variableNames" value="_fields_"/>
+ <property key="variableValues" value=""/>
+ </customproperties>
+ <blendMode>0</blendMode>
+ <featureBlendMode>0</featureBlendMode>
+ <layerTransparency>0</layerTransparency>
+ <SingleCategoryDiagramRenderer diagramType="Histogram" sizeLegend="0" attributeLegend="1">
+ <DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" sizeScale="0,0,0,0,0,0" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="0,0,0,0,0,0" sizeType="MM" lineSizeType="MM" minScaleDenominator="100000">
+ <fontProperties description="Ubuntu,11,-1,5,50,0,0,0,0,0" style=""/>
+ <attribute field="" color="#000000" label=""/>
+ </DiagramCategory>
+ <symbol alpha="1" clip_to_extent="1" type="marker" name="sizeSymbol">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_color" v="0,0,0,255"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0"/>
+ <prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="diameter"/>
+ <prop k="size" v="2"/>
+ <prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ </SingleCategoryDiagramRenderer>
+ <DiagramLayerSettings yPosColumn="-1" showColumn="-1" linePlacementFlags="10" placement="0" dist="0" xPosColumn="-1" priority="0" obstacle="0" zIndex="0" showAll="1"/>
+ <annotationform></annotationform>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions default="-1"/>
+ <attributetableconfig actionWidgetStyle="dropDown" sortExpression="" sortOrder="0">
+ <columns>
+ <column width="-1" hidden="0" type="field" name="pkuid"/>
+ <column width="-1" hidden="0" type="field" name="ftype"/>
+ <column width="-1" hidden="0" type="field" name="text"/>
+ <column width="-1" hidden="1" type="actions"/>
+ </columns>
+ </attributetableconfig>
+ <editform></editform>
+ <editforminit/>
+ <editforminitcodesource>0</editforminitcodesource>
+ <editforminitfilepath></editforminitfilepath>
+ <editforminitcode><![CDATA[# -*- coding: utf-8 -*-
+"""
+QGIS forms can have a Python function that is called when the form is
+opened.
+
+Use this function to add extra logic to your forms.
+
+Enter the name of the function in the "Python Init function"
+field.
+An example follows:
+"""
+from PyQt4.QtGui import QWidget
+
+def my_form_open(dialog, layer, feature):
+ geom = feature.geometry()
+ control = dialog.findChild(QWidget, "MyLineEdit")
+]]></editforminitcode>
+ <featformsuppress>0</featformsuppress>
+ <editorlayout>generatedlayout</editorlayout>
+ <widgets/>
+ <conditionalstyles>
+ <rowstyles/>
+ <fieldstyles/>
+ </conditionalstyles>
+ <layerGeometryType>2</layerGeometryType>
+</qgis>
diff --git a/tests/testdata/qgis_server/getcapabilities.txt b/tests/testdata/qgis_server/getcapabilities.txt
index ea62c81..327c7ef 100644
--- a/tests/testdata/qgis_server/getcapabilities.txt
+++ b/tests/testdata/qgis_server/getcapabilities.txt
@@ -1,8 +1,8 @@
-Content-Length: 5250
+Content-Length: 5614
Content-Type: text/xml; charset=utf-8
<?xml version="1.0" encoding="utf-8"?>
-<WMS_Capabilities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.3" xmlns="http://www.opengis.net/wms" xsi:schemaLocation="http://www.opengis.net/wms http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd http://www.qgis.org/wms http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&SERVICE=WMS&REQUEST=GetSchemaExtension" xmlns:sld="http://www.opengis.ne [...]
+<WMS_Capabilities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.3" xmlns="http://www.opengis.net/wms" xsi:schemaLocation="http://www.opengis.net/wms http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd http://www.qgis.org/wms http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&SERVICE=WMS&REQUEST=GetSchemaExtension" xmlns:sld="http://www.opengis.net/ [...]
<Service>
<Name>WMS</Name>
<Title>QGIS TestProject</Title>
@@ -30,7 +30,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -45,7 +45,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -59,7 +59,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -70,7 +70,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -80,7 +80,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -90,7 +90,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -131,7 +131,7 @@ Content-Type: text/xml; charset=utf-8
<Title>default</Title>
<LegendURL>
<Format>image/png</Format>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&&SERVICE=WMS&VERSION=1.3&REQUEST=GetLegendGraphic&LAYER=testlayer èé&FORMAT=image/png&STYLE=default"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&&SERVICE=WMS&VERSION=1.3&REQUEST=GetLegendGraphic&LAYER=testlayer èé&FORMAT=image/png&STYLE=default"/>
</LegendURL>
</Style>
</Layer>
diff --git a/tests/testdata/qgis_server/getprojectsettings.txt b/tests/testdata/qgis_server/getprojectsettings.txt
index cda888d..aa4bf98 100644
--- a/tests/testdata/qgis_server/getprojectsettings.txt
+++ b/tests/testdata/qgis_server/getprojectsettings.txt
@@ -1,8 +1,8 @@
-Content-Length: 6268
+Content-Length: 6781
Content-Type: text/xml; charset=utf-8
<?xml version="1.0" encoding="utf-8"?>
-<WMS_Capabilities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.3.0" xmlns="http://www.opengis.net/wms" xsi:schemaLocation="http://www.opengis.net/wms http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd http://www.qgis.org/wms http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&SERVICE=WMS&REQUEST=GetSchemaExtension" xmlns:sld="http://www.opengis. [...]
+<WMS_Capabilities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.3.0" xmlns="http://www.opengis.net/wms" xsi:schemaLocation="http://www.opengis.net/wms http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd http://www.qgis.org/wms http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&SERVICE=WMS&REQUEST=GetSchemaExtension" xmlns:sld="http://www.opengis.ne [...]
<Service>
<Name>WMS</Name>
<Title>QGIS TestProject</Title>
@@ -30,7 +30,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -45,7 +45,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -59,7 +59,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -70,7 +70,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -80,7 +80,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -90,7 +90,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -102,7 +102,7 @@ Content-Type: text/xml; charset=utf-8
<DCPType>
<HTTP>
<Get>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&"/>
</Get>
</HTTP>
</DCPType>
@@ -112,6 +112,9 @@ Content-Type: text/xml; charset=utf-8
<Format>text/xml</Format>
</Exception>
<sld:UserDefinedSymbolization RemoteWFS="0" RemoteWCS="0" InlineFeature="0" UserStyle="1" SupportSLD="1" UserLayer="0"/>
+ <WFSLayers>
+ <WFSLayer name="testlayer èé"/>
+ </WFSLayers>
<Layer queryable="1">
<Name>QGIS Test Project</Name>
<Title>QGIS Test Project</Title>
@@ -145,7 +148,7 @@ Content-Type: text/xml; charset=utf-8
<Title>default</Title>
<LegendURL>
<Format>image/png</Format>
- <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test%2Bproject.qgs&&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&LAYER=testlayer èé&FORMAT=image/png&STYLE=default&SLD_VERSION=1.1.0"/>
+ <OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http:?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project.qgs&&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&LAYER=testlayer èé&FORMAT=image/png&STYLE=default&SLD_VERSION=1.1.0"/>
</LegendURL>
</Style>
<TreeName>testlayer èé</TreeName>
diff --git a/tests/testdata/qgis_server/test+project.qgs b/tests/testdata/qgis_server/test_project.qgs
similarity index 79%
rename from tests/testdata/qgis_server/test+project.qgs
rename to tests/testdata/qgis_server/test_project.qgs
index c3dbec9..368e132 100644
--- a/tests/testdata/qgis_server/test+project.qgs
+++ b/tests/testdata/qgis_server/test_project.qgs
@@ -1,6 +1,8 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
-<qgis projectname="QGIS Test Project" version="2.9.0-Master">
+<qgis projectname="QGIS Test Project" version="2.17.0-Master">
<title>QGIS Test Project</title>
+ <autotransaction active="0"/>
+ <evaluateDefaultValues active="0"/>
<layer-tree-group expanded="1" checked="Qt::Checked" name="">
<customproperties/>
<layer-tree-layer expanded="1" checked="Qt::Checked" id="testlayer20150528120452665" name="testlayer èé">
@@ -30,11 +32,11 @@
<geographicflag>true</geographicflag>
</spatialrefsys>
</destinationsrs>
+ <rendermaptile>0</rendermaptile>
<layer_coordinate_transform_info>
<layer_coordinate_transform destAuthId="EPSG:4326" srcAuthId="EPSG:4326" srcDatumTransform="-1" destDatumTransform="-1" layerid="testlayer20150528120452665"/>
</layer_coordinate_transform_info>
</mapcanvas>
- <visibility-presets/>
<layer-tree-canvas>
<custom-order enabled="0">
<item>testlayer20150528120452665</item>
@@ -48,7 +50,7 @@
</legendlayer>
</legend>
<projectlayers>
- <maplayer minimumScale="-4.65661e-10" maximumScale="1e+08" simplifyDrawingHints="0" minLabelScale="0" maxLabelScale="1e+08" simplifyDrawingTol="1" geometry="Point" simplifyMaxScale="1" type="vector" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
+ <maplayer simplifyAlgorithm="0" minimumScale="-4.65661e-10" maximumScale="1e+08" simplifyDrawingHints="0" readOnly="0" minLabelScale="0" maxLabelScale="1e+08" simplifyDrawingTol="1" geometry="Point" simplifyMaxScale="1" type="vector" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
<id>testlayer20150528120452665</id>
<datasource>./testlayer.shp</datasource>
<title>A test vector layer</title>
@@ -72,40 +74,42 @@
<provider encoding="UTF-8">ogr</provider>
<previewExpression></previewExpression>
<vectorjoins/>
+ <layerDependencies/>
<expressionfields/>
<map-layer-style-manager current="">
<map-layer-style name=""/>
</map-layer-style-manager>
<edittypes>
<edittype widgetv2type="TextEdit" name="id">
- <widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="0"/>
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
</edittype>
<edittype widgetv2type="TextEdit" name="name">
- <widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="0"/>
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
</edittype>
<edittype widgetv2type="TextEdit" name="utf8nameè">
- <widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="0"/>
+ <widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
</edittype>
</edittypes>
- <renderer-v2 symbollevels="0" type="singleSymbol">
+ <renderer-v2 forceraster="0" symbollevels="0" type="singleSymbol" enableorderby="0">
<symbols>
<symbol alpha="1" clip_to_extent="1" type="marker" name="0">
<layer pass="0" class="SimpleMarker" locked="0">
<prop k="angle" v="0"/>
<prop k="color" v="102,164,67,255"/>
<prop k="horizontal_anchor_point" v="1"/>
+ <prop k="joinstyle" v="bevel"/>
<prop k="name" v="circle"/>
<prop k="offset" v="0,0"/>
- <prop k="offset_map_unit_scale" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="offset_unit" v="MM"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0"/>
- <prop k="outline_width_map_unit_scale" v="0,0"/>
+ <prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="outline_width_unit" v="MM"/>
<prop k="scale_method" v="area"/>
<prop k="size" v="2"/>
- <prop k="size_map_unit_scale" v="0,0"/>
+ <prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="size_unit" v="MM"/>
<prop k="vertical_anchor_point" v="1"/>
<effect enabled="0" type="effectStack">
@@ -120,7 +124,7 @@
</symbol>
</symbols>
<rotation/>
- <sizescale scalemethod="area"/>
+ <sizescale scalemethod="diameter"/>
<effect enabled="0" type="effectStack">
<effect type="drawSource">
<prop k="blend_mode" v="0"/>
@@ -130,6 +134,7 @@
</effect>
</effect>
</renderer-v2>
+ <labeling type="simple"/>
<customproperties>
<property key="labeling" value="pal"/>
<property key="labeling/addDirectionSymbol" value="false"/>
@@ -298,82 +303,115 @@
<multilineenabled fieldname="" on=""/>
<selectedonly on=""/>
</labelattributes>
- <SingleCategoryDiagramRenderer diagramType="Pie">
- <DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" font="Ubuntu,9,-1,5,50,0,0,0,0,0" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" sizeType="MM" minScaleDenominator="-4.65661e-10"/>
+ <SingleCategoryDiagramRenderer diagramType="Pie" sizeLegend="0" attributeLegend="1">
+ <DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" sizeScale="0,0,0,0,0,0" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="0,0,0,0,0,0" sizeType="MM" lineSizeType="MM" minScaleDenominator="-4.65661e-10">
+ <fontProperties description="Ubuntu,9,-1,5,50,0,0,0,0,0" style=""/>
+ <attribute field="" color="#000000" label=""/>
+ </DiagramCategory>
+ <symbol alpha="1" clip_to_extent="1" type="marker" name="sizeSymbol">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_color" v="0,0,0,255"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0"/>
+ <prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="diameter"/>
+ <prop k="size" v="2"/>
+ <prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
</SingleCategoryDiagramRenderer>
- <DiagramLayerSettings yPosColumn="-1" linePlacementFlags="10" placement="0" dist="0" xPosColumn="-1" priority="0" obstacle="0" showAll="1"/>
- <editform></editform>
+ <DiagramLayerSettings yPosColumn="-1" showColumn="0" linePlacementFlags="10" placement="0" dist="0" xPosColumn="-1" priority="0" obstacle="0" zIndex="0" showAll="1"/>
+ <annotationform>.</annotationform>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions default="0"/>
+ <attributetableconfig actionWidgetStyle="dropDown" sortExpression="" sortOrder="0">
+ <columns/>
+ </attributetableconfig>
+ <editform>.</editform>
<editforminit/>
+ <editforminitcodesource>0</editforminitcodesource>
+ <editforminitfilepath></editforminitfilepath>
+ <editforminitcode><![CDATA[]]></editforminitcode>
<featformsuppress>0</featformsuppress>
- <annotationform></annotationform>
<editorlayout>generatedlayout</editorlayout>
- <excludeAttributesWMS/>
- <excludeAttributesWFS/>
- <attributeactions/>
- <edittypes>
- <edittype widgetv2type="TextEdit" name="id">
- <widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="0"/>
- </edittype>
- <edittype widgetv2type="TextEdit" name="name">
- <widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="0"/>
- </edittype>
- <edittype widgetv2type="TextEdit" name="utf8nameè">
- <widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="0"/>
- </edittype>
- </edittypes>
+ <widgets/>
+ <conditionalstyles>
+ <rowstyles/>
+ <fieldstyles/>
+ </conditionalstyles>
</maplayer>
</projectlayers>
<properties>
- <WMSContactPerson type="QString">Alessandro Pasotti</WMSContactPerson>
- <WMSOnlineResource type="QString"></WMSOnlineResource>
- <WMSUseLayerIDs type="bool">false</WMSUseLayerIDs>
- <WMSContactOrganization type="QString">QGIS dev team</WMSContactOrganization>
+ <WMSUrl type="QString"></WMSUrl>
+ <SpatialRefSys>
+ <ProjectCRSProj4String type="QString">+proj=longlat +datum=WGS84 +no_defs</ProjectCRSProj4String>
+ <ProjectCrs type="QString">EPSG:4326</ProjectCrs>
+ <ProjectCRSID type="int">3452</ProjectCRSID>
+ <ProjectionsEnabled type="int">1</ProjectionsEnabled>
+ </SpatialRefSys>
+ <Measurement>
+ <DistanceUnits type="QString">meters</DistanceUnits>
+ <AreaUnits type="QString">m2</AreaUnits>
+ </Measurement>
+ <Legend>
+ <filterByMap type="bool">false</filterByMap>
+ </Legend>
<WMSExtent type="QStringList">
<value>8.20315414376310059</value>
<value>44.901236559338642</value>
<value>8.204164917965862</value>
<value>44.90159838674664172</value>
</WMSExtent>
- <WMSKeywordList type="QStringList">
- <value></value>
- </WMSKeywordList>
- <WFSUrl type="QString"></WFSUrl>
- <Paths>
- <Absolute type="bool">false</Absolute>
- </Paths>
- <WMSServiceTitle type="QString">QGIS TestProject</WMSServiceTitle>
- <WFSLayers type="QStringList"/>
+ <DefaultStyles>
+ <Fill type="QString"></Fill>
+ <Line type="QString"></Line>
+ <Marker type="QString"></Marker>
+ <RandomColors type="bool">true</RandomColors>
+ <AlphaInt type="int">255</AlphaInt>
+ <ColorRamp type="QString"></ColorRamp>
+ </DefaultStyles>
+ <WMSAccessConstraints type="QString">None</WMSAccessConstraints>
<WMSContactMail type="QString">elpaso at itopen.it</WMSContactMail>
+ <WMSImageQuality type="int">90</WMSImageQuality>
+ <WFSLayersPrecision>
+ <testlayer20150528120452665 type="int">8</testlayer20150528120452665>
+ </WFSLayersPrecision>
<WMSRestrictedComposers type="QStringList"/>
- <WMSRestrictedLayers type="QStringList"/>
- <PositionPrecision>
- <DecimalPlaces type="int">2</DecimalPlaces>
- <Automatic type="bool">true</Automatic>
- <DegreeFormat type="QString">D</DegreeFormat>
- </PositionPrecision>
- <WCSUrl type="QString"></WCSUrl>
- <WMSServiceCapabilities type="bool">true</WMSServiceCapabilities>
+ <WMSServiceTitle type="QString">QGIS TestProject</WMSServiceTitle>
<WMSContactPhone type="QString"></WMSContactPhone>
- <WMSServiceAbstract type="QString">Some UTF8 text èòù</WMSServiceAbstract>
- <WMSAddWktGeometry type="bool">true</WMSAddWktGeometry>
- <Measure>
- <Ellipsoid type="QString">WGS84</Ellipsoid>
- </Measure>
- <WMSPrecision type="QString">4</WMSPrecision>
<WFSTLayers>
- <Insert type="QStringList"/>
- <Update type="QStringList"/>
- <Delete type="QStringList"/>
+ <Insert type="QStringList">
+ <value>testlayer20150528120452665</value>
+ </Insert>
+ <Update type="QStringList">
+ <value>testlayer20150528120452665</value>
+ </Update>
+ <Delete type="QStringList">
+ <value>testlayer20150528120452665</value>
+ </Delete>
</WFSTLayers>
- <Gui>
- <SelectionColorBluePart type="int">0</SelectionColorBluePart>
- <CanvasColorGreenPart type="int">255</CanvasColorGreenPart>
- <CanvasColorRedPart type="int">255</CanvasColorRedPart>
- <SelectionColorRedPart type="int">255</SelectionColorRedPart>
- <SelectionColorAlphaPart type="int">255</SelectionColorAlphaPart>
- <SelectionColorGreenPart type="int">255</SelectionColorGreenPart>
- <CanvasColorBluePart type="int">255</CanvasColorBluePart>
- </Gui>
+ <WCSLayers type="QStringList"/>
+ <WMSRestrictedLayers type="QStringList"/>
+ <WMSFees type="QString">conditions unknown</WMSFees>
+ <Macros>
+ <pythonCode type="QString"></pythonCode>
+ </Macros>
+ <WMSAddWktGeometry type="bool">true</WMSAddWktGeometry>
+ <WCSUrl type="QString"></WCSUrl>
+ <WMSOnlineResource type="QString"></WMSOnlineResource>
+ <WMSPrecision type="QString">4</WMSPrecision>
<Digitizing>
<DefaultSnapToleranceUnit type="int">2</DefaultSnapToleranceUnit>
<LayerSnappingList type="QStringList"/>
@@ -389,30 +427,43 @@
<Identify>
<disabledLayers type="QStringList"/>
</Identify>
- <Macros>
- <pythonCode type="QString"></pythonCode>
- </Macros>
- <WMSAccessConstraints type="QString"></WMSAccessConstraints>
- <WCSLayers type="QStringList"/>
- <Legend>
- <filterByMap type="bool">false</filterByMap>
- </Legend>
- <SpatialRefSys>
- <ProjectCRSProj4String type="QString">+proj=longlat +datum=WGS84 +no_defs</ProjectCRSProj4String>
- <ProjectCrs type="QString">EPSG:4326</ProjectCrs>
- <ProjectCRSID type="int">3452</ProjectCRSID>
- <ProjectionsEnabled type="int">1</ProjectionsEnabled>
- </SpatialRefSys>
- <DefaultStyles>
- <Fill type="QString"></Fill>
- <Line type="QString"></Line>
- <Marker type="QString"></Marker>
- <RandomColors type="bool">true</RandomColors>
- <AlphaInt type="int">255</AlphaInt>
- <ColorRamp type="QString"></ColorRamp>
- </DefaultStyles>
- <WMSFees type="QString"></WMSFees>
- <WMSImageQuality type="int">90</WMSImageQuality>
- <WMSUrl type="QString"></WMSUrl>
+ <WMSContactPerson type="QString">Alessandro Pasotti</WMSContactPerson>
+ <WMSContactOrganization type="QString">QGIS dev team</WMSContactOrganization>
+ <WMSKeywordList type="QStringList">
+ <value></value>
+ </WMSKeywordList>
+ <Paths>
+ <Absolute type="bool">false</Absolute>
+ </Paths>
+ <Variables>
+ <variableNames type="QStringList"/>
+ <variableValues type="QStringList"/>
+ </Variables>
+ <WMSContactPosition type="QString"></WMSContactPosition>
+ <PositionPrecision>
+ <DecimalPlaces type="int">2</DecimalPlaces>
+ <Automatic type="bool">true</Automatic>
+ <DegreeFormat type="QString">D</DegreeFormat>
+ </PositionPrecision>
+ <Gui>
+ <SelectionColorBluePart type="int">0</SelectionColorBluePart>
+ <CanvasColorGreenPart type="int">255</CanvasColorGreenPart>
+ <CanvasColorRedPart type="int">255</CanvasColorRedPart>
+ <SelectionColorRedPart type="int">255</SelectionColorRedPart>
+ <SelectionColorAlphaPart type="int">255</SelectionColorAlphaPart>
+ <SelectionColorGreenPart type="int">255</SelectionColorGreenPart>
+ <CanvasColorBluePart type="int">255</CanvasColorBluePart>
+ </Gui>
+ <Measure>
+ <Ellipsoid type="QString">WGS84</Ellipsoid>
+ </Measure>
+ <WMSServiceAbstract type="QString">Some UTF8 text èòù</WMSServiceAbstract>
+ <WFSLayers type="QStringList">
+ <value>testlayer20150528120452665</value>
+ </WFSLayers>
+ <WFSUrl type="QString"></WFSUrl>
+ <WMSServiceCapabilities type="bool">true</WMSServiceCapabilities>
+ <WMSUseLayerIDs type="bool">false</WMSUseLayerIDs>
</properties>
+ <visibility-presets/>
</qgis>
diff --git a/tests/testdata/qgis_server/test+project_inspire.qgs b/tests/testdata/qgis_server/test_project_inspire.qgs
similarity index 100%
rename from tests/testdata/qgis_server/test+project_inspire.qgs
rename to tests/testdata/qgis_server/test_project_inspire.qgs
diff --git a/tests/testdata/qgis_server/test+project_wfs.qgs b/tests/testdata/qgis_server/test_project_wfs.qgs
similarity index 100%
rename from tests/testdata/qgis_server/test+project_wfs.qgs
rename to tests/testdata/qgis_server/test_project_wfs.qgs
diff --git a/tests/testdata/qgis_server/wms_getfeatureinfo-text-html.txt b/tests/testdata/qgis_server/wms_getfeatureinfo-text-html.txt
index a92e020..66a9714 100644
--- a/tests/testdata/qgis_server/wms_getfeatureinfo-text-html.txt
+++ b/tests/testdata/qgis_server/wms_getfeatureinfo-text-html.txt
@@ -1,4 +1,4 @@
-Content-Length: 360
+Content-Length: 512
Content-Type: text/html; charset=utf-8
<HEAD>
--
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