<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from rtf -->
<style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<font face="Calibri" size="2"><span style="font-size:11pt;">
<div>Thanks!</div>
<div> </div>
<div>Not sure if I do this the best way (I'm not a programmer nor a pyQGIS-expert)...</div>
<div>I ended up with adding two procedures and changing the code-line for setting the mask (****) accordingly:</div>
<div> </div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">def get_symbollayer(layer, ruleId, symbollayer_ids):</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    """</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    Returns the symbol layer according to given layer, ruleId (None if no rule) and the path</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    to symbol layer id (for instance [0, 1])</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    """</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    renderer = layer.renderer()</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    symbol = None</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    if renderer.type() == "categorizedSymbol":</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">        i = renderer.categoryIndexForValue(ruleId)</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">        cat = renderer.categories()[i]</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">        symbol = cat.symbol()</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    elif renderer.type() == "singleSymbol":</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">        symbol = renderer.symbol()</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;"> </span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    symbollayer = symbol.symbolLayer(symbollayer_ids[0])</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    for i in range(1, len(symbollayer_ids)):</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">        symbol = symbollayer.subSymbol()</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">        symbollayer = symbol.symbolLayer(symbollayer_ids[i])</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;"> </span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">    return symbollayer</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;"> </span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">def get_symbollayer_ref(layer, ruleId, symbollayer_ids):</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">       """</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">       Returns the symbol layer according to given layer, ruleId (None if no rule) and the path</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">       to symbol layer id (for instance [0, 1])</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">       """</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">       symbollayer = get_symbollayer(layer, ruleId, symbollayer_ids)</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">       return QgsSymbolLayerReference(layer.id(), symbollayer.id())</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">...</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">fileName = "./gpkg/karplantehoyder.gpkg"</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">layer = QgsVectorLayer(fileName, "hoyder", "ogr")</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">layer.loadNamedStyle('./qml/n5hoyder.qml')      # Load qml</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">QgsProject.instance().addMapLayer(layer, False) # Add layer False to be able </span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">root.insertLayer(4,layer)                       # to specify a custom position</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">label_settings = layer.labeling().settings()    # Get current settings of the layer</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">text_format = label_settings.format()           # Get text format of the settings</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">text_format.mask().setMaskedSymbolLayers([get_symbollayer_ref(layer,"",[0])])  # set masked symbol layers ****</span></font></div>
<div><font face="Courier New" size="2"><span style="font-size:10pt;">...</span></font></div>
<div> </div>
<div>It woks, but is this the most convenient way to do it?</div>
<div> </div>
<div>It seems to me like label masking information is <i>not</i> stored in the qml-file?</div>
<div>Is there a good reason for that?</div>
<div> </div>
<div>Kind regards</div>
<div>Anne</div>
<div> </div>
<div>-----Opprinnelig melding-----<br>

Fra: Julien Cabieces <julien.cabieces@oslandia.com> <br>

Sendt: onsdag 26. april 2023 18:02<br>

Til: Anne B. Nilsen <anne.b.nilsen@nibio.no><br>

Kopi: qgis-user@lists.osgeo.org<br>

Emne: Re: [Qgis-user] PyQGIS to set masked symbol layer and mask source in ver. 3.30</div>
<div> </div>
<div> </div>
<div>Hi,</div>
<div> </div>
<div>I changed the way we referenced symbol layer to make it more simple and robust. Now, symbol layer have a generated unique id so it's easier to reference each of them (instead of a path of indices in the symbol layers tree before).</div>
<div> </div>
<div>I see 2 solutions here:</div>
<div> </div>
<div>1. You keep your old references and call</div>
<div>QgsProjectFileTransform.fixOldSymbolLayerReferences() on your layers</div>
<div> </div>
<div>2. You change the way you create the references. here[0] is an example on how you can create QgsSymbolLayerReference. </div>
<div> </div>
<div>I would favor solution 2 because you wouldn't rely on deprecated method and so you would be more future proof for when we eventually drop these methods.</div>
<div> </div>
<div>Regards,</div>
<div>Julien</div>
<div> </div>
<div>[0] <a href="https://github.com/qgis/QGIS/pull/50786/files#diff-c7f779c945b0e9c401ddb964691ec0d6a07c6c3fcfca0e3db146f97aec2d17e2R177">https://github.com/qgis/QGIS/pull/50786/files#diff-c7f779c945b0e9c401ddb964691ec0d6a07c6c3fcfca0e3db146f97aec2d17e2R177</a></div>
<div> </div>
<div>> Thanks to the answer to this post </div>
<div>> <a href="https://gis.stackexchange.com/questions/447362/pyqgis-to-set-masked-sy">https://gis.stackexchange.com/questions/447362/pyqgis-to-set-masked-sy</a></div>
<div>> mbol-layer-and-mask-source</div>
<div>></div>
<div>> I managed to set the mask layer in QGIS version 3.28.</div>
<div>></div>
<div>>  </div>
<div>></div>
<div>> The code is not working In ver. 3.30 due to a change in the QgsSymbolLayerReference class.</div>
<div>></div>
<div>> However I’m not able to change the original code so it fits with the </div>
<div>> new specification</div>
<div>></div>
<div>>  </div>
<div>></div>
<div>> I just don’t understand how to set the input parameters to fulfil the </div>
<div>> requirements in </div>
<div>> <a href="https://qgis.org/pyqgis/3.30/core/QgsSymbolLayerReference.html#qgis.co">https://qgis.org/pyqgis/3.30/core/QgsSymbolLayerReference.html#qgis.co</a></div>
<div>> re.QgsSymbolLayerReference</div>
<div>></div>
<div>>  </div>
<div>></div>
<div>> # Set masked symbol layers :  setMaskedSymbolLayers(self, </div>
<div>> maskedLayers: Iterable[QgsSymbolLayerReference])</div>
<div>></div>
<div>>  </div>
<div>></div>
<div>> fileName = "./gpkg/karplantehoyder.gpkg"</div>
<div>></div>
<div>> layer = QgsVectorLayer(fileName, "hoyder", "ogr")</div>
<div>></div>
<div>> layer.loadNamedStyle('./qml/n5hoyder.qml')      # Load qml</div>
<div>></div>
<div>> QgsProject.instance().addMapLayer(layer, False) # Add layer False to </div>
<div>> be able</div>
<div>></div>
<div>> root.insertLayer(4,layer)                       # to specify a custom position</div>
<div>></div>
<div>> label_settings = layer.labeling().settings()    # Get current settings of the layer</div>
<div>></div>
<div>> text_format = label_settings.format()           # Get text format of the settings</div>
<div>></div>
<div>>  </div>
<div>></div>
<div>> # old code (working in 3.28)</div>
<div>></div>
<div>> # </div>
<div>> text_format.mask().setMaskedSymbolLayers([QgsSymbolLayerReference(laye</div>
<div>> r.id(), QgsSymbolLayerId("", 0))])  # set masked symbol layers *****</div>
<div>></div>
<div>>  </div>
<div>></div>
<div>> # -- New code</div>
<div>></div>
<div>> linesymbol = QgsLineSymbol()</div>
<div>></div>
<div>> lyr = linesymbol.symbolLayer(0)                 # Trying to get the id of the line layer (hoyder)</div>
<div>></div>
<div>> text_format.mask().setMaskedSymbolLayers([layer.id(), lyr.id()])  # </div>
<div>> set masked symbol layers – not working</div>
<div>></div>
<div>> # --</div>
<div>></div>
<div>>  </div>
<div>></div>
<div>> label_settings.setFormat(text_format)           # set format</div>
<div>></div>
<div>> layer.labeling().setSettings(label_settings)    # set settings</div>
<div>></div>
<div>> layer.saveStyleToDatabase(layer.name(),'style n5hoyder',True,'')  # </div>
<div>> Save style in gpkg</div>
<div>></div>
<div>>  </div>
<div>></div>
<div>> Anyone who knows how I should write the code marked with *****?</div>
<div>></div>
<div>>  </div>
<div>></div>
<div>> Kind regards</div>
<div>></div>
<div>> Anne</div>
<div>></div>
<div>> _______________________________________________</div>
<div>> QGIS-User mailing list</div>
<div>> <a href="mailto:QGIS-User@lists.osgeo.org">QGIS-User@lists.osgeo.org</a></div>
<div>> List info: <a href="https://lists.osgeo.org/mailman/listinfo/qgis-user">https://lists.osgeo.org/mailman/listinfo/qgis-user</a></div>
<div>> Unsubscribe: <a href="https://lists.osgeo.org/mailman/listinfo/qgis-user">https://lists.osgeo.org/mailman/listinfo/qgis-user</a></div>
<div> </div>
<div> </div>
<div>-- </div>
<div> </div>
<div>Julien Cabieces</div>
<div>Senior Developer at Oslandia</div>
<div><a href="mailto:julien.cabieces@oslandia.com">julien.cabieces@oslandia.com</a></div>
<div>09.72.52.52.76</div>
<div> </div>
</span></font>
</body>
</html>