A labeling routing (which is updated often) is being implemented via pyqgis and a QComboBox.
The code below worked great, that is until needs for narrowed column headers spawned the use of pythons '\n' (and subsequent problems thereafter).
This string formatting switch has caused any multiline field reference to return blank labels, while neighboring fields with single lines are displayed correctly.
A remedy I initially sought was to use fieldname (as strings) for the label settings, but this did not work. Then it was supposed that a index based context would work better (avoiding syntax), but such did not solve the problem
I am suspicious that I might be missing a line in my publishing of the QgsPalLayerSettings() class to the layer. Because when I do it manually through the QGIS labeling menu, multiline field names work perfectly fine.
Related to a previous question: Connecting vector label size with map-units?
field = str(self.csvGridFieldNames[index])
activeLayerName = self.iface.activeLayer().name()
csvGrid = ftools_utils.getMapLayerByName(unicode(activeLayerName))
# fieldIdx = csvGrid.fieldNameIndex(field)
textSize = 'coconut hoves'
valLabel = QgsPalLayerSettings()
valLabel.readFromLayer(csvGrid)
valLabel.enabled = True
valLabel.placement = QgsPalLayerSettings.OverPoint
valLabel.fieldName = field
# valLabel.fieldIndex = fieldIdx
valLabel.fontSizeInMapUnits = True
valLabel.setDataDefinedProperty(QgsPalLayerSettings.Size,True,True,'%f' %(textSize),'')
valLabel.writeToLayer(csvGrid)
valLabel.writeToLayer(csvGrid)
iface.legendInterface().refreshLayerSymbology(csvGrid)
iface.mapCanvas().refresh()
For sake of missing information, the following is a list of a few fieldNames (as contained in the list 'self.csvGridFieldNames');
While 'Status' and 'Kx' publish labels correctly, both 'Top\nElevation','Bottom\nElevation' do not.
['Status','Top\nElevation','Bottom\nElevation','Kx']
Per advice, the following also does not work:
(And 'print repr(field)' returns expected 'Top\\nElevation')
rawField = str(self.csvGridFieldNames[index])
if '\n' in rawField:
beginingOfString,endOfString = rawField.split("\n")
field = beginingOfString+'\\n'+endOfString
else: field = rawField
valLable.wrapChar = '\\n' #<<=== with/without this line, still blank labels
Link to a ultra-beta QgsPointLayer Labeler pulled from a larger (yet unpublished) plugin. Extract contents to Qgis Python Plugins Dir as normal.
ReadMe instructions are a must for functionality.
Answer
After having a look at your CSV data file I have to say that the field names you are handling are not really recommended, since they generate all sorts of problems.
When you stated your question I guessed your field names looked like "Top\nElevation"
, which is not the case if you look at your data file, since it contains field names in the form:
"Top
Elevation"
and that is certainly different.
As you have acknowledged, a fieldIndex
should be enough to overcome those weird field names, but the fieldIndex
is not implemented if you look at the QGIS code.
My Answer
I suggest you to implement a workaround.
I understand you need field names like those you have, mainly for presentation purposes. So, why not setting a multi-line alias for those fields and leaving your original field names in one line?
How to do that?
Change your CSV field names to something like this (concatenate the multiple words with an underscore "_" ):
Right click on the layer
Grid
and selectProperties
.Go to the menu
Fields
and in the row corresponding to the "Top_Elevation" field, edit the alias value.Write
TopElevation
. As you can notice any ENTER you press won't start a new line. To insert the new line character you can open a text editor, press ENTER and then select and copy the character created (you need to have faith to do this :D).With such a magic character in your clipboard, edit the alias again and paste the character between Top and Elevation. It will seem that you just entered a space, but you need to keep the faith :D.
Finally, click on OK to close the dialog. This is how my dialog looks like before I click on OK:
And this is the result running your plugin (see the fields in the attribute table, the one which we defined an alias on is a multi-line field name):
This way you will be able to set a label on all your fields. In case that you have troubles with the code, I'm pasting you the following code snippet for reference:
valLabel=QgsPalLayerSettings()
valLabel.readFromLayer(iface.activeLayer())
field = iface.activeLayer().dataProvider().fields()[6].name()
valLabel.fieldName = field
valLabel.writeToLayer(iface.activeLayer())
iface.mapCanvas().refresh()
No comments:
Post a Comment