[pygtk] gtkspell breaks the TextView / accessing invalidated iterators

Samuel Abels newsgroups at debain.org
Mon Jul 7 06:22:13 WST 2008


Hi,

The following code works flawlessly when the gtkspell line is commented
out, and breaks when gtkspell is enabled.

----------------------
import gtk, gtkspell, locale

class Window(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self)
        self.vbox   = gtk.VBox()
        self.hbox   = gtk.HBox()
        self.scroll = gtk.ScrolledWindow()
        self.view   = gtk.TextView()
        buffer      = self.view.get_buffer()
        self.scroll.set_policy(gtk.POLICY_AUTOMATIC,
                               gtk.POLICY_AUTOMATIC)
        self.set_size_request(600, 600)
        self.vbox.set_border_width(6)
        self.vbox.set_spacing(6)
        self.hbox.set_spacing(6)
        self.inserted = None

        # Pack widgets.
        self.scroll.add_with_viewport(self.view)
        self.add(self.vbox)
        self.vbox.pack_start(self.hbox, False)
        self.vbox.pack_start(self.scroll)
        self.show_all()

        buffer.connect('insert-text', self._on_buffer_insert_text)
        buffer.connect('changed', self._on_buffer_changed)
        #gtkspell.Spell(self.view).set_language(locale.getlocale()[0])


    def _on_buffer_insert_text(self, buffer, iter, text, length):
        print "Inserted:", repr(text)
        self.inserted = text, iter.get_offset()


    def _on_buffer_changed(self, buffer):
        if self.inserted is None:
            return
        print "Changed:", repr(self.inserted)
        inserted, pos = self.inserted
        self.inserted = None
        if inserted == '#':
            buffer.delete(buffer.get_iter_at_offset(pos),
                          buffer.get_iter_at_offset(pos + 1))
            buffer.insert(buffer.get_iter_at_offset(pos), "X")


# Create widgets.
window = Window()
window.connect('delete-event', gtk.main_quit)
gtk.main()
----------------------

With gtkspell disabled, any time the "#" key is pressed an X is written
into the buffer.
With gtkspell enabled, the following output is generated:

------------------
GtkWarning: Invalid text buffer iterator: either the iterator is
uninitialized, or the characters/pixbufs/widgets in the buffer have been
modified since the iterator was created.
You must use marks, character numbers, or line numbers to preserve a
position across buffer modifications.
You can apply tags and insert marks without invalidating your iterators,
but any mutation that affects 'indexable' buffer contents (contents that
can be referred to by character offset)
will invalidate all outstanding iterators
  gtk.main()
show_text_view.py:50: GtkWarning: _gtk_text_buffer_get_line_log_attrs:
assertion `GTK_IS_TEXT_BUFFER (buffer)' failed
  gtk.main()
show_text_view.py:50: GtkWarning: gtk_text_buffer_remove_tag: assertion
`gtk_text_iter_get_buffer (end) == buffer' failed
  gtk.main()
show_text_view.py:50: GtkWarning: gtk_text_buffer_set_mark: assertion
`gtk_text_iter_get_buffer (iter) == buffer' failed
  gtk.main()
Traceback (most recent call last):
  File "show_text_view.py", line 50, in <module>
    gtk.main()
------------------

It appears that gtkspell is trying to access an iterator that was
invalidated by manipulating the buffer in a callback. I tried to change
the buffer in different callbacks, such as insert-text, delete-range,
changed, but all of them break even when using connect_after().

Is this intended behavior, and if so, how do you manipulate the buffer
when spell-checking is enabled?

-Samuel




More information about the pygtk mailing list