From 1cc95fddb6dc502a43f9692b900c985ec108fc73 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sun, 12 Jun 2011 17:17:01 +0200 Subject: [PATCH 01/20] general thumb clean ups --- openlp/core/lib/__init__.py | 48 ++++++++++++++++++- openlp/core/lib/mediamanageritem.py | 38 --------------- openlp/core/ui/thememanager.py | 17 +++---- openlp/plugins/images/lib/mediaitem.py | 12 ++--- openlp/plugins/presentations/lib/mediaitem.py | 12 +++-- 5 files changed, 67 insertions(+), 60 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 75bafc5e8..15f40b0e3 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -137,6 +137,52 @@ def image_to_byte(image): # convert to base64 encoding so does not get missed! return byte_array.toBase64() +def create_thumb(image_path, thumb_path, return_icon=True): + """ + Create a thumbnail from the given image path and depending on + ``return_icon`` it returns an icon from this thumb. + + ``image_path`` + The image file to create the icon from. + + ``thumb_path`` + The filename to save the thumbnail to. + + ``return_icon`` + States if an icon should be build and returned from the thumb. Defaults + to ``True``. + """ + ext = os.path.splitext(thumb_path)[1].lower() + reader = QtGui.QImageReader(image_path) + ratio = float(reader.size().width()) / float(reader.size().height()) + reader.setScaledSize(QtCore.QSize(int(ratio * 88), 88)) + thumb = reader.read() + thumb.save(thumb_path, ext[1:]) + if not return_icon: + return + if os.path.exists(thumb_path): + return build_icon(unicode(thumb_path)) + # Fallback for files with animation support. + return build_icon(unicode(image_path)) + +def validate_thumb(image_path, thumb_path): + """ + Validates whether an image's thumb still exists and if is up to date. + **Note**, you must **not** call this function, before checking the + existence of the image. + + ``image_path`` + The path to the image. + + ``thumb_path`` + The path to the thumb. + """ + if not os.path.exists(unicode(thumb_path)): + return False + image_date = os.stat(unicode(image_path)).st_mtime + thumb_date = os.stat(unicode(thumb_path)).st_mtime + return image_date <= thumb_date + def resize_image(image_path, width, height, background=QtCore.Qt.black): """ Resize an image to fit on the current screen. @@ -151,7 +197,7 @@ def resize_image(image_path, width, height, background=QtCore.Qt.black): The new image height. ``background`` - The background colour defaults to black. + The background colour. Defaults to ``QtCore.Qt.black``. """ log.debug(u'resize_image - start') reader = QtGui.QImageReader(image_path) diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index b8f7b28ad..38846fec1 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -374,44 +374,6 @@ class MediaManagerItem(QtGui.QWidget): count += 1 return filelist - def validate(self, image, thumb): - """ - Validates whether an image still exists and, if it does, is the - thumbnail representation of the image up to date. - """ - if not os.path.exists(unicode(image)): - return False - if os.path.exists(thumb): - imageDate = os.stat(unicode(image)).st_mtime - thumbDate = os.stat(unicode(thumb)).st_mtime - # If image has been updated rebuild icon - if imageDate > thumbDate: - self.iconFromFile(image, thumb) - else: - self.iconFromFile(image, thumb) - return True - - def iconFromFile(self, image_path, thumb_path): - """ - Create a thumbnail icon from a given image. - - ``image_path`` - The image file to create the icon from. - - ``thumb_path`` - The filename to save the thumbnail to. - """ - ext = os.path.splitext(thumb_path)[1].lower() - reader = QtGui.QImageReader(image_path) - ratio = float(reader.size().width()) / float(reader.size().height()) - reader.setScaledSize(QtCore.QSize(int(ratio * 88), 88)) - thumb = reader.read() - thumb.save(thumb_path, ext[1:]) - if os.path.exists(thumb_path): - return build_icon(unicode(thumb_path)) - # Fallback for files with animation support. - return build_icon(unicode(image_path)) - def loadList(self, list): raise NotImplementedError(u'MediaManagerItem.loadList needs to be ' u'defined by the plugin') diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 72bdf4558..7ee3ccc88 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -36,7 +36,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, \ Receiver, SettingsManager, translate, check_item_selected, \ - check_directory_exists + check_directory_exists, create_thumb, validate_thumb from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \ BackgroundGradientType from openlp.core.lib.ui import UiStrings, critical_error_message_box @@ -364,7 +364,7 @@ class ThemeManager(QtGui.QWidget): The theme to delete. """ self.themelist.remove(theme) - thumb = theme + u'.png' + thumb = u'%s.png' % theme delete_file(os.path.join(self.path, thumb)) delete_file(os.path.join(self.thumbPath, thumb)) try: @@ -478,15 +478,12 @@ class ThemeManager(QtGui.QWidget): name = textName thumb = os.path.join(self.thumbPath, u'%s.png' % textName) item_name = QtGui.QListWidgetItem(name) - if os.path.exists(thumb): + if validate_thumb(theme, thumb): icon = build_icon(thumb) else: - icon = build_icon(theme) - pixmap = icon.pixmap(QtCore.QSize(88, 50)) - pixmap.save(thumb, u'png') + icon = create_thumb(theme, thumb) item_name.setIcon(icon) - item_name.setData(QtCore.Qt.UserRole, - QtCore.QVariant(textName)) + item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(textName)) self.themeListWidget.addItem(item_name) self.themelist.append(textName) self._pushThemes() @@ -658,9 +655,7 @@ class ThemeManager(QtGui.QWidget): os.unlink(samplepathname) frame.save(samplepathname, u'png') thumb = os.path.join(self.thumbPath, u'%s.png' % name) - icon = build_icon(frame) - pixmap = icon.pixmap(QtCore.QSize(88, 50)) - pixmap.save(thumb, u'png') + create_thumb(samplepathname, thumb, False) log.debug(u'Theme image written to %s', samplepathname) def updatePreviewImages(self): diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 921a52ede..875f5b7fc 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -33,7 +33,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \ SettingsManager, translate, check_item_selected, check_directory_exists, \ - Receiver + Receiver, create_thumb, validate_thumb from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.utils import AppLocation, delete_file, get_images_filter @@ -122,13 +122,13 @@ class ImageMediaItem(MediaManagerItem): self.plugin.formparent.incrementProgressBar() filename = os.path.split(unicode(imageFile))[1] thumb = os.path.join(self.servicePath, filename) - if os.path.exists(thumb): - if self.validate(imageFile, thumb): + if not os.path.exists(imageFile): + icon = build_icon(u':/general/general_delete.png') + else: + if validate_thumb(imageFile, thumb): icon = build_icon(thumb) else: - icon = build_icon(u':/general/general_delete.png') - else: - icon = self.iconFromFile(imageFile, thumb) + icon = create_thumb(imageFile, thumb) item_name = QtGui.QListWidgetItem(filename) item_name.setIcon(icon) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(imageFile)) diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index e138d4ef9..ff515f79b 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -32,7 +32,8 @@ import locale from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \ - translate, check_item_selected, Receiver, ItemCapabilities + translate, check_item_selected, Receiver, ItemCapabilities, create_thumb, \ + validate_thumb from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ media_item_combo_box from openlp.plugins.presentations.lib import MessageListener @@ -190,10 +191,13 @@ class PresentationMediaItem(MediaManagerItem): doc.load_presentation() preview = doc.get_thumbnail_path(1, True) doc.close_presentation() - if preview and self.validate(preview, thumb): - icon = build_icon(thumb) - else: + if not os.path.exists(preview): icon = build_icon(u':/general/general_delete.png') + else: + if validate_thumb(preview, thumb): + icon = build_icon(thumb) + else: + icon = create_thumb(preview, thumb) else: if initialLoad: icon = build_icon(u':/general/general_delete.png') From 900a817cbfca6aa49045f90e41678797ff8f1e79 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sun, 12 Jun 2011 17:59:46 +0200 Subject: [PATCH 02/20] asdf --- openlp/core/lib/__init__.py | 24 ++++++++++++------- .../lib/presentationcontroller.py | 18 ++++++++++---- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 15f40b0e3..24d86ab27 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -137,7 +137,7 @@ def image_to_byte(image): # convert to base64 encoding so does not get missed! return byte_array.toBase64() -def create_thumb(image_path, thumb_path, return_icon=True): +def create_thumb(image_path, thumb_path, return_icon=True, size=None): """ Create a thumbnail from the given image path and depending on ``return_icon`` it returns an icon from this thumb. @@ -151,11 +151,17 @@ def create_thumb(image_path, thumb_path, return_icon=True): ``return_icon`` States if an icon should be build and returned from the thumb. Defaults to ``True``. + + ``size`` + """ ext = os.path.splitext(thumb_path)[1].lower() reader = QtGui.QImageReader(image_path) - ratio = float(reader.size().width()) / float(reader.size().height()) - reader.setScaledSize(QtCore.QSize(int(ratio * 88), 88)) + if size is None: + ratio = float(reader.size().width()) / float(reader.size().height()) + reader.setScaledSize(QtCore.QSize(int(ratio * 88), 88)) + else: + reader.setScaledSize(size) thumb = reader.read() thumb.save(thumb_path, ext[1:]) if not return_icon: @@ -165,21 +171,21 @@ def create_thumb(image_path, thumb_path, return_icon=True): # Fallback for files with animation support. return build_icon(unicode(image_path)) -def validate_thumb(image_path, thumb_path): +def validate_thumb(file_path, thumb_path): """ - Validates whether an image's thumb still exists and if is up to date. + Validates whether an file's thumb still exists and if is up to date. **Note**, you must **not** call this function, before checking the - existence of the image. + existence of the file. - ``image_path`` - The path to the image. + ``file_path`` + The path to the file. The file must exist! ``thumb_path`` The path to the thumb. """ if not os.path.exists(unicode(thumb_path)): return False - image_date = os.stat(unicode(image_path)).st_mtime + image_date = os.stat(unicode(file_path)).st_mtime thumb_date = os.stat(unicode(thumb_path)).st_mtime return image_date <= thumb_date diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index 63bd44cc4..de138a6e1 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -31,7 +31,7 @@ import shutil from PyQt4 import QtCore -from openlp.core.lib import Receiver, resize_image +from openlp.core.lib import Receiver, create_thumb, resize_image, validate_thumb from openlp.core.utils import AppLocation log = logging.getLogger(__name__) @@ -149,11 +149,15 @@ class PresentationDocument(object): recent than the powerpoint """ lastimage = self.get_thumbnail_path(self.get_slide_count(), True) + a = validate_thumb(self.filepath, lastimage) if not (lastimage and os.path.isfile(lastimage)): return False imgdate = os.stat(lastimage).st_mtime pptdate = os.stat(self.filepath).st_mtime - return imgdate >= pptdate + #return imgdate >= pptdate + d = imgdate >= pptdate + print a, d + return a def close_presentation(self): """ @@ -245,9 +249,15 @@ class PresentationDocument(object): """ if self.check_thumbnails(): return + import time + import datetime + start = time.time() if os.path.isfile(file): - img = resize_image(file, 320, 240) - img.save(self.get_thumbnail_path(idx, False)) + size = QtCore.QSize(320, 240) + create_thumb(file, self.get_thumbnail_path(idx, False), False, size) +# img = resize_image(file, 320, 240) +# img.save(self.get_thumbnail_path(idx, False)) + print unicode(datetime.timedelta(seconds=time.time() - start)) def get_thumbnail_path(self, slide_no, check_exists): """ From dbef87021c0a268d9a5637360d72b0ef9d78366d Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 21 Jun 2011 12:10:53 +0200 Subject: [PATCH 03/20] minor clean ups; do not create qimage and then convert to qpixmap, instad create qpixmap directly --- openlp/core/ui/slidecontroller.py | 4 ++-- openlp/plugins/presentations/lib/mediaitem.py | 2 +- openlp/plugins/presentations/lib/presentationcontroller.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 30341b9dd..5ea2c5f23 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -625,14 +625,14 @@ class SlideController(QtGui.QWidget): label.setMargin(4) label.setScaledContents(True) if self.serviceItem.is_command(): - image = QtGui.QImage(frame[u'image']) + label.setPixmap(QtGui.QPixmap(frame[u'image'])) else: # If current slide set background to image if framenumber == slideno: self.serviceItem.bg_image_bytes = \ self.imageManager.get_image_bytes(frame[u'title']) image = self.imageManager.get_image(frame[u'title']) - label.setPixmap(QtGui.QPixmap.fromImage(image)) + label.setPixmap(QtGui.QPixmap.fromImage(image)) self.previewListWidget.setCellWidget(framenumber, 0, label) slideHeight = width * self.parent().renderer.screen_ratio row += 1 diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 5e14a88eb..e0bc1be0d 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -191,7 +191,7 @@ class PresentationMediaItem(MediaManagerItem): doc.load_presentation() preview = doc.get_thumbnail_path(1, True) doc.close_presentation() - if not os.path.exists(preview): + if not (preview and os.path.exists(preview)): icon = build_icon(u':/general/general_delete.png') else: if validate_thumb(preview, thumb): diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index f0588e1bc..c26396229 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -149,7 +149,7 @@ class PresentationDocument(object): the powerpoint file. """ lastimage = self.get_thumbnail_path(self.get_slide_count(), True) - if not os.path.isfile(lastimage): + if not (lastimage and os.path.isfile(lastimage)): return False return validate_thumb(self.filepath, lastimage) From 11cb39d2dc743953976dcd809ce8e82a9c1213d5 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 21 Jun 2011 13:37:28 +0200 Subject: [PATCH 04/20] resize image in the thread not when adding the image --- openlp/core/lib/imagemanager.py | 43 +++++++++++++++++-------------- openlp/core/ui/slidecontroller.py | 6 +++++ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index d89cefccc..88def49e4 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -53,15 +53,17 @@ class ImageThread(QtCore.QThread): """ Run the thread. """ - self.imageManager.process() + self.imageManager._process() class Image(object): - name = '' - path = '' - dirty = True - image = None - image_bytes = None + def __init__(self, name='', path=''): + self.name = name + self.path = path + self.dirty = True + self.image = None + self.image_bytes = None + self.priority = False class ImageManager(QtCore.QObject): @@ -92,7 +94,6 @@ class ImageManager(QtCore.QObject): for key in self._cache.keys(): image = self._cache[key] image.dirty = True - image.image = resize_image(image.path, self.width, self.height) self._cache_dirty = True # only one thread please if not self._thread_running: @@ -103,6 +104,10 @@ class ImageManager(QtCore.QObject): Return the Qimage from the cache """ log.debug(u'get_image %s' % name) + if not self._cache[name].image_bytes: + while self._cache[name].dirty: + log.debug(u'get_image - waiting') + time.sleep(0.1) return self._cache[name].image def get_image_bytes(self, name): @@ -131,10 +136,7 @@ class ImageManager(QtCore.QObject): """ log.debug(u'add_image %s:%s' % (name, path)) if not name in self._cache: - image = Image() - image.name = name - image.path = path - image.image = resize_image(path, self.width, self.height) + image = Image(name, path) self._cache[name] = image else: log.debug(u'Image in cache %s:%s' % (name, path)) @@ -143,29 +145,30 @@ class ImageManager(QtCore.QObject): if not self._thread_running: self.image_thread.start() - def process(self): + def _process(self): """ - Controls the processing called from a QThread + Controls the processing called from a ``QtCore.QThread``. """ - log.debug(u'process - started') + log.debug(u'_process - started') self._thread_running = True - self.clean_cache() + self._clean_cache() # data loaded since we started ? while self._cache_dirty: - log.debug(u'process - recycle') - self.clean_cache() + log.debug(u'_process - recycle') + self._clean_cache() self._thread_running = False - log.debug(u'process - ended') + log.debug(u'_process - ended') - def clean_cache(self): + def _clean_cache(self): """ Actually does the work. """ - log.debug(u'clean_cache') + log.debug(u'_clean_cache') # we will clean the cache now self._cache_dirty = False for key in self._cache.keys(): image = self._cache[key] if image.dirty: + image.image = resize_image(image.path, self.width, self.height) image.image_bytes = image_to_byte(image.image) image.dirty = False diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 5ea2c5f23..44dc5f3de 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -582,6 +582,9 @@ class SlideController(QtGui.QWidget): Loads a ServiceItem into the system from ServiceManager Display the slide number passed """ + import time + import datetime + start = time.time() log.debug(u'processManagerItem live = %s' % self.isLive) self.onStopLoop() old_item = self.serviceItem @@ -631,7 +634,9 @@ class SlideController(QtGui.QWidget): if framenumber == slideno: self.serviceItem.bg_image_bytes = \ self.imageManager.get_image_bytes(frame[u'title']) + print u' start', frame[u'title'] image = self.imageManager.get_image(frame[u'title']) + print u' end', frame[u'title'] label.setPixmap(QtGui.QPixmap.fromImage(image)) self.previewListWidget.setCellWidget(framenumber, 0, label) slideHeight = width * self.parent().renderer.screen_ratio @@ -668,6 +673,7 @@ class SlideController(QtGui.QWidget): self.onMediaClose() Receiver.send_message(u'slidecontroller_%s_started' % self.typePrefix, [serviceItem]) + print unicode(datetime.timedelta(seconds=time.time() - start)) def __updatePreviewSelection(self, slideno): """ From 47f5332bc37ec28ccbc7293be8eebf345c4ae85b Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 21 Jun 2011 22:28:22 +0200 Subject: [PATCH 05/20] Initial work on new image queuing (not working) --- openlp/core/lib/imagemanager.py | 92 ++++++++++++++++++++++++------- openlp/core/ui/slidecontroller.py | 2 - 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 88def49e4..a529a4287 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -32,6 +32,7 @@ to wait for the conversion to happen. """ import logging import time +import Queue from PyQt4 import QtCore @@ -55,15 +56,39 @@ class ImageThread(QtCore.QThread): """ self.imageManager._process() +class ProcessingPriority(object): + """ + Enumeration class. + + ``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): def __init__(self, name='', path=''): self.name = name self.path = path - self.dirty = True self.image = None self.image_bytes = None - self.priority = False + self.priority = ProcessingPriority.Normal class ImageManager(QtCore.QObject): @@ -80,7 +105,8 @@ class ImageManager(QtCore.QObject): self._cache = {} self._thread_running = False self._cache_dirty = False - self.image_thread = ImageThread(self) + self._image_thread = ImageThread(self) + self._clean_queue = Queue.PriorityQueue() def update_display(self): """ @@ -91,33 +117,45 @@ class ImageManager(QtCore.QObject): self.width = current_screen[u'size'].width() self.height = current_screen[u'size'].height() # mark the images as dirty for a rebuild + self._clean_queue = Queue.PriorityQueue() for key in self._cache.keys(): image = self._cache[key] - image.dirty = True + image.priority = ProcessingPriority.Normal + image.image = None + image.image_bytes = None + self._clean_queue.put_nowait((image.priority, image)) self._cache_dirty = True # only one thread please if not self._thread_running: - self.image_thread.start() + self._image_thread.start() def get_image(self, name): """ Return the Qimage from the cache """ + print u'get_image:', name log.debug(u'get_image %s' % name) - if not self._cache[name].image_bytes: - while self._cache[name].dirty: + image = self._cache[name] + if image.image_bytes is None: + image.priority = ProcessingPriority.High + self._clean_queue.put_nowait((image.priority, image)) + while image.image_bytes is None: log.debug(u'get_image - waiting') time.sleep(0.1) - return self._cache[name].image + return image.image def get_image_bytes(self, name): """ Returns the byte string for an image If not present wait for the background thread to process it. """ + print u'get_image_bytes:', name log.debug(u'get_image_bytes %s' % name) - if not self._cache[name].image_bytes: - while self._cache[name].dirty: + image = self._cache[name] + if image.image_bytes is None: + image.priority = ProcessingPriority.Urgent + self._clean_queue.put_nowait((image.priority, image)) + while self._cache[name].image_bytes is None: log.debug(u'get_image_bytes - waiting') time.sleep(0.1) return self._cache[name].image_bytes @@ -138,12 +176,13 @@ class ImageManager(QtCore.QObject): if not name in self._cache: image = Image(name, path) self._cache[name] = image + self._clean_queue.put_nowait((image.priority, image)) else: log.debug(u'Image in cache %s:%s' % (name, path)) self._cache_dirty = True # only one thread please if not self._thread_running: - self.image_thread.start() + self._image_thread.start() def _process(self): """ @@ -152,7 +191,7 @@ class ImageManager(QtCore.QObject): log.debug(u'_process - started') self._thread_running = True self._clean_cache() - # data loaded since we started ? + # data loaded since we started? while self._cache_dirty: log.debug(u'_process - recycle') self._clean_cache() @@ -164,11 +203,24 @@ class ImageManager(QtCore.QObject): Actually does the work. """ log.debug(u'_clean_cache') - # we will clean the cache now - self._cache_dirty = False - for key in self._cache.keys(): - image = self._cache[key] - if image.dirty: - image.image = resize_image(image.path, self.width, self.height) - image.image_bytes = image_to_byte(image.image) - image.dirty = False + if self._clean_queue.empty(): + print u'empty' + self._cache_dirty = False + return + image = self._clean_queue.get_nowait()[1] + if image.image is None: + print u'processing (image):', image.name, image.priority + image.image = resize_image(image.path, self.width, self.height) + if image.priority == ProcessingPriority.Urgent: + image.priority = ProcessingPriority.High + elif image.priority == ProcessingPriority.High: + image.priority = ProcessingPriority.Normal + else: + image.priority = ProcessingPriority.Low + self._clean_queue.put_nowait((image.priority, image)) + self._clean_queue.task_done() + return + if image.image_bytes is None: + print u'processing (bytes):', image.name, image.priority + image.image_bytes = image_to_byte(image.image) + self._clean_queue.task_done() diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 44dc5f3de..821bed9b3 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -634,9 +634,7 @@ class SlideController(QtGui.QWidget): if framenumber == slideno: self.serviceItem.bg_image_bytes = \ self.imageManager.get_image_bytes(frame[u'title']) - print u' start', frame[u'title'] image = self.imageManager.get_image(frame[u'title']) - print u' end', frame[u'title'] label.setPixmap(QtGui.QPixmap.fromImage(image)) self.previewListWidget.setCellWidget(framenumber, 0, label) slideHeight = width * self.parent().renderer.screen_ratio From 67a3a6dc08bddbd40220981446d18018ab344341 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 21 Jun 2011 22:31:46 +0200 Subject: [PATCH 06/20] added missing line --- openlp/core/lib/imagemanager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index a529a4287..d073728c2 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -56,6 +56,7 @@ class ImageThread(QtCore.QThread): """ self.imageManager._process() + class ProcessingPriority(object): """ Enumeration class. From 6f88ccb006e721bcb9f02ebb6a2a523d0198ed0f Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 21 Jun 2011 23:03:58 +0200 Subject: [PATCH 07/20] some fixes --- openlp/core/lib/imagemanager.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index d073728c2..bc4cb8f5a 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -137,10 +137,10 @@ class ImageManager(QtCore.QObject): print u'get_image:', name log.debug(u'get_image %s' % name) image = self._cache[name] - if image.image_bytes is None: + if image.image is None: image.priority = ProcessingPriority.High self._clean_queue.put_nowait((image.priority, image)) - while image.image_bytes is None: + while image.image is None: log.debug(u'get_image - waiting') time.sleep(0.1) return image.image @@ -156,10 +156,10 @@ class ImageManager(QtCore.QObject): if image.image_bytes is None: image.priority = ProcessingPriority.Urgent self._clean_queue.put_nowait((image.priority, image)) - while self._cache[name].image_bytes is None: + while image.image_bytes is None: log.debug(u'get_image_bytes - waiting') time.sleep(0.1) - return self._cache[name].image_bytes + return image.image_bytes def del_image(self, name): """ @@ -212,13 +212,16 @@ class ImageManager(QtCore.QObject): if image.image is None: print u'processing (image):', image.name, image.priority image.image = resize_image(image.path, self.width, self.height) - if image.priority == ProcessingPriority.Urgent: - image.priority = ProcessingPriority.High - elif image.priority == ProcessingPriority.High: - image.priority = ProcessingPriority.Normal - else: - image.priority = ProcessingPriority.Low - self._clean_queue.put_nowait((image.priority, image)) + self._clean_queue.task_done() + if image.priority != ProcessingPriority.Urgent: + if image.priority == ProcessingPriority.High: + image.priority = ProcessingPriority.Normal + else: + image.priority = ProcessingPriority.Low + self._clean_queue.put_nowait((image.priority, image)) + return + if image.priority not in [ProcessingPriority.Urgent, + ProcessingPriority.Low]: self._clean_queue.task_done() return if image.image_bytes is None: From e268b963519206b953012a31661c3cef8f06603c Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 21 Jun 2011 23:19:29 +0200 Subject: [PATCH 08/20] fixed crash --- openlp/core/lib/imagemanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index bc4cb8f5a..9c67d4593 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -219,7 +219,7 @@ class ImageManager(QtCore.QObject): else: image.priority = ProcessingPriority.Low self._clean_queue.put_nowait((image.priority, image)) - return + return if image.priority not in [ProcessingPriority.Urgent, ProcessingPriority.Low]: self._clean_queue.task_done() From bf1c643caa3379916f4dcfa067aa37ea52188d25 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 21 Jun 2011 23:24:27 +0200 Subject: [PATCH 09/20] use qt variable instead --- openlp/core/lib/imagemanager.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 9c67d4593..a056a783b 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -104,7 +104,6 @@ class ImageManager(QtCore.QObject): self.width = current_screen[u'size'].width() self.height = current_screen[u'size'].height() self._cache = {} - self._thread_running = False self._cache_dirty = False self._image_thread = ImageThread(self) self._clean_queue = Queue.PriorityQueue() @@ -127,7 +126,7 @@ class ImageManager(QtCore.QObject): self._clean_queue.put_nowait((image.priority, image)) self._cache_dirty = True # only one thread please - if not self._thread_running: + if not self._image_thread.isRunning(): self._image_thread.start() def get_image(self, name): @@ -182,7 +181,7 @@ class ImageManager(QtCore.QObject): log.debug(u'Image in cache %s:%s' % (name, path)) self._cache_dirty = True # only one thread please - if not self._thread_running: + if not self._image_thread.isRunning(): self._image_thread.start() def _process(self): @@ -190,13 +189,11 @@ class ImageManager(QtCore.QObject): Controls the processing called from a ``QtCore.QThread``. """ log.debug(u'_process - started') - self._thread_running = True self._clean_cache() # 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): From 9a58a0eca5157ea3b5658ad123feefe4e11ac3a7 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 22 Jun 2011 09:56:08 +0200 Subject: [PATCH 10/20] improved/fixed queue order --- openlp/core/lib/imagemanager.py | 43 +++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index a056a783b..ce187e7b2 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -92,6 +92,18 @@ class Image(object): self.priority = ProcessingPriority.Normal +class PriorityQueue(Queue.PriorityQueue): + """ + Customised ``Queue.PriorityQueue``. + """ +# def put(self, image): +# self._put((image.priority, image)) + + def remove(self, item): + if item in self.queue: + self.queue.remove(item) + + class ImageManager(QtCore.QObject): """ Image Manager handles the conversion and sizing of images. @@ -106,7 +118,7 @@ class ImageManager(QtCore.QObject): self._cache = {} self._cache_dirty = False self._image_thread = ImageThread(self) - self._clean_queue = Queue.PriorityQueue() + self._clean_queue = PriorityQueue() def update_display(self): """ @@ -123,7 +135,7 @@ class ImageManager(QtCore.QObject): image.priority = ProcessingPriority.Normal image.image = None image.image_bytes = None - self._clean_queue.put_nowait((image.priority, image)) + self._clean_queue.put((image.priority, image)) self._cache_dirty = True # only one thread please if not self._image_thread.isRunning(): @@ -137,8 +149,9 @@ class ImageManager(QtCore.QObject): log.debug(u'get_image %s' % name) image = self._cache[name] if image.image is None: + self._clean_queue.remove((image.priority, image)) image.priority = ProcessingPriority.High - self._clean_queue.put_nowait((image.priority, image)) + self._clean_queue.put((image.priority, image)) while image.image is None: log.debug(u'get_image - waiting') time.sleep(0.1) @@ -153,8 +166,9 @@ class ImageManager(QtCore.QObject): log.debug(u'get_image_bytes %s' % name) image = self._cache[name] if image.image_bytes is None: + self._clean_queue.remove((image.priority, image)) image.priority = ProcessingPriority.Urgent - self._clean_queue.put_nowait((image.priority, image)) + self._clean_queue.put((image.priority, image)) while image.image_bytes is None: log.debug(u'get_image_bytes - waiting') time.sleep(0.1) @@ -176,7 +190,7 @@ class ImageManager(QtCore.QObject): if not name in self._cache: image = Image(name, path) self._cache[name] = image - self._clean_queue.put_nowait((image.priority, image)) + self._clean_queue.put((image.priority, image)) else: log.debug(u'Image in cache %s:%s' % (name, path)) self._cache_dirty = True @@ -205,23 +219,22 @@ class ImageManager(QtCore.QObject): print u'empty' self._cache_dirty = False return - image = self._clean_queue.get_nowait()[1] + image = self._clean_queue.get()[1] if image.image is None: print u'processing (image):', image.name, image.priority image.image = resize_image(image.path, self.width, self.height) - self._clean_queue.task_done() + #self._clean_queue.task_done() if image.priority != ProcessingPriority.Urgent: - if image.priority == ProcessingPriority.High: - image.priority = ProcessingPriority.Normal - else: - image.priority = ProcessingPriority.Low - self._clean_queue.put_nowait((image.priority, image)) - return + self._clean_queue.task_done() + image.priority = ProcessingPriority.Low + self._clean_queue.put((image.priority, image)) + return if image.priority not in [ProcessingPriority.Urgent, ProcessingPriority.Low]: - self._clean_queue.task_done() + print u'return!', image.name, image.priority + #self._clean_queue.task_done() return if image.image_bytes is None: print u'processing (bytes):', image.name, image.priority image.image_bytes = image_to_byte(image.image) - self._clean_queue.task_done() + self._clean_queue.task_done() From b984f61e98ae6ef8915d166841615d400b0bf239 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 22 Jun 2011 10:04:01 +0200 Subject: [PATCH 11/20] clean ups --- openlp/core/lib/imagemanager.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index ce187e7b2..3303a1162 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -57,9 +57,9 @@ class ImageThread(QtCore.QThread): self.imageManager._process() -class ProcessingPriority(object): +class Priority(object): """ - Enumeration class. + Enumeration class for different priorities. ``Low`` Only the image's byte stream has to be generated. Neither the QImage nor @@ -89,17 +89,22 @@ class Image(object): self.path = path self.image = None self.image_bytes = None - self.priority = ProcessingPriority.Normal + self.priority = Priority.Normal class PriorityQueue(Queue.PriorityQueue): """ Customised ``Queue.PriorityQueue``. """ -# def put(self, image): -# self._put((image.priority, image)) - def remove(self, item): + """ + Removes the given ``item`` from the queue.remove + + ``item`` + The item to remove. This should be a tuple:: + + ``(Priority, Image)`` + """ if item in self.queue: self.queue.remove(item) @@ -132,7 +137,7 @@ class ImageManager(QtCore.QObject): self._clean_queue = Queue.PriorityQueue() for key in self._cache.keys(): image = self._cache[key] - image.priority = ProcessingPriority.Normal + image.priority = Priority.Normal image.image = None image.image_bytes = None self._clean_queue.put((image.priority, image)) @@ -150,7 +155,7 @@ class ImageManager(QtCore.QObject): image = self._cache[name] if image.image is None: self._clean_queue.remove((image.priority, image)) - image.priority = ProcessingPriority.High + image.priority = Priority.High self._clean_queue.put((image.priority, image)) while image.image is None: log.debug(u'get_image - waiting') @@ -167,7 +172,7 @@ class ImageManager(QtCore.QObject): image = self._cache[name] if image.image_bytes is None: self._clean_queue.remove((image.priority, image)) - image.priority = ProcessingPriority.Urgent + image.priority = Priority.Urgent self._clean_queue.put((image.priority, image)) while image.image_bytes is None: log.debug(u'get_image_bytes - waiting') @@ -224,13 +229,12 @@ class ImageManager(QtCore.QObject): print u'processing (image):', image.name, image.priority image.image = resize_image(image.path, self.width, self.height) #self._clean_queue.task_done() - if image.priority != ProcessingPriority.Urgent: + if image.priority != Priority.Urgent: self._clean_queue.task_done() - image.priority = ProcessingPriority.Low + image.priority = Priority.Low self._clean_queue.put((image.priority, image)) return - if image.priority not in [ProcessingPriority.Urgent, - ProcessingPriority.Low]: + if image.priority not in [Priority.Urgent, Priority.Low]: print u'return!', image.name, image.priority #self._clean_queue.task_done() return From 7996bb914da25d3b694902ac0041616338bf1808 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 22 Jun 2011 10:14:04 +0200 Subject: [PATCH 12/20] removed not needed code --- openlp/core/lib/imagemanager.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 3303a1162..92e1055d2 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -199,7 +199,7 @@ class ImageManager(QtCore.QObject): else: log.debug(u'Image in cache %s:%s' % (name, path)) self._cache_dirty = True - # only one thread please + # We want only one thread. if not self._image_thread.isRunning(): self._image_thread.start() @@ -208,8 +208,6 @@ class ImageManager(QtCore.QObject): Controls the processing called from a ``QtCore.QThread``. """ log.debug(u'_process - started') - self._clean_cache() - # data loaded since we started? while self._cache_dirty: log.debug(u'_process - recycle') self._clean_cache() @@ -228,16 +226,11 @@ class ImageManager(QtCore.QObject): if image.image is None: print u'processing (image):', image.name, image.priority image.image = resize_image(image.path, self.width, self.height) - #self._clean_queue.task_done() if image.priority != Priority.Urgent: self._clean_queue.task_done() image.priority = Priority.Low self._clean_queue.put((image.priority, image)) return - if image.priority not in [Priority.Urgent, Priority.Low]: - print u'return!', image.name, image.priority - #self._clean_queue.task_done() - return if image.image_bytes is None: print u'processing (bytes):', image.name, image.priority image.image_bytes = image_to_byte(image.image) From 87e6a61f19f1ca0adea77dda7cc5f34e8bf116bc Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 22 Jun 2011 10:25:49 +0200 Subject: [PATCH 13/20] clean ups --- openlp/core/lib/imagemanager.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 92e1055d2..30b46dc00 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -98,7 +98,7 @@ class PriorityQueue(Queue.PriorityQueue): """ def remove(self, item): """ - Removes the given ``item`` from the queue.remove + Removes the given ``item`` from the queue. ``item`` The item to remove. This should be a tuple:: @@ -127,14 +127,14 @@ class ImageManager(QtCore.QObject): 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') current_screen = ScreenList.get_instance().current self.width = current_screen[u'size'].width() self.height = current_screen[u'size'].height() - # mark the images as dirty for a rebuild - self._clean_queue = Queue.PriorityQueue() + # Mark the images as dirty for a rebuild. + self._clean_queue = PriorityQueue() for key in self._cache.keys(): image = self._cache[key] image.priority = Priority.Normal @@ -142,13 +142,13 @@ class ImageManager(QtCore.QObject): image.image_bytes = None self._clean_queue.put((image.priority, image)) self._cache_dirty = True - # only one thread please + # We want only one thread. if not self._image_thread.isRunning(): self._image_thread.start() def get_image(self, name): """ - Return the Qimage from the cache + Return the Qimage from the cache. """ print u'get_image:', name log.debug(u'get_image %s' % name) @@ -164,8 +164,8 @@ class ImageManager(QtCore.QObject): def get_image_bytes(self, name): """ - Returns the byte string for an image - If not present wait for the background thread to process it. + Returns the byte string for an image. If not present wait for the + background thread to process it. """ print u'get_image_bytes:', name log.debug(u'get_image_bytes %s' % name) From 63242b4191d8f5bc59360167f17264075a20556a Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 22 Jun 2011 18:13:07 +0200 Subject: [PATCH 14/20] more simplifications --- openlp/core/lib/imagemanager.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 30b46dc00..c282f925e 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -121,7 +121,6 @@ class ImageManager(QtCore.QObject): self.width = current_screen[u'size'].width() self.height = current_screen[u'size'].height() self._cache = {} - self._cache_dirty = False self._image_thread = ImageThread(self) self._clean_queue = PriorityQueue() @@ -141,7 +140,6 @@ class ImageManager(QtCore.QObject): image.image = None image.image_bytes = None self._clean_queue.put((image.priority, image)) - self._cache_dirty = True # We want only one thread. if not self._image_thread.isRunning(): self._image_thread.start() @@ -198,7 +196,6 @@ class ImageManager(QtCore.QObject): self._clean_queue.put((image.priority, image)) else: log.debug(u'Image in cache %s:%s' % (name, path)) - self._cache_dirty = True # We want only one thread. if not self._image_thread.isRunning(): self._image_thread.start() @@ -208,7 +205,7 @@ class ImageManager(QtCore.QObject): Controls the processing called from a ``QtCore.QThread``. """ log.debug(u'_process - started') - while self._cache_dirty: + while not self._clean_queue.empty(): log.debug(u'_process - recycle') self._clean_cache() log.debug(u'_process - ended') @@ -218,10 +215,6 @@ class ImageManager(QtCore.QObject): Actually does the work. """ log.debug(u'_clean_cache') - if self._clean_queue.empty(): - print u'empty' - self._cache_dirty = False - return image = self._clean_queue.get()[1] if image.image is None: print u'processing (image):', image.name, image.priority From 95d24f68b0f7302fa1a64547c4452cef8564db64 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 22 Jun 2011 19:06:35 +0200 Subject: [PATCH 15/20] fixed forgotten lines --- openlp/core/lib/imagemanager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index c282f925e..8f4142a1d 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -206,8 +206,8 @@ class ImageManager(QtCore.QObject): """ log.debug(u'_process - started') while not self._clean_queue.empty(): - log.debug(u'_process - recycle') self._clean_cache() + print u'empty' log.debug(u'_process - ended') def _clean_cache(self): @@ -221,6 +221,7 @@ class ImageManager(QtCore.QObject): image.image = resize_image(image.path, self.width, self.height) if image.priority != Priority.Urgent: self._clean_queue.task_done() + self._clean_queue.remove((image.priority, image)) image.priority = Priority.Low self._clean_queue.put((image.priority, image)) return From 929301b2e8cfe5d530290a923465bc3876da639e Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Fri, 24 Jun 2011 18:12:04 +0200 Subject: [PATCH 16/20] removed test lines --- openlp/core/lib/imagemanager.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 8f4142a1d..3103a7e12 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -148,7 +148,6 @@ class ImageManager(QtCore.QObject): """ Return the Qimage from the cache. """ - print u'get_image:', name log.debug(u'get_image %s' % name) image = self._cache[name] if image.image is None: @@ -165,7 +164,6 @@ class ImageManager(QtCore.QObject): Returns the byte string for an image. If not present wait for the background thread to process it. """ - print u'get_image_bytes:', name log.debug(u'get_image_bytes %s' % name) image = self._cache[name] if image.image_bytes is None: @@ -207,7 +205,6 @@ class ImageManager(QtCore.QObject): log.debug(u'_process - started') while not self._clean_queue.empty(): self._clean_cache() - print u'empty' log.debug(u'_process - ended') def _clean_cache(self): @@ -217,15 +214,11 @@ class ImageManager(QtCore.QObject): log.debug(u'_clean_cache') image = self._clean_queue.get()[1] if image.image is None: - print u'processing (image):', image.name, image.priority image.image = resize_image(image.path, self.width, self.height) if image.priority != Priority.Urgent: - self._clean_queue.task_done() self._clean_queue.remove((image.priority, image)) image.priority = Priority.Low self._clean_queue.put((image.priority, image)) return if image.image_bytes is None: - print u'processing (bytes):', image.name, image.priority image.image_bytes = image_to_byte(image.image) - self._clean_queue.task_done() From 1ff42f59de688c1dc7ee7fd9d7a39e438e8a0f28 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sat, 25 Jun 2011 06:36:43 +0200 Subject: [PATCH 17/20] - added comments - qt name change - remove test lines --- openlp/core/lib/imagemanager.py | 27 ++++++++++++++++----------- openlp/core/ui/slidecontroller.py | 4 ---- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 3103a7e12..bab9748d0 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -121,7 +121,7 @@ class ImageManager(QtCore.QObject): self.width = current_screen[u'size'].width() self.height = current_screen[u'size'].height() self._cache = {} - self._image_thread = ImageThread(self) + self._imageThread = ImageThread(self) self._clean_queue = PriorityQueue() def update_display(self): @@ -132,21 +132,22 @@ class ImageManager(QtCore.QObject): current_screen = ScreenList.get_instance().current self.width = current_screen[u'size'].width() self.height = current_screen[u'size'].height() - # Mark the images as dirty for a rebuild. + # Mark the images as dirty for a rebuild by setting the image and byte + # stream to None. self._clean_queue = PriorityQueue() - for key in self._cache.keys(): - image = self._cache[key] + for key, image in self._cache.iteritems(): image.priority = Priority.Normal image.image = None image.image_bytes = None self._clean_queue.put((image.priority, image)) # We want only one thread. - if not self._image_thread.isRunning(): - self._image_thread.start() + if not self._imageThread.isRunning(): + self._imageThread.start() def get_image(self, name): """ - Return the Qimage from the cache. + Return the ``QImage`` from the cache. If not present wait for the + background thread to process it. """ log.debug(u'get_image %s' % name) image = self._cache[name] @@ -177,7 +178,7 @@ class ImageManager(QtCore.QObject): def del_image(self, name): """ - Delete the Image from the Cache + Delete the Image from the cache. """ log.debug(u'del_image %s' % name) if name in self._cache: @@ -185,7 +186,7 @@ class ImageManager(QtCore.QObject): 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)) if not name in self._cache: @@ -195,8 +196,8 @@ class ImageManager(QtCore.QObject): else: log.debug(u'Image in cache %s:%s' % (name, path)) # We want only one thread. - if not self._image_thread.isRunning(): - self._image_thread.start() + if not self._imageThread.isRunning(): + self._imageThread.start() def _process(self): """ @@ -213,12 +214,16 @@ class ImageManager(QtCore.QObject): """ log.debug(u'_clean_cache') image = self._clean_queue.get()[1] + # Generate the QImage for the image. if image.image is None: image.image = resize_image(image.path, self.width, self.height) + # If the priority is not urgent, then set the priority to low and + # 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) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 821bed9b3..5ea2c5f23 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -582,9 +582,6 @@ class SlideController(QtGui.QWidget): Loads a ServiceItem into the system from ServiceManager Display the slide number passed """ - import time - import datetime - start = time.time() log.debug(u'processManagerItem live = %s' % self.isLive) self.onStopLoop() old_item = self.serviceItem @@ -671,7 +668,6 @@ class SlideController(QtGui.QWidget): self.onMediaClose() Receiver.send_message(u'slidecontroller_%s_started' % self.typePrefix, [serviceItem]) - print unicode(datetime.timedelta(seconds=time.time() - start)) def __updatePreviewSelection(self, slideno): """ From b12fd94f6e23c19702f3f7d141376a503ae87ba2 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sat, 25 Jun 2011 07:35:24 +0200 Subject: [PATCH 18/20] moved image queue changes to an own branch --- openlp/core/lib/imagemanager.py | 170 +++++++++++--------------------- 1 file changed, 56 insertions(+), 114 deletions(-) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index bab9748d0..d89cefccc 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -32,7 +32,6 @@ to wait for the conversion to happen. """ import logging import time -import Queue from PyQt4 import QtCore @@ -54,59 +53,15 @@ class ImageThread(QtCore.QThread): """ Run the thread. """ - 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 + self.imageManager.process() class Image(object): - def __init__(self, name='', path=''): - self.name = name - self.path = path - self.image = None - self.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) + name = '' + path = '' + dirty = True + image = None + image_bytes = None class ImageManager(QtCore.QObject): @@ -121,64 +76,50 @@ class ImageManager(QtCore.QObject): self.width = current_screen[u'size'].width() self.height = current_screen[u'size'].height() self._cache = {} - self._imageThread = ImageThread(self) - self._clean_queue = PriorityQueue() + self._thread_running = False + self._cache_dirty = False + self.image_thread = ImageThread(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') current_screen = ScreenList.get_instance().current self.width = current_screen[u'size'].width() self.height = current_screen[u'size'].height() - # Mark the images as dirty for a rebuild by setting the image and byte - # stream to None. - self._clean_queue = PriorityQueue() - for key, image in self._cache.iteritems(): - image.priority = Priority.Normal - image.image = None - image.image_bytes = None - self._clean_queue.put((image.priority, image)) - # We want only one thread. - if not self._imageThread.isRunning(): - self._imageThread.start() + # mark the images as dirty for a rebuild + for key in self._cache.keys(): + image = self._cache[key] + image.dirty = True + image.image = resize_image(image.path, self.width, self.height) + self._cache_dirty = True + # only one thread please + if not self._thread_running: + self.image_thread.start() def get_image(self, name): """ - Return the ``QImage`` from the cache. If not present wait for the - background thread to process it. + Return the Qimage from the cache """ log.debug(u'get_image %s' % name) - image = self._cache[name] - 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 + return self._cache[name].image def get_image_bytes(self, name): """ - Returns the byte string for an image. If not present wait for the - background thread to process it. + Returns the byte string for an image + If not present wait for the background thread to process it. """ log.debug(u'get_image_bytes %s' % name) - image = self._cache[name] - if image.image_bytes is None: - self._clean_queue.remove((image.priority, image)) - image.priority = Priority.Urgent - self._clean_queue.put((image.priority, image)) - while image.image_bytes is None: + if not self._cache[name].image_bytes: + while self._cache[name].dirty: log.debug(u'get_image_bytes - waiting') time.sleep(0.1) - return image.image_bytes + return self._cache[name].image_bytes def del_image(self, name): """ - Delete the Image from the cache. + Delete the Image from the Cache """ log.debug(u'del_image %s' % name) if name in self._cache: @@ -186,44 +127,45 @@ class ImageManager(QtCore.QObject): 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)) 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._clean_queue.put((image.priority, image)) else: log.debug(u'Image in cache %s:%s' % (name, path)) - # We want only one thread. - if not self._imageThread.isRunning(): - self._imageThread.start() + self._cache_dirty = True + # only one thread please + 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') - while not self._clean_queue.empty(): - self._clean_cache() - log.debug(u'_process - ended') + log.debug(u'process - started') + self._thread_running = True + self.clean_cache() + # 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. """ - log.debug(u'_clean_cache') - image = self._clean_queue.get()[1] - # Generate the QImage for the image. - if image.image is None: - image.image = resize_image(image.path, self.width, self.height) - # If the priority is not urgent, then set the priority to low and - # 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) + log.debug(u'clean_cache') + # we will clean the cache now + self._cache_dirty = False + for key in self._cache.keys(): + image = self._cache[key] + if image.dirty: + image.image_bytes = image_to_byte(image.image) + image.dirty = False From 14e2ce6b644c51b36dd7e0c719246c28dca761b2 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sat, 25 Jun 2011 15:23:49 +0200 Subject: [PATCH 19/20] better comment --- openlp/core/lib/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index f141ef305..80b35ef6f 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -153,7 +153,8 @@ def create_thumb(image_path, thumb_path, return_icon=True, size=None): to ``True``. ``size`` - Defaults to ``None``. + Allows to state a own size to use. Defaults to ``None``, which means + that a default height of 88 is used. """ ext = os.path.splitext(thumb_path)[1].lower() reader = QtGui.QImageReader(image_path) From 4f955f25d7c1c5af4bbed4f8bd45b3891dba908e Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sat, 25 Jun 2011 15:47:46 +0200 Subject: [PATCH 20/20] refactoring --- .../presentations/lib/presentationcontroller.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index c26396229..55823dfd2 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -31,7 +31,8 @@ import shutil from PyQt4 import QtCore -from openlp.core.lib import Receiver, create_thumb, resize_image, validate_thumb +from openlp.core.lib import Receiver, check_directory_exists, create_thumb, \ + resize_image, validate_thumb from openlp.core.utils import AppLocation log = logging.getLogger(__name__) @@ -97,8 +98,7 @@ class PresentationDocument(object): self.slidenumber = 0 self.controller = controller self.filepath = name - if not os.path.isdir(self.get_thumbnail_folder()): - os.mkdir(self.get_thumbnail_folder()) + check_directory_exists(self.get_thumbnail_folder()) def load_presentation(self): """ @@ -385,10 +385,8 @@ class PresentationController(object): AppLocation.get_section_data_path(self.settings_section), u'thumbnails') self.thumbnail_prefix = u'slide' - if not os.path.isdir(self.thumbnail_folder): - os.makedirs(self.thumbnail_folder) - if not os.path.isdir(self.temp_folder): - os.makedirs(self.temp_folder) + check_directory_exists(self.thumbnail_folder) + check_directory_exists(self.temp_folder) def enabled(self): """