forked from openlp/openlp
- stop the imageManager when closing OpenLP
bzr-revno: 1980
This commit is contained in:
commit
a12dc37d70
@ -163,143 +163,144 @@ class ImageManager(QtCore.QObject):
|
||||
|
||||
def __init__(self):
|
||||
QtCore.QObject.__init__(self)
|
||||
current_screen = ScreenList().current
|
||||
self.width = current_screen[u'size'].width()
|
||||
self.height = current_screen[u'size'].height()
|
||||
currentScreen = ScreenList().current
|
||||
self.width = currentScreen[u'size'].width()
|
||||
self.height = currentScreen[u'size'].height()
|
||||
self._cache = {}
|
||||
self._imageThread = ImageThread(self)
|
||||
self._conversion_queue = PriorityQueue()
|
||||
self.imageThread = ImageThread(self)
|
||||
self._conversionQueue = PriorityQueue()
|
||||
self.stopManager = False
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'config_updated'), self.process_updates)
|
||||
QtCore.SIGNAL(u'config_updated'), self.processUpdates)
|
||||
|
||||
def update_display(self):
|
||||
def updateDisplay(self):
|
||||
"""
|
||||
Screen has changed size so rebuild the cache to new size.
|
||||
"""
|
||||
log.debug(u'update_display')
|
||||
current_screen = ScreenList().current
|
||||
self.width = current_screen[u'size'].width()
|
||||
self.height = current_screen[u'size'].height()
|
||||
log.debug(u'updateDisplay')
|
||||
currentScreen = ScreenList().current
|
||||
self.width = currentScreen[u'size'].width()
|
||||
self.height = currentScreen[u'size'].height()
|
||||
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||
# stream to None.
|
||||
for image in self._cache.values():
|
||||
self._reset_image(image)
|
||||
self._resetImage(image)
|
||||
|
||||
def update_images(self, image_type, background):
|
||||
def updateImages(self, imageType, background):
|
||||
"""
|
||||
Border has changed so update all the images affected.
|
||||
"""
|
||||
log.debug(u'update_images')
|
||||
log.debug(u'updateImages')
|
||||
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||
# stream to None.
|
||||
for image in self._cache.values():
|
||||
if image.source == image_type:
|
||||
if image.source == imageType:
|
||||
image.background = background
|
||||
self._reset_image(image)
|
||||
self._resetImage(image)
|
||||
|
||||
def update_image(self, name, image_type, background):
|
||||
def updateImage(self, name, imageType, background):
|
||||
"""
|
||||
Border has changed so update the image affected.
|
||||
"""
|
||||
log.debug(u'update_images')
|
||||
log.debug(u'updateImage')
|
||||
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||
# stream to None.
|
||||
for image in self._cache.values():
|
||||
if image.source == image_type and image.name == name:
|
||||
if image.source == imageType and image.name == name:
|
||||
image.background = background
|
||||
self._reset_image(image)
|
||||
self._resetImage(image)
|
||||
|
||||
def _reset_image(self, image):
|
||||
def _resetImage(self, image):
|
||||
image.image = None
|
||||
image.image_bytes = None
|
||||
self._conversion_queue.modify_priority(image, Priority.Normal)
|
||||
self._conversionQueue.modify_priority(image, Priority.Normal)
|
||||
|
||||
def process_updates(self):
|
||||
def processUpdates(self):
|
||||
"""
|
||||
Flush the queue to updated any data to update
|
||||
"""
|
||||
# We want only one thread.
|
||||
if not self._imageThread.isRunning():
|
||||
self._imageThread.start()
|
||||
if not self.imageThread.isRunning():
|
||||
self.imageThread.start()
|
||||
|
||||
def get_image(self, name):
|
||||
def getImage(self, name):
|
||||
"""
|
||||
Return the ``QImage`` from the cache. If not present wait for the
|
||||
background thread to process it.
|
||||
"""
|
||||
log.debug(u'get_image %s' % name)
|
||||
log.debug(u'getImage %s' % name)
|
||||
image = self._cache[name]
|
||||
if image.image is None:
|
||||
self._conversion_queue.modify_priority(image, Priority.High)
|
||||
self._conversionQueue.modify_priority(image, Priority.High)
|
||||
# make sure we are running and if not give it a kick
|
||||
self.process_updates()
|
||||
self.processUpdates()
|
||||
while image.image is None:
|
||||
log.debug(u'get_image - waiting')
|
||||
log.debug(u'getImage - waiting')
|
||||
time.sleep(0.1)
|
||||
elif image.image_bytes is None:
|
||||
# Set the priority to Low, because the image was requested but the
|
||||
# byte stream was not generated yet. However, we only need to do
|
||||
# this, when the image was generated before it was requested
|
||||
# (otherwise this is already taken care of).
|
||||
self._conversion_queue.modify_priority(image, Priority.Low)
|
||||
self._conversionQueue.modify_priority(image, Priority.Low)
|
||||
return image.image
|
||||
|
||||
def get_image_bytes(self, name):
|
||||
def getImageBytes(self, name):
|
||||
"""
|
||||
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)
|
||||
log.debug(u'getImageBytes %s' % name)
|
||||
image = self._cache[name]
|
||||
if image.image_bytes is None:
|
||||
self._conversion_queue.modify_priority(image, Priority.Urgent)
|
||||
self._conversionQueue.modify_priority(image, Priority.Urgent)
|
||||
# make sure we are running and if not give it a kick
|
||||
self.process_updates()
|
||||
self.processUpdates()
|
||||
while image.image_bytes is None:
|
||||
log.debug(u'get_image_bytes - waiting')
|
||||
log.debug(u'getImageBytes - waiting')
|
||||
time.sleep(0.1)
|
||||
return image.image_bytes
|
||||
|
||||
def del_image(self, name):
|
||||
def deleteImage(self, name):
|
||||
"""
|
||||
Delete the Image from the cache.
|
||||
"""
|
||||
log.debug(u'del_image %s' % name)
|
||||
log.debug(u'deleteImage %s' % name)
|
||||
if name in self._cache:
|
||||
self._conversion_queue.remove(self._cache[name])
|
||||
self._conversionQueue.remove(self._cache[name])
|
||||
del self._cache[name]
|
||||
|
||||
def add_image(self, name, path, source, background):
|
||||
def addImage(self, name, path, source, background):
|
||||
"""
|
||||
Add image to cache if it is not already there.
|
||||
"""
|
||||
log.debug(u'add_image %s:%s' % (name, path))
|
||||
log.debug(u'addImage %s:%s' % (name, path))
|
||||
if not name in self._cache:
|
||||
image = Image(name, path, source, background)
|
||||
self._cache[name] = image
|
||||
self._conversion_queue.put(
|
||||
self._conversionQueue.put(
|
||||
(image.priority, image.secondary_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()
|
||||
if not self.imageThread.isRunning():
|
||||
self.imageThread.start()
|
||||
|
||||
def _process(self):
|
||||
"""
|
||||
Controls the processing called from a ``QtCore.QThread``.
|
||||
"""
|
||||
log.debug(u'_process - started')
|
||||
while not self._conversion_queue.empty():
|
||||
self._process_cache()
|
||||
while not self._conversionQueue.empty() and not self.stopManager:
|
||||
self._processCache()
|
||||
log.debug(u'_process - ended')
|
||||
|
||||
def _process_cache(self):
|
||||
def _processCache(self):
|
||||
"""
|
||||
Actually does the work.
|
||||
"""
|
||||
log.debug(u'_process_cache')
|
||||
image = self._conversion_queue.get()[2]
|
||||
log.debug(u'_processCache')
|
||||
image = self._conversionQueue.get()[2]
|
||||
# Generate the QImage for the image.
|
||||
if image.image is None:
|
||||
image.image = resize_image(image.path, self.width, self.height,
|
||||
@ -307,14 +308,14 @@ class ImageManager(QtCore.QObject):
|
||||
# Set the priority to Lowest and stop here as we need to process
|
||||
# more important images first.
|
||||
if image.priority == Priority.Normal:
|
||||
self._conversion_queue.modify_priority(image, Priority.Lowest)
|
||||
self._conversionQueue.modify_priority(image, Priority.Lowest)
|
||||
return
|
||||
# For image with high priority we set the priority to Low, as the
|
||||
# byte stream might be needed earlier the byte stream of image with
|
||||
# Normal priority. We stop here as we need to process more important
|
||||
# images first.
|
||||
elif image.priority == Priority.High:
|
||||
self._conversion_queue.modify_priority(image, Priority.Low)
|
||||
self._conversionQueue.modify_priority(image, Priority.Low)
|
||||
return
|
||||
# Generate the byte stream for the image.
|
||||
if image.image_bytes is None:
|
||||
|
@ -132,7 +132,7 @@ class Renderer(object):
|
||||
"""
|
||||
# if No file do not update cache
|
||||
if temp_theme.background_filename:
|
||||
self.imageManager.add_image(temp_theme.theme_name,
|
||||
self.imageManager.addImage(temp_theme.theme_name,
|
||||
temp_theme.background_filename, u'theme',
|
||||
QtGui.QColor(temp_theme.background_border_color))
|
||||
|
||||
@ -204,7 +204,7 @@ class Renderer(object):
|
||||
# make big page for theme edit dialog to get line count
|
||||
serviceItem.add_from_text(u'', VERSE_FOR_LINE_COUNT)
|
||||
else:
|
||||
self.imageManager.del_image(theme_data.theme_name)
|
||||
self.imageManager.deleteImage(theme_data.theme_name)
|
||||
serviceItem.add_from_text(u'', VERSE)
|
||||
serviceItem.renderer = self
|
||||
serviceItem.raw_footer = FOOTER
|
||||
|
@ -211,7 +211,7 @@ class ServiceItem(object):
|
||||
self.image_border = background
|
||||
self.service_item_type = ServiceItemType.Image
|
||||
self._raw_frames.append({u'title': title, u'path': path})
|
||||
self.renderer.imageManager.add_image(title, path, u'image',
|
||||
self.renderer.imageManager.addImage(title, path, u'image',
|
||||
self.image_border)
|
||||
self._new_item()
|
||||
|
||||
|
@ -277,7 +277,7 @@ class MainDisplay(Display):
|
||||
"""
|
||||
API for replacement backgrounds so Images are added directly to cache.
|
||||
"""
|
||||
self.imageManager.add_image(name, path, u'image', background)
|
||||
self.imageManager.addImage(name, path, u'image', background)
|
||||
if hasattr(self, u'serviceItem'):
|
||||
self.override[u'image'] = name
|
||||
self.override[u'theme'] = self.serviceItem.themedata.theme_name
|
||||
@ -297,7 +297,7 @@ class MainDisplay(Display):
|
||||
The name of the image to be displayed.
|
||||
"""
|
||||
log.debug(u'image to display')
|
||||
image = self.imageManager.get_image_bytes(name)
|
||||
image = self.imageManager.getImageBytes(name)
|
||||
self.controller.mediaController.video_reset(self.controller)
|
||||
self.displayImage(image)
|
||||
|
||||
@ -382,14 +382,14 @@ class MainDisplay(Display):
|
||||
else:
|
||||
# replace the background
|
||||
background = self.imageManager. \
|
||||
get_image_bytes(self.override[u'image'])
|
||||
getImageBytes(self.override[u'image'])
|
||||
self.setTransparency(self.serviceItem.themedata.background_type ==
|
||||
BackgroundType.to_string(BackgroundType.Transparent))
|
||||
if self.serviceItem.themedata.background_filename:
|
||||
self.serviceItem.bg_image_bytes = self.imageManager. \
|
||||
get_image_bytes(self.serviceItem.themedata.theme_name)
|
||||
getImageBytes(self.serviceItem.themedata.theme_name)
|
||||
if image:
|
||||
image_bytes = self.imageManager.get_image_bytes(image)
|
||||
image_bytes = self.imageManager.getImageBytes(image)
|
||||
else:
|
||||
image_bytes = None
|
||||
html = build_html(self.serviceItem, self.screen, self.isLive,
|
||||
|
@ -30,6 +30,7 @@ import os
|
||||
import sys
|
||||
import shutil
|
||||
from tempfile import gettempdir
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
@ -1121,7 +1122,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
log.debug(u'screenChanged')
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.imageManager.update_display()
|
||||
self.imageManager.updateDisplay()
|
||||
self.renderer.update_display()
|
||||
self.previewController.screenSizeChanged()
|
||||
self.liveController.screenSizeChanged()
|
||||
@ -1140,6 +1141,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
return
|
||||
# If we just did a settings import, close without saving changes.
|
||||
if self.settingsImported:
|
||||
self.cleanUp(False)
|
||||
event.accept()
|
||||
if self.serviceManagerContents.isModified():
|
||||
ret = self.serviceManagerContents.saveModifiedService()
|
||||
@ -1162,8 +1164,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
translate('OpenLP.MainWindow',
|
||||
'Are you sure you want to close OpenLP?'),
|
||||
QtGui.QMessageBox.StandardButtons(
|
||||
QtGui.QMessageBox.Yes |
|
||||
QtGui.QMessageBox.No),
|
||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
|
||||
QtGui.QMessageBox.Yes)
|
||||
if ret == QtGui.QMessageBox.Yes:
|
||||
self.cleanUp()
|
||||
@ -1174,21 +1175,29 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.cleanUp()
|
||||
event.accept()
|
||||
|
||||
def cleanUp(self):
|
||||
def cleanUp(self, save_settings=True):
|
||||
"""
|
||||
Runs all the cleanup code before OpenLP shuts down
|
||||
Runs all the cleanup code before OpenLP shuts down.
|
||||
|
||||
``save_settings``
|
||||
Switch to prevent saving settings. Defaults to **True**.
|
||||
"""
|
||||
self.imageManager.stopManager = True
|
||||
while self.imageManager.imageThread.isRunning():
|
||||
time.sleep(0.1)
|
||||
# Clean temporary files used by services
|
||||
self.serviceManagerContents.cleanUp()
|
||||
if QtCore.QSettings().value(u'advanced/save current plugin',
|
||||
QtCore.QVariant(False)).toBool():
|
||||
QtCore.QSettings().setValue(u'advanced/current media plugin',
|
||||
QtCore.QVariant(self.mediaToolBox.currentIndex()))
|
||||
if save_settings:
|
||||
if QtCore.QSettings().value(u'advanced/save current plugin',
|
||||
QtCore.QVariant(False)).toBool():
|
||||
QtCore.QSettings().setValue(u'advanced/current media plugin',
|
||||
QtCore.QVariant(self.mediaToolBox.currentIndex()))
|
||||
# Call the cleanup method to shutdown plugins.
|
||||
log.info(u'cleanup plugins')
|
||||
self.pluginManager.finalise_plugins()
|
||||
# Save settings
|
||||
self.saveSettings()
|
||||
if save_settings:
|
||||
# Save settings
|
||||
self.saveSettings()
|
||||
# Close down the display
|
||||
if self.liveController.display:
|
||||
self.liveController.display.close()
|
||||
|
@ -859,8 +859,8 @@ class SlideController(Controller):
|
||||
# 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'])
|
||||
self.imageManager.getImageBytes(frame[u'title'])
|
||||
image = self.imageManager.getImage(frame[u'title'])
|
||||
label.setPixmap(QtGui.QPixmap.fromImage(image))
|
||||
self.previewListWidget.setCellWidget(framenumber, 0, label)
|
||||
slideHeight = width * self.parent().renderer.screen_ratio
|
||||
|
@ -664,9 +664,9 @@ class ThemeManager(QtGui.QWidget):
|
||||
self._writeTheme(theme, image_from, image_to)
|
||||
if theme.background_type == \
|
||||
BackgroundType.to_string(BackgroundType.Image):
|
||||
self.mainwindow.imageManager.update_image(theme.theme_name,
|
||||
self.mainwindow.imageManager.updateImage(theme.theme_name,
|
||||
u'theme', QtGui.QColor(theme.background_border_color))
|
||||
self.mainwindow.imageManager.process_updates()
|
||||
self.mainwindow.imageManager.processUpdates()
|
||||
self.loadThemes()
|
||||
|
||||
def _writeTheme(self, theme, image_from, image_to):
|
||||
|
@ -96,4 +96,4 @@ class ImagePlugin(Plugin):
|
||||
"""
|
||||
background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection
|
||||
+ u'/background color', QtCore.QVariant(u'#000000')))
|
||||
self.liveController.imageManager.update_images(u'image', background)
|
||||
self.liveController.imageManager.updateImages(u'image', background)
|
||||
|
Loading…
Reference in New Issue
Block a user