Merged episode locking patch from Paul Rudkin
git-svn-id: svn://svn.berlios.de/gpodder/trunk@489 b0d088ad-0a06-0410-aad2-9ed5178a7e87
This commit is contained in:
parent
9dbc9d5a73
commit
fe05092ef6
6 changed files with 120 additions and 26 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
Wed, 12 Dec 2007 19:44:15 +0100 <thp@perli.net>
|
||||
Merged episode locking patch from Paul Rudkin
|
||||
|
||||
* src/gpodder/gui.py: Merged "lock episodes" patch to mark episodes as
|
||||
locked, patch by Paul Rudkin <paul@thegithouse.com>
|
||||
* data/gpodder.glade: Add menu item for toggle locked status
|
||||
* src/gpodder/libgpodder.py: Add "locked" history
|
||||
* src/gpodder/libpodcasts.py: When requesting a status icon, also draw
|
||||
the "Locked" status; is_locked() in podcastItem
|
||||
* src/gpodder/util.py: Added code for drawing a padlock icon on top of
|
||||
another (file type) icon; this is used for the "lock episodes" feature
|
||||
|
||||
Tue, 11 Dec 2007 22:10:03 +0100 <thp@perli.net>
|
||||
Updated TODO list
|
||||
|
||||
|
|
|
@ -576,6 +576,15 @@
|
|||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="item_toggle_lock">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Toggle lock status for selection</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_item_toggle_lock_activate"/>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separator11">
|
||||
<property name="visible">True</property>
|
||||
|
|
|
@ -430,10 +430,13 @@ class gPodder(GladeWidget):
|
|||
item.set_image( gtk.image_new_from_stock( gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_MENU))
|
||||
item.connect( 'activate', lambda w: self.on_treeAvailable_row_activated( self.toolPlay))
|
||||
menu.append( item)
|
||||
item = gtk.ImageMenuItem( _('Remove %s') % episode_title)
|
||||
item.set_image( gtk.image_new_from_stock( gtk.STOCK_DELETE, gtk.ICON_SIZE_MENU))
|
||||
item.connect( 'activate', self.on_btnDownloadedDelete_clicked)
|
||||
menu.append( item)
|
||||
|
||||
is_locked = gPodderLib().history_is_locked(first_url)
|
||||
if not is_locked:
|
||||
item = gtk.ImageMenuItem(_('Remove %s') % episode_title)
|
||||
item.set_image(gtk.image_new_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_MENU))
|
||||
item.connect('activate', self.on_btnDownloadedDelete_clicked)
|
||||
menu.append(item)
|
||||
|
||||
if can_download:
|
||||
item = gtk.ImageMenuItem( _('Download %s') % episode_title)
|
||||
|
@ -474,6 +477,19 @@ class gPodder(GladeWidget):
|
|||
item.connect( 'activate', lambda w: self.on_item_toggle_played_activate( w, False, True))
|
||||
menu.append( item)
|
||||
|
||||
menu.append(gtk.SeparatorMenuItem())
|
||||
is_locked = gPodderLib().history_is_locked(first_url)
|
||||
if is_locked:
|
||||
item = gtk.ImageMenuItem(_('Unlock %s') % episode_title)
|
||||
item.set_image(gtk.image_new_from_stock(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_MENU))
|
||||
item.connect('activate', self.on_item_toggle_lock_activate)
|
||||
menu.append(item)
|
||||
else:
|
||||
item = gtk.ImageMenuItem(_('Lock %s') % episode_title)
|
||||
item.set_image(gtk.image_new_from_stock(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_MENU))
|
||||
item.connect('activate', self.on_item_toggle_lock_activate)
|
||||
menu.append(item)
|
||||
|
||||
if can_cancel:
|
||||
item = gtk.ImageMenuItem( _('_Cancel download'))
|
||||
item.set_image( gtk.image_new_from_stock( gtk.STOCK_STOP, gtk.ICON_SIZE_MENU))
|
||||
|
@ -622,6 +638,7 @@ class gPodder(GladeWidget):
|
|||
try:
|
||||
channel = podcastChannel.get_by_url( url = result, force_update = True)
|
||||
except:
|
||||
log('Error in podcastChannel.get_by_url(%s)', result, sender=self)
|
||||
channel = None
|
||||
|
||||
if channel:
|
||||
|
@ -892,7 +909,7 @@ class gPodder(GladeWidget):
|
|||
selected = []
|
||||
for channel in self.channels:
|
||||
for episode in channel:
|
||||
if episode.is_downloaded():
|
||||
if episode.is_downloaded() and not episode.is_locked():
|
||||
episodes.append( episode)
|
||||
selected.append( episode.is_played())
|
||||
|
||||
|
@ -917,6 +934,14 @@ class gPodder(GladeWidget):
|
|||
|
||||
self.for_each_selected_episode_url( callback)
|
||||
|
||||
def on_item_toggle_lock_activate(self, widget, toggle=True, new_value=False):
|
||||
if toggle:
|
||||
callback = lambda url: gPodderLib().history_mark_locked(url, not gPodderLib().history_is_locked(url))
|
||||
else:
|
||||
callback = lambda url: gPodderLib().history_mark_locked(url, new_value)
|
||||
|
||||
self.for_each_selected_episode_url(callback)
|
||||
|
||||
def on_itemUpdate_activate(self, widget, *args):
|
||||
if self.channels:
|
||||
self.update_feed_cache()
|
||||
|
@ -1290,12 +1315,36 @@ class gPodder(GladeWidget):
|
|||
return
|
||||
|
||||
if selection.count_selected_rows() == 1:
|
||||
title = _('Remove %s?') % model.get_value( model.get_iter( paths[0]), 1)
|
||||
episode_title = saxutils.escape(model.get_value(model.get_iter(paths[0]), 1))
|
||||
|
||||
locked = gPodderLib().history_is_locked(model.get_value(model.get_iter(paths[0]), 0))
|
||||
if locked:
|
||||
title = _('%s is locked') % episode_title
|
||||
message = _('You cannot delete this locked episode. You must unlock it before you can delete it.')
|
||||
self.notification(message, title)
|
||||
return
|
||||
|
||||
title = _('Remove %s?') % episode_title
|
||||
message = _("If you remove this episode, it will be deleted from your computer. If you want to listen to this episode again, you will have to re-download it.")
|
||||
else:
|
||||
title = _('Remove %d episodes?') % selection.count_selected_rows()
|
||||
message = _('If you remove these episodes, they will be deleted from your computer. If you want to listen to any of these episodes again, you will have to re-download the episodes in question.')
|
||||
|
||||
|
||||
locked_count = 0
|
||||
for path in paths:
|
||||
url = model.get_value(model.get_iter(path), 0)
|
||||
if gPodderLib().history_is_locked(url):
|
||||
locked_count += 1
|
||||
|
||||
if selection.count_selected_rows() == locked_count:
|
||||
title = _('Episodes are locked')
|
||||
message = _('The selected episodes are locked. Please unlock the episodes that you want to delete before trying to delete them.')
|
||||
self.notification(message, title)
|
||||
return
|
||||
elif locked_count > 0:
|
||||
title = _('Remove %d out of %d episodes?') % (selection.count_selected_rows() - locked_count, selection.count_selected_rows())
|
||||
message = _('The selection contains locked episodes. These will not be deleted. If you want to listen to any of these episodes again, then you will have to re-download them.')
|
||||
|
||||
# if user confirms deletion, let's remove some stuff ;)
|
||||
if self.show_confirmation( message, title):
|
||||
try:
|
||||
|
|
|
@ -68,7 +68,8 @@ class gPodderLibClass( object):
|
|||
|
||||
self.__download_history = HistoryStore( os.path.join( gpodder_dir, 'download-history.txt'))
|
||||
self.__playback_history = HistoryStore( os.path.join( gpodder_dir, 'playback-history.txt'))
|
||||
|
||||
self.__locked_history = HistoryStore( os.path.join( gpodder_dir, 'lock-history.txt'))
|
||||
|
||||
def get_device_name( self):
|
||||
if self.config.device_type == 'ipod':
|
||||
return _('iPod')
|
||||
|
@ -134,12 +135,21 @@ class gPodderLibClass( object):
|
|||
else:
|
||||
self.__playback_history.del_item( url)
|
||||
|
||||
def history_mark_locked( self, url, add_item = True):
|
||||
if add_item:
|
||||
self.__locked_history.add_item( url)
|
||||
else:
|
||||
self.__locked_history.del_item( url)
|
||||
|
||||
def history_is_downloaded( self, url):
|
||||
return (url in self.__download_history)
|
||||
|
||||
def history_is_played( self, url):
|
||||
return (url in self.__playback_history)
|
||||
|
||||
def history_is_locked( self, url):
|
||||
return (url in self.__locked_history)
|
||||
|
||||
def playback_episode( self, channel, episode):
|
||||
self.history_mark_played( episode.url)
|
||||
filename = episode.local_filename()
|
||||
|
|
|
@ -407,17 +407,19 @@ class podcastChannel(ListType):
|
|||
url = model.get_value( iter, 0)
|
||||
local_filename = model.get_value( iter, 8)
|
||||
played = not libgpodder.gPodderLib().history_is_played( url)
|
||||
locked = libgpodder.gPodderLib().history_is_locked(url)
|
||||
|
||||
if os.path.exists( local_filename):
|
||||
file_type = util.file_type_by_extension( util.file_extension_from_url( url))
|
||||
if file_type == 'audio':
|
||||
status_icon = util.get_tree_icon( 'audio-x-generic', played, self.icon_cache)
|
||||
status_icon = util.get_tree_icon('audio-x-generic', played, locked, self.icon_cache)
|
||||
elif file_type == 'video':
|
||||
status_icon = util.get_tree_icon( 'video-x-generic', played, self.icon_cache)
|
||||
status_icon = util.get_tree_icon('video-x-generic', played, locked, self.icon_cache)
|
||||
elif file_type == 'torrent':
|
||||
status_icon = util.get_tree_icon( 'applications-internet', played, self.icon_cache)
|
||||
status_icon = util.get_tree_icon('applications-internet', played, locked, self.icon_cache)
|
||||
else:
|
||||
status_icon = util.get_tree_icon( 'unknown', played, self.icon_cache)
|
||||
status_icon = util.get_tree_icon('unknown', played, locked, self.icon_cache)
|
||||
|
||||
elif services.download_status_manager.is_download_in_progress( url):
|
||||
status_icon = util.get_tree_icon( gtk.STOCK_GO_DOWN, icon_cache = self.icon_cache)
|
||||
elif libgpodder.gPodderLib().history_is_downloaded( url):
|
||||
|
@ -592,6 +594,9 @@ class podcastItem(object):
|
|||
def is_downloaded( self):
|
||||
return os.path.exists( self.local_filename())
|
||||
|
||||
def is_locked(self):
|
||||
return libgpodder.gPodderLib().history_is_locked(self.url)
|
||||
|
||||
def delete_from_disk( self):
|
||||
self.channel.delete_episode_by_url( self.url)
|
||||
|
||||
|
|
|
@ -359,13 +359,13 @@ def file_type_by_extension( extension):
|
|||
return None
|
||||
|
||||
|
||||
def get_tree_icon( icon_name, add_bullet = False, icon_cache = None):
|
||||
def get_tree_icon(icon_name, add_bullet=False, add_padlock=False, icon_cache=None):
|
||||
"""
|
||||
Loads an icon from the current icon theme at the specified
|
||||
size, suitable for display in a gtk.TreeView.
|
||||
|
||||
Optionally adds a green bullet (the GTK Stock "Yes" icon)
|
||||
to the Pixbuf returned.
|
||||
to the Pixbuf returned. Also, a padlock icon can be added.
|
||||
|
||||
If an icon_cache parameter is supplied, it has to be a
|
||||
dictionary and will be used to store generated icons.
|
||||
|
@ -375,8 +375,8 @@ def get_tree_icon( icon_name, add_bullet = False, icon_cache = None):
|
|||
the cache.
|
||||
"""
|
||||
|
||||
if icon_cache != None and (icon_name,add_bullet) in icon_cache:
|
||||
return icon_cache[(icon_name,add_bullet)]
|
||||
if icon_cache != None and (icon_name,add_bullet,add_padlock) in icon_cache:
|
||||
return icon_cache[(icon_name,add_bullet,add_padlock)]
|
||||
|
||||
icon_theme = gtk.icon_theme_get_default()
|
||||
|
||||
|
@ -386,19 +386,28 @@ def get_tree_icon( icon_name, add_bullet = False, icon_cache = None):
|
|||
log( '(get_tree_icon) Warning: Cannot load icon with name "%s", will use default icon.', icon_name)
|
||||
icon = icon_theme.load_icon( gtk.STOCK_DIALOG_QUESTION, 16, 0)
|
||||
|
||||
if add_bullet and icon:
|
||||
if icon and (add_bullet or add_padlock):
|
||||
# We'll modify the icon, so use .copy()
|
||||
try:
|
||||
icon = icon.copy()
|
||||
emblem = icon_theme.load_icon( gtk.STOCK_YES, 10, 0)
|
||||
size = emblem.get_width()
|
||||
pos = icon.get_width() - size
|
||||
emblem.composite( icon, pos, pos, size, size, pos, pos, 1, 1, gtk.gdk.INTERP_BILINEAR, 255)
|
||||
except:
|
||||
log( '(get_tree_icon) Error adding emblem to icon "%s".', icon_name)
|
||||
if add_bullet:
|
||||
try:
|
||||
icon = icon.copy()
|
||||
emblem = icon_theme.load_icon(gtk.STOCK_YES, 10, 0)
|
||||
size = emblem.get_width()
|
||||
pos = icon.get_width() - size
|
||||
emblem.composite(icon, pos, pos, size, size, pos, pos, 1, 1, gtk.gdk.INTERP_BILINEAR, 255)
|
||||
except:
|
||||
log('(get_tree_icon) Error adding emblem to icon "%s".', icon_name)
|
||||
if add_padlock:
|
||||
try:
|
||||
icon = icon.copy()
|
||||
emblem = icon_theme.load_icon('emblem-nowrite', 8, 0)
|
||||
size = emblem.get_width()
|
||||
emblem.composite(icon, 0, 0, size, size, 0, 0, 1, 1, gtk.gdk.INTERP_BILINEAR, 255)
|
||||
except:
|
||||
log('(get_tree_icon) Error adding emblem to icon "%s".', icon_name)
|
||||
|
||||
if icon_cache != None:
|
||||
icon_cache[(icon_name,add_bullet)] = icon
|
||||
icon_cache[(icon_name,add_bullet,add_padlock)] = icon
|
||||
|
||||
return icon
|
||||
|
||||
|
|
Loading…
Reference in a new issue