It seems your "key" field must have type integer and not text.
I reproduced your problem with the following snippet:
uri = QgsDataSourceURI()
uri.setConnection("localhost", "5432", "mydb", "user", "pass")
query="SELECT id, CAST (id as text)|| '_' || (ST_DumpPoints(geom)).path[2] as key, (ST_DumpPoints(geom)).geom as points FROM line"
uri.setDataSource("", "(" + query + ")", "points", "", "key")
vl = iface.addVectorLayer(uri.uri(), "QueryLayer", "postgres")
Only after I changed the "key" field type to "int", I could get the layer loaded into QGIS:
uri = QgsDataSourceURI()
uri.setConnection("localhost", "5432", "mydb", "user", "pass")
query="SELECT id, CAST(CAST (id as text)|| (ST_DumpPoints(geom)).path[2] as int) as key, (ST_DumpPoints(geom)).geom as points FROM line"
uri.setDataSource("", "(" + query + ")", "points", "", "key")
vl = iface.addVectorLayer(uri.uri(), "QueryLayer", "postgres")
Note that I had to adjust your gid to id and your the_geom to geom, in order to work with my own data.
You can achieve it by running the following code snippet in the QGIS Python console:
from PyQt4.QtCore import QVariant
for layer in QgsMapLayerRegistry.instance().mapLayers().values():
prefix = layer.name().split("_")[0]
res = layer.dataProvider().addAttributes([QgsField("density", QVariant.String)])
layer.updateFields()
fieldIndex = layer.dataProvider().fieldNameIndex( "density" )
attrFeatMap = {}
attrMap = { fieldIndex : prefix }
for feature in layer.getFeatures():
attrFeatMap[ feature.id() ] = attrMap
layer.dataProvider().changeAttributeValues( attrFeatMap )
I assume the only layers you have loaded in the QGIS ToC are those you want to modify. Otherwise, you would need to validate things like the layer type (i.e., you don't want the script to run on raster layers).
The script iterates through layers loaded into QGIS, extracts the prefix from their names, creates the text field density
, builds a dictionary like this:
{ featureId : { fieldIndex : value } }
for each feature, and finally, applies the dictionary to change features' density values.
Let me know if something is not clear.
Best Answer
Processing algorithm dialogs use widget wrappers for different parameters such as
QgsProcessingMapLayerComboBox
, which is what you are referring to. I don't know of a similar generic out-of-the-box 'map layer/ file selection combination widget' which you can use in standard, non-processing Python plugins. I may be wrong here, but I think you will have to implement your own solution by writing a basic kind of widget wrapper. I present a simple example below, for vector layers, which should give you an idea of how this would work and how you could use this idea in a plugin.Demonstration screencast of resulting functionality: