-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Masking labels doesn't work with rule based labeling #46402
Comments
@Forna73 have you "Select this mask shape as a mask source in the overlapping layer properties labelmask Mask tab (see Masks Properties)." as explained here? |
I selcted them. I have only 1 layer, so it's the layer label that should mask its line, not an element of another layer. |
I've just noticed that the check box doesn't remain selected. If I exit the layer properties panel and then I reopen it, the check boxes aren't selected. |
@Forna73 attach a sample project+data, the issue may be data/expression dependent. |
it's done all from scratch. |
@Forna73 in your screenshot you are using rule based labeling with an expression. With the most simple case ("you can simply create a line layer and a label") it works. |
Ok.... You are right... simplest way works, I continued applying my rule; but this mean I can't use rule based labelling... is that expected to be right? |
@Forna73 please attach a minimal sample project with data that shows the behavior you describe. |
Hi! |
@Forna73 still works fine here. You really should attach a sample project with data that shows the issue. |
@Forna73 nevermind, as soon as two mask sources are enabled masking stops to work. Thanks for the report. |
The problem seems to be that when there are more than 1 masking sources then the selection for the sources and "masked symbol layer" do not stick in the layer properties, it seems that on ok/apply the selections are removed. |
I do confirm! |
Any progress on this bug? I am experiencing it with v 3.28.8-Firenze. I am new to GIS and QGIS, but I can attach my minimal qgz file and layer file if you tell me what is the expected layer file format. |
The issue can be replicated with the snippet below. Up to QGIS 3.28.15, the masks works with a rule based labeling but it disappears if I open the layer properties window and click "OK". It doesn't matter if I change a setting or not, simply clicking "OK" does the job. However, clicking "Cancel" does not cause the mask to disappear. It must be noted that trying to set the same label parameters manually via the GUI does not allow to successfully apply the mask. Starting at QGIS 3.30.0, my snippet breaks because of a change to the QgsSymbolLayerReference class. I haven't been able to figure out how to reference the symbol id in the new QgsSymbolLayerReference class... # Make two simple lines
elev_fieldname = "ELEV"
layer = QgsVectorLayer(f"linestring?crs=epsg:32198&field={elev_fieldname}:integer", "contours", "memory")
for wkt, elev in [('LineString (0 400000, 100 400000)', 5), ('LineString (0 400010, 100 400010)', 10)]:
geom = QgsGeometry.fromWkt(wkt)
fet = QgsFeature(layer.fields())
fet.setGeometry(geom)
fet[elev_fieldname] = elev
layer.dataProvider().addFeature(fet)
QgsProject.instance().addMapLayer(layer)
# Labeling
# Only the label of the upper line, with an elevation of 10, should be displayed
label_settings = QgsPalLayerSettings()
label_settings.placement = QgsPalLayerSettings.Line
label_settings.placementFlags = QgsPalLayerSettings.OnLine
label_settings.fieldName = elev_fieldname
mask = QgsTextMaskSettings()
mask.setEnabled(True)
mask.setSize(2)
mask.setMaskedSymbolLayers( [QgsSymbolLayerReference(layer.id(), QgsSymbolLayerId("", 0))] ) # Breaks starting at QGIS 3.30
text_format = label_settings.format()
text_format.setMask(mask)
label_settings.setFormat(text_format)
root = QgsRuleBasedLabeling.Rule(QgsPalLayerSettings())
rule = QgsRuleBasedLabeling.Rule(label_settings)
rule.setDescription("Only 10s")
rule.setFilterExpression(f"\"{elev_fieldname}\" % 10 = 0")
rule.setActive(True)
root.appendChild(rule)
rules_settings = QgsRuleBasedLabeling(root)
layer.setLabelsEnabled(True)
layer.setLabeling(rules_settings)
layer.labeling().setSettings(label_settings)
layer.triggerRepaint() |
The problem still exists in the settings dialog in version 3.34.6 and 3.34.10. |
I'm trying to understand what exactly @troopa81 Could you help on this matter as you seems to have edited the related lines of code related to these classes? Thanks. |
Just discovering this issue
You mean like this (2 mask sources, 1 masked symbol layer) ? And it does work (in master but pretty sure it works with recent one) It would be very better if someone could share a project so I can reproduce the issue |
The unique symbol layer id. Like for instance >>> iface.activeLayer().renderer()
<qgis._core.QgsSingleSymbolRenderer object at 0x7f7b5034c3a0>
>>> iface.activeLayer().renderer().symbol().symbolLayers()
[<qgis._core.QgsSimpleLineSymbolLayer object at 0x7f7b5044a290>, <qgis._core.QgsSimpleLineSymbolLayer object at 0x7f7b50331120>]
>>> iface.activeLayer().renderer().symbol().symbolLayers()[0].id()
'{6220c894-fcba-4f9f-86cf-d8884f4c49a5}' The last one is the expected id. Before my modifications, it was the order of the symbol layer regarding its parent symbol and it was a mess (like for instance when you were changing the order). So now we have a generated unique id. |
Thanks! My snippet below now works for >= 3.30. It displays two parallel lines with a label only on the upper one with a mask applied. The mask work, but like I said in my first comment, it stops working if the layer properties window is opened and then closed by clicking "OK", even without changing any setting. Before opening the layer properties window After opening and closing the layer properties window # Make two simple lines
elev_fieldname = "ELEV"
layer = QgsVectorLayer(f"linestring?crs=epsg:32198&field={elev_fieldname}:integer", "contours", "memory")
for wkt, elev in [('LineString (0 400000, 100 400000)', 5), ('LineString (0 400010, 100 400010)', 10)]:
geom = QgsGeometry.fromWkt(wkt)
fet = QgsFeature(layer.fields())
fet.setGeometry(geom)
fet[elev_fieldname] = elev
layer.dataProvider().addFeature(fet)
QgsProject.instance().addMapLayer(layer)
# Labeling
# Only the label of the upper line, with an elevation of 10, should be displayed
label_settings = QgsPalLayerSettings()
label_settings.placement = QgsPalLayerSettings.Line
label_settings.placementFlags = QgsPalLayerSettings.OnLine
label_settings.fieldName = elev_fieldname
mask = QgsTextMaskSettings()
mask.setEnabled(True)
mask.setSize(2)
mask.setMaskedSymbolLayers([
QgsSymbolLayerReference(
layer.id(),
layer.renderer().symbol().symbolLayers()[0].id()
)
])
text_format = label_settings.format()
text_format.setMask(mask)
label_settings.setFormat(text_format)
root = QgsRuleBasedLabeling.Rule(QgsPalLayerSettings())
rule = QgsRuleBasedLabeling.Rule(label_settings)
rule.setDescription("Only 10s")
rule.setFilterExpression(f"\"{elev_fieldname}\" % 10 = 0")
rule.setActive(True)
root.appendChild(rule)
rules_settings = QgsRuleBasedLabeling(root)
layer.setLabelsEnabled(True)
layer.setLabeling(rules_settings)
layer.labeling().setSettings(label_settings)
layer.triggerRepaint() |
@jfbourdon OK, thanks! I I manage to reproduce the issue. I'll fix the issue for next bugfix round (in january 2025) except if someone is willing to fund the fix |
The issue comes from symbol layers sharing the same ids which are supposedly unique. I fixed copy/paste symbol and converting from rule to categorized to avoid having duplicate id from the UI but already broken project would remain broken. Best is to recreate each rule symbol from scratch, or create one, and copy/paste with the version integrating the fix. |
@jfbourdon True. I'm looking into it |
rule key is used by other object as reference (masking for instance) Fixes qgis#46402
@jfbourdon #60490 will fix it! |
rule key is used by other object as reference (masking for instance) Fixes #46402
rule key is used by other object as reference (masking for instance) Fixes #46402
rule key is used by other object as reference (masking for instance) Fixes #46402
What is the bug or the crash?
Simple... I've any masking for labels even enabling the mask in label and selecting the masking options in layer properties
Steps to reproduce the issue
Versions
Versione di QGIS
3.16.6-Hannover
Revisione codice QGIS
bfd36fd
Compilato con Qt
5.11.2
Esecuzione con Qt
5.11.2
Compilato con GDAL/OGR
3.1.4
Esecuzione con GDAL/OGR
3.1.4
Compilato con GEOS
3.8.1-CAPI-1.13.3
Esecuzione con GEOS
3.8.1-CAPI-1.13.3
Compilato su SQLite
3.29.0
In esecuzione su SQLite
3.29.0
Versione client PostgreSQL
11.5
Versione SpatiaLite
4.3.0
Versione QWT
6.1.3
Versione QScintilla2
2.10.8
Compilato con PROJ
6.3.2
Esecuzione con PROJ
Rel. 6.3.2, May 1st, 2020
Versione SO
Windows 10 (10.0)
Attiva python plugin
AzimuthDistanceCalculator;
batch_hillshader-master;
clipper;
coordinates_converter;
DigitizingTools;
latlontools;
map-coords-plugin;
points2one;
profiletool;
Qgis2threejs;
zoom_level;
db_manager;
MetaSearch;
processing
Supported QGIS version
New profile
Additional context
No response
The text was updated successfully, but these errors were encountered: