This commit is contained in:
Andreas Preikschat 2011-07-26 17:32:02 +02:00
commit f8a705af78
43 changed files with 273 additions and 333 deletions

View File

@ -34,6 +34,7 @@ from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, \
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
# FIXME: Add html5 doctype. However, do not break theme gradients.
HTMLSRC = u""" HTMLSRC = u"""
<html> <html>
<head> <head>
@ -56,44 +57,44 @@ body {
height: %spx; height: %spx;
} }
#black { #black {
z-index:8; z-index: 8;
background-color: black; background-color: black;
display: none; display: none;
} }
#bgimage { #bgimage {
z-index:1; z-index: 1;
} }
#image { #image {
z-index:2; z-index: 2;
} }
#video1 { #video1 {
z-index:3; z-index: 3;
} }
#video2 { #video2 {
z-index:3; z-index: 3;
} }
#alert { #alert {
position: absolute; position: absolute;
left: 0px; left: 0px;
top: 0px; top: 0px;
z-index:10; z-index: 10;
%s %s
} }
#footer { #footer {
position: absolute; position: absolute;
z-index:6; z-index: 6;
%s %s
} }
/* lyric css */ /* lyric css */
%s %s
sup { sup {
font-size:0.6em; font-size: 0.6em;
vertical-align:top; vertical-align: top;
position:relative; position: relative;
top:-0.3em; top: -0.3em;
} }
</style> </style>
<script language="javascript"> <script>
var timer = null; var timer = null;
var video_timer = null; var video_timer = null;
var current_video = '1'; var current_video = '1';
@ -317,10 +318,10 @@ sup {
%s %s
<div id="footer" class="footer"></div> <div id="footer" class="footer"></div>
<div id="black" class="size"></div> <div id="black" class="size"></div>
<div id="alert" style="visibility:hidden;"></div> <div id="alert" style="visibility:hidden"></div>
</body> </body>
</html> </html>
""" """
def build_html(item, screen, alert, islive, background, image=None): def build_html(item, screen, alert, islive, background, image=None):
""" """
@ -446,15 +447,15 @@ def build_lyrics_css(item, webkitvers):
The version of qtwebkit we're using The version of qtwebkit we're using
""" """
style = """ style = u"""
.lyricstable { .lyricstable {
z-index:5; z-index: 5;
position: absolute; position: absolute;
display: table; display: table;
%s %s
} }
.lyricscell { .lyricscell {
display:table-cell; display: table-cell;
word-wrap: break-word; word-wrap: break-word;
%s %s
} }
@ -558,8 +559,8 @@ def build_lyrics_format_css(theme, width, height):
left_margin = 0 left_margin = 0
lyrics = u'white-space:pre-wrap; word-wrap: break-word; ' \ lyrics = u'white-space:pre-wrap; word-wrap: break-word; ' \
'text-align: %s; vertical-align: %s; font-family: %s; ' \ 'text-align: %s; vertical-align: %s; font-family: %s; ' \
'font-size: %spt; color: %s; line-height: %d%%; margin:0;' \ 'font-size: %spt; color: %s; line-height: %d%%; margin: 0;' \
'padding:0; padding-left:%spx; width: %spx; height: %spx; ' % \ 'padding: 0; padding-left: %spx; width: %spx; height: %spx; ' % \
(align, valign, theme.font_main_name, theme.font_main_size, (align, valign, theme.font_main_name, theme.font_main_size,
theme.font_main_color, 100 + int(theme.font_main_line_adjustment), theme.font_main_color, 100 + int(theme.font_main_line_adjustment),
left_margin, width, height) left_margin, width, height)
@ -608,7 +609,7 @@ def build_footer_css(item, height):
``item`` ``item``
Service Item to be processed. Service Item to be processed.
""" """
style = """ style = u"""
left: %spx; left: %spx;
bottom: %spx; bottom: %spx;
width: %spx; width: %spx;
@ -616,7 +617,7 @@ def build_footer_css(item, height):
font-size: %spt; font-size: %spt;
color: %s; color: %s;
text-align: left; text-align: left;
white-space:nowrap; white-space: nowrap;
""" """
theme = item.themedata theme = item.themedata
if not theme or not item.footer: if not theme or not item.footer:
@ -634,7 +635,7 @@ def build_alert_css(alertTab, width):
``alertTab`` ``alertTab``
Details from the Alert tab for fonts etc Details from the Alert tab for fonts etc
""" """
style = """ style = u"""
width: %spx; width: %spx;
vertical-align: %s; vertical-align: %s;
font-family: %s; font-family: %s;

View File

@ -96,7 +96,7 @@ class MediaManagerItem(QtGui.QWidget):
self.plugin = plugin self.plugin = plugin
visible_title = self.plugin.getString(StringContent.VisibleName) visible_title = self.plugin.getString(StringContent.VisibleName)
self.title = unicode(visible_title[u'title']) self.title = unicode(visible_title[u'title'])
self.settingsSection = self.plugin.name.lower() self.settingsSection = self.plugin.name
self.icon = None self.icon = None
if icon: if icon:
self.icon = build_icon(icon) self.icon = build_icon(icon)
@ -113,7 +113,7 @@ class MediaManagerItem(QtGui.QWidget):
self.retranslateUi() self.retranslateUi()
self.auto_select_id = -1 self.auto_select_id = -1
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_service_load' % self.plugin.name.lower()), QtCore.SIGNAL(u'%s_service_load' % self.plugin.name),
self.serviceLoad) self.serviceLoad)
def requiredIcons(self): def requiredIcons(self):
@ -558,7 +558,7 @@ class MediaManagerItem(QtGui.QWidget):
QtGui.QMessageBox.information(self, UiStrings().NISs, QtGui.QMessageBox.information(self, UiStrings().NISs,
translate('OpenLP.MediaManagerItem', translate('OpenLP.MediaManagerItem',
'You must select an existing service item to add to.')) 'You must select an existing service item to add to.'))
elif self.plugin.name.lower() == serviceItem.name.lower(): elif self.plugin.name == serviceItem.name:
self.generateSlideData(serviceItem) self.generateSlideData(serviceItem)
self.plugin.serviceManager.addServiceItem(serviceItem, self.plugin.serviceManager.addServiceItem(serviceItem,
replace=True) replace=True)

View File

@ -152,7 +152,7 @@ class Plugin(QtCore.QObject):
self.version = version self.version = version
else: else:
self.version = get_application_version()[u'version'] self.version = get_application_version()[u'version']
self.settingsSection = self.name.lower() self.settingsSection = self.name
self.icon = None self.icon = None
self.media_item_class = media_item_class self.media_item_class = media_item_class
self.settings_tab_class = settings_tab_class self.settings_tab_class = settings_tab_class

View File

@ -31,7 +31,7 @@ import os
import sys import sys
import logging import logging
from openlp.core.lib import Plugin, StringContent, PluginStatus from openlp.core.lib import Plugin, PluginStatus
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -56,20 +56,20 @@ class Renderer(object):
""" """
log.info(u'Renderer Loaded') log.info(u'Renderer Loaded')
def __init__(self, image_manager, theme_manager): def __init__(self, imageManager, themeManager):
""" """
Initialise the render manager. Initialise the render manager.
``image_manager`` ``imageManager``
A ImageManager instance which takes care of e. g. caching and resizing A ImageManager instance which takes care of e. g. caching and resizing
images. images.
``theme_manager`` ``themeManager``
The ThemeManager instance, used to get the current theme details. The ThemeManager instance, used to get the current theme details.
""" """
log.debug(u'Initialisation started') log.debug(u'Initialisation started')
self.theme_manager = theme_manager self.themeManager = themeManager
self.image_manager = image_manager self.imageManager = imageManager
self.screens = ScreenList.get_instance() self.screens = ScreenList.get_instance()
self.service_theme = u'' self.service_theme = u''
self.theme_level = u'' self.theme_level = u''
@ -77,7 +77,7 @@ class Renderer(object):
self.theme_data = None self.theme_data = None
self.bg_frame = None self.bg_frame = None
self.force_page = False self.force_page = False
self.display = MainDisplay(None, self.image_manager, False) self.display = MainDisplay(None, self.imageManager, False)
self.display.setup() self.display.setup()
def update_display(self): def update_display(self):
@ -88,7 +88,7 @@ class Renderer(object):
self._calculate_default(self.screens.current[u'size']) self._calculate_default(self.screens.current[u'size'])
if self.display: if self.display:
self.display.close() self.display.close()
self.display = MainDisplay(None, self.image_manager, False) self.display = MainDisplay(None, self.imageManager, False)
self.display.setup() self.display.setup()
self.bg_frame = None self.bg_frame = None
self.theme_data = None self.theme_data = None
@ -101,14 +101,14 @@ class Renderer(object):
The global-level theme to be set. The global-level theme to be set.
``theme_level`` ``theme_level``
Defaults to *``ThemeLevel.Global``*. The theme level, can be Defaults to ``ThemeLevel.Global``. The theme level, can be
``ThemeLevel.Global``, ``ThemeLevel.Service`` or ``ThemeLevel.Global``, ``ThemeLevel.Service`` or
``ThemeLevel.Song``. ``ThemeLevel.Song``.
""" """
self.global_theme = global_theme self.global_theme = global_theme
self.theme_level = theme_level self.theme_level = theme_level
self.global_theme_data = \ self.global_theme_data = \
self.theme_manager.getThemeData(self.global_theme) self.themeManager.getThemeData(self.global_theme)
self.theme_data = None self.theme_data = None
def set_service_theme(self, service_theme): def set_service_theme(self, service_theme):
@ -162,12 +162,12 @@ class Renderer(object):
if override_levels: if override_levels:
self.theme_data = override_theme self.theme_data = override_theme
else: else:
self.theme_data = self.theme_manager.getThemeData(theme) self.theme_data = self.themeManager.getThemeData(theme)
self._calculate_default(self.screens.current[u'size']) self._calculate_default(self.screens.current[u'size'])
self._build_text_rectangle(self.theme_data) self._build_text_rectangle(self.theme_data)
# if No file do not update cache # if No file do not update cache
if self.theme_data.background_filename: if self.theme_data.background_filename:
self.image_manager.add_image(self.theme_data.theme_name, self.imageManager.add_image(self.theme_data.theme_name,
self.theme_data.background_filename) self.theme_data.background_filename)
return self._rect, self._rect_footer return self._rect, self._rect_footer
@ -193,7 +193,7 @@ class Renderer(object):
# 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 + VERSE + VERSE) serviceItem.add_from_text(u'', VERSE + VERSE + VERSE)
else: else:
self.image_manager.del_image(theme_data.theme_name) self.imageManager.del_image(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
@ -205,43 +205,52 @@ class Renderer(object):
# Reset the real screen size for subsequent render requests # Reset the real screen size for subsequent render requests
self._calculate_default(self.screens.current[u'size']) self._calculate_default(self.screens.current[u'size'])
return preview return preview
self.force_page = False
def format_slide(self, text, line_break, item): def format_slide(self, text, item):
""" """
Calculate how much text can fit on a slide. Calculate how much text can fit on a slide.
``text`` ``text``
The words to go on the slides. The words to go on the slides.
``line_break`` ``item``
Add line endings after each line of text used for bibles. The :class:`~openlp.core.lib.serviceitem.ServiceItem` item object.
""" """
log.debug(u'format slide') log.debug(u'format slide')
# clean up line endings # Add line endings after each line of text used for bibles.
lines = self._lines_split(text) line_end = u'<br>'
pages = self._paginate_slide(lines, line_break, self.force_page) if item.is_capable(ItemCapabilities.NoLineBreaks):
if len(pages) > 1: line_end = u' '
# Songs and Custom # Bibles
if item.is_capable(ItemCapabilities.AllowsVirtualSplit): if item.is_capable(ItemCapabilities.AllowsWordSplit):
# Do not forget the line breaks ! pages = self._paginate_slide_words(text, line_end)
slides = text.split(u'[---]') else:
pages = [] # Clean up line endings.
for slide in slides: lines = self._lines_split(text)
lines = slide.strip(u'\n').split(u'\n') pages = self._paginate_slide(lines, line_end)
new_pages = self._paginate_slide(lines, line_break, if len(pages) > 1:
self.force_page) # Songs and Custom
pages.extend(new_pages) if item.is_capable(ItemCapabilities.AllowsVirtualSplit):
# Bibles # Do not forget the line breaks!
elif item.is_capable(ItemCapabilities.AllowsWordSplit): slides = text.split(u'[---]')
pages = self._paginate_slide_words(text, line_break) pages = []
return pages for slide in slides:
lines = slide.strip(u'\n').split(u'\n')
pages.extend(self._paginate_slide(lines, line_end))
new_pages = []
for page in pages:
while page.endswith(u'<br>'):
page = page[:-4]
new_pages.append(page)
return new_pages
def _calculate_default(self, screen): def _calculate_default(self, screen):
""" """
Calculate the default dimentions of the screen. Calculate the default dimentions of the screen.
``screen`` ``screen``
The QSize of the screen. The screen to calculate the default of.
""" """
log.debug(u'_calculate default %s', screen) log.debug(u'_calculate default %s', screen)
self.width = screen.width() self.width = screen.width()
@ -301,61 +310,44 @@ class Renderer(object):
self.web.resize(self.page_width, self.page_height) self.web.resize(self.page_width, self.page_height)
self.web_frame = self.web.page().mainFrame() self.web_frame = self.web.page().mainFrame()
# Adjust width and height to account for shadow. outline done in css # Adjust width and height to account for shadow. outline done in css
self.page_shell = u'<html><head><style>' \ self.page_shell = u'<!DOCTYPE html><html><head><style>' \
u'*{margin: 0; padding: 0; border: 0;} '\ u'*{margin:0; padding:0; border:0;} '\
u'#main {position:absolute; top:0px; %s %s}</style></head><body>' \ u'#main {position:absolute; top:0px; %s %s}</style></head><body>' \
u'<div id="main">' % \ u'<div id="main">' % \
(build_lyrics_format_css(self.theme_data, self.page_width, (build_lyrics_format_css(self.theme_data, self.page_width,
self.page_height), build_lyrics_outline_css(self.theme_data)) self.page_height), build_lyrics_outline_css(self.theme_data))
def _paginate_slide(self, lines, line_break, force_page=False): def _paginate_slide(self, lines, line_end):
""" """
Figure out how much text can appear on a slide, using the current Figure out how much text can appear on a slide, using the current
theme settings. theme settings.
``lines`` ``lines``
The words to be fitted on the slide split into lines. The text to be fitted on the slide split into lines.
``line_break``
Add line endings after each line of text (used for bibles).
``force_page``
Flag to tell message lines in page.
``line_end``
The text added after each line. Either ``u' '`` or ``u'<br>``.
""" """
log.debug(u'_paginate_slide - Start') log.debug(u'_paginate_slide - Start')
line_end = u''
if line_break:
line_end = u'<br>'
formatted = [] formatted = []
html_text = u'' previous_html = u''
styled_text = u'' previous_raw = u''
line_count = 0 separator = u'<br>'
for line in lines: html_lines = map(expand_tags, lines)
if line_count != -1: html = self.page_shell + separator.join(html_lines) + HTML_END
line_count += 1 self.web.setHtml(html)
styled_line = expand_tags(line) + line_end # Text too long so go to next page.
styled_text += styled_line if self.web_frame.contentsSize().height() > self.page_height:
html = self.page_shell + styled_text + HTML_END html_text, previous_raw = self._binary_chop(formatted,
self.web.setHtml(html) previous_html, previous_raw, html_lines, lines, separator, u'')
# Text too long so go to next page. else:
if self.web_frame.contentsSize().height() > self.page_height: previous_raw = separator.join(lines)
if force_page and line_count > 0: if previous_raw:
Receiver.send_message(u'theme_line_count', line_count - 1) formatted.append(previous_raw)
line_count = -1
while html_text.endswith(u'<br>'):
html_text = html_text[:-4]
formatted.append(html_text)
html_text = u''
styled_text = styled_line
html_text += line + line_end
while html_text.endswith(u'<br>'):
html_text = html_text[:-4]
formatted.append(html_text)
log.debug(u'_paginate_slide - End') log.debug(u'_paginate_slide - End')
return formatted return formatted
def _paginate_slide_words(self, text, line_break): def _paginate_slide_words(self, text, line_end):
""" """
Figure out how much text can appear on a slide, using the current Figure out how much text can appear on a slide, using the current
theme settings. This version is to handle text which needs to be split theme settings. This version is to handle text which needs to be split
@ -364,22 +356,19 @@ class Renderer(object):
``text`` ``text``
The words to be fitted on the slide split into lines. The words to be fitted on the slide split into lines.
``line_break`` ``line_end``
Add line endings after each line of text used for bibles. The text added after each line. Either ``u' '`` or ``u'<br>``.
This is needed for bibles.
""" """
log.debug(u'_paginate_slide_words - Start') log.debug(u'_paginate_slide_words - Start')
line_end = u' '
if line_break:
line_end = u'<br>'
formatted = [] formatted = []
previous_html = u'' previous_html = u''
previous_raw = u'' previous_raw = u''
lines = text.split(u'\n') lines = text.split(u'\n')
for line in lines: for line in lines:
line = line.strip() line = line.strip()
styled_line = expand_tags(line) html_line = expand_tags(line)
html = self.page_shell + previous_html + styled_line + HTML_END html = self.page_shell + previous_html + html_line + HTML_END
self.web.setHtml(html) self.web.setHtml(html)
# Text too long so go to next page. # Text too long so go to next page.
if self.web_frame.contentsSize().height() > self.page_height: if self.web_frame.contentsSize().height() > self.page_height:
@ -390,88 +379,123 @@ class Renderer(object):
self.web.setHtml(html) self.web.setHtml(html)
if self.web_frame.contentsSize().height() <= \ if self.web_frame.contentsSize().height() <= \
self.page_height: self.page_height:
while previous_raw.endswith(u'<br>'):
previous_raw = previous_raw[:-4]
formatted.append(previous_raw) formatted.append(previous_raw)
previous_html = u'' previous_html = u''
previous_raw = u'' previous_raw = u''
html = self.page_shell + styled_line + HTML_END html = self.page_shell + html_line + HTML_END
self.web.setHtml(html) self.web.setHtml(html)
# Now check if the current verse will fit, if it does # Now check if the current verse will fit, if it does
# not we have to start to process the verse word by # not we have to start to process the verse word by
# word. # word.
if self.web_frame.contentsSize().height() <= \ if self.web_frame.contentsSize().height() <= \
self.page_height: self.page_height:
previous_html = styled_line + line_end previous_html = html_line + line_end
previous_raw = line + line_end previous_raw = line + line_end
continue continue
# Figure out how many words of the line will fit on screen by # Figure out how many words of the line will fit on screen as
# using the algorithm known as "binary chop". # the line will not fit as a whole.
raw_words = self._words_split(line) raw_words = self._words_split(line)
html_words = [expand_tags(word) for word in raw_words] html_words = map(expand_tags, raw_words)
smallest_index = 0 previous_html, previous_raw = self._binary_chop(
highest_index = len(html_words) - 1 formatted, previous_html, previous_raw, html_words,
index = int(highest_index / 2) raw_words, u' ', line_end)
while True:
html = self.page_shell + previous_html + \
u''.join(html_words[:index + 1]).strip() + HTML_END
self.web.setHtml(html)
if self.web_frame.contentsSize().height() > \
self.page_height:
# We know that it does not fit, so change/calculate the
# new index and highest_index accordingly.
highest_index = index
index = int(index - (index - smallest_index) / 2)
else:
smallest_index = index
index = int(index + (highest_index - index) / 2)
# We found the number of words which will fit.
if smallest_index == index or highest_index == index:
index = smallest_index
formatted.append(previous_raw.rstrip(u'<br>') +
u''.join(raw_words[:index + 1]))
previous_html = u''
previous_raw = u''
else:
continue
# Check if the rest of the line fits on the slide. If it
# does we do not have to do the much more intensive "word by
# word" checking.
html = self.page_shell + \
u''.join(html_words[index + 1:]).strip() + HTML_END
self.web.setHtml(html)
if self.web_frame.contentsSize().height() <= \
self.page_height:
previous_html = \
u''.join(html_words[index + 1:]).strip() + line_end
previous_raw = \
u''.join(raw_words[index + 1:]).strip() + line_end
break
else:
# The other words do not fit, thus reset the indexes,
# create a new list and continue with "word by word".
raw_words = raw_words[index + 1:]
html_words = html_words[index + 1:]
smallest_index = 0
highest_index = len(html_words) - 1
index = int(highest_index / 2)
else: else:
previous_html += styled_line + line_end previous_html += html_line + line_end
previous_raw += line + line_end previous_raw += line + line_end
while previous_raw.endswith(u'<br>'):
previous_raw = previous_raw[:-4]
formatted.append(previous_raw) formatted.append(previous_raw)
log.debug(u'_paginate_slide_words - End') log.debug(u'_paginate_slide_words - End')
return formatted return formatted
def _binary_chop(self, formatted, previous_html, previous_raw, html_list,
raw_list, separator, line_end):
"""
This implements the binary chop algorithm for faster rendering. This
algorithm works line based (line by line) and word based (word by word).
It is assumed that this method is **only** called, when the lines/words
to be rendered do **not** fit as a whole.
``formatted``
The list to append any slides.
``previous_html``
The html text which is know to fit on a slide, but is not yet added
to the list of slides. (unicode string)
``previous_raw``
The raw text (with display tags) which is know to fit on a slide,
but is not yet added to the list of slides. (unicode string)
``html_list``
The elements which do not fit on a slide and needs to be processed
using the binary chop. The text contains html.
``raw_list``
The elements which do not fit on a slide and needs to be processed
using the binary chop. The elements can contain display tags.
``separator``
The separator for the elements. For lines this is ``u'<br>'`` and
for words this is ``u' '``.
``line_end``
The text added after each "element line". Either ``u' '`` or
``u'<br>``. This is needed for bibles.
"""
smallest_index = 0
highest_index = len(html_list) - 1
index = int(highest_index / 2)
while True:
html = self.page_shell + previous_html + \
separator.join(html_list[:index + 1]).strip() + HTML_END
self.web.setHtml(html)
if self.web_frame.contentsSize().height() > self.page_height:
# We know that it does not fit, so change/calculate the
# new index and highest_index accordingly.
highest_index = index
index = int(index - (index - smallest_index) / 2)
else:
smallest_index = index
index = int(index + (highest_index - index) / 2)
# We found the number of words which will fit.
if smallest_index == index or highest_index == index:
index = smallest_index
formatted.append(previous_raw.rstrip(u'<br>') +
separator.join(raw_list[:index + 1]))
previous_html = u''
previous_raw = u''
# Stop here as the theme line count was requested.
if self.force_page:
Receiver.send_message(u'theme_line_count', index + 1)
break
else:
continue
# Check if the remaining elements fit on the slide.
html = self.page_shell + \
separator.join(html_list[index + 1:]).strip() + HTML_END
self.web.setHtml(html)
if self.web_frame.contentsSize().height() <= self.page_height:
previous_html = separator.join(
html_list[index + 1:]).strip() + line_end
previous_raw = separator.join(
raw_list[index + 1:]).strip() + line_end
break
else:
# The remaining elements do not fit, thus reset the indexes,
# create a new list and continue.
raw_list = raw_list[index + 1:]
html_list = html_list[index + 1:]
smallest_index = 0
highest_index = len(html_list) - 1
index = int(highest_index / 2)
return previous_html, previous_raw
def _words_split(self, line): def _words_split(self, line):
""" """
Split the slide up by word so can wrap better Split the slide up by word so can wrap better
""" """
# this parse we are to be wordy # this parse we are to be wordy
line = line.replace(u'\n', u' ') line = line.replace(u'\n', u' ')
words = line.split(u' ') return line.split(u' ')
return [word + u' ' for word in words]
def _lines_split(self, text): def _lines_split(self, text):
""" """
@ -479,5 +503,5 @@ class Renderer(object):
""" """
# this parse we do not want to use this so remove it # this parse we do not want to use this so remove it
text = text.replace(u'\n[---]', u'') text = text.replace(u'\n[---]', u'')
lines = text.split(u'\n') text = text.replace(u'[---]', u'')
return [line.replace(u'[---]', u'') for line in lines] return text.split(u'\n')

View File

@ -36,7 +36,6 @@ import os
import uuid import uuid
from openlp.core.lib import build_icon, clean_tags, expand_tags, translate from openlp.core.lib import build_icon, clean_tags, expand_tags, translate
from openlp.core.lib.ui import UiStrings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -165,7 +164,6 @@ class ServiceItem(object):
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
line_break = not self.is_capable(ItemCapabilities.NoLineBreaks)
theme = self.theme if self.theme else None theme = self.theme if self.theme else None
self.main, self.footer = \ self.main, self.footer = \
self.renderer.set_override_theme(theme, use_override) self.renderer.set_override_theme(theme, use_override)
@ -173,9 +171,8 @@ class ServiceItem(object):
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:
formatted = self.renderer \ pages = self.renderer.format_slide(slide[u'raw_slide'], self)
.format_slide(slide[u'raw_slide'], line_break, self) for page in pages:
for page in formatted:
page = page.replace(u'<br>', u'{br}') page = page.replace(u'<br>', u'{br}')
html = expand_tags(cgi.escape(page.rstrip())) html = expand_tags(cgi.escape(page.rstrip()))
self._display_frames.append({ self._display_frames.append({
@ -210,7 +207,7 @@ class ServiceItem(object):
""" """
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.image_manager.add_image(title, path) self.renderer.imageManager.add_image(title, path)
self._new_item() self._new_item()
def add_from_text(self, title, raw_slide, verse_tag=None): def add_from_text(self, title, raw_slide, verse_tag=None):
@ -464,7 +461,7 @@ class ServiceItem(object):
elif not start and end: elif not start and end:
return end return end
else: else:
return u'%s <br />%s' % (start, end) return u'%s <br>%s' % (start, end)
def update_theme(self, theme): def update_theme(self, theme):
""" """

View File

@ -57,7 +57,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
self.dictionary = enchant.Dict() self.dictionary = enchant.Dict()
self.highlighter = Highlighter(self.document()) self.highlighter = Highlighter(self.document())
self.highlighter.spellingDictionary = self.dictionary self.highlighter.spellingDictionary = self.dictionary
except Error, DictNotFoundError: except (Error, DictNotFoundError):
ENCHANT_AVAILABLE = False ENCHANT_AVAILABLE = False
log.debug(u'Could not load default dictionary') log.debug(u'Could not load default dictionary')

View File

@ -34,8 +34,7 @@ import logging
from xml.dom.minidom import Document from xml.dom.minidom import Document
from lxml import etree, objectify from lxml import etree, objectify
from openlp.core.lib import str_to_bool, translate from openlp.core.lib import str_to_bool
from openlp.core.lib.ui import UiStrings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -28,7 +28,7 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.ui import UiStrings, create_accept_reject_button_box from openlp.core.lib.ui import UiStrings
class Ui_DisplayTagDialog(object): class Ui_DisplayTagDialog(object):

View File

@ -49,7 +49,7 @@ class Ui_FirstTimeWizard(object):
FirstTimeWizard.resize(550, 386) FirstTimeWizard.resize(550, 386)
FirstTimeWizard.setModal(True) FirstTimeWizard.setModal(True)
FirstTimeWizard.setWizardStyle(QtGui.QWizard.ModernStyle) FirstTimeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
FirstTimeWizard.setOptions(QtGui.QWizard.IndependentPages| FirstTimeWizard.setOptions(QtGui.QWizard.IndependentPages |
QtGui.QWizard.NoBackButtonOnStartPage | QtGui.QWizard.NoBackButtonOnStartPage |
QtGui.QWizard.NoBackButtonOnLastPage) QtGui.QWizard.NoBackButtonOnLastPage)
self.finishButton = self.button(QtGui.QWizard.FinishButton) self.finishButton = self.button(QtGui.QWizard.FinishButton)
@ -81,9 +81,9 @@ class Ui_FirstTimeWizard(object):
self.pluginLayout.addWidget(self.imageCheckBox) self.pluginLayout.addWidget(self.imageCheckBox)
self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage) self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage)
if sys.platform == "darwin": if sys.platform == "darwin":
self.presentationCheckBox.setChecked(False) self.presentationCheckBox.setChecked(False)
else: else:
self.presentationCheckBox.setChecked(True) self.presentationCheckBox.setChecked(True)
self.presentationCheckBox.setObjectName(u'presentationCheckBox') self.presentationCheckBox.setObjectName(u'presentationCheckBox')
self.pluginLayout.addWidget(self.presentationCheckBox) self.pluginLayout.addWidget(self.presentationCheckBox)
self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage) self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage)

View File

@ -48,13 +48,13 @@ class MainDisplay(QtGui.QGraphicsView):
""" """
This is the display screen. This is the display screen.
""" """
def __init__(self, parent, image_manager, live): def __init__(self, parent, imageManager, live):
if live: if live:
QtGui.QGraphicsView.__init__(self) QtGui.QGraphicsView.__init__(self)
else: else:
QtGui.QGraphicsView.__init__(self, parent) QtGui.QGraphicsView.__init__(self, parent)
self.isLive = live self.isLive = live
self.image_manager = image_manager self.imageManager = imageManager
self.screens = ScreenList.get_instance() self.screens = ScreenList.get_instance()
self.alertTab = None self.alertTab = None
self.hideMode = None self.hideMode = None
@ -232,7 +232,7 @@ class MainDisplay(QtGui.QGraphicsView):
""" """
API for replacement backgrounds so Images are added directly to cache API for replacement backgrounds so Images are added directly to cache
""" """
self.image_manager.add_image(name, path) self.imageManager.add_image(name, path)
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
@ -249,7 +249,7 @@ class MainDisplay(QtGui.QGraphicsView):
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.image_manager.get_image_bytes(name) image = self.imageManager.get_image_bytes(name)
self.resetVideo() self.resetVideo()
self.displayImage(image) self.displayImage(image)
return self.preview() return self.preview()
@ -482,13 +482,13 @@ class MainDisplay(QtGui.QGraphicsView):
self.override = {} self.override = {}
else: else:
# replace the background # replace the background
background = self.image_manager. \ background = self.imageManager. \
get_image_bytes(self.override[u'image']) get_image_bytes(self.override[u'image'])
if self.serviceItem.themedata.background_filename: if self.serviceItem.themedata.background_filename:
self.serviceItem.bg_image_bytes = self.image_manager. \ self.serviceItem.bg_image_bytes = self.imageManager. \
get_image_bytes(self.serviceItem.themedata.theme_name) get_image_bytes(self.serviceItem.themedata.theme_name)
if image: if image:
image_bytes = self.image_manager.get_image_bytes(image) image_bytes = self.imageManager.get_image_bytes(image)
else: else:
image_bytes = None image_bytes = None
html = build_html(self.serviceItem, self.screen, self.alertTab, html = build_html(self.serviceItem, self.screen, self.alertTab,

View File

@ -66,7 +66,7 @@ class MediaDockManager(object):
match = False match = False
for dock_index in range(0, self.media_dock.count()): for dock_index in range(0, self.media_dock.count()):
if self.media_dock.widget(dock_index).settingsSection == \ if self.media_dock.widget(dock_index).settingsSection == \
media_item.plugin.name.lower(): media_item.plugin.name:
match = True match = True
break break
if not match: if not match:
@ -84,6 +84,6 @@ class MediaDockManager(object):
for dock_index in range(0, self.media_dock.count()): for dock_index in range(0, self.media_dock.count()):
if self.media_dock.widget(dock_index): if self.media_dock.widget(dock_index):
if self.media_dock.widget(dock_index).settingsSection == \ if self.media_dock.widget(dock_index).settingsSection == \
media_item.plugin.name.lower(): media_item.plugin.name:
self.media_dock.widget(dock_index).setVisible(False) self.media_dock.widget(dock_index).setVisible(False)
self.media_dock.removeItem(dock_index) self.media_dock.removeItem(dock_index)

View File

@ -240,7 +240,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
translate('OpenLP.ServiceManager', 'Notes: '), p, translate('OpenLP.ServiceManager', 'Notes: '), p,
classId=u'itemNotesTitle') classId=u'itemNotesTitle')
notes = self._addElement(u'span', notes = self._addElement(u'span',
item.notes.replace(u'\n', u'<br />'), p, item.notes.replace(u'\n', u'<br>'), p,
classId=u'itemNotesText') classId=u'itemNotesText')
# Add play length of media files. # Add play length of media files.
if item.is_media() and self.metaDataCheckBox.isChecked(): if item.is_media() and self.metaDataCheckBox.isChecked():

View File

@ -781,48 +781,25 @@ class ServiceManager(QtGui.QWidget):
def onMoveSelectionUp(self): def onMoveSelectionUp(self):
""" """
Moves the selection up the window. Called by the up arrow. Moves the cursor selection up the window.
Called by the up arrow.
""" """
serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList) item = self.serviceManagerList.currentItem()
tempItem = None itemBefore = self.serviceManagerList.itemAbove(item)
setLastItem = False if itemBefore is None:
while serviceIterator.value(): return
if serviceIterator.value().isSelected() and tempItem is None: self.serviceManagerList.setCurrentItem(itemBefore)
setLastItem = True
serviceIterator.value().setSelected(False)
if serviceIterator.value().isSelected():
# We are on the first record
if tempItem:
tempItem.setSelected(True)
serviceIterator.value().setSelected(False)
else:
tempItem = serviceIterator.value()
lastItem = serviceIterator.value()
serviceIterator += 1
# Top Item was selected so set the last one
if setLastItem:
lastItem.setSelected(True)
def onMoveSelectionDown(self): def onMoveSelectionDown(self):
""" """
Moves the selection down the window. Called by the down arrow. Moves the cursor selection down the window.
Called by the down arrow.
""" """
serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList) item = self.serviceManagerList.currentItem()
firstItem = None itemAfter = self.serviceManagerList.itemBelow(item)
setSelected = False if itemAfter is None:
while serviceIterator.value(): return
if not firstItem: self.serviceManagerList.setCurrentItem(itemAfter)
firstItem = serviceIterator.value()
if setSelected:
setSelected = False
serviceIterator.value().setSelected(True)
elif serviceIterator.value() and \
serviceIterator.value().isSelected():
serviceIterator.value().setSelected(False)
setSelected = True
serviceIterator += 1
if setSelected:
firstItem.setSelected(True)
def onCollapseAll(self): def onCollapseAll(self):
""" """
@ -966,7 +943,7 @@ class ServiceManager(QtGui.QWidget):
if item[u'service_item'] \ if item[u'service_item'] \
.is_capable(ItemCapabilities.AllowsVariableStartTime): .is_capable(ItemCapabilities.AllowsVariableStartTime):
tips.append(item[u'service_item'].get_media_time()) tips.append(item[u'service_item'].get_media_time())
treewidgetitem.setToolTip(0, u'<br />'.join(tips)) treewidgetitem.setToolTip(0, u'<br>'.join(tips))
treewidgetitem.setData(0, QtCore.Qt.UserRole, treewidgetitem.setData(0, QtCore.Qt.UserRole,
QtCore.QVariant(item[u'order'])) QtCore.QVariant(item[u'order']))
treewidgetitem.setSelected(item[u'selected']) treewidgetitem.setSelected(item[u'selected'])

View File

@ -29,7 +29,7 @@ The :mod:`settingsform` provides a user interface for the OpenLP settings
""" """
import logging import logging
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui
from openlp.core.lib import Receiver, build_icon, PluginStatus from openlp.core.lib import Receiver, build_icon, PluginStatus
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab

View File

@ -247,7 +247,8 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
alternate_label_text = action.defaultShortcuts[1].toString() alternate_label_text = action.defaultShortcuts[1].toString()
shortcuts = self._actionShortcuts(action) shortcuts = self._actionShortcuts(action)
# We do not want to loose pending changes, that is why we have to # We do not want to loose pending changes, that is why we have to
# keep the text when, this function has not been triggered by a signal. # keep the text when, this function has not been triggered by a
# signal.
if item is None: if item is None:
primary_text = self.primaryPushButton.text() primary_text = self.primaryPushButton.text()
alternate_text = self.alternatePushButton.text() alternate_text = self.alternatePushButton.text()
@ -280,7 +281,8 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
""" """
Restores all default shortcuts. Restores all default shortcuts.
""" """
if self.buttonBox.buttonRole(button) != QtGui.QDialogButtonBox.ResetRole: if self.buttonBox.buttonRole(button) != \
QtGui.QDialogButtonBox.ResetRole:
return return
if QtGui.QMessageBox.question(self, if QtGui.QMessageBox.question(self,
translate('OpenLP.ShortcutListDialog', 'Restore Default Shortcuts'), translate('OpenLP.ShortcutListDialog', 'Restore Default Shortcuts'),

View File

@ -33,8 +33,8 @@ import copy
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon from PyQt4.phonon import Phonon
from openlp.core.lib import OpenLPToolbar, Receiver, resize_image, \ from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \
ItemCapabilities, translate, build_icon translate, build_icon
from openlp.core.lib.ui import UiStrings, shortcut_action from openlp.core.lib.ui import UiStrings, shortcut_action
from openlp.core.ui import HideMode, MainDisplay, ScreenList from openlp.core.ui import HideMode, MainDisplay, ScreenList
from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.utils.actions import ActionList, CategoryOrder
@ -508,6 +508,11 @@ class SlideController(QtGui.QWidget):
self.mediabar.setVisible(False) self.mediabar.setVisible(False)
self.toolbar.makeWidgetsInvisible([u'Song Menu']) self.toolbar.makeWidgetsInvisible([u'Song Menu'])
self.toolbar.makeWidgetsInvisible(self.loopList) self.toolbar.makeWidgetsInvisible(self.loopList)
# Reset the button
self.playSlidesOnce.setChecked(False)
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time.png'))
self.playSlidesLoop.setChecked(False)
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
if item.is_text(): if item.is_text():
if QtCore.QSettings().value( if QtCore.QSettings().value(
self.parent().songsSettingsSection + u'/display songbar', self.parent().songsSettingsSection + u'/display songbar',

View File

@ -459,25 +459,6 @@ def file_is_unicode(filename):
return None return None
return ucsfile return ucsfile
def string_is_unicode(test_string):
"""
Makes sure a string is unicode.
``test_string``
The string to confirm is unicode.
"""
return_string = u''
if not test_string:
return return_string
if isinstance(test_string, unicode):
return_string = test_string
if not isinstance(test_string, unicode):
try:
return_string = unicode(test_string, u'utf-8')
except UnicodeError:
log.exception("Error encoding string to unicode")
return return_string
def get_uno_command(): def get_uno_command():
""" """
Returns the UNO command to launch an openoffice.org instance. Returns the UNO command to launch an openoffice.org instance.
@ -510,5 +491,5 @@ from actions import ActionList
__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version', __all__ = [u'AppLocation', u'get_application_version', u'check_latest_version',
u'add_actions', u'get_filesystem_encoding', u'LanguageManager', u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
u'ActionList', u'get_web_page', u'file_is_unicode', u'string_is_unicode', u'ActionList', u'get_web_page', u'file_is_unicode', u'get_uno_command',
u'get_uno_command', u'get_uno_instance', u'delete_file'] u'get_uno_instance', u'delete_file']

View File

@ -27,7 +27,7 @@
import logging import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore
from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.db import Manager from openlp.core.lib.db import Manager
@ -43,7 +43,7 @@ class AlertsPlugin(Plugin):
log.info(u'Alerts Plugin loaded') log.info(u'Alerts Plugin loaded')
def __init__(self, plugin_helpers): def __init__(self, plugin_helpers):
Plugin.__init__(self, u'Alerts', plugin_helpers, Plugin.__init__(self, u'alerts', plugin_helpers,
settings_tab_class=AlertsTab) settings_tab_class=AlertsTab)
self.weight = -3 self.weight = -3
self.icon_path = u':/plugins/plugin_alerts.png' self.icon_path = u':/plugins/plugin_alerts.png'

View File

@ -41,7 +41,7 @@ class BiblePlugin(Plugin):
log.info(u'Bible Plugin loaded') log.info(u'Bible Plugin loaded')
def __init__(self, plugin_helpers): def __init__(self, plugin_helpers):
Plugin.__init__(self, u'Bibles', plugin_helpers, Plugin.__init__(self, u'bibles', plugin_helpers,
BibleMediaItem, BiblesTab) BibleMediaItem, BiblesTab)
self.weight = -9 self.weight = -9
self.icon_path = u':/plugins/plugin_bibles.png' self.icon_path = u':/plugins/plugin_bibles.png'

View File

@ -27,7 +27,6 @@
""" """
The bible import functions for OpenLP The bible import functions for OpenLP
""" """
import csv
import logging import logging
import os import os
import os.path import os.path
@ -39,7 +38,7 @@ from openlp.core.lib import Receiver, translate
from openlp.core.lib.db import delete_database from openlp.core.lib.db import delete_database
from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
from openlp.core.utils import AppLocation, string_is_unicode from openlp.core.utils import AppLocation
from openlp.plugins.bibles.lib.manager import BibleFormat from openlp.plugins.bibles.lib.manager import BibleFormat
from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename

View File

@ -38,7 +38,7 @@ from openlp.core.lib.db import delete_database
from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
from openlp.core.utils import AppLocation, delete_file from openlp.core.utils import AppLocation, delete_file
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB,\ from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, \
BiblesResourcesDB, clean_filename BiblesResourcesDB, clean_filename
from openlp.plugins.bibles.lib.http import BSExtract, BGExtract, CWExtract from openlp.plugins.bibles.lib.http import BSExtract, BGExtract, CWExtract

View File

@ -36,7 +36,7 @@ from sqlalchemy import Column, ForeignKey, or_, Table, types
from sqlalchemy.orm import class_mapper, mapper, relation from sqlalchemy.orm import class_mapper, mapper, relation
from sqlalchemy.orm.exc import UnmappedClassError from sqlalchemy.orm.exc import UnmappedClassError
from openlp.core.lib import Receiver, translate, check_directory_exists from openlp.core.lib import Receiver, translate
from openlp.core.lib.db import BaseModel, init_db, Manager from openlp.core.lib.db import BaseModel, init_db, Manager
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation

View File

@ -29,9 +29,7 @@ The :mod:`http` module enables OpenLP to retrieve scripture from bible
websites. websites.
""" """
import logging import logging
import os
import re import re
import sqlite3
import socket import socket
import urllib import urllib
from HTMLParser import HTMLParseError from HTMLParser import HTMLParseError
@ -40,7 +38,7 @@ from BeautifulSoup import BeautifulSoup, NavigableString, Tag
from openlp.core.lib import Receiver, translate from openlp.core.lib import Receiver, translate
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation, get_web_page from openlp.core.utils import get_web_page
from openlp.plugins.bibles.lib import SearchResults from openlp.plugins.bibles.lib import SearchResults
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, \ from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, \
Book Book

View File

@ -34,7 +34,7 @@ from openlp.core.lib import Receiver, SettingsManager, translate
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation, delete_file from openlp.core.utils import AppLocation, delete_file
from openlp.plugins.bibles.lib import parse_reference from openlp.plugins.bibles.lib import parse_reference
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
from csvbible import CSVBible from csvbible import CSVBible
from http import HTTPBible from http import HTTPBible
from opensong import OpenSongBible from opensong import OpenSongBible

View File

@ -46,7 +46,7 @@ class CustomPlugin(Plugin):
log.info(u'Custom Plugin loaded') log.info(u'Custom Plugin loaded')
def __init__(self, plugin_helpers): def __init__(self, plugin_helpers):
Plugin.__init__(self, u'Custom', plugin_helpers, Plugin.__init__(self, u'custom', plugin_helpers,
CustomMediaItem, CustomTab) CustomMediaItem, CustomTab)
self.weight = -5 self.weight = -5
self.manager = Manager(u'custom', init_schema) self.manager = Manager(u'custom', init_schema)

View File

@ -36,7 +36,7 @@ class ImagePlugin(Plugin):
log.info(u'Image Plugin loaded') log.info(u'Image Plugin loaded')
def __init__(self, plugin_helpers): def __init__(self, plugin_helpers):
Plugin.__init__(self, u'Images', plugin_helpers, ImageMediaItem) Plugin.__init__(self, u'images', plugin_helpers, ImageMediaItem)
self.weight = -7 self.weight = -7
self.icon_path = u':/plugins/plugin_images.png' self.icon_path = u':/plugins/plugin_images.png'
self.icon = build_icon(self.icon_path) self.icon = build_icon(self.icon_path)

View File

@ -39,7 +39,7 @@ class MediaPlugin(Plugin):
log.info(u'%s MediaPlugin loaded', __name__) log.info(u'%s MediaPlugin loaded', __name__)
def __init__(self, plugin_helpers): def __init__(self, plugin_helpers):
Plugin.__init__(self, u'Media', plugin_helpers, Plugin.__init__(self, u'media', plugin_helpers,
MediaMediaItem, MediaTab) MediaMediaItem, MediaTab)
self.weight = -6 self.weight = -6
self.icon_path = u':/plugins/plugin_media.png' self.icon_path = u':/plugins/plugin_media.png'

View File

@ -52,7 +52,7 @@ class PresentationPlugin(Plugin):
""" """
log.debug(u'Initialised') log.debug(u'Initialised')
self.controllers = {} self.controllers = {}
Plugin.__init__(self, u'Presentations', plugin_helpers) Plugin.__init__(self, u'presentations', plugin_helpers)
self.weight = -8 self.weight = -8
self.icon_path = u':/plugins/plugin_presentations.png' self.icon_path = u':/plugins/plugin_presentations.png'
self.icon = build_icon(self.icon_path) self.icon = build_icon(self.icon_path)

View File

@ -357,7 +357,8 @@ class HttpConnection(object):
if ext == u'.html': if ext == u'.html':
mimetype = u'text/html' mimetype = u'text/html'
variables = self.template_vars variables = self.template_vars
html = Template(filename=path, input_encoding=u'utf-8', output_encoding=u'utf-8').render(**variables) html = Template(filename=path, input_encoding=u'utf-8',
output_encoding=u'utf-8').render(**variables)
elif ext == u'.css': elif ext == u'.css':
mimetype = u'text/css' mimetype = u'text/css'
elif ext == u'.js': elif ext == u'.js':

View File

@ -39,7 +39,7 @@ class RemotesPlugin(Plugin):
""" """
remotes constructor remotes constructor
""" """
Plugin.__init__(self, u'Remotes', plugin_helpers, Plugin.__init__(self, u'remotes', plugin_helpers,
settings_tab_class=RemoteTab) settings_tab_class=RemoteTab)
self.icon_path = u':/plugins/plugin_remote.png' self.icon_path = u':/plugins/plugin_remote.png'
self.icon = build_icon(self.icon_path) self.icon = build_icon(self.icon_path)

View File

@ -90,7 +90,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.onVerseListViewPressed) self.onVerseListViewPressed)
QtCore.QObject.connect(self.themeAddButton, QtCore.QObject.connect(self.themeAddButton,
QtCore.SIGNAL(u'clicked()'), QtCore.SIGNAL(u'clicked()'),
self.mediaitem.plugin.renderer.theme_manager.onAddTheme) self.mediaitem.plugin.renderer.themeManager.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(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),

View File

@ -29,7 +29,7 @@ The :mod:`db` module provides the database and schema that is the backend for
the Songs plugin the Songs plugin
""" """
from sqlalchemy import Column, ForeignKey, Index, Table, types from sqlalchemy import Column, ForeignKey, Table, types
from sqlalchemy.orm import mapper, relation from sqlalchemy.orm import mapper, relation
from openlp.core.lib.db import BaseModel, init_db from openlp.core.lib.db import BaseModel, init_db

View File

@ -26,13 +26,10 @@
############################################################################### ###############################################################################
import logging import logging
import os
import re import re
from lxml import etree, objectify from lxml import etree, objectify
from openlp.core.lib import translate
from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport

View File

@ -34,7 +34,6 @@ import struct
import re import re
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib import retrieve_windows_encoding from openlp.plugins.songs.lib import retrieve_windows_encoding
from songimport import SongImport from songimport import SongImport

View File

@ -26,9 +26,7 @@
############################################################################### ###############################################################################
import logging import logging
import os
import re import re
from zipfile import ZipFile
from lxml import objectify from lxml import objectify
from lxml.etree import Error, LxmlError from lxml.etree import Error, LxmlError
@ -110,48 +108,13 @@ class OpenSongImport(SongImport):
SongImport.__init__(self, manager, **kwargs) SongImport.__init__(self, manager, **kwargs)
def do_import(self): def do_import(self):
""" self.import_wizard.progressBar.setMaximum(len(self.import_source))
Import either each of the files in self.import_source - each element of
which can be either a single opensong file, or a zipfile containing
multiple opensong files.
"""
numfiles = 0
for filename in self.import_source:
ext = os.path.splitext(filename)[1]
if ext.lower() == u'.zip':
z = ZipFile(filename, u'r')
numfiles += len(z.infolist())
z.close()
else:
numfiles += 1
log.debug(u'Total number of files: %d', numfiles)
self.import_wizard.progressBar.setMaximum(numfiles)
for filename in self.import_source: for filename in self.import_source:
if self.stop_import_flag: if self.stop_import_flag:
return return
ext = os.path.splitext(filename)[1] song_file = open(filename)
if ext.lower() == u'.zip': self.do_import_file(song_file)
log.debug(u'Zipfile found %s', filename) song_file.close()
z = ZipFile(filename, u'r')
for song in z.infolist():
if self.stop_import_flag:
z.close()
return
parts = os.path.split(song.filename)
if parts[-1] == u'':
# No final part => directory
continue
log.info(u'Zip importing %s', parts[-1])
song_file = z.open(song)
self.do_import_file(song_file)
song_file.close()
z.close()
else:
# not a zipfile
log.info(u'Direct import %s', filename)
song_file = open(filename)
self.do_import_file(song_file)
song_file.close()
def do_import_file(self, file): def do_import_file(self, file):
""" """

View File

@ -36,7 +36,6 @@ import re
from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport
from openlp.plugins.songs.lib.ui import SongStrings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -29,9 +29,8 @@ import re
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Receiver, translate, check_directory_exists from openlp.core.lib import Receiver, translate
from openlp.core.ui.wizard import WizardStrings from openlp.core.ui.wizard import WizardStrings
from openlp.core.utils import AppLocation
from openlp.plugins.songs.lib import clean_song, VerseType from openlp.plugins.songs.lib import clean_song, VerseType
from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib.ui import SongStrings

View File

@ -31,7 +31,6 @@ Worship songs into the OpenLP database.
import os import os
import logging import logging
from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport
BLOCK_TYPES = (u'V', u'C', u'B') BLOCK_TYPES = (u'V', u'C', u'B')

View File

@ -57,7 +57,7 @@ class SongsPlugin(Plugin):
""" """
Create and set up the Songs plugin. Create and set up the Songs plugin.
""" """
Plugin.__init__(self, u'Songs', plugin_helpers, SongMediaItem, SongsTab) Plugin.__init__(self, u'songs', plugin_helpers, SongMediaItem, SongsTab)
self.weight = -10 self.weight = -10
self.manager = Manager(u'songs', init_schema) self.manager = Manager(u'songs', init_schema)
self.icon_path = u':/plugins/plugin_songs.png' self.icon_path = u':/plugins/plugin_songs.png'

View File

@ -33,7 +33,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, \ from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, \
translate translate
from openlp.core.lib.db import Manager from openlp.core.lib.db import Manager
from openlp.core.lib.ui import base_action, shortcut_action, UiStrings from openlp.core.lib.ui import base_action, shortcut_action
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList
from openlp.plugins.songusage.forms import SongUsageDetailForm, \ from openlp.plugins.songusage.forms import SongUsageDetailForm, \
SongUsageDeleteForm SongUsageDeleteForm
@ -45,7 +45,7 @@ class SongUsagePlugin(Plugin):
log.info(u'SongUsage Plugin loaded') log.info(u'SongUsage Plugin loaded')
def __init__(self, plugin_helpers): def __init__(self, plugin_helpers):
Plugin.__init__(self, u'SongUsage', plugin_helpers) Plugin.__init__(self, u'songusage', plugin_helpers)
self.weight = -4 self.weight = -4
self.icon = build_icon(u':/plugins/plugin_songusage.png') self.icon = build_icon(u':/plugins/plugin_songusage.png')
self.activeIcon = build_icon(u':/songusage/song_usage_active.png') self.activeIcon = build_icon(u':/songusage/song_usage_active.png')

View File

@ -5,7 +5,12 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2011 Raoul Snyman # # Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Millar, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it # # This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free # # under the terms of the GNU General Public License as published by the Free #

View File

@ -46,12 +46,6 @@ PyEnchant
Inno Setup 5 Inno Setup 5
Inno Setup should be installed into "C:\%PROGRAMFILES%\Inno Setup 5" Inno Setup should be installed into "C:\%PROGRAMFILES%\Inno Setup 5"
UPX
This is used to compress DLLs and EXEs so that they take up less space, but
still function exactly the same. To install UPX, download it from
http://upx.sourceforge.net/, extract it into C:\%PROGRAMFILES%\UPX, and then
add that directory to your PATH environment variable.
Sphinx Sphinx
This is used to build the documentation. The documentation trunk must be at This is used to build the documentation. The documentation trunk must be at
the same directory level as Openlp trunk and named "documentation" the same directory level as Openlp trunk and named "documentation"
@ -179,6 +173,7 @@ def run_pyinstaller():
pyinstaller = Popen((python_exe, pyi_build, pyinstaller = Popen((python_exe, pyi_build,
u'--noconfirm', u'--noconfirm',
u'--windowed', u'--windowed',
u'--noupx',
u'-o', branch_path, u'-o', branch_path,
u'-i', win32_icon, u'-i', win32_icon,
u'-p', branch_path, u'-p', branch_path,