Merge branch 'master' into dev-adaptive
This commit is contained in:
commit
03a6aabf96
|
@ -6,7 +6,7 @@
|
|||
Media aggregator and podcast client
|
||||
___
|
||||
|
||||
Copyright 2005-2018 The gPodder Team
|
||||
Copyright 2005-2022 The gPodder Team
|
||||
|
||||
|
||||
## License
|
||||
|
|
718
po/cs_CZ.po
718
po/cs_CZ.po
File diff suppressed because it is too large
Load Diff
714
po/es_ES.po
714
po/es_ES.po
File diff suppressed because it is too large
Load Diff
714
po/es_MX.po
714
po/es_MX.po
File diff suppressed because it is too large
Load Diff
697
po/fa_IR.po
697
po/fa_IR.po
File diff suppressed because it is too large
Load Diff
688
po/id_ID.po
688
po/id_ID.po
File diff suppressed because it is too large
Load Diff
710
po/ko_KR.po
710
po/ko_KR.po
File diff suppressed because it is too large
Load Diff
690
po/messages.pot
690
po/messages.pot
File diff suppressed because it is too large
Load Diff
714
po/pt_BR.po
714
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
712
po/zh_CN.po
712
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
|
@ -128,7 +128,7 @@ class CurrentTrackTracker(object):
|
|||
'calc: %r observed: %r', cur['pos'], kwargs['pos'])
|
||||
self.notify_stop()
|
||||
|
||||
if ((kwargs['pos']) == 0 and
|
||||
if ((kwargs['pos']) <= 0 and
|
||||
self.pos is not None and
|
||||
self.length is not None and
|
||||
(self.length - USECS_IN_SEC) < self.pos and
|
||||
|
@ -144,7 +144,8 @@ class CurrentTrackTracker(object):
|
|||
logger.debug('pos=0 not end of stream (calculated pos: %f/%f [%f])',
|
||||
self.pos / USECS_IN_SEC, self.length / USECS_IN_SEC,
|
||||
(self.pos / USECS_IN_SEC) - (self.length / USECS_IN_SEC))
|
||||
self.pos = kwargs.pop('pos')
|
||||
newpos = kwargs.pop('pos')
|
||||
self.pos = newpos if newpos >= 0 else 0
|
||||
|
||||
if 'status' in kwargs:
|
||||
self.status = kwargs.pop('status')
|
||||
|
@ -274,35 +275,28 @@ class MPRISDBusReceiver(object):
|
|||
collected_info['rate'] = changed_properties['Rate']
|
||||
# Fix #788 pos=0 when Stopped resulting in not saving position on VLC quit
|
||||
if changed_properties.get('PlaybackStatus') != 'Stopped':
|
||||
collected_info['pos'] = self.query_position(sender)
|
||||
|
||||
try:
|
||||
collected_info['pos'] = self.query_property(sender, 'Position')
|
||||
except dbus.exceptions.DBusException:
|
||||
pass
|
||||
if 'status' not in collected_info:
|
||||
collected_info['status'] = str(self.query_status(sender))
|
||||
logger.debug('collected info: %r', collected_info)
|
||||
try:
|
||||
collected_info['status'] = str(self.query_property(
|
||||
sender, 'PlaybackStatus'))
|
||||
except dbus.exceptions.DBusException:
|
||||
pass
|
||||
|
||||
logger.debug('collected info: %r', collected_info)
|
||||
self.cur.update(**collected_info)
|
||||
|
||||
def on_seeked(self, position):
|
||||
logger.debug('seeked to pos: %f', position)
|
||||
self.cur.update(pos=position)
|
||||
|
||||
def query_position(self, sender):
|
||||
def query_property(self, sender, prop):
|
||||
proxy = self.bus.get_object(sender, self.PATH_MPRIS)
|
||||
props = dbus.Interface(proxy, self.INTERFACE_PROPS)
|
||||
try:
|
||||
pos = props.Get(self.INTERFACE_MPRIS, 'Position')
|
||||
except:
|
||||
pos = None
|
||||
return pos
|
||||
|
||||
def query_status(self, sender):
|
||||
proxy = self.bus.get_object(sender, self.PATH_MPRIS)
|
||||
props = dbus.Interface(proxy, self.INTERFACE_PROPS)
|
||||
try:
|
||||
status = props.Get(self.INTERFACE_MPRIS, 'PlaybackStatus')
|
||||
except:
|
||||
status = None
|
||||
return status
|
||||
return props.Get(self.INTERFACE_MPRIS, prop)
|
||||
|
||||
|
||||
class gPodderNotifier(dbus.service.Object):
|
||||
|
|
|
@ -18,6 +18,10 @@ except:
|
|||
import gpodder
|
||||
from gpodder import download, feedcore, model, registry, util, youtube
|
||||
|
||||
import gi # isort:skip
|
||||
gi.require_version('Gtk', '3.0') # isort:skip
|
||||
from gi.repository import Gtk # isort:skip
|
||||
|
||||
_ = gpodder.gettext
|
||||
|
||||
|
||||
|
@ -477,3 +481,40 @@ class gPodderExtension:
|
|||
# create a new gPodderYoutubeDL to force using it even if manage_downloads is False
|
||||
downloader = gPodderYoutubeDL(self.container.manager.core.config, self.container.config, force=True)
|
||||
self.gpodder.download_episode_list(episodes, downloader=downloader)
|
||||
|
||||
def toggle_manage_channel(self, widget):
|
||||
self.container.config.manage_channel = widget.get_active()
|
||||
|
||||
def toggle_manage_downloads(self, widget):
|
||||
self.container.config.manage_downloads = widget.get_active()
|
||||
|
||||
def show_preferences(self):
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||
box.set_border_width(10)
|
||||
|
||||
checkbox = Gtk.CheckButton(_('Parse Youtube channel feeds with Youtube-DL to access more than 15 episodes'))
|
||||
checkbox.set_active(self.container.config.manage_channel)
|
||||
checkbox.connect('toggled', self.toggle_manage_channel)
|
||||
box.pack_start(checkbox, False, False, 0)
|
||||
|
||||
box.pack_start(Gtk.HSeparator(), False, False, 0)
|
||||
|
||||
checkbox = Gtk.CheckButton(_('Download all supported episodes with Youtube-DL'))
|
||||
checkbox.set_active(self.container.config.manage_downloads)
|
||||
checkbox.connect('toggled', self.toggle_manage_downloads)
|
||||
box.pack_start(checkbox, False, False, 0)
|
||||
note = Gtk.Label(use_markup=True, wrap=True, label=_(
|
||||
'Youtube-DL provides access to additional Youtube formats and DRM content.'
|
||||
' Episodes from non-Youtube channels, that have Youtube-DL support, will <b>fail</b> to download unless you manually'
|
||||
' <a href="https://gpodder.github.io/docs/youtube.html#formats">add custom formats</a> for each site.'
|
||||
' <b>Download with Youtube-DL</b> appears in the episode menu when this option is disabled,'
|
||||
' and can be used to manually download from supported sites.'))
|
||||
note.connect('activate-link', lambda label, url: util.open_website(url))
|
||||
note.set_property('xalign', 0.0)
|
||||
box.add(note)
|
||||
|
||||
box.show_all()
|
||||
return box
|
||||
|
||||
def on_preferences(self):
|
||||
return [(_('Youtube-DL'), self.show_preferences)]
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
<property name="title" translatable="yes">Preferences</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="window-position">center-on-parent</property>
|
||||
<property name="default-width">320</property>
|
||||
<property name="default-height">260</property>
|
||||
<property name="default-width">480</property>
|
||||
<property name="default-height">340</property>
|
||||
<property name="type-hint">dialog</property>
|
||||
<signal name="destroy" handler="on_dialog_destroy" swapped="no"/>
|
||||
<child internal-child="vbox">
|
||||
|
@ -136,6 +136,7 @@
|
|||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkStack" id="prefs_stack">
|
||||
<property name="width-request">297</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hhomogeneous">False</property>
|
||||
|
@ -146,7 +147,7 @@
|
|||
<property name="can-focus">False</property>
|
||||
<property name="border-width">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<!-- n-columns=3 n-rows=2 -->
|
||||
<object class="GtkGrid">
|
||||
|
@ -298,13 +299,14 @@
|
|||
<property name="can-focus">False</property>
|
||||
<property name="border-width">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="checkbutton_enable">
|
||||
<property name="label" translatable="yes">Synchronize subscriptions and episode actions</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
<signal name="toggled" handler="on_enabled_toggled" swapped="no"/>
|
||||
</object>
|
||||
|
@ -425,9 +427,22 @@
|
|||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Replace subscription list on server with local subscriptions:</property>
|
||||
<property name="wrap">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_overwrite">
|
||||
<property name="label" translatable="yes">Replace list on server with local subscriptions</property>
|
||||
<property name="label" translatable="yes">Upload local subscriptions</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
|
@ -436,7 +451,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -452,17 +467,19 @@
|
|||
<property name="can-focus">False</property>
|
||||
<property name="border-width">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox_updating_interval">
|
||||
<object class="GtkBox" id="vbox_updating_interval">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_update_interval">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Update interval:</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.10000000149011612</property>
|
||||
</object>
|
||||
|
@ -506,46 +523,52 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox_episode_limit">
|
||||
<object class="GtkFlowBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<property name="min-children-per-line">1</property>
|
||||
<property name="max-children-per-line">2</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_episode_limit">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Maximum number of episodes per podcast:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_episode_limit">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="text" translatable="yes">200</property>
|
||||
<property name="adjustment">adjustment_episode_limit</property>
|
||||
<property name="value">200</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_episode_limit">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Maximum number of episodes per podcast:</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_episode_limit">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="text" translatable="yes">200</property>
|
||||
<property name="adjustment">adjustment_episode_limit</property>
|
||||
<property name="value">200</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -556,44 +579,49 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox_auto_download">
|
||||
<object class="GtkFlowBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<property name="min-children-per-line">1</property>
|
||||
<property name="max-children-per-line">2</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_auto_download">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">When new episodes are found:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_auto_download">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">When new episodes are found:</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combo_auto_download">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="changed" handler="on_combo_auto_download_changed" swapped="no"/>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combo_auto_download">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="changed" handler="on_combo_auto_download_changed" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -613,6 +641,7 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -634,11 +663,12 @@
|
|||
<property name="can-focus">False</property>
|
||||
<property name="border-width">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox_expiration">
|
||||
<object class="GtkBox" id="vbox_expiration">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_expiration">
|
||||
|
@ -685,6 +715,7 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -699,6 +730,7 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -720,62 +752,41 @@
|
|||
<property name="can-focus">False</property>
|
||||
<property name="border-width">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<!-- n-columns=2 n-rows=2 -->
|
||||
<object class="GtkGrid">
|
||||
<object class="GtkFlowBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="row-spacing">6</property>
|
||||
<property name="column-spacing">12</property>
|
||||
<property name="min-children-per-line">1</property>
|
||||
<property name="max-children-per-line">2</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_device_type">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Device type:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_device_type">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<signal name="changed" handler="on_combobox_device_type_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_device_mount">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Mountpoint:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="btn_filesystemMountpoint">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<signal name="clicked" handler="on_btn_device_mountpoint_clicked" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_device_type">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Device type:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_device_type">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<signal name="changed" handler="on_combobox_device_type_changed" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -785,13 +796,41 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="checkbutton_create_playlists">
|
||||
<property name="label" translatable="yes">Create playlists on device</property>
|
||||
<object class="GtkFlowBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
<signal name="toggled" handler="on_checkbutton_create_playlists_toggled" swapped="no"/>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="min-children-per-line">1</property>
|
||||
<property name="max-children-per-line">2</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_device_mount">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Mountpoint:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="btn_filesystemMountpoint">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<signal name="clicked" handler="on_btn_device_mountpoint_clicked" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
@ -800,36 +839,9 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_device_playlists">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Playlists Folder:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="btn_playlistfolder">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<signal name="clicked" handler="on_btn_playlist_folder_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
@ -838,12 +850,14 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="checkbutton_delete_using_playlists">
|
||||
<property name="label" translatable="yes">Remove episodes deleted on device from gPodder</property>
|
||||
<object class="GtkCheckButton" id="checkbutton_create_playlists">
|
||||
<property name="label" translatable="yes">Create playlists on device</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
<signal name="toggled" handler="on_checkbutton_create_playlists_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
@ -852,34 +866,39 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<object class="GtkFlowBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<property name="min-children-per-line">1</property>
|
||||
<property name="max-children-per-line">2</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_on_sync">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">After syncing an episode:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_device_playlists">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Playlists Folder:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_on_sync">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="changed" handler="on_combobox_on_sync_changed" swapped="no"/>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="btn_playlistfolder">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<signal name="clicked" handler="on_btn_playlist_folder_clicked" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -889,11 +908,13 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="checkbutton_skip_played_episodes">
|
||||
<property name="label" translatable="yes">Only sync unplayed episodes</property>
|
||||
<object class="GtkCheckButton" id="checkbutton_delete_using_playlists">
|
||||
<property name="label" translatable="yes">Remove episodes deleted on device from gPodder</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -903,12 +924,9 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="checkbutton_delete_deleted_episodes">
|
||||
<property name="label" translatable="yes">Remove episodes deleted in gPodder from device</property>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
@ -916,6 +934,90 @@
|
|||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFlowBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="min-children-per-line">1</property>
|
||||
<property name="max-children-per-line">2</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_on_sync">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">After syncing an episode:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_on_sync">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="changed" handler="on_combobox_on_sync_changed" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="checkbutton_skip_played_episodes">
|
||||
<property name="label" translatable="yes">Only sync unplayed episodes</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="margin-bottom">4</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="checkbutton_delete_deleted_episodes">
|
||||
<property name="label" translatable="yes">Remove episodes deleted in gPodder from device</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="margin-bottom">4</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">10</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">devices</property>
|
||||
|
@ -929,84 +1031,94 @@
|
|||
<property name="can-focus">False</property>
|
||||
<property name="border-width">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<!-- n-columns=2 n-rows=3 -->
|
||||
<object class="GtkGrid" id="table_video">
|
||||
<object class="GtkFlowBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="row-spacing">6</property>
|
||||
<property name="column-spacing">12</property>
|
||||
<property name="min-children-per-line">1</property>
|
||||
<property name="max-children-per-line">2</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_preferred_youtube_format">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Preferred YouTube format:</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_preferred_youtube_format">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Preferred YouTube format:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_preferred_youtube_format">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<signal name="changed" handler="on_combobox_preferred_youtube_format_changed" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_preferred_youtube_format">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="changed" handler="on_combobox_preferred_youtube_format_changed" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_preferred_youtube_hls_format">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Preferred YouTube HLS format:</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_preferred_youtube_hls_format">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Preferred YouTube HLS format:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_preferred_youtube_hls_format">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<signal name="changed" handler="on_combobox_preferred_youtube_hls_format_changed" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_preferred_youtube_hls_format">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="changed" handler="on_combobox_preferred_youtube_hls_format_changed" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_preferred_vimeo_format">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Preferred Vimeo format:</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_preferred_vimeo_format">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Preferred Vimeo format:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_preferred_vimeo_format">
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="changed" handler="on_combobox_preferred_vimeo_format_changed" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_preferred_vimeo_format">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="changed" handler="on_combobox_preferred_vimeo_format_changed" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -1028,7 +1140,7 @@
|
|||
<property name="can-focus">False</property>
|
||||
<property name="border-width">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="treeviewExtensions">
|
||||
<property name="visible">True</property>
|
||||
|
@ -1037,6 +1149,9 @@
|
|||
<property name="search-column">1</property>
|
||||
<signal name="button-release-event" handler="on_treeview_extension_button_released" swapped="no"/>
|
||||
<signal name="popup-menu" handler="on_treeview_extension_show_context_menu" swapped="no"/>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
|
|
|
@ -209,6 +209,7 @@ class gPodderPreferences(BuilderWidget):
|
|||
self.preferred_youtube_format_model = YouTubeVideoFormatListModel(self._config)
|
||||
self.combobox_preferred_youtube_format.set_model(self.preferred_youtube_format_model)
|
||||
cellrenderer = Gtk.CellRendererText()
|
||||
cellrenderer.set_property('ellipsize', Pango.EllipsizeMode.END)
|
||||
self.combobox_preferred_youtube_format.pack_start(cellrenderer, True)
|
||||
self.combobox_preferred_youtube_format.add_attribute(cellrenderer, 'text', self.preferred_youtube_format_model.C_CAPTION)
|
||||
self.combobox_preferred_youtube_format.set_active(self.preferred_youtube_format_model.get_index())
|
||||
|
@ -216,6 +217,7 @@ class gPodderPreferences(BuilderWidget):
|
|||
self.preferred_youtube_hls_format_model = YouTubeVideoHLSFormatListModel(self._config)
|
||||
self.combobox_preferred_youtube_hls_format.set_model(self.preferred_youtube_hls_format_model)
|
||||
cellrenderer = Gtk.CellRendererText()
|
||||
cellrenderer.set_property('ellipsize', Pango.EllipsizeMode.END)
|
||||
self.combobox_preferred_youtube_hls_format.pack_start(cellrenderer, True)
|
||||
self.combobox_preferred_youtube_hls_format.add_attribute(cellrenderer, 'text', self.preferred_youtube_hls_format_model.C_CAPTION)
|
||||
self.combobox_preferred_youtube_hls_format.set_active(self.preferred_youtube_hls_format_model.get_index())
|
||||
|
@ -223,6 +225,7 @@ class gPodderPreferences(BuilderWidget):
|
|||
self.preferred_vimeo_format_model = VimeoVideoFormatListModel(self._config)
|
||||
self.combobox_preferred_vimeo_format.set_model(self.preferred_vimeo_format_model)
|
||||
cellrenderer = Gtk.CellRendererText()
|
||||
cellrenderer.set_property('ellipsize', Pango.EllipsizeMode.END)
|
||||
self.combobox_preferred_vimeo_format.pack_start(cellrenderer, True)
|
||||
self.combobox_preferred_vimeo_format.add_attribute(cellrenderer, 'text', self.preferred_vimeo_format_model.C_CAPTION)
|
||||
self.combobox_preferred_vimeo_format.set_active(self.preferred_vimeo_format_model.get_index())
|
||||
|
@ -323,6 +326,17 @@ class gPodderPreferences(BuilderWidget):
|
|||
for label, callback in result:
|
||||
self.prefs_stack.add_titled(callback(), label, label)
|
||||
|
||||
def _wrap_checkbox_labels(w, *args):
|
||||
if w.get_name().startswith("no_label_wrap"):
|
||||
return
|
||||
elif isinstance(w, Gtk.CheckButton):
|
||||
label = w.get_child()
|
||||
label.set_line_wrap(True)
|
||||
elif isinstance(w, Gtk.Container):
|
||||
w.foreach(_wrap_checkbox_labels)
|
||||
|
||||
self.prefs_stack.foreach(_wrap_checkbox_labels)
|
||||
|
||||
def _extensions_select_function(self, selection, model, path, path_currently_selected):
|
||||
return model.get_value(model.get_iter(path), self.C_SHOW_TOGGLE)
|
||||
|
||||
|
@ -623,7 +637,8 @@ class gPodderPreferences(BuilderWidget):
|
|||
children = self.btn_playlistfolder.get_children()
|
||||
if children:
|
||||
label = children.pop()
|
||||
label.set_alignment(0., .5)
|
||||
label.set_ellipsize(Pango.EllipsizeMode.START)
|
||||
label.set_xalign(0.0)
|
||||
else:
|
||||
self.btn_playlistfolder.set_sensitive(False)
|
||||
self.btn_playlistfolder.set_label('')
|
||||
|
@ -645,10 +660,6 @@ class gPodderPreferences(BuilderWidget):
|
|||
self.btn_filesystemMountpoint.set_label(self._config.device_sync.device_folder or "")
|
||||
self.btn_filesystemMountpoint.set_sensitive(True)
|
||||
self.checkbutton_create_playlists.set_sensitive(True)
|
||||
children = self.btn_filesystemMountpoint.get_children()
|
||||
if children:
|
||||
label = children.pop()
|
||||
label.set_alignment(0., .5)
|
||||
self.toggle_playlist_interface(self._config.device_sync.playlists.create)
|
||||
self.combobox_on_sync.set_sensitive(True)
|
||||
self.checkbutton_skip_played_episodes.set_sensitive(True)
|
||||
|
@ -662,10 +673,11 @@ class gPodderPreferences(BuilderWidget):
|
|||
self.combobox_on_sync.set_sensitive(False)
|
||||
self.checkbutton_skip_played_episodes.set_sensitive(False)
|
||||
|
||||
children = self.btn_filesystemMountpoint.get_children()
|
||||
if children:
|
||||
label = children.pop()
|
||||
label.set_alignment(0., .5)
|
||||
children = self.btn_filesystemMountpoint.get_children()
|
||||
if children:
|
||||
label = children.pop()
|
||||
label.set_ellipsize(Pango.EllipsizeMode.START)
|
||||
label.set_xalign(0.0)
|
||||
|
||||
def on_btn_device_mountpoint_clicked(self, widget):
|
||||
fs = Gtk.FileChooserDialog(title=_('Select folder for mount point'),
|
||||
|
@ -709,7 +721,8 @@ class gPodderPreferences(BuilderWidget):
|
|||
children = self.btn_playlistfolder.get_children()
|
||||
if children:
|
||||
label = children.pop()
|
||||
label.set_alignment(0., .5)
|
||||
label.set_ellipsize(Pango.EllipsizeMode.START)
|
||||
label.set_xalign(0.0)
|
||||
break
|
||||
|
||||
fs.destroy()
|
||||
|
|
|
@ -49,9 +49,10 @@ class gPodderAddPodcast(BuilderWidget):
|
|||
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
||||
|
||||
def receive_clipboard_text(clipboard, text, second_try):
|
||||
# Heuristic: If there is a space in the clipboard
|
||||
# text, assume it's some arbitrary text, and no URL
|
||||
if text is not None and ' ' not in text:
|
||||
# Heuristic: If space is present in clipboard text
|
||||
# normalize_feed_url will either fix to valid url or
|
||||
# return None if URL cannot be validated
|
||||
if text is not None:
|
||||
url = util.normalize_feed_url(text)
|
||||
if url is not None:
|
||||
self.entry_url.set_text(url)
|
||||
|
@ -72,7 +73,7 @@ class gPodderAddPodcast(BuilderWidget):
|
|||
|
||||
def receive_clipboard_text(self, clipboard, text, data=None):
|
||||
if text is not None:
|
||||
self.entry_url.set_text(text)
|
||||
self.entry_url.set_text(text).strip()
|
||||
else:
|
||||
self.show_message(_('Nothing to paste.'), _('Clipboard is empty'))
|
||||
|
||||
|
|
|
@ -2207,7 +2207,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
any_new = any(e.is_new and e.state != gpodder.STATE_DELETED for e in episodes)
|
||||
downloaded = all(e.was_downloaded(and_exists=True) for e in episodes)
|
||||
downloading = any(e.downloading for e in episodes)
|
||||
(open_instead_of_play, can_play, can_download, can_pause, can_cancel, can_delete) = self.play_or_download()
|
||||
(open_instead_of_play, can_play, can_download, can_pause, can_cancel, can_delete, can_lock) = self.play_or_download()
|
||||
menu = self.application.builder.get_object('episodes-context')
|
||||
|
||||
# Play
|
||||
|
@ -2255,9 +2255,9 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
return True
|
||||
|
||||
def set_episode_actions(self, open_instead_of_play=False, can_play=False, can_download=False, can_pause=False, can_cancel=False,
|
||||
can_delete=False):
|
||||
can_delete=False, can_lock=False, is_episode_selected=False):
|
||||
# play icon and label
|
||||
# if open_instead_of_play:
|
||||
# if open_instead_of_play or not is_episode_selected:
|
||||
# self.toolPlay.set_icon_name('document-open')
|
||||
# self.toolPlay.set_label(_('Open'))
|
||||
# else:
|
||||
|
@ -2287,8 +2287,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
self.pause_action.set_enabled(can_pause)
|
||||
self.episodes_cancel_action.set_enabled(can_cancel)
|
||||
self.delete_action.set_enabled(can_delete)
|
||||
# self.toggle_episode_new_action.set_enabled(can_play)
|
||||
# self.toggle_episode_lock_action.set_enabled(can_play)
|
||||
# self.toggle_episode_new_action.set_enabled(is_episode_selected)
|
||||
# self.toggle_episode_lock_action.set_enabled(can_lock)
|
||||
self.episode_new_action.set_enabled(can_play)
|
||||
self.episode_lock_action.set_enabled(can_play)
|
||||
|
||||
|
@ -2435,7 +2435,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
# current_page = self.wNotebook.get_current_page()
|
||||
# if current_page == 0:
|
||||
if True:
|
||||
(open_instead_of_play, can_play, can_download, can_pause, can_cancel, can_delete) = (False,) * 6
|
||||
(open_instead_of_play, can_play, can_download, can_pause, can_cancel, can_delete, can_lock) = (False,) * 7
|
||||
|
||||
selection = self.treeAvailable.get_selection()
|
||||
if selection.count_selected_rows() > 0:
|
||||
|
@ -2451,16 +2451,20 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
logger.error('Invalid episode at path %s', str(path))
|
||||
continue
|
||||
|
||||
# These values should only ever be set, never unset them once set.
|
||||
# Actions filter episodes using these methods.
|
||||
open_instead_of_play = open_instead_of_play or episode.file_type() not in ('audio', 'video')
|
||||
can_play = can_play or episode.can_play(self.config)
|
||||
can_download = can_download or episode.can_download()
|
||||
can_pause = can_pause or episode.can_pause()
|
||||
can_cancel = can_cancel or episode.can_cancel()
|
||||
can_delete = can_delete or episode.can_delete()
|
||||
can_lock = can_lock or episode.can_lock()
|
||||
|
||||
self.set_episode_actions(open_instead_of_play, can_play, can_download, can_pause, can_cancel, can_delete)
|
||||
self.set_episode_actions(open_instead_of_play, can_play, can_download, can_pause, can_cancel, can_delete, can_lock,
|
||||
selection.count_selected_rows() > 0)
|
||||
|
||||
return (open_instead_of_play, can_play, can_download, can_pause, can_cancel, can_delete)
|
||||
return (open_instead_of_play, can_play, can_download, can_pause, can_cancel, can_delete, can_lock)
|
||||
else:
|
||||
(can_queue, can_pause, can_cancel, can_remove) = (False,) * 4
|
||||
|
||||
|
@ -2478,14 +2482,16 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
logger.error('Invalid task at path %s', str(path))
|
||||
continue
|
||||
|
||||
# These values should only ever be set, never unset them once set.
|
||||
# Actions filter tasks using these methods.
|
||||
can_queue = can_queue or task.can_queue()
|
||||
can_pause = can_pause or task.can_pause()
|
||||
can_cancel = can_cancel or task.can_cancel()
|
||||
can_remove = can_remove or task.can_remove()
|
||||
|
||||
self.set_episode_actions(False, False, can_queue, can_pause, can_cancel, can_remove)
|
||||
self.set_episode_actions(False, False, can_queue, can_pause, can_cancel, can_remove, False, False)
|
||||
|
||||
return (False, False, can_queue, can_pause, can_cancel, can_remove)
|
||||
return (False, False, can_queue, can_pause, can_cancel, can_remove, False)
|
||||
|
||||
def on_cbMaxDownloads_toggled(self, widget, *args):
|
||||
self.spinMaxDownloads.set_sensitive(self.cbMaxDownloads.get_active())
|
||||
|
@ -3002,16 +3008,22 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
# download older episodes first
|
||||
episodes = list(Model.sort_episodes_by_pubdate(episodes))
|
||||
|
||||
if not episodes:
|
||||
# Remove episodes without downloadable content
|
||||
downloadable_episodes = [e for e in episodes if e.url]
|
||||
|
||||
if not downloadable_episodes:
|
||||
# Nothing new here - but inform the user
|
||||
self.pbFeedUpdate.set_fraction(1.0)
|
||||
self.pbFeedUpdate.set_text(_('No new episodes'))
|
||||
self.pbFeedUpdate.set_text(
|
||||
_('No new episodes with downloadable content') if episodes else _('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))
|
||||
else:
|
||||
episodes = downloadable_episodes
|
||||
|
||||
count = len(episodes)
|
||||
# New episodes are available
|
||||
self.pbFeedUpdate.set_fraction(1.0)
|
||||
|
@ -3241,6 +3253,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
self.update_episode_list_icons(selected=True)
|
||||
self.db.commit()
|
||||
|
||||
self.play_or_download()
|
||||
|
||||
def mark_selected_episodes_new(self):
|
||||
for episode in self.get_selected_episodes():
|
||||
episode.mark(is_played=False)
|
||||
|
|
|
@ -194,6 +194,7 @@ class EpisodeListModel(Gtk.ListStore):
|
|||
# Are we currently showing "all episodes"/section or a single channel?
|
||||
self._section_view = False
|
||||
|
||||
self.ICON_WEB_BROWSER = 'web-browser'
|
||||
self.ICON_AUDIO_FILE = 'audio-x-generic'
|
||||
self.ICON_VIDEO_FILE = 'video-x-generic'
|
||||
self.ICON_IMAGE_FILE = 'image-x-generic'
|
||||
|
@ -468,6 +469,12 @@ class EpisodeListModel(Gtk.ListStore):
|
|||
if episode.state == gpodder.STATE_NORMAL and episode.is_new:
|
||||
view_show_downloaded = self._config.ui.gtk.episode_list.always_show_new
|
||||
view_show_unplayed = True
|
||||
elif not episode.url:
|
||||
tooltip.append(_('No downloadable content'))
|
||||
status_icon = self.ICON_WEB_BROWSER
|
||||
if episode.state == gpodder.STATE_NORMAL and episode.is_new:
|
||||
view_show_downloaded = self._config.ui.gtk.episode_list.always_show_new
|
||||
view_show_unplayed = True
|
||||
elif episode.state == gpodder.STATE_NORMAL and episode.is_new:
|
||||
tooltip.append(_('New episode'))
|
||||
view_show_downloaded = self._config.ui.gtk.episode_list.always_show_new
|
||||
|
|
|
@ -431,8 +431,9 @@ class gPodderShownotesHTML(gPodderShownotes):
|
|||
if req.get_uri() in (self._base_uri, 'about:blank'):
|
||||
decision.use()
|
||||
else:
|
||||
logger.debug("refusing to go to %s (base URI=%s)", req.get_uri(), self._base_uri)
|
||||
# Avoid opening the page inside the WebView and open in the browser instead
|
||||
decision.ignore()
|
||||
util.open_website(req.get_uri())
|
||||
return False
|
||||
else:
|
||||
decision.use()
|
||||
|
|
|
@ -351,7 +351,11 @@ class PodcastEpisode(PodcastModelObject):
|
|||
if link_has_media:
|
||||
return episode
|
||||
|
||||
return None
|
||||
# The episode has no downloadable content.
|
||||
# It is either a blog post or it links to a webpage with content accessible from shownotes title.
|
||||
# Remove the URL so downloading will fail.
|
||||
episode.url = ''
|
||||
return episode
|
||||
|
||||
def __init__(self, channel):
|
||||
self.parent = channel
|
||||
|
@ -507,6 +511,13 @@ class PodcastEpisode(PodcastModelObject):
|
|||
return self.state != gpodder.STATE_DELETED and not self.archive and (
|
||||
not self.download_task or self.download_task.status == self.download_task.FAILED)
|
||||
|
||||
def can_lock(self):
|
||||
"""
|
||||
gPodder.on_item_toggle_lock_activate() unlocks deleted episodes and toggles all others.
|
||||
Locked episodes can always be unlocked.
|
||||
"""
|
||||
return self.state != gpodder.STATE_DELETED or self.archive
|
||||
|
||||
def check_is_new(self):
|
||||
return (self.state == gpodder.STATE_NORMAL and self.is_new and
|
||||
not self.downloading)
|
||||
|
|
|
@ -73,14 +73,14 @@ logger = logging.getLogger(__name__)
|
|||
try:
|
||||
import html5lib
|
||||
except ImportError:
|
||||
logger.warn('html5lib not found, falling back to HTMLParser')
|
||||
logger.warning("html5lib was not found, fall-back to HTMLParser")
|
||||
html5lib = None
|
||||
|
||||
if gpodder.ui.win32:
|
||||
try:
|
||||
import gpodder.utilwin32ctypes as win32file
|
||||
except ImportError:
|
||||
logger.warn('Running on Win32 but utilwin32ctypes can\'t be loaded.')
|
||||
logger.warning('Running on Win32: utilwin32ctypes cannot be loaded')
|
||||
win32file = None
|
||||
|
||||
_ = gpodder.gettext
|
||||
|
@ -248,6 +248,12 @@ def normalize_feed_url(url):
|
|||
if not url or len(url) < 8:
|
||||
return None
|
||||
|
||||
# Removes leading and/or trailing whitespaces - if url contains whitespaces
|
||||
# in between after str.strip() -> conclude invalid url & return None
|
||||
url = url.strip()
|
||||
if ' ' in url:
|
||||
return None
|
||||
|
||||
# This is a list of prefixes that you can use to minimize the amount of
|
||||
# keystrokes that you have to use.
|
||||
# Feel free to suggest other useful prefixes, and I'll add them here.
|
||||
|
|
Loading…
Reference in New Issue