mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-09 00:08:52 -04:00
242 lines
8.4 KiB
Python
242 lines
8.4 KiB
Python
"""
|
|
***************************************************************************
|
|
dataobject.py
|
|
---------------------
|
|
Date : August 2012
|
|
Copyright : (C) 2012 by Victor Olaya
|
|
Email : volayaf at gmail dot com
|
|
***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************
|
|
"""
|
|
|
|
__author__ = "Victor Olaya"
|
|
__date__ = "August 2012"
|
|
__copyright__ = "(C) 2012, Victor Olaya"
|
|
|
|
import os
|
|
import re
|
|
|
|
from qgis.core import (
|
|
QgsDataProvider,
|
|
QgsRasterLayer,
|
|
QgsWkbTypes,
|
|
QgsVectorLayer,
|
|
QgsProject,
|
|
QgsSettings,
|
|
QgsProcessingContext,
|
|
QgsProcessingUtils,
|
|
QgsFeatureRequest,
|
|
QgsExpressionContext,
|
|
QgsExpressionContextUtils,
|
|
QgsExpressionContextScope,
|
|
)
|
|
from qgis.gui import QgsSublayersDialog
|
|
from qgis.PyQt.QtCore import QCoreApplication
|
|
from qgis.utils import iface
|
|
|
|
from processing.core.ProcessingConfig import ProcessingConfig
|
|
|
|
ALL_TYPES = [-1]
|
|
|
|
TYPE_VECTOR_ANY = -1
|
|
TYPE_VECTOR_POINT = 0
|
|
TYPE_VECTOR_LINE = 1
|
|
TYPE_VECTOR_POLYGON = 2
|
|
TYPE_RASTER = 3
|
|
TYPE_FILE = 4
|
|
TYPE_TABLE = 5
|
|
|
|
|
|
# changing this signature? make sure you update the signature in
|
|
# python/processing/__init__.py too!
|
|
# Docstring for this function is in python/processing/__init__.py
|
|
def createContext(feedback=None):
|
|
context = QgsProcessingContext()
|
|
context.setProject(QgsProject.instance())
|
|
context.setFeedback(feedback)
|
|
|
|
invalid_features_method = ProcessingConfig.getSetting(
|
|
ProcessingConfig.FILTER_INVALID_GEOMETRIES
|
|
)
|
|
if invalid_features_method is None:
|
|
invalid_features_method = (
|
|
QgsFeatureRequest.InvalidGeometryCheck.GeometryAbortOnInvalid
|
|
)
|
|
else:
|
|
invalid_features_method = QgsFeatureRequest.InvalidGeometryCheck(
|
|
int(invalid_features_method)
|
|
)
|
|
context.setInvalidGeometryCheck(invalid_features_method)
|
|
|
|
settings = QgsSettings()
|
|
context.setDefaultEncoding(
|
|
QgsProcessingUtils.resolveDefaultEncoding(
|
|
settings.value("/Processing/encoding")
|
|
)
|
|
)
|
|
|
|
context.setExpressionContext(createExpressionContext())
|
|
|
|
if iface and iface.mapCanvas() and iface.mapCanvas().mapSettings().isTemporal():
|
|
context.setCurrentTimeRange(iface.mapCanvas().mapSettings().temporalRange())
|
|
|
|
return context
|
|
|
|
|
|
def createExpressionContext():
|
|
context = QgsExpressionContext()
|
|
context.appendScope(QgsExpressionContextUtils.globalScope())
|
|
context.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance()))
|
|
|
|
if iface and iface.mapCanvas():
|
|
context.appendScope(
|
|
QgsExpressionContextUtils.mapSettingsScope(iface.mapCanvas().mapSettings())
|
|
)
|
|
|
|
processingScope = QgsExpressionContextScope()
|
|
|
|
if iface and iface.mapCanvas():
|
|
extent = iface.mapCanvas().fullExtent()
|
|
processingScope.setVariable("fullextent_minx", extent.xMinimum())
|
|
processingScope.setVariable("fullextent_miny", extent.yMinimum())
|
|
processingScope.setVariable("fullextent_maxx", extent.xMaximum())
|
|
processingScope.setVariable("fullextent_maxy", extent.yMaximum())
|
|
|
|
context.appendScope(processingScope)
|
|
return context
|
|
|
|
|
|
def load(fileName, name=None, crs=None, style=None, isRaster=False):
|
|
"""
|
|
Loads a layer/table into the current project, given its file.
|
|
|
|
.. deprecated:: 3.0
|
|
Do not use, will be removed in QGIS 4.0
|
|
"""
|
|
|
|
from warnings import warn
|
|
|
|
warn(
|
|
"processing.load is deprecated and will be removed in QGIS 4.0",
|
|
DeprecationWarning,
|
|
)
|
|
|
|
if fileName is None:
|
|
return
|
|
|
|
if name is None:
|
|
name = os.path.split(fileName)[1]
|
|
|
|
if isRaster:
|
|
options = QgsRasterLayer.LayerOptions()
|
|
options.skipCrsValidation = True
|
|
qgslayer = QgsRasterLayer(fileName, name, "gdal", options)
|
|
if qgslayer.isValid():
|
|
if crs is not None and qgslayer.crs() is None:
|
|
qgslayer.setCrs(crs, False)
|
|
if style is None:
|
|
style = ProcessingConfig.getSetting(ProcessingConfig.RASTER_STYLE)
|
|
qgslayer.loadNamedStyle(style)
|
|
QgsProject.instance().addMapLayers([qgslayer])
|
|
else:
|
|
raise RuntimeError(
|
|
QCoreApplication.translate(
|
|
"dataobject",
|
|
"Could not load layer: {0}\nCheck the processing framework log to look for errors.",
|
|
).format(fileName)
|
|
)
|
|
else:
|
|
options = QgsVectorLayer.LayerOptions()
|
|
options.skipCrsValidation = True
|
|
qgslayer = QgsVectorLayer(fileName, name, "ogr", options)
|
|
if qgslayer.isValid():
|
|
if crs is not None and qgslayer.crs() is None:
|
|
qgslayer.setCrs(crs, False)
|
|
if style is None:
|
|
if qgslayer.geometryType() == QgsWkbTypes.GeometryType.PointGeometry:
|
|
style = ProcessingConfig.getSetting(
|
|
ProcessingConfig.VECTOR_POINT_STYLE
|
|
)
|
|
elif qgslayer.geometryType() == QgsWkbTypes.GeometryType.LineGeometry:
|
|
style = ProcessingConfig.getSetting(
|
|
ProcessingConfig.VECTOR_LINE_STYLE
|
|
)
|
|
else:
|
|
style = ProcessingConfig.getSetting(
|
|
ProcessingConfig.VECTOR_POLYGON_STYLE
|
|
)
|
|
qgslayer.loadNamedStyle(style)
|
|
QgsProject.instance().addMapLayers([qgslayer])
|
|
|
|
return qgslayer
|
|
|
|
|
|
def getRasterSublayer(path, param):
|
|
layer = QgsRasterLayer(path)
|
|
|
|
try:
|
|
# If the layer is a raster layer and has multiple sublayers, let the user chose one.
|
|
# Based on QgisApp::askUserForGDALSublayers
|
|
if (
|
|
layer
|
|
and param.showSublayersDialog
|
|
and layer.dataProvider().name() == "gdal"
|
|
and len(layer.subLayers()) > 1
|
|
):
|
|
layers = []
|
|
subLayerNum = 0
|
|
# simplify raster sublayer name
|
|
for subLayer in layer.subLayers():
|
|
# if netcdf/hdf use all text after filename
|
|
if bool(re.match("netcdf", subLayer, re.I)) or bool(
|
|
re.match("hdf", subLayer, re.I)
|
|
):
|
|
subLayer = subLayer.split(path)[1]
|
|
subLayer = subLayer[1:]
|
|
else:
|
|
# remove driver name and file name
|
|
subLayer.replace(
|
|
subLayer.split(QgsDataProvider.SUBLAYER_SEPARATOR)[0], ""
|
|
)
|
|
subLayer.replace(path, "")
|
|
# remove any : or " left over
|
|
if subLayer.startswith(":"):
|
|
subLayer = subLayer[1:]
|
|
if subLayer.startswith('"'):
|
|
subLayer = subLayer[1:]
|
|
if subLayer.endswith(":"):
|
|
subLayer = subLayer[:-1]
|
|
if subLayer.endswith('"'):
|
|
subLayer = subLayer[:-1]
|
|
|
|
ld = QgsSublayersDialog.LayerDefinition()
|
|
ld.layerId = subLayerNum
|
|
ld.layerName = subLayer
|
|
layers.append(ld)
|
|
subLayerNum = subLayerNum + 1
|
|
|
|
# Use QgsSublayersDialog
|
|
# Would be good if QgsSublayersDialog had an option to allow only one sublayer to be selected
|
|
chooseSublayersDialog = QgsSublayersDialog(
|
|
QgsSublayersDialog.ProviderType.Gdal, "gdal"
|
|
)
|
|
chooseSublayersDialog.populateLayerTable(layers)
|
|
|
|
if chooseSublayersDialog.exec():
|
|
return layer.subLayers()[chooseSublayersDialog.selectionIndexes()[0]]
|
|
else:
|
|
# If user pressed cancel then just return the input path
|
|
return path
|
|
else:
|
|
# If the sublayers selection dialog is not to be shown then just return the input path
|
|
return path
|
|
except:
|
|
# If the layer is not a raster layer, then just return the input path
|
|
return path
|