diff options
Diffstat (limited to 'ranger/core/loader.py')
-rw-r--r-- | ranger/core/loader.py | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/ranger/core/loader.py b/ranger/core/loader.py new file mode 100644 index 00000000..4f4424e4 --- /dev/null +++ b/ranger/core/loader.py @@ -0,0 +1,127 @@ +# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from collections import deque +from time import time +from ranger.shared import FileManagerAware +import math + +def status_generator(): + """Generate a rotating line which can be used as a throbber""" + while True: + yield '/' + yield '-' + yield '\\' + yield '|' + +class LoadableObject(object): + def __init__(self, gen, descr): + self.load_generator = gen + self.description = descr + + def get_description(self): + return self.description + + +class Loader(FileManagerAware): + seconds_of_work_time = 0.03 + + def __init__(self): + self.queue = deque() + self.item = None + self.load_generator = None + self.status_generator = status_generator() + self.rotate() + self.old_item = None + + def rotate(self): + """Rotate the throbber""" + # TODO: move all throbber logic to UI + self.status = next(self.status_generator) + + def add(self, obj): + """ + Add an object to the queue. + It should have a load_generator method. + """ + while obj in self.queue: + self.queue.remove(obj) + self.queue.appendleft(obj) + + def move(self, _from, to): + try: + item = self.queue[_from] + except IndexError: + return + + del self.queue[_from] + + if to == 0: + self.queue.appendleft(item) + elif to == -1: + self.queue.append(item) + else: + raise NotImplementedError + + def remove(self, item=None, index=None): + if item is not None and index is None: + for i, test in enumerate(self.queue): + if test == item: + index = i + break + else: + return + + if index is not None: + if item is None: + item = self.queue[index] + if hasattr(item, 'unload'): + item.unload() + del self.queue[index] + + def work(self): + """ + Load items from the queue if there are any. + Stop after approximately self.seconds_of_work_time. + """ + while True: + # get the first item with a proper load_generator + try: + item = self.queue[0] + if item.load_generator is None: + self.queue.popleft() + else: + break + except IndexError: + return + + self.rotate() + if item != self.old_item: + self.old_item = item + + end_time = time() + self.seconds_of_work_time + + try: + while time() < end_time: + next(item.load_generator) + except StopIteration: + item.load_generator = None + self.queue.remove(item) + except Exception as err: + self.fm.notify(err) + + def has_work(self): + """Is there anything to load?""" + return bool(self.queue) |