Search code examples
pythonpython-3.xgtk3pygobject

run a method when TextView is idle in python GTK3


Consider having a simple window with a Gtk.textView

#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class myWindow(Gtk.Window):
    def __init__(self):
        ...
        self.txtBuffer = Gtk.TextBuffer()
        self.txtView = Gtk.TextView(buffer = self.txtBuffer)
        ...

    def autosave(self):
        # code to save txtBuffer content to a file

I want the autosave method to run when txtView is idle (after the writing is stopped for an amount of time, say 5 seconds) but I don't know what event(s) to use.


Solution

  • Add a callback to the key-release-event which will update a boolean flag indicating that the key on the keyboard was pressed then add a timeout function at regular intervals (defined as 5 seconds) that checks the keypressed flag, if so then autosave.

    #!/usr/bin/python3
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk
    
    class myWindow(Gtk.Window):
        def __init__(self):
            ...
            self.txtBuffer = Gtk.TextBuffer()
            self.txtView = Gtk.TextView(buffer = self.txtBuffer)
            #####################################################################
            self.txtView.connect ("key-release-event", self.on_key_release_event)
            GLib.timeout_add_seconds(5, self.check_autosave_timer)
            #####################################################################
            ...
    
        def autosave(self):
            # code to save txtBuffer content to a file
    
        def check_autosave_timer(self):
            if self.keypressed:
                self.autosave(self)
                self.keypressed = False
            return True 
    
        def on_key_release_event(self, event, user_data):
            self.keypressed = True
    

    EDIT:

    Just checked that you also may want to contemplate the mouse copy-paste. Gtk.TextBuffer has the changed signal. You can use the same approach on that, eg. on_textbuffer_changed you set the flag and then on glib.timeout you would save. Maybe it's a better approach and includes keystrokes and mouse events.

    Also note that this solution will save after 5 seconds of a keystroke/textbuffer change. To do it, only after, 5 seconds of being idle, a timer must be used and every time the textbuffer changes the timer is reset so that the timeout function will only save if the timer elapses more than the defined time for idle save (the timeout_add_seconds timed callback must be set at a lower frequency than that chosen for the idle autosave timer).