Author: duncan
Date: Sat Mar 24 10:09:24 2007
New Revision: 9380
Modified:
branches/rel-1/freevo/src/tv/plugins/recordings_manager.py
Log:
[ 1672003 ] TV Recordings Manager and automatic space reclaiming
Patch from Adam Charrett applied, this patch adds more sort options
Modified: branches/rel-1/freevo/src/tv/plugins/recordings_manager.py
==============================================================================
--- branches/rel-1/freevo/src/tv/plugins/recordings_manager.py (original)
+++ branches/rel-1/freevo/src/tv/plugins/recordings_manager.py Sat Mar 24
10:09:24 2007
@@ -36,6 +36,7 @@
"""
import os
+import os.path
import datetime
import traceback
import re
@@ -62,6 +63,38 @@
disk_manager = None
+
+SORTING_DATE_NAME = 0
+SORTING_STATUS_NAME = 1
+SORTING_STATUS_DATE_NAME = 2
+SORTING_NAME = 4
+
+sorting_methods = [_('Date then Name'),
+ _('Status then Name'),
+ _('Status, Date then Name'),
+ _('Name')
+ ]
+series_sorting_methods = sorting_methods
+
+status_order_methods = ['Unwatched, Keep, Watched',
+ 'Unwatched, Watched, Keep',
+ 'Keep, Unwatched, Watched']
+
+STATUS_ORDERS = [ ('2', '1', '0'),
+ ('2', '0', '1'),
+ ('1', '2', '0')]
+
+STATUS_ORDER_UNWATCHED = 0
+STATUS_ORDER_KEEP = 1
+STATUS_ORDER_WATCHED = 2
+
+sorting = 0
+sorting_reversed = False
+series_sorting = 0
+series_sorting_reversed = False
+status_order = 0
+
+
class PluginInterface(plugin.MainMenuPlugin):
"""
Plugin interface for the Manage Recordings TV menu and
@@ -107,6 +140,8 @@
Item.__init__(self, parent, skin_type='tv')
self.name = _('Manage Recordings')
self.dir = config.TV_RECORD_DIR
+ self.settings_fxd = os.path.join(self.dir, 'folder.fxd')
+ self.load_settings()
# ======================================================================
# actions
@@ -116,7 +151,8 @@
"""
return a list of actions for this item
"""
- items = [ ( self.browse, _('Browse directory')) ]
+ items = [ ( self.browse, _('Browse directory')) ,
+ ( self.configure, _('Configure directory'))]
return items
@@ -137,24 +173,25 @@
selected_id = self.menu.selected.id()
selected_pos = self.menu.choices.index(self.menu.selected)
-
- segregated_recordings.sort(lambda l, o:
cmp(o.sort('date+name').upper(), l.sort('date+name').upper()))
-
+ items = segregated_recordings
+ items.sort(lambda l, o: cmp(o.sort(sorting).upper(),
l.sort(sorting).upper()))
+ if sorting_reversed:
+ items.reverse()
if arg == 'update':
# update because of DiskManager
- self.menu.choices = segregated_recordings
+ self.menu.choices = items
if selected_pos != -1:
- for i in segregated_recordings:
+ for i in items:
if Unicode(i.id()) == Unicode(selected_id):
self.menu.selected = i
break
else:
# item is gone now, try to the selection close
# to the old item
- pos = max(0, min(selected_pos-1,
len(segregated_recordings)-1))
- if segregated_recordings:
- self.menu.selected = segregated_recordings[pos]
+ pos = max(0, min(selected_pos-1, len(items)-1))
+ if items:
+ self.menu.selected = items[pos]
else:
self.menu.selected = None
if self.menu.selected and selected_pos != -1:
@@ -164,13 +201,66 @@
self.menuw.refresh()
else:
# normal menu build
- item_menu = Menu(self.name, segregated_recordings,
reload_func=self.reload, item_types = 'tv')
+ item_menu = Menu(self.name, items, reload_func=self.reload,
item_types = 'tv')
menuw.pushmenu(item_menu)
self.menu = item_menu
self.menuw = menuw
- disk_manager.set_update_menu(self, menuw, None)
+ disk_manager.set_update_menu(self, self.menu, self.menuw)
+
+
+ # ======================================================================
+ # Configure methods
+ # ======================================================================
+
+ def configure_sorting(self, arg=None, menuw=None):
+ exec('%s += 1' % arg, globals())
+
+ if eval('%s >= len(%s_methods)' %(arg, arg), globals()):
+ exec('%s = 0' % arg, globals())
+
+ self.save_settings()
+
+ item = menuw.menustack[-1].selected
+ item.name = item.name[:item.name.find(u'\t') + 1] +
_(eval('%s_methods[%s]' % (arg,arg), globals()))
+
+ copy_and_replace_menu_item(menuw, item)
+
+
+ def configure_sorting_reversed(self, arg=None, menuw=None):
+ exec('%s = not %s' % (arg,arg), globals())
+ self.save_settings()
+
+ item = menuw.menustack[-1].selected
+ item.name = item.name[:item.name.find(u'\t') + 1] +
self.configure_get_icon( eval(arg, globals()))
+
+ copy_and_replace_menu_item(menuw, item)
+
+
+ def configure_get_icon(self, value):
+ if value:
+ icon = u'ICON_LEFT_ON_' + _('on')
+ else:
+ icon = u'ICON_LEFT_OFF_' + _('off')
+ return icon
+
+
+ def configure(self, arg=None, menuw=None):
+ items = [ MenuItem(_('Sort by') + u'\t' + _(sorting_methods[sorting]),
+ self.configure_sorting, 'sorting'),
+ MenuItem(_('Reverse sort')+ u'\t' +
self.configure_get_icon(sorting_reversed),
+ self.configure_sorting_reversed,
'sorting_reversed'),
+ MenuItem(_('Sort series by') + u'\t' +
_(series_sorting_methods[series_sorting]),
+ self.configure_sorting, 'series_sorting'),
+ MenuItem(_('Reverse series sort')+ u'\t' +
self.configure_get_icon(series_sorting_reversed),
+ self.configure_sorting_reversed,
'series_sorting_reversed'),
+ MenuItem(_('Status order') + u'\t' +
_(status_order_methods[status_order]),
+ self.configure_sorting, 'status_order')
+ ]
+ m = Menu(_('Configure'), items)
+ m.table = (50, 50)
+ menuw.pushmenu(m)
# ======================================================================
# Helper methods
@@ -182,7 +272,60 @@
"""
self.browse(arg='update')
return None
+
+ def load_settings(self):
+ if vfs.isfile(self.settings_fxd):
+ try:
+ parser = util.fxdparser.FXD(self.settings_fxd)
+ parser.set_handler('tvrmsettings', self.read_settings_fxd)
+ parser.parse()
+ except:
+ print "fxd file %s corrupt" % self.settings_fxd
+ traceback.print_exc()
+ def save_settings(self):
+ try:
+ parser = util.fxdparser.FXD(self.settings_fxd)
+ parser.set_handler('tvrmsettings', self.write_settings_fxd, 'w',
True)
+ parser.save()
+ except:
+ print "fxd file %s corrupt" % self.settings_fxd
+ traceback.print_exc()
+
+ def read_settings_fxd(self, fxd, node):
+ '''
+ parse the xml file for directory settings
+
+ <?xml version="1.0" ?>
+ <freevo>
+ <tvrmsettings>
+ <setvar name="sorting" val="0"/>
+ </tvrmsettings>
+ </freevo>
+ '''
+
+ for child in fxd.get_children(node, 'setvar', 1):
+ name = child.attrs[('', 'name')]
+ val = child.attrs[('', 'val')]
+ exec('%s = %s' % (name, val), globals())
+
+
+ def write_settings_fxd(self, fxd, node):
+ """
+ callback to save the modified fxd file
+ """
+ # remove old setvar
+ for child in copy.copy(node.children):
+ if child.name == 'setvar':
+ node.children.remove(child)
+
+ # add current vars as setvar
+ fxd.add(fxd.XMLnode('setvar', (('name', 'sorting'),
('val', sorting))), node, None)
+ fxd.add(fxd.XMLnode('setvar', (('name', 'sorting_reversed'),
('val', sorting_reversed))), node, None)
+ fxd.add(fxd.XMLnode('setvar', (('name', 'series_sorting'),
('val', series_sorting))), node, None)
+ fxd.add(fxd.XMLnode('setvar', (('name', 'series_sorting_reversed'),
('val', series_sorting_reversed))), node, None)
+ fxd.add(fxd.XMLnode('setvar', (('name', 'status_order'),
('val', status_order))), node, None)
+
# ======================================================================
# Program Class
@@ -274,7 +417,7 @@
self.update_fxd(self.watched, self.keep)
self.set_icon()
if menuw:
- copy_and_replace_menu_item(menuw, self)
+ menuw.refresh(reload=True)
def mark_as_watched(self, arg=None, menuw=None):
@@ -285,7 +428,7 @@
self.update_fxd(self.watched, self.keep)
self.set_icon()
if menuw:
- copy_and_replace_menu_item(menuw, self)
+ menuw.refresh(reload=True)
def set_name_to_episode(self):
@@ -371,8 +514,12 @@
"""
Return a string to use to sort this item.
"""
- if mode == 'date+name':
+ if mode == SORTING_DATE_NAME:
return u'%010.0f%s' % (self.timestamp, self.name)
+ elif mode == SORTING_STATUS_NAME:
+ return get_status_sort_order(self.watched, self.keep) + self.name
+ elif mode == SORTING_STATUS_DATE_NAME:
+ return get_status_sort_order(self.watched, self.keep) +
self.sort(SORTING_DATE_NAME)
return self.name
@@ -456,7 +603,7 @@
self.menu = item_menu
self.menuw = menuw
- disk_manager.set_update_menu(self, menuw, None)
+ disk_manager.set_update_menu(self, self.menu, self.menuw)
def play_all(self, arg=None, menuw=None):
@@ -496,7 +643,7 @@
item.mark_to_keep()
self.set_icon()
if menuw:
- copy_and_replace_menu_item(menuw, self)
+ menuw.refresh(reload=True)
def update(self, items):
@@ -507,8 +654,10 @@
for item in self.items:
item.set_name_to_episode()
- # TODO: Replace with smart sort that knows about 'n/m <subtitle>'
style names
- self.items.sort(lambda l, o: cmp(l.sort().upper(), o.sort().upper()))
+ self.items.sort(lambda l, o: cmp(o.sort(series_sorting),
l.sort(series_sorting)))
+ if series_sorting_reversed:
+ self.items.reverse()
+
self.set_icon()
@@ -535,7 +684,9 @@
self.icon = config.ICON_DIR + '/status/series_watched.png'
else:
self.icon = config.ICON_DIR + '/status/series_unwatched.png'
-
+
+ self.watched = watched
+ self.keep = keep
def __getitem__(self, key):
"""
@@ -558,13 +709,18 @@
"""
Return a string to use to sort this item.
"""
- if mode == 'date+name':
+ if mode == SORTING_DATE_NAME:
latest_timestamp = 0.0
for item in self.items:
if item.timestamp > latest_timestamp:
latest_timestamp = item.timestamp
return u'%10d%s' % (int(latest_timestamp), self.name)
-
+
+ elif mode == SORTING_STATUS_NAME:
+ return get_status_sort_order(self.watched, self.keep) + self.name
+ elif mode == SORTING_STATUS_DATE_NAME:
+ return get_status_sort_order(self.watched, self.keep) +
self.sort(SORTING_DATE_NAME)
+
return self.name
def id(self):
@@ -605,12 +761,15 @@
self.check_recordings()
- def set_update_menu(self, menu, menuw, interested_series):
+ def set_update_menu(self, obj, menu, menuw):
"""
Set the menu to update when the recordings directory changes.
+ When an update is required, obj.browse(menuw=menuw,arg='update') will
be called.
+ menu is used to check that the menu is currently being displayed (ie
its at the top of the stack).
+ menuw is passed to obj.browse method.
"""
self.menuw = menuw
- self.interested_series = interested_series
+ self.obj = obj
self.menu = menu
@@ -632,8 +791,9 @@
if changed:
self.last_time = vfs.mtime(config.TV_RECORD_DIR)
self.update_recordings()
- if self.menu:
- self.menu.browse(menuw=self.menuw, arg='update')
+ # Only call update if the menu is on the top of the menu stack
+ if self.menu and (self.menuw.menustack[-1] == self.menu):
+ self.obj.browse(menuw=self.menuw, arg='update')
def update_recordings(self):
"""
@@ -751,3 +911,13 @@
menuw.delete_submenu(True, True)
+def get_status_sort_order(watched, keep):
+ orders = STATUS_ORDERS[status_order]
+
+ order = orders[STATUS_ORDER_UNWATCHED]
+ if keep:
+ order = orders[STATUS_ORDER_KEEP]
+ elif watched:
+ order = orders[STATUS_ORDER_WATCHED]
+ return order
+
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog