X-Git-Url: http://git.tremily.us/?p=hooke.git;a=blobdiff_plain;f=hooke%2Fplaylist.py;h=dfec6d72c28c65b3888f6b4d5265b43fee523d73;hp=c57604ff08872fd8f9ab3aef584551947eac191c;hb=b90995fb4b6d8151df862d40edc8c369d7052cfa;hpb=565f9d7b69d2e4a9ea447d7a50f8f835c3e08642 diff --git a/hooke/playlist.py b/hooke/playlist.py index c57604f..dfec6d7 100644 --- a/hooke/playlist.py +++ b/hooke/playlist.py @@ -24,6 +24,7 @@ import copy import hashlib import os.path +import types import xml.dom.minidom from . import curve as curve @@ -44,13 +45,27 @@ class NoteIndexList (list): self._index = 0 def __str__(self): - return '<%s %s>' % (self.__class__.__name__, self.name) + return str(self.__unicode__()) + + def __unicode__(self): + return u'<%s %s>' % (self.__class__.__name__, self.name) + + def __repr__(self): + return self.__str__() def _setup_item(self, item): """Perform any required initialization before returning an item. """ pass + def index(self, value=None, *args, **kwargs): + """Extend `list.index`, returning the current index if `value` + is `None`. + """ + if value == None: + return self._index + return super(NoteIndexList, self).index(value, *args, **kwargs) + def current(self): if len(self) == 0: return None @@ -70,10 +85,34 @@ class NoteIndexList (list): def previous(self): self.jump(self._index - 1) + def items(self, reverse=False): + """Iterate through `self` calling `_setup_item` on each item + before yielding. + + Notes + ----- + Updates :attr:`_index` during the iteration so + :func:`~hooke.plugin.curve.current_curve_callback` works as + expected in :class:`~hooke.command.Command`\s called from + :class:`~hooke.plugin.playlist.ApplyCommandStack`. After the + iteration completes, :attr:`_index` is restored to its + original value. + """ + index = self._index + items = self + if reverse == True: + items = reversed(enumerate(self)) + else: + items = enumerate(self) + for i,item in items: + self._index = i + self._setup_item(item) + yield item + self._index = index + def filter(self, keeper_fn=lambda item:True, *args, **kwargs): c = copy.deepcopy(self) - for item in reversed(c): - c._setup_item(item) + for item in c.items(reverse=True): if keeper_fn(item, *args, **kwargs) != True: c.remove(item) try: # attempt to maintain the same current item @@ -82,6 +121,7 @@ class NoteIndexList (list): c._index = 0 return c + class Playlist (NoteIndexList): """A :class:`NoteIndexList` of :class:`hooke.curve.Curve`\s. @@ -93,11 +133,10 @@ class Playlist (NoteIndexList): self._loaded = [] # List of loaded curves, see :meth:`._setup_item`. self._max_loaded = 100 # curves to hold in memory simultaneously. - def append_curve_by_path(self, path, info=None, identify=True): - if self.path != None: - path = os.path.join(os.path.dirname(self.path), path) + def append_curve_by_path(self, path, info=None, identify=True, hooke=None): path = os.path.normpath(path) c = curve.Curve(path, info=info) + c.set_hooke(hooke) if identify == True: c.identify(self.drivers) self.append(c) @@ -116,11 +155,13 @@ class Playlist (NoteIndexList): oldest = self._loaded.pop(0) oldest.unload() + class FilePlaylist (Playlist): version = '0.1' def __init__(self, drivers, name=None, path=None): super(FilePlaylist, self).__init__(drivers, name) + self.path = None self.set_path(path) self._digest = None self._ignored_keys = [ @@ -135,6 +176,11 @@ class FilePlaylist (Playlist): if self.name == None: self.name = os.path.basename(path) + def append_curve_by_path(self, path, *args, **kwargs): + if self.path != None: + path = os.path.join(os.path.dirname(self.path), path) + super(FilePlaylist, self).append_curve_by_path(path, *args, **kwargs) + def is_saved(self): return self.digest() == self._digest @@ -231,6 +277,9 @@ class FilePlaylist (Playlist): root.setAttribute('version', self.version) # store playlist version root.setAttribute('index', str(self._index)) for key,value in self.info.items(): # save info variables + if (key in self._ignored_keys + or not isinstance(value, types.StringTypes)): + continue root.setAttribute(self._clean_key(key), str(value)) for curve in self: # save curves and their attributes curve_element = doc.createElement('curve') @@ -244,7 +293,8 @@ class FilePlaylist (Playlist): os.path.expanduser(self.path)))) curve_element.setAttribute('path', path) for key,value in curve.info.items(): - if key in self._ignored_keys: + if (key in self._ignored_keys + or not isinstance(value, types.StringTypes)): continue curve_element.setAttribute(self._clean_key(key), str(value)) string = doc.toprettyxml(encoding='utf-8') @@ -303,18 +353,20 @@ class FilePlaylist (Playlist): doc = xml.dom.minidom.parseString(string) self._from_xml_doc(doc, identify=identify) - def load(self, path=None, identify=True): + def load(self, path=None, identify=True, hooke=None): """Load a playlist from a file. """ self.set_path(path) doc = xml.dom.minidom.parse(self.path) self._from_xml_doc(doc, identify=identify) self._digest = self.digest() - + for curve in self: + curve.set_hooke(hooke) + def save(self, path=None): """Saves the playlist in a XML file. """ self.set_path(path) - f = file(self.path, 'w') - f.write(self.flatten()) - f.close() + with open(self.path, 'w') as f: + f.write(self.flatten()) + self._digest = self.digest()