diff --git a/dynamic_layers/core/layer_datasource_modifier.py b/dynamic_layers/core/layer_datasource_modifier.py index d0934b2..ae7d977 100644 --- a/dynamic_layers/core/layer_datasource_modifier.py +++ b/dynamic_layers/core/layer_datasource_modifier.py @@ -11,10 +11,8 @@ QgsProcessingException, QgsProcessingFeedback, QgsProject, - QgsReadWriteContext, QgsVectorLayer, ) -from qgis.PyQt.QtXml import QDomDocument from dynamic_layers.definitions import CustomProperty from dynamic_layers.tools import log_message, string_substitution, tr @@ -76,28 +74,20 @@ def set_data_source(self, new_source_uri: str): """ Method to apply a new datasource to a vector Layer """ - # TODO :: Change to QgsMapLayer::setDataSource - context = QgsReadWriteContext() - new_ds, new_uri = self.split_source(new_source_uri) - new_datasource_type = new_ds or self.layer.dataProvider().name() - - # read layer definition - xml_document = QDomDocument("style") - # XMLMapLayers = QDomElement() - xml_map_layers = xml_document.createElement("maplayers") - # XMLMapLayer = QDomElement() - xml_map_layer = xml_document.createElement("maplayer") - self.layer.writeLayerXml(xml_map_layer, xml_document, context) - - # apply layer definition - xml_map_layer.firstChildElement("datasource").firstChild().setNodeValue(new_uri) - xml_map_layer.firstChildElement("provider").firstChild().setNodeValue(new_datasource_type) - xml_map_layers.appendChild(xml_map_layer) - xml_document.appendChild(xml_map_layers) - self.layer.readLayerXml(xml_map_layer, context) + self.layer.setDataSource(new_source_uri, self.layer.name(), self.layer.dataProvider().name()) + + if not self.layer.isValid(): + log_message( + tr( + "Error, layer '{name}' is not valid, error : {error}" + ).format(self.layer.name(), self.layer.error()), + Qgis.Critical, + self.feedback, + ) + return # Update layer extent - self.layer.updateExtents() + self.layer.updateExtents(True) # Update graduated symbol renderer if self.layer.renderer() and self.layer.renderer().type() == 'graduatedSymbol': @@ -107,6 +97,7 @@ def set_data_source(self, new_source_uri: str): # Reload layer self.layer.reload() + # self.layer.triggerRepaint() @staticmethod def split_source(source: str) -> typing.Tuple[str, str]: @@ -192,23 +183,25 @@ def set_dynamic_layer_properties(self, search_and_replace_dictionary: dict = Non ) self.layer.setAbstract(abstract) - # Set fields aliases - if self.layer.type() == QgsMapLayer.VectorLayer: - for fid, field in enumerate(self.layer.fields()): - alias = self.layer.attributeAlias(fid) - if not alias: - continue - - log_message( - tr("Compute new value for layer {} field alias {}").format(self.layer.name(), alias), - Qgis.Info, - self.feedback, - ) - new_alias = string_substitution( - input_string=alias, - variables=search_and_replace_dictionary, - project=self.project, - layer=self.layer, - feature=self.feature, - ) - self.layer.setFieldAlias(fid, new_alias) + return + + # # Set fields aliases + # if self.layer.type() == QgsMapLayer.VectorLayer: + # for fid, field in enumerate(self.layer.fields()): + # alias = self.layer.attributeAlias(fid) + # if not alias: + # continue + # + # log_message( + # tr("Compute new value for layer {} field alias {}").format(self.layer.name(), alias), + # Qgis.Info, + # self.feedback, + # ) + # new_alias = string_substitution( + # input_string=alias, + # variables=search_and_replace_dictionary, + # project=self.project, + # layer=self.layer, + # feature=self.feature, + # ) + # self.layer.setFieldAlias(fid, new_alias) diff --git a/dynamic_layers/tools.py b/dynamic_layers/tools.py index 090a6e9..675a263 100644 --- a/dynamic_layers/tools.py +++ b/dynamic_layers/tools.py @@ -35,6 +35,11 @@ def string_substitution( feedback: QgsProcessingFeedback = None, ) -> str: """ String substitution. """ + if not input_string: + msg = tr("No expression to evaluate, returning empty string") + log_message(msg, Qgis.Info, feedback) + return "" + msg = tr( "Evaluation of the expression '{expression}' \n" "with variables :\n").format(expression=input_string) @@ -73,7 +78,9 @@ def string_substitution( expression = QgsExpression(input_string) if expression.hasEvalError() or expression.hasParserError(): - raise QgsProcessingException(tr("Invalid QGIS expression : {}").format(input_string)) + msg = tr("Invalid QGIS expression : {}").format(input_string) + log_message(msg, Qgis.Critical, feedback) + raise QgsProcessingException(msg) output = expression.evaluate(context) msg = tr("Output is {}").format(output) @@ -84,9 +91,10 @@ def string_substitution( def log_message(msg: str, level: Qgis.MessageLevel = Qgis.Info, feedback: QgsProcessingFeedback = None): """ Log a message, either in the log panel, or in the Processing UI panel. """ + # noinspection PyTypeChecker + QgsMessageLog.logMessage(msg, PLUGIN_MESSAGE, level) + if not feedback: - # noinspection PyTypeChecker - QgsMessageLog.logMessage(msg, PLUGIN_MESSAGE, level) return if level == Qgis.Warning: @@ -101,6 +109,16 @@ def log_message(msg: str, level: Qgis.MessageLevel = Qgis.Info, feedback: QgsPro feedback.pushDebugInfo(msg) +def format_expression(input_text: str, is_expression: bool = True) -> str: + """ Format the text if it's an expression. """ + if not is_expression: + return input_text + + # Escaping ' to \' + input_text = input_text.replace("'", "\\'") + input_text = f"'{input_text}'" + return input_text + def plugin_path(*args) -> Path: """Return the path to the plugin root folder."""