Insert-text signal in Entry not being called

Hi,

I’m testing some code examples and I can’t get the insert_text signal to call the handler.
If I connect to the text property It works with no problem.

I’m using the example code here:
https://pygobject.gnome.org/tutorials/gtk4/controls/entries.html

with the following additions:

        self.entry.connect('insert_text', self.onInsertText)
    


        def onInsertText(self, text, length, position):
             print('Text inserted')

Hi,

Can you try with insert-text instead of insert_text?

According to the doc, that is the signal name. Anyway, it doesn’t work with insert-text either.

insert_text is a non-canonical name of the signal. Usually they’re internally converted to the canonical form (insert-text here), but in some cases that may not work. In doubt, always prefer the canonical form.

Huh… I just tried an I can confirm it doesn’t work :frowning_face:
Weird… especially since it used to work in gtk3.

Probably a bug, I’ll have a look.

In the meanwhile you can connect to the buffer’s inserted-text signal instead:

import sys
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class MyAppWindow(Gtk.ApplicationWindow):
    def __init__(self, **kwargs):
        super().__init__(default_width=200, default_height=200, **kwargs)
        entry = Gtk.Entry(halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER)
        entry.connect('insert-text', self.onInsertText)
        entry.get_buffer().connect('inserted-text', self.onInsertedText)
        self.set_child(entry)
        self.present()
    def onInsertText(self, entry, text, length, position):
         print('Text inserted')
    def onInsertedText(self, buffer, position, text, length):
         print('Text inserted in buffer')

class MyApp(Gtk.Application):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.connect('activate', self.on_activate)
    def on_activate(self, app):
        self.add_window(MyAppWindow())

if __name__ == '__main__':
    sys.exit(MyApp().run(sys.argv))

insert_text is a non-canonical name of the signal. Usually they’re internally converted to the canonical form (insert-text here), but in some cases that may not work. In doubt, always prefer the canonical form.

Good to know.

Should buffer.stop_emission_by_name(‘inserted-text’) stop the character from being inserted in the Entry?

No, this signal is emitted after the insertion, so too late.

If you want to control what’s inserted in the entry, better subclass the buffer and override its insert_text virtual method.

Small example that duplicates the inserted text (typing “a” will write “aa”):

import sys
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class MyEntryBuffer(Gtk.EntryBuffer):
    def do_insert_text(self, position, text, length):
        print(f"Insert {text} at {position}")
        new_text = text * 2
        # Chain-up to parent class
        return Gtk.EntryBuffer.do_insert_text(self, position, new_text, len(new_text))

class MyAppWindow(Gtk.ApplicationWindow):
    def __init__(self, **kwargs):
        super().__init__(default_width=200, default_height=200, **kwargs)
        entry = Gtk.Entry.new_with_buffer(MyEntryBuffer())
        entry.set_halign(Gtk.Align.CENTER)
        entry.set_valign(Gtk.Align.CENTER)
        self.set_child(entry)
        self.present()

class MyApp(Gtk.Application):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.connect('activate', self.on_activate)
    def on_activate(self, app):
        self.add_window(MyAppWindow())

if __name__ == '__main__':
    sys.exit(MyApp().run(sys.argv))

Would this be the right way to filter out the last character entered?

    def do_insert_text(self, position, text, length):
        if(GLib.unichar_isalpha(text[-1:]) or GLib.unichar_ispunct(text[-1:])):
            return 0
        return Gtk.EntryBuffer.do_insert_text(self, position, text, len(text))

This seems to work but I’m getting a warning if I don’t return a number, why?

Because the virtual method signature expects to return an integer, see Gtk.EntryBuffer.insert_text

With that code, if multiple characters are entered at once (like when pasting text from the clipboard), the whole text will be rejected if the last char is alpha or punct, but accepted if an alpha/punct is not in the last position…

Is it what you want?
If not, can you give some more examples of what you want to filter out?

I want to limit the input to numbers ( I’ve just seen I can use the unichar_isdigit function :sweat_smile: ) but I don’t want the Entry to accept pasted text. Is there an easy way to achive this?