deinonychusaur
deinonychusaur

Reputation: 7304

Manually toggling of widgets ability to emit signals in pygtk

I'm probably missing something basic in my pygtk programming, but I want to connect a signal to e.g. an gtk.Entry and then make it only emit the connected signal when I allow it to do so.

That is, I want to add something to toggle_signalling in this minimal code (only for interactive use) so that Hello is only printed when signalling is "allowed":

import gtk

signal_states = ['On', 'Off']
signal_state = True

def reporter_function(*args,**kwargs):
    print "Hello"

def toggle_signaling(widget, **kwargs):
    global signal_state
    signal_state = not signal_state
    widget.set_label(signal_states[signal_state])
    print ['Emit allowed', 'Emit not allowed'][not signal_state]

w = gtk.Window()
e = gtk.Entry()
b = gtk.Button(label=signal_states[signal_state])

hbox = gtk.HBox()
hbox.pack_start(e)
hbox.pack_end(b)

e.connect("changed", reporter_function)
b.connect("clicked", toggle_signaling)
w.add(hbox)
w.show_all()

I've previously let there be a boolean flag for such send signal state e.g. self._updating in my custom widget-classes and let the callback-functions check this state before doing anything. That is not what I want.

I want a gtk-native way of letting the widget know that it shouldn't send the signal (when I've clicked the button in the example). I'm pretty sure I've stumbled upon a way of doing this once but I'm lost at finding it again.

Also, to be absolutely clear, the widget must still be allowed to be enabled.

Upvotes: 3

Views: 1108

Answers (1)

f4lco
f4lco

Reputation: 3814

I don't think there's a way around the boolean flag. Wether a widget is allowed to emit a signal or not is additional application logic and therefore has to be kept somewhere.
Based on your previous research on the topic and the quite acurately described functionality you're most probably looking for chapter 20.1.2 of the PyGTK tutorial.
I put comprehensive example code together. The only thing to keep around except the boolean indicator is the handler_id of the connected signal. As you might notice, it's programmed in Gtk3, but the important methods handler_block and handler_unblock function the exact same way in both Gtk 2 and 3.

from gi.repository import Gtk

class TestWindow(Gtk.Window):

    def __init__(self, *args, **kwargs):
        Gtk.Window.__init__(self, *args, **kwargs)
        self.connect("destroy", Gtk.main_quit)
        self.is_allowed = True
        self.create_widgets()
        self.show_all()

    def create_widgets(self):
        box = Gtk.HBox()
        self.entry = Gtk.Entry()
        self.handler_id = self.entry.connect("changed", self.on_entry_changed)
        box.pack_start(self.entry, True, True, 0)
        button = Gtk.Button("Toggle")
        button.connect("clicked", self.on_button_clicked)
        box.pack_start(button, True, True, 0)
        self.add(box)

    def on_entry_changed(self, *args):
        print "entry has changed"

    def on_button_clicked(self, *args):
        if self.is_allowed:
            self.entry.handler_block(self.handler_id)
            print "now blocking"
        else:
            self.entry.handler_unblock(self.handler_id)
            print "now unblocking"
        self.is_allowed = not self.is_allowed

TestWindow()
Gtk.main()

Upvotes: 4

Related Questions