forked from openlp/openlp
r1982
This commit is contained in:
commit
328f918c9f
@ -163,143 +163,144 @@ class ImageManager(QtCore.QObject):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
QtCore.QObject.__init__(self)
|
QtCore.QObject.__init__(self)
|
||||||
current_screen = ScreenList().current
|
currentScreen = ScreenList().current
|
||||||
self.width = current_screen[u'size'].width()
|
self.width = currentScreen[u'size'].width()
|
||||||
self.height = current_screen[u'size'].height()
|
self.height = currentScreen[u'size'].height()
|
||||||
self._cache = {}
|
self._cache = {}
|
||||||
self._imageThread = ImageThread(self)
|
self.imageThread = ImageThread(self)
|
||||||
self._conversion_queue = PriorityQueue()
|
self._conversionQueue = PriorityQueue()
|
||||||
|
self.stopManager = False
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
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.
|
Screen has changed size so rebuild the cache to new size.
|
||||||
"""
|
"""
|
||||||
log.debug(u'update_display')
|
log.debug(u'updateDisplay')
|
||||||
current_screen = ScreenList().current
|
currentScreen = ScreenList().current
|
||||||
self.width = current_screen[u'size'].width()
|
self.width = currentScreen[u'size'].width()
|
||||||
self.height = current_screen[u'size'].height()
|
self.height = currentScreen[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 by setting the image and byte
|
||||||
# stream to None.
|
# stream to None.
|
||||||
for image in self._cache.values():
|
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.
|
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
|
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||||
# stream to None.
|
# stream to None.
|
||||||
for image in self._cache.values():
|
for image in self._cache.values():
|
||||||
if image.source == image_type:
|
if image.source == imageType:
|
||||||
image.background = background
|
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.
|
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
|
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||||
# stream to None.
|
# stream to None.
|
||||||
for image in self._cache.values():
|
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
|
image.background = background
|
||||||
self._reset_image(image)
|
self._resetImage(image)
|
||||||
|
|
||||||
def _reset_image(self, image):
|
def _resetImage(self, image):
|
||||||
image.image = None
|
image.image = None
|
||||||
image.image_bytes = 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
|
Flush the queue to updated any data to update
|
||||||
"""
|
"""
|
||||||
# We want only one thread.
|
# We want only one thread.
|
||||||
if not self._imageThread.isRunning():
|
if not self.imageThread.isRunning():
|
||||||
self._imageThread.start()
|
self.imageThread.start()
|
||||||
|
|
||||||
def get_image(self, name):
|
def getImage(self, name):
|
||||||
"""
|
"""
|
||||||
Return the ``QImage`` from the cache. If not present wait for the
|
Return the ``QImage`` from the cache. If not present wait for the
|
||||||
background thread to process it.
|
background thread to process it.
|
||||||
"""
|
"""
|
||||||
log.debug(u'get_image %s' % name)
|
log.debug(u'getImage %s' % name)
|
||||||
image = self._cache[name]
|
image = self._cache[name]
|
||||||
if image.image is None:
|
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
|
# make sure we are running and if not give it a kick
|
||||||
self.process_updates()
|
self.processUpdates()
|
||||||
while image.image is None:
|
while image.image is None:
|
||||||
log.debug(u'get_image - waiting')
|
log.debug(u'getImage - waiting')
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
elif image.image_bytes is None:
|
elif image.image_bytes is None:
|
||||||
# Set the priority to Low, because the image was requested but the
|
# Set the priority to Low, because the image was requested but the
|
||||||
# byte stream was not generated yet. However, we only need to do
|
# byte stream was not generated yet. However, we only need to do
|
||||||
# this, when the image was generated before it was requested
|
# this, when the image was generated before it was requested
|
||||||
# (otherwise this is already taken care of).
|
# (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
|
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
|
Returns the byte string for an image. If not present wait for the
|
||||||
background thread to process it.
|
background thread to process it.
|
||||||
"""
|
"""
|
||||||
log.debug(u'get_image_bytes %s' % name)
|
log.debug(u'getImageBytes %s' % name)
|
||||||
image = self._cache[name]
|
image = self._cache[name]
|
||||||
if image.image_bytes is None:
|
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
|
# make sure we are running and if not give it a kick
|
||||||
self.process_updates()
|
self.processUpdates()
|
||||||
while image.image_bytes is None:
|
while image.image_bytes is None:
|
||||||
log.debug(u'get_image_bytes - waiting')
|
log.debug(u'getImageBytes - waiting')
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
return image.image_bytes
|
return image.image_bytes
|
||||||
|
|
||||||
def del_image(self, name):
|
def deleteImage(self, name):
|
||||||
"""
|
"""
|
||||||
Delete the Image from the cache.
|
Delete the Image from the cache.
|
||||||
"""
|
"""
|
||||||
log.debug(u'del_image %s' % name)
|
log.debug(u'deleteImage %s' % name)
|
||||||
if name in self._cache:
|
if name in self._cache:
|
||||||
self._conversion_queue.remove(self._cache[name])
|
self._conversionQueue.remove(self._cache[name])
|
||||||
del 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.
|
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:
|
if not name in self._cache:
|
||||||
image = Image(name, path, source, background)
|
image = Image(name, path, source, background)
|
||||||
self._cache[name] = image
|
self._cache[name] = image
|
||||||
self._conversion_queue.put(
|
self._conversionQueue.put(
|
||||||
(image.priority, image.secondary_priority, image))
|
(image.priority, image.secondary_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.
|
# We want only one thread.
|
||||||
if not self._imageThread.isRunning():
|
if not self.imageThread.isRunning():
|
||||||
self._imageThread.start()
|
self.imageThread.start()
|
||||||
|
|
||||||
def _process(self):
|
def _process(self):
|
||||||
"""
|
"""
|
||||||
Controls the processing called from a ``QtCore.QThread``.
|
Controls the processing called from a ``QtCore.QThread``.
|
||||||
"""
|
"""
|
||||||
log.debug(u'_process - started')
|
log.debug(u'_process - started')
|
||||||
while not self._conversion_queue.empty():
|
while not self._conversionQueue.empty() and not self.stopManager:
|
||||||
self._process_cache()
|
self._processCache()
|
||||||
log.debug(u'_process - ended')
|
log.debug(u'_process - ended')
|
||||||
|
|
||||||
def _process_cache(self):
|
def _processCache(self):
|
||||||
"""
|
"""
|
||||||
Actually does the work.
|
Actually does the work.
|
||||||
"""
|
"""
|
||||||
log.debug(u'_process_cache')
|
log.debug(u'_processCache')
|
||||||
image = self._conversion_queue.get()[2]
|
image = self._conversionQueue.get()[2]
|
||||||
# Generate the QImage for the image.
|
# Generate the QImage for the image.
|
||||||
if image.image is None:
|
if image.image is None:
|
||||||
image.image = resize_image(image.path, self.width, self.height,
|
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
|
# Set the priority to Lowest and stop here as we need to process
|
||||||
# more important images first.
|
# more important images first.
|
||||||
if image.priority == Priority.Normal:
|
if image.priority == Priority.Normal:
|
||||||
self._conversion_queue.modify_priority(image, Priority.Lowest)
|
self._conversionQueue.modify_priority(image, Priority.Lowest)
|
||||||
return
|
return
|
||||||
# For image with high priority we set the priority to Low, as the
|
# 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
|
# byte stream might be needed earlier the byte stream of image with
|
||||||
# Normal priority. We stop here as we need to process more important
|
# Normal priority. We stop here as we need to process more important
|
||||||
# images first.
|
# images first.
|
||||||
elif image.priority == Priority.High:
|
elif image.priority == Priority.High:
|
||||||
self._conversion_queue.modify_priority(image, Priority.Low)
|
self._conversionQueue.modify_priority(image, Priority.Low)
|
||||||
return
|
return
|
||||||
# Generate the byte stream for the image.
|
# Generate the byte stream for the image.
|
||||||
if image.image_bytes is None:
|
if image.image_bytes is None:
|
||||||
|
@ -55,29 +55,32 @@ class Renderer(object):
|
|||||||
"""
|
"""
|
||||||
log.info(u'Renderer Loaded')
|
log.info(u'Renderer Loaded')
|
||||||
|
|
||||||
def __init__(self, imageManager, themeManager):
|
def __init__(self, image_manager, theme_manager):
|
||||||
"""
|
"""
|
||||||
Initialise the renderer.
|
Initialise the renderer.
|
||||||
|
|
||||||
``imageManager``
|
``image_manager``
|
||||||
A imageManager instance which takes care of e. g. caching and resizing
|
A image_manager instance which takes care of e. g. caching and
|
||||||
images.
|
resizing images.
|
||||||
|
|
||||||
``themeManager``
|
``theme_manager``
|
||||||
The themeManager instance, used to get the current theme details.
|
The theme_manager instance, used to get the current theme details.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Initialisation started')
|
log.debug(u'Initialisation started')
|
||||||
self.themeManager = themeManager
|
self.theme_manager = theme_manager
|
||||||
self.imageManager = imageManager
|
self.image_manager = image_manager
|
||||||
self.screens = ScreenList()
|
self.screens = ScreenList()
|
||||||
self.service_theme = u''
|
self.theme_level = ThemeLevel.Global
|
||||||
self.theme_level = u''
|
self.global_theme_name = u''
|
||||||
self.override_background = None
|
self.service_theme_name = u''
|
||||||
self.theme_data = None
|
self.item_theme_name = u''
|
||||||
self.bg_frame = None
|
|
||||||
self.force_page = False
|
self.force_page = False
|
||||||
self.display = MainDisplay(None, self.imageManager, False, self)
|
self.display = MainDisplay(None, self.image_manager, False, self)
|
||||||
self.display.setup()
|
self.display.setup()
|
||||||
|
self._theme_dimensions = {}
|
||||||
|
self._calculate_default()
|
||||||
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
|
QtCore.SIGNAL(u'theme_update_global'), self.set_global_theme)
|
||||||
|
|
||||||
def update_display(self):
|
def update_display(self):
|
||||||
"""
|
"""
|
||||||
@ -87,88 +90,132 @@ class Renderer(object):
|
|||||||
self._calculate_default()
|
self._calculate_default()
|
||||||
if self.display:
|
if self.display:
|
||||||
self.display.close()
|
self.display.close()
|
||||||
self.display = MainDisplay(None, self.imageManager, False, self)
|
self.display = MainDisplay(None, self.image_manager, False, self)
|
||||||
self.display.setup()
|
self.display.setup()
|
||||||
self.bg_frame = None
|
self._theme_dimensions = {}
|
||||||
self.theme_data = None
|
|
||||||
|
|
||||||
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
|
def update_theme(self, theme_name, old_theme_name=None, only_delete=False):
|
||||||
"""
|
"""
|
||||||
Set the global-level theme and the theme level.
|
This method updates the theme in ``_theme_dimensions`` when a theme
|
||||||
|
has been edited or renamed.
|
||||||
|
|
||||||
``global_theme``
|
``theme_name``
|
||||||
The global-level theme to be set.
|
The current theme name.
|
||||||
|
|
||||||
|
``old_theme_name``
|
||||||
|
The old theme name. Has only to be passed, when the theme has been
|
||||||
|
renamed. Defaults to *None*.
|
||||||
|
|
||||||
|
``only_delete``
|
||||||
|
Only remove the given ``theme_name`` from the ``_theme_dimensions``
|
||||||
|
list. This can be used when a theme is permanently deleted.
|
||||||
|
"""
|
||||||
|
if old_theme_name is not None and \
|
||||||
|
old_theme_name in self._theme_dimensions:
|
||||||
|
del self._theme_dimensions[old_theme_name]
|
||||||
|
if theme_name in self._theme_dimensions:
|
||||||
|
del self._theme_dimensions[theme_name]
|
||||||
|
if not only_delete:
|
||||||
|
self._set_theme(theme_name)
|
||||||
|
|
||||||
|
def _set_theme(self, theme_name):
|
||||||
|
"""
|
||||||
|
Helper method to save theme names and theme data.
|
||||||
|
|
||||||
|
``theme_name``
|
||||||
|
The theme name.
|
||||||
|
"""
|
||||||
|
if theme_name not in self._theme_dimensions:
|
||||||
|
theme_data = self.theme_manager.getThemeData(theme_name)
|
||||||
|
main_rect = self.get_main_rectangle(theme_data)
|
||||||
|
footer_rect = self.get_footer_rectangle(theme_data)
|
||||||
|
self._theme_dimensions[theme_name] = \
|
||||||
|
[theme_data, main_rect, footer_rect]
|
||||||
|
else:
|
||||||
|
theme_data, main_rect, footer_rect = \
|
||||||
|
self._theme_dimensions[theme_name]
|
||||||
|
# if No file do not update cache
|
||||||
|
if theme_data.background_filename:
|
||||||
|
self.image_manager.addImage(theme_data.theme_name,
|
||||||
|
theme_data.background_filename, u'theme',
|
||||||
|
QtGui.QColor(theme_data.background_border_color))
|
||||||
|
|
||||||
|
def pre_render(self, override_theme_data=None):
|
||||||
|
"""
|
||||||
|
Set up the theme to be used before rendering an item.
|
||||||
|
|
||||||
|
``override_theme_data``
|
||||||
|
The theme data should be passed, when we want to use our own theme
|
||||||
|
data, regardless of the theme level. This should for example be used
|
||||||
|
in the theme manager. **Note**, this is **not** to be mixed up with
|
||||||
|
the ``set_item_theme`` method.
|
||||||
|
"""
|
||||||
|
# Just assume we use the global theme.
|
||||||
|
theme_to_use = self.global_theme_name
|
||||||
|
# The theme level is either set to Service or Item. Use the service
|
||||||
|
# theme if one is set. We also have to use the service theme, even when
|
||||||
|
# the theme level is set to Item, because the item does not necessarily
|
||||||
|
# have to have a theme.
|
||||||
|
if self.theme_level != ThemeLevel.Global:
|
||||||
|
# When the theme level is at Service and we actually have a service
|
||||||
|
# theme then use it.
|
||||||
|
if self.service_theme_name:
|
||||||
|
theme_to_use = self.service_theme_name
|
||||||
|
# If we have Item level and have an item theme then use it.
|
||||||
|
if self.theme_level == ThemeLevel.Song and self.item_theme_name:
|
||||||
|
theme_to_use = self.item_theme_name
|
||||||
|
if override_theme_data is None:
|
||||||
|
if theme_to_use not in self._theme_dimensions:
|
||||||
|
self._set_theme(theme_to_use)
|
||||||
|
theme_data, main_rect, footer_rect = \
|
||||||
|
self._theme_dimensions[theme_to_use]
|
||||||
|
else:
|
||||||
|
# Ignore everything and use own theme data.
|
||||||
|
theme_data = override_theme_data
|
||||||
|
main_rect = self.get_main_rectangle(override_theme_data)
|
||||||
|
footer_rect = self.get_footer_rectangle(override_theme_data)
|
||||||
|
self._set_text_rectangle(theme_data, main_rect, footer_rect)
|
||||||
|
return theme_data, self._rect, self._rect_footer
|
||||||
|
|
||||||
|
def set_theme_level(self, theme_level):
|
||||||
|
"""
|
||||||
|
Sets the theme level.
|
||||||
|
|
||||||
``theme_level``
|
``theme_level``
|
||||||
Defaults to ``ThemeLevel.Global``. The theme level, can be
|
The theme level to be used.
|
||||||
``ThemeLevel.Global``, ``ThemeLevel.Service`` or
|
|
||||||
``ThemeLevel.Song``.
|
|
||||||
"""
|
"""
|
||||||
self.global_theme = global_theme
|
|
||||||
self.theme_level = theme_level
|
self.theme_level = theme_level
|
||||||
self.global_theme_data = \
|
|
||||||
self.themeManager.getThemeData(self.global_theme)
|
|
||||||
self.theme_data = None
|
|
||||||
|
|
||||||
def set_service_theme(self, service_theme):
|
def set_global_theme(self, global_theme_name):
|
||||||
|
"""
|
||||||
|
Set the global-level theme name.
|
||||||
|
|
||||||
|
``global_theme_name``
|
||||||
|
The global-level theme's name.
|
||||||
|
"""
|
||||||
|
self._set_theme(global_theme_name)
|
||||||
|
self.global_theme_name = global_theme_name
|
||||||
|
|
||||||
|
def set_service_theme(self, service_theme_name):
|
||||||
"""
|
"""
|
||||||
Set the service-level theme.
|
Set the service-level theme.
|
||||||
|
|
||||||
``service_theme``
|
``service_theme_name``
|
||||||
The service-level theme to be set.
|
The service level theme's name.
|
||||||
"""
|
"""
|
||||||
self.service_theme = service_theme
|
self._set_theme(service_theme_name)
|
||||||
self.theme_data = None
|
self.service_theme_name = service_theme_name
|
||||||
|
|
||||||
def set_override_theme(self, override_theme, override_levels=False):
|
def set_item_theme(self, item_theme_name):
|
||||||
"""
|
"""
|
||||||
Set the appropriate theme depending on the theme level.
|
Set the item-level theme. **Note**, this has to be done for each item we
|
||||||
Called by the service item when building a display frame
|
are rendering.
|
||||||
|
|
||||||
``override_theme``
|
``item_theme_name``
|
||||||
The name of the song-level theme. None means the service
|
The item theme's name.
|
||||||
item wants to use the given value.
|
|
||||||
|
|
||||||
``override_levels``
|
|
||||||
Used to force the theme data passed in to be used.
|
|
||||||
"""
|
"""
|
||||||
log.debug(u'set override theme to %s', override_theme)
|
self._set_theme(item_theme_name)
|
||||||
theme_level = self.theme_level
|
self.item_theme_name = item_theme_name
|
||||||
if override_levels:
|
|
||||||
theme_level = ThemeLevel.Song
|
|
||||||
if theme_level == ThemeLevel.Global:
|
|
||||||
theme = self.global_theme
|
|
||||||
elif theme_level == ThemeLevel.Service:
|
|
||||||
if self.service_theme == u'':
|
|
||||||
theme = self.global_theme
|
|
||||||
else:
|
|
||||||
theme = self.service_theme
|
|
||||||
else:
|
|
||||||
# Images have a theme of -1
|
|
||||||
if override_theme and override_theme != -1:
|
|
||||||
theme = override_theme
|
|
||||||
elif theme_level == ThemeLevel.Song or \
|
|
||||||
theme_level == ThemeLevel.Service:
|
|
||||||
if self.service_theme == u'':
|
|
||||||
theme = self.global_theme
|
|
||||||
else:
|
|
||||||
theme = self.service_theme
|
|
||||||
else:
|
|
||||||
theme = self.global_theme
|
|
||||||
log.debug(u'theme is now %s', theme)
|
|
||||||
# Force the theme to be the one passed in.
|
|
||||||
if override_levels:
|
|
||||||
self.theme_data = override_theme
|
|
||||||
else:
|
|
||||||
self.theme_data = self.themeManager.getThemeData(theme)
|
|
||||||
self._calculate_default()
|
|
||||||
self._build_text_rectangle(self.theme_data)
|
|
||||||
# if No file do not update cache
|
|
||||||
if self.theme_data.background_filename:
|
|
||||||
self.imageManager.add_image(self.theme_data.theme_name,
|
|
||||||
self.theme_data.background_filename, u'theme',
|
|
||||||
QtGui.QColor(self.theme_data.background_border_color))
|
|
||||||
return self._rect, self._rect_footer
|
|
||||||
|
|
||||||
def generate_preview(self, theme_data, force_page=False):
|
def generate_preview(self, theme_data, force_page=False):
|
||||||
"""
|
"""
|
||||||
@ -183,27 +230,31 @@ class Renderer(object):
|
|||||||
log.debug(u'generate preview')
|
log.debug(u'generate preview')
|
||||||
# save value for use in format_slide
|
# save value for use in format_slide
|
||||||
self.force_page = force_page
|
self.force_page = force_page
|
||||||
# set the default image size for previews
|
|
||||||
self._calculate_default()
|
|
||||||
# build a service item to generate preview
|
# build a service item to generate preview
|
||||||
serviceItem = ServiceItem()
|
serviceItem = ServiceItem()
|
||||||
serviceItem.theme = theme_data
|
|
||||||
if self.force_page:
|
if self.force_page:
|
||||||
# make big page for theme edit dialog to get line count
|
# make big page for theme edit dialog to get line count
|
||||||
serviceItem.add_from_text(u'', VERSE_FOR_LINE_COUNT)
|
serviceItem.add_from_text(u'', VERSE_FOR_LINE_COUNT)
|
||||||
else:
|
else:
|
||||||
self.imageManager.del_image(theme_data.theme_name)
|
self.image_manager.deleteImage(theme_data.theme_name)
|
||||||
serviceItem.add_from_text(u'', VERSE)
|
serviceItem.add_from_text(u'', VERSE)
|
||||||
serviceItem.renderer = self
|
serviceItem.renderer = self
|
||||||
serviceItem.raw_footer = FOOTER
|
serviceItem.raw_footer = FOOTER
|
||||||
|
# if No file do not update cache
|
||||||
|
if theme_data.background_filename:
|
||||||
|
self.image_manager.addImage(theme_data.theme_name,
|
||||||
|
theme_data.background_filename, u'theme',
|
||||||
|
QtGui.QColor(theme_data.background_border_color))
|
||||||
|
theme_data, main, footer = self.pre_render(theme_data)
|
||||||
|
serviceItem.themedata = theme_data
|
||||||
|
serviceItem.main = main
|
||||||
|
serviceItem.footer = footer
|
||||||
serviceItem.render(True)
|
serviceItem.render(True)
|
||||||
if not self.force_page:
|
if not self.force_page:
|
||||||
self.display.buildHtml(serviceItem)
|
self.display.buildHtml(serviceItem)
|
||||||
raw_html = serviceItem.get_rendered_frame(0)
|
raw_html = serviceItem.get_rendered_frame(0)
|
||||||
self.display.text(raw_html)
|
self.display.text(raw_html)
|
||||||
preview = self.display.preview()
|
preview = self.display.preview()
|
||||||
# Reset the real screen size for subsequent render requests
|
|
||||||
self._calculate_default()
|
|
||||||
return preview
|
return preview
|
||||||
self.force_page = False
|
self.force_page = False
|
||||||
|
|
||||||
@ -303,52 +354,41 @@ class Renderer(object):
|
|||||||
# 90% is start of footer
|
# 90% is start of footer
|
||||||
self.footer_start = int(self.height * 0.90)
|
self.footer_start = int(self.height * 0.90)
|
||||||
|
|
||||||
def _build_text_rectangle(self, theme):
|
def get_main_rectangle(self, theme_data):
|
||||||
"""
|
|
||||||
Builds a text block using the settings in ``theme``
|
|
||||||
and the size of the display screen.height.
|
|
||||||
Note the system has a 10 pixel border round the screen
|
|
||||||
|
|
||||||
``theme``
|
|
||||||
The theme to build a text block for.
|
|
||||||
"""
|
|
||||||
log.debug(u'_build_text_rectangle')
|
|
||||||
main_rect = self.get_main_rectangle(theme)
|
|
||||||
footer_rect = self.get_footer_rectangle(theme)
|
|
||||||
self._set_text_rectangle(main_rect, footer_rect)
|
|
||||||
|
|
||||||
def get_main_rectangle(self, theme):
|
|
||||||
"""
|
"""
|
||||||
Calculates the placement and size of the main rectangle.
|
Calculates the placement and size of the main rectangle.
|
||||||
|
|
||||||
``theme``
|
``theme_data``
|
||||||
The theme information
|
The theme information
|
||||||
"""
|
"""
|
||||||
if not theme.font_main_override:
|
if not theme_data.font_main_override:
|
||||||
return QtCore.QRect(10, 0, self.width - 20, self.footer_start)
|
return QtCore.QRect(10, 0, self.width, self.footer_start)
|
||||||
else:
|
else:
|
||||||
return QtCore.QRect(theme.font_main_x, theme.font_main_y,
|
return QtCore.QRect(theme_data.font_main_x, theme_data.font_main_y,
|
||||||
theme.font_main_width - 1, theme.font_main_height - 1)
|
theme_data.font_main_width - 1, theme_data.font_main_height - 1)
|
||||||
|
|
||||||
def get_footer_rectangle(self, theme):
|
def get_footer_rectangle(self, theme_data):
|
||||||
"""
|
"""
|
||||||
Calculates the placement and size of the footer rectangle.
|
Calculates the placement and size of the footer rectangle.
|
||||||
|
|
||||||
``theme``
|
``theme_data``
|
||||||
The theme information
|
The theme data.
|
||||||
"""
|
"""
|
||||||
if not theme.font_footer_override:
|
if not theme_data.font_footer_override:
|
||||||
return QtCore.QRect(10, self.footer_start, self.width - 20,
|
return QtCore.QRect(10, self.footer_start, self.width - 20,
|
||||||
self.height - self.footer_start)
|
self.height - self.footer_start)
|
||||||
else:
|
else:
|
||||||
return QtCore.QRect(theme.font_footer_x,
|
return QtCore.QRect(theme_data.font_footer_x,
|
||||||
theme.font_footer_y, theme.font_footer_width - 1,
|
theme_data.font_footer_y, theme_data.font_footer_width - 1,
|
||||||
theme.font_footer_height - 1)
|
theme_data.font_footer_height - 1)
|
||||||
|
|
||||||
def _set_text_rectangle(self, rect_main, rect_footer):
|
def _set_text_rectangle(self, theme_data, rect_main, rect_footer):
|
||||||
"""
|
"""
|
||||||
Sets the rectangle within which text should be rendered.
|
Sets the rectangle within which text should be rendered.
|
||||||
|
|
||||||
|
``theme_data``
|
||||||
|
The theme data.
|
||||||
|
|
||||||
``rect_main``
|
``rect_main``
|
||||||
The main text block.
|
The main text block.
|
||||||
|
|
||||||
@ -360,9 +400,9 @@ class Renderer(object):
|
|||||||
self._rect_footer = rect_footer
|
self._rect_footer = rect_footer
|
||||||
self.page_width = self._rect.width()
|
self.page_width = self._rect.width()
|
||||||
self.page_height = self._rect.height()
|
self.page_height = self._rect.height()
|
||||||
if self.theme_data.font_main_shadow:
|
if theme_data.font_main_shadow:
|
||||||
self.page_width -= int(self.theme_data.font_main_shadow_size)
|
self.page_width -= int(theme_data.font_main_shadow_size)
|
||||||
self.page_height -= int(self.theme_data.font_main_shadow_size)
|
self.page_height -= int(theme_data.font_main_shadow_size)
|
||||||
self.web = QtWebKit.QWebView()
|
self.web = QtWebKit.QWebView()
|
||||||
self.web.setVisible(False)
|
self.web.setVisible(False)
|
||||||
self.web.resize(self.page_width, self.page_height)
|
self.web.resize(self.page_width, self.page_height)
|
||||||
@ -380,8 +420,8 @@ class Renderer(object):
|
|||||||
</script><style>*{margin: 0; padding: 0; border: 0;}
|
</script><style>*{margin: 0; padding: 0; border: 0;}
|
||||||
#main {position: absolute; top: 0px; %s %s}</style></head><body>
|
#main {position: absolute; top: 0px; %s %s}</style></head><body>
|
||||||
<div id="main"></div></body></html>""" % \
|
<div id="main"></div></body></html>""" % \
|
||||||
(build_lyrics_format_css(self.theme_data, self.page_width,
|
(build_lyrics_format_css(theme_data, self.page_width,
|
||||||
self.page_height), build_lyrics_outline_css(self.theme_data))
|
self.page_height), build_lyrics_outline_css(theme_data))
|
||||||
self.web.setHtml(html)
|
self.web.setHtml(html)
|
||||||
self.empty_height = self.web_frame.contentsSize().height()
|
self.empty_height = self.web_frame.contentsSize().height()
|
||||||
|
|
||||||
|
@ -158,19 +158,24 @@ class ServiceItem(object):
|
|||||||
self.icon = icon
|
self.icon = icon
|
||||||
self.iconic_representation = build_icon(icon)
|
self.iconic_representation = build_icon(icon)
|
||||||
|
|
||||||
def render(self, use_override=False):
|
def render(self, provides_own_theme_data=False):
|
||||||
"""
|
"""
|
||||||
The render method is what generates the frames for the screen and
|
The render method is what generates the frames for the screen and
|
||||||
obtains the display information from the renderer. At this point all
|
obtains the display information from the renderer. At this point all
|
||||||
slides are built for the given display size.
|
slides are built for the given display size.
|
||||||
|
|
||||||
|
``provides_own_theme_data``
|
||||||
|
This switch disables the usage of the item's theme. However, this is
|
||||||
|
disabled by default. If this is used, it has to be taken care, that
|
||||||
|
the renderer knows the correct theme data. However, this is needed
|
||||||
|
for the theme manager.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Render called')
|
log.debug(u'Render called')
|
||||||
self._display_frames = []
|
self._display_frames = []
|
||||||
self.bg_image_bytes = None
|
self.bg_image_bytes = None
|
||||||
theme = self.theme if self.theme else None
|
if not provides_own_theme_data:
|
||||||
self.main, self.footer = \
|
self.renderer.set_item_theme(self.theme)
|
||||||
self.renderer.set_override_theme(theme, use_override)
|
self.themedata, self.main, self.footer = self.renderer.pre_render()
|
||||||
self.themedata = self.renderer.theme_data
|
|
||||||
if self.service_item_type == ServiceItemType.Text:
|
if self.service_item_type == ServiceItemType.Text:
|
||||||
log.debug(u'Formatting slides')
|
log.debug(u'Formatting slides')
|
||||||
for slide in self._raw_frames:
|
for slide in self._raw_frames:
|
||||||
@ -211,7 +216,7 @@ class ServiceItem(object):
|
|||||||
self.image_border = background
|
self.image_border = background
|
||||||
self.service_item_type = ServiceItemType.Image
|
self.service_item_type = ServiceItemType.Image
|
||||||
self._raw_frames.append({u'title': title, u'path': path})
|
self._raw_frames.append({u'title': title, u'path': path})
|
||||||
self.renderer.imageManager.add_image(title, path, u'image',
|
self.renderer.image_manager.addImage(title, path, u'image',
|
||||||
self.image_border)
|
self.image_border)
|
||||||
self._new_item()
|
self._new_item()
|
||||||
|
|
||||||
|
@ -444,6 +444,20 @@ class ThemeXML(object):
|
|||||||
element.appendChild(child)
|
element.appendChild(child)
|
||||||
return child
|
return child
|
||||||
|
|
||||||
|
def set_default_header_footer(self):
|
||||||
|
"""
|
||||||
|
Set the header and footer size into the current primary screen.
|
||||||
|
10 px on each side is removed to allow for a border.
|
||||||
|
"""
|
||||||
|
from openlp.core.ui import ScreenList
|
||||||
|
current_screen = ScreenList().current
|
||||||
|
self.font_main_y = 0
|
||||||
|
self.font_main_width = current_screen[u'size'].width() - 20
|
||||||
|
self.font_main_height = current_screen[u'size'].height() * 9 / 10
|
||||||
|
self.font_footer_width = current_screen[u'size'].width() - 20
|
||||||
|
self.font_footer_y = current_screen[u'size'].height() * 9 / 10
|
||||||
|
self.font_footer_height = current_screen[u'size'].height() / 10
|
||||||
|
|
||||||
def dump_xml(self):
|
def dump_xml(self):
|
||||||
"""
|
"""
|
||||||
Dump the XML to file used for debugging
|
Dump the XML to file used for debugging
|
||||||
|
@ -56,6 +56,9 @@ class ThemeScreenshotThread(QtCore.QThread):
|
|||||||
themes = themes.split(u',')
|
themes = themes.split(u',')
|
||||||
config = self.parent().config
|
config = self.parent().config
|
||||||
for theme in themes:
|
for theme in themes:
|
||||||
|
# Stop if the wizard has been cancelled.
|
||||||
|
if self.parent().downloadCancelled:
|
||||||
|
return
|
||||||
title = config.get(u'theme_%s' % theme, u'title')
|
title = config.get(u'theme_%s' % theme, u'title')
|
||||||
filename = config.get(u'theme_%s' % theme, u'filename')
|
filename = config.get(u'theme_%s' % theme, u'filename')
|
||||||
screenshot = config.get(u'theme_%s' % theme, u'screenshot')
|
screenshot = config.get(u'theme_%s' % theme, u'screenshot')
|
||||||
@ -86,7 +89,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
files = self.webAccess.read()
|
files = self.webAccess.read()
|
||||||
self.config.readfp(io.BytesIO(files))
|
self.config.readfp(io.BytesIO(files))
|
||||||
self.updateScreenListCombo()
|
self.updateScreenListCombo()
|
||||||
self.downloadCanceled = False
|
self.downloadCancelled = False
|
||||||
self.downloading = unicode(translate('OpenLP.FirstTimeWizard',
|
self.downloading = unicode(translate('OpenLP.FirstTimeWizard',
|
||||||
'Downloading %s...'))
|
'Downloading %s...'))
|
||||||
QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL('clicked()'),
|
QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL('clicked()'),
|
||||||
@ -242,11 +245,12 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
Process the triggering of the cancel button.
|
Process the triggering of the cancel button.
|
||||||
"""
|
"""
|
||||||
if self.lastId == FirstTimePage.NoInternet or \
|
if self.lastId == FirstTimePage.NoInternet or \
|
||||||
(self.lastId <= FirstTimePage.Plugins and \
|
(self.lastId <= FirstTimePage.Plugins and not self.hasRunWizard):
|
||||||
not self.hasRunWizard):
|
|
||||||
QtCore.QCoreApplication.exit()
|
QtCore.QCoreApplication.exit()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
self.downloadCanceled = True
|
self.downloadCancelled = True
|
||||||
|
while self.themeScreenshotThread.isRunning():
|
||||||
|
time.sleep(0.1)
|
||||||
Receiver.send_message(u'cursor_normal')
|
Receiver.send_message(u'cursor_normal')
|
||||||
|
|
||||||
def onNoInternetFinishButtonClicked(self):
|
def onNoInternetFinishButtonClicked(self):
|
||||||
@ -272,7 +276,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
filesize = urlfile.headers["Content-Length"]
|
filesize = urlfile.headers["Content-Length"]
|
||||||
filename = open(fpath, "wb")
|
filename = open(fpath, "wb")
|
||||||
# Download until finished or canceled.
|
# Download until finished or canceled.
|
||||||
while not self.downloadCanceled:
|
while not self.downloadCancelled:
|
||||||
data = urlfile.read(block_size)
|
data = urlfile.read(block_size)
|
||||||
if not data:
|
if not data:
|
||||||
break
|
break
|
||||||
@ -280,8 +284,8 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
block_count += 1
|
block_count += 1
|
||||||
self._downloadProgress(block_count, block_size, filesize)
|
self._downloadProgress(block_count, block_size, filesize)
|
||||||
filename.close()
|
filename.close()
|
||||||
# Delete file if canceled, it may be a partial file.
|
# Delete file if cancelled, it may be a partial file.
|
||||||
if self.downloadCanceled:
|
if self.downloadCancelled:
|
||||||
os.remove(fpath)
|
os.remove(fpath)
|
||||||
|
|
||||||
def _buildThemeScreenshots(self):
|
def _buildThemeScreenshots(self):
|
||||||
|
@ -277,7 +277,7 @@ class MainDisplay(Display):
|
|||||||
"""
|
"""
|
||||||
API for replacement backgrounds so Images are added directly to cache.
|
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'):
|
if hasattr(self, u'serviceItem'):
|
||||||
self.override[u'image'] = name
|
self.override[u'image'] = name
|
||||||
self.override[u'theme'] = self.serviceItem.themedata.theme_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.
|
The name of the image to be displayed.
|
||||||
"""
|
"""
|
||||||
log.debug(u'image to display')
|
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.controller.mediaController.video_reset(self.controller)
|
||||||
self.displayImage(image)
|
self.displayImage(image)
|
||||||
|
|
||||||
@ -382,14 +382,14 @@ class MainDisplay(Display):
|
|||||||
else:
|
else:
|
||||||
# replace the background
|
# replace the background
|
||||||
background = self.imageManager. \
|
background = self.imageManager. \
|
||||||
get_image_bytes(self.override[u'image'])
|
getImageBytes(self.override[u'image'])
|
||||||
self.setTransparency(self.serviceItem.themedata.background_type ==
|
self.setTransparency(self.serviceItem.themedata.background_type ==
|
||||||
BackgroundType.to_string(BackgroundType.Transparent))
|
BackgroundType.to_string(BackgroundType.Transparent))
|
||||||
if self.serviceItem.themedata.background_filename:
|
if self.serviceItem.themedata.background_filename:
|
||||||
self.serviceItem.bg_image_bytes = self.imageManager. \
|
self.serviceItem.bg_image_bytes = self.imageManager. \
|
||||||
get_image_bytes(self.serviceItem.themedata.theme_name)
|
getImageBytes(self.serviceItem.themedata.theme_name)
|
||||||
if image:
|
if image:
|
||||||
image_bytes = self.imageManager.get_image_bytes(image)
|
image_bytes = self.imageManager.getImageBytes(image)
|
||||||
else:
|
else:
|
||||||
image_bytes = None
|
image_bytes = None
|
||||||
html = build_html(self.serviceItem, self.screen, self.isLive,
|
html = build_html(self.serviceItem, self.screen, self.isLive,
|
||||||
|
@ -30,6 +30,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
from tempfile import gettempdir
|
from tempfile import gettempdir
|
||||||
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
@ -1121,7 +1122,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
"""
|
"""
|
||||||
log.debug(u'screenChanged')
|
log.debug(u'screenChanged')
|
||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
self.imageManager.update_display()
|
self.imageManager.updateDisplay()
|
||||||
self.renderer.update_display()
|
self.renderer.update_display()
|
||||||
self.previewController.screenSizeChanged()
|
self.previewController.screenSizeChanged()
|
||||||
self.liveController.screenSizeChanged()
|
self.liveController.screenSizeChanged()
|
||||||
@ -1140,6 +1141,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
return
|
return
|
||||||
# If we just did a settings import, close without saving changes.
|
# If we just did a settings import, close without saving changes.
|
||||||
if self.settingsImported:
|
if self.settingsImported:
|
||||||
|
self.cleanUp(False)
|
||||||
event.accept()
|
event.accept()
|
||||||
if self.serviceManagerContents.isModified():
|
if self.serviceManagerContents.isModified():
|
||||||
ret = self.serviceManagerContents.saveModifiedService()
|
ret = self.serviceManagerContents.saveModifiedService()
|
||||||
@ -1162,8 +1164,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
translate('OpenLP.MainWindow',
|
translate('OpenLP.MainWindow',
|
||||||
'Are you sure you want to close OpenLP?'),
|
'Are you sure you want to close OpenLP?'),
|
||||||
QtGui.QMessageBox.StandardButtons(
|
QtGui.QMessageBox.StandardButtons(
|
||||||
QtGui.QMessageBox.Yes |
|
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
|
||||||
QtGui.QMessageBox.No),
|
|
||||||
QtGui.QMessageBox.Yes)
|
QtGui.QMessageBox.Yes)
|
||||||
if ret == QtGui.QMessageBox.Yes:
|
if ret == QtGui.QMessageBox.Yes:
|
||||||
self.cleanUp()
|
self.cleanUp()
|
||||||
@ -1174,12 +1175,19 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
self.cleanUp()
|
self.cleanUp()
|
||||||
event.accept()
|
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
|
# Clean temporary files used by services
|
||||||
self.serviceManagerContents.cleanUp()
|
self.serviceManagerContents.cleanUp()
|
||||||
|
if save_settings:
|
||||||
if QtCore.QSettings().value(u'advanced/save current plugin',
|
if QtCore.QSettings().value(u'advanced/save current plugin',
|
||||||
QtCore.QVariant(False)).toBool():
|
QtCore.QVariant(False)).toBool():
|
||||||
QtCore.QSettings().setValue(u'advanced/current media plugin',
|
QtCore.QSettings().setValue(u'advanced/current media plugin',
|
||||||
@ -1187,6 +1195,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
# Call the cleanup method to shutdown plugins.
|
# Call the cleanup method to shutdown plugins.
|
||||||
log.info(u'cleanup plugins')
|
log.info(u'cleanup plugins')
|
||||||
self.pluginManager.finalise_plugins()
|
self.pluginManager.finalise_plugins()
|
||||||
|
if save_settings:
|
||||||
# Save settings
|
# Save settings
|
||||||
self.saveSettings()
|
self.saveSettings()
|
||||||
# Close down the display
|
# Close down the display
|
||||||
|
@ -859,11 +859,11 @@ class SlideController(Controller):
|
|||||||
# If current slide set background to image
|
# If current slide set background to image
|
||||||
if framenumber == slideno:
|
if framenumber == slideno:
|
||||||
self.serviceItem.bg_image_bytes = \
|
self.serviceItem.bg_image_bytes = \
|
||||||
self.imageManager.get_image_bytes(frame[u'title'])
|
self.imageManager.getImageBytes(frame[u'title'])
|
||||||
image = self.imageManager.get_image(frame[u'title'])
|
image = self.imageManager.getImage(frame[u'title'])
|
||||||
label.setPixmap(QtGui.QPixmap.fromImage(image))
|
label.setPixmap(QtGui.QPixmap.fromImage(image))
|
||||||
self.previewListWidget.setCellWidget(framenumber, 0, label)
|
self.previewListWidget.setCellWidget(framenumber, 0, label)
|
||||||
slideHeight = width * self.parent().renderer.screen_ratio
|
slideHeight = width * (1 / self.ratio)
|
||||||
row += 1
|
row += 1
|
||||||
self.slideList[unicode(row)] = row - 1
|
self.slideList[unicode(row)] = row - 1
|
||||||
text.append(unicode(row))
|
text.append(unicode(row))
|
||||||
|
@ -247,8 +247,7 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
QtCore.QSettings().setValue(
|
QtCore.QSettings().setValue(
|
||||||
self.settingsSection + u'/global theme',
|
self.settingsSection + u'/global theme',
|
||||||
QtCore.QVariant(self.global_theme))
|
QtCore.QVariant(self.global_theme))
|
||||||
Receiver.send_message(u'theme_update_global',
|
Receiver.send_message(u'theme_update_global', self.global_theme)
|
||||||
self.global_theme)
|
|
||||||
self._pushThemes()
|
self._pushThemes()
|
||||||
|
|
||||||
def onAddTheme(self):
|
def onAddTheme(self):
|
||||||
@ -257,6 +256,7 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
editing form for the user to make their customisations.
|
editing form for the user to make their customisations.
|
||||||
"""
|
"""
|
||||||
theme = ThemeXML()
|
theme = ThemeXML()
|
||||||
|
theme.set_default_header_footer()
|
||||||
self.themeForm.theme = theme
|
self.themeForm.theme = theme
|
||||||
self.themeForm.exec_()
|
self.themeForm.exec_()
|
||||||
|
|
||||||
@ -284,6 +284,8 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
if plugin.usesTheme(old_theme_name):
|
if plugin.usesTheme(old_theme_name):
|
||||||
plugin.renameTheme(old_theme_name, new_theme_name)
|
plugin.renameTheme(old_theme_name, new_theme_name)
|
||||||
self.loadThemes()
|
self.loadThemes()
|
||||||
|
self.mainwindow.renderer.update_theme(
|
||||||
|
new_theme_name, old_theme_name)
|
||||||
|
|
||||||
def onCopyTheme(self):
|
def onCopyTheme(self):
|
||||||
"""
|
"""
|
||||||
@ -320,9 +322,8 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
Loads the settings for the theme that is to be edited and launches the
|
Loads the settings for the theme that is to be edited and launches the
|
||||||
theme editing form so the user can make their changes.
|
theme editing form so the user can make their changes.
|
||||||
"""
|
"""
|
||||||
if check_item_selected(self.themeListWidget,
|
if check_item_selected(self.themeListWidget, translate(
|
||||||
translate('OpenLP.ThemeManager',
|
'OpenLP.ThemeManager', 'You must select a theme to edit.')):
|
||||||
'You must select a theme to edit.')):
|
|
||||||
item = self.themeListWidget.currentItem()
|
item = self.themeListWidget.currentItem()
|
||||||
theme = self.getThemeData(
|
theme = self.getThemeData(
|
||||||
unicode(item.data(QtCore.Qt.UserRole).toString()))
|
unicode(item.data(QtCore.Qt.UserRole).toString()))
|
||||||
@ -331,6 +332,7 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
self.themeForm.theme = theme
|
self.themeForm.theme = theme
|
||||||
self.themeForm.exec_(True)
|
self.themeForm.exec_(True)
|
||||||
self.old_background_image = None
|
self.old_background_image = None
|
||||||
|
self.mainwindow.renderer.update_theme(theme.theme_name)
|
||||||
|
|
||||||
def onDeleteTheme(self):
|
def onDeleteTheme(self):
|
||||||
"""
|
"""
|
||||||
@ -348,6 +350,7 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
# As we do not reload the themes, push out the change. Reload the
|
# As we do not reload the themes, push out the change. Reload the
|
||||||
# list as the internal lists and events need to be triggered.
|
# list as the internal lists and events need to be triggered.
|
||||||
self._pushThemes()
|
self._pushThemes()
|
||||||
|
self.mainwindow.renderer.update_theme(theme, only_delete=True)
|
||||||
|
|
||||||
def deleteTheme(self, theme):
|
def deleteTheme(self, theme):
|
||||||
"""
|
"""
|
||||||
@ -663,9 +666,9 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
self._writeTheme(theme, image_from, image_to)
|
self._writeTheme(theme, image_from, image_to)
|
||||||
if theme.background_type == \
|
if theme.background_type == \
|
||||||
BackgroundType.to_string(BackgroundType.Image):
|
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))
|
u'theme', QtGui.QColor(theme.background_border_color))
|
||||||
self.mainwindow.imageManager.process_updates()
|
self.mainwindow.imageManager.processUpdates()
|
||||||
self.loadThemes()
|
self.loadThemes()
|
||||||
|
|
||||||
def _writeTheme(self, theme, image_from, image_to):
|
def _writeTheme(self, theme, image_from, image_to):
|
||||||
|
@ -151,8 +151,8 @@ class ThemesTab(SettingsTab):
|
|||||||
settings.setValue(u'theme level', QtCore.QVariant(self.theme_level))
|
settings.setValue(u'theme level', QtCore.QVariant(self.theme_level))
|
||||||
settings.setValue(u'global theme', QtCore.QVariant(self.global_theme))
|
settings.setValue(u'global theme', QtCore.QVariant(self.global_theme))
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
self.mainwindow.renderer.set_global_theme(
|
self.mainwindow.renderer.set_global_theme(self.global_theme)
|
||||||
self.global_theme, self.theme_level)
|
self.mainwindow.renderer.set_theme_level(self.theme_level)
|
||||||
Receiver.send_message(u'theme_update_global', self.global_theme)
|
Receiver.send_message(u'theme_update_global', self.global_theme)
|
||||||
|
|
||||||
def postSetUp(self):
|
def postSetUp(self):
|
||||||
@ -169,8 +169,8 @@ class ThemesTab(SettingsTab):
|
|||||||
|
|
||||||
def onDefaultComboBoxChanged(self, value):
|
def onDefaultComboBoxChanged(self, value):
|
||||||
self.global_theme = unicode(self.DefaultComboBox.currentText())
|
self.global_theme = unicode(self.DefaultComboBox.currentText())
|
||||||
self.mainwindow.renderer.set_global_theme(
|
self.mainwindow.renderer.set_global_theme(self.global_theme)
|
||||||
self.global_theme, self.theme_level)
|
self.mainwindow.renderer.set_theme_level(self.theme_level)
|
||||||
self.__previewGlobalTheme()
|
self.__previewGlobalTheme()
|
||||||
|
|
||||||
def updateThemeList(self, theme_list):
|
def updateThemeList(self, theme_list):
|
||||||
@ -189,8 +189,8 @@ class ThemesTab(SettingsTab):
|
|||||||
self.DefaultComboBox.clear()
|
self.DefaultComboBox.clear()
|
||||||
self.DefaultComboBox.addItems(theme_list)
|
self.DefaultComboBox.addItems(theme_list)
|
||||||
find_and_set_in_combo_box(self.DefaultComboBox, self.global_theme)
|
find_and_set_in_combo_box(self.DefaultComboBox, self.global_theme)
|
||||||
self.mainwindow.renderer.set_global_theme(
|
self.mainwindow.renderer.set_global_theme(self.global_theme)
|
||||||
self.global_theme, self.theme_level)
|
self.mainwindow.renderer.set_theme_level(self.theme_level)
|
||||||
if self.global_theme is not u'':
|
if self.global_theme is not u'':
|
||||||
self.__previewGlobalTheme()
|
self.__previewGlobalTheme()
|
||||||
|
|
||||||
|
@ -197,9 +197,6 @@ class CustomMediaItem(MediaManagerItem):
|
|||||||
|
|
||||||
def generateSlideData(self, service_item, item=None, xmlVersion=False,
|
def generateSlideData(self, service_item, item=None, xmlVersion=False,
|
||||||
remote=False):
|
remote=False):
|
||||||
raw_footer = []
|
|
||||||
slide = None
|
|
||||||
theme = None
|
|
||||||
item_id = self._getIdOfItemToGenerate(item, self.remoteCustom)
|
item_id = self._getIdOfItemToGenerate(item, self.remoteCustom)
|
||||||
service_item.add_capability(ItemCapabilities.CanEdit)
|
service_item.add_capability(ItemCapabilities.CanEdit)
|
||||||
service_item.add_capability(ItemCapabilities.CanPreview)
|
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||||
@ -220,10 +217,9 @@ class CustomMediaItem(MediaManagerItem):
|
|||||||
service_item.add_from_text(slide[:30], slide)
|
service_item.add_from_text(slide[:30], slide)
|
||||||
if QtCore.QSettings().value(self.settingsSection + u'/display footer',
|
if QtCore.QSettings().value(self.settingsSection + u'/display footer',
|
||||||
QtCore.QVariant(True)).toBool() or credit:
|
QtCore.QVariant(True)).toBool() or credit:
|
||||||
raw_footer.append(title + u' ' + credit)
|
service_item.raw_footer.append(u' '.join([title, credit]))
|
||||||
else:
|
else:
|
||||||
raw_footer.append(u'')
|
service_item.raw_footer.append(u'')
|
||||||
service_item.raw_footer = raw_footer
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def onSearchTextButtonClicked(self):
|
def onSearchTextButtonClicked(self):
|
||||||
|
@ -96,4 +96,4 @@ class ImagePlugin(Plugin):
|
|||||||
"""
|
"""
|
||||||
background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection
|
background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection
|
||||||
+ u'/background color', QtCore.QVariant(u'#000000')))
|
+ u'/background color', QtCore.QVariant(u'#000000')))
|
||||||
self.liveController.imageManager.update_images(u'image', background)
|
self.liveController.imageManager.updateImages(u'image', background)
|
||||||
|
@ -164,7 +164,7 @@
|
|||||||
<input type="search" name="search-text" id="search-text" value="" />
|
<input type="search" name="search-text" id="search-text" value="" />
|
||||||
</div>
|
</div>
|
||||||
<a href="#" id="search-submit" data-role="button">${search}</a>
|
<a href="#" id="search-submit" data-role="button">${search}</a>
|
||||||
<ul data-role="listview" data-inset="true">
|
<ul data-role="listview" data-inset="true"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-role="page" id="options">
|
<div data-role="page" id="options">
|
||||||
|
@ -97,7 +97,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
self.onVerseOrderTextChanged)
|
self.onVerseOrderTextChanged)
|
||||||
QtCore.QObject.connect(self.themeAddButton,
|
QtCore.QObject.connect(self.themeAddButton,
|
||||||
QtCore.SIGNAL(u'clicked()'),
|
QtCore.SIGNAL(u'clicked()'),
|
||||||
self.mediaitem.plugin.renderer.themeManager.onAddTheme)
|
self.mediaitem.plugin.renderer.theme_manager.onAddTheme)
|
||||||
QtCore.QObject.connect(self.maintenanceButton,
|
QtCore.QObject.connect(self.maintenanceButton,
|
||||||
QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked)
|
QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked)
|
||||||
QtCore.QObject.connect(self.audioAddFromFileButton,
|
QtCore.QObject.connect(self.audioAddFromFileButton,
|
||||||
@ -707,7 +707,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
text = unicode(self.songBookComboBox.currentText())
|
text = unicode(self.songBookComboBox.currentText())
|
||||||
if item == 0 and text:
|
if item == 0 and text:
|
||||||
temp_song_book = text
|
temp_song_book = text
|
||||||
self.mediaitem.songMaintenanceForm.exec_()
|
self.mediaitem.songMaintenanceForm.exec_(True)
|
||||||
self.loadAuthors()
|
self.loadAuthors()
|
||||||
self.loadBooks()
|
self.loadBooks()
|
||||||
self.loadTopics()
|
self.loadTopics()
|
||||||
@ -865,12 +865,16 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
for row in xrange(self.authorsListView.count()):
|
for row in xrange(self.authorsListView.count()):
|
||||||
item = self.authorsListView.item(row)
|
item = self.authorsListView.item(row)
|
||||||
authorId = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
authorId = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||||
self.song.authors.append(self.manager.get_object(Author, authorId))
|
author = self.manager.get_object(Author, authorId)
|
||||||
|
if author is not None:
|
||||||
|
self.song.authors.append(author)
|
||||||
self.song.topics = []
|
self.song.topics = []
|
||||||
for row in xrange(self.topicsListView.count()):
|
for row in xrange(self.topicsListView.count()):
|
||||||
item = self.topicsListView.item(row)
|
item = self.topicsListView.item(row)
|
||||||
topicId = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
topicId = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||||
self.song.topics.append(self.manager.get_object(Topic, topicId))
|
topic = self.manager.get_object(Topic, topicId)
|
||||||
|
if topic is not None:
|
||||||
|
self.song.topics.append(topic)
|
||||||
# Save the song here because we need a valid id for the audio files.
|
# Save the song here because we need a valid id for the audio files.
|
||||||
clean_song(self.manager, self.song)
|
clean_song(self.manager, self.song)
|
||||||
self.manager.save_object(self.song)
|
self.manager.save_object(self.song)
|
||||||
|
@ -87,7 +87,15 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
QtCore.SIGNAL(u'currentRowChanged(int)'),
|
QtCore.SIGNAL(u'currentRowChanged(int)'),
|
||||||
self.onBooksListRowChanged)
|
self.onBooksListRowChanged)
|
||||||
|
|
||||||
def exec_(self):
|
def exec_(self, fromSongEdit=False):
|
||||||
|
"""
|
||||||
|
Show the dialog.
|
||||||
|
|
||||||
|
``fromSongEdit``
|
||||||
|
Indicates if the maintenance dialog has been opened from song edit
|
||||||
|
or from the media manager. Defaults to **False**.
|
||||||
|
"""
|
||||||
|
self.fromSongEdit = fromSongEdit
|
||||||
self.typeListWidget.setCurrentRow(0)
|
self.typeListWidget.setCurrentRow(0)
|
||||||
self.resetAuthors()
|
self.resetAuthors()
|
||||||
self.resetTopics()
|
self.resetTopics()
|
||||||
@ -103,20 +111,20 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
else:
|
else:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def _deleteItem(self, item_class, list_widget, reset_func, dlg_title,
|
def _deleteItem(self, itemClass, listWidget, resetFunc, dlgTitle,
|
||||||
del_text, err_text):
|
del_text, err_text):
|
||||||
item_id = self._getCurrentItemId(list_widget)
|
item_id = self._getCurrentItemId(listWidget)
|
||||||
if item_id != -1:
|
if item_id != -1:
|
||||||
item = self.manager.get_object(item_class, item_id)
|
item = self.manager.get_object(itemClass, item_id)
|
||||||
if item and not item.songs:
|
if item and not item.songs:
|
||||||
if critical_error_message_box(dlg_title, del_text, self,
|
if critical_error_message_box(dlgTitle, del_text, self,
|
||||||
True) == QtGui.QMessageBox.Yes:
|
True) == QtGui.QMessageBox.Yes:
|
||||||
self.manager.delete_object(item_class, item.id)
|
self.manager.delete_object(itemClass, item.id)
|
||||||
reset_func()
|
resetFunc()
|
||||||
else:
|
else:
|
||||||
critical_error_message_box(dlg_title, err_text)
|
critical_error_message_box(dlgTitle, err_text)
|
||||||
else:
|
else:
|
||||||
critical_error_message_box(dlg_title, UiStrings().NISs)
|
critical_error_message_box(dlgTitle, UiStrings().NISs)
|
||||||
|
|
||||||
def resetAuthors(self):
|
def resetAuthors(self):
|
||||||
"""
|
"""
|
||||||
@ -157,34 +165,34 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id))
|
book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id))
|
||||||
self.booksListWidget.addItem(book_name)
|
self.booksListWidget.addItem(book_name)
|
||||||
|
|
||||||
def checkAuthor(self, new_author, edit=False):
|
def checkAuthor(self, newAuthor, edit=False):
|
||||||
"""
|
"""
|
||||||
Returns *False* if the given Author already exists, otherwise *True*.
|
Returns *False* if the given Author already exists, otherwise *True*.
|
||||||
"""
|
"""
|
||||||
authors = self.manager.get_all_objects(Author,
|
authors = self.manager.get_all_objects(Author,
|
||||||
and_(Author.first_name == new_author.first_name,
|
and_(Author.first_name == newAuthor.first_name,
|
||||||
Author.last_name == new_author.last_name,
|
Author.last_name == newAuthor.last_name,
|
||||||
Author.display_name == new_author.display_name))
|
Author.display_name == newAuthor.display_name))
|
||||||
return self.__checkObject(authors, new_author, edit)
|
return self.__checkObject(authors, newAuthor, edit)
|
||||||
|
|
||||||
def checkTopic(self, new_topic, edit=False):
|
def checkTopic(self, newTopic, edit=False):
|
||||||
"""
|
"""
|
||||||
Returns *False* if the given Topic already exists, otherwise *True*.
|
Returns *False* if the given Topic already exists, otherwise *True*.
|
||||||
"""
|
"""
|
||||||
topics = self.manager.get_all_objects(Topic,
|
topics = self.manager.get_all_objects(Topic,
|
||||||
Topic.name == new_topic.name)
|
Topic.name == newTopic.name)
|
||||||
return self.__checkObject(topics, new_topic, edit)
|
return self.__checkObject(topics, newTopic, edit)
|
||||||
|
|
||||||
def checkBook(self, new_book, edit=False):
|
def checkBook(self, newBook, edit=False):
|
||||||
"""
|
"""
|
||||||
Returns *False* if the given Topic already exists, otherwise *True*.
|
Returns *False* if the given Topic already exists, otherwise *True*.
|
||||||
"""
|
"""
|
||||||
books = self.manager.get_all_objects(Book,
|
books = self.manager.get_all_objects(Book,
|
||||||
and_(Book.name == new_book.name,
|
and_(Book.name == newBook.name,
|
||||||
Book.publisher == new_book.publisher))
|
Book.publisher == newBook.publisher))
|
||||||
return self.__checkObject(books, new_book, edit)
|
return self.__checkObject(books, newBook, edit)
|
||||||
|
|
||||||
def __checkObject(self, objects, new_object, edit):
|
def __checkObject(self, objects, newObject, edit):
|
||||||
"""
|
"""
|
||||||
Utility method to check for an existing object.
|
Utility method to check for an existing object.
|
||||||
|
|
||||||
@ -196,7 +204,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
# not return False when nothing has changed.
|
# not return False when nothing has changed.
|
||||||
if edit:
|
if edit:
|
||||||
for object in objects:
|
for object in objects:
|
||||||
if object.id != new_object.id:
|
if object.id != newObject.id:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@ -275,6 +283,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
if self.checkAuthor(author, True):
|
if self.checkAuthor(author, True):
|
||||||
if self.manager.save_object(author):
|
if self.manager.save_object(author):
|
||||||
self.resetAuthors()
|
self.resetAuthors()
|
||||||
|
if not self.fromSongEdit:
|
||||||
Receiver.send_message(u'songs_load_list')
|
Receiver.send_message(u'songs_load_list')
|
||||||
else:
|
else:
|
||||||
critical_error_message_box(
|
critical_error_message_box(
|
||||||
@ -373,75 +382,76 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
merge(dbObject)
|
merge(dbObject)
|
||||||
reset()
|
reset()
|
||||||
|
if not self.fromSongEdit:
|
||||||
Receiver.send_message(u'songs_load_list')
|
Receiver.send_message(u'songs_load_list')
|
||||||
Receiver.send_message(u'cursor_normal')
|
Receiver.send_message(u'cursor_normal')
|
||||||
|
|
||||||
def mergeAuthors(self, old_author):
|
def mergeAuthors(self, oldAuthor):
|
||||||
"""
|
"""
|
||||||
Merges two authors into one author.
|
Merges two authors into one author.
|
||||||
|
|
||||||
``old_author``
|
``oldAuthor``
|
||||||
The object, which was edited, that will be deleted
|
The object, which was edited, that will be deleted
|
||||||
"""
|
"""
|
||||||
# Find the duplicate.
|
# Find the duplicate.
|
||||||
existing_author = self.manager.get_object_filtered(Author,
|
existing_author = self.manager.get_object_filtered(Author,
|
||||||
and_(Author.first_name == old_author.first_name,
|
and_(Author.first_name == oldAuthor.first_name,
|
||||||
Author.last_name == old_author.last_name,
|
Author.last_name == oldAuthor.last_name,
|
||||||
Author.display_name == old_author.display_name,
|
Author.display_name == oldAuthor.display_name,
|
||||||
Author.id != old_author.id))
|
Author.id != oldAuthor.id))
|
||||||
# Find the songs, which have the old_author as author.
|
# Find the songs, which have the oldAuthor as author.
|
||||||
songs = self.manager.get_all_objects(Song,
|
songs = self.manager.get_all_objects(Song,
|
||||||
Song.authors.contains(old_author))
|
Song.authors.contains(oldAuthor))
|
||||||
for song in songs:
|
for song in songs:
|
||||||
# We check if the song has already existing_author as author. If
|
# We check if the song has already existing_author as author. If
|
||||||
# that is not the case we add it.
|
# that is not the case we add it.
|
||||||
if existing_author not in song.authors:
|
if existing_author not in song.authors:
|
||||||
song.authors.append(existing_author)
|
song.authors.append(existing_author)
|
||||||
song.authors.remove(old_author)
|
song.authors.remove(oldAuthor)
|
||||||
self.manager.save_object(song)
|
self.manager.save_object(song)
|
||||||
self.manager.delete_object(Author, old_author.id)
|
self.manager.delete_object(Author, oldAuthor.id)
|
||||||
|
|
||||||
def mergeTopics(self, old_topic):
|
def mergeTopics(self, oldTopic):
|
||||||
"""
|
"""
|
||||||
Merges two topics into one topic.
|
Merges two topics into one topic.
|
||||||
|
|
||||||
``old_topic``
|
``oldTopic``
|
||||||
The object, which was edited, that will be deleted
|
The object, which was edited, that will be deleted
|
||||||
"""
|
"""
|
||||||
# Find the duplicate.
|
# Find the duplicate.
|
||||||
existing_topic = self.manager.get_object_filtered(Topic,
|
existing_topic = self.manager.get_object_filtered(Topic,
|
||||||
and_(Topic.name == old_topic.name, Topic.id != old_topic.id))
|
and_(Topic.name == oldTopic.name, Topic.id != oldTopic.id))
|
||||||
# Find the songs, which have the old_topic as topic.
|
# Find the songs, which have the oldTopic as topic.
|
||||||
songs = self.manager.get_all_objects(Song,
|
songs = self.manager.get_all_objects(Song,
|
||||||
Song.topics.contains(old_topic))
|
Song.topics.contains(oldTopic))
|
||||||
for song in songs:
|
for song in songs:
|
||||||
# We check if the song has already existing_topic as topic. If that
|
# We check if the song has already existing_topic as topic. If that
|
||||||
# is not the case we add it.
|
# is not the case we add it.
|
||||||
if existing_topic not in song.topics:
|
if existing_topic not in song.topics:
|
||||||
song.topics.append(existing_topic)
|
song.topics.append(existing_topic)
|
||||||
song.topics.remove(old_topic)
|
song.topics.remove(oldTopic)
|
||||||
self.manager.save_object(song)
|
self.manager.save_object(song)
|
||||||
self.manager.delete_object(Topic, old_topic.id)
|
self.manager.delete_object(Topic, oldTopic.id)
|
||||||
|
|
||||||
def mergeBooks(self, old_book):
|
def mergeBooks(self, oldBook):
|
||||||
"""
|
"""
|
||||||
Merges two books into one book.
|
Merges two books into one book.
|
||||||
|
|
||||||
``old_book``
|
``oldBook``
|
||||||
The object, which was edited, that will be deleted
|
The object, which was edited, that will be deleted
|
||||||
"""
|
"""
|
||||||
# Find the duplicate.
|
# Find the duplicate.
|
||||||
existing_book = self.manager.get_object_filtered(Book,
|
existing_book = self.manager.get_object_filtered(Book,
|
||||||
and_(Book.name == old_book.name,
|
and_(Book.name == oldBook.name,
|
||||||
Book.publisher == old_book.publisher,
|
Book.publisher == oldBook.publisher,
|
||||||
Book.id != old_book.id))
|
Book.id != oldBook.id))
|
||||||
# Find the songs, which have the old_book as book.
|
# Find the songs, which have the oldBook as book.
|
||||||
songs = self.manager.get_all_objects(Song,
|
songs = self.manager.get_all_objects(Song,
|
||||||
Song.song_book_id == old_book.id)
|
Song.song_book_id == oldBook.id)
|
||||||
for song in songs:
|
for song in songs:
|
||||||
song.song_book_id = existing_book.id
|
song.song_book_id = existing_book.id
|
||||||
self.manager.save_object(song)
|
self.manager.save_object(song)
|
||||||
self.manager.delete_object(Book, old_book.id)
|
self.manager.delete_object(Book, oldBook.id)
|
||||||
|
|
||||||
def onAuthorDeleteButtonClicked(self):
|
def onAuthorDeleteButtonClicked(self):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user