merged with lp:~trb143/openlp/beta1
@ -1,3 +1,5 @@
|
|||||||
|
.. _dualmonitors:
|
||||||
|
|
||||||
==================
|
==================
|
||||||
Dual Monitor Setup
|
Dual Monitor Setup
|
||||||
==================
|
==================
|
||||||
@ -32,6 +34,14 @@ projector hooked up to your computer as the second monitor. With the option of
|
|||||||
extending your desktop across the second monitor, or your operating system's
|
extending your desktop across the second monitor, or your operating system's
|
||||||
equivalent.
|
equivalent.
|
||||||
|
|
||||||
|
**Special Note For Projectors Using USB Connections**
|
||||||
|
|
||||||
|
Users have reported experiencing difficulties when using a projector with a USB
|
||||||
|
connection, as third party software is often required to properly configure
|
||||||
|
dual monitors. If possible, it is best to use a direct output (VGA, DVI, HDMI,
|
||||||
|
S-Video) from your machine's video card. If a USB connection is your only option
|
||||||
|
please consult the manufacturer's manual for instructions on a proper setup.
|
||||||
|
|
||||||
Microsoft Windows
|
Microsoft Windows
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 195 KiB |
@ -175,3 +175,23 @@ only download the section you search for. If you do not have an internet
|
|||||||
connection where you intend to use OpenLP you will need another scripture
|
connection where you intend to use OpenLP you will need another scripture
|
||||||
source. For more information about acquiring Bibles please see :ref:`bibleimporter`.
|
source. For more information about acquiring Bibles please see :ref:`bibleimporter`.
|
||||||
|
|
||||||
|
OpenLP is using a large amount of RAM when showing a presentation
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
|
OpenLP uses a large amount of RAM when showing a presentation due to the way it
|
||||||
|
handles presentations. OpenLP itself is unable to show those presentations or
|
||||||
|
load the presentation files, so it interacts with the presentation through
|
||||||
|
either Microsoft PowerPoint or LibreOffice Impress. In order to show the slides
|
||||||
|
in the slide controller, OpenLP requests that the presentation application
|
||||||
|
export the slides to images, and then uses those images as slides. This results
|
||||||
|
in a large amount of RAM being used, especially in presentations with more than
|
||||||
|
about 20 slides.
|
||||||
|
|
||||||
|
OpenLP is not displaying correctly, or is not on the correct screen
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
Please read the documentation on :ref:`dualmonitors`. It is very important to
|
||||||
|
have dual monitors setup properly for OpenLP to function as expected.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -214,26 +214,24 @@ class Renderer(object):
|
|||||||
``line_break``
|
``line_break``
|
||||||
Add line endings after each line of text used for bibles.
|
Add line endings after each line of text used for bibles.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
log.debug(u'format slide')
|
log.debug(u'format slide')
|
||||||
# clean up line endings
|
# clean up line endings
|
||||||
lines = self._lines_split(text)
|
lines = self._lines_split(text)
|
||||||
# Songs and Custom
|
pages = self._paginate_slide(lines, line_break, self.force_page)
|
||||||
if item.is_capable(ItemCapabilities.AllowsVirtualSplit):
|
if len(pages) > 1:
|
||||||
# Do not forget the line breaks !
|
# Songs and Custom
|
||||||
slides = text.split(u'\n[---]\n')
|
if item.is_capable(ItemCapabilities.AllowsVirtualSplit):
|
||||||
pages = []
|
# Do not forget the line breaks !
|
||||||
for slide in slides:
|
slides = text.split(u'\n[---]\n')
|
||||||
lines = self._lines(slide)
|
pages = []
|
||||||
new_pages = self._paginate_slide(lines, line_break,
|
for slide in slides:
|
||||||
self.force_page)
|
lines = self._lines(slide)
|
||||||
pages.extend([page for page in new_pages])
|
new_pages = self._paginate_slide(lines, line_break,
|
||||||
# Bibles
|
self.force_page)
|
||||||
elif item.is_capable(ItemCapabilities.AllowsWordSplit):
|
pages.extend([page for page in new_pages])
|
||||||
pages = self._paginate_slide_words(text, line_break)
|
# Bibles
|
||||||
# Theme preview "service items".
|
elif item.is_capable(ItemCapabilities.AllowsWordSplit):
|
||||||
else:
|
pages = self._paginate_slide_words(text, line_break)
|
||||||
pages = self._paginate_slide(lines, line_break, self.force_page)
|
|
||||||
return pages
|
return pages
|
||||||
|
|
||||||
def _calculate_default(self, screen):
|
def _calculate_default(self, screen):
|
||||||
@ -256,6 +254,7 @@ class Renderer(object):
|
|||||||
"""
|
"""
|
||||||
Builds a text block using the settings in ``theme``
|
Builds a text block using the settings in ``theme``
|
||||||
and the size of the display screen.height.
|
and the size of the display screen.height.
|
||||||
|
Note the system has a 10 pixel border round the screen
|
||||||
|
|
||||||
``theme``
|
``theme``
|
||||||
The theme to build a text block for.
|
The theme to build a text block for.
|
||||||
@ -365,8 +364,6 @@ class Renderer(object):
|
|||||||
Add line endings after each line of text used for bibles.
|
Add line endings after each line of text used for bibles.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# TODO: Make sure spaces are striped so that they will not confuse
|
|
||||||
# rendering. for instance when the style is set to Verse per Line:
|
|
||||||
# In the beginning ...
|
# In the beginning ...
|
||||||
# <space> <!-- here we could have added the second verse -->
|
# <space> <!-- here we could have added the second verse -->
|
||||||
# <new slide>
|
# <new slide>
|
||||||
@ -378,7 +375,7 @@ class Renderer(object):
|
|||||||
formatted = []
|
formatted = []
|
||||||
previous_html = u''
|
previous_html = u''
|
||||||
previous_raw = u''
|
previous_raw = u''
|
||||||
lines = self._lines(text, u'[---]')
|
lines = self._lines(text)
|
||||||
for line in lines:
|
for line in lines:
|
||||||
styled_line = expand_tags(line)
|
styled_line = expand_tags(line)
|
||||||
html = self.page_shell + previous_html + styled_line + HTML_END
|
html = self.page_shell + previous_html + styled_line + HTML_END
|
||||||
@ -392,7 +389,8 @@ class Renderer(object):
|
|||||||
HTML_END
|
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:
|
||||||
previous_raw = previous_raw.rstrip(u'<br>')
|
previous_raw = previous_raw.rstrip(u'<br>')
|
||||||
formatted.append(previous_raw)
|
formatted.append(previous_raw)
|
||||||
previous_html = u''
|
previous_html = u''
|
||||||
@ -409,26 +407,26 @@ class Renderer(object):
|
|||||||
log.debug(u'_paginate_slide_words - End')
|
log.debug(u'_paginate_slide_words - End')
|
||||||
return formatted
|
return formatted
|
||||||
|
|
||||||
def _lines(self, words, split=u'n[---]n'):
|
def _lines(self, text):
|
||||||
"""
|
"""
|
||||||
Split the slide up by physical line
|
Split the slide up by physical line
|
||||||
"""
|
"""
|
||||||
# this parse we do not want to use this so remove it
|
# this parse we do not want to use this so remove it
|
||||||
#words = words.replace(split, u'')
|
verses_text = text.split(u'\n')
|
||||||
verses_text = words.split(u'\n')
|
|
||||||
text = []
|
text = []
|
||||||
for verse in verses_text:
|
for verse in verses_text:
|
||||||
lines = verse.split(u'\n')
|
lines = verse.split(u'\n')
|
||||||
text.extend([line for line in lines])
|
text.extend([line for line in lines])
|
||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def _words_split(self, words):
|
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
|
||||||
words = words.replace(u'\n', u' ')
|
line = line.replace(u'\n', u' ')
|
||||||
verses_text = words.split(u' ')
|
verses_text = line.split(u' ')
|
||||||
text = []
|
text = []
|
||||||
for verse in verses_text:
|
for verse in verses_text:
|
||||||
lines = verse.split(u' ')
|
lines = verse.split(u' ')
|
||||||
@ -440,10 +438,11 @@ class Renderer(object):
|
|||||||
Split the slide up by physical line
|
Split the slide up by physical line
|
||||||
"""
|
"""
|
||||||
# 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'')
|
||||||
lines = text.split(u'\n')
|
lines = text.split(u'\n')
|
||||||
real_lines = []
|
real_lines = []
|
||||||
for line in lines:
|
for line in lines:
|
||||||
line = line.replace(u' [---]', u'[---]')
|
line = line.replace(u'[---]', u'')
|
||||||
sub_lines = line.split(u'\n')
|
sub_lines = line.split(u'\n')
|
||||||
real_lines.extend([sub_line for sub_line in sub_lines])
|
real_lines.extend([sub_line for sub_line in sub_lines])
|
||||||
return real_lines
|
return real_lines
|
||||||
|
@ -191,7 +191,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
|||||||
div = self._addElement(u'div', parent=html_data.body,
|
div = self._addElement(u'div', parent=html_data.body,
|
||||||
classId=u'customNotes')
|
classId=u'customNotes')
|
||||||
self._addElement(u'span', translate('OpenLP.ServiceManager',
|
self._addElement(u'span', translate('OpenLP.ServiceManager',
|
||||||
u'Custom Service Notes: '), div, classId=u'customNotesTitle')
|
'Custom Service Notes: '), div, classId=u'customNotesTitle')
|
||||||
self._addElement(u'span', self.footerTextEdit.toPlainText(), div,
|
self._addElement(u'span', self.footerTextEdit.toPlainText(), div,
|
||||||
classId=u'customNotesText')
|
classId=u'customNotesText')
|
||||||
self.document.setHtml(html.tostring(html_data))
|
self.document.setHtml(html.tostring(html_data))
|
||||||
|
@ -56,6 +56,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.registerFields()
|
self.registerFields()
|
||||||
self.updateThemeAllowed = True
|
self.updateThemeAllowed = True
|
||||||
|
self.temp_background_filename = u''
|
||||||
QtCore.QObject.connect(self.backgroundComboBox,
|
QtCore.QObject.connect(self.backgroundComboBox,
|
||||||
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
||||||
self.onBackgroundComboBoxCurrentIndexChanged)
|
self.onBackgroundComboBoxCurrentIndexChanged)
|
||||||
@ -279,6 +280,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
Run the wizard.
|
Run the wizard.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Editing theme %s' % self.theme.theme_name)
|
log.debug(u'Editing theme %s' % self.theme.theme_name)
|
||||||
|
self.temp_background_filename = u''
|
||||||
self.updateThemeAllowed = False
|
self.updateThemeAllowed = False
|
||||||
self.setDefaults()
|
self.setDefaults()
|
||||||
self.updateThemeAllowed = True
|
self.updateThemeAllowed = True
|
||||||
@ -432,6 +434,16 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
# do not allow updates when screen is building for the first time.
|
# do not allow updates when screen is building for the first time.
|
||||||
if self.updateThemeAllowed:
|
if self.updateThemeAllowed:
|
||||||
self.theme.background_type = BackgroundType.to_string(index)
|
self.theme.background_type = BackgroundType.to_string(index)
|
||||||
|
if self.theme.background_type != \
|
||||||
|
BackgroundType.to_string(BackgroundType.Image) and \
|
||||||
|
self.temp_background_filename == u'':
|
||||||
|
self.temp_background_filename = self.theme.background_filename
|
||||||
|
self.theme.background_filename = u''
|
||||||
|
if self.theme.background_type == \
|
||||||
|
BackgroundType.to_string(BackgroundType.Image) and \
|
||||||
|
self.temp_background_filename != u'':
|
||||||
|
self.theme.background_filename = self.temp_background_filename
|
||||||
|
self.temp_background_filename = u''
|
||||||
self.setBackgroundPageValues()
|
self.setBackgroundPageValues()
|
||||||
|
|
||||||
def onGradientComboBoxCurrentIndexChanged(self, index):
|
def onGradientComboBoxCurrentIndexChanged(self, index):
|
||||||
|
@ -278,24 +278,29 @@ def clean_song(manager, song):
|
|||||||
# List for later comparison.
|
# List for later comparison.
|
||||||
compare_order = []
|
compare_order = []
|
||||||
for verse in verses:
|
for verse in verses:
|
||||||
type = VerseType.Tags[VerseType.from_loose_input(verse[0][u'type'])]
|
verse_type = VerseType.Tags[VerseType.from_loose_input(
|
||||||
|
verse[0][u'type'])]
|
||||||
sxml.add_verse_to_lyrics(
|
sxml.add_verse_to_lyrics(
|
||||||
type,
|
verse_type,
|
||||||
verse[0][u'label'],
|
verse[0][u'label'],
|
||||||
verse[1],
|
verse[1],
|
||||||
verse[0][u'lang'] if verse[0].has_key(u'lang') else None
|
verse[0][u'lang'] if verse[0].has_key(u'lang') else None
|
||||||
)
|
)
|
||||||
compare_order.append((u'%s%s' % (type, verse[0][u'label'])).upper())
|
compare_order.append((u'%s%s' % (verse_type, verse[0][u'label'])
|
||||||
|
).upper())
|
||||||
|
if verse[0][u'label'] == u'1':
|
||||||
|
compare_order.append(verse_type.upper())
|
||||||
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
||||||
# Rebuild the verse order, to convert translated verse tags, which might
|
# Rebuild the verse order, to convert translated verse tags, which might
|
||||||
# have been added prior to 1.9.5.
|
# have been added prior to 1.9.5.
|
||||||
order = song.verse_order.strip().split()
|
order = song.verse_order.strip().split()
|
||||||
new_order = []
|
new_order = []
|
||||||
for verse_def in order:
|
for verse_def in order:
|
||||||
new_order.append((u'%s%s' % (
|
verse_type = VerseType.Tags[VerseType.from_loose_input(verse_def[0])]
|
||||||
VerseType.Tags[VerseType.from_loose_input(verse_def[0])],
|
if len(verse_def) > 1:
|
||||||
verse_def[1:])).upper()
|
new_order.append((u'%s%s' % (verse_type, verse_def[1:])).upper())
|
||||||
)
|
else:
|
||||||
|
new_order.append(verse_type.upper())
|
||||||
song.verse_order = u' '.join(new_order)
|
song.verse_order = u' '.join(new_order)
|
||||||
# Check if the verse order contains tags for verses which do not exist.
|
# Check if the verse order contains tags for verses which do not exist.
|
||||||
for order in new_order:
|
for order in new_order:
|
||||||
|
@ -193,7 +193,10 @@ class OpenSongImport(SongImport):
|
|||||||
verse_num = u'1'
|
verse_num = u'1'
|
||||||
# for the case where song has several sections with same marker
|
# for the case where song has several sections with same marker
|
||||||
inst = 1
|
inst = 1
|
||||||
lyrics = unicode(root.lyrics)
|
if u'lyrics' in fields:
|
||||||
|
lyrics = unicode(root.lyrics)
|
||||||
|
else:
|
||||||
|
lyrics = u''
|
||||||
for this_line in lyrics.split(u'\n'):
|
for this_line in lyrics.split(u'\n'):
|
||||||
# remove comments
|
# remove comments
|
||||||
semicolon = this_line.find(u';')
|
semicolon = this_line.find(u';')
|
||||||
@ -214,7 +217,7 @@ class OpenSongImport(SongImport):
|
|||||||
# have we got any digits?
|
# have we got any digits?
|
||||||
# If so, verse number is everything from the digits
|
# If so, verse number is everything from the digits
|
||||||
# to the end (even if there are some alpha chars on the end)
|
# to the end (even if there are some alpha chars on the end)
|
||||||
match = re.match(u'(.*)(\d+.*)', content)
|
match = re.match(u'(\D*)(\d+.*)', content)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
verse_tag = match.group(1)
|
verse_tag = match.group(1)
|
||||||
verse_num = match.group(2)
|
verse_num = match.group(2)
|
||||||
@ -223,12 +226,13 @@ class OpenSongImport(SongImport):
|
|||||||
# the verse tag
|
# the verse tag
|
||||||
verse_tag = content
|
verse_tag = content
|
||||||
verse_num = u'1'
|
verse_num = u'1'
|
||||||
|
verse_index = VerseType.from_loose_input(verse_tag)
|
||||||
|
verse_tag = VerseType.Tags[verse_index]
|
||||||
inst = 1
|
inst = 1
|
||||||
if [verse_tag, verse_num, inst] in our_verse_order \
|
if [verse_tag, verse_num, inst] in our_verse_order \
|
||||||
and verses.has_key(verse_tag) \
|
and verses.has_key(verse_tag) \
|
||||||
and verses[verse_tag].has_key(verse_num):
|
and verses[verse_tag].has_key(verse_num):
|
||||||
inst = len(verses[verse_tag][verse_num]) + 1
|
inst = len(verses[verse_tag][verse_num]) + 1
|
||||||
our_verse_order.append([verse_tag, verse_num, inst])
|
|
||||||
continue
|
continue
|
||||||
# number at start of line.. it's verse number
|
# number at start of line.. it's verse number
|
||||||
if this_line[0].isdigit():
|
if this_line[0].isdigit():
|
||||||
@ -241,6 +245,7 @@ class OpenSongImport(SongImport):
|
|||||||
verses[verse_tag][verse_num] = {}
|
verses[verse_tag][verse_num] = {}
|
||||||
if not verses[verse_tag][verse_num].has_key(inst):
|
if not verses[verse_tag][verse_num].has_key(inst):
|
||||||
verses[verse_tag][verse_num][inst] = []
|
verses[verse_tag][verse_num][inst] = []
|
||||||
|
our_verse_order.append([verse_tag, verse_num, inst])
|
||||||
# Tidy text and remove the ____s from extended words
|
# Tidy text and remove the ____s from extended words
|
||||||
this_line = self.tidy_text(this_line)
|
this_line = self.tidy_text(this_line)
|
||||||
this_line = this_line.replace(u'_', u'')
|
this_line = this_line.replace(u'_', u'')
|
||||||
@ -252,6 +257,8 @@ class OpenSongImport(SongImport):
|
|||||||
verse_def = u'%s%s' % (verse_tag, verse_num)
|
verse_def = u'%s%s' % (verse_tag, verse_num)
|
||||||
lines = u'\n'.join(verses[verse_tag][verse_num][inst])
|
lines = u'\n'.join(verses[verse_tag][verse_num][inst])
|
||||||
self.add_verse(lines, verse_def)
|
self.add_verse(lines, verse_def)
|
||||||
|
if not self.verses:
|
||||||
|
self.add_verse('')
|
||||||
# figure out the presentation order, if present
|
# figure out the presentation order, if present
|
||||||
if u'presentation' in fields and root.presentation:
|
if u'presentation' in fields and root.presentation:
|
||||||
order = unicode(root.presentation)
|
order = unicode(root.presentation)
|
||||||
@ -259,7 +266,7 @@ class OpenSongImport(SongImport):
|
|||||||
# and then split into a list on the whitespace
|
# and then split into a list on the whitespace
|
||||||
order = order.lower().split()
|
order = order.lower().split()
|
||||||
for verse_def in order:
|
for verse_def in order:
|
||||||
match = re.match(u'(.*)(\d+.*)', verse_def)
|
match = re.match(u'(\D*)(\d+.*)', verse_def)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
verse_tag = match.group(1)
|
verse_tag = match.group(1)
|
||||||
verse_num = match.group(2)
|
verse_num = match.group(2)
|
||||||
|