Refactor shownotes
Use GtkOverlay to show link destination in both HTML and text shownotes. Remove GtkTextView from HTML shownote pane and write a HTML header from episode title and other data. The title section now scrolls with the rest of the description text. Plain text descriptions are converted to HTML by adding <br> tags on newlines.
This commit is contained in:
parent
b055f65de0
commit
ed93257fdc
|
@ -18,6 +18,7 @@
|
|||
#
|
||||
import html
|
||||
import logging
|
||||
import re
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import gpodder
|
||||
|
@ -57,14 +58,10 @@ class gPodderShownotes:
|
|||
def __init__(self, shownotes_pane):
|
||||
self.shownotes_pane = shownotes_pane
|
||||
|
||||
self.text_view = Gtk.TextView()
|
||||
self.text_view.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
|
||||
self.text_view.set_border_width(10)
|
||||
self.text_view.set_editable(False)
|
||||
self.text_buffer = Gtk.TextBuffer()
|
||||
self.text_buffer.create_tag('heading', scale=1.2, weight=Pango.Weight.BOLD)
|
||||
self.text_buffer.create_tag('subheading', scale=1.0)
|
||||
self.text_view.set_buffer(self.text_buffer)
|
||||
self.scrolled_window = Gtk.ScrolledWindow()
|
||||
self.scrolled_window.set_shadow_type(Gtk.ShadowType.IN)
|
||||
self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
||||
self.scrolled_window.add(self.init())
|
||||
|
||||
self.status = Gtk.Label.new()
|
||||
self.status.set_halign(Gtk.Align.START)
|
||||
|
@ -78,13 +75,20 @@ class gPodderShownotes:
|
|||
self.link_color = None
|
||||
self.visited_color = None
|
||||
|
||||
self.scrolled_window = Gtk.ScrolledWindow()
|
||||
# main_component is the scrolled_window, except for gPodderShownotesText
|
||||
# where it's an overlay, to show hyperlink targets
|
||||
self.main_component = self.scrolled_window
|
||||
self.scrolled_window.set_shadow_type(Gtk.ShadowType.IN)
|
||||
self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
||||
self.scrolled_window.add(self.init())
|
||||
self.overlay = Gtk.Overlay()
|
||||
self.overlay.add(self.scrolled_window)
|
||||
# need an EventBox for an opaque background behind the label
|
||||
box = Gtk.EventBox()
|
||||
self.status_bg = box
|
||||
box.add(self.status)
|
||||
box.set_hexpand(False)
|
||||
box.set_vexpand(False)
|
||||
box.set_valign(Gtk.Align.END)
|
||||
box.set_halign(Gtk.Align.START)
|
||||
self.overlay.add_overlay(box)
|
||||
self.overlay.set_overlay_pass_through(box, True)
|
||||
|
||||
self.main_component = self.overlay
|
||||
self.main_component.show_all()
|
||||
|
||||
self.da_message = Gtk.DrawingArea()
|
||||
|
@ -109,9 +113,7 @@ class gPodderShownotes:
|
|||
if self.pane_is_visible:
|
||||
if len(selected_episodes) == 1:
|
||||
episode = selected_episodes[0]
|
||||
heading = episode.title
|
||||
subheading = _('from %s') % (episode.channel.title)
|
||||
self.update(heading, subheading, episode)
|
||||
self.update(episode)
|
||||
self.set_complain_about_selection(False)
|
||||
else:
|
||||
self.set_complain_about_selection(True)
|
||||
|
@ -157,38 +159,43 @@ class gPodderShownotes:
|
|||
# ([(Gtk.Window, 'background', ''), (Gtk.TextView, 'view', '')], self.text_view),
|
||||
# ([(Gtk.Window, 'background', ''), (Gtk.TextView, 'view', 'text')], self.text_view),
|
||||
# ])
|
||||
self.background_color = get_background_color(Gtk.StateFlags.NORMAL, widget=self.text_view) or Gdk.RGBA()
|
||||
self.foreground_color = get_foreground_color(Gtk.StateFlags.NORMAL, widget=self.text_view) or Gdk.RGBA(0, 0, 0)
|
||||
self.link_color = (get_foreground_color(state=Gtk.StateFlags.LINK, widget=self.text_view) or Gdk.RGBA(0, 0, 0))
|
||||
self.visited_color = (get_foreground_color(state=Gtk.StateFlags.VISITED, widget=self.text_view) or self.link_color)
|
||||
dummy_tv = Gtk.TextView()
|
||||
self.background_color = get_background_color(Gtk.StateFlags.NORMAL,
|
||||
widget=dummy_tv) or Gdk.RGBA()
|
||||
self.foreground_color = get_foreground_color(Gtk.StateFlags.NORMAL,
|
||||
widget=dummy_tv) or Gdk.RGBA(0, 0, 0)
|
||||
self.link_color = get_foreground_color(state=Gtk.StateFlags.LINK,
|
||||
widget=dummy_tv) or Gdk.RGBA(0, 0, 0)
|
||||
self.visited_color = get_foreground_color(state=Gtk.StateFlags.VISITED,
|
||||
widget=dummy_tv) or self.link_color
|
||||
del dummy_tv
|
||||
|
||||
self.status_bg.override_background_color(Gtk.StateFlags.NORMAL, self.background_color)
|
||||
self.text_buffer.create_tag('hyperlink',
|
||||
foreground=self.link_color.to_string(),
|
||||
underline=Pango.Underline.SINGLE)
|
||||
if hasattr(self, "text_buffer"):
|
||||
self.text_buffer.create_tag('hyperlink',
|
||||
foreground=self.link_color.to_string(),
|
||||
underline=Pango.Underline.SINGLE)
|
||||
|
||||
|
||||
class gPodderShownotesText(gPodderShownotes):
|
||||
def init(self):
|
||||
self.text_view = Gtk.TextView()
|
||||
self.text_view.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
|
||||
self.text_view.set_border_width(10)
|
||||
self.text_view.set_editable(False)
|
||||
self.text_buffer = Gtk.TextBuffer()
|
||||
self.text_buffer.create_tag('heading', scale=1.2, weight=Pango.Weight.BOLD)
|
||||
self.text_buffer.create_tag('subheading', scale=1.0)
|
||||
self.text_view.set_buffer(self.text_buffer)
|
||||
self.text_view.set_property('expand', True)
|
||||
self.text_view.connect('button-release-event', self.on_button_release)
|
||||
self.text_view.connect('key-press-event', self.on_key_press)
|
||||
self.text_view.connect('motion-notify-event', self.on_hover_hyperlink)
|
||||
self.overlay = Gtk.Overlay()
|
||||
self.overlay.add(self.scrolled_window)
|
||||
# need an EventBox for an opaque background behind the label
|
||||
box = Gtk.EventBox()
|
||||
self.status_bg = box
|
||||
box.add(self.status)
|
||||
box.set_hexpand(False)
|
||||
box.set_vexpand(False)
|
||||
box.set_valign(Gtk.Align.END)
|
||||
box.set_halign(Gtk.Align.START)
|
||||
self.overlay.add_overlay(box)
|
||||
self.overlay.set_overlay_pass_through(box, True)
|
||||
self.main_component = self.overlay
|
||||
return self.text_view
|
||||
|
||||
def update(self, heading, subheading, episode):
|
||||
def update(self, episode):
|
||||
heading = episode.title
|
||||
subheading = _('from %s') % (episode.channel.title)
|
||||
self.define_colors()
|
||||
hyperlinks = [(0, None)]
|
||||
self.text_buffer.set_text('')
|
||||
|
@ -267,23 +274,12 @@ class gPodderShownotesHTML(gPodderShownotes):
|
|||
self.html_view.connect('context-menu', self.on_context_menu)
|
||||
self.html_view.connect('decide-policy', self.on_decide_policy)
|
||||
self.html_view.connect('authenticate', self.on_authenticate)
|
||||
# give the vertical space to the html view!
|
||||
self.text_view.set_property('hexpand', True)
|
||||
grid = Gtk.Grid()
|
||||
self.status_bg = grid
|
||||
grid.attach(self.text_view, 0, 0, 1, 1)
|
||||
grid.attach(self.html_view, 0, 1, 1, 1)
|
||||
grid.attach(self.status, 0, 2, 1, 1)
|
||||
return grid
|
||||
|
||||
def update(self, heading, subheading, episode):
|
||||
return self.html_view
|
||||
|
||||
def update(self, episode):
|
||||
self.define_colors()
|
||||
|
||||
self.text_buffer.set_text('')
|
||||
self.text_buffer.insert_with_tags_by_name(self.text_buffer.get_end_iter(), heading, 'heading')
|
||||
self.text_buffer.insert_at_cursor('\n')
|
||||
self.text_buffer.insert_with_tags_by_name(self.text_buffer.get_end_iter(), subheading, 'subheading')
|
||||
|
||||
if episode.has_website_link():
|
||||
self._base_uri = episode.link
|
||||
else:
|
||||
|
@ -298,14 +294,14 @@ class gPodderShownotesHTML(gPodderShownotes):
|
|||
stylesheet = self.get_stylesheet()
|
||||
if stylesheet:
|
||||
self.manager.add_style_sheet(stylesheet)
|
||||
header_html = _('<h3>%s</h3>\n<p>from %s</p>\n') % (episode.title, episode.channel.title)
|
||||
description_html = episode.description_html
|
||||
if description_html:
|
||||
# uncomment to prevent background override in html shownotes
|
||||
# self.manager.remove_all_style_sheets ()
|
||||
logger.debug("base uri: %s (chan:%s)", self._base_uri, episode.channel.url)
|
||||
self.html_view.load_html(description_html, self._base_uri)
|
||||
else:
|
||||
self.html_view.load_plain_text(episode.description)
|
||||
if not description_html:
|
||||
description_html = re.sub(r'\n', '<br>\n', episode.description)
|
||||
# uncomment to prevent background override in html shownotes
|
||||
# self.manager.remove_all_style_sheets ()
|
||||
logger.debug("base uri: %s (chan:%s)", self._base_uri, episode.channel.url)
|
||||
self.html_view.load_html(header_html + description_html, self._base_uri)
|
||||
# uncomment to show web inspector
|
||||
# self.html_view.get_inspector().show()
|
||||
self.episode = episode
|
||||
|
|
Loading…
Reference in New Issue