Initial string conversions for variable templates

This commit is contained in:
Ken Roberts 2016-06-03 17:15:19 -07:00
parent 0355b6f221
commit 598d715de6
13 changed files with 142 additions and 129 deletions

View File

@ -80,8 +80,9 @@ class UiStrings(object):
self.Export = translate('OpenLP.Ui', 'Export')
self.File = translate('OpenLP.Ui', 'File')
self.FileNotFound = translate('OpenLP.Ui', 'File Not Found')
# TODO: Check before converting to python3 string
self.FileNotFoundMessage = translate('OpenLP.Ui', 'File %s not found.\nPlease try selecting it individually.')
# TODO: Passed nose - verify in real life example
self.FileNotFoundMessage = translate('OpenLP.Ui',
'File {name} not found.\nPlease try selecting it individually.')
self.FontSizePtUnit = translate('OpenLP.Ui', 'pt', 'Abbreviated font pointsize unit')
self.Help = translate('OpenLP.Ui', 'Help')
self.Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours')
@ -140,8 +141,8 @@ class UiStrings(object):
self.Split = translate('OpenLP.Ui', 'Optional &Split')
self.SplitToolTip = translate('OpenLP.Ui',
'Split a slide into two only if it does not fit on the screen as one slide.')
# TODO: Check before converting to python3 string
self.StartTimeCode = translate('OpenLP.Ui', 'Start %s')
# TODO: WHERE is this used at? cannot find where it's used at in code.
self.StartTimeCode = translate('OpenLP.Ui', 'Start {code}')
self.StopPlaySlidesInLoop = translate('OpenLP.Ui', 'Stop Play Slides in Loop')
self.StopPlaySlidesToEnd = translate('OpenLP.Ui', 'Stop Play Slides to End')
self.Theme = translate('OpenLP.Ui', 'Theme', 'Singular')

View File

@ -323,8 +323,7 @@ def create_separated_list(string_list):
return ''
elif len(string_list) == 1:
return string_list[0]
# TODO:
# Cannot convert these strings to python3 yet until I can figure out how to mock translate() with the new format
# TODO: Verify mocking of translate() test before conversion
elif len(string_list) == 2:
return translate('OpenLP.core.lib', '%s and %s',
'Locale list separator: 2 items') % (string_list[0], string_list[1])

View File

@ -51,9 +51,9 @@ class FileDialog(QtWidgets.QFileDialog):
file = parse.unquote(file)
if not os.path.exists(file):
log.error('File {text} not found.'.format(text=file))
# TODO: Test with UiStrings() before converting to python3 strings
# TODO: Should work - need to verify
QtWidgets.QMessageBox.information(parent, UiStrings().FileNotFound,
UiStrings().FileNotFoundMessage % file)
UiStrings().FileNotFoundMessage.format(name=file))
continue
file_list.append(file)
return file_list

View File

@ -396,74 +396,74 @@ from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, Vertic
log = logging.getLogger(__name__)
# TODO: Verify where this is used before converting to python3
# TODO: Tested at home
HTMLSRC = """
<!DOCTYPE html>
<html>
<head>
<title>OpenLP Display</title>
<style>
*{
*{{
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
-webkit-user-select: none;
}
body {
%s;
}
.size {
}}
body {{
{background_css};
}}
.size {{
position: absolute;
left: 0px;
top: 0px;
width: 100%%;
height: 100%%;
}
#black {
width: 100%;
height: 100%;
}}
#black {{
z-index: 8;
background-color: black;
display: none;
}
#bgimage {
}}
#bgimage {{
z-index: 1;
}
#image {
}}
#image {{
z-index: 2;
}
%s
#footer {
}}
{additions}
#footer {{
position: absolute;
z-index: 6;
%s
}
{footer_css}
}}
/* lyric css */
%s
sup {
{lyrics_css}
sup {{
font-size: 0.6em;
vertical-align: top;
position: relative;
top: -0.3em;
}
}}
</style>
<script>
var timer = null;
var transition = %s;
%s
var transition = {transitions};
{js_additions}
function show_image(src){
function show_image(src){{
var img = document.getElementById('image');
img.src = src;
if(src == '')
img.style.display = 'none';
else
img.style.display = 'block';
}
}}
function show_blank(state){
function show_blank(state){{
var black = 'none';
var lyrics = '';
switch(state){
switch(state){{
case 'theme':
lyrics = 'hidden';
break;
@ -472,18 +472,18 @@ sup {
break;
case 'desktop':
break;
}
}}
document.getElementById('black').style.display = black;
document.getElementById('lyricsmain').style.visibility = lyrics;
document.getElementById('image').style.visibility = lyrics;
document.getElementById('footer').style.visibility = lyrics;
}
}}
function show_footer(footertext){
function show_footer(footertext){{
document.getElementById('footer').innerHTML = footertext;
}
}}
function show_text(new_text){
function show_text(new_text){{
var match = /-webkit-text-fill-color:[^;\"]+/gi;
if(timer != null)
clearTimeout(timer);
@ -493,35 +493,35 @@ sup {
but only in this scenario.
*/
var txt = document.getElementById('lyricsmain');
if(window.getComputedStyle(txt).textAlign == 'justify'){
if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
if(window.getComputedStyle(txt).textAlign == 'justify'){{
if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){{
new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
function(match) {
function(match) {{
return '</span>' + match + '<span>';
});
}});
new_text = '<span>' + new_text + '</span>';
}
}
}}
}}
text_fade('lyricsmain', new_text);
}
}}
function text_fade(id, new_text){
function text_fade(id, new_text){{
/*
Show the text.
*/
var text = document.getElementById(id);
if(text == null) return;
if(!transition){
if(!transition){{
text.innerHTML = new_text;
return;
}
}}
// Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
text.style.opacity = '0.1';
// Fade new text in after the old text has finished fading out.
timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
}
timer = window.setTimeout(function(){{_show_text(text, new_text)}}, 400);
}}
function _show_text(text, new_text) {
function _show_text(text, new_text) {{
/*
Helper function to show the new_text delayed.
*/
@ -529,18 +529,18 @@ sup {
text.style.opacity = '1';
// Wait until the text is completely visible. We want to save the timer id, to be able to call
// clearTimeout(timer) when the text has changed before finishing fading.
timer = window.setTimeout(function(){timer = null;}, 400);
}
timer = window.setTimeout(function(){{timer = null;}}, 400);
}}
function show_text_completed(){
function show_text_completed(){{
return (timer == null);
}
}}
</script>
</head>
<body>
<img id="bgimage" class="size" %s />
<img id="image" class="size" %s />
%s
<img id="bgimage" class="size" {bgimage} />
<img id="image" class="size" {image} />
{html_additions}
<div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
<div id="footer" class="footer"></div>
<div id="black" class="size"></div>
@ -582,17 +582,17 @@ def build_html(item, screen, is_live, background, image=None, plugins=None):
css_additions += plugin.get_display_css()
js_additions += plugin.get_display_javascript()
html_additions += plugin.get_display_html()
html = HTMLSRC % (
build_background_css(item, width),
css_additions,
build_footer_css(item, height),
build_lyrics_css(item),
'true' if theme_data and theme_data.display_slide_transition and is_live else 'false',
js_additions,
bgimage_src,
image_src,
html_additions
)
html = HTMLSRC.format(background_css=build_background_css(item, width),
additions=css_additions,
footer_css=build_footer_css(item, height),
lyrics_css=build_lyrics_css(item),
transitions='true' if (theme_data and
theme_data.display_slide_transition and
is_live) else 'false',
js_additions=js_additions,
bgimage=bgimage_src,
image=image_src,
html_additions=html_additions)
return html
@ -650,23 +650,23 @@ def build_lyrics_css(item):
:param item: Service Item containing theme and location information
"""
# TODO: Verify this before converting to python3
# TODO: Tested at home
style = """
.lyricstable {
.lyricstable {{
z-index: 5;
position: absolute;
display: table;
%s
}
.lyricscell {
{stable}
}}
.lyricscell {{
display: table-cell;
word-wrap: break-word;
-webkit-transition: opacity 0.4s ease;
%s
}
.lyricsmain {
%s
}
{lyrics}
}}
.lyricsmain {{
{main}
}}
"""
theme_data = item.theme_data
lyricstable = ''
@ -680,7 +680,7 @@ def build_lyrics_css(item):
lyricsmain += ' text-shadow: {theme} {shadow}px ' \
'{shadow}px;'.format(theme=theme_data.font_main_shadow_color,
shadow=theme_data.font_main_shadow_size)
lyrics_css = style % (lyricstable, lyrics, lyricsmain)
lyrics_css = style.format(stable=lyricstable, lyrics=lyrics, main=lyricsmain)
return lyrics_css

View File

@ -370,21 +370,22 @@ class Renderer(OpenLPMixin, RegistryMixin, RegistryProperties):
self.web.resize(self.page_width, self.page_height)
self.web_frame = self.web.page().mainFrame()
# Adjust width and height to account for shadow. outline done in css.
# TODO: Verify before converting to python3 strings
# TODO: Tested at home
html = """<!DOCTYPE html><html><head><script>
function show_text(newtext) {
function show_text(newtext) {{
var main = document.getElementById('main');
main.innerHTML = newtext;
// We need to be sure that the page is loaded, that is why we
// return the element's height (even though we do not use the
// returned value).
return main.offsetHeight;
}
</script><style>*{margin: 0; padding: 0; border: 0;}
#main {position: absolute; top: 0px; %s %s}</style></head><body>
<div id="main"></div></body></html>""" % \
(build_lyrics_format_css(theme_data, self.page_width, self.page_height),
build_lyrics_outline_css(theme_data))
}}
</script><style>*{{margin: 0; padding: 0; border: 0;}}
#main {{position: absolute; top: 0px; {format_css} {outline_css}}}</style></head><body>
<div id="main"></div></body></html>""".format(format_css=build_lyrics_format_css(theme_data,
self.page_width,
self.page_height),
outline_css=build_lyrics_outline_css(theme_data))
self.web.setHtml(html)
self.empty_height = self.web_frame.contentsSize().height()

View File

@ -513,8 +513,8 @@ class ThemeXML(object):
theme_strings = []
for key in dir(self):
if key[0:1] != '_':
# TODO: Verify spacing format before converting to python3 string
theme_strings.append('%30s: %s' % (key, getattr(self, key)))
# TODO: Tested at home
theme_strings.append('{key:>30}: {value}'.format(key=key, value=getattr(self, key)))
return '\n'.join(theme_strings)
def _build_xml_from_attrs(self):

View File

@ -91,13 +91,13 @@ class ExceptionForm(QtWidgets.QDialog, Ui_ExceptionDialog, RegistryProperties):
super(ExceptionForm, self).__init__(None, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
self.setupUi(self)
self.settings_section = 'crashreport'
# TODO: Need to see how to format strings when string with tags is actually a variable
# TODO: Should work - need to test
self.report_text = '**OpenLP Bug Report**\n' \
'Version: %s\n\n' \
'--- Details of the Exception. ---\n\n%s\n\n ' \
'--- Exception Traceback ---\n%s\n' \
'--- System information ---\n%s\n' \
'--- Library Versions ---\n%s\n'
'Version: {version}\n\n' \
'--- Details of the Exception. ---\n\n{description}\n\n ' \
'--- Exception Traceback ---\n{traceback}\n' \
'--- System information ---\n{system}\n' \
'--- Library Versions ---\n{libs}\n'
def exec(self):
"""
@ -133,7 +133,15 @@ class ExceptionForm(QtWidgets.QDialog, Ui_ExceptionDialog, RegistryProperties):
system += 'Desktop: GNOME\n'
elif os.environ.get('DESKTOP_SESSION') == 'xfce':
system += 'Desktop: Xfce\n'
return openlp_version, description, traceback, system, libraries
# NOTE: This needs to return a string that format() will use. See __init__.self.report_text for names.
return ("version='{version}', "
"description='{description}', "
"traceback='{traceback}', "
"libs='{libs}'").format(version=openlp_version,
description=description,
traceback=traceback,
system=system,
libs=libraries)
def on_save_report_button_clicked(self):
"""
@ -147,7 +155,8 @@ class ExceptionForm(QtWidgets.QDialog, Ui_ExceptionDialog, RegistryProperties):
if filename:
filename = str(filename).replace('/', os.path.sep)
Settings().setValue(self.settings_section + '/last directory', os.path.dirname(filename))
report_text = self.report_text % self._create_report()
# NOTE: self._create_report() should return a string with the key names for format()
report_text = self.report_text.format(self._create_report())
try:
report_file = open(filename, 'w')
try:
@ -167,6 +176,7 @@ class ExceptionForm(QtWidgets.QDialog, Ui_ExceptionDialog, RegistryProperties):
"""
Opening systems default email client and inserting exception log and system information.
"""
# NOTE: self._create_report() should return a string with keys for format()
content = self._create_report()
source = ''
exception = ''
@ -178,8 +188,8 @@ class ExceptionForm(QtWidgets.QDialog, Ui_ExceptionDialog, RegistryProperties):
subject = 'Bug report: {error} in {source}'.format(error=exception, source=source)
mail_urlquery = QtCore.QUrlQuery()
mail_urlquery.addQueryItem('subject', subject)
# TODO: Find out how to format() text that is in a variable
mail_urlquery.addQueryItem('body', self.report_text % content)
# TODO: Should be good - need to test
mail_urlquery.addQueryItem('body', self.report_text.format(content))
if self.file_attachment:
mail_urlquery.addQueryItem('attach', self.file_attachment)
mail_to_url = QtCore.QUrl('mailto:bugs@openlp.org')

View File

@ -207,8 +207,8 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
trace_error_handler(log)
self.update_screen_list_combo()
self.application.process_events()
# TODO: Figure out how to use a variable with format()
self.downloading = translate('OpenLP.FirstTimeWizard', 'Downloading %s...')
# TODO: Tested at home
self.downloading = translate('OpenLP.FirstTimeWizard', 'Downloading {name}...')
if self.has_run_wizard:
self.songs_check_box.setChecked(self.plugin_manager.get_plugin_by_name('songs').is_active())
self.bible_check_box.setChecked(self.plugin_manager.get_plugin_by_name('bibles').is_active())
@ -564,7 +564,7 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
self.progress_bar.setValue(self.progress_bar.maximum())
if self.has_run_wizard:
text = translate('OpenLP.FirstTimeWizard',
'Download complete. Click the {button} button to return to OpenLP.'
'Download complete. Click the {text} button to return to OpenLP.'
).format(text=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))
self.progress_label.setText(text)
else:
@ -632,7 +632,8 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
item = self.songs_list_widget.item(i)
if item.checkState() == QtCore.Qt.Checked:
filename, sha256 = item.data(QtCore.Qt.UserRole)
self._increment_progress_bar(self.downloading % filename, 0)
# TODO: Tested at home
self._increment_progress_bar(self.downloading.format(name=filename), 0)
self.previous_size = 0
destination = os.path.join(songs_destination, str(filename))
if not self.url_get_file('{path}{name}'.format(path=self.songs_url, name=filename),
@ -644,7 +645,8 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
item = bibles_iterator.value()
if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
bible, sha256 = item.data(0, QtCore.Qt.UserRole)
self._increment_progress_bar(self.downloading % bible, 0)
# TODO: Tested at home
self._increment_progress_bar(self.downloading.format(name=bible), 0)
self.previous_size = 0
if not self.url_get_file('{path}{name}'.format(path=self.bibles_url, name=bible),
os.path.join(bibles_destination, bible),
@ -656,8 +658,8 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
item = self.themes_list_widget.item(i)
if item.checkState() == QtCore.Qt.Checked:
theme, sha256 = item.data(QtCore.Qt.UserRole)
# TODO: Verify how to use format() with strings in a variable
self._increment_progress_bar(self.downloading % theme, 0)
# TODO: Tested at home
self._increment_progress_bar(self.downloading.format(name=theme), 0)
self.previous_size = 0
if not self.url_get_file('{path}{name}'.format(path=self.themes_url, name=theme),
os.path.join(themes_destination, theme),

View File

@ -1334,7 +1334,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties):
self.recent_files_menu.clear()
for file_id, filename in enumerate(recent_files_to_display):
log.debug('Recent file name: {name}'.format(name=filename))
# TODO: Verify ''.format() before committing
# TODO: Should be good
action = create_action(self, '',
text='&{n} {name}'.format(n=file_id + 1,
name=os.path.splitext(os.path.basename(str(filename)))[0]),

View File

@ -60,7 +60,7 @@ class PluginForm(QtWidgets.QDialog, Ui_PluginViewDialog, RegistryProperties):
self._clear_details()
self.programatic_change = True
plugin_list_width = 0
# TODO: See how to use format() with variables
# TODO: Tested at home
for plugin in self.plugin_manager.plugins:
item = QtWidgets.QListWidgetItem(self.plugin_list_widget)
# We do this just to make 100% sure the status is an integer as
@ -68,19 +68,19 @@ class PluginForm(QtWidgets.QDialog, Ui_PluginViewDialog, RegistryProperties):
plugin.status = int(plugin.status)
# Set the little status text in brackets next to the plugin name.
if plugin.status == PluginStatus.Disabled:
status_text = translate('OpenLP.PluginForm', '%s (Disabled)')
status_text = translate('OpenLP.PluginForm', '{name} (Disabled)')
elif plugin.status == PluginStatus.Active:
status_text = translate('OpenLP.PluginForm', '%s (Active)')
status_text = translate('OpenLP.PluginForm', '{name} (Active)')
else:
# PluginStatus.Inactive
status_text = translate('OpenLP.PluginForm', '%s (Inactive)')
item.setText(status_text % plugin.name_strings['singular'])
status_text = translate('OpenLP.PluginForm', '{name} (Inactive)')
item.setText(status_text.format(name=plugin.name_strings['singular']))
# If the plugin has an icon, set it!
if plugin.icon:
item.setIcon(plugin.icon)
self.plugin_list_widget.addItem(item)
plugin_list_width = max(plugin_list_width, self.fontMetrics().width(
translate('OpenLP.PluginForm', '%s (Inactive)') % plugin.name_strings['singular']))
translate('OpenLP.PluginForm', '{name} (Inactive)').format(name=plugin.name_strings['singular'])))
self.plugin_list_widget.setFixedWidth(plugin_list_width + self.plugin_list_widget.iconSize().width() + 48)
def _clear_details(self):
@ -137,13 +137,13 @@ class PluginForm(QtWidgets.QDialog, Ui_PluginViewDialog, RegistryProperties):
self.active_plugin.app_startup()
else:
self.active_plugin.toggle_status(PluginStatus.Inactive)
# TODO: Verify using format() with a variable
status_text = translate('OpenLP.PluginForm', '%s (Inactive)')
# TODO: Tested at home
status_text = translate('OpenLP.PluginForm', '{name} (Inactive)')
if self.active_plugin.status == PluginStatus.Active:
status_text = translate('OpenLP.PluginForm', '%s (Active)')
status_text = translate('OpenLP.PluginForm', '{name} (Active)')
elif self.active_plugin.status == PluginStatus.Inactive:
status_text = translate('OpenLP.PluginForm', '%s (Inactive)')
status_text = translate('OpenLP.PluginForm', '{name} (Inactive)')
elif self.active_plugin.status == PluginStatus.Disabled:
status_text = translate('OpenLP.PluginForm', '%s (Disabled)')
status_text = translate('OpenLP.PluginForm', '{name} (Disabled)')
self.plugin_list_widget.currentItem().setText(
status_text % self.active_plugin.name_strings['singular'])
status_text.format(name=self.active_plugin.name_strings['singular']))

View File

@ -464,9 +464,9 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
"""
Background video button pushed.
"""
# TODO: Check this before converting
visible_formats = '(%s)' % '; '.join(VIDEO_EXT)
actual_formats = '(%s)' % ' '.join(VIDEO_EXT)
# TODO: Should work
visible_formats = '({name})'.format(name='; '.join(VIDEO_EXT))
actual_formats = '({name})'.format(name=' '.join(VIDEO_EXT))
video_filter = '{trans} {visible} {actual}'.format(trans=translate('OpenLP', 'Video Files'),
visible=visible_formats, actual=actual_formats)
video_filter = '{video};;{ui} (*.*)'.format(video=video_filter, ui=UiStrings().AllFiles)

View File

@ -769,7 +769,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
'{count} time(s) by {plugin}'
).format(name=used_count,
plugin=plugin.name)))
plugin_usage = "%s\n" % plugin_usage
plugin_usage = "{text}\n".format(text=plugin_usage)
if plugin_usage:
critical_error_message_box(translate('OpenLP.ThemeManager', 'Unable to delete theme'),
translate('OpenLP.ThemeManager',

View File

@ -60,7 +60,7 @@ class TestFileDialog(TestCase):
self.mocked_os.path.exists.side_effect = lambda file_name: file_name in [
'/Valid File', '/url encoded file #1']
self.mocked_ui_strings().FileNotFound = 'File Not Found'
self.mocked_ui_strings().FileNotFoundMessage = 'File %s not found.\nPlease try selecting it individually.'
self.mocked_ui_strings().FileNotFoundMessage = 'File {name} not found.\nPlease try selecting it individually.'
# WHEN: FileDialog.getOpenFileNames is called
result = FileDialog.getOpenFileNames(self.mocked_parent)