mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-02 00:04:53 -04:00
Merge branch 'master' of https://github.com/QGIS/QGIS into regularShape_gui
This commit is contained in:
commit
d1e40d9086
@ -1,4 +1,7 @@
|
|||||||
|
|
||||||
|
# CACHE_TAG is provided by Docker cloud
|
||||||
|
# see https://docs.docker.com/docker-cloud/builds/advanced/
|
||||||
|
# using ARG in FROM requires min v17.05.0-ce
|
||||||
ARG CACHE_TAG=latest
|
ARG CACHE_TAG=latest
|
||||||
|
|
||||||
FROM qgis/qgis3-build-deps:${CACHE_TAG}
|
FROM qgis/qgis3-build-deps:${CACHE_TAG}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# About QGIS
|
# About QGIS
|
||||||
|
|
||||||
[](https://travis-ci.org/qgis/QGIS)
|
[](https://travis-ci.org/qgis/QGIS)
|
||||||
|
[](https://cloud.docker.com/app/qgis/repository/docker/qgis/qgis/general)
|
||||||
|
|
||||||
QGIS is an Open Source Geographic Information System. The project was born in
|
QGIS is an Open Source Geographic Information System. The project was born in
|
||||||
May of 2002 and was established as a project on SourceForge in June of the same
|
May of 2002 and was established as a project on SourceForge in June of the same
|
||||||
@ -63,7 +64,7 @@ an email address where we can request additional information.
|
|||||||
## Support
|
## Support
|
||||||
You can get support in the following ways:
|
You can get support in the following ways:
|
||||||
|
|
||||||
- Using the QGIS community site at http://qgis.org
|
- Using the QGIS community site at http://qgis.org
|
||||||
- Joining the [qgis-users mailing list](https://lists.osgeo.org/mailman/listinfo/qgis-user)
|
- Joining the [qgis-users mailing list](https://lists.osgeo.org/mailman/listinfo/qgis-user)
|
||||||
- Using IRC by joining the [#qgis](http://webchat.freenode.net/?channels=#qgis) channel on irc.freenode.net. Please wait around for a response to your question as many folks on the channel are doing other things and it may take a while for them to notice your question.
|
- Using IRC by joining the [#qgis](http://webchat.freenode.net/?channels=#qgis) channel on irc.freenode.net. Please wait around for a response to your question as many folks on the channel are doing other things and it may take a while for them to notice your question.
|
||||||
- Join the [Gitter](https://gitter.im/qgis/QGIS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) chat.
|
- Join the [Gitter](https://gitter.im/qgis/QGIS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) chat.
|
||||||
|
3
debian/libqgis-dev.install.in
vendored
3
debian/libqgis-dev.install.in
vendored
@ -3,7 +3,8 @@ usr/lib/libqgis_app.so
|
|||||||
usr/lib/libqgis_core.so
|
usr/lib/libqgis_core.so
|
||||||
usr/lib/libqgis_gui.so
|
usr/lib/libqgis_gui.so
|
||||||
usr/lib/libqgis_analysis.so
|
usr/lib/libqgis_analysis.so
|
||||||
#server#usr/lib/libqgis_server.so
|
usr/lib/libqgis_native.so
|
||||||
|
usr/lib/libqgis_server.so
|
||||||
usr/lib/libqgisgrass{GRASSVER}.so
|
usr/lib/libqgisgrass{GRASSVER}.so
|
||||||
usr/lib/libqgispython.so
|
usr/lib/libqgispython.so
|
||||||
usr/share/qgis/FindQGIS.cmake
|
usr/share/qgis/FindQGIS.cmake
|
||||||
|
1
debian/qgis-common.install
vendored
1
debian/qgis-common.install
vendored
@ -12,6 +12,7 @@ usr/share/qgis/doc/images
|
|||||||
usr/share/qgis/doc/index.html
|
usr/share/qgis/doc/index.html
|
||||||
usr/share/qgis/doc/news
|
usr/share/qgis/doc/news
|
||||||
usr/share/qgis/doc/news.html
|
usr/share/qgis/doc/news.html
|
||||||
|
usr/share/qgis/doc/nohelp.html
|
||||||
usr/share/qgis/doc/style.css
|
usr/share/qgis/doc/style.css
|
||||||
usr/share/qgis/i18n/*
|
usr/share/qgis/i18n/*
|
||||||
usr/share/qgis/images/*
|
usr/share/qgis/images/*
|
||||||
|
1
debian/qgis.install
vendored
1
debian/qgis.install
vendored
@ -6,7 +6,6 @@ usr/lib/qgis/plugins/libspatialqueryplugin.so
|
|||||||
usr/lib/qgis/plugins/libofflineeditingplugin.so
|
usr/lib/qgis/plugins/libofflineeditingplugin.so
|
||||||
usr/lib/qgis/plugins/libtopolplugin.so
|
usr/lib/qgis/plugins/libtopolplugin.so
|
||||||
usr/lib/qgis/plugins/libgeometrycheckerplugin.so
|
usr/lib/qgis/plugins/libgeometrycheckerplugin.so
|
||||||
usr/lib/qgis/qgis_help
|
|
||||||
usr/share/pixmaps/
|
usr/share/pixmaps/
|
||||||
usr/share/applications/
|
usr/share/applications/
|
||||||
usr/share/mime/packages/
|
usr/share/mime/packages/
|
||||||
|
4
debian/qgis.lintian-overrides
vendored
4
debian/qgis.lintian-overrides
vendored
@ -1,4 +0,0 @@
|
|||||||
# Build uses -D_FORTIFY_SOURCE=2, but hardening-check reports:
|
|
||||||
# Fortify Source functions: no, only unprotected functions found!
|
|
||||||
# unprotected: fgets
|
|
||||||
qgis: hardening-no-fortify-functions usr/lib/qgis/qgis_help
|
|
@ -269,6 +269,7 @@ should now call QgsCoordinateReferenceSystem::invalidateCache() and QgsCoordinat
|
|||||||
- QgsFileNameWidgetWrapper was removed. Use QgsExternalResourceWidgetWrapper instead.
|
- QgsFileNameWidgetWrapper was removed. Use QgsExternalResourceWidgetWrapper instead.
|
||||||
- QgsFileDropEdit was removed. Use QgsFileWidget instead.
|
- QgsFileDropEdit was removed. Use QgsFileWidget instead.
|
||||||
- QgsFormAnnotationItem. Use QgsFormAnnotation instead.
|
- QgsFormAnnotationItem. Use QgsFormAnnotation instead.
|
||||||
|
- QgsGeometryAnalyzer. Use the equivalent Processing algorithms instead.
|
||||||
- QgsHtmlAnnotationItem. Use QgsHtmlAnnotation instead.
|
- QgsHtmlAnnotationItem. Use QgsHtmlAnnotation instead.
|
||||||
- QgsHttpTransaction. This class was outdated and code should be ported to native Qt or Python implementations.
|
- QgsHttpTransaction. This class was outdated and code should be ported to native Qt or Python implementations.
|
||||||
- QgsGenericProjectionSelector. Use QgsProjectionSelectionTreeWidget instead.
|
- QgsGenericProjectionSelector. Use QgsProjectionSelectionTreeWidget instead.
|
||||||
@ -287,6 +288,7 @@ should now call QgsCoordinateReferenceSystem::invalidateCache() and QgsCoordinat
|
|||||||
- QgsMapRenderer. It has been replaced by QgsMapRendererJob with subclasses and QgsMapSettings.
|
- QgsMapRenderer. It has been replaced by QgsMapRendererJob with subclasses and QgsMapSettings.
|
||||||
- QgsMapToolTouch. The touch navigation functionality is now built into the standard QgsMapToolPan tool.
|
- QgsMapToolTouch. The touch navigation functionality is now built into the standard QgsMapToolPan tool.
|
||||||
- QgsPhotoWidgetWrapper was removed. Use QgsExternalResourceWidgetWrapper instead.
|
- QgsPhotoWidgetWrapper was removed. Use QgsExternalResourceWidgetWrapper instead.
|
||||||
|
- QgsPointSample. Use the Processing "Random Points in Polygon" algorithm instead.
|
||||||
- QgsPseudoColorShader. This shader has been broken for some time and was replaced by QgsSingleBandPseudoColorRenderer.
|
- QgsPseudoColorShader. This shader has been broken for some time and was replaced by QgsSingleBandPseudoColorRenderer.
|
||||||
- QgsProjectBadLayerGuiHandler was removed. It was unused in QGIS code and barely useful. Implement your own QgsProjectBadLayerHandler subclass if needed.
|
- QgsProjectBadLayerGuiHandler was removed. It was unused in QGIS code and barely useful. Implement your own QgsProjectBadLayerHandler subclass if needed.
|
||||||
- QgsRendererV2DataDefinedMenus was removed. Use QgsPropertyOverrideButton instead.
|
- QgsRendererV2DataDefinedMenus was removed. Use QgsPropertyOverrideButton instead.
|
||||||
|
@ -384,7 +384,6 @@ tar -C %OSGEO4W_ROOT% -cjf %ARCH%/release/qgis/%PACKAGENAME%/%PACKAGENAME%-%VERS
|
|||||||
"apps/%PACKAGENAME%/plugins/spatialqueryplugin.dll" ^
|
"apps/%PACKAGENAME%/plugins/spatialqueryplugin.dll" ^
|
||||||
"apps/%PACKAGENAME%/plugins/topolplugin.dll" ^
|
"apps/%PACKAGENAME%/plugins/topolplugin.dll" ^
|
||||||
"apps/%PACKAGENAME%/plugins/geometrycheckerplugin.dll" ^
|
"apps/%PACKAGENAME%/plugins/geometrycheckerplugin.dll" ^
|
||||||
"apps/%PACKAGENAME%/qgis_help.exe" ^
|
|
||||||
"apps/%PACKAGENAME%/qtplugins/sqldrivers/qsqlspatialite.dll" ^
|
"apps/%PACKAGENAME%/qtplugins/sqldrivers/qsqlspatialite.dll" ^
|
||||||
"apps/%PACKAGENAME%/qtplugins/designer/" ^
|
"apps/%PACKAGENAME%/qtplugins/designer/" ^
|
||||||
"apps/%PACKAGENAME%/python/" ^
|
"apps/%PACKAGENAME%/python/" ^
|
||||||
|
@ -12,9 +12,6 @@
|
|||||||
%Include raster/qgsrastermatrix.sip
|
%Include raster/qgsrastermatrix.sip
|
||||||
%Include raster/qgsrastercalcnode.sip
|
%Include raster/qgsrastercalcnode.sip
|
||||||
%Include raster/qgstotalcurvaturefilter.sip
|
%Include raster/qgstotalcurvaturefilter.sip
|
||||||
%Include vector/qgsgeometryanalyzer.sip
|
|
||||||
%Include vector/qgsoverlayanalyzer.sip
|
|
||||||
%Include vector/qgspointsample.sip
|
|
||||||
%Include vector/qgstransectsample.sip
|
%Include vector/qgstransectsample.sip
|
||||||
%Include vector/qgszonalstatistics.sip
|
%Include vector/qgszonalstatistics.sip
|
||||||
%Include interpolation/qgsinterpolator.sip
|
%Include interpolation/qgsinterpolator.sip
|
||||||
|
@ -1,143 +0,0 @@
|
|||||||
/************************************************************************
|
|
||||||
* This file has been generated automatically from *
|
|
||||||
* *
|
|
||||||
* src/analysis/vector/qgsgeometryanalyzer.h *
|
|
||||||
* *
|
|
||||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
|
||||||
************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class QgsGeometryAnalyzer
|
|
||||||
{
|
|
||||||
%Docstring
|
|
||||||
The QGis class provides vector geometry analysis functions
|
|
||||||
%End
|
|
||||||
|
|
||||||
%TypeHeaderCode
|
|
||||||
#include "qgsgeometryanalyzer.h"
|
|
||||||
%End
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool simplify( QgsVectorLayer *layer, const QString &shapefileName, double tolerance,
|
|
||||||
bool onlySelectedFeatures = false, QProgressDialog *p = 0 );
|
|
||||||
%Docstring
|
|
||||||
Simplify vector layer using (a modified) Douglas-Peucker algorithm
|
|
||||||
and write it to a new shape file
|
|
||||||
\param layer input vector layer
|
|
||||||
\param shapefileName path to the output shp
|
|
||||||
\param tolerance (level of simplification)
|
|
||||||
\param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
\param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
:rtype: bool
|
|
||||||
%End
|
|
||||||
|
|
||||||
bool centroids( QgsVectorLayer *layer, const QString &shapefileName,
|
|
||||||
bool onlySelectedFeatures = false, QProgressDialog *p = 0 );
|
|
||||||
%Docstring
|
|
||||||
Calculate the true centroids, or 'center of mass' for a vector layer and
|
|
||||||
write it to a new shape file
|
|
||||||
\param layer input vector layer
|
|
||||||
\param shapefileName path to the output shp
|
|
||||||
\param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
\param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
:rtype: bool
|
|
||||||
%End
|
|
||||||
|
|
||||||
bool extent( QgsVectorLayer *layer, const QString &shapefileName, bool onlySelectedFeatures = false, QProgressDialog *p = 0 );
|
|
||||||
%Docstring
|
|
||||||
Create a polygon based on the extent of all (selected) features and write it to a new shape file
|
|
||||||
\param layer input vector layer
|
|
||||||
\param shapefileName path to the output shp
|
|
||||||
\param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
\param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
:rtype: bool
|
|
||||||
%End
|
|
||||||
|
|
||||||
bool buffer( QgsVectorLayer *layer, const QString &shapefileName, double bufferDistance,
|
|
||||||
bool onlySelectedFeatures = false, bool dissolve = false, int bufferDistanceField = -1, QProgressDialog *p = 0 );
|
|
||||||
%Docstring
|
|
||||||
Create buffers for a vector layer and write it to a new shape file
|
|
||||||
\param layer input vector layer
|
|
||||||
\param shapefileName path to the output shp
|
|
||||||
\param bufferDistance distance for buffering (if no buffer field is specified)
|
|
||||||
\param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
\param dissolve if true, merge all the buffers to a big multipolygon
|
|
||||||
\param bufferDistanceField index of the attribute field that contains the buffer distance (or -1 if all features have the same buffer distance)
|
|
||||||
\param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
:rtype: bool
|
|
||||||
%End
|
|
||||||
|
|
||||||
bool convexHull( QgsVectorLayer *layer, const QString &shapefileName, bool onlySelectedFeatures = false,
|
|
||||||
int uniqueIdField = -1, QProgressDialog *p = 0 );
|
|
||||||
%Docstring
|
|
||||||
Create convex hull(s) of a vector layer and write it to a new shape file
|
|
||||||
\param layer input vector layer
|
|
||||||
\param shapefileName path to the output shp
|
|
||||||
\param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
\param uniqueIdField index of the attribute field that contains the unique convex hull id (or -1 if
|
|
||||||
all features have the same buffer distance)
|
|
||||||
\param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
:rtype: bool
|
|
||||||
%End
|
|
||||||
|
|
||||||
bool dissolve( QgsVectorLayer *layer, const QString &shapefileName, bool onlySelectedFeatures = false,
|
|
||||||
int uniqueIdField = -1, QProgressDialog *p = 0 );
|
|
||||||
%Docstring
|
|
||||||
Dissolve a vector layer and write it to a new shape file
|
|
||||||
\param layer input vector layer
|
|
||||||
\param shapefileName path to the output shp
|
|
||||||
\param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
\param uniqueIdField index of the attribute field that contains the unique id to dissolve on (or -1 if
|
|
||||||
all features should be dissolved together)
|
|
||||||
\param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
:rtype: bool
|
|
||||||
%End
|
|
||||||
|
|
||||||
bool eventLayer( QgsVectorLayer *lineLayer, QgsVectorLayer *eventLayer, int lineField, int eventField, QgsFeatureIds &unlocatedFeatureIds /Out/, const QString &outputLayer,
|
|
||||||
const QString &outputFormat, int locationField1, int locationField2 = -1, int offsetField = -1, double offsetScale = 1.0,
|
|
||||||
bool forceSingleGeometry = false, QgsVectorDataProvider *memoryProvider = 0, QProgressDialog *p = 0 );
|
|
||||||
%Docstring
|
|
||||||
Creates an event layer (multipoint or multiline) by locating features from a (non-spatial) event table along the features of a line layer.
|
|
||||||
Note that currently (until QgsGeometry supports m-values) the z-coordinate of the line layer is used for linear referencing
|
|
||||||
\param lineLayer layer with the line geometry
|
|
||||||
\param eventLayer layer with features and location field
|
|
||||||
\param lineField join index in line layer
|
|
||||||
\param eventField join index in event layer
|
|
||||||
\param outputLayer name of output file (can be empty if a memory layer is used)
|
|
||||||
\param outputFormat name of output format (can be empty if a memory provider is used to store the results)
|
|
||||||
\param unlocatedFeatureIds out: ids of event features where linear referencing was not successful
|
|
||||||
\param locationField1 attribute index of location field in event layer
|
|
||||||
\param locationField2 attribute index of location end field (or -1 for point layer)
|
|
||||||
\param offsetField attribute index for offset field. Negative offset value = offset to left side, positive value = offset to right side
|
|
||||||
\param offsetScale factor to scale offset
|
|
||||||
\param forceSingleGeometry force layer to single point/line type. Feature attributes are copied in case of multiple matches
|
|
||||||
\param memoryProvider memory provider to write output to (can be 0 if output is written to a file)
|
|
||||||
\param p progress dialog or 0 if no progress dialog should be shown
|
|
||||||
:rtype: bool
|
|
||||||
%End
|
|
||||||
|
|
||||||
QgsGeometry locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry &lineGeom );
|
|
||||||
%Docstring
|
|
||||||
Returns linear reference geometry as a multiline (or 0 if no match). Currently, the z-coordinates are considered to be the measures (no support for m-values in QGIS)
|
|
||||||
:rtype: QgsGeometry
|
|
||||||
%End
|
|
||||||
|
|
||||||
QgsGeometry locateAlongMeasure( double measure, const QgsGeometry &lineGeom );
|
|
||||||
%Docstring
|
|
||||||
Returns linear reference geometry. Unlike the PostGIS function, this method always returns multipoint or 0 if no match (not geometry collection).
|
|
||||||
Currently, the z-coordinates are considered to be the measures (no support for m-values in QGIS)
|
|
||||||
:rtype: QgsGeometry
|
|
||||||
%End
|
|
||||||
|
|
||||||
};
|
|
||||||
/************************************************************************
|
|
||||||
* This file has been generated automatically from *
|
|
||||||
* *
|
|
||||||
* src/analysis/vector/qgsgeometryanalyzer.h *
|
|
||||||
* *
|
|
||||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
|
||||||
************************************************************************/
|
|
@ -1,46 +0,0 @@
|
|||||||
/************************************************************************
|
|
||||||
* This file has been generated automatically from *
|
|
||||||
* *
|
|
||||||
* src/analysis/vector/qgsoverlayanalyzer.h *
|
|
||||||
* *
|
|
||||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
|
||||||
************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class QgsOverlayAnalyzer
|
|
||||||
{
|
|
||||||
%Docstring
|
|
||||||
The QGis class provides vector overlay analysis functions
|
|
||||||
%End
|
|
||||||
|
|
||||||
%TypeHeaderCode
|
|
||||||
#include "qgsoverlayanalyzer.h"
|
|
||||||
%End
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool intersection( QgsVectorLayer *layerA, QgsVectorLayer *layerB,
|
|
||||||
const QString &shapefileName, bool onlySelectedFeatures = false,
|
|
||||||
QProgressDialog *p = 0 );
|
|
||||||
%Docstring
|
|
||||||
Perform an intersection on two input vector layers and write output to a new shape file
|
|
||||||
\param layerA input vector layer
|
|
||||||
\param layerB input vector layer
|
|
||||||
\param shapefileName path to the output shp
|
|
||||||
\param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
\param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
:rtype: bool
|
|
||||||
%End
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* This file has been generated automatically from *
|
|
||||||
* *
|
|
||||||
* src/analysis/vector/qgsoverlayanalyzer.h *
|
|
||||||
* *
|
|
||||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
|
||||||
************************************************************************/
|
|
@ -1,38 +0,0 @@
|
|||||||
/************************************************************************
|
|
||||||
* This file has been generated automatically from *
|
|
||||||
* *
|
|
||||||
* src/analysis/vector/qgspointsample.h *
|
|
||||||
* *
|
|
||||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
|
||||||
************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class QgsPointSample
|
|
||||||
{
|
|
||||||
%Docstring
|
|
||||||
Creates random points in polygons / multipolygons*
|
|
||||||
%End
|
|
||||||
|
|
||||||
%TypeHeaderCode
|
|
||||||
#include "qgspointsample.h"
|
|
||||||
%End
|
|
||||||
public:
|
|
||||||
QgsPointSample( QgsVectorLayer *inputLayer, const QString &outputLayer, const QString &nPointsAttribute, const QString &minDistAttribute = QString() );
|
|
||||||
|
|
||||||
int createRandomPoints( QProgressDialog *pd );
|
|
||||||
%Docstring
|
|
||||||
Starts calculation of random points
|
|
||||||
:return: 0 in case of success*
|
|
||||||
:rtype: int
|
|
||||||
%End
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* This file has been generated automatically from *
|
|
||||||
* *
|
|
||||||
* src/analysis/vector/qgspointsample.h *
|
|
||||||
* *
|
|
||||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
|
||||||
************************************************************************/
|
|
@ -223,12 +223,6 @@ Returns the path to the licence file.
|
|||||||
:rtype: str
|
:rtype: str
|
||||||
%End
|
%End
|
||||||
|
|
||||||
static QString helpAppPath();
|
|
||||||
%Docstring
|
|
||||||
Returns the path to the help application.
|
|
||||||
:rtype: str
|
|
||||||
%End
|
|
||||||
|
|
||||||
static QString i18nPath();
|
static QString i18nPath();
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns the path to the translation directory.
|
Returns the path to the translation directory.
|
||||||
|
@ -35,6 +35,7 @@ from .GdalUtils import GdalUtils
|
|||||||
|
|
||||||
from .AssignProjection import AssignProjection
|
from .AssignProjection import AssignProjection
|
||||||
from .aspect import aspect
|
from .aspect import aspect
|
||||||
|
from .buildvrt import buildvrt
|
||||||
from .ColorRelief import ColorRelief
|
from .ColorRelief import ColorRelief
|
||||||
from .tri import tri
|
from .tri import tri
|
||||||
from .warp import warp
|
from .warp import warp
|
||||||
@ -44,7 +45,6 @@ from .nearblack import nearblack
|
|||||||
# from .translate import translate
|
# from .translate import translate
|
||||||
# from .pct2rgb import pct2rgb
|
# from .pct2rgb import pct2rgb
|
||||||
# from .merge import merge
|
# from .merge import merge
|
||||||
# from .buildvrt import buildvrt
|
|
||||||
# from .polygonize import polygonize
|
# from .polygonize import polygonize
|
||||||
# from .gdaladdo import gdaladdo
|
# from .gdaladdo import gdaladdo
|
||||||
# from .ClipByExtent import ClipByExtent
|
# from .ClipByExtent import ClipByExtent
|
||||||
@ -144,6 +144,7 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
|
|||||||
# information(),
|
# information(),
|
||||||
AssignProjection(),
|
AssignProjection(),
|
||||||
aspect(),
|
aspect(),
|
||||||
|
buildvrt(),
|
||||||
ColorRelief(),
|
ColorRelief(),
|
||||||
tri(),
|
tri(),
|
||||||
warp(),
|
warp(),
|
||||||
@ -151,7 +152,6 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
|
|||||||
# rgb2pct(),
|
# rgb2pct(),
|
||||||
# pct2rgb(),
|
# pct2rgb(),
|
||||||
# merge(),
|
# merge(),
|
||||||
# buildvrt(),
|
|
||||||
# polygonize(),
|
# polygonize(),
|
||||||
# gdaladdo(),
|
# gdaladdo(),
|
||||||
# ClipByExtent(),
|
# ClipByExtent(),
|
||||||
|
@ -29,14 +29,16 @@ import os
|
|||||||
|
|
||||||
from qgis.PyQt.QtGui import QIcon
|
from qgis.PyQt.QtGui import QIcon
|
||||||
|
|
||||||
from qgis.core import QgsProcessingUtils
|
from qgis.core import (QgsProcessing,
|
||||||
|
QgsProperty,
|
||||||
|
QgsProcessingParameterMultipleLayers,
|
||||||
|
QgsProcessingParameterEnum,
|
||||||
|
QgsProcessingParameterBoolean,
|
||||||
|
QgsProcessingParameterRasterDestination,
|
||||||
|
QgsProcessingOutputLayerDefinition,
|
||||||
|
QgsProcessingUtils)
|
||||||
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
|
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
|
||||||
from processing.core.outputs import OutputRaster
|
|
||||||
from processing.core.parameters import ParameterBoolean
|
|
||||||
from processing.core.parameters import ParameterMultipleInput
|
|
||||||
from processing.core.parameters import ParameterSelection
|
|
||||||
from processing.algs.gdal.GdalUtils import GdalUtils
|
from processing.algs.gdal.GdalUtils import GdalUtils
|
||||||
from processing.tools import dataobjects
|
|
||||||
|
|
||||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||||
|
|
||||||
@ -55,15 +57,27 @@ class buildvrt(GdalAlgorithm):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
def initAlgorithm(self, config=None):
|
def initAlgorithm(self, config=None):
|
||||||
self.addParameter(ParameterMultipleInput(self.INPUT,
|
|
||||||
self.tr('Input layers'), dataobjects.TYPE_RASTER))
|
class ParameterVrtDestination(QgsProcessingParameterRasterDestination):
|
||||||
self.addParameter(ParameterSelection(self.RESOLUTION,
|
|
||||||
self.tr('Resolution'), self.RESOLUTION_OPTIONS, 0))
|
def __init__(self, name, description):
|
||||||
self.addParameter(ParameterBoolean(self.SEPARATE,
|
super().__init__(name, description)
|
||||||
self.tr('Layer stack'), True))
|
|
||||||
self.addParameter(ParameterBoolean(self.PROJ_DIFFERENCE,
|
def type(self):
|
||||||
self.tr('Allow projection difference'), False))
|
return 'vrt_destination'
|
||||||
self.addOutput(OutputRaster(buildvrt.OUTPUT, self.tr('Virtual')))
|
|
||||||
|
def defaultFileExtension(self):
|
||||||
|
return 'vrt'
|
||||||
|
|
||||||
|
self.addParameter(QgsProcessingParameterMultipleLayers(self.INPUT,
|
||||||
|
self.tr('Input layers'), QgsProcessing.TypeRaster))
|
||||||
|
self.addParameter(QgsProcessingParameterEnum(self.RESOLUTION,
|
||||||
|
self.tr('Resolution'), options=self.RESOLUTION_OPTIONS, defaultValue=0))
|
||||||
|
self.addParameter(QgsProcessingParameterBoolean(self.SEPARATE,
|
||||||
|
self.tr('Layer stack'), defaultValue=True))
|
||||||
|
self.addParameter(QgsProcessingParameterBoolean(self.PROJ_DIFFERENCE,
|
||||||
|
self.tr('Allow projection difference'), defaultValue=False))
|
||||||
|
self.addParameter(ParameterVrtDestination(self.OUTPUT, self.tr('Virtual')))
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return 'buildvirtualraster'
|
return 'buildvirtualraster'
|
||||||
@ -80,25 +94,34 @@ class buildvrt(GdalAlgorithm):
|
|||||||
def getConsoleCommands(self, parameters, context, feedback):
|
def getConsoleCommands(self, parameters, context, feedback):
|
||||||
arguments = []
|
arguments = []
|
||||||
arguments.append('-resolution')
|
arguments.append('-resolution')
|
||||||
arguments.append(self.RESOLUTION_OPTIONS[self.getParameterValue(self.RESOLUTION)])
|
arguments.append(self.RESOLUTION_OPTIONS[self.parameterAsEnum(parameters, self.RESOLUTION, context)])
|
||||||
if self.getParameterValue(buildvrt.SEPARATE):
|
if self.parameterAsBool(parameters, buildvrt.SEPARATE, context):
|
||||||
arguments.append('-separate')
|
arguments.append('-separate')
|
||||||
if self.getParameterValue(buildvrt.PROJ_DIFFERENCE):
|
if self.parameterAsBool(parameters, buildvrt.PROJ_DIFFERENCE, context):
|
||||||
arguments.append('-allow_projection_difference')
|
arguments.append('-allow_projection_difference')
|
||||||
# Always write input files to a text file in case there are many of them and the
|
# Always write input files to a text file in case there are many of them and the
|
||||||
# length of the command will be longer then allowed in command prompt
|
# length of the command will be longer then allowed in command prompt
|
||||||
listFile = os.path.join(QgsProcessingUtils.tempFolder(), 'buildvrtInputFiles.txt')
|
listFile = os.path.join(QgsProcessingUtils.tempFolder(), 'buildvrtInputFiles.txt')
|
||||||
with open(listFile, 'w') as f:
|
with open(listFile, 'w') as f:
|
||||||
f.write(self.getParameterValue(buildvrt.INPUT).replace(';', '\n'))
|
layers = []
|
||||||
|
for l in self.parameterAsLayerList(parameters, self.INPUT, context):
|
||||||
|
layers.append(l.source())
|
||||||
|
f.write('\n'.join(layers))
|
||||||
arguments.append('-input_file_list')
|
arguments.append('-input_file_list')
|
||||||
arguments.append(listFile)
|
arguments.append(listFile)
|
||||||
out = self.getOutputValue(buildvrt.OUTPUT)
|
|
||||||
|
out = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
|
||||||
# Ideally the file extensions should be limited to just .vrt but I'm not sure how
|
# Ideally the file extensions should be limited to just .vrt but I'm not sure how
|
||||||
# to do it simply so instead a check is performed.
|
# to do it simply so instead a check is performed.
|
||||||
_, ext = os.path.splitext(out)
|
_, ext = os.path.splitext(out)
|
||||||
if not ext.lower() == '.vrt':
|
if not ext.lower() == '.vrt':
|
||||||
out = out.replace(ext, '.vrt')
|
out = out[:-len(ext)] + '.vrt'
|
||||||
self.setOutputValue(self.OUTPUT, out)
|
if isinstance(parameters[self.OUTPUT], QgsProcessingOutputLayerDefinition):
|
||||||
|
output_def = QgsProcessingOutputLayerDefinition(parameters[self.OUTPUT])
|
||||||
|
output_def.sink = QgsProperty.fromValue(out)
|
||||||
|
self.setOutputValue(self.OUTPUT, output_def)
|
||||||
|
else:
|
||||||
|
self.setOutputValue(self.OUTPUT, out)
|
||||||
arguments.append(out)
|
arguments.append(out)
|
||||||
|
|
||||||
return ['gdalbuildvrt', GdalUtils.escapeAndJoin(arguments)]
|
return ['gdalbuildvrt', GdalUtils.escapeAndJoin(arguments)]
|
||||||
|
@ -29,12 +29,17 @@ __revision__ = '$Format:%H$'
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from qgis.core import QgsSettings
|
from qgis.core import (QgsSettings,
|
||||||
|
QgsProcessing,
|
||||||
|
QgsVectorFileWriter,
|
||||||
|
QgsProviderRegistry,
|
||||||
|
QgsProcessingModelChildParameterSource)
|
||||||
from qgis.PyQt import uic
|
from qgis.PyQt import uic
|
||||||
from qgis.PyQt.QtCore import Qt
|
from qgis.PyQt.QtCore import Qt
|
||||||
from qgis.PyQt.QtCore import QByteArray
|
from qgis.PyQt.QtCore import QByteArray
|
||||||
from qgis.PyQt.QtWidgets import QDialog, QAbstractItemView, QPushButton, QDialogButtonBox
|
from qgis.PyQt.QtWidgets import QDialog, QAbstractItemView, QPushButton, QDialogButtonBox, QFileDialog
|
||||||
from qgis.PyQt.QtGui import QStandardItemModel, QStandardItem
|
from qgis.PyQt.QtGui import QStandardItemModel, QStandardItem
|
||||||
|
from processing.tools import dataobjects
|
||||||
|
|
||||||
pluginPath = os.path.split(os.path.dirname(__file__))[0]
|
pluginPath = os.path.split(os.path.dirname(__file__))[0]
|
||||||
WIDGET, BASE = uic.loadUiType(
|
WIDGET, BASE = uic.loadUiType(
|
||||||
@ -43,9 +48,11 @@ WIDGET, BASE = uic.loadUiType(
|
|||||||
|
|
||||||
class MultipleInputDialog(BASE, WIDGET):
|
class MultipleInputDialog(BASE, WIDGET):
|
||||||
|
|
||||||
def __init__(self, options, selectedoptions=None):
|
def __init__(self, options, selectedoptions=None, datatype=None):
|
||||||
super(MultipleInputDialog, self).__init__(None)
|
super(MultipleInputDialog, self).__init__(None)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
self.datatype = datatype
|
||||||
|
self.model = None
|
||||||
|
|
||||||
self.lstLayers.setSelectionMode(QAbstractItemView.NoSelection)
|
self.lstLayers.setSelectionMode(QAbstractItemView.NoSelection)
|
||||||
|
|
||||||
@ -68,6 +75,11 @@ class MultipleInputDialog(BASE, WIDGET):
|
|||||||
self.btnToggleSelection = QPushButton(self.tr('Toggle selection'))
|
self.btnToggleSelection = QPushButton(self.tr('Toggle selection'))
|
||||||
self.buttonBox.addButton(self.btnToggleSelection,
|
self.buttonBox.addButton(self.btnToggleSelection,
|
||||||
QDialogButtonBox.ActionRole)
|
QDialogButtonBox.ActionRole)
|
||||||
|
if self.datatype is not None:
|
||||||
|
btnAddFile = QPushButton(self.tr('Add file(s)…'))
|
||||||
|
btnAddFile.clicked.connect(self.addFiles)
|
||||||
|
self.buttonBox.addButton(btnAddFile,
|
||||||
|
QDialogButtonBox.ActionRole)
|
||||||
|
|
||||||
self.btnSelectAll.clicked.connect(lambda: self.selectAll(True))
|
self.btnSelectAll.clicked.connect(lambda: self.selectAll(True))
|
||||||
self.btnClearSelection.clicked.connect(lambda: self.selectAll(False))
|
self.btnClearSelection.clicked.connect(lambda: self.selectAll(False))
|
||||||
@ -76,6 +88,7 @@ class MultipleInputDialog(BASE, WIDGET):
|
|||||||
self.settings = QgsSettings()
|
self.settings = QgsSettings()
|
||||||
self.restoreGeometry(self.settings.value("/Processing/multipleInputDialogGeometry", QByteArray()))
|
self.restoreGeometry(self.settings.value("/Processing/multipleInputDialogGeometry", QByteArray()))
|
||||||
|
|
||||||
|
self.lstLayers.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
||||||
self.populateList()
|
self.populateList()
|
||||||
self.finished.connect(self.saveWindowGeometry)
|
self.finished.connect(self.saveWindowGeometry)
|
||||||
|
|
||||||
@ -83,15 +96,26 @@ class MultipleInputDialog(BASE, WIDGET):
|
|||||||
self.settings.setValue("/Processing/multipleInputDialogGeometry", self.saveGeometry())
|
self.settings.setValue("/Processing/multipleInputDialogGeometry", self.saveGeometry())
|
||||||
|
|
||||||
def populateList(self):
|
def populateList(self):
|
||||||
model = QStandardItemModel()
|
self.model = QStandardItemModel()
|
||||||
for value, text in self.options:
|
for value, text in self.options:
|
||||||
item = QStandardItem(text)
|
item = QStandardItem(text)
|
||||||
item.setData(value, Qt.UserRole)
|
item.setData(value, Qt.UserRole)
|
||||||
item.setCheckState(Qt.Checked if value in self.selectedoptions else Qt.Unchecked)
|
item.setCheckState(Qt.Checked if value in self.selectedoptions else Qt.Unchecked)
|
||||||
item.setCheckable(True)
|
item.setCheckable(True)
|
||||||
model.appendRow(item)
|
self.model.appendRow(item)
|
||||||
|
|
||||||
self.lstLayers.setModel(model)
|
# add extra options (e.g. manually added layers)
|
||||||
|
for t in [o for o in self.selectedoptions if not isinstance(o, int)]:
|
||||||
|
if isinstance(t, QgsProcessingModelChildParameterSource):
|
||||||
|
item = QStandardItem(t.staticValue())
|
||||||
|
else:
|
||||||
|
item = QStandardItem(t)
|
||||||
|
item.setData(item.text(), Qt.UserRole)
|
||||||
|
item.setCheckState(Qt.Checked)
|
||||||
|
item.setCheckable(True)
|
||||||
|
self.model.appendRow(item)
|
||||||
|
|
||||||
|
self.lstLayers.setModel(self.model)
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
self.selectedoptions = []
|
self.selectedoptions = []
|
||||||
@ -106,15 +130,56 @@ class MultipleInputDialog(BASE, WIDGET):
|
|||||||
self.selectedoptions = None
|
self.selectedoptions = None
|
||||||
QDialog.reject(self)
|
QDialog.reject(self)
|
||||||
|
|
||||||
|
def getItemsToModify(self):
|
||||||
|
items = []
|
||||||
|
if len(self.lstLayers.selectedIndexes()) > 1:
|
||||||
|
for i in self.lstLayers.selectedIndexes():
|
||||||
|
items.append(self.model.itemFromIndex(i))
|
||||||
|
else:
|
||||||
|
for i in range(self.model.rowCount()):
|
||||||
|
items.append(self.model.item(i))
|
||||||
|
return items
|
||||||
|
|
||||||
def selectAll(self, value):
|
def selectAll(self, value):
|
||||||
model = self.lstLayers.model()
|
for item in self.getItemsToModify():
|
||||||
for i in range(model.rowCount()):
|
|
||||||
item = model.item(i)
|
|
||||||
item.setCheckState(Qt.Checked if value else Qt.Unchecked)
|
item.setCheckState(Qt.Checked if value else Qt.Unchecked)
|
||||||
|
|
||||||
def toggleSelection(self):
|
def toggleSelection(self):
|
||||||
model = self.lstLayers.model()
|
for item in self.getItemsToModify():
|
||||||
for i in range(model.rowCount()):
|
|
||||||
item = model.item(i)
|
|
||||||
checked = item.checkState() == Qt.Checked
|
checked = item.checkState() == Qt.Checked
|
||||||
item.setCheckState(Qt.Unchecked if checked else Qt.Checked)
|
item.setCheckState(Qt.Unchecked if checked else Qt.Checked)
|
||||||
|
|
||||||
|
def getFileFilter(self, datatype):
|
||||||
|
"""
|
||||||
|
Returns a suitable file filter pattern for the specified parameter definition
|
||||||
|
:param param:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if datatype == QgsProcessing.TypeRaster:
|
||||||
|
return QgsProviderRegistry.instance().fileRasterFilters()
|
||||||
|
elif datatype == QgsProcessing.TypeFile:
|
||||||
|
return self.tr('All files (*.*)')
|
||||||
|
else:
|
||||||
|
exts = QgsVectorFileWriter.supportedFormatExtensions()
|
||||||
|
for i in range(len(exts)):
|
||||||
|
exts[i] = self.tr('{0} files (*.{1})').format(exts[i].upper(), exts[i].lower())
|
||||||
|
return self.tr('All files (*.*)') + ';;' + ';;'.join(exts)
|
||||||
|
|
||||||
|
def addFiles(self):
|
||||||
|
filter = self.getFileFilter(self.datatype)
|
||||||
|
|
||||||
|
settings = QgsSettings()
|
||||||
|
path = str(settings.value('/Processing/LastInputPath'))
|
||||||
|
|
||||||
|
ret, selected_filter = QFileDialog.getOpenFileNames(self, self.tr('Select file(s)'),
|
||||||
|
path, filter)
|
||||||
|
if ret:
|
||||||
|
files = list(ret)
|
||||||
|
settings.setValue('/Processing/LastInputPath',
|
||||||
|
os.path.dirname(str(files[0])))
|
||||||
|
for filename in files:
|
||||||
|
item = QStandardItem(filename)
|
||||||
|
item.setData(filename, Qt.UserRole)
|
||||||
|
item.setCheckState(Qt.Checked)
|
||||||
|
item.setCheckable(True)
|
||||||
|
self.model.appendRow(item)
|
||||||
|
@ -28,9 +28,10 @@ __revision__ = '$Format:%H$'
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from qgis.core import QgsProcessing
|
||||||
from qgis.PyQt import uic
|
from qgis.PyQt import uic
|
||||||
from qgis.PyQt.QtCore import pyqtSignal
|
from qgis.PyQt.QtCore import pyqtSignal
|
||||||
|
''
|
||||||
from processing.gui.MultipleInputDialog import MultipleInputDialog
|
from processing.gui.MultipleInputDialog import MultipleInputDialog
|
||||||
from processing.gui.MultipleFileInputDialog import MultipleFileInputDialog
|
from processing.gui.MultipleFileInputDialog import MultipleFileInputDialog
|
||||||
|
|
||||||
@ -63,10 +64,10 @@ class MultipleInputPanel(BASE, WIDGET):
|
|||||||
self.tr('{0} elements selected').format(len(self.selectedoptions)))
|
self.tr('{0} elements selected').format(len(self.selectedoptions)))
|
||||||
|
|
||||||
def showSelectionDialog(self):
|
def showSelectionDialog(self):
|
||||||
if self.datatype is None:
|
if self.datatype == QgsProcessing.TypeFile:
|
||||||
dlg = MultipleInputDialog(self.options, self.selectedoptions)
|
|
||||||
else:
|
|
||||||
dlg = MultipleFileInputDialog(self.selectedoptions)
|
dlg = MultipleFileInputDialog(self.selectedoptions)
|
||||||
|
else:
|
||||||
|
dlg = MultipleInputDialog(self.options, self.selectedoptions, datatype=self.datatype)
|
||||||
dlg.exec_()
|
dlg.exec_()
|
||||||
if dlg.selectedoptions is not None:
|
if dlg.selectedoptions is not None:
|
||||||
self.selectedoptions = dlg.selectedoptions
|
self.selectedoptions = dlg.selectedoptions
|
||||||
@ -76,12 +77,15 @@ class MultipleInputPanel(BASE, WIDGET):
|
|||||||
|
|
||||||
def updateForOptions(self, options):
|
def updateForOptions(self, options):
|
||||||
selectedoptions = []
|
selectedoptions = []
|
||||||
selected = [self.options[i] for i in self.selectedoptions]
|
selected = [self.options[i] if isinstance(i, int) else i for i in self.selectedoptions]
|
||||||
for sel in selected:
|
for sel in selected:
|
||||||
try:
|
if isinstance(sel, int):
|
||||||
idx = options.index(sel)
|
try:
|
||||||
selectedoptions.append(idx)
|
idx = options.index(sel)
|
||||||
except ValueError:
|
selectedoptions.append(idx)
|
||||||
pass
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
selectedoptions.append(sel)
|
||||||
self.options = options
|
self.options = options
|
||||||
self.setSelectedItems(selectedoptions)
|
self.setSelectedItems(selectedoptions)
|
||||||
|
@ -69,6 +69,7 @@ from qgis.core import (
|
|||||||
QgsProcessingOutputVectorLayer,
|
QgsProcessingOutputVectorLayer,
|
||||||
QgsProcessingOutputString,
|
QgsProcessingOutputString,
|
||||||
QgsProcessingOutputNumber,
|
QgsProcessingOutputNumber,
|
||||||
|
QgsProcessingModelChildParameterSource,
|
||||||
QgsProcessingModelAlgorithm)
|
QgsProcessingModelAlgorithm)
|
||||||
|
|
||||||
from qgis.PyQt.QtWidgets import (
|
from qgis.PyQt.QtWidgets import (
|
||||||
@ -524,20 +525,20 @@ class MultipleInputWidgetWrapper(WidgetWrapper):
|
|||||||
|
|
||||||
def _getOptions(self):
|
def _getOptions(self):
|
||||||
if self.param.layerType() == QgsProcessing.TypeVectorAny:
|
if self.param.layerType() == QgsProcessing.TypeVectorAny:
|
||||||
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer)
|
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer, QgsProcessingParameterMultipleLayers), QgsProcessingOutputVectorLayer)
|
||||||
elif self.param.layerType() == QgsProcessing.TypeVectorPoint:
|
elif self.param.layerType() == QgsProcessing.TypeVectorPoint:
|
||||||
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer,
|
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer, QgsProcessingParameterMultipleLayers), QgsProcessingOutputVectorLayer,
|
||||||
[QgsProcessing.TypeVectorPoint, QgsProcessing.TypeVectorAny])
|
[QgsProcessing.TypeVectorPoint, QgsProcessing.TypeVectorAny])
|
||||||
elif self.param.layerType() == QgsProcessing.TypeVectorLine:
|
elif self.param.layerType() == QgsProcessing.TypeVectorLine:
|
||||||
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer,
|
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer, QgsProcessingParameterMultipleLayers), QgsProcessingOutputVectorLayer,
|
||||||
[QgsProcessing.TypeVectorLine, QgsProcessing.TypeVectorAny])
|
[QgsProcessing.TypeVectorLine, QgsProcessing.TypeVectorAny])
|
||||||
elif self.param.layerType() == QgsProcessing.TypeVectorPolygon:
|
elif self.param.layerType() == QgsProcessing.TypeVectorPolygon:
|
||||||
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer,
|
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer, QgsProcessingParameterMultipleLayers), QgsProcessingOutputVectorLayer,
|
||||||
[QgsProcessing.TypeVectorPolygon, QgsProcessing.TypeVectorAny])
|
[QgsProcessing.TypeVectorPolygon, QgsProcessing.TypeVectorAny])
|
||||||
elif self.param.layerType() == QgsProcessing.TypeRaster:
|
elif self.param.layerType() == QgsProcessing.TypeRaster:
|
||||||
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterRasterLayer, QgsProcessingOutputRasterLayer)
|
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterRasterLayer, QgsProcessingParameterMultipleLayers), QgsProcessingOutputRasterLayer)
|
||||||
elif self.param.layerType() == QgsProcessing.TypeTable:
|
elif self.param.layerType() == QgsProcessing.TypeTable:
|
||||||
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterVectorLayer, OutputTable)
|
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer, QgsProcessingParameterMultipleLayers), OutputTable)
|
||||||
else:
|
else:
|
||||||
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFile, OutputFile)
|
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFile, OutputFile)
|
||||||
options = sorted(options, key=lambda opt: self.dialog.resolveValueDescription(opt))
|
options = sorted(options, key=lambda opt: self.dialog.resolveValueDescription(opt))
|
||||||
@ -546,7 +547,7 @@ class MultipleInputWidgetWrapper(WidgetWrapper):
|
|||||||
def createWidget(self):
|
def createWidget(self):
|
||||||
if self.dialogType == DIALOG_STANDARD:
|
if self.dialogType == DIALOG_STANDARD:
|
||||||
if self.param.layerType() == QgsProcessing.TypeFile:
|
if self.param.layerType() == QgsProcessing.TypeFile:
|
||||||
return MultipleInputPanel(datatype=dataobjects.TYPE_FILE)
|
return MultipleInputPanel(datatype=QgsProcessing.TypeFile)
|
||||||
else:
|
else:
|
||||||
if self.param.layerType() == QgsProcessing.TypeRaster:
|
if self.param.layerType() == QgsProcessing.TypeRaster:
|
||||||
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
|
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
|
||||||
@ -555,14 +556,14 @@ class MultipleInputWidgetWrapper(WidgetWrapper):
|
|||||||
else:
|
else:
|
||||||
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.layerType()], False)
|
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.layerType()], False)
|
||||||
opts = [getExtendedLayerName(opt) for opt in options]
|
opts = [getExtendedLayerName(opt) for opt in options]
|
||||||
return MultipleInputPanel(opts)
|
return MultipleInputPanel(opts, datatype=self.param.layerType())
|
||||||
elif self.dialogType == DIALOG_BATCH:
|
elif self.dialogType == DIALOG_BATCH:
|
||||||
widget = BatchInputSelectionPanel(self.param, self.row, self.col, self.dialog)
|
widget = BatchInputSelectionPanel(self.param, self.row, self.col, self.dialog)
|
||||||
widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||||
return widget
|
return widget
|
||||||
else:
|
else:
|
||||||
options = [self.dialog.resolveValueDescription(opt) for opt in self._getOptions()]
|
options = [self.dialog.resolveValueDescription(opt) for opt in self._getOptions()]
|
||||||
return MultipleInputPanel(options)
|
return MultipleInputPanel(options, datatype=self.param.layerType())
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
if self.param.layerType() != QgsProcessing.TypeFile:
|
if self.param.layerType() != QgsProcessing.TypeFile:
|
||||||
@ -582,11 +583,20 @@ class MultipleInputWidgetWrapper(WidgetWrapper):
|
|||||||
return self.widget.setText(value)
|
return self.widget.setText(value)
|
||||||
else:
|
else:
|
||||||
options = self._getOptions()
|
options = self._getOptions()
|
||||||
selected = []
|
|
||||||
for i, opt in enumerate(options):
|
if not isinstance(value, (tuple, list)):
|
||||||
if opt in value:
|
value = [value]
|
||||||
selected.append(i)
|
|
||||||
self.widget.setSelectedItems(selected)
|
selected_options = []
|
||||||
|
for sel in value:
|
||||||
|
if sel in options:
|
||||||
|
selected_options.append(options.index(sel))
|
||||||
|
elif isinstance(sel, QgsProcessingModelChildParameterSource):
|
||||||
|
selected_options.append(sel.staticValue())
|
||||||
|
else:
|
||||||
|
selected_options.append(sel)
|
||||||
|
|
||||||
|
self.widget.setSelectedItems(selected_options)
|
||||||
|
|
||||||
def value(self):
|
def value(self):
|
||||||
if self.dialogType == DIALOG_STANDARD:
|
if self.dialogType == DIALOG_STANDARD:
|
||||||
@ -599,12 +609,12 @@ class MultipleInputWidgetWrapper(WidgetWrapper):
|
|||||||
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
|
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
|
||||||
else:
|
else:
|
||||||
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.layerType()], False)
|
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.layerType()], False)
|
||||||
return [options[i] for i in self.widget.selectedoptions]
|
return [options[i] if isinstance(i, int) else i for i in self.widget.selectedoptions]
|
||||||
elif self.dialogType == DIALOG_BATCH:
|
elif self.dialogType == DIALOG_BATCH:
|
||||||
return self.widget.getText()
|
return self.widget.getText()
|
||||||
else:
|
else:
|
||||||
options = self._getOptions()
|
options = self._getOptions()
|
||||||
values = [options[i] for i in self.widget.selectedoptions]
|
values = [options[i] if isinstance(i, int) else QgsProcessingModelChildParameterSource.fromStaticValue(i) for i in self.widget.selectedoptions]
|
||||||
if len(values) == 0 and not self.param.flags() & QgsProcessing.FlagOptional:
|
if len(values) == 0 and not self.param.flags() & QgsProcessing.FlagOptional:
|
||||||
raise InvalidParameterValue()
|
raise InvalidParameterValue()
|
||||||
return values
|
return values
|
||||||
|
@ -44,6 +44,7 @@ from qgis.core import (QgsProcessingParameterDefinition,
|
|||||||
QgsProcessingModelChildAlgorithm,
|
QgsProcessingModelChildAlgorithm,
|
||||||
QgsProcessingModelChildParameterSource,
|
QgsProcessingModelChildParameterSource,
|
||||||
QgsProcessingParameterFeatureSink,
|
QgsProcessingParameterFeatureSink,
|
||||||
|
QgsProcessingParameterMultipleLayers,
|
||||||
QgsProcessingParameterRasterDestination,
|
QgsProcessingParameterRasterDestination,
|
||||||
QgsProcessingParameterFileDestination,
|
QgsProcessingParameterFileDestination,
|
||||||
QgsProcessingParameterFolderDestination,
|
QgsProcessingParameterFolderDestination,
|
||||||
@ -236,11 +237,11 @@ class ModelerParametersDialog(QDialog):
|
|||||||
# upgrade paramType to list
|
# upgrade paramType to list
|
||||||
if paramType is None:
|
if paramType is None:
|
||||||
paramType = []
|
paramType = []
|
||||||
elif not isinstance(paramType, list):
|
elif not isinstance(paramType, (tuple, list)):
|
||||||
paramType = [paramType]
|
paramType = [paramType]
|
||||||
if outTypes is None:
|
if outTypes is None:
|
||||||
outTypes = []
|
outTypes = []
|
||||||
elif not isinstance(outTypes, list):
|
elif not isinstance(outTypes, (tuple, list)):
|
||||||
outTypes = [outTypes]
|
outTypes = [outTypes]
|
||||||
|
|
||||||
return self.model.availableSourcesForChild(self.childId, [p.typeName() for p in paramType if issubclass(p, QgsProcessingParameterDefinition)],
|
return self.model.availableSourcesForChild(self.childId, [p.typeName() for p in paramType if issubclass(p, QgsProcessingParameterDefinition)],
|
||||||
|
@ -35,12 +35,9 @@ SET(QGIS_ANALYSIS_SRCS
|
|||||||
raster/qgsrastercalculator.cpp
|
raster/qgsrastercalculator.cpp
|
||||||
raster/qgsrastermatrix.cpp
|
raster/qgsrastermatrix.cpp
|
||||||
vector/mersenne-twister.cpp
|
vector/mersenne-twister.cpp
|
||||||
vector/qgsgeometryanalyzer.cpp
|
|
||||||
vector/qgsgeometrysnapper.cpp
|
vector/qgsgeometrysnapper.cpp
|
||||||
vector/qgspointsample.cpp
|
|
||||||
vector/qgstransectsample.cpp
|
vector/qgstransectsample.cpp
|
||||||
vector/qgszonalstatistics.cpp
|
vector/qgszonalstatistics.cpp
|
||||||
vector/qgsoverlayanalyzer.cpp
|
|
||||||
|
|
||||||
openstreetmap/qgsosmbase.cpp
|
openstreetmap/qgsosmbase.cpp
|
||||||
openstreetmap/qgsosmdatabase.cpp
|
openstreetmap/qgsosmdatabase.cpp
|
||||||
@ -116,9 +113,6 @@ SET(QGIS_ANALYSIS_HDRS
|
|||||||
raster/qgsrastercalcnode.h
|
raster/qgsrastercalcnode.h
|
||||||
raster/qgstotalcurvaturefilter.h
|
raster/qgstotalcurvaturefilter.h
|
||||||
|
|
||||||
vector/qgsgeometryanalyzer.h
|
|
||||||
vector/qgsoverlayanalyzer.h
|
|
||||||
vector/qgspointsample.h
|
|
||||||
vector/qgstransectsample.h
|
vector/qgstransectsample.h
|
||||||
vector/qgszonalstatistics.h
|
vector/qgszonalstatistics.h
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,161 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgsgeometryanalyzer.h - QGIS Tools for vector geometry analysis
|
|
||||||
-------------------
|
|
||||||
begin : 19 March 2009
|
|
||||||
copyright : (C) Carson Farmer
|
|
||||||
email : carson.farmer@gmail.com
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QGSGEOMETRYANALYZERH
|
|
||||||
#define QGSGEOMETRYANALYZERH
|
|
||||||
|
|
||||||
#include "qgsfeature.h"
|
|
||||||
#include "qgsgeometry.h"
|
|
||||||
#include "qgis_analysis.h"
|
|
||||||
|
|
||||||
class QgsVectorFileWriter;
|
|
||||||
class QProgressDialog;
|
|
||||||
class QgsVectorDataProvider;
|
|
||||||
class QgsDistanceArea;
|
|
||||||
|
|
||||||
/** \ingroup analysis
|
|
||||||
* The QGis class provides vector geometry analysis functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ANALYSIS_EXPORT QgsGeometryAnalyzer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/** Simplify vector layer using (a modified) Douglas-Peucker algorithm
|
|
||||||
* and write it to a new shape file
|
|
||||||
* \param layer input vector layer
|
|
||||||
* \param shapefileName path to the output shp
|
|
||||||
* \param tolerance (level of simplification)
|
|
||||||
* \param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
* \param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
*/
|
|
||||||
bool simplify( QgsVectorLayer *layer, const QString &shapefileName, double tolerance,
|
|
||||||
bool onlySelectedFeatures = false, QProgressDialog *p = nullptr );
|
|
||||||
|
|
||||||
/** Calculate the true centroids, or 'center of mass' for a vector layer and
|
|
||||||
* write it to a new shape file
|
|
||||||
* \param layer input vector layer
|
|
||||||
* \param shapefileName path to the output shp
|
|
||||||
* \param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
* \param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
*/
|
|
||||||
bool centroids( QgsVectorLayer *layer, const QString &shapefileName,
|
|
||||||
bool onlySelectedFeatures = false, QProgressDialog *p = nullptr );
|
|
||||||
|
|
||||||
/** Create a polygon based on the extent of all (selected) features and write it to a new shape file
|
|
||||||
* \param layer input vector layer
|
|
||||||
* \param shapefileName path to the output shp
|
|
||||||
* \param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
* \param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
*/
|
|
||||||
bool extent( QgsVectorLayer *layer, const QString &shapefileName, bool onlySelectedFeatures = false, QProgressDialog *p = 0 );
|
|
||||||
|
|
||||||
/** Create buffers for a vector layer and write it to a new shape file
|
|
||||||
* \param layer input vector layer
|
|
||||||
* \param shapefileName path to the output shp
|
|
||||||
* \param bufferDistance distance for buffering (if no buffer field is specified)
|
|
||||||
* \param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
* \param dissolve if true, merge all the buffers to a big multipolygon
|
|
||||||
* \param bufferDistanceField index of the attribute field that contains the buffer distance (or -1 if all features have the same buffer distance)
|
|
||||||
* \param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
*/
|
|
||||||
bool buffer( QgsVectorLayer *layer, const QString &shapefileName, double bufferDistance,
|
|
||||||
bool onlySelectedFeatures = false, bool dissolve = false, int bufferDistanceField = -1, QProgressDialog *p = nullptr );
|
|
||||||
|
|
||||||
/** Create convex hull(s) of a vector layer and write it to a new shape file
|
|
||||||
* \param layer input vector layer
|
|
||||||
* \param shapefileName path to the output shp
|
|
||||||
* \param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
* \param uniqueIdField index of the attribute field that contains the unique convex hull id (or -1 if
|
|
||||||
* all features have the same buffer distance)
|
|
||||||
* \param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
*/
|
|
||||||
bool convexHull( QgsVectorLayer *layer, const QString &shapefileName, bool onlySelectedFeatures = false,
|
|
||||||
int uniqueIdField = -1, QProgressDialog *p = nullptr );
|
|
||||||
|
|
||||||
/** Dissolve a vector layer and write it to a new shape file
|
|
||||||
* \param layer input vector layer
|
|
||||||
* \param shapefileName path to the output shp
|
|
||||||
* \param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
* \param uniqueIdField index of the attribute field that contains the unique id to dissolve on (or -1 if
|
|
||||||
* all features should be dissolved together)
|
|
||||||
* \param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
*/
|
|
||||||
bool dissolve( QgsVectorLayer *layer, const QString &shapefileName, bool onlySelectedFeatures = false,
|
|
||||||
int uniqueIdField = -1, QProgressDialog *p = nullptr );
|
|
||||||
|
|
||||||
/** Creates an event layer (multipoint or multiline) by locating features from a (non-spatial) event table along the features of a line layer.
|
|
||||||
* Note that currently (until QgsGeometry supports m-values) the z-coordinate of the line layer is used for linear referencing
|
|
||||||
* \param lineLayer layer with the line geometry
|
|
||||||
* \param eventLayer layer with features and location field
|
|
||||||
* \param lineField join index in line layer
|
|
||||||
* \param eventField join index in event layer
|
|
||||||
* \param outputLayer name of output file (can be empty if a memory layer is used)
|
|
||||||
* \param outputFormat name of output format (can be empty if a memory provider is used to store the results)
|
|
||||||
* \param unlocatedFeatureIds out: ids of event features where linear referencing was not successful
|
|
||||||
* \param locationField1 attribute index of location field in event layer
|
|
||||||
* \param locationField2 attribute index of location end field (or -1 for point layer)
|
|
||||||
* \param offsetField attribute index for offset field. Negative offset value = offset to left side, positive value = offset to right side
|
|
||||||
* \param offsetScale factor to scale offset
|
|
||||||
* \param forceSingleGeometry force layer to single point/line type. Feature attributes are copied in case of multiple matches
|
|
||||||
* \param memoryProvider memory provider to write output to (can be 0 if output is written to a file)
|
|
||||||
* \param p progress dialog or 0 if no progress dialog should be shown
|
|
||||||
*/
|
|
||||||
bool eventLayer( QgsVectorLayer *lineLayer, QgsVectorLayer *eventLayer, int lineField, int eventField, QgsFeatureIds &unlocatedFeatureIds SIP_OUT, const QString &outputLayer,
|
|
||||||
const QString &outputFormat, int locationField1, int locationField2 = -1, int offsetField = -1, double offsetScale = 1.0,
|
|
||||||
bool forceSingleGeometry = false, QgsVectorDataProvider *memoryProvider = nullptr, QProgressDialog *p = nullptr );
|
|
||||||
|
|
||||||
//! Returns linear reference geometry as a multiline (or 0 if no match). Currently, the z-coordinates are considered to be the measures (no support for m-values in QGIS)
|
|
||||||
QgsGeometry locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry &lineGeom );
|
|
||||||
|
|
||||||
/** Returns linear reference geometry. Unlike the PostGIS function, this method always returns multipoint or 0 if no match (not geometry collection).
|
|
||||||
* Currently, the z-coordinates are considered to be the measures (no support for m-values in QGIS)
|
|
||||||
*/
|
|
||||||
QgsGeometry locateAlongMeasure( double measure, const QgsGeometry &lineGeom );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
QList<double> simpleMeasure( QgsGeometry &geometry );
|
|
||||||
double perimeterMeasure( const QgsGeometry &geometry, QgsDistanceArea &measure );
|
|
||||||
//! Helper function to simplify an individual feature
|
|
||||||
void simplifyFeature( QgsFeature &f, QgsVectorFileWriter *vfw, double tolerance );
|
|
||||||
//! Helper function to get the cetroid of an individual feature
|
|
||||||
void centroidFeature( QgsFeature &f, QgsVectorFileWriter *vfw );
|
|
||||||
//! Helper function to buffer an individual feature
|
|
||||||
void bufferFeature( QgsFeature &f, int nProcessedFeatures, QgsVectorFileWriter *vfw, bool dissolve, QgsGeometry &dissolveGeometry,
|
|
||||||
double bufferDistance, int bufferDistanceField );
|
|
||||||
//! Helper function to get the convex hull of feature(s)
|
|
||||||
void convexFeature( QgsFeature &f, int nProcessedFeatures, QgsGeometry &dissolveGeometry );
|
|
||||||
//! Helper function to dissolve feature(s)
|
|
||||||
QgsGeometry dissolveFeature( const QgsFeature &f, const QgsGeometry &dissolveInto );
|
|
||||||
|
|
||||||
//helper functions for event layer
|
|
||||||
void addEventLayerFeature( QgsFeature &feature, const QgsGeometry &geom, const QgsGeometry &lineGeom, QgsVectorFileWriter *fileWriter, QgsFeatureList &memoryFeatures, int offsetField = -1, double offsetScale = 1.0,
|
|
||||||
bool forceSingleType = false );
|
|
||||||
|
|
||||||
/** Create geometry offset relative to line geometry.
|
|
||||||
\param geom the geometry to modify
|
|
||||||
\param lineGeom the line geometry to which the feature is referenced
|
|
||||||
\param offset the offset value in layer unit. Negative values mean offset towards left, positive values offset to the right side*/
|
|
||||||
QgsGeometry createOffsetGeometry( const QgsGeometry &geom, const QgsGeometry &lineGeom, double offset );
|
|
||||||
QgsPointXY createPointOffset( double x, double y, double dist, const QgsGeometry &lineGeom ) const;
|
|
||||||
QgsConstWkbPtr locateBetweenWkbString( QgsConstWkbPtr ptr, QgsMultiPolyline &result, double fromMeasure, double toMeasure );
|
|
||||||
QgsConstWkbPtr locateAlongWkbString( QgsConstWkbPtr ptr, QgsMultiPoint &result, double measure );
|
|
||||||
static bool clipSegmentByRange( double x1, double y1, double m1, double x2, double y2, double m2, double range1, double range2, QgsPointXY &pt1, QgsPointXY &pt2, bool &secondPointClipped );
|
|
||||||
static void locateAlongSegment( double x1, double y1, double m1, double x2, double y2, double m2, double measure, bool &pt1Ok, QgsPointXY &pt1, bool &pt2Ok, QgsPointXY &pt2 );
|
|
||||||
};
|
|
||||||
#endif //QGSVECTORANALYZER
|
|
@ -1,195 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgsoverlayanalyzer.cpp - QGIS Tools for vector geometry analysis
|
|
||||||
-------------------
|
|
||||||
begin : 8 Nov 2009
|
|
||||||
copyright : (C) Carson J. Q. Farmer
|
|
||||||
email : carson.farmer@gmail.com
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include "qgsoverlayanalyzer.h"
|
|
||||||
|
|
||||||
#include "qgsapplication.h"
|
|
||||||
#include "qgsfeatureiterator.h"
|
|
||||||
#include "qgsfields.h"
|
|
||||||
#include "qgsfeature.h"
|
|
||||||
#include "qgsgeometry.h"
|
|
||||||
#include "qgslogger.h"
|
|
||||||
#include "qgscoordinatereferencesystem.h"
|
|
||||||
#include "qgsspatialindex.h"
|
|
||||||
#include "qgsvectorfilewriter.h"
|
|
||||||
#include "qgsvectordataprovider.h"
|
|
||||||
#include "qgsdistancearea.h"
|
|
||||||
#include <QProgressDialog>
|
|
||||||
|
|
||||||
bool QgsOverlayAnalyzer::intersection( QgsVectorLayer *layerA, QgsVectorLayer *layerB,
|
|
||||||
const QString &shapefileName, bool onlySelectedFeatures,
|
|
||||||
QProgressDialog *p )
|
|
||||||
{
|
|
||||||
if ( !layerA || !layerB )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsVectorDataProvider *dpA = layerA->dataProvider();
|
|
||||||
QgsVectorDataProvider *dpB = layerB->dataProvider();
|
|
||||||
if ( !dpA || !dpB )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsWkbTypes::Type outputType = dpA->wkbType();
|
|
||||||
QgsCoordinateReferenceSystem crs = layerA->crs();
|
|
||||||
QgsFields fieldsA = layerA->fields();
|
|
||||||
QgsFields fieldsB = layerB->fields();
|
|
||||||
combineFieldLists( fieldsA, fieldsB );
|
|
||||||
|
|
||||||
QgsVectorFileWriter vWriter( shapefileName, dpA->encoding(), fieldsA, outputType, crs );
|
|
||||||
QgsFeature currentFeature;
|
|
||||||
|
|
||||||
//take only selection
|
|
||||||
if ( onlySelectedFeatures )
|
|
||||||
{
|
|
||||||
QgsFeatureIds selectionB = layerB->selectedFeatureIds();
|
|
||||||
QgsFeatureRequest req = QgsFeatureRequest().setFilterFids( selectionB ).setSubsetOfAttributes( QgsAttributeList() );
|
|
||||||
QgsSpatialIndex index = QgsSpatialIndex( layerB->getFeatures( req ) );
|
|
||||||
|
|
||||||
//use QgsVectorLayer::featureAtId
|
|
||||||
const QgsFeatureIds selectionA = layerA->selectedFeatureIds();
|
|
||||||
if ( p )
|
|
||||||
{
|
|
||||||
p->setMaximum( selectionA.size() );
|
|
||||||
}
|
|
||||||
req = QgsFeatureRequest().setFilterFids( selectionA );
|
|
||||||
QgsFeatureIterator selectionAIt = layerA->getFeatures( req );
|
|
||||||
QgsFeature currentFeature;
|
|
||||||
int processedFeatures = 0;
|
|
||||||
while ( selectionAIt.nextFeature( currentFeature ) )
|
|
||||||
{
|
|
||||||
if ( p )
|
|
||||||
{
|
|
||||||
p->setValue( processedFeatures );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( p && p->wasCanceled() )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
intersectFeature( currentFeature, &vWriter, layerB, &index );
|
|
||||||
++processedFeatures;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( p )
|
|
||||||
{
|
|
||||||
p->setValue( selectionA.size() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//take all features
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QgsFeatureRequest req = QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() );
|
|
||||||
QgsSpatialIndex index = QgsSpatialIndex( layerB->getFeatures( req ) );
|
|
||||||
|
|
||||||
int featureCount = layerA->featureCount();
|
|
||||||
if ( p )
|
|
||||||
{
|
|
||||||
p->setMaximum( featureCount );
|
|
||||||
}
|
|
||||||
int processedFeatures = 0;
|
|
||||||
|
|
||||||
QgsFeatureIterator fit = layerA->getFeatures();
|
|
||||||
|
|
||||||
QgsFeature currentFeature;
|
|
||||||
while ( fit.nextFeature( currentFeature ) )
|
|
||||||
{
|
|
||||||
if ( p )
|
|
||||||
{
|
|
||||||
p->setValue( processedFeatures );
|
|
||||||
}
|
|
||||||
if ( p && p->wasCanceled() )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
intersectFeature( currentFeature, &vWriter, layerB, &index );
|
|
||||||
++processedFeatures;
|
|
||||||
}
|
|
||||||
if ( p )
|
|
||||||
{
|
|
||||||
p->setValue( featureCount );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsOverlayAnalyzer::intersectFeature( QgsFeature &f, QgsVectorFileWriter *vfw,
|
|
||||||
QgsVectorLayer *vl, QgsSpatialIndex *index )
|
|
||||||
{
|
|
||||||
if ( !f.hasGeometry() )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsGeometry featureGeometry = f.geometry();
|
|
||||||
QgsGeometry intersectGeometry;
|
|
||||||
QgsFeature overlayFeature;
|
|
||||||
|
|
||||||
QList<QgsFeatureId> intersects = index->intersects( featureGeometry.boundingBox() );
|
|
||||||
QgsFeatureRequest req = QgsFeatureRequest().setFilterFids( intersects.toSet() );
|
|
||||||
QgsFeatureIterator intersectIt = vl->getFeatures( req );
|
|
||||||
QgsFeature outFeature;
|
|
||||||
while ( intersectIt.nextFeature( overlayFeature ) )
|
|
||||||
{
|
|
||||||
if ( featureGeometry.intersects( overlayFeature.geometry() ) )
|
|
||||||
{
|
|
||||||
intersectGeometry = featureGeometry.intersection( overlayFeature.geometry() );
|
|
||||||
|
|
||||||
outFeature.setGeometry( intersectGeometry );
|
|
||||||
QgsAttributes attributesA = f.attributes();
|
|
||||||
QgsAttributes attributesB = overlayFeature.attributes();
|
|
||||||
combineAttributeMaps( attributesA, attributesB );
|
|
||||||
outFeature.setAttributes( attributesA );
|
|
||||||
|
|
||||||
//add it to vector file writer
|
|
||||||
if ( vfw )
|
|
||||||
{
|
|
||||||
vfw->addFeature( outFeature );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsOverlayAnalyzer::combineFieldLists( QgsFields &fieldListA, const QgsFields &fieldListB )
|
|
||||||
{
|
|
||||||
QList<QString> names;
|
|
||||||
Q_FOREACH ( const QgsField &field, fieldListA )
|
|
||||||
names.append( field.name() );
|
|
||||||
|
|
||||||
for ( int idx = 0; idx < fieldListB.count(); ++idx )
|
|
||||||
{
|
|
||||||
QgsField field = fieldListB.at( idx );
|
|
||||||
int count = 0;
|
|
||||||
while ( names.contains( field.name() ) )
|
|
||||||
{
|
|
||||||
QString name = QStringLiteral( "%1_%2" ).arg( field.name() ).arg( count );
|
|
||||||
field = QgsField( name, field.type() );
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
fieldListA.append( field );
|
|
||||||
names.append( field.name() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsOverlayAnalyzer::combineAttributeMaps( QgsAttributes &attributesA, const QgsAttributes &attributesB )
|
|
||||||
{
|
|
||||||
attributesA += attributesB;
|
|
||||||
}
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgsoverlayanalyzer.h - QGIS Tools for vector geometry analysis
|
|
||||||
-------------------
|
|
||||||
begin : 19 March 2009
|
|
||||||
copyright : (C) Carson Farmer
|
|
||||||
email : carson.farmer@gmail.com
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QGSOVERLAYANALYZERH
|
|
||||||
#define QGSOVERLAYANALYZERH
|
|
||||||
|
|
||||||
#include "qgsvectorlayer.h"
|
|
||||||
#include "qgis_analysis.h"
|
|
||||||
|
|
||||||
class QgsVectorFileWriter;
|
|
||||||
class QProgressDialog;
|
|
||||||
class QgsSpatialIndex;
|
|
||||||
|
|
||||||
/** \ingroup analysis
|
|
||||||
* The QGis class provides vector overlay analysis functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ANALYSIS_EXPORT QgsOverlayAnalyzer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/** Perform an intersection on two input vector layers and write output to a new shape file
|
|
||||||
\param layerA input vector layer
|
|
||||||
\param layerB input vector layer
|
|
||||||
\param shapefileName path to the output shp
|
|
||||||
\param onlySelectedFeatures if true, only selected features are considered, else all the features
|
|
||||||
\param p progress dialog (or 0 if no progress dialog is to be shown)
|
|
||||||
*/
|
|
||||||
bool intersection( QgsVectorLayer *layerA, QgsVectorLayer *layerB,
|
|
||||||
const QString &shapefileName, bool onlySelectedFeatures = false,
|
|
||||||
QProgressDialog *p = nullptr );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void combineFieldLists( QgsFields &fieldListA, const QgsFields &fieldListB );
|
|
||||||
void intersectFeature( QgsFeature &f, QgsVectorFileWriter *vfw, QgsVectorLayer *dp, QgsSpatialIndex *index );
|
|
||||||
void combineAttributeMaps( QgsAttributes &attributesA, const QgsAttributes &attributesB );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //QGSVECTORANALYZER
|
|
@ -1,170 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgspointsample.cpp
|
|
||||||
---------------------
|
|
||||||
begin : July 2013
|
|
||||||
copyright : (C) 2013 by Marco Hugentobler
|
|
||||||
email : marco dot hugentobler at sourcepole 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. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
#include "qgspointsample.h"
|
|
||||||
#include "qgsfeatureiterator.h"
|
|
||||||
#include "qgsgeometry.h"
|
|
||||||
#include "qgsspatialindex.h"
|
|
||||||
#include "qgsvectorfilewriter.h"
|
|
||||||
#include "qgsvectorlayer.h"
|
|
||||||
#include <QFile>
|
|
||||||
#include "mersenne-twister.h"
|
|
||||||
|
|
||||||
|
|
||||||
QgsPointSample::QgsPointSample( QgsVectorLayer *inputLayer, const QString &outputLayer, const QString &nPointsAttribute, const QString &minDistAttribute ): mInputLayer( inputLayer ),
|
|
||||||
mOutputLayer( outputLayer ), mNumberOfPointsAttribute( nPointsAttribute ), mMinDistanceAttribute( minDistAttribute ), mNCreatedPoints( 0 )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsPointSample::QgsPointSample()
|
|
||||||
: mInputLayer( nullptr )
|
|
||||||
, mNCreatedPoints( 0 )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int QgsPointSample::createRandomPoints( QProgressDialog *pd )
|
|
||||||
{
|
|
||||||
Q_UNUSED( pd );
|
|
||||||
|
|
||||||
//create input layer from id (test if polygon, valid)
|
|
||||||
if ( !mInputLayer )
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( mInputLayer->geometryType() != QgsWkbTypes::PolygonGeometry )
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
//delete output file if it already exists
|
|
||||||
if ( QFile::exists( mOutputLayer ) )
|
|
||||||
{
|
|
||||||
QgsVectorFileWriter::deleteShapeFile( mOutputLayer );
|
|
||||||
}
|
|
||||||
|
|
||||||
//create vector file writer
|
|
||||||
QgsFields outputFields;
|
|
||||||
outputFields.append( QgsField( QStringLiteral( "id" ), QVariant::Int ) );
|
|
||||||
outputFields.append( QgsField( QStringLiteral( "station_id" ), QVariant::Int ) );
|
|
||||||
outputFields.append( QgsField( QStringLiteral( "stratum_id" ), QVariant::Int ) );
|
|
||||||
QgsVectorFileWriter writer( mOutputLayer, QStringLiteral( "UTF-8" ),
|
|
||||||
outputFields,
|
|
||||||
QgsWkbTypes::Point,
|
|
||||||
mInputLayer->crs() );
|
|
||||||
|
|
||||||
//check if creation of output layer successful
|
|
||||||
if ( writer.hasError() != QgsVectorFileWriter::NoError )
|
|
||||||
{
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
//init random number generator
|
|
||||||
mt_srand( QTime::currentTime().msec() );
|
|
||||||
QgsFeature fet;
|
|
||||||
int nPoints = 0;
|
|
||||||
double minDistance = 0;
|
|
||||||
mNCreatedPoints = 0;
|
|
||||||
|
|
||||||
QgsFeatureIterator fIt = mInputLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes(
|
|
||||||
QStringList() << mNumberOfPointsAttribute << mMinDistanceAttribute, mInputLayer->fields() ) );
|
|
||||||
while ( fIt.nextFeature( fet ) )
|
|
||||||
{
|
|
||||||
nPoints = fet.attribute( mNumberOfPointsAttribute ).toInt();
|
|
||||||
if ( !mMinDistanceAttribute.isEmpty() )
|
|
||||||
{
|
|
||||||
minDistance = fet.attribute( mMinDistanceAttribute ).toDouble();
|
|
||||||
}
|
|
||||||
addSamplePoints( fet, writer, nPoints, minDistance );
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsPointSample::addSamplePoints( QgsFeature &inputFeature, QgsVectorFileWriter &writer, int nPoints, double minDistance )
|
|
||||||
{
|
|
||||||
if ( !inputFeature.hasGeometry() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
QgsGeometry geom = inputFeature.geometry();
|
|
||||||
QgsRectangle geomRect = geom.boundingBox();
|
|
||||||
if ( geomRect.isEmpty() )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsSpatialIndex sIndex; //to check minimum distance
|
|
||||||
QMap< QgsFeatureId, QgsPointXY > pointMapForFeature;
|
|
||||||
|
|
||||||
int nIterations = 0;
|
|
||||||
int maxIterations = nPoints * 200;
|
|
||||||
int points = 0;
|
|
||||||
|
|
||||||
double randX = 0;
|
|
||||||
double randY = 0;
|
|
||||||
|
|
||||||
while ( nIterations < maxIterations && points < nPoints )
|
|
||||||
{
|
|
||||||
randX = ( ( double )mt_rand() / MD_RAND_MAX ) * geomRect.width() + geomRect.xMinimum();
|
|
||||||
randY = ( ( double )mt_rand() / MD_RAND_MAX ) * geomRect.height() + geomRect.yMinimum();
|
|
||||||
QgsPointXY randPoint( randX, randY );
|
|
||||||
QgsGeometry ptGeom = QgsGeometry::fromPoint( randPoint );
|
|
||||||
if ( ptGeom.within( geom ) && checkMinDistance( randPoint, sIndex, minDistance, pointMapForFeature ) )
|
|
||||||
{
|
|
||||||
//add feature to writer
|
|
||||||
QgsFeature f( mNCreatedPoints );
|
|
||||||
f.setAttribute( QStringLiteral( "id" ), mNCreatedPoints + 1 );
|
|
||||||
f.setAttribute( QStringLiteral( "station_id" ), points + 1 );
|
|
||||||
f.setAttribute( QStringLiteral( "stratum_id" ), inputFeature.id() );
|
|
||||||
f.setGeometry( ptGeom );
|
|
||||||
writer.addFeature( f );
|
|
||||||
sIndex.insertFeature( f );
|
|
||||||
pointMapForFeature.insert( mNCreatedPoints, randPoint );
|
|
||||||
++points;
|
|
||||||
++mNCreatedPoints;
|
|
||||||
}
|
|
||||||
++nIterations;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QgsPointSample::checkMinDistance( QgsPointXY &pt, QgsSpatialIndex &index, double minDistance, QMap< QgsFeatureId, QgsPointXY > &pointMap )
|
|
||||||
{
|
|
||||||
if ( minDistance <= 0 )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QgsFeatureId> neighborList = index.nearestNeighbor( pt, 1 );
|
|
||||||
if ( neighborList.isEmpty() )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMap< QgsFeatureId, QgsPointXY >::const_iterator it = pointMap.find( neighborList[0] );
|
|
||||||
if ( it == pointMap.constEnd() ) //should not happen
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsPointXY neighborPt = it.value();
|
|
||||||
if ( neighborPt.sqrDist( pt ) < ( minDistance * minDistance ) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgspointsample.h
|
|
||||||
---------------------
|
|
||||||
begin : July 2013
|
|
||||||
copyright : (C) 2013 by Marco Hugentobler
|
|
||||||
email : marco dot hugentobler at sourcepole 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. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
#ifndef QGSPOINTSAMPLE_H
|
|
||||||
#define QGSPOINTSAMPLE_H
|
|
||||||
|
|
||||||
#include "qgsfeature.h"
|
|
||||||
#include <QString>
|
|
||||||
#include "qgis_analysis.h"
|
|
||||||
|
|
||||||
class QgsFeature;
|
|
||||||
class QgsPointXY;
|
|
||||||
class QgsSpatialIndex;
|
|
||||||
class QgsVectorFileWriter;
|
|
||||||
class QgsVectorLayer;
|
|
||||||
class QProgressDialog;
|
|
||||||
|
|
||||||
/** \ingroup analysis
|
|
||||||
* Creates random points in polygons / multipolygons*/
|
|
||||||
class ANALYSIS_EXPORT QgsPointSample
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QgsPointSample( QgsVectorLayer *inputLayer, const QString &outputLayer, const QString &nPointsAttribute, const QString &minDistAttribute = QString() );
|
|
||||||
|
|
||||||
/** Starts calculation of random points
|
|
||||||
\returns 0 in case of success*/
|
|
||||||
int createRandomPoints( QProgressDialog *pd );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
QgsPointSample(); //default constructor is forbidden
|
|
||||||
void addSamplePoints( QgsFeature &inputFeature, QgsVectorFileWriter &writer, int nPoints, double minDistance );
|
|
||||||
bool checkMinDistance( QgsPointXY &pt, QgsSpatialIndex &index, double minDistance, QMap< QgsFeatureId, QgsPointXY > &pointMap );
|
|
||||||
|
|
||||||
//! Layer id of input polygon/multipolygon layer
|
|
||||||
QgsVectorLayer *mInputLayer = nullptr;
|
|
||||||
//! Output path of result layer
|
|
||||||
QString mOutputLayer;
|
|
||||||
//! Attribute containing number of points per feature
|
|
||||||
QString mNumberOfPointsAttribute;
|
|
||||||
//! Attribute containing minimum distance between sample points (or -1 if no min. distance constraint)
|
|
||||||
QString mMinDistanceAttribute;
|
|
||||||
QgsFeatureId mNCreatedPoints; //helper to find free ids
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QGSPOINTSAMPLE_H
|
|
@ -124,8 +124,6 @@ SET(QGIS_APP_SRCS
|
|||||||
qgstextannotationdialog.cpp
|
qgstextannotationdialog.cpp
|
||||||
qgssvgannotationdialog.cpp
|
qgssvgannotationdialog.cpp
|
||||||
qgsundowidget.cpp
|
qgsundowidget.cpp
|
||||||
qgstipgui.cpp
|
|
||||||
qgstipfactory.cpp
|
|
||||||
qgsvectorlayerproperties.cpp
|
qgsvectorlayerproperties.cpp
|
||||||
qgsmapthemes.cpp
|
qgsmapthemes.cpp
|
||||||
qgshandlebadlayers.cpp
|
qgshandlebadlayers.cpp
|
||||||
@ -342,8 +340,6 @@ SET (QGIS_APP_MOC_HDRS
|
|||||||
qgsstatisticalsummarydockwidget.h
|
qgsstatisticalsummarydockwidget.h
|
||||||
qgssvgannotationdialog.h
|
qgssvgannotationdialog.h
|
||||||
qgstextannotationdialog.h
|
qgstextannotationdialog.h
|
||||||
qgstipgui.h
|
|
||||||
qgstipfactory.h
|
|
||||||
qgsundowidget.h
|
qgsundowidget.h
|
||||||
qgsvectorlayerproperties.h
|
qgsvectorlayerproperties.h
|
||||||
qgsmapthemes.h
|
qgsmapthemes.h
|
||||||
|
@ -261,7 +261,6 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
|
|||||||
#include "qgstaskmanagerwidget.h"
|
#include "qgstaskmanagerwidget.h"
|
||||||
#include "qgssymbolselectordialog.h"
|
#include "qgssymbolselectordialog.h"
|
||||||
#include "qgstextannotation.h"
|
#include "qgstextannotation.h"
|
||||||
#include "qgstipgui.h"
|
|
||||||
#include "qgsundowidget.h"
|
#include "qgsundowidget.h"
|
||||||
#include "qgsuserinputdockwidget.h"
|
#include "qgsuserinputdockwidget.h"
|
||||||
#include "qgsvectordataprovider.h"
|
#include "qgsvectordataprovider.h"
|
||||||
@ -1181,18 +1180,6 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
|
|||||||
toggleSnapping->setProperty( "Icon", QgsApplication::getThemeIcon( "/mIconSnapping.svg" ) );
|
toggleSnapping->setProperty( "Icon", QgsApplication::getThemeIcon( "/mIconSnapping.svg" ) );
|
||||||
connect( toggleSnapping, &QShortcut::activated, mSnappingUtils, &QgsSnappingUtils::toggleEnabled );
|
connect( toggleSnapping, &QShortcut::activated, mSnappingUtils, &QgsSnappingUtils::toggleEnabled );
|
||||||
|
|
||||||
// Show a nice tip of the day
|
|
||||||
if ( settings.value( QStringLiteral( "qgis/showTips%1" ).arg( Qgis::QGIS_VERSION_INT / 100 ), true ).toBool() )
|
|
||||||
{
|
|
||||||
mSplash->hide();
|
|
||||||
QgsTipGui myTip( this );
|
|
||||||
myTip.exec();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QgsDebugMsg( "Tips are disabled" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! QTouchDevice::devices().isEmpty() )
|
if ( ! QTouchDevice::devices().isEmpty() )
|
||||||
{
|
{
|
||||||
//add reacting to long click in touch
|
//add reacting to long click in touch
|
||||||
|
@ -628,7 +628,6 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
|
|||||||
mLegendLayersBoldChkBx->setChecked( mSettings->value( QStringLiteral( "/qgis/legendLayersBold" ), true ).toBool() );
|
mLegendLayersBoldChkBx->setChecked( mSettings->value( QStringLiteral( "/qgis/legendLayersBold" ), true ).toBool() );
|
||||||
mLegendGroupsBoldChkBx->setChecked( mSettings->value( QStringLiteral( "/qgis/legendGroupsBold" ), false ).toBool() );
|
mLegendGroupsBoldChkBx->setChecked( mSettings->value( QStringLiteral( "/qgis/legendGroupsBold" ), false ).toBool() );
|
||||||
cbxHideSplash->setChecked( mSettings->value( QStringLiteral( "/qgis/hideSplash" ), false ).toBool() );
|
cbxHideSplash->setChecked( mSettings->value( QStringLiteral( "/qgis/hideSplash" ), false ).toBool() );
|
||||||
cbxShowTips->setChecked( mSettings->value( QStringLiteral( "/qgis/showTips%1" ).arg( Qgis::QGIS_VERSION_INT / 100 ), true ).toBool() );
|
|
||||||
mDataSourceManagerNonModal->setChecked( mSettings->value( "/qgis/dataSourceManagerNonModal", false ).toBool() );
|
mDataSourceManagerNonModal->setChecked( mSettings->value( "/qgis/dataSourceManagerNonModal", false ).toBool() );
|
||||||
cbxCheckVersion->setChecked( mSettings->value( QStringLiteral( "/qgis/checkVersion" ), true ).toBool() );
|
cbxCheckVersion->setChecked( mSettings->value( QStringLiteral( "/qgis/checkVersion" ), true ).toBool() );
|
||||||
cbxAttributeTableDocked->setChecked( mSettings->value( QStringLiteral( "/qgis/dockAttributeTable" ), false ).toBool() );
|
cbxAttributeTableDocked->setChecked( mSettings->value( QStringLiteral( "/qgis/dockAttributeTable" ), false ).toBool() );
|
||||||
@ -1209,7 +1208,6 @@ void QgsOptions::saveOptions()
|
|||||||
bool legendGroupsBold = mSettings->value( QStringLiteral( "/qgis/legendGroupsBold" ), false ).toBool();
|
bool legendGroupsBold = mSettings->value( QStringLiteral( "/qgis/legendGroupsBold" ), false ).toBool();
|
||||||
mSettings->setValue( QStringLiteral( "/qgis/legendGroupsBold" ), mLegendGroupsBoldChkBx->isChecked() );
|
mSettings->setValue( QStringLiteral( "/qgis/legendGroupsBold" ), mLegendGroupsBoldChkBx->isChecked() );
|
||||||
mSettings->setValue( QStringLiteral( "/qgis/hideSplash" ), cbxHideSplash->isChecked() );
|
mSettings->setValue( QStringLiteral( "/qgis/hideSplash" ), cbxHideSplash->isChecked() );
|
||||||
mSettings->setValue( QStringLiteral( "/qgis/showTips%1" ).arg( Qgis::QGIS_VERSION_INT / 100 ), cbxShowTips->isChecked() );
|
|
||||||
mSettings->setValue( QStringLiteral( "/qgis/dataSourceManagerNonModal" ), mDataSourceManagerNonModal->isChecked() );
|
mSettings->setValue( QStringLiteral( "/qgis/dataSourceManagerNonModal" ), mDataSourceManagerNonModal->isChecked() );
|
||||||
mSettings->setValue( QStringLiteral( "/qgis/checkVersion" ), cbxCheckVersion->isChecked() );
|
mSettings->setValue( QStringLiteral( "/qgis/checkVersion" ), cbxCheckVersion->isChecked() );
|
||||||
mSettings->setValue( QStringLiteral( "/qgis/dockAttributeTable" ), cbxAttributeTableDocked->isChecked() );
|
mSettings->setValue( QStringLiteral( "/qgis/dockAttributeTable" ), cbxAttributeTableDocked->isChecked() );
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgstip.h
|
|
||||||
---------------------
|
|
||||||
begin : February 2011
|
|
||||||
copyright : (C) 2011 by Tim Sutton
|
|
||||||
email : tim at linfiniti 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 QGSTIP
|
|
||||||
#define QGSTIP
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QString>
|
|
||||||
#include "qgis_app.h"
|
|
||||||
|
|
||||||
/** \ingroup app
|
|
||||||
* \brief An QgsTip represents a tip generated by the
|
|
||||||
* QgsTipFactory factory class to serve up tips to the user.
|
|
||||||
* Tips can be generic, in which case they make no mention of
|
|
||||||
* gui dialogs etc, or gui-specific in which case they may allude
|
|
||||||
* to features of the graphical user interface.
|
|
||||||
* \see also QgsTipOfTheDay, QgsTipFactory
|
|
||||||
*/
|
|
||||||
|
|
||||||
class APP_EXPORT QgsTip
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Constructor
|
|
||||||
QgsTip() {}
|
|
||||||
//! Destructor
|
|
||||||
~QgsTip() {}
|
|
||||||
//
|
|
||||||
// Accessors
|
|
||||||
//
|
|
||||||
//! Get the tip title
|
|
||||||
QString title() {return mTitle;}
|
|
||||||
//! Get the tip content
|
|
||||||
QString content() {return mContent;}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Mutators
|
|
||||||
//
|
|
||||||
//! Set the tip title
|
|
||||||
void setTitle( const QString &title ) {mTitle = title;}
|
|
||||||
//! Set the tip content
|
|
||||||
void setContent( const QString &content ) {mContent = content;}
|
|
||||||
private:
|
|
||||||
QString mTitle;
|
|
||||||
QString mContent;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //QGSTIP
|
|
||||||
|
|
@ -1,362 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgstipfactory.cpp
|
|
||||||
---------------------
|
|
||||||
begin : February 2011
|
|
||||||
copyright : (C) 2007 by Tim Sutton
|
|
||||||
email : tim at linfiniti 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 "qgstipfactory.h"
|
|
||||||
#include <QTime>
|
|
||||||
//for rand & srand
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
|
|
||||||
QgsTipFactory::QgsTipFactory() : QObject()
|
|
||||||
{
|
|
||||||
// I'm just doing this in a simple way so
|
|
||||||
// its easy for translators...later
|
|
||||||
// it its worth the time I'll move this data
|
|
||||||
// into a sqlite database...
|
|
||||||
QgsTip myTip;
|
|
||||||
myTip.setTitle( tr( "QGIS is open source" ) );
|
|
||||||
myTip.setContent( tr( "QGIS is open source software."
|
|
||||||
" This means that the software source code can be freely viewed"
|
|
||||||
" and modified. The GPL places a restriction that any modifications"
|
|
||||||
" you make must be made available in source form to whoever you give"
|
|
||||||
" modified versions to, and that you can not create a new version of"
|
|
||||||
" QGIS under a 'closed source' license. Visit"
|
|
||||||
" <a href=\"https://qgis.org\"> the QGIS home page</a>"
|
|
||||||
" for more information."
|
|
||||||
) );
|
|
||||||
addGenericTip( myTip );
|
|
||||||
//
|
|
||||||
myTip.setTitle( tr( "QGIS Publications" ) );
|
|
||||||
myTip.setContent( tr( "If you write a scientific paper or any other article"
|
|
||||||
" that refers to QGIS we would love to include your work"
|
|
||||||
" in the <a href=\"https://qgis.org/en/site/about/case_studies/index.html\">case studies section</a> of"
|
|
||||||
" the QGIS home page."
|
|
||||||
) );
|
|
||||||
addGenericTip( myTip );
|
|
||||||
myTip.setTitle( tr( "Become a QGIS translator" ) );
|
|
||||||
myTip.setContent( tr( "Would you like to see QGIS"
|
|
||||||
" in your native language? We are looking for more translators"
|
|
||||||
" and would appreciate your help! The translation process is"
|
|
||||||
" fairly straight forward - instructions are available in the"
|
|
||||||
" QGIS wiki"
|
|
||||||
" <a href=\"https://qgis.org/en/site/getinvolved/translate.html#howto-translate-gui\">translator's page.</a>"
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
myTip.setTitle( tr( "Getting Help With QGIS" ) );
|
|
||||||
myTip.setContent( tr( "If you need help using QGIS"
|
|
||||||
" there is a 'users' mailing list where users help each other with issues"
|
|
||||||
" related to using QGIS. We also have a 'developers' mailing list"
|
|
||||||
" for those wanting help and discuss things relating to the QGIS code base."
|
|
||||||
" Details on different means to get help are described in the"
|
|
||||||
" <a href=\"https://qgis.org/en/site/forusers/support.html#mailing-lists\">community section</a> of the QGIS home page."
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
myTip.setTitle( tr( "Is it 'QGIS' or 'Quantum GIS'?" ) );
|
|
||||||
myTip.setContent( tr( "Both used to be correct, but we recently decided to just use 'QGIS'. For articles we suggest you write 'QGIS is ....'"
|
|
||||||
) );
|
|
||||||
addGenericTip( myTip );
|
|
||||||
myTip.setTitle( tr( "How do I refer to QGIS?" ) );
|
|
||||||
myTip.setContent( tr( "QGIS is spelled in all caps."
|
|
||||||
" We have various subprojects of the QGIS project"
|
|
||||||
" and it will help to avoid confusion if you refer to each by"
|
|
||||||
" its name:"
|
|
||||||
"<ul>"
|
|
||||||
"<li><strong>QGIS Library</strong> - this is the C++ library that contains"
|
|
||||||
" the core logic that is used to build the QGIS user interface and other applications.</li>"
|
|
||||||
"<li><strong>QGIS Desktop</strong> - this is the desktop application that you know and love so much :-).</li>"
|
|
||||||
"<li><strong>QGIS Server</strong> - this is a server-side application based on the QGIS Library"
|
|
||||||
" that will serve up your .qgs projects using OGC standard protocols.</li>"
|
|
||||||
"</ul>"
|
|
||||||
) );
|
|
||||||
addGenericTip( myTip );
|
|
||||||
// This tip contributed by Andreas Neumann
|
|
||||||
myTip.setTitle( tr( "Add the current date to a map layout" ) );
|
|
||||||
myTip.setContent( tr( "You can add a current date variable to your map"
|
|
||||||
" layout. Create a regular text label and add the string"
|
|
||||||
" $CURRENT_DATE(yyyy-MM-dd) to the text box. See the"
|
|
||||||
" <a href=\"https://doc.qt.io/qt-5.3/qdate.html#toString\">"
|
|
||||||
"QDate::toString format documentation</a> for the possible date formats."
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
myTip.setTitle( tr( "Moving Elements and Maps in the Print Composer" ) );
|
|
||||||
myTip.setContent( tr( "In the print composer toolbar you can find two buttons for moving"
|
|
||||||
" elements. The first one ( <img src=\":/images/themes/default/mActionSelect.svg\"/> )"
|
|
||||||
" selects and moves elements in the layout. After selecting the element"
|
|
||||||
" with this tool you can also move them around with the arrow keys."
|
|
||||||
" For accurate positioning use the <strong>%1</strong> section,"
|
|
||||||
" which can be found in the tab <strong>%2</strong>."
|
|
||||||
" The other move tool ( <img src=\":/images/themes/default/mActionMoveItemContent.svg\"/> )"
|
|
||||||
" allows you to move the map content within a map frame." )
|
|
||||||
.arg( tr( "Position and Size" ) )
|
|
||||||
.arg( tr( "Item Properties" ) )
|
|
||||||
);
|
|
||||||
addGuiTip( myTip );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// This tip contributed by Andreas Neumann
|
|
||||||
myTip.setTitle( tr( "Lock an item in the layout view" ) );
|
|
||||||
myTip.setContent( tr( "Locking an element in the layout view prevents you to select or accidentally"
|
|
||||||
" move it with the mouse. Locking an item is done by checking its"
|
|
||||||
" <img src=\":/images/themes/default/locked.svg\"/> state in the"
|
|
||||||
" <strong>%1</strong> tab. While in a locked state, you can still get it"
|
|
||||||
" selected from the <strong>%1</strong> tab, and configure any of its"
|
|
||||||
" properties in the <strong>%2</strong> tab, including precisely setting"
|
|
||||||
" its position and size." )
|
|
||||||
.arg( tr( "Items" ) )
|
|
||||||
.arg( tr( "Item Properties" ) )
|
|
||||||
);
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// This tip contributed by Andreas Neumann
|
|
||||||
myTip.setTitle( tr( "Rotating a map and linking a north arrow" ) );
|
|
||||||
myTip.setContent( tr( "In the Print Composer you can rotate a map by setting its rotation value"
|
|
||||||
" in the tab <strong>Item Properties -> Map -> Main properties</strong> section."
|
|
||||||
" To place a north arrow in your layout you can use the"
|
|
||||||
" <strong>%1</strong> tool. After the selection and"
|
|
||||||
" placement of the north arrow in the layout you can link it"
|
|
||||||
" with a specific map frame by activating the <strong>%2</strong>"
|
|
||||||
" checkbox and selecting a map frame. Whenever you change the rotation"
|
|
||||||
" value of a linked map, the north arrow will now automatically adjust"
|
|
||||||
" its rotation." )
|
|
||||||
.arg( tr( "Add Image" ) )
|
|
||||||
.arg( tr( "Sync with map" ) )
|
|
||||||
);
|
|
||||||
addGuiTip( myTip );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// This tip contributed by Andreas Neumann
|
|
||||||
myTip.setTitle( tr( "Numeric scale value in map layout linked to map frame" ) );
|
|
||||||
myTip.setContent( tr( "If you want to place a text label as a placeholder for the"
|
|
||||||
" current scale, linked to a map frame, you need to place a scalebar and"
|
|
||||||
" set the style to 'Numeric'. You also need to select the map frame, if there"
|
|
||||||
" is more than one."
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by Tim
|
|
||||||
myTip.setTitle( tr( "Using the mouse scroll wheel" ) );
|
|
||||||
myTip.setContent( tr( "You can use the scroll wheel on your mouse to zoom in,"
|
|
||||||
" out and pan the map. Scroll forwards to zoom in, scroll backwards to"
|
|
||||||
" zoom out and press and hold the scroll wheel down to pan the map. You"
|
|
||||||
" can configure the zoom scale factor in the <strong> %1 -> %2 </strong> panel." )
|
|
||||||
.arg( tr( "Options" ) )
|
|
||||||
.arg( tr( "Map tools" ) )
|
|
||||||
);
|
|
||||||
addGuiTip( myTip );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by Tim
|
|
||||||
myTip.setTitle( tr( "Disabling rendering" ) );
|
|
||||||
myTip.setContent( tr( "Sometimes you have a very large dataset which takes ages"
|
|
||||||
" to draw. If you are going to be performing several"
|
|
||||||
" actions (e.g. modifying symbology options) and wish to temporarily"
|
|
||||||
" disable map rendering while you do so, you can uncheck the 'Render'"
|
|
||||||
" checkbox in the bottom right of the status bar. Don't forget to check"
|
|
||||||
" it on again when you are ready to have the map draw itself again!"
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// Tip contributed by Alister Hood
|
|
||||||
myTip.setTitle( tr( "Join intersected polylines when rendering" ) );
|
|
||||||
myTip.setContent( tr( "When applying layered styles to a polyline layer, you can join"
|
|
||||||
" intersecting lines together simply by enabling symbol levels."
|
|
||||||
" The image below shows a before (left) and after (right) view of"
|
|
||||||
" an intersection when symbol levels are enabled." ) +
|
|
||||||
QStringLiteral( "<p><center><img src=\":/images/tips/symbol_levels.png\"/></center></p>" )
|
|
||||||
);
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by Tim
|
|
||||||
myTip.setTitle( tr( "Auto-enable on the fly projection" ) );
|
|
||||||
myTip.setContent( tr( "In the options dialog, under the CRS tab, you can set QGIS so that"
|
|
||||||
" whenever you create a new project, 'on the fly projection' is enabled"
|
|
||||||
" automatically and a pre-selected Coordinate Reference System of your"
|
|
||||||
" choice is used."
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by Tim
|
|
||||||
myTip.setTitle( tr( "Sponsor QGIS" ) );
|
|
||||||
myTip.setContent( tr( "If QGIS is saving you money or you like our work and"
|
|
||||||
" have the financial ability to help, please consider sponsoring the"
|
|
||||||
" development of QGIS. We use money from sponsors to pay for"
|
|
||||||
" travel and costs related to our regular hackfest meetings, and to generally"
|
|
||||||
" support the goals of our project. Please see the <a"
|
|
||||||
" href=\"https://qgis.org/en/site/getinvolved/governance/sponsorship/sponsorship.html\">QGIS Sponsorship Web"
|
|
||||||
" Page</a> for more details."
|
|
||||||
) );
|
|
||||||
addGenericTip( myTip );
|
|
||||||
// by gsherman
|
|
||||||
myTip.setTitle( tr( "QGIS has Plugins!" ) );
|
|
||||||
myTip.setContent( tr( "QGIS has plugins that extend its functionality."
|
|
||||||
" QGIS ships with some core plugins you can explore from the"
|
|
||||||
" <strong> %1 -> %2</strong> menu. In addition there"
|
|
||||||
" are a lot of <a href=\"https://plugins.qgis.org/\">Python plugins </a>"
|
|
||||||
" contributed by the user community that can be"
|
|
||||||
" installed via this same menu. Don't miss out on all QGIS has to offer!"
|
|
||||||
" Check out the plugins and see what they can do for you." )
|
|
||||||
.arg( tr( "Plugins" ) )
|
|
||||||
.arg( tr( "Manage and Install Plugins..." ) )
|
|
||||||
);
|
|
||||||
addGuiTip( myTip );
|
|
||||||
addGenericTip( myTip );
|
|
||||||
// by yjacolin
|
|
||||||
myTip.setTitle( tr( "Add an action to layer" ) );
|
|
||||||
myTip.setContent( tr( "Action in a layer allows user to trigger action when clicking on a geometry"
|
|
||||||
" with 'Run Feature Action' tools."
|
|
||||||
"For example, you can open a HTML page using the field value of the geometry "
|
|
||||||
"as a parameter. Look at the <a href=\"https://docs.qgis.org/latest/en/docs/user_manual/working_with_vector/vector_properties.html?#actions-menu\">documentation</a>."
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by yjacolin
|
|
||||||
myTip.setTitle( tr( "Copy, paste and cut in QGIS" ) );
|
|
||||||
myTip.setContent( tr( "Copy, paste, and cut work as in another applications in QGIS. Select a "
|
|
||||||
"feature (a geometry or an attribute row in the attribute table) and use "
|
|
||||||
"one of these shortcuts: Ctrl+C to copy, Ctrl+X to cut, and Ctrl+V to paste."
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by yjacolin
|
|
||||||
myTip.setTitle( tr( "Right click with identify tools" ) );
|
|
||||||
myTip.setContent( tr( "Right click with the identify tool to show a context menu from which you can "
|
|
||||||
"choose the layer in which to identify a feature. A sub-menu will list features "
|
|
||||||
"identified and a third sub-menu will show the action link setup for the layer. "
|
|
||||||
"If one of this sub-menu doesn't contain any information, the next sub-menu "
|
|
||||||
"will appear instead. For example, if you have just one layer, and click "
|
|
||||||
"somewhere with several features, the first menu will list the features "
|
|
||||||
"instead of layer list."
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by Alister Hood
|
|
||||||
myTip.setTitle( tr( "Use VRT files" ) );
|
|
||||||
myTip.setContent( tr( "If you have a number of aerial photos spread across a wide area, instead of "
|
|
||||||
"loading each file as a separate layer you can treat them all as a single layer "
|
|
||||||
"by using a .vrt file. "
|
|
||||||
"To create a .vrt, go to <strong> %1 -> %2 -> %3</strong>." )
|
|
||||||
.arg( tr( "Raster" ) )
|
|
||||||
.arg( tr( "Miscellaneous" ) )
|
|
||||||
.arg( tr( "Build Virtual Raster (Catalog)" ) )
|
|
||||||
);
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by Harrissou Sant-anna
|
|
||||||
myTip.setTitle( tr( "Switch quickly between different styles of the layer" ) );
|
|
||||||
myTip.setContent( tr( "From the Layer properties dialog, use the <strong>Styles -> Add</strong> combobox"
|
|
||||||
" to create as many combinations of layer properties settings (symbology, labeling,"
|
|
||||||
" diagram, fields form, actions...) as you want. Then, simply switch between styles"
|
|
||||||
" from the context menu of the layer in <strong>%1</strong> to automatically"
|
|
||||||
" get different custom representations of your data." )
|
|
||||||
.arg( tr( "Layers Panel" ) )
|
|
||||||
);
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by Harrissou Sant-anna
|
|
||||||
myTip.setTitle( tr( "Live update rendering" ) );
|
|
||||||
myTip.setContent( tr( "Press F7 to activate the <strong>%1</strong> panel from which you can"
|
|
||||||
" easily and quickly configure the layer rendering. Check the <strong>%2</strong>"
|
|
||||||
" option to automatically apply to the map canvas each of your modifications." )
|
|
||||||
.arg( tr( "Layer Styling" ) )
|
|
||||||
.arg( tr( "Live update" ) )
|
|
||||||
);
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by Harrissou Sant-anna
|
|
||||||
myTip.setTitle( tr( "Print or export a specific feature from an atlas composition" ) );
|
|
||||||
myTip.setContent( tr( "If you want to print or export the composition of only one feature of the atlas,"
|
|
||||||
" start the atlas preview, select the desired feature in the drop-down list"
|
|
||||||
" and click on <strong>Composer -> Print</strong> menu (or use <strong>Composer ->"
|
|
||||||
" Export...</strong> to any supported file format)."
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by Harrissou Sant-anna
|
|
||||||
myTip.setTitle( tr( "Start QGIS from command line" ) );
|
|
||||||
myTip.setContent( tr( "QGIS can be launched from command line and supports a number of options. This can be"
|
|
||||||
" handy if you need to use QGIS with particular configurations such as custom"
|
|
||||||
" user profile or, without plugins... To get the list of the options,"
|
|
||||||
" enter qgis --help on the command line."
|
|
||||||
) );
|
|
||||||
addGuiTip( myTip );
|
|
||||||
// by Harrissou Sant-anna
|
|
||||||
myTip.setTitle( tr( "Set your own shortcuts for your actions" ) );
|
|
||||||
myTip.setContent( tr( "QGIS provides you with a list of predefined shortcuts you can use to speed"
|
|
||||||
" your workflow. These are available under <strong> %1 -> %2 </strong>"
|
|
||||||
" menu and can be extended and customized for any dialog or tool." )
|
|
||||||
.arg( tr( "Settings" ) )
|
|
||||||
.arg( tr( "Keyboard Shortcuts" ) )
|
|
||||||
);
|
|
||||||
addGuiTip( myTip );
|
|
||||||
|
|
||||||
/* Template for adding more tips
|
|
||||||
myTip.setTitle(tr(""));
|
|
||||||
myTip.setContent(tr(""
|
|
||||||
));
|
|
||||||
addGuiTip(myTip);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsTipFactory::~QgsTipFactory()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
//private helper method
|
|
||||||
void QgsTipFactory::addGuiTip( const QgsTip &tip )
|
|
||||||
{
|
|
||||||
mGuiTips << tip;
|
|
||||||
mAllTips << tip;
|
|
||||||
}
|
|
||||||
//private helper method
|
|
||||||
void QgsTipFactory::addGenericTip( const QgsTip &tip )
|
|
||||||
{
|
|
||||||
mGenericTips << tip;
|
|
||||||
mAllTips << tip;
|
|
||||||
}
|
|
||||||
QgsTip QgsTipFactory::getTip()
|
|
||||||
{
|
|
||||||
int myRand = qrand();
|
|
||||||
int myValue = static_cast<int>( myRand % mAllTips.count() ); //range [0,(count-1)]
|
|
||||||
QgsTip myTip = mAllTips.at( myValue );
|
|
||||||
return myTip;
|
|
||||||
}
|
|
||||||
QgsTip QgsTipFactory::getTip( int position )
|
|
||||||
{
|
|
||||||
QgsTip myTip = mAllTips.at( position );
|
|
||||||
return myTip;
|
|
||||||
}
|
|
||||||
QgsTip QgsTipFactory::getGenericTip()
|
|
||||||
{
|
|
||||||
int myRand = qrand();
|
|
||||||
int myValue = static_cast<int>( myRand % mGenericTips.count() ); //range [0,(count-1)]
|
|
||||||
QgsTip myTip = mGenericTips.at( myValue );
|
|
||||||
return myTip;
|
|
||||||
}
|
|
||||||
QgsTip QgsTipFactory::getGuiTip()
|
|
||||||
{
|
|
||||||
int myRand = qrand();
|
|
||||||
int myValue = static_cast<int>( myRand % mGuiTips.count() ); //range [0,(count-1)]
|
|
||||||
QgsTip myTip = mGuiTips.at( myValue );
|
|
||||||
return myTip;
|
|
||||||
}
|
|
||||||
|
|
||||||
int QgsTipFactory::randomNumber( int max )
|
|
||||||
{
|
|
||||||
Q_UNUSED( max );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int QgsTipFactory::position( QgsTip tip )
|
|
||||||
{
|
|
||||||
for ( int i = 0; i < mAllTips.count(); ++i )
|
|
||||||
{
|
|
||||||
QgsTip myTip = mAllTips.at( i );
|
|
||||||
if ( myTip.title() == tip.title() )
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int QgsTipFactory::count()
|
|
||||||
{
|
|
||||||
return mAllTips.count();
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgstipfactory.h
|
|
||||||
---------------------
|
|
||||||
begin : February 2011
|
|
||||||
copyright : (C) 2011 by Tim Sutton
|
|
||||||
email : tim at linfiniti 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 QGSTIPFACTORY
|
|
||||||
#define QGSTIPFACTORY
|
|
||||||
|
|
||||||
#include "qgstip.h"
|
|
||||||
#include <QList>
|
|
||||||
#include "qgis_app.h"
|
|
||||||
|
|
||||||
/** \ingroup app
|
|
||||||
* \brief A factory class to serve up tips to the user.
|
|
||||||
* Tips can be generic, in which case they make no mention of
|
|
||||||
* gui dialogs etc, or gui-specific in which case they may allude
|
|
||||||
* to features of the graphical user interface.
|
|
||||||
* \see also QgsTipOfTheDay, QgsTip
|
|
||||||
*/
|
|
||||||
|
|
||||||
class APP_EXPORT QgsTipFactory : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT //used for tr() so we don't need to do QObject::tr()
|
|
||||||
public:
|
|
||||||
//! Constructor
|
|
||||||
QgsTipFactory();
|
|
||||||
|
|
||||||
~QgsTipFactory();
|
|
||||||
|
|
||||||
/** Get a random tip (generic or gui-centric)
|
|
||||||
* \returns An QgsTip containing the tip
|
|
||||||
*/
|
|
||||||
QgsTip getTip();
|
|
||||||
|
|
||||||
/** Get a specific tip (generic or gui-centric).
|
|
||||||
* \param position The tip returned will be based on the
|
|
||||||
* number passed in as position. If the
|
|
||||||
* position is invalid, an empty string will be
|
|
||||||
* returned.
|
|
||||||
* \returns An QgsTip containing the tip
|
|
||||||
*/
|
|
||||||
QgsTip getTip( int position );
|
|
||||||
|
|
||||||
/** Get a random generic tip
|
|
||||||
* \returns An QgsTip containing the tip
|
|
||||||
*/
|
|
||||||
QgsTip getGenericTip();
|
|
||||||
|
|
||||||
/** Get a random gui-centric tip
|
|
||||||
* \returns An QgsTip containing the tip
|
|
||||||
*/
|
|
||||||
QgsTip getGuiTip();
|
|
||||||
|
|
||||||
int position( QgsTip );
|
|
||||||
int count();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void addGenericTip( const QgsTip & );
|
|
||||||
void addGuiTip( const QgsTip & );
|
|
||||||
int randomNumber( int max );
|
|
||||||
//@TODO move tipts into a sqlite db
|
|
||||||
QList <QgsTip> mGenericTips;
|
|
||||||
QList <QgsTip> mGuiTips;
|
|
||||||
QList <QgsTip> mAllTips;
|
|
||||||
};
|
|
||||||
#endif //QGSTIPFACTORY
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgstipgui.cpp - description
|
|
||||||
-------------------
|
|
||||||
begin : Sat Aug 10 2002
|
|
||||||
copyright : (C) 2002 by Gary E.Sherman
|
|
||||||
email : sherman at mrcc.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 <QPushButton>
|
|
||||||
|
|
||||||
#include "qgstipgui.h"
|
|
||||||
#include "qgssettings.h"
|
|
||||||
#include "qgsapplication.h"
|
|
||||||
#include "qgstip.h"
|
|
||||||
#include "qgstipfactory.h"
|
|
||||||
|
|
||||||
#ifdef Q_OS_MACX
|
|
||||||
QgsTipGui::QgsTipGui( QWidget *parent )
|
|
||||||
: QDialog( parent, Qt::WindowSystemMenuHint ) // Dialog with close button only
|
|
||||||
#else
|
|
||||||
QgsTipGui::QgsTipGui( QWidget * parent )
|
|
||||||
: QDialog( parent ) // Normal dialog in non Mac-OS
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
setupUi( this );
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsTipGui::~QgsTipGui()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsTipGui::init()
|
|
||||||
{
|
|
||||||
|
|
||||||
QgsTipFactory myFactory;
|
|
||||||
QgsTip myTip = myFactory.getTip();
|
|
||||||
mTipPosition = myFactory.position( myTip );
|
|
||||||
|
|
||||||
showTip( myTip );
|
|
||||||
|
|
||||||
QPushButton *pb = nullptr;
|
|
||||||
pb = new QPushButton( tr( "&Previous" ) );
|
|
||||||
connect( pb, &QAbstractButton::clicked, this, &QgsTipGui::prevClicked );
|
|
||||||
buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
|
|
||||||
|
|
||||||
pb = new QPushButton( tr( "&Next" ) );
|
|
||||||
connect( pb, &QAbstractButton::clicked, this, &QgsTipGui::nextClicked );
|
|
||||||
buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsTipGui::showTip( QgsTip myTip )
|
|
||||||
{
|
|
||||||
// TODO - This html construction can be simplified using QStringBuilder
|
|
||||||
// once Qt 4.6 is the minimum required version for building QGIS.
|
|
||||||
//
|
|
||||||
QString content = "<img src='"
|
|
||||||
+ QgsApplication::appIconPath()
|
|
||||||
+ "' style='float:left;'>"
|
|
||||||
+ "<h2>"
|
|
||||||
+ myTip.title()
|
|
||||||
+ "</h2><br clear='all'/>"
|
|
||||||
+ myTip.content();
|
|
||||||
|
|
||||||
txtTip->setHtml( content );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsTipGui::on_cbxDisableTips_toggled( bool flag )
|
|
||||||
{
|
|
||||||
QgsSettings settings;
|
|
||||||
//note the ! below as when the cbx is checked (true) we want to
|
|
||||||
//change the setting to false
|
|
||||||
settings.setValue( QStringLiteral( "/qgis/showTips%1" ).arg( Qgis::QGIS_VERSION_INT / 100 ), !flag );
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsTipGui::nextClicked()
|
|
||||||
{
|
|
||||||
mTipPosition += 1;
|
|
||||||
QgsTipFactory myFactory;
|
|
||||||
if ( mTipPosition >= myFactory.count() )
|
|
||||||
{
|
|
||||||
mTipPosition = 0;
|
|
||||||
}
|
|
||||||
QgsTip myTip = myFactory.getTip( mTipPosition );
|
|
||||||
showTip( myTip );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsTipGui::prevClicked()
|
|
||||||
{
|
|
||||||
mTipPosition -= 1;
|
|
||||||
QgsTipFactory myFactory;
|
|
||||||
if ( mTipPosition < 0 )
|
|
||||||
{
|
|
||||||
mTipPosition = myFactory.count() - 1;
|
|
||||||
}
|
|
||||||
QgsTip myTip = myFactory.getTip( mTipPosition );
|
|
||||||
showTip( myTip );
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgstipgui.h - description
|
|
||||||
-------------------
|
|
||||||
begin : Fri 18 Feb 2011
|
|
||||||
copyright : (C) 2011 by Tim Sutton
|
|
||||||
email : tim@linfiniti.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 QGSTIPGUI_H
|
|
||||||
#define QGSTIPGUI_H
|
|
||||||
|
|
||||||
#include "ui_qgstipguibase.h"
|
|
||||||
#include "qgis_app.h"
|
|
||||||
class QgsTip;
|
|
||||||
|
|
||||||
class APP_EXPORT QgsTipGui : public QDialog, private Ui::QgsTipGuiBase
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
QgsTipGui( QWidget *parent = nullptr );
|
|
||||||
~QgsTipGui();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init();
|
|
||||||
void showTip( QgsTip );
|
|
||||||
|
|
||||||
int mTipPosition;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_cbxDisableTips_toggled( bool flag );
|
|
||||||
void prevClicked();
|
|
||||||
void nextClicked();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -22,6 +22,7 @@
|
|||||||
#include "qgsprocessingoutputs.h"
|
#include "qgsprocessingoutputs.h"
|
||||||
#include "qgssettings.h"
|
#include "qgssettings.h"
|
||||||
#include "qgsvectorfilewriter.h"
|
#include "qgsvectorfilewriter.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
bool QgsProcessingParameters::isDynamic( const QVariantMap ¶meters, const QString &name )
|
bool QgsProcessingParameters::isDynamic( const QVariantMap ¶meters, const QString &name )
|
||||||
{
|
{
|
||||||
@ -596,33 +597,38 @@ QList<QgsMapLayer *> QgsProcessingParameters::parameterAsLayerList( const QgsPro
|
|||||||
|
|
||||||
QStringList resultStringList;
|
QStringList resultStringList;
|
||||||
|
|
||||||
if ( val.canConvert<QgsProperty>() )
|
std::function< void( const QVariant &var ) > processVariant;
|
||||||
resultStringList << val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
|
processVariant = [ &resultStringList, &layers, &context, &definition, &processVariant ]( const QVariant & var )
|
||||||
else if ( val.type() == QVariant::List )
|
|
||||||
{
|
{
|
||||||
Q_FOREACH ( const QVariant &var, val.toList() )
|
if ( var.type() == QVariant::List )
|
||||||
{
|
{
|
||||||
if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( var ) ) )
|
Q_FOREACH ( const QVariant &listVar, var.toList() )
|
||||||
{
|
{
|
||||||
layers << layer;
|
processVariant( listVar );
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resultStringList << var.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if ( var.type() == QVariant::StringList )
|
||||||
else if ( val.type() == QVariant::StringList )
|
|
||||||
{
|
|
||||||
Q_FOREACH ( const QString &s, val.toStringList() )
|
|
||||||
{
|
{
|
||||||
resultStringList << s;
|
Q_FOREACH ( const QString &s, var.toStringList() )
|
||||||
|
{
|
||||||
|
resultStringList << s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else if ( var.canConvert<QgsProperty>() )
|
||||||
else
|
resultStringList << var.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
|
||||||
resultStringList << val.toString();
|
else if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( var ) ) )
|
||||||
|
{
|
||||||
|
layers << layer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resultStringList << var.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if ( ( resultStringList.isEmpty() || resultStringList.at( 0 ).isEmpty() ) )
|
processVariant( val );
|
||||||
|
|
||||||
|
if ( layers.isEmpty() && ( resultStringList.isEmpty() || resultStringList.at( 0 ).isEmpty() ) )
|
||||||
{
|
{
|
||||||
resultStringList.clear();
|
resultStringList.clear();
|
||||||
// check default
|
// check default
|
||||||
|
@ -614,21 +614,6 @@ QString QgsApplication::licenceFilePath()
|
|||||||
return ABISYM( mPkgDataPath ) + QStringLiteral( "/doc/LICENSE" );
|
return ABISYM( mPkgDataPath ) + QStringLiteral( "/doc/LICENSE" );
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QgsApplication::helpAppPath()
|
|
||||||
{
|
|
||||||
QString helpAppPath;
|
|
||||||
#ifdef Q_OS_MACX
|
|
||||||
helpAppPath = applicationDirPath() + "/bin/qgis_help.app/Contents/MacOS";
|
|
||||||
#else
|
|
||||||
helpAppPath = libexecPath();
|
|
||||||
#endif
|
|
||||||
helpAppPath += QLatin1String( "/qgis_help" );
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
helpAppPath += ".exe";
|
|
||||||
#endif
|
|
||||||
return helpAppPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QgsApplication::i18nPath()
|
QString QgsApplication::i18nPath()
|
||||||
{
|
{
|
||||||
if ( ABISYM( mRunningFromBuildDir ) )
|
if ( ABISYM( mRunningFromBuildDir ) )
|
||||||
|
@ -234,9 +234,6 @@ class CORE_EXPORT QgsApplication : public QApplication
|
|||||||
*/
|
*/
|
||||||
static QString licenceFilePath();
|
static QString licenceFilePath();
|
||||||
|
|
||||||
//! Returns the path to the help application.
|
|
||||||
static QString helpAppPath();
|
|
||||||
|
|
||||||
//! Returns the path to the translation directory.
|
//! Returns the path to the translation directory.
|
||||||
static QString i18nPath();
|
static QString i18nPath();
|
||||||
|
|
||||||
|
@ -20,13 +20,18 @@
|
|||||||
#include "qgsproject.h"
|
#include "qgsproject.h"
|
||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
#include "qgsrasterlayer.h"
|
#include "qgsrasterlayer.h"
|
||||||
|
#include "qgsogrprovider.h"
|
||||||
#include "qgsnewgeopackagelayerdialog.h"
|
#include "qgsnewgeopackagelayerdialog.h"
|
||||||
|
#include "qgsmessageoutput.h"
|
||||||
|
#include "qgsvectorlayerexporter.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
|
||||||
|
QGISEXTERN bool deleteLayer( const QString &uri, const QString &errCause );
|
||||||
|
|
||||||
QgsDataItem *QgsGeoPackageDataItemProvider::createDataItem( const QString &path, QgsDataItem *parentItem )
|
QgsDataItem *QgsGeoPackageDataItemProvider::createDataItem( const QString &path, QgsDataItem *parentItem )
|
||||||
{
|
{
|
||||||
QgsDebugMsg( "path = " + path );
|
QgsDebugMsg( "path = " + path );
|
||||||
@ -268,6 +273,115 @@ QList<QAction *> QgsGeoPackageConnectionItem::actions()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAction )
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( !QgsMimeDataUtils::isUriList( data ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// TODO: probably should show a GUI with settings etc
|
||||||
|
QString uri;
|
||||||
|
|
||||||
|
QStringList importResults;
|
||||||
|
bool hasError = false;
|
||||||
|
|
||||||
|
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
|
||||||
|
Q_FOREACH ( const QgsMimeDataUtils::Uri &u, lst )
|
||||||
|
{
|
||||||
|
if ( u.layerType == QStringLiteral( "vector" ) )
|
||||||
|
{
|
||||||
|
// open the source layer
|
||||||
|
bool owner;
|
||||||
|
QString error;
|
||||||
|
QgsVectorLayer *srcLayer = u.vectorLayer( owner, error );
|
||||||
|
if ( !srcLayer )
|
||||||
|
{
|
||||||
|
importResults.append( tr( "%1: %2" ).arg( u.name ).arg( error ) );
|
||||||
|
hasError = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( srcLayer->isValid() )
|
||||||
|
{
|
||||||
|
uri = mPath;
|
||||||
|
QgsDebugMsgLevel( "URI " + uri, 3 );
|
||||||
|
|
||||||
|
// check if the destination layer already exists
|
||||||
|
bool exists = false;
|
||||||
|
// Q_FOREACH won't detach ...
|
||||||
|
for ( const auto child : children() )
|
||||||
|
{
|
||||||
|
if ( child->name() == u.name )
|
||||||
|
{
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( ! exists || QMessageBox::question( nullptr, tr( "Overwrite Layer" ),
|
||||||
|
tr( "Destination layer <b>%1</b> already exists. Do you want to overwrite it?" ).arg( u.name ), QMessageBox::Yes | QMessageBox::No ) == QMessageBox::Yes )
|
||||||
|
{
|
||||||
|
|
||||||
|
std::unique_ptr< QMap<QString, QVariant> > options( new QMap<QString, QVariant> );
|
||||||
|
options->insert( QStringLiteral( "driverName" ), QStringLiteral( "GPKG" ) );
|
||||||
|
options->insert( QStringLiteral( "update" ), true );
|
||||||
|
options->insert( QStringLiteral( "overwrite" ), true );
|
||||||
|
options->insert( QStringLiteral( "layerName" ), u.name );
|
||||||
|
|
||||||
|
std::unique_ptr< QgsVectorLayerExporterTask > exportTask( new QgsVectorLayerExporterTask( srcLayer, uri, QStringLiteral( "ogr" ), srcLayer->crs(), options.get(), owner ) );
|
||||||
|
|
||||||
|
// when export is successful:
|
||||||
|
connect( exportTask.get(), &QgsVectorLayerExporterTask::exportComplete, this, [ = ]()
|
||||||
|
{
|
||||||
|
// this is gross - TODO - find a way to get access to messageBar from data items
|
||||||
|
QMessageBox::information( nullptr, tr( "Import to GeoPackage database" ), tr( "Import was successful." ) );
|
||||||
|
refreshConnections();
|
||||||
|
} );
|
||||||
|
|
||||||
|
// when an error occurs:
|
||||||
|
connect( exportTask.get(), &QgsVectorLayerExporterTask::errorOccurred, this, [ = ]( int error, const QString & errorMessage )
|
||||||
|
{
|
||||||
|
if ( error != QgsVectorLayerExporter::ErrUserCanceled )
|
||||||
|
{
|
||||||
|
QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
|
||||||
|
output->setTitle( tr( "Import to GeoPackage database" ) );
|
||||||
|
output->setMessage( tr( "Failed to import some layers!\n\n" ) + errorMessage, QgsMessageOutput::MessageText );
|
||||||
|
output->showMessage();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
QgsApplication::taskManager()->addTask( exportTask.release() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
importResults.append( tr( "%1: Not a valid layer!" ).arg( u.name ) );
|
||||||
|
hasError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: implemnent raster import
|
||||||
|
QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
|
||||||
|
output->setTitle( tr( "Import to GeoPackage database faile" ) );
|
||||||
|
output->setMessage( tr( "Failed to import some layers!\n\n" ) + QStringLiteral( "Raster import is not yet implemented!\n" ), QgsMessageOutput::MessageText );
|
||||||
|
output->showMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( hasError )
|
||||||
|
{
|
||||||
|
QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
|
||||||
|
output->setTitle( tr( "Import to GeoPackage database" ) );
|
||||||
|
output->setMessage( tr( "Failed to import some layers!\n\n" ) + importResults.join( QStringLiteral( "\n" ) ), QgsMessageOutput::MessageText );
|
||||||
|
output->showMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QgsLayerItem::LayerType QgsGeoPackageConnectionItem::layerTypeFromDb( const QString &geometryType )
|
QgsLayerItem::LayerType QgsGeoPackageConnectionItem::layerTypeFromDb( const QString &geometryType )
|
||||||
{
|
{
|
||||||
if ( geometryType.contains( QStringLiteral( "Point" ), Qt::CaseInsensitive ) )
|
if ( geometryType.contains( QStringLiteral( "Point" ), Qt::CaseInsensitive ) )
|
||||||
@ -327,7 +441,6 @@ void QgsGeoPackageConnectionItem::addTable()
|
|||||||
QList<QAction *> QgsGeoPackageAbstractLayerItem::actions()
|
QList<QAction *> QgsGeoPackageAbstractLayerItem::actions()
|
||||||
{
|
{
|
||||||
QList<QAction *> lst;
|
QList<QAction *> lst;
|
||||||
|
|
||||||
// TODO: delete layer when the provider supports it (not currently implemented)
|
// TODO: delete layer when the provider supports it (not currently implemented)
|
||||||
return lst;
|
return lst;
|
||||||
}
|
}
|
||||||
@ -352,3 +465,55 @@ QgsGeoPackageRasterLayerItem::QgsGeoPackageRasterLayerItem( QgsDataItem *parent,
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_GUI
|
||||||
|
QList<QAction *> QgsGeoPackageVectorLayerItem::actions()
|
||||||
|
{
|
||||||
|
QList<QAction *> lst = QgsGeoPackageAbstractLayerItem::actions();
|
||||||
|
QAction *actionDeleteLayer = new QAction( tr( "Delete layer '%1'..." ).arg( mName ), this );
|
||||||
|
connect( actionDeleteLayer, &QAction::triggered, this, &QgsGeoPackageVectorLayerItem::deleteLayer );
|
||||||
|
lst.append( actionDeleteLayer );
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QgsGeoPackageVectorLayerItem::deleteLayer()
|
||||||
|
{
|
||||||
|
// Check if the layer is in the registry
|
||||||
|
const QgsMapLayer *projectLayer = nullptr;
|
||||||
|
Q_FOREACH ( const QgsMapLayer *layer, QgsProject::instance()->mapLayers() )
|
||||||
|
{
|
||||||
|
if ( layer->publicSource() == mUri )
|
||||||
|
{
|
||||||
|
projectLayer = layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( ! projectLayer )
|
||||||
|
{
|
||||||
|
if ( QMessageBox::question( nullptr, QObject::tr( "Delete Layer" ),
|
||||||
|
QObject::tr( "Are you sure you want to delete layer '%1' from GeoPackage?" ).arg( mName ),
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString errCause;
|
||||||
|
bool res = ::deleteLayer( mUri, errCause );
|
||||||
|
if ( !res )
|
||||||
|
{
|
||||||
|
QMessageBox::warning( nullptr, tr( "Delete Layer" ), errCause );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::information( nullptr, tr( "Delete Layer" ), tr( "Layer deleted successfully." ) );
|
||||||
|
if ( mParent )
|
||||||
|
mParent->refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::warning( nullptr, QObject::tr( "Delete Layer" ), QObject::tr( "The layer '%1' cannot be deleted because it is in the current project as '%2',"
|
||||||
|
" remove it from the project and retry." ).arg( mName, projectLayer->name() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -49,7 +49,11 @@ class QgsGeoPackageVectorLayerItem : public QgsGeoPackageAbstractLayerItem
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QgsGeoPackageVectorLayerItem( QgsDataItem *parent, QString name, QString path, QString uri, LayerType layerType );
|
QgsGeoPackageVectorLayerItem( QgsDataItem *parent, QString name, QString path, QString uri, LayerType layerType );
|
||||||
|
#ifdef HAVE_GUI
|
||||||
|
QList<QAction *> actions() override;
|
||||||
|
public slots:
|
||||||
|
void deleteLayer();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -67,7 +71,7 @@ class QgsGeoPackageConnectionItem : public QgsDataCollectionItem
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual bool acceptDrop() override { return true; }
|
virtual bool acceptDrop() override { return true; }
|
||||||
//virtual bool handleDrop( const QMimeData *data, Qt::DropAction action ) override;
|
virtual bool handleDrop( const QMimeData *data, Qt::DropAction action ) override;
|
||||||
|
|
||||||
//! Return the layer type from \a geometryType
|
//! Return the layer type from \a geometryType
|
||||||
static QgsLayerItem::LayerType layerTypeFromDb( const QString &geometryType );
|
static QgsLayerItem::LayerType layerTypeFromDb( const QString &geometryType );
|
||||||
|
@ -18,10 +18,12 @@
|
|||||||
#include "qgslogger.h"
|
#include "qgslogger.h"
|
||||||
#include "qgsmessagelog.h"
|
#include "qgsmessagelog.h"
|
||||||
#include "qgssettings.h"
|
#include "qgssettings.h"
|
||||||
|
#include "qgsproject.h"
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include <ogr_srs_api.h>
|
#include <ogr_srs_api.h>
|
||||||
#include <cpl_error.h>
|
#include <cpl_error.h>
|
||||||
@ -31,11 +33,14 @@
|
|||||||
QGISEXTERN QStringList fileExtensions();
|
QGISEXTERN QStringList fileExtensions();
|
||||||
QGISEXTERN QStringList wildcards();
|
QGISEXTERN QStringList wildcards();
|
||||||
|
|
||||||
|
QGISEXTERN bool deleteLayer( const QString &uri, const QString &errCause );
|
||||||
|
|
||||||
|
|
||||||
QgsOgrLayerItem::QgsOgrLayerItem( QgsDataItem *parent,
|
QgsOgrLayerItem::QgsOgrLayerItem( QgsDataItem *parent,
|
||||||
QString name, QString path, QString uri, LayerType layerType )
|
QString name, QString path, QString uri, LayerType layerType, bool isSubLayer )
|
||||||
: QgsLayerItem( parent, name, path, uri, layerType, QStringLiteral( "ogr" ) )
|
: QgsLayerItem( parent, name, path, uri, layerType, QStringLiteral( "ogr" ) )
|
||||||
{
|
{
|
||||||
|
mIsSubLayer = isSubLayer;
|
||||||
mToolTip = uri;
|
mToolTip = uri;
|
||||||
setState( Populated ); // children are not expected
|
setState( Populated ); // children are not expected
|
||||||
|
|
||||||
@ -56,6 +61,7 @@ QgsOgrLayerItem::QgsOgrLayerItem( QgsDataItem *parent,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool QgsOgrLayerItem::setCrs( const QgsCoordinateReferenceSystem &crs )
|
bool QgsOgrLayerItem::setCrs( const QgsCoordinateReferenceSystem &crs )
|
||||||
{
|
{
|
||||||
if ( !( mCapabilities & SetCrs ) )
|
if ( !( mCapabilities & SetCrs ) )
|
||||||
@ -110,9 +116,71 @@ QString QgsOgrLayerItem::layerName() const
|
|||||||
return info.completeBaseName();
|
return info.completeBaseName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_GUI
|
||||||
|
QList<QAction *> QgsOgrLayerItem::actions()
|
||||||
|
{
|
||||||
|
QList<QAction *> lst;
|
||||||
|
// Messages are different for files and tables
|
||||||
|
QString message = mIsSubLayer ? QObject::tr( "Delete layer '%1'..." ).arg( mName ) : QObject::tr( "Delete file '%1'..." ).arg( mUri );
|
||||||
|
QAction *actionDeleteLayer = new QAction( message, this );
|
||||||
|
connect( actionDeleteLayer, &QAction::triggered, this, &QgsOgrLayerItem::deleteLayer );
|
||||||
|
lst.append( actionDeleteLayer );
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsOgrLayerItem::deleteLayer()
|
||||||
|
{
|
||||||
|
// Messages are different for files and tables
|
||||||
|
QString title = mIsSubLayer ? QObject::tr( "Delete Layer" ) : QObject::tr( "Delete File" );
|
||||||
|
// Check if the layer is in the registry
|
||||||
|
const QgsMapLayer *projectLayer = nullptr;
|
||||||
|
Q_FOREACH ( const QgsMapLayer *layer, QgsProject::instance()->mapLayers() )
|
||||||
|
{
|
||||||
|
if ( layer->publicSource() == mUri )
|
||||||
|
{
|
||||||
|
projectLayer = layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( ! projectLayer )
|
||||||
|
{
|
||||||
|
QString confirmMessage;
|
||||||
|
if ( mIsSubLayer )
|
||||||
|
{
|
||||||
|
confirmMessage = QObject::tr( "Are you sure you want to delete layer '%1' from datasource?" ).arg( mName );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
confirmMessage = QObject::tr( "Are you sure you want to delete file '%1'?" ).arg( mUri );
|
||||||
|
}
|
||||||
|
if ( QMessageBox::question( nullptr, title,
|
||||||
|
confirmMessage,
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString errCause;
|
||||||
|
bool res = ::deleteLayer( mUri, errCause );
|
||||||
|
if ( !res )
|
||||||
|
{
|
||||||
|
QMessageBox::warning( nullptr, title, errCause );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::information( nullptr, title, mIsSubLayer ? tr( "Layer deleted successfully." ) : tr( "File deleted successfully." ) );
|
||||||
|
if ( mParent )
|
||||||
|
mParent->refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::warning( nullptr, title, QObject::tr( "The layer '%1' cannot be deleted because it is in the current project as '%2',"
|
||||||
|
" remove it from the project and retry." ).arg( mName, projectLayer->name() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// -------
|
// -------
|
||||||
|
|
||||||
static QgsOgrLayerItem *dataItemForLayer( QgsDataItem *parentItem, QString name, QString path, OGRDataSourceH hDataSource, int layerId )
|
static QgsOgrLayerItem *dataItemForLayer( QgsDataItem *parentItem, QString name, QString path, OGRDataSourceH hDataSource, int layerId, bool isSubLayer = false )
|
||||||
{
|
{
|
||||||
OGRLayerH hLayer = OGR_DS_GetLayer( hDataSource, layerId );
|
OGRLayerH hLayer = OGR_DS_GetLayer( hDataSource, layerId );
|
||||||
OGRFeatureDefnH hDef = OGR_L_GetLayerDefn( hLayer );
|
OGRFeatureDefnH hDef = OGR_L_GetLayerDefn( hLayer );
|
||||||
@ -166,7 +234,7 @@ static QgsOgrLayerItem *dataItemForLayer( QgsDataItem *parentItem, QString name,
|
|||||||
|
|
||||||
QgsDebugMsgLevel( "OGR layer uri : " + layerUri, 2 );
|
QgsDebugMsgLevel( "OGR layer uri : " + layerUri, 2 );
|
||||||
|
|
||||||
return new QgsOgrLayerItem( parentItem, name, path, layerUri, layerType );
|
return new QgsOgrLayerItem( parentItem, name, path, layerUri, layerType, isSubLayer );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
@ -189,7 +257,7 @@ QVector<QgsDataItem *> QgsOgrDataCollectionItem::createChildren()
|
|||||||
children.reserve( numLayers );
|
children.reserve( numLayers );
|
||||||
for ( int i = 0; i < numLayers; ++i )
|
for ( int i = 0; i < numLayers; ++i )
|
||||||
{
|
{
|
||||||
QgsOgrLayerItem *item = dataItemForLayer( this, QString(), mPath, hDataSource, i );
|
QgsOgrLayerItem *item = dataItemForLayer( this, QString(), mPath, hDataSource, i, true );
|
||||||
children.append( item );
|
children.append( item );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,11 +24,19 @@ class QgsOgrLayerItem : public QgsLayerItem
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QgsOgrLayerItem( QgsDataItem *parent, QString name, QString path, QString uri, LayerType layerType );
|
QgsOgrLayerItem( QgsDataItem *parent, QString name, QString path, QString uri, LayerType layerType, bool isSubLayer = false );
|
||||||
|
|
||||||
bool setCrs( const QgsCoordinateReferenceSystem &crs ) override;
|
bool setCrs( const QgsCoordinateReferenceSystem &crs ) override;
|
||||||
|
|
||||||
QString layerName() const override;
|
QString layerName() const override;
|
||||||
|
|
||||||
|
#ifdef HAVE_GUI
|
||||||
|
QList<QAction *> actions() override;
|
||||||
|
public slots:
|
||||||
|
void deleteLayer();
|
||||||
|
#endif
|
||||||
|
private:
|
||||||
|
bool mIsSubLayer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -4297,3 +4297,76 @@ QGISEXTERN void cleanupProvider()
|
|||||||
// NOTE: QgsApplication takes care of
|
// NOTE: QgsApplication takes care of
|
||||||
// calling OGRCleanupAll();
|
// calling OGRCleanupAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QGISEXTERN bool deleteLayer( const QString &uri, QString &errCause )
|
||||||
|
{
|
||||||
|
bool isSubLayer;
|
||||||
|
int layerIndex;
|
||||||
|
QString layerName;
|
||||||
|
QString subsetString;
|
||||||
|
OGRwkbGeometryType ogrGeometryType;
|
||||||
|
QString filePath = AnalyzeURI( uri,
|
||||||
|
isSubLayer,
|
||||||
|
layerIndex,
|
||||||
|
layerName,
|
||||||
|
subsetString,
|
||||||
|
ogrGeometryType );
|
||||||
|
|
||||||
|
OGRDataSourceH hDS = GDALOpenEx( filePath.toLocal8Bit().data(), GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_UPDATE, NULL, NULL, NULL );
|
||||||
|
if ( hDS && ( ! layerName.isEmpty() || layerIndex != -1 ) )
|
||||||
|
{
|
||||||
|
if ( layerIndex == -1 )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < GDALDatasetGetLayerCount( hDS ); i++ )
|
||||||
|
{
|
||||||
|
OGRLayerH hL = GDALDatasetGetLayer( hDS, i );
|
||||||
|
if ( layerName == QString( OGR_L_GetName( hL ) ) )
|
||||||
|
{
|
||||||
|
layerIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OGRErr error = GDALDatasetDeleteLayer( hDS, layerIndex );
|
||||||
|
switch ( error )
|
||||||
|
{
|
||||||
|
case OGRERR_NOT_ENOUGH_DATA:
|
||||||
|
errCause = QObject::tr( "Not enough data to deserialize" );
|
||||||
|
break;
|
||||||
|
case OGRERR_NOT_ENOUGH_MEMORY:
|
||||||
|
errCause = QObject::tr( "Not enough memory" );
|
||||||
|
break;
|
||||||
|
case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
|
||||||
|
errCause = QObject::tr( "Unsupported geometry type" );
|
||||||
|
break;
|
||||||
|
case OGRERR_UNSUPPORTED_OPERATION:
|
||||||
|
errCause = QObject::tr( "Unsupported operation" );
|
||||||
|
break;
|
||||||
|
case OGRERR_CORRUPT_DATA:
|
||||||
|
errCause = QObject::tr( "Corrupt data" );
|
||||||
|
break;
|
||||||
|
case OGRERR_FAILURE:
|
||||||
|
errCause = QObject::tr( "Failure" );
|
||||||
|
break;
|
||||||
|
case OGRERR_UNSUPPORTED_SRS:
|
||||||
|
errCause = QObject::tr( "Unsupported SRS" );
|
||||||
|
break;
|
||||||
|
case OGRERR_INVALID_HANDLE:
|
||||||
|
errCause = QObject::tr( "Invalid handle" );
|
||||||
|
break;
|
||||||
|
case OGRERR_NON_EXISTING_FEATURE:
|
||||||
|
errCause = QObject::tr( "Non existing feature" );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case OGRERR_NONE:
|
||||||
|
errCause = QObject::tr( "Success" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
errCause = QObject::tr( "GDAL result code: %s" ).arg( errCause );
|
||||||
|
return error == OGRERR_NONE;
|
||||||
|
}
|
||||||
|
// This should never happen:
|
||||||
|
errCause = QObject::tr( "Layer not found: %s" ).arg( uri );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -602,8 +602,32 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_29">
|
<layout class="QGridLayout" name="gridLayout_16">
|
||||||
<item>
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="mDataSourceManagerNonModal">
|
||||||
|
<property name="text">
|
||||||
|
<string>Modeless data source manager dialog</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="mCustomGroupBoxChkBx">
|
||||||
|
<property name="text">
|
||||||
|
<string>QGIS-styled group boxes</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QCheckBox" name="cbxCheckVersion">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check QGIS version at startup</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
<widget class="QCheckBox" name="cbxHideSplash">
|
<widget class="QCheckBox" name="cbxHideSplash">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
@ -616,82 +640,14 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="2" column="0">
|
||||||
<widget class="Line" name="line_3">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>12</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cbxShowTips">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Show tips at start up</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line_2">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>12</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cbxCheckVersion">
|
|
||||||
<property name="text">
|
|
||||||
<string>Check QGIS version at startup</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_30">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="mDataSourceManagerNonModal">
|
|
||||||
<property name="text">
|
|
||||||
<string>Modeless data source manager dialog</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="mCustomGroupBoxChkBx">
|
|
||||||
<property name="text">
|
|
||||||
<string>QGIS-styled group boxes</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_31">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="mNativeColorDialogsChkBx">
|
<widget class="QCheckBox" name="mNativeColorDialogsChkBx">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use native color chooser dialogs</string>
|
<string>Use native color chooser dialogs</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="2" column="1">
|
||||||
<widget class="QCheckBox" name="mLiveColorDialogsChkBx">
|
<widget class="QCheckBox" name="mLiveColorDialogsChkBx">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use live-updating color chooser dialogs</string>
|
<string>Use live-updating color chooser dialogs</string>
|
||||||
@ -5543,12 +5499,6 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
|||||||
<tabstop>mFontFamilyComboBox</tabstop>
|
<tabstop>mFontFamilyComboBox</tabstop>
|
||||||
<tabstop>spinFontSize</tabstop>
|
<tabstop>spinFontSize</tabstop>
|
||||||
<tabstop>mMessageTimeoutSpnBx</tabstop>
|
<tabstop>mMessageTimeoutSpnBx</tabstop>
|
||||||
<tabstop>cbxHideSplash</tabstop>
|
|
||||||
<tabstop>cbxShowTips</tabstop>
|
|
||||||
<tabstop>cbxCheckVersion</tabstop>
|
|
||||||
<tabstop>mCustomGroupBoxChkBx</tabstop>
|
|
||||||
<tabstop>mNativeColorDialogsChkBx</tabstop>
|
|
||||||
<tabstop>mLiveColorDialogsChkBx</tabstop>
|
|
||||||
<tabstop>groupBox_11</tabstop>
|
<tabstop>groupBox_11</tabstop>
|
||||||
<tabstop>mProjectOnLaunchCmbBx</tabstop>
|
<tabstop>mProjectOnLaunchCmbBx</tabstop>
|
||||||
<tabstop>mProjectOnLaunchLineEdit</tabstop>
|
<tabstop>mProjectOnLaunchLineEdit</tabstop>
|
||||||
|
@ -63,7 +63,6 @@ ENDMACRO (ADD_QGIS_TEST)
|
|||||||
#############################################################
|
#############################################################
|
||||||
# Tests:
|
# Tests:
|
||||||
SET(TESTS
|
SET(TESTS
|
||||||
testqgsvectoranalyzer.cpp
|
|
||||||
testqgsgeometrysnapper.cpp
|
testqgsgeometrysnapper.cpp
|
||||||
testopenstreetmap.cpp
|
testopenstreetmap.cpp
|
||||||
testqgszonalstatistics.cpp
|
testqgszonalstatistics.cpp
|
||||||
|
@ -1,145 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
testqgsvectoranalyzer.cpp
|
|
||||||
--------------------------------------
|
|
||||||
Date : Sun Sep 16 12:22:49 AKDT 2007
|
|
||||||
Copyright : (C) 2007 by Gary E. Sherman
|
|
||||||
Email : sherman at mrcc 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 "qgstest.h"
|
|
||||||
|
|
||||||
//header for class being tested
|
|
||||||
#include <qgsgeometryanalyzer.h>
|
|
||||||
#include <qgsapplication.h>
|
|
||||||
#include <qgsproviderregistry.h>
|
|
||||||
#include "qgsvectorlayer.h"
|
|
||||||
|
|
||||||
class TestQgsVectorAnalyzer : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
TestQgsVectorAnalyzer()
|
|
||||||
: mpLineLayer( 0 )
|
|
||||||
, mpPolyLayer( 0 )
|
|
||||||
, mpPointLayer( 0 )
|
|
||||||
{}
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void initTestCase();// will be called before the first testfunction is executed.
|
|
||||||
void cleanupTestCase();// will be called after the last testfunction was executed.
|
|
||||||
void init() ;// will be called before each testfunction is executed.
|
|
||||||
void cleanup() ;// will be called after every testfunction.
|
|
||||||
//! Our tests proper begin here
|
|
||||||
void singleToMulti();
|
|
||||||
void multiToSingle();
|
|
||||||
void extractNodes();
|
|
||||||
void polygonsToLines();
|
|
||||||
void exportGeometryInfo();
|
|
||||||
void simplifyGeometry();
|
|
||||||
void polygonCentroids();
|
|
||||||
void layerExtent();
|
|
||||||
private:
|
|
||||||
QgsGeometryAnalyzer mAnalyzer;
|
|
||||||
QgsVectorLayer *mpLineLayer = nullptr;
|
|
||||||
QgsVectorLayer *mpPolyLayer = nullptr;
|
|
||||||
QgsVectorLayer *mpPointLayer = nullptr;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void TestQgsVectorAnalyzer::initTestCase()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Runs once before any tests are run
|
|
||||||
//
|
|
||||||
// init QGIS's paths - true means that all path will be inited from prefix
|
|
||||||
QgsApplication::init();
|
|
||||||
QgsApplication::initQgis();
|
|
||||||
QgsApplication::showSettings();
|
|
||||||
|
|
||||||
//create some objects that will be used in all tests...
|
|
||||||
//create a map layer that will be used in all tests...
|
|
||||||
QString myBaseFileName( TEST_DATA_DIR ); //defined in CmakeLists.txt
|
|
||||||
QString myEndName = QStringLiteral( "lines.shp" );
|
|
||||||
QString myFileName = myBaseFileName + '/' + myEndName;
|
|
||||||
qDebug() << myFileName;
|
|
||||||
QFileInfo myLineInfo( myFileName );
|
|
||||||
mpLineLayer = new QgsVectorLayer( myLineInfo.filePath(),
|
|
||||||
myLineInfo.completeBaseName(), QStringLiteral( "ogr" ) );
|
|
||||||
|
|
||||||
myEndName = QStringLiteral( "polys.shp" );
|
|
||||||
myFileName = myBaseFileName + '/' + myEndName;
|
|
||||||
QFileInfo myPolyInfo( myFileName );
|
|
||||||
mpPolyLayer = new QgsVectorLayer( myPolyInfo.filePath(),
|
|
||||||
myPolyInfo.completeBaseName(), QStringLiteral( "ogr" ) );
|
|
||||||
|
|
||||||
myEndName = QStringLiteral( "points.shp" );
|
|
||||||
myFileName = myBaseFileName + '/' + myEndName;
|
|
||||||
QFileInfo myPointInfo( myFileName );
|
|
||||||
mpPointLayer = new QgsVectorLayer( myPointInfo.filePath(),
|
|
||||||
myPointInfo.completeBaseName(), QStringLiteral( "ogr" ) );
|
|
||||||
}
|
|
||||||
void TestQgsVectorAnalyzer::cleanupTestCase()
|
|
||||||
{
|
|
||||||
delete mpLineLayer;
|
|
||||||
delete mpPolyLayer;
|
|
||||||
delete mpPointLayer;
|
|
||||||
QgsApplication::exitQgis();
|
|
||||||
}
|
|
||||||
void TestQgsVectorAnalyzer::init()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
void TestQgsVectorAnalyzer::cleanup()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
void TestQgsVectorAnalyzer::singleToMulti()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
void TestQgsVectorAnalyzer::multiToSingle()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
void TestQgsVectorAnalyzer::extractNodes()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
void TestQgsVectorAnalyzer::polygonsToLines()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
void TestQgsVectorAnalyzer::exportGeometryInfo()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestQgsVectorAnalyzer::simplifyGeometry()
|
|
||||||
{
|
|
||||||
QString myTmpDir = QDir::tempPath() + '/';
|
|
||||||
QString myFileName = myTmpDir + "simplify_layer.shp";
|
|
||||||
QVERIFY( mAnalyzer.simplify( mpLineLayer, myFileName, 1.0 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestQgsVectorAnalyzer::polygonCentroids()
|
|
||||||
{
|
|
||||||
QString myTmpDir = QDir::tempPath() + '/';
|
|
||||||
QString myFileName = myTmpDir + "centroid_layer.shp";
|
|
||||||
QVERIFY( mAnalyzer.centroids( mpPolyLayer, myFileName ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestQgsVectorAnalyzer::layerExtent()
|
|
||||||
{
|
|
||||||
QString myTmpDir = QDir::tempPath() + '/';
|
|
||||||
QString myFileName = myTmpDir + "extent_layer.shp";
|
|
||||||
QVERIFY( mAnalyzer.extent( mpPointLayer, myFileName ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
QGSTEST_MAIN( TestQgsVectorAnalyzer )
|
|
||||||
#include "testqgsvectoranalyzer.moc"
|
|
@ -2183,7 +2183,8 @@ void TestQgsProcessing::parameterLayerList()
|
|||||||
QFileInfo fi1( raster1 );
|
QFileInfo fi1( raster1 );
|
||||||
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
|
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
|
||||||
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon?crs=EPSG:3111", "V4", "memory" );
|
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon?crs=EPSG:3111", "V4", "memory" );
|
||||||
p.addMapLayers( QList<QgsMapLayer *>() << v1 << r1 );
|
QgsVectorLayer *v2 = new QgsVectorLayer( "Polygon?crs=EPSG:3111", "V5", "memory" );
|
||||||
|
p.addMapLayers( QList<QgsMapLayer *>() << v1 << v2 << r1 );
|
||||||
QgsProcessingContext context;
|
QgsProcessingContext context;
|
||||||
context.setProject( &p );
|
context.setProject( &p );
|
||||||
|
|
||||||
@ -2225,6 +2226,14 @@ void TestQgsProcessing::parameterLayerList()
|
|||||||
params.insert( "non_optional", QVariantList() << QVariant::fromValue( v1 ) << QVariant::fromValue( r1 ) );
|
params.insert( "non_optional", QVariantList() << QVariant::fromValue( v1 ) << QVariant::fromValue( r1 ) );
|
||||||
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 << r1 );
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 << r1 );
|
||||||
|
|
||||||
|
// mix of list and single layers (happens from models)
|
||||||
|
params.insert( "non_optional", QVariantList() << QVariant( QVariantList() << QVariant::fromValue( v1 ) << QVariant::fromValue( v2 ) ) << QVariant::fromValue( r1 ) );
|
||||||
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 << v2 << r1 );
|
||||||
|
|
||||||
|
// mix of two lists (happens from models)
|
||||||
|
params.insert( "non_optional", QVariantList() << QVariant( QVariantList() << QVariant::fromValue( v1 ) << QVariant::fromValue( v2 ) ) << QVariant( QVariantList() << QVariant::fromValue( r1 ) ) );
|
||||||
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 << v2 << r1 );
|
||||||
|
|
||||||
// mix of existing layers and non project layer string
|
// mix of existing layers and non project layer string
|
||||||
params.insert( "non_optional", QVariantList() << v1->id() << raster2 );
|
params.insert( "non_optional", QVariantList() << v1->id() << raster2 );
|
||||||
QList< QgsMapLayer *> layers = QgsProcessingParameters::parameterAsLayerList( def.get(), params, context );
|
QList< QgsMapLayer *> layers = QgsProcessingParameters::parameterAsLayerList( def.get(), params, context );
|
||||||
@ -2310,6 +2319,9 @@ void TestQgsProcessing::parameterLayerList()
|
|||||||
params.insert( "optional", QVariant() );
|
params.insert( "optional", QVariant() );
|
||||||
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 );
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 );
|
||||||
|
|
||||||
|
params.insert( "optional", QVariantList() << QVariant::fromValue( r1 ) );
|
||||||
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << r1 );
|
||||||
|
|
||||||
code = def->asScriptCode();
|
code = def->asScriptCode();
|
||||||
QCOMPARE( code, QStringLiteral( "##optional=optional multiple vector " ) + v1->id() );
|
QCOMPARE( code, QStringLiteral( "##optional=optional multiple vector " ) + v1->id() );
|
||||||
fromCode.reset( dynamic_cast< QgsProcessingParameterMultipleLayers * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
fromCode.reset( dynamic_cast< QgsProcessingParameterMultipleLayers * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user