Handlers for checkboxes to select various map features I am developing a plugin for QGIS (a Geographic Information Systems) software which uses Python. I have several functions where each of them is connected to a QCheckbox. So when a checkbox is checked, the associated function then does the following:


It reads the text of a QComboBox which contains a list of layers.
Identifies the layer by its name.
Sets an expression to be used.
Selects all features which satisfies the expression.


And when the checkbox is unchecked:


Deselects all features which satisfies the expression.




Is there a way to merge these functions into one or make it more consise?

Here is the code:

def score_0():
    opp_selectedLayerIndex = self.dockwidget.areaOpporunityMap_combo.currentText()
    opp_sel_layer = QgsMapLayerRegistry.instance().mapLayersByName(str(opp_selectedLayerIndex))[0]   
    # Select all features where "Score" = NULL
    expr = QgsExpression( """ "Score" IS NULL """ )
    it = opp_sel_layer.getFeatures( QgsFeatureRequest( expr ) )
    ids = [i.id() for i in it]
    area = 0
    if self.dockwidget.score0_checkbox.isChecked():
        opp_sel_layer.select( ids )            
    else:  
        opp_sel_layer.deselect( ids)            

def score_1():
    opp_selectedLayerIndex = self.dockwidget.areaOpporunityMap_combo.currentText()
    opp_sel_layer = QgsMapLayerRegistry.instance().mapLayersByName(str(opp_selectedLayerIndex))[0]   
    # Select all features where "Score" = 1
    expr = QgsExpression( """ "Score" = 1 OR "Category" = 'Possible' OR "Category" = 'Favourable'  """ )
    it = opp_sel_layer.getFeatures( QgsFeatureRequest( expr ) )
    ids = [i.id() for i in it]
    area = 0
    if self.dockwidget.score1_checkbox.isChecked():
        opp_sel_layer.select( ids )             
    else:    
        opp_sel_layer.deselect( ids)            

def score_2():
    opp_selectedLayerIndex = self.dockwidget.areaOpporunityMap_combo.currentText()
    opp_sel_layer = QgsMapLayerRegistry.instance().mapLayersByName(str(opp_selectedLayerIndex))[0]     
    # Select all features where "Score" = 2
    expr = QgsExpression( """ "Score" = 2 OR "Category" = 'Intermediate' OR "Category" = 'Likely' """ )
    it = opp_sel_layer.getFeatures( QgsFeatureRequest( expr ) )
    ids = [i.id() for i in it]
    area = 0
    if self.dockwidget.score2_checkbox.isChecked():
        opp_sel_layer.select( ids )              
    else:   
        opp_sel_layer.deselect( ids)            

def score_3():
    opp_selectedLayerIndex = self.dockwidget.areaOpporunityMap_combo.currentText()
    opp_sel_layer = QgsMapLayerRegistry.instance().mapLayersByName(str(opp_selectedLayerIndex))[0]  
    # Select all features where "Score" = 3  
    expr = QgsExpression( """ "Score" = 3 OR "Category" = 'Sensitive' OR "Category" = 'Unlikely' """ )
    it = opp_sel_layer.getFeatures( QgsFeatureRequest( expr ) )
    ids = [i.id() for i in it]
    area = 0
    if self.dockwidget.score3_checkbox.isChecked():
        opp_sel_layer.select( ids )            
    else:   
        opp_sel_layer.deselect( ids)            

def score_4():
    opp_selectedLayerIndex = self.dockwidget.areaOpporunityMap_combo.currentText()
    opp_sel_layer = QgsMapLayerRegistry.instance().mapLayersByName(str(opp_selectedLayerIndex))[0]    
    # Select all features where "Score" = 4
    expr = QgsExpression( """ "Score" = 4 OR "Category" = 'Showstopper' """ )
    it = opp_sel_layer.getFeatures( QgsFeatureRequest( expr ) )
    ids = [i.id() for i in it]
    area = 0
    if self.dockwidget.score4_checkbox.isChecked():
        opp_sel_layer.select( ids )           
    else:   
        opp_sel_layer.deselect( ids)


# Connect checkboxes with their associated functions
self.dockwidget.score0_checkbox.stateChanged.connect(score_0)
self.dockwidget.score1_checkbox.stateChanged.connect(score_1)
self.dockwidget.score2_checkbox.stateChanged.connect(score_2)
self.dockwidget.score3_checkbox.stateChanged.connect(score_3)
self.dockwidget.score4_checkbox.stateChanged.connect(score_4)
you only have a difference in two places: query and attribute of dockwidget you are going to check against. so you can pass them as parameters to your score function.

def score(self, query, check_attr):    
    opp_selectedLayerIndex = self.dockwidget.areaOpporunityMap_combo.currentText()
    opp_sel_layer = QgsMapLayerRegistry.instance().mapLayersByName(str(opp_selectedLayerIndex))[0]   
    # Select all features where "Score" = NULL
    expr = QgsExpression(query)
    it = opp_sel_layer.getFeatures(QgsFeatureRequest(expr))
    ids = [i.id() for i in it]

    checkbox = self.dockwidget.getattr(check_attr)

    if checkbox.isChecked():
        opp_sel_layer.select(ids)            
    else:  
        opp_sel_layer.deselect(ids)