moved image queue changes to an own branch

This commit is contained in:
Andreas Preikschat 2011-06-25 07:35:24 +02:00
parent 1ff42f59de
commit b12fd94f6e

View File

@ -32,7 +32,6 @@ to wait for the conversion to happen.
""" """
import logging import logging
import time import time
import Queue
from PyQt4 import QtCore from PyQt4 import QtCore
@ -54,59 +53,15 @@ class ImageThread(QtCore.QThread):
""" """
Run the thread. Run the thread.
""" """
self.imageManager._process() self.imageManager.process()
class Priority(object):
"""
Enumeration class for different priorities.
``Low``
Only the image's byte stream has to be generated. Neither the QImage nor
the byte stream has been requested yet.
``Normal``
The image's byte stream as well as the image has to be generated.
Neither the QImage nor the byte stream has been requested yet.
``High``
The image's byte stream as well as the image has to be generated. The
QImage for this image has been requested.
``Urgent``
The image's byte stream as well as the image has to be generated. The
byte stream for this image has been requested.
"""
Low = 3
Normal = 2
High = 1
Urgent = 0
class Image(object): class Image(object):
def __init__(self, name='', path=''): name = ''
self.name = name path = ''
self.path = path dirty = True
self.image = None image = None
self.image_bytes = None image_bytes = None
self.priority = Priority.Normal
class PriorityQueue(Queue.PriorityQueue):
"""
Customised ``Queue.PriorityQueue``.
"""
def remove(self, item):
"""
Removes the given ``item`` from the queue.
``item``
The item to remove. This should be a tuple::
``(Priority, Image)``
"""
if item in self.queue:
self.queue.remove(item)
class ImageManager(QtCore.QObject): class ImageManager(QtCore.QObject):
@ -121,64 +76,50 @@ class ImageManager(QtCore.QObject):
self.width = current_screen[u'size'].width() self.width = current_screen[u'size'].width()
self.height = current_screen[u'size'].height() self.height = current_screen[u'size'].height()
self._cache = {} self._cache = {}
self._imageThread = ImageThread(self) self._thread_running = False
self._clean_queue = PriorityQueue() self._cache_dirty = False
self.image_thread = ImageThread(self)
def update_display(self): def update_display(self):
""" """
Screen has changed size so rebuild the cache to new size. Screen has changed size so rebuild the cache to new size
""" """
log.debug(u'update_display') log.debug(u'update_display')
current_screen = ScreenList.get_instance().current current_screen = ScreenList.get_instance().current
self.width = current_screen[u'size'].width() self.width = current_screen[u'size'].width()
self.height = current_screen[u'size'].height() self.height = current_screen[u'size'].height()
# Mark the images as dirty for a rebuild by setting the image and byte # mark the images as dirty for a rebuild
# stream to None. for key in self._cache.keys():
self._clean_queue = PriorityQueue() image = self._cache[key]
for key, image in self._cache.iteritems(): image.dirty = True
image.priority = Priority.Normal image.image = resize_image(image.path, self.width, self.height)
image.image = None self._cache_dirty = True
image.image_bytes = None # only one thread please
self._clean_queue.put((image.priority, image)) if not self._thread_running:
# We want only one thread. self.image_thread.start()
if not self._imageThread.isRunning():
self._imageThread.start()
def get_image(self, name): def get_image(self, name):
""" """
Return the ``QImage`` from the cache. If not present wait for the Return the Qimage from the cache
background thread to process it.
""" """
log.debug(u'get_image %s' % name) log.debug(u'get_image %s' % name)
image = self._cache[name] return self._cache[name].image
if image.image is None:
self._clean_queue.remove((image.priority, image))
image.priority = Priority.High
self._clean_queue.put((image.priority, image))
while image.image is None:
log.debug(u'get_image - waiting')
time.sleep(0.1)
return image.image
def get_image_bytes(self, name): def get_image_bytes(self, name):
""" """
Returns the byte string for an image. If not present wait for the Returns the byte string for an image
background thread to process it. If not present wait for the background thread to process it.
""" """
log.debug(u'get_image_bytes %s' % name) log.debug(u'get_image_bytes %s' % name)
image = self._cache[name] if not self._cache[name].image_bytes:
if image.image_bytes is None: while self._cache[name].dirty:
self._clean_queue.remove((image.priority, image))
image.priority = Priority.Urgent
self._clean_queue.put((image.priority, image))
while image.image_bytes is None:
log.debug(u'get_image_bytes - waiting') log.debug(u'get_image_bytes - waiting')
time.sleep(0.1) time.sleep(0.1)
return image.image_bytes return self._cache[name].image_bytes
def del_image(self, name): def del_image(self, name):
""" """
Delete the Image from the cache. Delete the Image from the Cache
""" """
log.debug(u'del_image %s' % name) log.debug(u'del_image %s' % name)
if name in self._cache: if name in self._cache:
@ -186,44 +127,45 @@ class ImageManager(QtCore.QObject):
def add_image(self, name, path): def add_image(self, name, path):
""" """
Add image to cache if it is not already there. Add image to cache if it is not already there
""" """
log.debug(u'add_image %s:%s' % (name, path)) log.debug(u'add_image %s:%s' % (name, path))
if not name in self._cache: if not name in self._cache:
image = Image(name, path) image = Image()
image.name = name
image.path = path
image.image = resize_image(path, self.width, self.height)
self._cache[name] = image self._cache[name] = image
self._clean_queue.put((image.priority, image))
else: else:
log.debug(u'Image in cache %s:%s' % (name, path)) log.debug(u'Image in cache %s:%s' % (name, path))
# We want only one thread. self._cache_dirty = True
if not self._imageThread.isRunning(): # only one thread please
self._imageThread.start() if not self._thread_running:
self.image_thread.start()
def _process(self): def process(self):
""" """
Controls the processing called from a ``QtCore.QThread``. Controls the processing called from a QThread
""" """
log.debug(u'_process - started') log.debug(u'process - started')
while not self._clean_queue.empty(): self._thread_running = True
self._clean_cache() self.clean_cache()
log.debug(u'_process - ended') # data loaded since we started ?
while self._cache_dirty:
log.debug(u'process - recycle')
self.clean_cache()
self._thread_running = False
log.debug(u'process - ended')
def _clean_cache(self): def clean_cache(self):
""" """
Actually does the work. Actually does the work.
""" """
log.debug(u'_clean_cache') log.debug(u'clean_cache')
image = self._clean_queue.get()[1] # we will clean the cache now
# Generate the QImage for the image. self._cache_dirty = False
if image.image is None: for key in self._cache.keys():
image.image = resize_image(image.path, self.width, self.height) image = self._cache[key]
# If the priority is not urgent, then set the priority to low and if image.dirty:
# do not start to generate the byte stream.
if image.priority != Priority.Urgent:
self._clean_queue.remove((image.priority, image))
image.priority = Priority.Low
self._clean_queue.put((image.priority, image))
return
# Generate the byte stream for the image.
if image.image_bytes is None:
image.image_bytes = image_to_byte(image.image) image.image_bytes = image_to_byte(image.image)
image.dirty = False