diff --git a/src/gpodder/gtkui/download.py b/src/gpodder/gtkui/download.py index 68964721..35ddb931 100644 --- a/src/gpodder/gtkui/download.py +++ b/src/gpodder/gtkui/download.py @@ -195,10 +195,7 @@ class DownloadStatusModel(Gtk.ListStore): # as only the main thread is allowed to manipulate the list store. def get_next(self): dqr = DequeueRequest() - # this can not be idle_add because update_downloads_list() is called from a higher - # priority timeout_add and would spin forever, never calling this. - from gi.repository import GLib - GLib.timeout_add(0, self.__get_next, dqr) + util.idle_add(self.__get_next, dqr) return dqr.dequeue() def _work_gen(self): diff --git a/src/gpodder/gtkui/interface/progress.py b/src/gpodder/gtkui/interface/progress.py index 917fcec4..5f26fd1a 100644 --- a/src/gpodder/gtkui/interface/progress.py +++ b/src/gpodder/gtkui/interface/progress.py @@ -50,6 +50,7 @@ class ProgressIndicator(object): self._initial_message = None self._initial_progress = None self._progress_set = False + # use timeout_add, not util.idle_timeout_add, so it updates before Gtk+ redraws the dialog self.source_id = GLib.timeout_add(self.DELAY, self._create_progress) self.set_max_ticks(max_ticks) @@ -111,6 +112,7 @@ class ProgressIndicator(object): self._update_gui() # previous self.source_id timeout is removed when this returns False + # use timeout_add, not util.idle_timeout_add, so it updates before Gtk+ redraws the dialog self.source_id = GLib.timeout_add(self.INTERVAL, self._update_gui) return False diff --git a/src/gpodder/gtkui/interface/searchtree.py b/src/gpodder/gtkui/interface/searchtree.py index f89bd31d..e73d10d3 100644 --- a/src/gpodder/gtkui/interface/searchtree.py +++ b/src/gpodder/gtkui/interface/searchtree.py @@ -48,6 +48,7 @@ class SearchTree: if self.search_box.get_property('visible'): if self._search_timeout is not None: GLib.source_remove(self._search_timeout) + # use timeout_add, not util.idle_timeout_add, so it updates the TreeView before background tasks self._search_timeout = GLib.timeout_add( self.config.ui.gtk.live_search_delay, self.set_search_term, editable.get_chars(0, -1)) diff --git a/src/gpodder/gtkui/main.py b/src/gpodder/gtkui/main.py index a185f05c..563f9f32 100644 --- a/src/gpodder/gtkui/main.py +++ b/src/gpodder/gtkui/main.py @@ -2431,7 +2431,7 @@ class gPodder(BuilderWidget, dbus.service.Object): if remaining_seconds > 3600: # timeout an hour early in the event daylight savings changes the clock forward remaining_seconds = remaining_seconds - 3600 - GLib.timeout_add(remaining_seconds * 1000, self.refresh_episode_dates) + util.idle_timeout_add(remaining_seconds * 1000, self.refresh_episode_dates) def update_podcast_list_model(self, urls=None, selected=False, select_url=None, sections_changed=False): @@ -3821,8 +3821,7 @@ class gPodder(BuilderWidget, dbus.service.Object): interval = 60 * 1000 * self.config.auto.update.frequency logger.debug('Setting up auto update timer with interval %d.', self.config.auto.update.frequency) - self._auto_update_timer_source_id = GLib.timeout_add( - interval, self._on_auto_update_timer) + self._auto_update_timer_source_id = util.idle_timeout_add(interval, self._on_auto_update_timer) def _on_auto_update_timer(self): if self.config.check_connection and not util.connection_available(): diff --git a/src/gpodder/util.py b/src/gpodder/util.py index 692520a9..fb8dbb26 100644 --- a/src/gpodder/util.py +++ b/src/gpodder/util.py @@ -1320,8 +1320,25 @@ def idle_add(func, *args): func(*args) +def idle_timeout_add(milliseconds, func, *args): + """Run a function in the main GUI thread at regular intervals, at idle priority + + PRIORITY_HIGH -100 + PRIORITY_DEFAULT 0 timeout_add() + PRIORITY_HIGH_IDLE 100 + resizing 110 + redraw 120 + PRIORITY_DEFAULT_IDLE 200 idle_add() + PRIORITY_LOW 300 + """ + if not gpodder.ui.gtk: + raise Exception('util.idle_timeout_add() is only supported by Gtk+') + from gi.repository import GLib + return GLib.timeout_add(milliseconds, func, *args, priority=GLib.PRIORITY_DEFAULT_IDLE) + + class IdleTimeout(object): - """Run a function in the main GUI thread at regular intervals since the last run + """Run a function in the main GUI thread at regular intervals since the last run, at idle priority A simple timeout_add() continuously calls the function if it exceeds the interval, which lags the UI and prevents idle_add() calls from happening. This class restarts @@ -1333,13 +1350,13 @@ class IdleTimeout(object): self.milliseconds = milliseconds self.func = func from gi.repository import GLib - self.id = GLib.timeout_add(milliseconds, self._callback, *args) + self.id = GLib.timeout_add(milliseconds, self._callback, *args, priority=GLib.PRIORITY_DEFAULT_IDLE) def _callback(self, *args): self.cancel() if self.func(*args): from gi.repository import GLib - self.id = GLib.timeout_add(self.milliseconds, self._callback, *args) + self.id = GLib.timeout_add(self.milliseconds, self._callback, *args, priority=GLib.PRIORITY_DEFAULT_IDLE) def cancel(self): if self.id: