def fetch_and_apply_style(layer: QgsMapLayer, url: str, style_attr: str = '') -> Optional[str]: """ Fetches a QML style from the specified URL, and applies it to a layer. @param layer: target layer to apply style to @param url: URL for QML content @param style_attr: optional str specifying name of existing field in layer to automatically update classified references to @return: Returns a str if an error occurred, or None if the fetch and apply was successful """ request = QgsBlockingNetworkRequest() if request.get(QNetworkRequest( QUrl(url))) != QgsBlockingNetworkRequest.NoError: return 'Error while fetching QML style: {}'.format( request.errorMessage()) reply = request.reply().content() tmp_file = QTemporaryFile('{}/XXXXXX.qml'.format(QDir.tempPath())) tmp_file.open() tmp_file_name = tmp_file.fileName() tmp_file.close() with open(tmp_file_name, 'wt', encoding='utf8') as f: f.write(reply.data().decode()) layer.loadNamedStyle(tmp_file_name) if style_attr: StyleUtils.update_class_attribute(layer, style_attr) layer.triggerRepaint() return None
def _set_output_layer_style(layerName: str, layer: QgsMapLayer, alg: QgsProcessingAlgorithm, details: 'QgsProcessingContext::LayerDetails', context: QgsProcessingContext, parameters) -> None: """ Set layer style Original code is from python/plugins/processing/gui/Postprocessing.py """ '''If running a model, the execution will arrive here when an algorithm that is part of that model is executed. We check if its output is a final otuput of the model, and adapt the output name accordingly''' outputName = details.outputName if parameters: expcontext = QgsExpressionContext() scope = QgsExpressionContextScope() expcontext.appendScope(scope) for out in alg.outputDefinitions(): if out.name() not in parameters: continue outValue = parameters[out.name()] if hasattr(outValue, "sink"): outValue = outValue.sink.valueAsString(expcontext)[0] else: outValue = str(outValue) if outValue == layerName: outputName = out.name() break style = None if outputName: # If a style with the same name as the outputName exists # in workdir then use it style = os.path.join(context.workdir, outputName + '.qml') if not os.path.exists(style): style = RenderingStyles.getStyle(alg.id(), outputName) LOGGER.debug("Getting style for %s: %s <%s>", alg.id(), outputName, style) # Get defaults styles if style is None: if layer.type() == QgsMapLayer.RasterLayer: style = ProcessingConfig.getSetting(ProcessingConfig.RASTER_STYLE) else: if layer.geometryType() == QgsWkbTypes.PointGeometry: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_POINT_STYLE) elif layer.geometryType() == QgsWkbTypes.LineGeometry: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_LINE_STYLE) else: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_POLYGON_STYLE) if style: LOGGER.debug("Adding style '%s' to layer %s (outputName %s)", style, details.name, outputName) layer.loadNamedStyle(style) LOGGER.debug("Layer name set to %s <details name: %s>", layer.name(), details.name)
def update_symbology(layer: QgsMapLayer, color: typing.Tuple[int, int, int] = None, size: float = None, file: str = None) -> None: assert layer, 'Layer is not defined' if file: assert isinstance(file, str) (msg, noError) = layer.loadNamedStyle(file) if not noError: raise Exception(msg) renderer = layer.renderer() symbol = None if isinstance(renderer, QgsSingleSymbolRenderer): symbol = renderer.symbol() elif isinstance(renderer, QgsGraduatedSymbolRenderer): symbol = renderer.sourceSymbol() else: raise Exception('Unknown renderer!') if color: assert isinstance( color, collections.abc.Sequence ), 'Color should be a iteratable of three numbers for Red, Green, Blue; Each of them between 0 and 255' assert len(color) in ( 3, 4 ), 'There should be three numbers passed for Red, Green, Blue; Each of them between 0 and 255' symbol.setColor(QColor.fromRgb(*color)) if size: # For lines if type(symbol) == QgsLineSymbol: symbol.setWidth(size) # For points if type(symbol) == QgsMarkerSymbol: symbol.setSize(size) layer.triggerRepaint() iface.layerTreeView().refreshLayerSymbology(layer.id())
def _load_qml_style(map_layer: qgc.QgsMapLayer, style_path: Path) -> None: msg, status = map_layer.loadNamedStyle(str(style_path)) if not status: raise RuntimeError(f"Problem loading '{style_path}': '{msg}'")