1# -*- coding: utf-8 -*- 2 3""" 4*************************************************************************** 5 dataobject.py 6 --------------------- 7 Date : August 2012 8 Copyright : (C) 2012 by Victor Olaya 9 Email : volayaf at gmail dot com 10*************************************************************************** 11* * 12* This program is free software; you can redistribute it and/or modify * 13* it under the terms of the GNU General Public License as published by * 14* the Free Software Foundation; either version 2 of the License, or * 15* (at your option) any later version. * 16* * 17*************************************************************************** 18""" 19 20__author__ = 'Victor Olaya' 21__date__ = 'August 2012' 22__copyright__ = '(C) 2012, Victor Olaya' 23 24import os 25import re 26 27from qgis.core import (QgsDataProvider, 28 QgsRasterLayer, 29 QgsWkbTypes, 30 QgsVectorLayer, 31 QgsProject, 32 QgsSettings, 33 QgsProcessingContext, 34 QgsFeatureRequest, 35 QgsExpressionContext, 36 QgsExpressionContextUtils, 37 QgsExpressionContextScope) 38from qgis.gui import QgsSublayersDialog 39from qgis.PyQt.QtCore import QCoreApplication 40from qgis.utils import iface 41 42from processing.core.ProcessingConfig import ProcessingConfig 43 44ALL_TYPES = [-1] 45 46TYPE_VECTOR_ANY = -1 47TYPE_VECTOR_POINT = 0 48TYPE_VECTOR_LINE = 1 49TYPE_VECTOR_POLYGON = 2 50TYPE_RASTER = 3 51TYPE_FILE = 4 52TYPE_TABLE = 5 53 54 55def createContext(feedback=None): 56 """ 57 Creates a default processing context 58 59 :param feedback: Optional existing QgsProcessingFeedback object, or None to use a default feedback object 60 :type feedback: Optional[QgsProcessingFeedback] 61 62 :returns: New QgsProcessingContext object 63 :rtype: QgsProcessingContext 64 """ 65 context = QgsProcessingContext() 66 context.setProject(QgsProject.instance()) 67 context.setFeedback(feedback) 68 69 invalid_features_method = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES) 70 if invalid_features_method is None: 71 invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid 72 context.setInvalidGeometryCheck(invalid_features_method) 73 74 settings = QgsSettings() 75 context.setDefaultEncoding(settings.value("/Processing/encoding", "System")) 76 77 context.setExpressionContext(createExpressionContext()) 78 79 if iface and iface.mapCanvas() and iface.mapCanvas().mapSettings().isTemporal(): 80 context.setCurrentTimeRange(iface.mapCanvas().mapSettings().temporalRange()) 81 82 return context 83 84 85def createExpressionContext(): 86 context = QgsExpressionContext() 87 context.appendScope(QgsExpressionContextUtils.globalScope()) 88 context.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance())) 89 90 if iface and iface.mapCanvas(): 91 context.appendScope(QgsExpressionContextUtils.mapSettingsScope(iface.mapCanvas().mapSettings())) 92 93 processingScope = QgsExpressionContextScope() 94 95 if iface and iface.mapCanvas(): 96 extent = iface.mapCanvas().fullExtent() 97 processingScope.setVariable('fullextent_minx', extent.xMinimum()) 98 processingScope.setVariable('fullextent_miny', extent.yMinimum()) 99 processingScope.setVariable('fullextent_maxx', extent.xMaximum()) 100 processingScope.setVariable('fullextent_maxy', extent.yMaximum()) 101 102 context.appendScope(processingScope) 103 return context 104 105 106def load(fileName, name=None, crs=None, style=None, isRaster=False): 107 """ 108 Loads a layer/table into the current project, given its file. 109 110 .. deprecated:: 3.0 111 Do not use, will be removed in QGIS 4.0 112 """ 113 114 from warnings import warn 115 warn("processing.load is deprecated and will be removed in QGIS 4.0", DeprecationWarning) 116 117 if fileName is None: 118 return 119 120 if name is None: 121 name = os.path.split(fileName)[1] 122 123 if isRaster: 124 options = QgsRasterLayer.LayerOptions() 125 options.skipCrsValidation = True 126 qgslayer = QgsRasterLayer(fileName, name, 'gdal', options) 127 if qgslayer.isValid(): 128 if crs is not None and qgslayer.crs() is None: 129 qgslayer.setCrs(crs, False) 130 if style is None: 131 style = ProcessingConfig.getSetting(ProcessingConfig.RASTER_STYLE) 132 qgslayer.loadNamedStyle(style) 133 QgsProject.instance().addMapLayers([qgslayer]) 134 else: 135 raise RuntimeError(QCoreApplication.translate('dataobject', 136 'Could not load layer: {0}\nCheck the processing framework log to look for errors.').format( 137 fileName)) 138 else: 139 options = QgsVectorLayer.LayerOptions() 140 options.skipCrsValidation = True 141 qgslayer = QgsVectorLayer(fileName, name, 'ogr', options) 142 if qgslayer.isValid(): 143 if crs is not None and qgslayer.crs() is None: 144 qgslayer.setCrs(crs, False) 145 if style is None: 146 if qgslayer.geometryType() == QgsWkbTypes.PointGeometry: 147 style = ProcessingConfig.getSetting(ProcessingConfig.VECTOR_POINT_STYLE) 148 elif qgslayer.geometryType() == QgsWkbTypes.LineGeometry: 149 style = ProcessingConfig.getSetting(ProcessingConfig.VECTOR_LINE_STYLE) 150 else: 151 style = ProcessingConfig.getSetting(ProcessingConfig.VECTOR_POLYGON_STYLE) 152 qgslayer.loadNamedStyle(style) 153 QgsProject.instance().addMapLayers([qgslayer]) 154 155 return qgslayer 156 157 158def getRasterSublayer(path, param): 159 layer = QgsRasterLayer(path) 160 161 try: 162 # If the layer is a raster layer and has multiple sublayers, let the user chose one. 163 # Based on QgisApp::askUserForGDALSublayers 164 if layer and param.showSublayersDialog and layer.dataProvider().name() == "gdal" and len(layer.subLayers()) > 1: 165 layers = [] 166 subLayerNum = 0 167 # simplify raster sublayer name 168 for subLayer in layer.subLayers(): 169 # if netcdf/hdf use all text after filename 170 if bool(re.match('netcdf', subLayer, re.I)) or bool(re.match('hdf', subLayer, re.I)): 171 subLayer = subLayer.split(path)[1] 172 subLayer = subLayer[1:] 173 else: 174 # remove driver name and file name 175 subLayer.replace(subLayer.split(QgsDataProvider.SUBLAYER_SEPARATOR)[0], "") 176 subLayer.replace(path, "") 177 # remove any : or " left over 178 if subLayer.startswith(":"): 179 subLayer = subLayer[1:] 180 if subLayer.startswith("\""): 181 subLayer = subLayer[1:] 182 if subLayer.endswith(":"): 183 subLayer = subLayer[:-1] 184 if subLayer.endswith("\""): 185 subLayer = subLayer[:-1] 186 187 ld = QgsSublayersDialog.LayerDefinition() 188 ld.layerId = subLayerNum 189 ld.layerName = subLayer 190 layers.append(ld) 191 subLayerNum = subLayerNum + 1 192 193 # Use QgsSublayersDialog 194 # Would be good if QgsSublayersDialog had an option to allow only one sublayer to be selected 195 chooseSublayersDialog = QgsSublayersDialog(QgsSublayersDialog.Gdal, "gdal") 196 chooseSublayersDialog.populateLayerTable(layers) 197 198 if chooseSublayersDialog.exec_(): 199 return layer.subLayers()[chooseSublayersDialog.selectionIndexes()[0]] 200 else: 201 # If user pressed cancel then just return the input path 202 return path 203 else: 204 # If the sublayers selection dialog is not to be shown then just return the input path 205 return path 206 except: 207 # If the layer is not a raster layer, then just return the input path 208 return path 209