forked from openlp/openlp
Added an option to wrap footer text
bzr-revno: 2409
This commit is contained in:
commit
04bafa62fa
@ -286,6 +286,7 @@ class Settings(QtCore.QSettings):
|
|||||||
'themes/last directory export': '',
|
'themes/last directory export': '',
|
||||||
'themes/last directory import': '',
|
'themes/last directory import': '',
|
||||||
'themes/theme level': ThemeLevel.Song,
|
'themes/theme level': ThemeLevel.Song,
|
||||||
|
'themes/wrap footer': False,
|
||||||
'user interface/live panel': True,
|
'user interface/live panel': True,
|
||||||
'user interface/live splitter geometry': QtCore.QByteArray(),
|
'user interface/live splitter geometry': QtCore.QByteArray(),
|
||||||
'user interface/lock panel': False,
|
'user interface/lock panel': False,
|
||||||
|
@ -398,6 +398,7 @@ import logging
|
|||||||
|
|
||||||
from PyQt4 import QtWebKit
|
from PyQt4 import QtWebKit
|
||||||
|
|
||||||
|
from openlp.core.common import Settings
|
||||||
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, VerticalType, HorizontalType
|
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, VerticalType, HorizontalType
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -750,12 +751,13 @@ 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: %s;
|
||||||
"""
|
"""
|
||||||
theme = item.theme_data
|
theme = item.theme_data
|
||||||
if not theme or not item.footer:
|
if not theme or not item.footer:
|
||||||
return ''
|
return ''
|
||||||
bottom = height - int(item.footer.y()) - int(item.footer.height())
|
bottom = height - int(item.footer.y()) - int(item.footer.height())
|
||||||
|
whitespace = 'normal' if Settings().value('themes/wrap footer') else 'nowrap'
|
||||||
lyrics_html = style % (item.footer.x(), bottom, item.footer.width(),
|
lyrics_html = style % (item.footer.x(), bottom, item.footer.width(),
|
||||||
theme.font_footer_name, theme.font_footer_size, theme.font_footer_color)
|
theme.font_footer_name, theme.font_footer_size, theme.font_footer_color, whitespace)
|
||||||
return lyrics_html
|
return lyrics_html
|
||||||
|
@ -69,6 +69,14 @@ class ThemesTab(SettingsTab):
|
|||||||
self.default_list_view.setObjectName('default_list_view')
|
self.default_list_view.setObjectName('default_list_view')
|
||||||
self.global_group_box_layout.addWidget(self.default_list_view)
|
self.global_group_box_layout.addWidget(self.default_list_view)
|
||||||
self.left_layout.addWidget(self.global_group_box)
|
self.left_layout.addWidget(self.global_group_box)
|
||||||
|
self.universal_group_box = QtGui.QGroupBox(self.left_column)
|
||||||
|
self.universal_group_box.setObjectName('universal_group_box')
|
||||||
|
self.universal_group_box_layout = QtGui.QVBoxLayout(self.universal_group_box)
|
||||||
|
self.universal_group_box_layout.setObjectName('universal_group_box_layout')
|
||||||
|
self.wrap_footer_check_box = QtGui.QCheckBox(self.universal_group_box)
|
||||||
|
self.wrap_footer_check_box.setObjectName('wrap_footer_check_box')
|
||||||
|
self.universal_group_box_layout.addWidget(self.wrap_footer_check_box)
|
||||||
|
self.left_layout.addWidget(self.universal_group_box)
|
||||||
self.left_layout.addStretch()
|
self.left_layout.addStretch()
|
||||||
self.level_group_box = QtGui.QGroupBox(self.right_column)
|
self.level_group_box = QtGui.QGroupBox(self.right_column)
|
||||||
self.level_group_box.setObjectName('level_group_box')
|
self.level_group_box.setObjectName('level_group_box')
|
||||||
@ -112,6 +120,8 @@ class ThemesTab(SettingsTab):
|
|||||||
"""
|
"""
|
||||||
self.tab_title_visible = UiStrings().Themes
|
self.tab_title_visible = UiStrings().Themes
|
||||||
self.global_group_box.setTitle(translate('OpenLP.ThemesTab', 'Global Theme'))
|
self.global_group_box.setTitle(translate('OpenLP.ThemesTab', 'Global Theme'))
|
||||||
|
self.universal_group_box.setTitle(translate('OpenLP.ThemesTab', 'Universal Settings'))
|
||||||
|
self.wrap_footer_check_box.setText(translate('OpenLP.ThemesTab', '&Wrap footer text'))
|
||||||
self.level_group_box.setTitle(translate('OpenLP.ThemesTab', 'Theme Level'))
|
self.level_group_box.setTitle(translate('OpenLP.ThemesTab', 'Theme Level'))
|
||||||
self.song_level_radio_button.setText(translate('OpenLP.ThemesTab', 'S&ong Level'))
|
self.song_level_radio_button.setText(translate('OpenLP.ThemesTab', 'S&ong Level'))
|
||||||
self.song_level_label.setText(
|
self.song_level_label.setText(
|
||||||
@ -136,6 +146,7 @@ class ThemesTab(SettingsTab):
|
|||||||
settings.beginGroup(self.settings_section)
|
settings.beginGroup(self.settings_section)
|
||||||
self.theme_level = settings.value('theme level')
|
self.theme_level = settings.value('theme level')
|
||||||
self.global_theme = settings.value('global theme')
|
self.global_theme = settings.value('global theme')
|
||||||
|
self.wrap_footer_check_box.setChecked(settings.value('wrap footer'))
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
if self.theme_level == ThemeLevel.Global:
|
if self.theme_level == ThemeLevel.Global:
|
||||||
self.global_level_radio_button.setChecked(True)
|
self.global_level_radio_button.setChecked(True)
|
||||||
@ -152,6 +163,7 @@ class ThemesTab(SettingsTab):
|
|||||||
settings.beginGroup(self.settings_section)
|
settings.beginGroup(self.settings_section)
|
||||||
settings.setValue('theme level', self.theme_level)
|
settings.setValue('theme level', self.theme_level)
|
||||||
settings.setValue('global theme', self.global_theme)
|
settings.setValue('global theme', self.global_theme)
|
||||||
|
settings.setValue('wrap footer', self.wrap_footer_check_box.isChecked())
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
self.renderer.set_theme_level(self.theme_level)
|
self.renderer.set_theme_level(self.theme_level)
|
||||||
if self.tab_visited:
|
if self.tab_visited:
|
||||||
|
@ -6,11 +6,12 @@ from unittest import TestCase
|
|||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
|
from openlp.core.common import Settings
|
||||||
from openlp.core.lib.htmlbuilder import build_html, build_background_css, build_lyrics_css, build_lyrics_outline_css, \
|
from openlp.core.lib.htmlbuilder import build_html, build_background_css, build_lyrics_css, build_lyrics_outline_css, \
|
||||||
build_lyrics_format_css, build_footer_css
|
build_lyrics_format_css, build_footer_css
|
||||||
from openlp.core.lib.theme import HorizontalType, VerticalType
|
from openlp.core.lib.theme import HorizontalType, VerticalType
|
||||||
from tests.functional import MagicMock, patch
|
from tests.functional import MagicMock, patch
|
||||||
|
from tests.helpers.testmixin import TestMixin
|
||||||
|
|
||||||
HTML = """
|
HTML = """
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@ -184,7 +185,7 @@ LYRICS_OUTLINE_CSS = ' -webkit-text-stroke: 0.125em #000000; -webkit-text-fill-c
|
|||||||
LYRICS_FORMAT_CSS = ' word-wrap: break-word; text-align: justify; vertical-align: bottom; ' + \
|
LYRICS_FORMAT_CSS = ' word-wrap: break-word; text-align: justify; vertical-align: bottom; ' + \
|
||||||
'font-family: Arial; font-size: 40pt; color: #FFFFFF; line-height: 108%; margin: 0;padding: 0; ' + \
|
'font-family: Arial; font-size: 40pt; color: #FFFFFF; line-height: 108%; margin: 0;padding: 0; ' + \
|
||||||
'padding-bottom: 0.5em; padding-left: 2px; width: 1580px; height: 810px; font-style:italic; font-weight:bold; '
|
'padding-bottom: 0.5em; padding-left: 2px; width: 1580px; height: 810px; font-style:italic; font-weight:bold; '
|
||||||
FOOTER_CSS = """
|
FOOTER_CSS_BASE = """
|
||||||
left: 10px;
|
left: 10px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
width: 1260px;
|
width: 1260px;
|
||||||
@ -192,11 +193,28 @@ FOOTER_CSS = """
|
|||||||
font-size: 12pt;
|
font-size: 12pt;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
white-space: nowrap;
|
white-space: %s;
|
||||||
"""
|
"""
|
||||||
|
FOOTER_CSS = FOOTER_CSS_BASE % ('nowrap')
|
||||||
|
FOOTER_CSS_WRAP = FOOTER_CSS_BASE % ('normal')
|
||||||
|
|
||||||
|
|
||||||
class Htmbuilder(TestCase):
|
class Htmbuilder(TestCase, TestMixin):
|
||||||
|
"""
|
||||||
|
Test the functions in the Htmlbuilder module
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create the UI
|
||||||
|
"""
|
||||||
|
self.build_settings()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""
|
||||||
|
Delete all the C++ objects at the end so that we don't have a segfault
|
||||||
|
"""
|
||||||
|
self.destroy_settings()
|
||||||
|
|
||||||
def build_html_test(self):
|
def build_html_test(self):
|
||||||
"""
|
"""
|
||||||
Test the build_html() function
|
Test the build_html() function
|
||||||
@ -225,7 +243,7 @@ class Htmbuilder(TestCase):
|
|||||||
html = build_html(item, screen, is_live, background, plugins=plugins)
|
html = build_html(item, screen, is_live, background, plugins=plugins)
|
||||||
|
|
||||||
# THEN: The returned html should match.
|
# THEN: The returned html should match.
|
||||||
assert html == HTML
|
self.assertEqual(html, HTML, 'The returned html should match')
|
||||||
|
|
||||||
def build_background_css_radial_test(self):
|
def build_background_css_radial_test(self):
|
||||||
"""
|
"""
|
||||||
@ -241,7 +259,7 @@ class Htmbuilder(TestCase):
|
|||||||
css = build_background_css(item, width)
|
css = build_background_css(item, width)
|
||||||
|
|
||||||
# THEN: The returned css should match.
|
# THEN: The returned css should match.
|
||||||
assert BACKGROUND_CSS_RADIAL == css, 'The background css should be equal.'
|
self.assertEqual(BACKGROUND_CSS_RADIAL, css, 'The background css should be equal.')
|
||||||
|
|
||||||
def build_lyrics_css_test(self):
|
def build_lyrics_css_test(self):
|
||||||
"""
|
"""
|
||||||
@ -262,7 +280,7 @@ class Htmbuilder(TestCase):
|
|||||||
css = build_lyrics_css(item)
|
css = build_lyrics_css(item)
|
||||||
|
|
||||||
# THEN: The css should be equal.
|
# THEN: The css should be equal.
|
||||||
assert LYRICS_CSS == css, 'The lyrics css should be equal.'
|
self.assertEqual(LYRICS_CSS, css, 'The lyrics css should be equal.')
|
||||||
|
|
||||||
def build_lyrics_outline_css_test(self):
|
def build_lyrics_outline_css_test(self):
|
||||||
"""
|
"""
|
||||||
@ -279,7 +297,7 @@ class Htmbuilder(TestCase):
|
|||||||
css = build_lyrics_outline_css(theme_data)
|
css = build_lyrics_outline_css(theme_data)
|
||||||
|
|
||||||
# THEN: The css should be equal.
|
# THEN: The css should be equal.
|
||||||
assert LYRICS_OUTLINE_CSS == css, 'The outline css should be equal.'
|
self.assertEqual(LYRICS_OUTLINE_CSS, css, 'The outline css should be equal.')
|
||||||
|
|
||||||
def build_lyrics_format_css_test(self):
|
def build_lyrics_format_css_test(self):
|
||||||
"""
|
"""
|
||||||
@ -302,7 +320,7 @@ class Htmbuilder(TestCase):
|
|||||||
css = build_lyrics_format_css(theme_data, width, height)
|
css = build_lyrics_format_css(theme_data, width, height)
|
||||||
|
|
||||||
# THEN: They should be equal.
|
# THEN: They should be equal.
|
||||||
assert LYRICS_FORMAT_CSS == css, 'The lyrics format css should be equal.'
|
self.assertEqual(LYRICS_FORMAT_CSS, css, 'The lyrics format css should be equal.')
|
||||||
|
|
||||||
def build_footer_css_test(self):
|
def build_footer_css_test(self):
|
||||||
"""
|
"""
|
||||||
@ -316,8 +334,27 @@ class Htmbuilder(TestCase):
|
|||||||
item.theme_data.font_footer_color = '#FFFFFF'
|
item.theme_data.font_footer_color = '#FFFFFF'
|
||||||
height = 1024
|
height = 1024
|
||||||
|
|
||||||
# WHEN: create the css.
|
# WHEN: create the css with default settings.
|
||||||
css = build_footer_css(item, height)
|
css = build_footer_css(item, height)
|
||||||
|
|
||||||
# THEN: THE css should be the same.
|
# THEN: THE css should be the same.
|
||||||
assert FOOTER_CSS == css, 'The footer strings should be equal.'
|
self.assertEqual(FOOTER_CSS, css, 'The footer strings should be equal.')
|
||||||
|
|
||||||
|
def build_footer_css_wrap_test(self):
|
||||||
|
"""
|
||||||
|
Test the build_footer_css() function
|
||||||
|
"""
|
||||||
|
# GIVEN: Create a theme.
|
||||||
|
item = MagicMock()
|
||||||
|
item.footer = QtCore.QRect(10, 921, 1260, 103)
|
||||||
|
item.theme_data.font_footer_name = 'Arial'
|
||||||
|
item.theme_data.font_footer_size = 12
|
||||||
|
item.theme_data.font_footer_color = '#FFFFFF'
|
||||||
|
height = 1024
|
||||||
|
|
||||||
|
# WHEN: Settings say that footer should wrap
|
||||||
|
Settings().setValue('themes/wrap footer', True)
|
||||||
|
css = build_footer_css(item, height)
|
||||||
|
|
||||||
|
# THEN: Footer should wrap
|
||||||
|
self.assertEqual(FOOTER_CSS_WRAP, css, 'The footer strings should be equal.')
|
||||||
|
@ -504,11 +504,10 @@ class TestSlideController(TestCase):
|
|||||||
mocked_item = MagicMock()
|
mocked_item = MagicMock()
|
||||||
mocked_item.is_command.return_value = True
|
mocked_item.is_command.return_value = True
|
||||||
mocked_item.name = 'Mocked Item'
|
mocked_item.name = 'Mocked Item'
|
||||||
mocked_execute = MagicMock()
|
|
||||||
mocked_update_preview = MagicMock()
|
mocked_update_preview = MagicMock()
|
||||||
mocked_preview_widget = MagicMock()
|
mocked_preview_widget = MagicMock()
|
||||||
mocked_slide_selected = MagicMock()
|
mocked_slide_selected = MagicMock()
|
||||||
Registry.execute = mocked_execute
|
with patch.object(Registry, 'execute') as mocked_execute:
|
||||||
Registry.create()
|
Registry.create()
|
||||||
slide_controller = SlideController(None)
|
slide_controller = SlideController(None)
|
||||||
slide_controller.service_item = mocked_item
|
slide_controller.service_item = mocked_item
|
||||||
@ -535,11 +534,10 @@ class TestSlideController(TestCase):
|
|||||||
mocked_item = MagicMock()
|
mocked_item = MagicMock()
|
||||||
mocked_item.is_command.return_value = False
|
mocked_item.is_command.return_value = False
|
||||||
mocked_item.name = 'Mocked Item'
|
mocked_item.name = 'Mocked Item'
|
||||||
mocked_execute = MagicMock()
|
|
||||||
mocked_update_preview = MagicMock()
|
mocked_update_preview = MagicMock()
|
||||||
mocked_preview_widget = MagicMock()
|
mocked_preview_widget = MagicMock()
|
||||||
mocked_slide_selected = MagicMock()
|
mocked_slide_selected = MagicMock()
|
||||||
Registry.execute = mocked_execute
|
with patch.object(Registry, 'execute') as mocked_execute:
|
||||||
Registry.create()
|
Registry.create()
|
||||||
slide_controller = SlideController(None)
|
slide_controller = SlideController(None)
|
||||||
slide_controller.service_item = mocked_item
|
slide_controller.service_item = mocked_item
|
||||||
|
Loading…
Reference in New Issue
Block a user