This commit is contained in:
rimach 2010-11-27 08:09:14 +01:00
commit bd173bd217
7 changed files with 139 additions and 66 deletions

View File

@ -48,7 +48,7 @@ Service Manger
--------------
The service manager contains the media items in your service file. This is the
area from wich your media items go live, and you can also save, open, and edit
area from which your media items go live, and you can also save, open, and edit
services files.
.. image:: pics/servicemanager.png

View File

@ -32,7 +32,7 @@ import logging
from PyQt4 import QtWebKit
from openlp.core.lib import expand_tags, build_lyrics_format_css, \
build_lyrics_outline_css
build_lyrics_outline_css, Receiver
log = logging.getLogger(__name__)
@ -92,13 +92,20 @@ class Renderer(object):
(build_lyrics_format_css(self._theme, self.page_width,
self.page_height), build_lyrics_outline_css(self._theme))
def format_slide(self, words, line_break):
def format_slide(self, words, line_break, force_page=False):
"""
Figure out how much text can appear on a slide, using the current
theme settings.
``words``
The words to be fitted on the slide.
``line_break``
Add line endings after each line of text used for bibles.
``force_page``
Flag to tell message lines in page.
"""
log.debug(u'format_slide - Start')
line_end = u''
@ -114,13 +121,19 @@ class Renderer(object):
formatted = []
html_text = u''
styled_text = u''
line_count = 0
for line in text:
if line_count != -1:
line_count += 1
styled_line = expand_tags(line) + line_end
styled_text += styled_line
html = self.page_shell + styled_text + u'</div></body></html>'
self.web.setHtml(html)
# Text too long so go to next page
if self.web_frame.contentsSize().height() > self.page_height:
if force_page and line_count > 0:
Receiver.send_message(u'theme_line_count', line_count)
line_count = -1
if html_text.endswith(u'<br>'):
html_text = html_text[:len(html_text)-4]
formatted.append(html_text)

View File

@ -67,8 +67,9 @@ class RenderManager(object):
self.service_theme = u''
self.theme_level = u''
self.override_background = None
self.themedata = None
self.theme_data = None
self.alertTab = None
self.force_page = False
def update_display(self):
"""
@ -80,7 +81,7 @@ class RenderManager(object):
self.display.imageManager = self.image_manager
self.display.setup()
self.renderer.bg_frame = None
self.themedata = None
self.theme_data = None
self.image_manager.update_display(self.width, self.height)
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
@ -99,7 +100,7 @@ class RenderManager(object):
self.theme_level = theme_level
self.global_theme_data = \
self.theme_manager.getThemeData(self.global_theme)
self.themedata = None
self.theme_data = None
def set_service_theme(self, service_theme):
"""
@ -109,7 +110,7 @@ class RenderManager(object):
The service-level theme to be set.
"""
self.service_theme = service_theme
self.themedata = None
self.theme_data = None
def set_override_theme(self, theme, overrideLevels=False):
"""
@ -146,19 +147,19 @@ class RenderManager(object):
self.theme = self.service_theme
else:
self.theme = self.global_theme
if self.theme != self.renderer.theme_name or self.themedata is None \
if self.theme != self.renderer.theme_name or self.theme_data is None \
or overrideLevels:
log.debug(u'theme is now %s', self.theme)
# Force the theme to be the one passed in.
if overrideLevels:
self.themedata = theme
self.theme_data = theme
else:
self.themedata = self.theme_manager.getThemeData(self.theme)
self.theme_data = self.theme_manager.getThemeData(self.theme)
self.calculate_default(self.screens.current[u'size'])
self.renderer.set_theme(self.themedata)
self.build_text_rectangle(self.themedata)
self.image_manager.add_image(self.themedata.theme_name,
self.themedata.background_filename)
self.renderer.set_theme(self.theme_data)
self.build_text_rectangle(self.theme_data)
self.image_manager.add_image(self.theme_data.theme_name,
self.theme_data.background_filename)
return self.renderer._rect, self.renderer._rect_footer
def build_text_rectangle(self, theme):
@ -187,14 +188,19 @@ class RenderManager(object):
theme.font_footer_height - 1)
self.renderer.set_text_rectangle(main_rect, footer_rect)
def generate_preview(self, themedata):
def generate_preview(self, theme_data, force_page=False):
"""
Generate a preview of a theme.
``themedata``
``theme_data``
The theme to generated a preview for.
``force_page``
Flag to tell message lines per page need to be generated.
"""
log.debug(u'generate preview')
# save value for use in format_slide
self.force_page = force_page
# set the default image size for previews
self.calculate_default(self.screens.preview[u'size'])
verse = u'The Lord said to {r}Noah{/r}: \n' \
@ -204,17 +210,21 @@ class RenderManager(object):
'Get those children out of the muddy, muddy \n' \
'{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}' \
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
# make big page for theme edit dialog to get line count
if self.force_page:
verse = verse + verse + verse
footer = []
footer.append(u'Arky Arky (Unknown)' )
footer.append(u'Public Domain')
footer.append(u'CCLI 123456')
# build a service item to generate preview
serviceItem = ServiceItem()
serviceItem.theme = themedata
serviceItem.theme = theme_data
serviceItem.add_from_text(u'', verse, footer)
serviceItem.render_manager = self
serviceItem.raw_footer = footer
serviceItem.render(True)
if not self.force_page:
self.display.buildHtml(serviceItem)
raw_html = serviceItem.get_rendered_frame(0)
preview = self.display.text(raw_html)
@ -228,9 +238,12 @@ class RenderManager(object):
``words``
The words to go on the slides.
``line_break``
Add line endings after each line of text used for bibles.
"""
log.debug(u'format slide')
return self.renderer.format_slide(words, line_break)
return self.renderer.format_slide(words, line_break, self.force_page)
def calculate_default(self, screen):
"""

View File

@ -29,7 +29,8 @@ import os
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, BackgroundType, BackgroundGradientType
from openlp.core.lib import translate, BackgroundType, BackgroundGradientType, \
Receiver
from openlp.core.utils import get_images_filter
from themewizard import Ui_ThemeWizard
@ -96,10 +97,40 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
QtCore.QObject.connect(self,
QtCore.SIGNAL(u'currentIdChanged(int)'),
self.pageChanged)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'theme_line_count'),
self.updateLinesText)
QtCore.QObject.connect(self.mainSizeSpinBox,
QtCore.SIGNAL(u'valueChanged(int)'),
self.calculateLines)
QtCore.QObject.connect(self.mainSizeSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.calculateLines)
QtCore.QObject.connect(self.lineSpacingSpinBox,
QtCore.SIGNAL(u'valueChanged(int)'),
self.calculateLines)
QtCore.QObject.connect(self.lineSpacingSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.calculateLines)
QtCore.QObject.connect(self.outlineSizeSpinBox,
QtCore.SIGNAL(u'valueChanged(int)'),
self.calculateLines)
QtCore.QObject.connect(self.outlineSizeSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.calculateLines)
QtCore.QObject.connect(self.shadowSizeSpinBox,
QtCore.SIGNAL(u'valueChanged(int)'),
self.calculateLines)
QtCore.QObject.connect(self.shadowSizeSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.calculateLines)
QtCore.QObject.connect(self.mainFontComboBox,
QtCore.SIGNAL(u'activated(int)'),
self.calculateLines)
def pageChanged(self, pageId):
"""
Detects Page changes and updates.
Detects Page changes and updates as approprate.
"""
if pageId == 6:
self.updateTheme()
@ -184,6 +215,22 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.backgroundPage.registerField(
u'name', self.themeNameEdit)
def calculateLines(self):
"""
Calculate the number of lines on a page by rendering text
"""
# Do not trigger on start up
if self.page != 0:
self.updateTheme()
frame = self.thememanager.generateImage(self.theme, True)
def updateLinesText(self, lines):
"""
Updates the lines on a page on the wizard
"""
self.mainLineCountLabel.setText(unicode(translate('OpenLP.ThemeForm', \
'(%d lines per slide)' % int(lines))))
def onOutlineCheckCheckBoxChanged(self, state):
"""
Change state as Outline check box changed
@ -194,6 +241,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.theme.font_main_outline = False
self.outlineColorPushButton.setEnabled(self.theme.font_main_outline)
self.outlineSizeSpinBox.setEnabled(self.theme.font_main_outline)
self.calculateLines()
def onShadowCheckCheckBoxChanged(self, state):
"""
@ -205,6 +253,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.theme.font_main_shadow = False
self.shadowColorPushButton.setEnabled(self.theme.font_main_shadow)
self.shadowSizeSpinBox.setEnabled(self.theme.font_main_shadow)
self.calculateLines()
def onMainDefaultPositionCheckBox(self, value):
"""
@ -244,6 +293,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
Set up the pages for Initial run through dialog
"""
log.debug(u'initializePage %s' % id)
self.page = id
if id == 1:
self.setBackgroundTabValues()
elif id == 2:
@ -578,15 +628,15 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
(QtGui.QMessageBox.Ok),
QtGui.QMessageBox.Ok)
return
save_from = None
save_to = None
saveFrom = None
saveTo = None
if self.theme.background_type == \
BackgroundType.to_string(BackgroundType.Image):
filename = \
os.path.split(unicode(self.theme.background_filename))[1]
save_to = os.path.join(self.path, self.theme.theme_name, filename)
save_from = self.theme.background_filename
if self.thememanager.saveTheme(self.theme, save_from, save_to):
saveTo = os.path.join(self.path, self.theme.theme_name, filename)
saveFrom = self.theme.background_filename
if self.thememanager.saveTheme(self.theme, saveFrom, saveTo):
return QtGui.QDialog.accept(self)
def _colorButton(self, field):

View File

@ -252,17 +252,14 @@ class ThemeManager(QtGui.QWidget):
Takes a theme and makes a new copy of it as well as saving it.
"""
log.debug(u'cloneThemeData')
themeData.new_document(newThemeName)
themeData.build_xml_from_attrs()
save_to = None
save_from = None
saveTo = None
saveFrom = None
if themeData.background_type == u'image':
save_to = os.path.join(self.path, newThemeName,
saveTo = os.path.join(self.path, newThemeName,
os.path.split(unicode(themeData.background_filename))[1])
save_from = themeData.background_filename
theme = themeData.extract_xml()
pretty_theme = themeData.extract_formatted_xml()
self.saveTheme(newThemeName, theme, pretty_theme, save_from, save_to)
saveFrom = themeData.background_filename
themeData.theme_name = newThemeName
self.saveTheme(themeData, saveFrom, saveTo)
def onEditTheme(self):
"""
@ -462,17 +459,17 @@ class ThemeManager(QtGui.QWidget):
"""
return self.themelist
def getThemeData(self, themename):
def getThemeData(self, themeName):
"""
Returns a theme object from an XML file
``themename``
``themeName``
Name of the theme to load from file
"""
log.debug(u'getthemedata for theme %s', themename)
xml_file = os.path.join(self.path, unicode(themename),
unicode(themename) + u'.xml')
xml = get_text_file_string(xml_file)
log.debug(u'getthemedata for theme %s', themeName)
xmlFile = os.path.join(self.path, unicode(themeName),
unicode(themeName) + u'.xml')
xml = get_text_file_string(xmlFile)
if not xml:
return self.baseTheme()
else:
@ -640,7 +637,7 @@ class ThemeManager(QtGui.QWidget):
newtheme.display_vertical_align = vAlignCorrection
return newtheme.extract_xml()
def saveTheme(self, theme, image_from, image_to):
def saveTheme(self, theme, imageFrom, imageTo):
"""
Called by thememaintenance Dialog to save the theme
and to trigger the reload of the theme list
@ -673,8 +670,8 @@ class ThemeManager(QtGui.QWidget):
self.deleteTheme(self.saveThemeName)
if result == QtGui.QMessageBox.Yes:
# Save the theme, overwriting the existing theme if necessary.
if image_to and self.oldBackgroundImage and \
image_to != self.oldBackgroundImage:
if imageTo and self.oldBackgroundImage and \
imageTo != self.oldBackgroundImage:
try:
os.remove(self.oldBackgroundImage)
except OSError:
@ -688,12 +685,12 @@ class ThemeManager(QtGui.QWidget):
finally:
if outfile:
outfile.close()
if image_from and image_from != image_to:
if imageFrom and imageFrom != imageTo:
try:
encoding = get_filesystem_encoding()
shutil.copyfile(
unicode(image_from).encode(encoding),
unicode(image_to).encode(encoding))
unicode(imageFrom).encode(encoding),
unicode(imageTo).encode(encoding))
except IOError:
log.exception(u'Failed to save theme image')
self.generateAndSaveImage(self.path, name, theme)
@ -729,7 +726,6 @@ class ThemeManager(QtGui.QWidget):
def generateAndSaveImage(self, dir, name, theme):
log.debug(u'generateAndSaveImage %s %s', dir, name)
#theme = self.createThemeFromXml(theme_xml, dir)
theme_xml = theme.extract_xml()
frame = self.generateImage(theme)
samplepathname = os.path.join(self.path, name + u'.png')
@ -742,12 +738,18 @@ class ThemeManager(QtGui.QWidget):
pixmap.save(thumb, u'png')
log.debug(u'Theme image written to %s', samplepathname)
def generateImage(self, themedata):
def generateImage(self, themeData, forcePage=False):
"""
Call the RenderManager to build a Sample Image
``themeData``
The theme to generated a preview for.
``forcePage``
Flag to tell message lines per page need to be generated.
"""
log.debug(u'generateImage \n%s ', themedata)
return self.parent.RenderManager.generate_preview(themedata)
log.debug(u'generateImage \n%s ', themeData)
return self.parent.RenderManager.generate_preview(themeData, forcePage)
def getPreviewImage(self, theme):
"""
@ -768,14 +770,14 @@ class ThemeManager(QtGui.QWidget):
newtheme = ThemeXML()
return newtheme
def createThemeFromXml(self, theme_xml, path):
def createThemeFromXml(self, themeXml, path):
"""
Return a theme object using information parsed from XML
``theme_xml``
``themeXml``
The XML data to load into the theme
"""
theme = ThemeXML()
theme.parse(theme_xml)
theme.parse(themeXml)
theme.extend_image_filename(path)
return theme

View File

@ -213,7 +213,7 @@ class BGExtract(object):
finally:
if not page:
return None
cleaner = [(re.compile('&nbsp;|<br />'), lambda match: '')]
cleaner = [(re.compile('&nbsp;|<br />|\'\+\''), lambda match: '')]
soup = None
try:
soup = BeautifulSoup(page, markupMassage=cleaner)

View File

@ -415,17 +415,12 @@ class SongMediaItem(MediaManagerItem):
if search_results:
for song in search_results:
count = 0
# temp debug to find why service items do not edit
log.debug(u'author list %s' % author_list)
for author in song.authors:
log.debug(u'author %s' % author.display_name)
if author.display_name in author_list:
count += 1
log.debug(u'found %s : %s' % (count, len(author_list)))
if count == len(author_list):
editId = song.id
uuid = item._uuid
if editId != 0:
Receiver.send_message(u'service_item_update',
u'%s:%s' %(editId, uuid))