One method (which you are currently using) is the standard QComboBox. First we need to import some more classes so add this before importing PyQt4:
from qgis.core import QgsMapLayerRegistry, QgsField, QgsExpression
from PyQt4.QtCore import QVariant, QSettings, QTranslator, qVersion, QCoreApplication
Then in your run(self)
function, we can use the following (I've added some comments which hopefully will help you understand what's going on):
def run(self):
# here I populate a combo box in a form
layers = self.iface.legendInterface().layers()
layer_list = []
for layer in layers:
layer_list.append(layer.name())
self.dlg.Cmb_Capa.addItems(layer_list)
self.dlg.show()
result = self.dlg.exec_()
if result:
# Read current text from combo box
combo_layer = self.dlg.Cmb_Capa.currentText()
# Identify layer from table of contents by matching name with the combo box text
selected_layer = QgsMapLayerRegistry.instance().mapLayersByName(combo_layer)[0]
# Add a "real" field type with the name "Area"
selected_layer.dataProvider().addAttributes( [ QgsField("Area", QVariant.Double) ] )
# Update the attribute table
selected_layer.updateFields()
# Allow editing of the selected layer
selected_layer.startEditing()
# Find index of the newly-created "Area" field
idx = selected_layer.fieldNameIndex( "Area" )
# Use standard QgsExpression to calculate area for each feature
e = QgsExpression( """ $area """ )
e.prepare( selected_layer.pendingFields() )
for f in selected_layer.getFeatures():
f[idx] = e.evaluate(f)
selected_layer.updateFeature(f)
# Save the selected layer
selected_layer.commitChanges()
Alternatively, you could use QGIS custom widget: QgsMapLayerComboBox. This is automatically updated when any changes are made to the layer list (i.e. layers added/removed, names changed etc) without you having to refresh the plugin. To use this, you will need to import an additional class:
from qgis.gui import QgsMapLayerProxyModel
Now your run(self)
function can look like this:
def run(self):
# Here, QgsMapLayerComboBox automatically reads the relevant layers
self.dlg.Cmb_Capa.setFilters( QgsMapLayerProxyModel.PolygonLayer )
self.dlg.show()
result = self.dlg.exec_()
if result:
combo_layer = self.dlg.Cmb_Capa.currentText()
selected_layer = QgsMapLayerRegistry.instance().mapLayersByName(combo_layer)[0]
selected_layer.dataProvider().addAttributes( [ QgsField("Area", QVariant.Double) ] )
selected_layer.updateFields()
selected_layer.startEditing()
idx = selected_layer.fieldNameIndex( "Area" )
e = QgsExpression( """ $area """ )
e.prepare( selected_layer.pendingFields() )
for f in selected_layer.getFeatures():
f[idx] = e.evaluate(f)
selected_layer.updateFeature(f)
selected_layer.commitChanges()
Note: When using QGIS custom widgets, you may need to edit your "plugin_name_dialog_base.ui" file, find the QgsMapLayerComboBox class
and replace the <header>
to qgis.gui.h.
For example, it might look like this:
<customwidget>
<class>QgsMapLayerComboBox</class>
<extends>QComboBox</extends>
<header>qgsmaplayercombobox.h</header>
</customwidget>
And it needs to look like this:
<customwidget>
<class>QgsMapLayerComboBox</class>
<extends>QComboBox</extends>
<header>qgis.gui.h</header>
</customwidget>