1

I am developing a plugin for the GIS software, QGIS. I have a QAction icon which, when checked, connects layers in a group to a function whenever their visibility is toggled. Then when it is unchecked, it is supposed to disconnect these functions but instead I receive an error:

Traceback (most recent call last):
  File "C:/Users/Me/.qgis2/python/plugins\Example\Example.py", line 248, in run
    layers.visibilityChanged.disconnect(print_one)            
TypeError: 'function' object is not connected

This is an example code:

def run(self, checked):
    root = QgsProject.instance().layerTreeRoot()
    group = root.findGroup('Group')

    def print_one():
        print 'one'

    if checked == True:            
        for layers in group.children():
            layers.visibilityChanged.connect(print_one)            
    else:
        for layers in group.children():
            layers.visibilityChanged.disconnect(print_one)            

Why is the signal not being disconnected?

I could just use layers.visibilityChanged.disconnect() but this disconnects all signals to it so is not in my interest.

Joseph
  • 586
  • 1
  • 13
  • 32
  • Possible duplicated http://gis.stackexchange.com/questions/227719/how-to-disconnect-a-signal-when-untoggling-plugin-icon – Fran Raga Mar 09 '17 at 07:07
  • @FranciscoRaga - Although the answer in the post you linked to works, this new question is asking ***why*** can it be connected in the `if` statement but cannot be disconnected in the `else` statement. – Joseph Mar 09 '17 at 10:00

3 Answers3

2

For what I understood in PyQt manual, you should try this way :

layers.disconnect(print_one)

But I'm not sure and sadly I don't have time to try it...

Joseph
  • 586
  • 1
  • 13
  • 32
Viper
  • 405
  • 3
  • 11
  • Thanks for your answer, unfortunately this produces an error: `TypeError: arguments did not match any overloaded call: QObject.disconnect(QObject, SIGNAL(), QObject, SLOT()): argument 1 has unexpected type 'function' QObject.disconnect(QObject, SIGNAL(), callable): argument 1 has unexpected type 'function'` – Joseph Mar 08 '17 at 11:12
  • My bad, I did not understand what you wanted to do. – Viper Mar 08 '17 at 12:17
  • Don't worry about it, I only found a workaround so the question is still open :) – Joseph Mar 08 '17 at 12:18
1

From the documentation (emphasis mine):

disconnect([slot])

Disconnect one or more slots from a signal. An exception will be raised if the slot is not connected to the signal or if the signal has no connections at all.

Thus, you are receiving an exception because the signal is not connected to the slot when you are trying to disconnect it.

As a workaround:

if checked == True:            
    for layers in group.children():
        layers.visibilityChanged.connect(print_one)            
else:
    for layers in group.children():
        try:
            layers.visibilityChanged.disconnect(print_one) 
        except:
            pass
antonio
  • 18,044
  • 4
  • 45
  • 61
  • Thanks for your answer but this is exactly what I tried before. Obviously no errors appear because it is being passed but it still does not disconnect the slot for some reason... – Joseph Mar 09 '17 at 09:57
0

Guess I found an alternative method which is to include an if statement to check if the QAction icon is checked or not and place this inside the print_one() function:

def run(self):
    root = QgsProject.instance().layerTreeRoot()
    group = root.findGroup('Group')

    def print_one():
        if self.plugin_icon.isChecked():
            print 'one'
        else:
            layers.visibilityChanged.disconnect(print_one)             

    for layers in group.children():
        layers.visibilityChanged.connect(print_one) 

Still curious as to why I couldn't disconnect it using the method shown in the question but in the meantime, this works.

Joseph
  • 586
  • 1
  • 13
  • 32