Gtk UI: Move refresh progress bar into the header bar

This commit is contained in:
Thomas Perl 2021-08-28 10:35:44 +02:00
parent a73d6cbb47
commit 2db8b93c87
4 changed files with 93 additions and 81 deletions

View File

@ -175,7 +175,9 @@
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vexpand">True</property>
<property name="vexpand">True</property>
<property name="hexpand">True</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
@ -214,56 +216,6 @@
</child>
</object>
</child>
<child>
<object class="GtkGrid" id="vbox42">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="hexpand">True</property>
<child>
<object class="GtkButton" id="btnUpdateFeeds">
<property name="label" translatable="yes">Check for new episodes</property>
<property name="can_focus">True</property>
<property name="focus_on_click">True</property>
<property name="action-name">win.update</property>
<property name="hexpand">True</property>
</object>
<packing>
</packing>
</child>
<child>
<object class="GtkGrid" id="hboxUpdateFeeds">
<property name="column_spacing">6</property>
<property name="orientation">horizontal</property>
<child>
<object class="GtkProgressBar" id="pbFeedUpdate">
<property name="hexpand">True</property>
<property name="pulse_step">0.10000000149</property>
<property name="show-text">True</property>
<property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
</object>
<packing>
</packing>
</child>
<child>
<object class="GtkButton" id="btnCancelFeedUpdate">
<property name="can_focus">True</property>
<property name="focus_on_click">True</property>
<signal handler="on_btnCancelFeedUpdate_clicked" name="clicked"/>
<child>
<object class="GtkImage" id="image3209">
<property name="visible">True</property>
<property name="stock">gtk-cancel</property>
<property name="icon_size">4</property>
</object>
</child>
</object>
</child>
</object>
<packing>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="shrink">False</property>

View File

@ -43,6 +43,10 @@
<attribute name="label" translatable="yes">Check for new episodes</attribute>
<attribute name="accel">&lt;Primary&gt;r</attribute>
</item>
<item>
<attribute name="action">win.cancelFeedUpdate</attribute>
<attribute name="label" translatable="yes">Cancel check for new episodes</attribute>
</item>
<item>
<attribute name="action">win.downloadAllNew</attribute>
<attribute name="label" translatable="yes">Download new episodes</attribute>

View File

@ -145,7 +145,25 @@ class gPodderApplication(Gtk.Application):
self.want_headerbar = ('GNOME' in xdg_current_desktops) and not gpodder.ui.osx and not csd_disabled
self.header_bar_refresh_button = Gtk.Button.new_from_icon_name('view-refresh-symbolic', Gtk.IconSize.SMALL_TOOLBAR)
# TODO: In Gtk 4, Gtk.Button.set_icon_name() is a thing, so this can probably be removed once we migrate
def _set_icon_name_patch(icon_name):
self.header_bar_refresh_button.set_image(Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.SMALL_TOOLBAR))
self.header_bar_refresh_button.set_icon_name = _set_icon_name_patch
self.header_bar_refresh_button.set_action_name('win.update')
self.header_bar_refresh_ui = Gtk.Grid()
self.header_bar_menu_button = Gtk.Button.new_from_icon_name('open-menu-symbolic', Gtk.IconSize.SMALL_TOOLBAR)
self.header_bar_menu_button.set_action_name('app.menu')
self.app_menu = builder.get_object('app-menu')
self.menu_popover = Gtk.Popover.new_from_model(self.header_bar_menu_button, self.app_menu)
self.menu_popover.set_position(Gtk.PositionType.BOTTOM)
if self.want_headerbar:
# This is a dirty hack to remove the "Quit" item in the menu
it = self.app_menu.iterate_item_links(2)
@ -153,14 +171,6 @@ class gPodderApplication(Gtk.Application):
it.get_value().remove(2)
# Use GtkHeaderBar for client-side decorations on recent GNOME 3 versions
self.header_bar_menu_button = Gtk.Button.new_from_icon_name('open-menu-symbolic', Gtk.IconSize.SMALL_TOOLBAR)
self.header_bar_menu_button.set_action_name('app.menu')
self.header_bar_refresh_button = Gtk.Button.new_from_icon_name('view-refresh-symbolic', Gtk.IconSize.SMALL_TOOLBAR)
self.header_bar_refresh_button.set_action_name('win.updateChannel')
self.menu_popover = Gtk.Popover.new_from_model(self.header_bar_menu_button, self.app_menu)
self.menu_popover.set_position(Gtk.PositionType.BOTTOM)
for (accel, action) in parse_app_menu_for_accels(menu_filename):
self.add_accelerator(accel, action, None)
@ -168,7 +178,6 @@ class gPodderApplication(Gtk.Application):
# TODO: Move the menubar
self.set_menubar(self.menubar)
else:
self.menubar.insert_submenu(0, 'gPodder', self.app_menu)
self.set_menubar(self.menubar)
Gtk.Window.set_default_icon_name('gpodder')

View File

@ -98,10 +98,22 @@ class gPodder(BuilderWidget, dbus.service.Object):
self.stack_switcher = Gtk.StackSwitcher()
self.stack_switcher.set_stack(self.wNotebook)
self.pbFeedUpdate = Gtk.ProgressBar()
self.pbFeedUpdate.set_show_text(True)
self.pbFeedUpdate.set_property('ellipsize', Pango.EllipsizeMode.END)
self.pbFeedUpdate.set_property('valign', Gtk.Align.CENTER)
self.pbFeedUpdate.set_property('vexpand', True)
self.header_bar_refresh_ui_revealer = Gtk.Revealer()
self.header_bar_refresh_ui_revealer.set_transition_type(Gtk.RevealerTransitionType.CROSSFADE)
self.header_bar_refresh_ui_revealer.add(self.pbFeedUpdate)
self.application.header_bar_refresh_ui.attach(self.header_bar_refresh_ui_revealer, 0, 0, 1, 1)
if self.application.want_headerbar:
self.header_bar = Gtk.HeaderBar()
self.header_bar.pack_end(self.application.header_bar_menu_button)
self.header_bar.pack_start(self.application.header_bar_refresh_button)
self.header_bar.pack_start(self.application.header_bar_refresh_ui)
self.header_bar.set_custom_title(self.stack_switcher)
self.header_bar.set_show_close_button(True)
self.header_bar.show_all()
@ -111,10 +123,28 @@ class gPodder(BuilderWidget, dbus.service.Object):
self.main_window.set_titlebar(self.header_bar)
else:
self.vMain.pack_start(self.stack_switcher, False, True, 6)
hb = Gtk.HBox()
hb.set_border_width(6)
self.vMain.pack_start(hb, False, True, 0)
self.vMain.reorder_child(hb, 1)
self.pbFeedUpdate.set_property('vexpand', False)
self.vMain.pack_start(self.application.header_bar_refresh_ui, False, False, 0)
def _on_child_revealed(widget, prop=None):
widget.set_visible(widget.get_child_revealed())
self.header_bar_refresh_ui_revealer.connect('notify::child-revealed', _on_child_revealed)
self.application.header_bar_refresh_ui.show_all()
_on_child_revealed(self.header_bar_refresh_ui_revealer)
self.vMain.reorder_child(self.application.header_bar_refresh_ui, 2)
hb.pack_start(self.application.header_bar_refresh_button, False, False, 0)
hb.pack_start(self.stack_switcher, True, True, 6)
hb.pack_start(self.application.header_bar_menu_button, False, False, 0)
self.stack_switcher.set_property('halign', Gtk.Align.CENTER)
self.vMain.reorder_child(self.stack_switcher, 1)
self.stack_switcher.show_all()
hb.show_all()
gpodder.user_extensions.on_ui_object_available('gpodder-gtk', self)
self.toolbar.set_property('visible', self.config.show_toolbar)
@ -225,8 +255,6 @@ class gPodder(BuilderWidget, dbus.service.Object):
util.run_in_background(self.user_apps_reader.read)
# Now, update the feed cache, when everything's in place
if not self.application.want_headerbar:
self.btnUpdateFeeds.show()
self.feed_cache_update_cancelled = False
self.update_podcast_list_model()
@ -240,6 +268,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
if self.config.auto_update_feeds:
self.restart_auto_update_timer()
self._hide_refresh_ui_source_id = None
# Find expired (old) episodes and delete them
old_episodes = list(common.get_expired_episodes(self.channels, self.config))
if len(old_episodes) > 0:
@ -307,6 +337,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
action_defs = [
('update', self.on_itemUpdate_activate),
('cancelFeedUpdate', self.on_btnCancelFeedUpdate_clicked),
('downloadAllNew', self.on_itemDownloadAllNew_activate),
('removeOldEpisodes', self.on_itemRemoveOldEpisodes_activate),
('discover', self.on_itemImportChannels_activate),
@ -336,6 +367,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
self.update_action = g.lookup_action('update')
self.update_channel_action = g.lookup_action('updateChannel')
self.cancel_feed_update_action = g.lookup_action('cancelFeedUpdate')
self.edit_channel_action = g.lookup_action('editChannel')
self.play_action = g.lookup_action('play')
self.open_action = g.lookup_action('open')
@ -345,6 +377,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
self.toggle_episode_new_action = g.lookup_action('toggleEpisodeNew')
self.toggle_episode_lock_action = g.lookup_action('toggleEpisodeLock')
self.cancel_feed_update_action.set_enabled(False)
action = Gio.SimpleAction.new_stateful(
'showToolbar', None, GLib.Variant.new_boolean(self.config.show_toolbar))
action.connect('activate', self.on_itemShowToolbar_activate)
@ -2627,20 +2661,35 @@ class gPodder(BuilderWidget, dbus.service.Object):
def show_update_feeds_buttons(self):
# Make sure that the buttons for updating feeds
# appear - this should happen after a feed update
self.hboxUpdateFeeds.hide()
if not self.application.want_headerbar:
self.btnUpdateFeeds.show()
self.header_bar_refresh_ui_revealer.set_reveal_child(False)
self._make_update_button_update()
def _make_update_button_update(self):
self.cancel_feed_update_action.set_enabled(False)
self.application.header_bar_refresh_button.set_icon_name('view-refresh-symbolic')
self.application.header_bar_refresh_button.set_action_name('win.update')
self.update_action.set_enabled(True)
self.update_channel_action.set_enabled(True)
def on_btnCancelFeedUpdate_clicked(self, widget):
def _make_update_button_cancel(self):
self.update_action.set_enabled(False)
self.update_channel_action.set_enabled(False)
self.application.header_bar_refresh_button.set_icon_name('edit-undo-symbolic')
self.application.header_bar_refresh_button.set_action_name('win.cancelFeedUpdate')
self.cancel_feed_update_action.set_enabled(True)
def on_btnCancelFeedUpdate_clicked(self, *args):
if not self.feed_cache_update_cancelled:
self.pbFeedUpdate.set_text(_('Cancelling...'))
self.feed_cache_update_cancelled = True
self.btnCancelFeedUpdate.set_sensitive(False)
else:
self.show_update_feeds_buttons()
def _hide_header_bar_refresh_ui(self):
self.header_bar_refresh_ui_revealer.set_reveal_child(False)
self._hide_refresh_ui_source_id = None
return False
def update_feed_cache(self, channels=None,
show_new_episodes_dialog=True):
if self.config.check_connection and not util.connection_available():
@ -2655,15 +2704,15 @@ class gPodder(BuilderWidget, dbus.service.Object):
# Only update podcasts for which updates are enabled
channels = [c for c in self.channels if not c.pause_subscription]
self.update_action.set_enabled(False)
self.update_channel_action.set_enabled(False)
self._make_update_button_cancel()
self.feed_cache_update_cancelled = False
self.btnCancelFeedUpdate.show()
self.btnCancelFeedUpdate.set_sensitive(True)
self.btnCancelFeedUpdate.set_image(Gtk.Image.new_from_icon_name('process-stop', Gtk.IconSize.BUTTON))
self.hboxUpdateFeeds.show_all()
self.btnUpdateFeeds.hide()
if self._hide_refresh_ui_source_id is not None:
GObject.source_remove(self._hide_refresh_ui_source_id)
self._hide_refresh_ui_source_id = None
self.header_bar_refresh_ui_revealer.set_reveal_child(True)
count = len(channels)
text = N_('Updating %(count)d feed...', 'Updating %(count)d feeds...',
@ -2759,10 +2808,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
self.pbFeedUpdate.set_fraction(1.0)
self.pbFeedUpdate.set_text(_('No new episodes'))
self.feed_cache_update_cancelled = True
self.btnCancelFeedUpdate.show()
self.btnCancelFeedUpdate.set_sensitive(True)
self.update_action.set_enabled(True)
self.btnCancelFeedUpdate.set_image(Gtk.Image.new_from_icon_name('edit-clear', Gtk.IconSize.BUTTON))
self._hide_refresh_ui_source_id = GObject.timeout_add(3000, self._hide_header_bar_refresh_ui)
self._make_update_button_update()
else:
count = len(episodes)
# New episodes are available