diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py
index e6f70b1e8..c527a4e20 100644
--- a/openlp/core/__init__.py
+++ b/openlp/core/__init__.py
@@ -251,8 +251,7 @@ class OpenLP(OpenLPMixin, QtWidgets.QApplication):
if QtWidgets.QMessageBox.question(None, translate('OpenLP', 'Backup'),
translate('OpenLP', 'OpenLP has been upgraded, do you want to create\n'
'a backup of the old data folder?'),
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
- QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
+ defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
# Create copy of data folder
data_folder_path = AppLocation.get_data_path()
timestamp = time.strftime("%Y%m%d-%H%M%S")
diff --git a/openlp/core/common/languagemanager.py b/openlp/core/common/languagemanager.py
index 5023f7383..026a6ddda 100644
--- a/openlp/core/common/languagemanager.py
+++ b/openlp/core/common/languagemanager.py
@@ -140,8 +140,8 @@ class LanguageManager(object):
reg_ex = QtCore.QRegExp("^.*i18n/(.*).qm")
if reg_ex.exactMatch(qmf):
name = '{regex}'.format(regex=reg_ex.cap(1))
- # TODO: Test before converting to python3 string format
- LanguageManager.__qm_list__['%#2i %s' % (counter + 1, LanguageManager.language_name(qmf))] = name
+ LanguageManager.__qm_list__[
+ '{count:>2i} {name}'.format(count=counter + 1, name=LanguageManager.language_name(qmf))] = name
@staticmethod
def get_qm_list():
diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py
index 39320ae96..7a1e31553 100644
--- a/openlp/core/common/settings.py
+++ b/openlp/core/common/settings.py
@@ -238,7 +238,11 @@ class Settings(QtCore.QSettings):
('shortcuts/offlineHelpItem', 'shortcuts/userManualItem', []), # Online and Offline help were combined in 2.6.
('shortcuts/onlineHelpItem', 'shortcuts/userManualItem', []), # Online and Offline help were combined in 2.6.
('bibles/advanced bible', '', []), # Common bible search widgets combined in 2.6
- ('bibles/quick bible', 'bibles/primary bible', []) # Common bible search widgets combined in 2.6
+ ('bibles/quick bible', 'bibles/primary bible', []), # Common bible search widgets combined in 2.6
+ # Last search type was renamed to last used search type in 2.6 since Bible search value type changed in 2.6.
+ ('songs/last search type', 'songs/last used search type', []),
+ ('bibles/last search type', '', []),
+ ('custom/last search type', 'custom/last used search type', [])
]
@staticmethod
diff --git a/openlp/core/common/uistrings.py b/openlp/core/common/uistrings.py
index a2481ab84..b818d3b31 100644
--- a/openlp/core/common/uistrings.py
+++ b/openlp/core/common/uistrings.py
@@ -152,8 +152,6 @@ 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: 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')
diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py
index 3e2187b77..6407f7a78 100644
--- a/openlp/core/lib/db.py
+++ b/openlp/core/lib/db.py
@@ -144,6 +144,7 @@ def upgrade_db(url, upgrade):
:param url: The url of the database to upgrade.
:param upgrade: The python module that contains the upgrade instructions.
"""
+ log.debug('Checking upgrades for DB {db}'.format(db=url))
session, metadata = init_db(url)
class Metadata(BaseModel):
@@ -160,17 +161,15 @@ def upgrade_db(url, upgrade):
metadata_table.create(checkfirst=True)
mapper(Metadata, metadata_table)
version_meta = session.query(Metadata).get('version')
- if version_meta is None:
- # Tables have just been created - fill the version field with the most recent version
- if session.query(Metadata).get('dbversion'):
- version = 0
- else:
- version = upgrade.__version__
+ if version_meta:
+ version = int(version_meta.value)
+ else:
+ # Due to issues with other checks, if the version is not set in the DB then default to 0
+ # and let the upgrade function handle the checks
+ version = 0
version_meta = Metadata.populate(key='version', value=version)
session.add(version_meta)
session.commit()
- else:
- version = int(version_meta.value)
if version > upgrade.__version__:
session.remove()
return version, upgrade.__version__
diff --git a/openlp/core/lib/exceptions.py b/openlp/core/lib/exceptions.py
index 8e1645fae..26ff56a79 100644
--- a/openlp/core/lib/exceptions.py
+++ b/openlp/core/lib/exceptions.py
@@ -24,7 +24,6 @@ The :mod:`~openlp.core.lib.exceptions` module contains custom exceptions
"""
-# TODO: Test __init__ & __str__
class ValidationError(Exception):
"""
The :class:`~openlp.core.lib.exceptions.ValidationError` exception provides a custom exception for validating
diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py
index 4ddbaa401..f2071a190 100644
--- a/openlp/core/lib/imagemanager.py
+++ b/openlp/core/lib/imagemanager.py
@@ -110,6 +110,8 @@ class Image(object):
:param width: The width of the image, defaults to -1 meaning that the screen width will be used.
:param height: The height of the image, defaults to -1 meaning that the screen height will be used.
"""
+ if not os.path.exists(path):
+ raise FileNotFoundError('{path} not found'.format(path=path))
self.path = path
self.image = None
self.image_bytes = None
@@ -119,9 +121,7 @@ class Image(object):
self.timestamp = 0
self.width = width
self.height = height
- # FIXME: We assume that the path exist. The caller has to take care that it exists!
- if os.path.exists(path):
- self.timestamp = os.stat(path).st_mtime
+ self.timestamp = os.stat(path).st_mtime
self.secondary_priority = Image.secondary_priority
Image.secondary_priority += 1
diff --git a/openlp/core/lib/projector/constants.py b/openlp/core/lib/projector/constants.py
index 5177aa691..38331f500 100644
--- a/openlp/core/lib/projector/constants.py
+++ b/openlp/core/lib/projector/constants.py
@@ -57,35 +57,115 @@ LF = chr(0x0A) # \n
PJLINK_PORT = 4352
TIMEOUT = 30.0
PJLINK_MAX_PACKET = 136
-# NOTE: Change format to account for some commands are both class 1 and 2
+# NOTE: Changed format to account for some commands are both class 1 and 2
PJLINK_VALID_CMD = {
- 'ACKN': ['2', ], # UDP Reply to 'SRCH'
- 'AVMT': ['1', ], # Shutter option
- 'CLSS': ['1', ], # PJLink class support query
- 'ERST': ['1', '2'], # Error status option
- 'FILT': ['2', ], # Get current filter usage time
- 'FREZ': ['2', ], # Set freeze/unfreeze picture being projected
- 'INF1': ['1', ], # Manufacturer name query
- 'INF2': ['1', ], # Product name query
- 'INFO': ['1', ], # Other information query
- 'INNM': ['2', ], # Get Video source input terminal name
- 'INPT': ['1', ], # Video sources option
- 'INST': ['1', ], # Input sources available query
- 'IRES': ['2', ], # Get Video source resolution
- 'LAMP': ['1', ], # Lamp(s) query (Includes fans)
- 'LKUP': ['2', ], # UPD Linkup status notification
- 'MVOL': ['2', ], # Set microphone volume
- 'NAME': ['1', ], # Projector name query
- 'PJLINK': ['1', ], # Initial connection
- 'POWR': ['1', ], # Power option
- 'RFIL': ['2', ], # Get replacement air filter model number
- 'RLMP': ['2', ], # Get lamp replacement model number
- 'RRES': ['2', ], # Get projector recommended video resolution
- 'SNUM': ['2', ], # Get projector serial number
- 'SRCH': ['2', ], # UDP broadcast search for available projectors on local network
- 'SVER': ['2', ], # Get projector software version
- 'SVOL': ['2', ] # Set speaker volume
+ 'ACKN': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Acknowledge a PJLink SRCH command - returns MAC address.')
+ },
+ 'AVMT': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Blank/unblank video and/or mute audio.')
+ },
+ 'CLSS': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query projector PJLink class support.')
+ },
+ 'ERST': {'version': ['1', '2'],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query error status from projector. '
+ 'Returns fan/lamp/temp/cover/filter/other error status.')
+ },
+ 'FILT': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query number of hours on filter.')
+ },
+ 'FREZ': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Freeze or unfreeze current image being projected.')
+ },
+ 'INF1': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query projector manufacturer name.')
+ },
+ 'INF2': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query projector product name.')
+ },
+ 'INFO': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query projector for other information set by manufacturer.')
+ },
+ 'INNM': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query specified input source name')
+ },
+ 'INPT': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Switch to specified video source.')
+ },
+ 'INST': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query available input sources.')
+ },
+ 'IRES': {'version:': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query current input resolution.')
+ },
+ 'LAMP': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query lamp time and on/off status. Multiple lamps supported.')
+ },
+ 'LKUP': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'UDP Status notify. Includes MAC address.')
+ },
+ 'MVOL': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Adjust microphone volume by 1 step.')
+ },
+ 'NAME': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query customer-set projector name.')
+ },
+ 'PJLINK': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Initial connection with authentication/no authentication request.')
+ },
+ 'POWR': {'version': ['1', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Turn lamp on or off/standby.')
+ },
+ 'RFIL': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query replacement air filter model number.')
+ },
+ 'RLMP': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query replacement lamp model number.')
+ },
+ 'RRES': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query recommended resolution.')
+ },
+ 'SNUM': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query projector serial number.')
+ },
+ 'SRCH': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'UDP broadcast search request for available projectors.')
+ },
+ 'SVER': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Query projector software version number.')
+ },
+ 'SVOL': {'version': ['2', ],
+ 'description': translate('OpenLP.PJLinkConstants',
+ 'Adjust speaker volume by 1 step.')
+ }
}
+
# Error and status codes
S_OK = E_OK = 0 # E_OK included since I sometimes forget
# Error codes. Start at 200 so we don't duplicate system error codes.
diff --git a/openlp/core/lib/projector/db.py b/openlp/core/lib/projector/db.py
index 11b84b019..89b807f21 100644
--- a/openlp/core/lib/projector/db.py
+++ b/openlp/core/lib/projector/db.py
@@ -44,6 +44,7 @@ from sqlalchemy.orm import relationship
from openlp.core.lib.db import Manager, init_db, init_url
from openlp.core.lib.projector.constants import PJLINK_DEFAULT_CODES
+from openlp.core.lib.projector import upgrade
Base = declarative_base(MetaData())
@@ -166,13 +167,14 @@ class Projector(CommonBase, Base):
"""
Return basic representation of Source table entry.
"""
- return '< Projector(id="{data}", ip="{ip}", port="{port}", pin="{pin}", name="{name}", ' \
+ return '< Projector(id="{data}", ip="{ip}", port="{port}", mac_adx="{mac}", pin="{pin}", name="{name}", ' \
'location="{location}", notes="{notes}", pjlink_name="{pjlink_name}", ' \
'manufacturer="{manufacturer}", model="{model}", serial_no="{serial}", other="{other}", ' \
'sources="{sources}", source_list="{source_list}", model_filter="{mfilter}", ' \
'model_lamp="{mlamp}", sw_version="{sw_ver}") >'.format(data=self.id,
ip=self.ip,
port=self.port,
+ mac=self.mac_adx,
pin=self.pin,
name=self.name,
location=self.location,
@@ -189,6 +191,7 @@ class Projector(CommonBase, Base):
sw_ver=self.sw_version)
ip = Column(String(100))
port = Column(String(8))
+ mac_adx = Column(String(18))
pin = Column(String(20))
name = Column(String(20))
location = Column(String(30))
@@ -243,7 +246,9 @@ class ProjectorDB(Manager):
"""
def __init__(self, *args, **kwargs):
log.debug('ProjectorDB().__init__(args="{arg}", kwargs="{kwarg}")'.format(arg=args, kwarg=kwargs))
- super().__init__(plugin_name='projector', init_schema=self.init_schema)
+ super().__init__(plugin_name='projector',
+ init_schema=self.init_schema,
+ upgrade_mod=upgrade)
log.debug('ProjectorDB() Initialized using db url {db}'.format(db=self.db_url))
log.debug('Session: {session}'.format(session=self.session))
diff --git a/openlp/core/lib/projector/pjlink1.py b/openlp/core/lib/projector/pjlink1.py
index 2252c566c..dfc261f0a 100644
--- a/openlp/core/lib/projector/pjlink1.py
+++ b/openlp/core/lib/projector/pjlink1.py
@@ -129,7 +129,7 @@ class PJLink(QtNetwork.QTcpSocket):
self.ip = ip
self.port = port
self.pin = pin
- super(PJLink, self).__init__()
+ super().__init__()
self.dbid = None
self.location = None
self.notes = None
@@ -186,10 +186,15 @@ class PJLink(QtNetwork.QTcpSocket):
self.pjlink_name = None
self.manufacturer = None
self.model = None
+ self.serial_no = None
+ self.sw_version = None
self.shutter = None
self.mute = None
self.lamp = None
+ self.model_lamp = None
self.fan = None
+ self.filter_time = None
+ self.model_filter = None
self.source_available = None
self.source = None
self.other_info = None
@@ -451,18 +456,18 @@ class PJLink(QtNetwork.QTcpSocket):
return
data_split = data.split('=')
try:
- (prefix, class_, cmd, data) = (data_split[0][0], data_split[0][1], data_split[0][2:], data_split[1])
+ (prefix, version, cmd, data) = (data_split[0][0], data_split[0][1], data_split[0][2:], data_split[1])
except ValueError as e:
log.warning('({ip}) get_data(): Invalid packet - expected header + command + data'.format(ip=self.ip))
log.warning('({ip}) get_data(): Received data: "{data}"'.format(ip=self.ip, data=data_in.strip()))
self.change_status(E_INVALID_DATA)
self.receive_data_signal()
return
- if not (cmd in PJLINK_VALID_CMD and class_ in PJLINK_VALID_CMD[cmd]):
+ if cmd not in PJLINK_VALID_CMD:
log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd))
self.receive_data_signal()
return
- if int(self.pjlink_class) < int(class_):
+ if int(self.pjlink_class) < int(version):
log.warn('({ip}) get_data(): Projector returned class reply higher '
'than projector stated class'.format(ip=self.ip))
return self.process_command(cmd, data)
@@ -507,14 +512,25 @@ class PJLink(QtNetwork.QTcpSocket):
log.warning('({ip}) send_command(): Not connected - returning'.format(ip=self.ip))
self.send_queue = []
return
+ if cmd not in PJLINK_VALID_CMD:
+ log.error('({ip}) send_command(): Invalid command requested - ignoring.'.format(ip=self.ip))
+ return
self.projectorNetwork.emit(S_NETWORK_SENDING)
log.debug('({ip}) send_command(): Building cmd="{command}" opts="{data}"{salt}'.format(ip=self.ip,
command=cmd,
data=opts,
salt='' if salt is None
else ' with hash'))
- # TODO: Check for class of command rather than default to projector PJLink class
- header = PJLINK_HEADER.format(linkclass=self.pjlink_class)
+ cmd_ver = PJLINK_VALID_CMD[cmd]['version']
+ if self.pjlink_class in cmd_ver:
+ header = PJLINK_HEADER.format(linkclass=self.pjlink_class)
+ elif len(cmd_ver) == 1 and (int(cmd_ver[0]) < int(self.pjlink_class)):
+ # Typically a class 1 only command
+ header = PJLINK_HEADER.format(linkclass=cmd_ver[0])
+ else:
+ # NOTE: Once we get to version 3 then think about looping
+ log.error('({ip}): send_command(): PJLink class check issue? aborting'.format(ip=self.ip))
+ return
out = '{salt}{header}{command} {options}{suffix}'.format(salt="" if salt is None else salt,
header=header,
command=cmd,
@@ -589,10 +605,13 @@ class PJLink(QtNetwork.QTcpSocket):
cmd=cmd,
data=data))
# Check if we have a future command not available yet
- if cmd in self.pjlink_future:
- self._not_implemented(cmd)
+ if cmd not in PJLINK_VALID_CMD:
+ log.error('({ip}) Unknown command received - ignoring'.format(ip=self.ip))
return
- if data in PJLINK_ERRORS:
+ elif cmd not in self.pjlink_functions:
+ log.warn('({ip}) Future command received - unable to process yet'.format(ip=self.ip))
+ return
+ elif data in PJLINK_ERRORS:
# Oops - projector error
log.error('({ip}) Projector returned error "{data}"'.format(ip=self.ip, data=data))
if data.upper() == 'ERRA':
@@ -624,14 +643,11 @@ class PJLink(QtNetwork.QTcpSocket):
self.send_busy = False
self.projectorReceivedData.emit()
return
-
- if cmd in self.pjlink_functions:
- log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd))
- self.pjlink_functions[cmd](data)
- else:
- log.warning('({ip}) Invalid command {data}'.format(ip=self.ip, data=cmd))
+ # Command checks already passed
+ log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd))
self.send_busy = False
self.projectorReceivedData.emit()
+ self.pjlink_functions[cmd](data)
def process_lamp(self, data):
"""
diff --git a/openlp/core/lib/projector/upgrade.py b/openlp/core/lib/projector/upgrade.py
new file mode 100644
index 000000000..4d2f4532e
--- /dev/null
+++ b/openlp/core/lib/projector/upgrade.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2017 OpenLP Developers #
+# --------------------------------------------------------------------------- #
+# 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 #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+"""
+The :mod:`upgrade` module provides a way for the database and schema that is the
+backend for the projector setup.
+"""
+import logging
+
+# Not all imports used at this time, but keep for future upgrades
+from sqlalchemy import Column, types
+from sqlalchemy.sql.expression import null
+
+from openlp.core.common.db import drop_columns
+from openlp.core.lib.db import get_upgrade_op
+
+log = logging.getLogger(__name__)
+
+# Initial projector DB was unversioned
+__version__ = 2
+
+log.debug('Projector DB upgrade module loading')
+
+
+def upgrade_1(session, metadata):
+ """
+ Version 1 upgrade - old db might/might not be versioned.
+ """
+ pass
+
+
+def upgrade_2(session, metadata):
+ """
+ Version 2 upgrade.
+
+ Update Projector() table to include new data defined in PJLink version 2 changes
+
+ serial_no: Column(String(30))
+ sw_version: Column(String(30))
+ model_filter: Column(String(30))
+ model_lamp: Column(String(30))
+
+ :param session: DB session instance
+ :param metadata: Metadata of current DB
+ """
+
+ new_op = get_upgrade_op(session)
+ if 'serial_no' not in [t.name for t in metadata.tables.values()]:
+ log.debug("Upgrading projector DB to version '2'")
+ new_op.add_column('projector', Column('mac_adx', types.String(18), server_default=null()))
+ new_op.add_column('projector', Column('serial_no', types.String(30), server_default=null()))
+ new_op.add_column('projector', Column('sw_version', types.String(30), server_default=null()))
+ new_op.add_column('projector', Column('model_filter', types.String(30), server_default=null()))
+ new_op.add_column('projector', Column('model_lamp', types.String(30), server_default=null()))
+ else:
+ log.warn("Skipping upgrade_2 of projector DB")
diff --git a/openlp/core/lib/searchedit.py b/openlp/core/lib/searchedit.py
index 52baf0d2c..e2e70a934 100644
--- a/openlp/core/lib/searchedit.py
+++ b/openlp/core/lib/searchedit.py
@@ -105,7 +105,7 @@ class SearchEdit(QtWidgets.QLineEdit):
self.setPlaceholderText(action.placeholder_text)
self.menu_button.setDefaultAction(action)
self._current_search_type = identifier
- Settings().setValue('{section}/last search type'.format(section=self.settings_section), identifier)
+ Settings().setValue('{section}/last used search type'.format(section=self.settings_section), identifier)
self.searchTypeChanged.emit(identifier)
return True
@@ -141,7 +141,7 @@ class SearchEdit(QtWidgets.QLineEdit):
self.menu_button.resize(QtCore.QSize(28, 18))
self.menu_button.setMenu(menu)
self.set_current_search_type(
- Settings().value('{section}/last search type'.format(section=self.settings_section)))
+ Settings().value('{section}/last used search type'.format(section=self.settings_section)))
self.menu_button.show()
self._update_style_sheet()
diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py
index 8cd68384f..fe67c53ba 100644
--- a/openlp/core/lib/ui.py
+++ b/openlp/core/lib/ui.py
@@ -49,6 +49,7 @@ def add_welcome_page(parent, image):
parent.title_label = QtWidgets.QLabel(parent.welcome_page)
parent.title_label.setObjectName('title_label')
parent.welcome_layout.addWidget(parent.title_label)
+ parent.title_label.setWordWrap(True)
parent.welcome_layout.addSpacing(40)
parent.information_label = QtWidgets.QLabel(parent.welcome_page)
parent.information_label.setWordWrap(True)
diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py
index 1b71229b5..2b8383755 100644
--- a/openlp/core/ui/__init__.py
+++ b/openlp/core/ui/__init__.py
@@ -99,7 +99,7 @@ from .themelayoutform import ThemeLayoutForm
from .themeform import ThemeForm
from .filerenameform import FileRenameForm
from .starttimeform import StartTimeForm
-from .maindisplay import MainDisplay, Display
+from .maindisplay import MainDisplay, Display, AudioPlayer
from .servicenoteform import ServiceNoteForm
from .serviceitemeditform import ServiceItemEditForm
from .slidecontroller import SlideController, DisplayController, PreviewController, LiveController
@@ -120,8 +120,8 @@ from .projector.tab import ProjectorTab
from .projector.editform import ProjectorEditForm
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeForm',
- 'ThemeManager', 'ServiceItemEditForm', 'FirstTimeForm', 'FirstTimeLanguageForm',
- 'Display', 'ServiceNoteForm', 'ThemeLayoutForm', 'FileRenameForm', 'StartTimeForm', 'MainDisplay',
+ 'ThemeManager', 'ServiceItemEditForm', 'FirstTimeForm', 'FirstTimeLanguageForm', 'Display', 'AudioPlayer',
+ 'ServiceNoteForm', 'ThemeLayoutForm', 'FileRenameForm', 'StartTimeForm', 'MainDisplay',
'SlideController', 'DisplayController', 'GeneralTab', 'ThemesTab', 'AdvancedTab', 'PluginForm',
'FormattingTagForm', 'ShortcutListForm', 'FormattingTagController', 'SingleColumnTableWidget',
'ProjectorManager', 'ProjectorTab', 'ProjectorEditForm']
diff --git a/openlp/core/ui/aboutform.py b/openlp/core/ui/aboutform.py
index f4f9b06a0..e1768b127 100644
--- a/openlp/core/ui/aboutform.py
+++ b/openlp/core/ui/aboutform.py
@@ -40,7 +40,8 @@ class AboutForm(QtWidgets.QDialog, UiAboutDialog):
"""
Do some initialisation stuff
"""
- super(AboutForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(AboutForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self._setup()
def _setup(self):
diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py
index d3955fb63..8d64bfecc 100644
--- a/openlp/core/ui/advancedtab.py
+++ b/openlp/core/ui/advancedtab.py
@@ -495,9 +495,7 @@ class AdvancedTab(SettingsTab):
'location of the OpenLP data directory to:\n\n{path}'
'\n\nThe data directory will be changed when OpenLP is '
'closed.').format(path=new_data_path),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
- QtWidgets.QMessageBox.No),
- QtWidgets.QMessageBox.No)
+ defaultButton=QtWidgets.QMessageBox.No)
if answer != QtWidgets.QMessageBox.Yes:
self.data_directory_path_edit.path = AppLocation.get_data_path()
return
diff --git a/openlp/core/ui/filerenameform.py b/openlp/core/ui/filerenameform.py
index 0fb9c8668..2314fda43 100644
--- a/openlp/core/ui/filerenameform.py
+++ b/openlp/core/ui/filerenameform.py
@@ -38,8 +38,8 @@ class FileRenameForm(QtWidgets.QDialog, Ui_FileRenameDialog, RegistryProperties)
"""
Constructor
"""
- super(FileRenameForm, self).__init__(Registry().get('main_window'),
- QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(FileRenameForm, self).__init__(Registry().get('main_window'), QtCore.Qt.WindowSystemMenuHint |
+ QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
self._setup()
def _setup(self):
diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py
index cc7668587..2a9682c36 100644
--- a/openlp/core/ui/firsttimeform.py
+++ b/openlp/core/ui/firsttimeform.py
@@ -206,7 +206,6 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
trace_error_handler(log)
self.update_screen_list_combo()
self.application.process_events()
- # 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())
@@ -561,7 +560,6 @@ 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)
- # 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))
@@ -574,7 +572,6 @@ 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)
- # TODO: Tested at home
self._increment_progress_bar(self.downloading.format(name=bible), 0)
self.previous_size = 0
if not url_get_file(self, '{path}{name}'.format(path=self.bibles_url, name=bible),
@@ -587,7 +584,6 @@ 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: Tested at home
self._increment_progress_bar(self.downloading.format(name=theme), 0)
self.previous_size = 0
if not url_get_file(self, '{path}{name}'.format(path=self.themes_url, name=theme),
diff --git a/openlp/core/ui/firsttimelanguageform.py b/openlp/core/ui/firsttimelanguageform.py
index 9e9d664ca..bfe593b83 100644
--- a/openlp/core/ui/firsttimelanguageform.py
+++ b/openlp/core/ui/firsttimelanguageform.py
@@ -37,7 +37,8 @@ class FirstTimeLanguageForm(QtWidgets.QDialog, Ui_FirstTimeLanguageDialog):
"""
Constructor
"""
- super(FirstTimeLanguageForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(FirstTimeLanguageForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint |
+ QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
self.qm_list = LanguageManager.get_qm_list()
self.language_combo_box.addItem('Autodetect')
diff --git a/openlp/core/ui/formattingtagcontroller.py b/openlp/core/ui/formattingtagcontroller.py
index 62e1833d4..062eb21fc 100644
--- a/openlp/core/ui/formattingtagcontroller.py
+++ b/openlp/core/ui/formattingtagcontroller.py
@@ -130,8 +130,7 @@ class FormattingTagController(object):
elif not match.group('empty'):
end_tags.append(tag)
match = self.html_tag_regex.search(start_html, match.end())
- # TODO: Verify format() works with lambda
- return ''.join(map(lambda tag: '%s>' % tag, reversed(end_tags)))
+ return ''.join(map(lambda tag: '{tag}>'.format(tag=tag), reversed(end_tags)))
def start_tag_changed(self, start_html, end_html):
"""
diff --git a/openlp/core/ui/formattingtagform.py b/openlp/core/ui/formattingtagform.py
index 1aeda9bc3..a4c32440a 100644
--- a/openlp/core/ui/formattingtagform.py
+++ b/openlp/core/ui/formattingtagform.py
@@ -51,7 +51,8 @@ class FormattingTagForm(QtWidgets.QDialog, Ui_FormattingTagDialog, FormattingTag
"""
Constructor
"""
- super(FormattingTagForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(FormattingTagForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
self._setup()
@@ -122,8 +123,7 @@ class FormattingTagForm(QtWidgets.QDialog, Ui_FormattingTagDialog, FormattingTag
self.tag_table_widget.item(count, 2).text(),
self.tag_table_widget.item(count, 3).text())
if error:
- QtWidgets.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), error,
- QtWidgets.QMessageBox.Ok)
+ QtWidgets.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), error)
self.tag_table_widget.selectRow(count)
return
count += 1
@@ -198,6 +198,5 @@ class FormattingTagForm(QtWidgets.QDialog, Ui_FormattingTagDialog, FormattingTag
if tag:
self.tag_table_widget.setItem(pre_row, 3, QtWidgets.QTableWidgetItem(tag))
if errors:
- QtWidgets.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), errors,
- QtWidgets.QMessageBox.Ok)
+ QtWidgets.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), errors)
self.tag_table_widget.resizeRowsToContents()
diff --git a/openlp/core/ui/lib/pathedit.py b/openlp/core/ui/lib/pathedit.py
index c489daa33..9c66478b2 100755
--- a/openlp/core/ui/lib/pathedit.py
+++ b/openlp/core/ui/lib/pathedit.py
@@ -48,7 +48,7 @@ class PathEdit(QtWidgets.QWidget):
:type parent: QWidget or None
:param dialog_caption: Used to customise the caption in the QFileDialog.
- :param dialog_caption: str
+ :type dialog_caption: str
:param default_path: The default path. This is set as the path when the revert button is clicked
:type default_path: str
diff --git a/openlp/core/ui/lib/wizard.py b/openlp/core/ui/lib/wizard.py
index 088bc3c1f..936682585 100644
--- a/openlp/core/ui/lib/wizard.py
+++ b/openlp/core/ui/lib/wizard.py
@@ -25,7 +25,7 @@ The :mod:``wizard`` module provides generic wizard tools for OpenLP.
import logging
import os
-from PyQt5 import QtGui, QtWidgets
+from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings, translate, is_macosx
from openlp.core.lib import build_icon
@@ -50,13 +50,13 @@ class WizardStrings(object):
# These strings should need a good reason to be retranslated elsewhere.
FinishedImport = translate('OpenLP.Ui', 'Finished import.')
FormatLabel = translate('OpenLP.Ui', 'Format:')
- HeaderStyle = '%s'
+ HeaderStyle = '{text}'
Importing = translate('OpenLP.Ui', 'Importing')
- ImportingType = translate('OpenLP.Ui', 'Importing "%s"...')
+ ImportingType = translate('OpenLP.Ui', 'Importing "{source}"...')
ImportSelect = translate('OpenLP.Ui', 'Select Import Source')
ImportSelectLong = translate('OpenLP.Ui', 'Select the import format and the location to import from.')
- OpenTypeFile = translate('OpenLP.Ui', 'Open %s File')
- OpenTypeFolder = translate('OpenLP.Ui', 'Open %s Folder')
+ OpenTypeFile = translate('OpenLP.Ui', 'Open {file_type} File')
+ OpenTypeFolder = translate('OpenLP.Ui', 'Open {folder_name} Folder')
PercentSymbolFormat = translate('OpenLP.Ui', '%p%')
Ready = translate('OpenLP.Ui', 'Ready.')
StartingImport = translate('OpenLP.Ui', 'Starting import...')
@@ -93,7 +93,10 @@ class OpenLPWizard(QtWidgets.QWizard, RegistryProperties):
"""
Constructor
"""
- super(OpenLPWizard, self).__init__(parent)
+ # QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint remove the "?" buttons from windows,
+ # QtCore.Qt.WindowCloseButtonHint enables the "x" button to close these windows.
+ super(OpenLPWizard, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.plugin = plugin
self.with_progress_page = add_progress_page
self.setFixedWidth(640)
diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py
index a40ade826..23151395c 100644
--- a/openlp/core/ui/maindisplay.py
+++ b/openlp/core/ui/maindisplay.py
@@ -689,7 +689,7 @@ class AudioPlayer(OpenLPMixin, QtCore.QObject):
"""
Skip forward to the next track in the list
"""
- self.playerlist.next()
+ self.playlist.next()
def go_to(self, index):
"""
diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py
index 79c19adf9..8299fc985 100644
--- a/openlp/core/ui/mainwindow.py
+++ b/openlp/core/ui/mainwindow.py
@@ -926,8 +926,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties):
QtWidgets.QMessageBox.information(self, translate('OpenLP.MainWindow', 'Import settings'),
translate('OpenLP.MainWindow',
'OpenLP will now close. Imported settings will '
- 'be applied the next time you start OpenLP.'),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
+ 'be applied the next time you start OpenLP.'))
self.settings_imported = True
self.clean_up()
QtCore.QCoreApplication.exit()
@@ -1322,7 +1321,6 @@ 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: 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]),
diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py
index e84fbee63..f0fb47cc6 100644
--- a/openlp/core/ui/media/mediacontroller.py
+++ b/openlp/core/ui/media/mediacontroller.py
@@ -468,9 +468,10 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
player = self.media_players[used_players[0]]
if suffix not in player.video_extensions_list and suffix not in player.audio_extensions_list:
# Media could not be loaded correctly
- critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported Media File'),
- translate('MediaPlugin.MediaItem', 'File %s not supported using player %s') %
- (service_item.get_frame_path(), used_players[0]))
+ critical_error_message_box(
+ translate('MediaPlugin.MediaItem', 'Unsupported Media File'),
+ translate('MediaPlugin.MediaItem', 'File {file_path} not supported using player {player_name}'
+ ).format(file_path=service_item.get_frame_path(), player_name=used_players[0]))
return False
media_data = MediaInfoWrapper.parse(service_item.get_frame_path())
# duration returns in milli seconds
diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py
index 69b96a7ac..0299683a5 100644
--- a/openlp/core/ui/pluginform.py
+++ b/openlp/core/ui/pluginform.py
@@ -41,7 +41,8 @@ class PluginForm(QtWidgets.QDialog, Ui_PluginViewDialog, RegistryProperties):
"""
Constructor
"""
- super(PluginForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(PluginForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.active_plugin = None
self.programatic_change = False
self.setupUi(self)
@@ -60,7 +61,6 @@ class PluginForm(QtWidgets.QDialog, Ui_PluginViewDialog, RegistryProperties):
self._clear_details()
self.programatic_change = True
plugin_list_width = 0
- # 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
@@ -137,7 +137,6 @@ class PluginForm(QtWidgets.QDialog, Ui_PluginViewDialog, RegistryProperties):
self.active_plugin.app_startup()
else:
self.active_plugin.toggle_status(PluginStatus.Inactive)
- # TODO: Tested at home
status_text = translate('OpenLP.PluginForm', '{name} (Inactive)')
if self.active_plugin.status == PluginStatus.Active:
status_text = translate('OpenLP.PluginForm', '{name} (Active)')
diff --git a/openlp/core/ui/printserviceform.py b/openlp/core/ui/printserviceform.py
index 7b3d80c8b..5a26a001d 100644
--- a/openlp/core/ui/printserviceform.py
+++ b/openlp/core/ui/printserviceform.py
@@ -125,8 +125,8 @@ class PrintServiceForm(QtWidgets.QDialog, Ui_PrintServiceDialog, RegistryPropert
"""
Constructor
"""
- super(PrintServiceForm, self).__init__(Registry().get('main_window'),
- QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(PrintServiceForm, self).__init__(Registry().get('main_window'), QtCore.Qt.WindowSystemMenuHint |
+ QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
self.printer = QtPrintSupport.QPrinter()
self.print_dialog = QtPrintSupport.QPrintDialog(self.printer, self)
self.document = QtGui.QTextDocument()
diff --git a/openlp/core/ui/projector/editform.py b/openlp/core/ui/projector/editform.py
index eec7a19de..6a6f0a362 100644
--- a/openlp/core/ui/projector/editform.py
+++ b/openlp/core/ui/projector/editform.py
@@ -142,7 +142,8 @@ class ProjectorEditForm(QtWidgets.QDialog, Ui_ProjectorEditForm):
editProjector = QtCore.pyqtSignal(object)
def __init__(self, parent=None, projectordb=None):
- super(ProjectorEditForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(ProjectorEditForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.projectordb = projectordb
self.setupUi(self)
self.button_box.accepted.connect(self.accept_me)
diff --git a/openlp/core/ui/projector/manager.py b/openlp/core/ui/projector/manager.py
index 747a63a85..e47b3c1f9 100644
--- a/openlp/core/ui/projector/manager.py
+++ b/openlp/core/ui/projector/manager.py
@@ -662,6 +662,20 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, UiProjecto
message = '%s%s: %s
' % (message,
translate('OpenLP.ProjectorManager', 'Current source input is'),
projector.link.source)
+ if projector.link.pjlink_class == '2':
+ # Information only available for PJLink Class 2 projectors
+ message += '{title}: {data}
'.format(title=translate('OpenLP.ProjectorManager',
+ 'Serial Number'),
+ data=projector.serial_no)
+ message += '{title}: {data}
'.format(title=translate('OpenLP.ProjectorManager',
+ 'Software Version'),
+ data=projector.sw_version)
+ message += '{title}: {data}
'.format(title=translate('OpenLP.ProjectorManager',
+ 'Lamp type'),
+ data=projector.model_lamp)
+ message += '{title}: {data}
'.format(title=translate('OpenLP.ProjectorManager',
+ 'Filter type'),
+ data=projector.model_filter)
count = 1
for item in projector.link.lamp:
message += '{title} {count} {status} '.format(title=translate('OpenLP.ProjectorManager',
diff --git a/openlp/core/ui/projector/sourceselectform.py b/openlp/core/ui/projector/sourceselectform.py
index c9fe4e1f1..1d17c07cd 100644
--- a/openlp/core/ui/projector/sourceselectform.py
+++ b/openlp/core/ui/projector/sourceselectform.py
@@ -233,7 +233,8 @@ class SourceSelectTabs(QtWidgets.QDialog):
:param projectordb: ProjectorDB session to use
"""
log.debug('Initializing SourceSelectTabs()')
- super(SourceSelectTabs, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(SourceSelectTabs, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setMinimumWidth(350)
self.projectordb = projectordb
self.edit = edit
@@ -388,7 +389,8 @@ class SourceSelectSingle(QtWidgets.QDialog):
"""
log.debug('Initializing SourceSelectSingle()')
self.projectordb = projectordb
- super(SourceSelectSingle, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(SourceSelectSingle, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.edit = edit
if self.edit:
title = translate('OpenLP.SourceSelectForm', 'Edit Projector Source Text')
diff --git a/openlp/core/ui/serviceitemeditform.py b/openlp/core/ui/serviceitemeditform.py
index dead6160a..f23956e70 100644
--- a/openlp/core/ui/serviceitemeditform.py
+++ b/openlp/core/ui/serviceitemeditform.py
@@ -37,8 +37,8 @@ class ServiceItemEditForm(QtWidgets.QDialog, Ui_ServiceItemEditDialog, RegistryP
"""
Constructor
"""
- super(ServiceItemEditForm, self).__init__(Registry().get('main_window'),
- QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(ServiceItemEditForm, self).__init__(Registry().get('main_window'), QtCore.Qt.WindowSystemMenuHint |
+ QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
self.item_list = []
self.list_widget.currentRowChanged.connect(self.on_current_row_changed)
diff --git a/openlp/core/ui/servicenoteform.py b/openlp/core/ui/servicenoteform.py
index dd1f42674..fc4da438a 100644
--- a/openlp/core/ui/servicenoteform.py
+++ b/openlp/core/ui/servicenoteform.py
@@ -37,8 +37,8 @@ class ServiceNoteForm(QtWidgets.QDialog, RegistryProperties):
"""
Constructor
"""
- super(ServiceNoteForm, self).__init__(Registry().get('main_window'),
- QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(ServiceNoteForm, self).__init__(Registry().get('main_window'), QtCore.Qt.WindowSystemMenuHint |
+ QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
self.setupUi()
self.retranslateUi()
diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py
index 2985883d4..8663ad018 100644
--- a/openlp/core/ui/settingsform.py
+++ b/openlp/core/ui/settingsform.py
@@ -47,7 +47,8 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties):
"""
Registry().register('settings_form', self)
Registry().register_function('bootstrap_post_set_up', self.bootstrap_post_set_up)
- super(SettingsForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(SettingsForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.processes = []
self.setupUi(self)
self.setting_list_widget.currentRowChanged.connect(self.list_item_changed)
diff --git a/openlp/core/ui/shortcutlistform.py b/openlp/core/ui/shortcutlistform.py
index a42600193..fc9a77ac8 100644
--- a/openlp/core/ui/shortcutlistform.py
+++ b/openlp/core/ui/shortcutlistform.py
@@ -44,7 +44,8 @@ class ShortcutListForm(QtWidgets.QDialog, Ui_ShortcutListDialog, RegistryPropert
"""
Constructor
"""
- super(ShortcutListForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(ShortcutListForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
self.changed_actions = {}
self.action_list = ActionList.get_instance()
@@ -279,9 +280,7 @@ class ShortcutListForm(QtWidgets.QDialog, Ui_ShortcutListDialog, RegistryPropert
return
if QtWidgets.QMessageBox.question(self, translate('OpenLP.ShortcutListDialog', 'Restore Default Shortcuts'),
translate('OpenLP.ShortcutListDialog', 'Do you want to restore all '
- 'shortcuts to their defaults?'),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
- QtWidgets.QMessageBox.No)
+ 'shortcuts to their defaults?')
) == QtWidgets.QMessageBox.No:
return
self._adjust_button(self.primary_push_button, False, text='')
diff --git a/openlp/core/ui/starttimeform.py b/openlp/core/ui/starttimeform.py
index 1b453a9c2..ae82d4c9e 100644
--- a/openlp/core/ui/starttimeform.py
+++ b/openlp/core/ui/starttimeform.py
@@ -38,8 +38,8 @@ class StartTimeForm(QtWidgets.QDialog, Ui_StartTimeDialog, RegistryProperties):
"""
Constructor
"""
- super(StartTimeForm, self).__init__(Registry().get('main_window'),
- QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(StartTimeForm, self).__init__(Registry().get('main_window'), QtCore.Qt.WindowSystemMenuHint |
+ QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
def exec(self):
diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py
index 59576808b..969d676a8 100644
--- a/openlp/core/ui/thememanager.py
+++ b/openlp/core/ui/thememanager.py
@@ -257,10 +257,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
Renames an existing theme to a new name
:param field:
"""
- # TODO: Check for delayed format() conversions
if self._validate_theme_action(translate('OpenLP.ThemeManager', 'You must select a theme to rename.'),
translate('OpenLP.ThemeManager', 'Rename Confirmation'),
- translate('OpenLP.ThemeManager', 'Rename %s theme?'), False, False):
+ translate('OpenLP.ThemeManager', 'Rename {theme_name} theme?'), False, False):
item = self.theme_list_widget.currentItem()
old_theme_name = item.data(QtCore.Qt.UserRole)
self.file_rename_form.file_name_edit.setText(old_theme_name)
@@ -334,10 +333,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
Delete a theme triggered by the UI.
:param field:
"""
- # TODO: Verify delayed format() conversions
if self._validate_theme_action(translate('OpenLP.ThemeManager', 'You must select a theme to delete.'),
translate('OpenLP.ThemeManager', 'Delete Confirmation'),
- translate('OpenLP.ThemeManager', 'Delete %s theme?')):
+ translate('OpenLP.ThemeManager', 'Delete {theme_name} theme?')):
item = self.theme_list_widget.currentItem()
theme = item.text()
row = self.theme_list_widget.row(item)
@@ -539,9 +537,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
translate('OpenLP.ThemeManager',
'Theme {name} already exists. '
'Do you want to replace it?').format(name=theme_name),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
- QtWidgets.QMessageBox.No),
- QtWidgets.QMessageBox.No)
+ defaultButton=QtWidgets.QMessageBox.No)
return ret == QtWidgets.QMessageBox.Yes
def unzip_theme(self, file_name, directory):
@@ -785,9 +781,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
# confirm deletion
if confirm:
answer = QtWidgets.QMessageBox.question(
- self, confirm_title, confirm_text % theme,
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
- QtWidgets.QMessageBox.No)
+ self, confirm_title, confirm_text.format(theme_name=theme),
+ defaultButton=QtWidgets.QMessageBox.No)
if answer == QtWidgets.QMessageBox.No:
return False
# should be the same unless default
diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py
index f944fcd43..878540dbf 100644
--- a/openlp/plugins/alerts/alertsplugin.py
+++ b/openlp/plugins/alerts/alertsplugin.py
@@ -90,21 +90,20 @@ JAVASCRIPT = """
}
}
"""
-# TODO: Verify format() with variable templates
CSS = """
- #alert {
+ #alert {{
position: absolute;
left: 0px;
top: 0px;
z-index: 10;
- width: 100%%;
- vertical-align: %s;
- font-family: %s;
- font-size: %spt;
- color: %s;
- background-color: %s;
+ width: 100%;
+ vertical-align: {vertical_align};
+ font-family: {font_family};
+ font-size: {font_size:d}pt;
+ color: {color};
+ background-color: {background_color};
word-wrap: break-word;
- }
+ }}
"""
HTML = """
@@ -232,8 +231,11 @@ class AlertsPlugin(Plugin):
Add CSS to the main display.
"""
align = VerticalType.Names[self.settings_tab.location]
- return CSS % (align, self.settings_tab.font_face, self.settings_tab.font_size, self.settings_tab.font_color,
- self.settings_tab.background_color)
+ return CSS.format(vertical_align=align,
+ font_family=self.settings_tab.font_face,
+ font_size=self.settings_tab.font_size,
+ color=self.settings_tab.font_color,
+ background_color=self.settings_tab.background_color)
@staticmethod
def get_display_html():
diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py
index 88f44210e..a9cb6cac3 100644
--- a/openlp/plugins/alerts/forms/alertform.py
+++ b/openlp/plugins/alerts/forms/alertform.py
@@ -36,8 +36,8 @@ class AlertForm(QtWidgets.QDialog, Ui_AlertDialog):
"""
Initialise the alert form
"""
- super(AlertForm, self).__init__(Registry().get('main_window'),
- QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(AlertForm, self).__init__(Registry().get('main_window'), QtCore.Qt.WindowSystemMenuHint |
+ QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
self.manager = plugin.manager
self.plugin = plugin
self.item_id = None
@@ -180,9 +180,7 @@ class AlertForm(QtWidgets.QDialog, Ui_AlertDialog):
translate('AlertsPlugin.AlertForm', 'No Parameter Found'),
translate('AlertsPlugin.AlertForm',
'You have not entered a parameter to be replaced.\n'
- 'Do you want to continue anyway?'),
- QtWidgets.QMessageBox.StandardButtons(
- QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes)
+ 'Do you want to continue anyway?')
) == QtWidgets.QMessageBox.No:
self.parameter_edit.setFocus()
return False
@@ -193,9 +191,7 @@ class AlertForm(QtWidgets.QDialog, Ui_AlertDialog):
translate('AlertsPlugin.AlertForm', 'No Placeholder Found'),
translate('AlertsPlugin.AlertForm',
'The alert text does not contain \'<>\'.\n'
- 'Do you want to continue anyway?'),
- QtWidgets.QMessageBox.StandardButtons(
- QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes)
+ 'Do you want to continue anyway?')
) == QtWidgets.QMessageBox.No:
self.parameter_edit.setFocus()
return False
diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py
index 1bcf8ff5d..4bcdab563 100644
--- a/openlp/plugins/bibles/bibleplugin.py
+++ b/openlp/plugins/bibles/bibleplugin.py
@@ -40,7 +40,7 @@ __default_settings__ = {
'bibles/db password': '',
'bibles/db hostname': '',
'bibles/db database': '',
- 'bibles/last search type': BibleSearch.Combined,
+ 'bibles/last used search type': BibleSearch.Combined,
'bibles/reset to combined quick search': True,
'bibles/verse layout style': LayoutStyle.VersePerSlide,
'bibles/book name language': LanguageSelection.Bible,
diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py
index 0a0de0b24..a6a2a4299 100644
--- a/openlp/plugins/bibles/forms/bibleimportform.py
+++ b/openlp/plugins/bibles/forms/bibleimportform.py
@@ -421,8 +421,8 @@ class BibleImportForm(OpenLPWizard):
Allow for localisation of the bible import wizard.
"""
self.setWindowTitle(translate('BiblesPlugin.ImportWizardForm', 'Bible Import Wizard'))
- self.title_label.setText(WizardStrings.HeaderStyle % translate('OpenLP.Ui',
- 'Welcome to the Bible Import Wizard'))
+ self.title_label.setText(WizardStrings.HeaderStyle.format(text=translate('OpenLP.Ui',
+ 'Welcome to the Bible Import Wizard')))
self.information_label.setText(
translate('BiblesPlugin.ImportWizardForm',
'This wizard will help you to import Bibles from a variety of '
diff --git a/openlp/plugins/bibles/forms/booknameform.py b/openlp/plugins/bibles/forms/booknameform.py
index 0a2411131..588ba96d4 100644
--- a/openlp/plugins/bibles/forms/booknameform.py
+++ b/openlp/plugins/bibles/forms/booknameform.py
@@ -49,7 +49,8 @@ class BookNameForm(QDialog, Ui_BookNameDialog):
"""
Constructor
"""
- super(BookNameForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(BookNameForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
self.custom_signals()
self.book_names = BibleStrings().BookNames
diff --git a/openlp/plugins/bibles/forms/editbibleform.py b/openlp/plugins/bibles/forms/editbibleform.py
index c0570e772..543531c2d 100644
--- a/openlp/plugins/bibles/forms/editbibleform.py
+++ b/openlp/plugins/bibles/forms/editbibleform.py
@@ -45,7 +45,8 @@ class EditBibleForm(QtWidgets.QDialog, Ui_EditBibleDialog, RegistryProperties):
"""
Constructor
"""
- super(EditBibleForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(EditBibleForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.media_item = media_item
self.book_names = BibleStrings().BookNames
self.setupUi(self)
diff --git a/openlp/plugins/bibles/forms/languageform.py b/openlp/plugins/bibles/forms/languageform.py
index 46571e262..6494950c8 100644
--- a/openlp/plugins/bibles/forms/languageform.py
+++ b/openlp/plugins/bibles/forms/languageform.py
@@ -47,7 +47,8 @@ class LanguageForm(QDialog, Ui_LanguageDialog):
"""
Constructor
"""
- super(LanguageForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(LanguageForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
def exec(self, bible_name):
diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py
index e4025411c..9d90a94e2 100644
--- a/openlp/plugins/bibles/lib/__init__.py
+++ b/openlp/plugins/bibles/lib/__init__.py
@@ -221,18 +221,16 @@ def update_reference_separators():
REFERENCE_SEPARATORS['sep_{role}'.format(role=role)] = '\s*(?:{source})\s*'.format(source=source_string)
REFERENCE_SEPARATORS['sep_{role}_default'.format(role=role)] = default_separators[index]
# verse range match: (:)?(-((:)?|end)?)?
- # TODO: Check before converting this string
- range_regex = '(?:(?P[0-9]+)%(sep_v)s)?' \
- '(?P[0-9]+)(?P%(sep_r)s(?:(?:(?P' \
- '[0-9]+)%(sep_v)s)?(?P[0-9]+)|%(sep_e)s)?)?' % REFERENCE_SEPARATORS
- # TODO: Test before converting re.compile strings
- REFERENCE_MATCHES['range'] = re.compile('^\s*%s\s*$' % range_regex, re.UNICODE)
+ range_regex = '(?:(?P[0-9]+){sep_v})?' \
+ '(?P[0-9]+)(?P{sep_r}(?:(?:(?P' \
+ '[0-9]+){sep_v})?(?P[0-9]+)|{sep_e})?)?'.format_map(REFERENCE_SEPARATORS)
+ REFERENCE_MATCHES['range'] = re.compile(r'^\s*{range}\s*$'.format(range=range_regex), re.UNICODE)
REFERENCE_MATCHES['range_separator'] = re.compile(REFERENCE_SEPARATORS['sep_l'], re.UNICODE)
# full reference match: ((,(?!$)|(?=$)))+
REFERENCE_MATCHES['full'] = \
- re.compile('^\s*(?!\s)(?P[\d]*[^\d\.]+)\.*(?(?:%(range_regex)s(?:%(sep_l)s(?!\s*$)|(?=\s*$)))+)\s*$'
- % dict(list(REFERENCE_SEPARATORS.items()) + [('range_regex', range_regex)]), re.UNICODE)
+ re.compile(r'^\s*(?!\s)(?P[\d]*[.]?[^\d\.]+)\.*(?(?:{range_regex}(?:{sep_l}(?!\s*$)|(?=\s*$)))+)\s*$'.format(
+ range_regex=range_regex, sep_l=REFERENCE_SEPARATORS['sep_l']), re.UNICODE)
def get_reference_separator(separator_type):
@@ -326,7 +324,7 @@ def parse_reference(reference, bible, language_selection, book_ref_id=False):
``^\s*(?!\s)(?P[\d]*[^\d]+)(?(?:%(range_regex)s(?:%(sep_l)s(?!\s*$)|(?=\s*$)))+)\s*$``
The second group contains all ``ranges``. This can be multiple declarations of range_regex separated by a list
diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py
index 9afdd2efc..65460c92e 100644
--- a/openlp/plugins/bibles/lib/db.py
+++ b/openlp/plugins/bibles/lib/db.py
@@ -306,9 +306,8 @@ class BibleDB(Manager):
book_escaped = book
for character in RESERVED_CHARACTERS:
book_escaped = book_escaped.replace(character, '\\' + character)
- # TODO: Verify regex patters before using format()
- regex_book = re.compile('\s*%s\s*' % '\s*'.join(
- book_escaped.split()), re.UNICODE | re.IGNORECASE)
+ regex_book = re.compile('\\s*{book}\\s*'.format(book='\\s*'.join(book_escaped.split())),
+ re.UNICODE | re.IGNORECASE)
if language_selection == LanguageSelection.Bible:
db_book = self.get_book(book)
if db_book:
diff --git a/openlp/plugins/bibles/lib/importers/http.py b/openlp/plugins/bibles/lib/importers/http.py
index 76daa8e25..4f032784d 100644
--- a/openlp/plugins/bibles/lib/importers/http.py
+++ b/openlp/plugins/bibles/lib/importers/http.py
@@ -90,6 +90,8 @@ class BGExtract(RegistryProperties):
"""
Extract verses from BibleGateway
"""
+ NAME = 'BibleGateway'
+
def __init__(self, proxy_url=None):
log.debug('BGExtract.init("{url}")'.format(url=proxy_url))
self.proxy_url = proxy_url
@@ -357,6 +359,8 @@ class BSExtract(RegistryProperties):
"""
Extract verses from Bibleserver.com
"""
+ NAME = 'BibleServer'
+
def __init__(self, proxy_url=None):
log.debug('BSExtract.init("{url}")'.format(url=proxy_url))
self.proxy_url = proxy_url
@@ -458,6 +462,8 @@ class CWExtract(RegistryProperties):
"""
Extract verses from CrossWalk/BibleStudyTools
"""
+ NAME = 'Crosswalk'
+
def __init__(self, proxy_url=None):
log.debug('CWExtract.init("{url}")'.format(url=proxy_url))
self.proxy_url = proxy_url
diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py
index f0ef34dd6..1c210c9ed 100755
--- a/openlp/plugins/bibles/lib/mediaitem.py
+++ b/openlp/plugins/bibles/lib/mediaitem.py
@@ -414,7 +414,9 @@ class BibleMediaItem(MediaManagerItem):
if self.bible:
book_data = self.get_common_books(self.bible, self.second_bible)
language_selection = self.plugin.manager.get_language_selection(self.bible.name)
- books = [book.get_name(language_selection) for book in book_data]
+ # Get book names + add a space to the end. Thus Psalm23 becomes Psalm 23
+ # when auto complete is used and user does not need to add the space manually.
+ books = [book.get_name(language_selection) + ' ' for book in book_data]
books.sort(key=get_locale_key)
set_case_insensitive_completer(books, self.search_edit)
diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py
index a081f8623..99eda1d52 100644
--- a/openlp/plugins/custom/customplugin.py
+++ b/openlp/plugins/custom/customplugin.py
@@ -42,7 +42,7 @@ __default_settings__ = {
'custom/db password': '',
'custom/db hostname': '',
'custom/db database': '',
- 'custom/last search type': CustomSearch.Titles,
+ 'custom/last used search type': CustomSearch.Titles,
'custom/display footer': True,
'custom/add custom from service': True
}
diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py
index 993acc688..1bd2187f2 100644
--- a/openlp/plugins/custom/forms/editcustomform.py
+++ b/openlp/plugins/custom/forms/editcustomform.py
@@ -44,7 +44,8 @@ class EditCustomForm(QtWidgets.QDialog, Ui_CustomEditDialog):
"""
Constructor
"""
- super(EditCustomForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(EditCustomForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.manager = manager
self.media_item = media_item
self.setupUi(self)
diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py
index b3c77e859..77f086dbb 100644
--- a/openlp/plugins/custom/forms/editcustomslideform.py
+++ b/openlp/plugins/custom/forms/editcustomslideform.py
@@ -39,7 +39,8 @@ class EditCustomSlideForm(QtWidgets.QDialog, Ui_CustomSlideEditDialog):
"""
Constructor
"""
- super(EditCustomSlideForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(EditCustomSlideForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
# Connecting signals and slots
self.insert_button.clicked.connect(self.on_insert_button_clicked)
diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py
index c9a8aa046..c90d14e10 100644
--- a/openlp/plugins/custom/lib/mediaitem.py
+++ b/openlp/plugins/custom/lib/mediaitem.py
@@ -190,9 +190,7 @@ class CustomMediaItem(MediaManagerItem):
translate('CustomPlugin.MediaItem',
'Are you sure you want to delete the "{items:d}" '
'selected custom slide(s)?').format(items=len(items)),
- QtWidgets.QMessageBox.StandardButtons(
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
- QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.No:
+ defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.No:
return
row_list = [item.row() for item in self.list_view.selectedIndexes()]
row_list.sort(reverse=True)
diff --git a/openlp/plugins/images/forms/addgroupform.py b/openlp/plugins/images/forms/addgroupform.py
index 3ea91c29e..953d02339 100644
--- a/openlp/plugins/images/forms/addgroupform.py
+++ b/openlp/plugins/images/forms/addgroupform.py
@@ -35,7 +35,8 @@ class AddGroupForm(QtWidgets.QDialog, Ui_AddGroupDialog):
"""
Constructor
"""
- super(AddGroupForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(AddGroupForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
def exec(self, clear=True, show_top_level_group=False, selected_group=None):
diff --git a/openlp/plugins/images/forms/choosegroupform.py b/openlp/plugins/images/forms/choosegroupform.py
index 88f4e72de..5867481b9 100644
--- a/openlp/plugins/images/forms/choosegroupform.py
+++ b/openlp/plugins/images/forms/choosegroupform.py
@@ -33,7 +33,8 @@ class ChooseGroupForm(QtWidgets.QDialog, Ui_ChooseGroupDialog):
"""
Constructor
"""
- super(ChooseGroupForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(ChooseGroupForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
def exec(self, selected_group=None):
diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py
index e3f39143b..97a9dd956 100644
--- a/openlp/plugins/images/lib/mediaitem.py
+++ b/openlp/plugins/images/lib/mediaitem.py
@@ -246,9 +246,7 @@ class ImageMediaItem(MediaManagerItem):
translate('ImagePlugin.MediaItem', 'Remove group'),
translate('ImagePlugin.MediaItem',
'Are you sure you want to remove "{name}" and everything in it?'
- ).format(name=item_data.group_name),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
- QtWidgets.QMessageBox.No)
+ ).format(name=item_data.group_name)
) == QtWidgets.QMessageBox.Yes:
self.recursively_delete_group(item_data)
self.manager.delete_object(ImageGroups, row_item.data(0, QtCore.Qt.UserRole).id)
@@ -597,8 +595,7 @@ class ImageMediaItem(MediaManagerItem):
self, translate('ImagePlugin.MediaItem', 'Missing Image(s)'),
translate('ImagePlugin.MediaItem', 'The following image(s) no longer exist: {names}\n'
'Do you want to add the other images anyway?'
- ).format(names='\n'.join(missing_items_file_names)),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes)) == \
+ ).format(names='\n'.join(missing_items_file_names))) == \
QtWidgets.QMessageBox.No:
return False
# Continue with the existing images.
diff --git a/openlp/plugins/media/forms/mediaclipselectorform.py b/openlp/plugins/media/forms/mediaclipselectorform.py
index c02e79232..d6e6fd352 100644
--- a/openlp/plugins/media/forms/mediaclipselectorform.py
+++ b/openlp/plugins/media/forms/mediaclipselectorform.py
@@ -52,7 +52,8 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro
"""
Constructor
"""
- super(MediaClipSelectorForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(MediaClipSelectorForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint |
+ QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
self.vlc_instance = None
self.vlc_media_player = None
self.vlc_media = None
diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py
index d36db36f0..d59fd83a4 100644
--- a/openlp/plugins/presentations/lib/pdfcontroller.py
+++ b/openlp/plugins/presentations/lib/pdfcontroller.py
@@ -253,15 +253,14 @@ class PdfDocument(PresentationDocument):
try:
if not os.path.isdir(self.get_temp_folder()):
os.makedirs(self.get_temp_folder())
+ # The %03d in the file name is handled by each binary
if self.controller.mudrawbin:
log.debug('loading presentation using mudraw')
- # TODO: Find out where the string conversion actually happens
runlog = check_output([self.controller.mudrawbin, '-w', str(size.width()), '-h', str(size.height()),
'-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path],
startupinfo=self.startupinfo)
elif self.controller.mutoolbin:
log.debug('loading presentation using mutool')
- # TODO: Find out where the string convertsion actually happens
runlog = check_output([self.controller.mutoolbin, 'draw', '-w', str(size.width()), '-h',
str(size.height()),
'-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path],
@@ -269,7 +268,6 @@ class PdfDocument(PresentationDocument):
elif self.controller.gsbin:
log.debug('loading presentation using gs')
resolution = self.gs_get_resolution(size)
- # TODO: Find out where the string conversion actually happens
runlog = check_output([self.controller.gsbin, '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m',
'-r' + str(resolution), '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4',
'-sOutputFile=' + os.path.join(self.get_temp_folder(), 'mainslide%03d.png'),
diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py
index 0ee165deb..09ab940e7 100644
--- a/openlp/plugins/presentations/lib/powerpointcontroller.py
+++ b/openlp/plugins/presentations/lib/powerpointcontroller.py
@@ -81,7 +81,7 @@ class PowerpointController(PresentationController):
if app_version >= 12:
self.also_supports = ['odp']
except (OSError, ValueError):
- log.warning('Detection of powerpoint version using registry failed.')
+ log.exception('Detection of powerpoint version using registry failed.')
return True
except OSError:
pass
@@ -109,9 +109,8 @@ class PowerpointController(PresentationController):
if self.process.Presentations.Count > 0:
return
self.process.Quit()
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Exception caught while killing powerpoint process')
- log.exception(e)
trace_error_handler(log)
self.process = None
@@ -154,9 +153,8 @@ class PowerpointDocument(PresentationDocument):
if len(ScreenList().screen_list) > 1:
Registry().get('main_window').activateWindow()
return True
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Exception caught while loading Powerpoint presentation')
- log.exception(e)
trace_error_handler(log)
return False
@@ -192,9 +190,8 @@ class PowerpointDocument(PresentationDocument):
if self.presentation:
try:
self.presentation.Close()
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while closing powerpoint presentation')
- log.exception(e)
trace_error_handler(log)
self.presentation = None
self.controller.remove_doc(self)
@@ -210,9 +207,8 @@ class PowerpointDocument(PresentationDocument):
try:
if self.controller.process.Presentations.Count == 0:
return False
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in is_loaded')
- log.exception(e)
trace_error_handler(log)
return False
return True
@@ -229,9 +225,8 @@ class PowerpointDocument(PresentationDocument):
return False
if self.presentation.SlideShowWindow.View is None:
return False
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in is_active')
- log.exception(e)
trace_error_handler(log)
return False
return True
@@ -249,9 +244,8 @@ class PowerpointDocument(PresentationDocument):
self.presentation.SlideShowWindow.View.GotoSlide(self.index_map[self.blank_slide], False)
if self.blank_click:
self.presentation.SlideShowWindow.View.GotoClick(self.blank_click)
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in unblank_screen')
- log.exception(e)
trace_error_handler(log)
self.show_error_msg()
# Stop powerpoint from flashing in the taskbar
@@ -273,9 +267,8 @@ class PowerpointDocument(PresentationDocument):
self.blank_click = self.presentation.SlideShowWindow.View.GetClickIndex()
# ppSlideShowBlackScreen = 3
self.presentation.SlideShowWindow.View.State = 3
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in blank_screen')
- log.exception(e)
trace_error_handler(log)
self.show_error_msg()
@@ -288,9 +281,8 @@ class PowerpointDocument(PresentationDocument):
try:
# ppSlideShowBlackScreen = 3
return self.presentation.SlideShowWindow.View.State == 3
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in is_blank')
- log.exception(e)
trace_error_handler(log)
self.show_error_msg()
else:
@@ -303,9 +295,8 @@ class PowerpointDocument(PresentationDocument):
log.debug('stop_presentation')
try:
self.presentation.SlideShowWindow.View.Exit()
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in stop_presentation')
- log.exception(e)
trace_error_handler(log)
self.show_error_msg()
@@ -328,9 +319,8 @@ class PowerpointDocument(PresentationDocument):
ppt_window = None
try:
ppt_window = self.presentation.SlideShowSettings.Run()
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in start_presentation')
- log.exception(e)
trace_error_handler(log)
self.show_error_msg()
if ppt_window and not Settings().value('presentations/powerpoint control window'):
@@ -339,9 +329,8 @@ class PowerpointDocument(PresentationDocument):
ppt_window.Height = size.height() * 72 / dpi
ppt_window.Left = size.x() * 72 / dpi
ppt_window.Width = size.width() * 72 / dpi
- except AttributeError as e:
+ except AttributeError:
log.exception('AttributeError while in start_presentation')
- log.exception(e)
# Find the presentation window and save the handle for later
self.presentation_hwnd = None
if ppt_window:
@@ -399,9 +388,8 @@ class PowerpointDocument(PresentationDocument):
ret = next((key for key, slidenum in self.index_map.items() if slidenum == ret), None)
else:
ret = self.presentation.SlideShowWindow.View.CurrentShowPosition
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in get_slide_number')
- log.exception(e)
trace_error_handler(log)
self.show_error_msg()
return ret
@@ -431,9 +419,8 @@ class PowerpointDocument(PresentationDocument):
self.next_step()
else:
self.presentation.SlideShowWindow.View.GotoSlide(self.index_map[slide_no])
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in goto_slide')
- log.exception(e)
trace_error_handler(log)
self.show_error_msg()
@@ -445,9 +432,8 @@ class PowerpointDocument(PresentationDocument):
try:
self.presentation.SlideShowWindow.Activate()
self.presentation.SlideShowWindow.View.Next()
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in next_step')
- log.exception(e)
trace_error_handler(log)
self.show_error_msg()
return
@@ -468,9 +454,8 @@ class PowerpointDocument(PresentationDocument):
log.debug('previous_step')
try:
self.presentation.SlideShowWindow.View.Previous()
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Caught exception while in previous_step')
- log.exception(e)
trace_error_handler(log)
self.show_error_msg()
@@ -503,8 +488,8 @@ class PowerpointDocument(PresentationDocument):
slide = self.presentation.Slides(self.index_map[num + 1])
try:
text = slide.Shapes.Title.TextFrame.TextRange.Text
- except Exception as e:
- log.exception(e)
+ except Exception:
+ log.exception('Exception raised when getting title text')
text = ''
titles.append(text.replace('\n', ' ').replace('\x0b', ' ') + '\n')
note = _get_text_from_shapes(slide.NotesPage.Shapes)
@@ -519,9 +504,8 @@ class PowerpointDocument(PresentationDocument):
"""
try:
self.presentation.SlideShowWindow.View.Exit()
- except (AttributeError, pywintypes.com_error) as e:
+ except (AttributeError, pywintypes.com_error):
log.exception('Failed to exit Powerpoint presentation after error')
- log.exception(e)
critical_error_message_box(UiStrings().Error, translate('PresentationPlugin.PowerpointDocument',
'An error occurred in the PowerPoint integration '
'and the presentation will be stopped. '
@@ -540,7 +524,6 @@ def _get_text_from_shapes(shapes):
if shape.PlaceholderFormat.Type == 2: # 2 from is enum PpPlaceholderType.ppPlaceholderBody
if shape.HasTextFrame and shape.TextFrame.HasText:
text += shape.TextFrame.TextRange.Text + '\n'
- except pywintypes.com_error as e:
- log.warning('Failed to extract text from powerpoint slide')
- log.warning(e)
+ except pywintypes.com_error:
+ log.exception('Failed to extract text from powerpoint slide')
return text
diff --git a/openlp/plugins/songs/forms/authorsform.py b/openlp/plugins/songs/forms/authorsform.py
index bec967561..84e0343e9 100644
--- a/openlp/plugins/songs/forms/authorsform.py
+++ b/openlp/plugins/songs/forms/authorsform.py
@@ -35,7 +35,8 @@ class AuthorsForm(QtWidgets.QDialog, Ui_AuthorsDialog):
"""
Set up the screen and common data
"""
- super(AuthorsForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(AuthorsForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
self.auto_display_name = False
self.first_name_edit.textEdited.connect(self.on_first_name_edited)
diff --git a/openlp/plugins/songs/forms/duplicatesongremovalform.py b/openlp/plugins/songs/forms/duplicatesongremovalform.py
index dbebf19bc..b89748402 100644
--- a/openlp/plugins/songs/forms/duplicatesongremovalform.py
+++ b/openlp/plugins/songs/forms/duplicatesongremovalform.py
@@ -82,6 +82,9 @@ class DuplicateSongRemovalForm(OpenLPWizard, RegistryProperties):
self.finish_button.clicked.connect(self.on_wizard_exit)
self.cancel_button.clicked.connect(self.on_wizard_exit)
+ def closeEvent(self, event):
+ self.on_wizard_exit()
+
def add_custom_pages(self):
"""
Add song wizard specific pages.
@@ -130,9 +133,9 @@ class DuplicateSongRemovalForm(OpenLPWizard, RegistryProperties):
Song wizard localisation.
"""
self.setWindowTitle(translate('Wizard', 'Wizard'))
- # TODO: Check format() using template strings
- self.title_label.setText(WizardStrings.HeaderStyle % translate('OpenLP.Ui',
- 'Welcome to the Duplicate Song Removal Wizard'))
+ self.title_label.setText(
+ WizardStrings.HeaderStyle.format(text=translate('OpenLP.Ui',
+ 'Welcome to the Duplicate Song Removal Wizard')))
self.information_label.setText(
translate("Wizard",
'This wizard will help you to remove duplicate songs from the song database. You will have a '
@@ -216,8 +219,7 @@ class DuplicateSongRemovalForm(OpenLPWizard, RegistryProperties):
self.button(QtWidgets.QWizard.CancelButton).hide()
QtWidgets.QMessageBox.information(
self, translate('Wizard', 'Information'),
- translate('Wizard', 'No duplicate songs have been found in the database.'),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
+ translate('Wizard', 'No duplicate songs have been found in the database.'))
def add_duplicates_to_song_list(self, search_song, duplicate_song):
"""
diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py
index d7f614245..dd965f733 100644
--- a/openlp/plugins/songs/forms/editsongform.py
+++ b/openlp/plugins/songs/forms/editsongform.py
@@ -56,7 +56,8 @@ class EditSongForm(QtWidgets.QDialog, Ui_EditSongDialog, RegistryProperties):
"""
Constructor
"""
- super(EditSongForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(EditSongForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.media_item = media_item
self.song = None
# can this be automated?
@@ -203,8 +204,7 @@ class EditSongForm(QtWidgets.QDialog, Ui_EditSongDialog, RegistryProperties):
'There is no verse corresponding to "{invalid}". Valid entries are {valid}.\n'
'Please enter the verses separated by spaces.').format(invalid=invalid_verses[0],
valid=valid)
- critical_error_message_box(title=translate('SongsPlugin.EditSongForm', 'Invalid Verse Order'),
- message=msg)
+ critical_error_message_box(title=translate('SongsPlugin.EditSongForm', 'Invalid Verse Order'), message=msg)
return len(invalid_verses) == 0
def _validate_song(self):
@@ -579,8 +579,7 @@ class EditSongForm(QtWidgets.QDialog, Ui_EditSongDialog, RegistryProperties):
self,
translate('SongsPlugin.EditSongForm', 'Add Author'),
translate('SongsPlugin.EditSongForm', 'This author does not exist, do you want to add them?'),
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
- QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
+ defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
if text.find(' ') == -1:
author = Author.populate(first_name='', last_name='', display_name=text)
else:
@@ -658,8 +657,7 @@ class EditSongForm(QtWidgets.QDialog, Ui_EditSongDialog, RegistryProperties):
if QtWidgets.QMessageBox.question(
self, translate('SongsPlugin.EditSongForm', 'Add Topic'),
translate('SongsPlugin.EditSongForm', 'This topic does not exist, do you want to add it?'),
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
- QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
+ defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
topic = Topic.populate(name=text)
self.manager.save_object(topic)
topic_item = QtWidgets.QListWidgetItem(str(topic.name))
@@ -705,8 +703,7 @@ class EditSongForm(QtWidgets.QDialog, Ui_EditSongDialog, RegistryProperties):
if QtWidgets.QMessageBox.question(
self, translate('SongsPlugin.EditSongForm', 'Add Songbook'),
translate('SongsPlugin.EditSongForm', 'This Songbook does not exist, do you want to add it?'),
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
- QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
+ defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
songbook = Book.populate(name=text)
self.manager.save_object(songbook)
self.add_songbook_entry_to_list(songbook.id, songbook.name, self.songbook_entry_edit.text())
diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py
index f033f47d9..1e36df1e4 100644
--- a/openlp/plugins/songs/forms/editverseform.py
+++ b/openlp/plugins/songs/forms/editverseform.py
@@ -43,7 +43,8 @@ class EditVerseForm(QtWidgets.QDialog, Ui_EditVerseDialog):
"""
Constructor
"""
- super(EditVerseForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(EditVerseForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
self.has_single_verse = False
self.insert_button.clicked.connect(self.on_insert_button_clicked)
diff --git a/openlp/plugins/songs/forms/mediafilesform.py b/openlp/plugins/songs/forms/mediafilesform.py
index 0839b273e..10e9334f7 100644
--- a/openlp/plugins/songs/forms/mediafilesform.py
+++ b/openlp/plugins/songs/forms/mediafilesform.py
@@ -37,7 +37,8 @@ class MediaFilesForm(QtWidgets.QDialog, Ui_MediaFilesDialog):
log.info('{name} MediaFilesForm loaded'.format(name=__name__))
def __init__(self, parent):
- super(MediaFilesForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(MediaFilesForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
def populate_files(self, files):
diff --git a/openlp/plugins/songs/forms/songbookform.py b/openlp/plugins/songs/forms/songbookform.py
index 132611d65..fc1b87c09 100644
--- a/openlp/plugins/songs/forms/songbookform.py
+++ b/openlp/plugins/songs/forms/songbookform.py
@@ -38,7 +38,8 @@ class SongBookForm(QtWidgets.QDialog, Ui_SongBookDialog):
"""
Constructor
"""
- super(SongBookForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(SongBookForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
def exec(self, clear=True):
diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py
index 1780e7c7c..03ac9ee22 100644
--- a/openlp/plugins/songs/forms/songexportform.py
+++ b/openlp/plugins/songs/forms/songexportform.py
@@ -121,7 +121,7 @@ class SongExportForm(OpenLPWizard):
self.selected_list_widget = QtWidgets.QListWidget(self.export_song_page)
self.selected_list_widget.setObjectName('selected_list_widget')
self.grid_layout.addWidget(self.selected_list_widget, 1, 0, 1, 1)
- # FIXME: self.horizontal_layout is already defined above?!?!?
+ # FIXME: self.horizontal_layout is already defined above?!?!? Replace with Path Eidt!
self.horizontal_layout = QtWidgets.QHBoxLayout()
self.horizontal_layout.setObjectName('horizontal_layout')
self.directory_label = QtWidgets.QLabel(self.export_song_page)
@@ -143,9 +143,8 @@ class SongExportForm(OpenLPWizard):
Song wizard localisation.
"""
self.setWindowTitle(translate('SongsPlugin.ExportWizardForm', 'Song Export Wizard'))
- # TODO: Verify format() with template variables
- self.title_label.setText(WizardStrings.HeaderStyle %
- translate('OpenLP.Ui', 'Welcome to the Song Export Wizard'))
+ self.title_label.setText(
+ WizardStrings.HeaderStyle.format(text=translate('OpenLP.Ui', 'Welcome to the Song Export Wizard')))
self.information_label.setText(
translate('SongsPlugin.ExportWizardForm', 'This wizard will help to export your songs to the open and free '
'OpenLyrics worship song format.'))
diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py
index 253702b56..3547521c9 100644
--- a/openlp/plugins/songs/forms/songimportform.py
+++ b/openlp/plugins/songs/forms/songimportform.py
@@ -132,9 +132,8 @@ class SongImportForm(OpenLPWizard, RegistryProperties):
Song wizard localisation.
"""
self.setWindowTitle(translate('SongsPlugin.ImportWizardForm', 'Song Import Wizard'))
- # TODO: Verify format() with template variables
- self.title_label.setText(WizardStrings.HeaderStyle % translate('OpenLP.Ui',
- 'Welcome to the Song Import Wizard'))
+ self.title_label.setText(
+ WizardStrings.HeaderStyle.format(text=translate('OpenLP.Ui', 'Welcome to the Song Import Wizard')))
self.information_label.setText(
translate('SongsPlugin.ImportWizardForm',
'This wizard will help you to import songs from a variety of formats. Click the next button '
@@ -272,12 +271,11 @@ class SongImportForm(OpenLPWizard, RegistryProperties):
select_mode, format_name, ext_filter = SongFormat.get(this_format, 'selectMode', 'name', 'filter')
file_path_edit = self.format_widgets[this_format]['file_path_edit']
if select_mode == SongFormatSelect.SingleFile:
- # TODO: Verify format() with template variables
- self.get_file_name(
- WizardStrings.OpenTypeFile % format_name, file_path_edit, 'last directory import', ext_filter)
+ self.get_file_name(WizardStrings.OpenTypeFile.format(file_type=format_name),
+ file_path_edit, 'last directory import', ext_filter)
elif select_mode == SongFormatSelect.SingleFolder:
- # TODO: Verify format() with template variables
- self.get_folder(WizardStrings.OpenTypeFolder % format_name, file_path_edit, 'last directory import')
+ self.get_folder(
+ WizardStrings.OpenTypeFolder.format(folder_name=format_name), file_path_edit, 'last directory import')
def on_add_button_clicked(self):
"""
@@ -286,8 +284,7 @@ class SongImportForm(OpenLPWizard, RegistryProperties):
this_format = self.current_format
select_mode, format_name, ext_filter, custom_title = \
SongFormat.get(this_format, 'selectMode', 'name', 'filter', 'getFilesTitle')
- # TODO: Verify format() with template variables
- title = custom_title if custom_title else WizardStrings.OpenTypeFile % format_name
+ title = custom_title if custom_title else WizardStrings.OpenTypeFile.format(file_type=format_name)
if select_mode == SongFormatSelect.MultipleFiles:
self.get_files(title, self.format_widgets[this_format]['file_list_widget'], ext_filter)
self.source_page.completeChanged.emit()
diff --git a/openlp/plugins/songs/forms/songmaintenancedialog.py b/openlp/plugins/songs/forms/songmaintenancedialog.py
index 2ed284298..be226f55e 100644
--- a/openlp/plugins/songs/forms/songmaintenancedialog.py
+++ b/openlp/plugins/songs/forms/songmaintenancedialog.py
@@ -39,7 +39,7 @@ class Ui_SongMaintenanceDialog(object):
song_maintenance_dialog.setObjectName('song_maintenance_dialog')
song_maintenance_dialog.setWindowIcon(build_icon(':/icon/openlp-logo.svg'))
song_maintenance_dialog.setWindowModality(QtCore.Qt.ApplicationModal)
- song_maintenance_dialog.resize(10, 350)
+ song_maintenance_dialog.resize(600, 600)
self.dialog_layout = QtWidgets.QGridLayout(song_maintenance_dialog)
self.dialog_layout.setObjectName('dialog_layout')
self.type_list_widget = QtWidgets.QListWidget(song_maintenance_dialog)
diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py
index a29c048e2..766231712 100644
--- a/openlp/plugins/songs/forms/songmaintenanceform.py
+++ b/openlp/plugins/songs/forms/songmaintenanceform.py
@@ -44,7 +44,8 @@ class SongMaintenanceForm(QtWidgets.QDialog, Ui_SongMaintenanceDialog, RegistryP
"""
Constructor
"""
- super(SongMaintenanceForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(SongMaintenanceForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
self.manager = manager
self.author_form = AuthorsForm(self)
diff --git a/openlp/plugins/songs/forms/songselectform.py b/openlp/plugins/songs/forms/songselectform.py
index 1169cb672..4863529a9 100644
--- a/openlp/plugins/songs/forms/songselectform.py
+++ b/openlp/plugins/songs/forms/songselectform.py
@@ -81,7 +81,8 @@ class SongSelectForm(QtWidgets.QDialog, Ui_SongSelectDialog):
"""
def __init__(self, parent=None, plugin=None, db_manager=None):
- QtWidgets.QDialog.__init__(self, parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ QtWidgets.QDialog.__init__(self, parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.plugin = plugin
self.db_manager = db_manager
self.setup_ui(self)
@@ -248,8 +249,7 @@ class SongSelectForm(QtWidgets.QDialog, Ui_SongSelectDialog):
translate('SongsPlugin.SongSelectForm', 'WARNING: Saving your username and password is INSECURE, your '
'password is stored in PLAIN TEXT. Click Yes to save your '
'password or No to cancel this.'),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
- QtWidgets.QMessageBox.No)
+ defaultButton=QtWidgets.QMessageBox.No)
if answer == QtWidgets.QMessageBox.No:
self.save_password_checkbox.setChecked(False)
@@ -397,8 +397,7 @@ class SongSelectForm(QtWidgets.QDialog, Ui_SongSelectDialog):
translate('SongsPlugin.SongSelectForm',
'Your song has been imported, would you '
'like to import more songs?'),
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
- QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
+ defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
self.on_back_button_clicked()
else:
self.application.process_events()
diff --git a/openlp/plugins/songs/forms/topicsform.py b/openlp/plugins/songs/forms/topicsform.py
index a811b277a..f0c7f0ab1 100644
--- a/openlp/plugins/songs/forms/topicsform.py
+++ b/openlp/plugins/songs/forms/topicsform.py
@@ -38,7 +38,8 @@ class TopicsForm(QtWidgets.QDialog, Ui_TopicsDialog):
"""
Constructor
"""
- super(TopicsForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(TopicsForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
def exec(self, clear=True):
diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py
index d6287b065..9e1f4f166 100644
--- a/openlp/plugins/songs/lib/importer.py
+++ b/openlp/plugins/songs/lib/importer.py
@@ -265,7 +265,7 @@ class SongFormat(object):
},
EasyWorshipService: {
'class': EasyWorshipSongImport,
- 'name': 'EasyWorship Service File',
+ 'name': 'EasyWorship Service',
'prefix': 'ew',
'selectMode': SongFormatSelect.SingleFile,
'filter': '{text} (*.ews)'.format(text=translate('SongsPlugin.ImportWizardForm',
diff --git a/openlp/plugins/songs/lib/importers/foilpresenter.py b/openlp/plugins/songs/lib/importers/foilpresenter.py
index 7a8146aa4..06f45c89c 100644
--- a/openlp/plugins/songs/lib/importers/foilpresenter.py
+++ b/openlp/plugins/songs/lib/importers/foilpresenter.py
@@ -121,8 +121,8 @@ class FoilPresenterImport(SongImport):
for file_path in self.import_source:
if self.stop_import_flag:
return
- # TODO: Verify format() with template strings
- self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
+ self.import_wizard.increment_progress_bar(
+ WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
try:
parsed_file = etree.parse(file_path, parser)
xml = etree.tostring(parsed_file).decode()
diff --git a/openlp/plugins/songs/lib/importers/openlp.py b/openlp/plugins/songs/lib/importers/openlp.py
index c0506bf6a..a42e7e37c 100644
--- a/openlp/plugins/songs/lib/importers/openlp.py
+++ b/openlp/plugins/songs/lib/importers/openlp.py
@@ -275,11 +275,9 @@ class OpenLPSongImport(SongImport):
self.manager.save_object(new_song)
if progress_dialog:
progress_dialog.setValue(progress_dialog.value() + 1)
- # TODO: Verify format() with template strings
- progress_dialog.setLabelText(WizardStrings.ImportingType % new_song.title)
+ progress_dialog.setLabelText(WizardStrings.ImportingType.format(source=new_song.title))
else:
- # TODO: Verify format() with template strings
- self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % new_song.title)
+ self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=new_song.title))
if self.stop_import_flag:
break
self.source_session.close()
diff --git a/openlp/plugins/songs/lib/importers/openlyrics.py b/openlp/plugins/songs/lib/importers/openlyrics.py
index fbdfd7b67..09cc1ef91 100644
--- a/openlp/plugins/songs/lib/importers/openlyrics.py
+++ b/openlp/plugins/songs/lib/importers/openlyrics.py
@@ -58,8 +58,8 @@ class OpenLyricsImport(SongImport):
for file_path in self.import_source:
if self.stop_import_flag:
return
- # TODO: Verify format() with template strings
- self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
+ self.import_wizard.increment_progress_bar(
+ WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
try:
# Pass a file object, because lxml does not cope with some
# special characters in the path (see lp:757673 and lp:744337).
diff --git a/openlp/plugins/songs/lib/importers/powerpraise.py b/openlp/plugins/songs/lib/importers/powerpraise.py
index 358f01e10..a652cf58c 100644
--- a/openlp/plugins/songs/lib/importers/powerpraise.py
+++ b/openlp/plugins/songs/lib/importers/powerpraise.py
@@ -41,8 +41,8 @@ class PowerPraiseImport(SongImport):
for file_path in self.import_source:
if self.stop_import_flag:
return
- # TODO: Verify format() with template strings
- self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
+ self.import_wizard.increment_progress_bar(
+ WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
root = objectify.parse(open(file_path, 'rb')).getroot()
self.process_song(root)
diff --git a/openlp/plugins/songs/lib/importers/presentationmanager.py b/openlp/plugins/songs/lib/importers/presentationmanager.py
index 7113842c4..4031431ba 100644
--- a/openlp/plugins/songs/lib/importers/presentationmanager.py
+++ b/openlp/plugins/songs/lib/importers/presentationmanager.py
@@ -44,8 +44,8 @@ class PresentationManagerImport(SongImport):
for file_path in self.import_source:
if self.stop_import_flag:
return
- # TODO: Verify format() with template strings
- self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
+ self.import_wizard.increment_progress_bar(
+ WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
try:
tree = etree.parse(file_path, parser=etree.XMLParser(recover=True))
except etree.XMLSyntaxError:
diff --git a/openlp/plugins/songs/lib/importers/propresenter.py b/openlp/plugins/songs/lib/importers/propresenter.py
index f1401c8a0..9a3fa372d 100644
--- a/openlp/plugins/songs/lib/importers/propresenter.py
+++ b/openlp/plugins/songs/lib/importers/propresenter.py
@@ -46,8 +46,8 @@ class ProPresenterImport(SongImport):
for file_path in self.import_source:
if self.stop_import_flag:
return
- # TODO: Verify format() with template strings
- self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
+ self.import_wizard.increment_progress_bar(
+ WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
root = objectify.parse(open(file_path, 'rb')).getroot()
self.process_song(root, file_path)
diff --git a/openlp/plugins/songs/lib/importers/songimport.py b/openlp/plugins/songs/lib/importers/songimport.py
index 7ea66a3da..070919c44 100644
--- a/openlp/plugins/songs/lib/importers/songimport.py
+++ b/openlp/plugins/songs/lib/importers/songimport.py
@@ -347,8 +347,7 @@ class SongImport(QtCore.QObject):
song = Song()
song.title = self.title
if self.import_wizard is not None:
- # TODO: Verify format() with template variables
- self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % song.title)
+ self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=song.title))
song.alternate_title = self.alternate_title
# Values will be set when cleaning the song.
song.search_title = ''
diff --git a/openlp/plugins/songs/lib/importers/songshowplus.py b/openlp/plugins/songs/lib/importers/songshowplus.py
index 4848349f0..b0841b672 100644
--- a/openlp/plugins/songs/lib/importers/songshowplus.py
+++ b/openlp/plugins/songs/lib/importers/songshowplus.py
@@ -100,8 +100,7 @@ class SongShowPlusImport(SongImport):
self.other_count = 0
self.other_list = {}
file_name = os.path.split(file)[1]
- # TODO: Verify format() with template variables
- self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % file_name, 0)
+ self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=file_name), 0)
song_data = open(file, 'rb')
while True:
block_key, = struct.unpack("I", song_data.read(4))
diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py
index 7c8bba200..c5f424a9a 100644
--- a/openlp/plugins/songs/lib/mediaitem.py
+++ b/openlp/plugins/songs/lib/mediaitem.py
@@ -231,9 +231,14 @@ class SongMediaItem(MediaManagerItem):
def search_entire(self, search_keywords):
search_string = '%{text}%'.format(text=clean_string(search_keywords))
- return self.plugin.manager.get_all_objects(
- Song, or_(Song.search_title.like(search_string), Song.search_lyrics.like(search_string),
- Song.comments.like(search_string)))
+ return self.plugin.manager.session.query(Song) \
+ .join(SongBookEntry, isouter=True) \
+ .join(Book, isouter=True) \
+ .filter(or_(Book.name.like(search_string), SongBookEntry.entry.like(search_string),
+ # hint: search_title contains alternate title
+ Song.search_title.like(search_string), Song.search_lyrics.like(search_string),
+ Song.comments.like(search_string))) \
+ .all()
def on_song_list_load(self):
"""
@@ -500,8 +505,7 @@ class SongMediaItem(MediaManagerItem):
translate('SongsPlugin.MediaItem',
'Are you sure you want to delete the "{items:d}" '
'selected song(s)?').format(items=len(items)),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
- QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.No:
+ defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.No:
return
self.application.set_busy_cursor()
self.main_window.display_progress_bar(len(items))
diff --git a/openlp/plugins/songs/lib/openlyricsxml.py b/openlp/plugins/songs/lib/openlyricsxml.py
index bc02043ac..807ea5593 100644
--- a/openlp/plugins/songs/lib/openlyricsxml.py
+++ b/openlp/plugins/songs/lib/openlyricsxml.py
@@ -70,8 +70,7 @@ from openlp.plugins.songs.lib.db import Author, AuthorType, Book, Song, Topic
log = logging.getLogger(__name__)
NAMESPACE = 'http://openlyrics.info/namespace/2009/song'
-# TODO: Verify format() with template variable
-NSMAP = '{' + NAMESPACE + '}' + '%s'
+NSMAP = '{{' + NAMESPACE + '}}{tag}'
class SongXML(object):
@@ -616,15 +615,13 @@ class OpenLyrics(object):
text = ''
use_endtag = True
# Skip elements - not yet supported.
- # TODO: Verify format() with template variables
- if element.tag == NSMAP % 'comment':
+ if element.tag == NSMAP.format(tag='comment'):
if element.tail:
# Append tail text at comment element.
text += element.tail
return text
# Convert chords to ChordPro format which OpenLP uses internally
- # TODO: Verify format() with template variables
- elif element.tag == NSMAP % 'chord':
+ elif element.tag == NSMAP.format(tag='chord'):
if Settings().value('songs/enable chords') and not Settings().value('songs/disable chords import'):
text += '[{chord}]'.format(chord=element.get('name'))
if element.tail:
@@ -632,15 +629,13 @@ class OpenLyrics(object):
text += element.tail
return text
# Convert line breaks
to \n.
- # TODO: Verify format() with template variables
- elif newlines and element.tag == NSMAP % 'br':
+ elif newlines and element.tag == NSMAP.format(tag='br'):
text += '\n'
if element.tail:
text += element.tail
return text
# Start formatting tag.
- # TODO: Verify format() with template variables
- if element.tag == NSMAP % 'tag':
+ if element.tag == NSMAP.format(tag='tag'):
text += '{{{name}}}'.format(name=element.get('name'))
# Some formattings may have only start tag.
# Handle this case if element has no children and contains no text.
@@ -654,8 +649,7 @@ class OpenLyrics(object):
# Use recursion since nested formatting tags are allowed.
text += self._process_lines_mixed_content(child, newlines)
# Append text from tail and add formatting end tag.
- # TODO: Verify format() with template variables
- if element.tag == NSMAP % 'tag' and use_endtag:
+ if element.tag == NSMAP.format(tag='tag') and use_endtag:
text += '{{/{name}}}'.format(name=element.get('name'))
# Append text from tail.
if element.tail:
@@ -682,8 +676,7 @@ class OpenLyrics(object):
# Loop over the "line" elements removing comments
for line in element:
# Skip comment lines.
- # TODO: Verify format() with template variables
- if line.tag == NSMAP % 'comment':
+ if line.tag == NSMAP.format(tag='comment'):
continue
if text:
text += '\n'
diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py
index 5682fb13d..2367e828c 100644
--- a/openlp/plugins/songs/songsplugin.py
+++ b/openlp/plugins/songs/songsplugin.py
@@ -58,7 +58,7 @@ __default_settings__ = {
'songs/db password': '',
'songs/db hostname': '',
'songs/db database': '',
- 'songs/last search type': SongSearch.Entire,
+ 'songs/last used search type': SongSearch.Entire,
'songs/last import type': SongFormat.OpenLyrics,
'songs/update service on edit': False,
'songs/add song from service': True,
diff --git a/openlp/plugins/songusage/forms/songusagedeleteform.py b/openlp/plugins/songusage/forms/songusagedeleteform.py
index 108ccb438..37664b06a 100644
--- a/openlp/plugins/songusage/forms/songusagedeleteform.py
+++ b/openlp/plugins/songusage/forms/songusagedeleteform.py
@@ -37,7 +37,7 @@ class SongUsageDeleteForm(QtWidgets.QDialog, Ui_SongUsageDeleteDialog, RegistryP
"""
self.manager = manager
super(SongUsageDeleteForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint |
- QtCore.Qt.WindowTitleHint)
+ QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
self.setupUi(self)
self.button_box.clicked.connect(self.on_button_box_clicked)
@@ -53,9 +53,7 @@ class SongUsageDeleteForm(QtWidgets.QDialog, Ui_SongUsageDeleteDialog, RegistryP
'Delete Selected Song Usage Events?'),
translate('SongUsagePlugin.SongUsageDeleteForm',
'Are you sure you want to delete selected Song Usage data?'),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
- QtWidgets.QMessageBox.No),
- QtWidgets.QMessageBox.No)
+ defaultButton=QtWidgets.QMessageBox.No)
if ret == QtWidgets.QMessageBox.Yes:
delete_date = self.delete_calendar.selectedDate().toPyDate()
self.manager.delete_all_objects(SongUsageItem, SongUsageItem.usagedate <= delete_date)
diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py
index 8a270598e..172cca6b1 100644
--- a/openlp/plugins/songusage/forms/songusagedetailform.py
+++ b/openlp/plugins/songusage/forms/songusagedetailform.py
@@ -44,7 +44,8 @@ class SongUsageDetailForm(QtWidgets.QDialog, Ui_SongUsageDetailDialog, RegistryP
"""
Initialise the form
"""
- super(SongUsageDetailForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
+ super(SongUsageDetailForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
+ QtCore.Qt.WindowCloseButtonHint)
self.plugin = plugin
self.setupUi(self)
diff --git a/tests/functional/openlp_core_lib/test_projector_constants.py b/tests/functional/openlp_core_lib/test_projector_constants.py
index 4a8e7a9e1..019c18888 100644
--- a/tests/functional/openlp_core_lib/test_projector_constants.py
+++ b/tests/functional/openlp_core_lib/test_projector_constants.py
@@ -29,7 +29,7 @@ class TestProjectorConstants(TestCase):
"""
Test specific functions in the projector constants module.
"""
- def build_pjlink_video_label_test(self):
+ def test_build_pjlink_video_label(self):
"""
Test building PJLINK_DEFAULT_CODES dictionary
"""
diff --git a/tests/functional/openlp_core_lib/test_projector_pjlink1.py b/tests/functional/openlp_core_lib/test_projector_pjlink1.py
index cd62da060..e5fb7566f 100644
--- a/tests/functional/openlp_core_lib/test_projector_pjlink1.py
+++ b/tests/functional/openlp_core_lib/test_projector_pjlink1.py
@@ -384,21 +384,6 @@ class TestPJLink(TestCase):
self.assertEquals("{test}".format(test=mock_send_command.call_args),
"call(data='{hash}%1CLSS ?\\r')".format(hash=TEST_HASH))
- @patch.object(pjlink_test, '_not_implemented')
- def not_implemented_test(self, mock_not_implemented):
- """
- Test PJLink._not_implemented method being called
- """
- # GIVEN: test object
- pjlink = pjlink_test
- test_cmd = 'TESTMEONLY'
-
- # WHEN: A future command is called that is not implemented yet
- pjlink.process_command(test_cmd, "Garbage data for test only")
-
- # THEN: PJLink.__not_implemented should have been called with test_cmd
- mock_not_implemented.assert_called_with(test_cmd)
-
@patch.object(pjlink_test, 'disconnect_from_host')
def socket_abort_test(self, mock_disconnect):
"""
diff --git a/tests/functional/openlp_core_lib/test_projectordb.py b/tests/functional/openlp_core_lib/test_projectordb.py
index 6b63ad493..d4ff4e75c 100644
--- a/tests/functional/openlp_core_lib/test_projectordb.py
+++ b/tests/functional/openlp_core_lib/test_projectordb.py
@@ -27,11 +27,15 @@ PREREQUISITE: add_record() and get_all() functions validated.
"""
import os
import shutil
-from unittest import TestCase
+from tempfile import mkdtemp
+
+from unittest import TestCase, skip
from unittest.mock import MagicMock, patch
-from openlp.core.lib.projector.db import Manufacturer, Model, Projector, ProjectorDB, ProjectorSource, Source
+from openlp.core.lib.projector import upgrade
+from openlp.core.lib.db import upgrade_db
from openlp.core.lib.projector.constants import PJLINK_PORT
+from openlp.core.lib.projector.db import Manufacturer, Model, Projector, ProjectorDB, ProjectorSource, Source
from tests.resources.projector.data import TEST_DB_PJLINK1, TEST_DB, TEST1_DATA, TEST2_DATA, TEST3_DATA
from tests.utils.constants import TEST_RESOURCES_PATH
@@ -85,6 +89,42 @@ def add_records(projector_db, test):
return added
+class TestProjectorDBUpdate(TestCase):
+ """
+ Test case for upgrading Projector DB.
+ NOTE: Separate class so I don't have to look for upgrade tests.
+ """
+ def setUp(self):
+ """
+ Setup for tests
+ """
+ self.tmp_folder = mkdtemp(prefix='openlp_')
+
+ def tearDown(self):
+ """
+ Clean up after tests
+ """
+ # Ignore errors since windows can have problems with locked files
+ shutil.rmtree(self.tmp_folder, ignore_errors=True)
+
+ def test_upgrade_old_projector_db(self):
+ """
+ Test that we can upgrade an old song db to the current schema
+ """
+ # GIVEN: An old song db
+ old_db = os.path.join(TEST_RESOURCES_PATH, "projector", TEST_DB_PJLINK1)
+ tmp_db = os.path.join(self.tmp_folder, TEST_DB)
+ shutil.copyfile(old_db, tmp_db)
+ db_url = 'sqlite:///{db}'.format(db=tmp_db)
+
+ # WHEN: upgrading the db
+ updated_to_version, latest_version = upgrade_db(db_url, upgrade)
+
+ # THEN: the song db should have been upgraded to the latest version
+ self.assertEqual(updated_to_version, latest_version,
+ 'The projector DB should have been upgrade to the latest version')
+
+
class TestProjectorDB(TestCase):
"""
Test case for ProjectorDB
@@ -94,7 +134,9 @@ class TestProjectorDB(TestCase):
"""
Set up anything necessary for all tests
"""
- mocked_init_url.return_value = 'sqlite:///{db}'.format(db=TEST_DB)
+ self.tmp_folder = mkdtemp(prefix='openlp_')
+ tmpdb_url = 'sqlite:///{db}'.format(db=os.path.join(self.tmp_folder, TEST_DB))
+ mocked_init_url.return_value = tmpdb_url
self.projector = ProjectorDB()
def tearDown(self):
@@ -103,15 +145,8 @@ class TestProjectorDB(TestCase):
"""
self.projector.session.close()
self.projector = None
- retries = 0
- while retries < 5:
- try:
- if os.path.exists(TEST_DB):
- os.unlink(TEST_DB)
- break
- except:
- time.sleep(1)
- retries += 1
+ # Ignore errors since windows can have problems with locked files
+ shutil.rmtree(self.tmp_folder, ignore_errors=True)
def test_find_record_by_ip(self):
"""
@@ -271,10 +306,10 @@ class TestProjectorDB(TestCase):
# THEN: __repr__ should return a proper string
self.assertEqual(str(projector),
- '< Projector(id="0", ip="127.0.0.1", port="4352", pin="None", name="Test One", '
- 'location="Somewhere over the rainbow", notes="Not again", pjlink_name="TEST", '
- 'manufacturer="IN YOUR DREAMS", model="OpenLP", serial_no="None", other="None", '
- 'sources="None", source_list="[]", model_filter="None", model_lamp="None", '
+ '< Projector(id="0", ip="127.0.0.1", port="4352", mac_adx="None", pin="None", '
+ 'name="Test One", location="Somewhere over the rainbow", notes="Not again", '
+ 'pjlink_name="TEST", manufacturer="IN YOUR DREAMS", model="OpenLP", serial_no="None", '
+ 'other="None", sources="None", source_list="[]", model_filter="None", model_lamp="None", '
'sw_version="None") >',
'Projector.__repr__() should have returned a proper representation string')
diff --git a/tests/functional/openlp_core_ui/test_formattingtagsform.py b/tests/functional/openlp_core_ui/test_formattingtagsform.py
index bb9534439..c4069a553 100644
--- a/tests/functional/openlp_core_ui/test_formattingtagsform.py
+++ b/tests/functional/openlp_core_ui/test_formattingtagsform.py
@@ -27,12 +27,6 @@ from unittest.mock import MagicMock, patch, call
from openlp.core.ui.formattingtagform import FormattingTagForm
-# TODO: Tests Still TODO
-# __init__
-# exec
-# on_saved_clicked
-# _reloadTable
-
class TestFormattingTagForm(TestCase):
diff --git a/tests/functional/openlp_core_ui/test_maindisplay.py b/tests/functional/openlp_core_ui/test_maindisplay.py
index 86aaf5ea7..e9ec825d2 100644
--- a/tests/functional/openlp_core_ui/test_maindisplay.py
+++ b/tests/functional/openlp_core_ui/test_maindisplay.py
@@ -29,7 +29,7 @@ from PyQt5 import QtCore
from openlp.core.common import Registry, is_macosx, Settings
from openlp.core.lib import ScreenList, PluginManager
-from openlp.core.ui import MainDisplay
+from openlp.core.ui import MainDisplay, AudioPlayer
from openlp.core.ui.media import MediaController
from openlp.core.ui.maindisplay import TRANSPARENT_STYLESHEET, OPAQUE_STYLESHEET
@@ -283,3 +283,18 @@ class TestMainDisplay(TestCase, TestMixin):
self.assertEquals(main_display.web_view.setHtml.call_count, 1, 'setHTML should be called once')
self.assertEquals(main_display.media_controller.video.call_count, 1,
'Media Controller video should have been called once')
+
+
+def test_calling_next_item_in_playlist():
+ """
+ Test the AudioPlayer.next() method
+ """
+ # GIVEN: An instance of AudioPlayer with a mocked out playlist
+ audio_player = AudioPlayer(None)
+
+ # WHEN: next is called.
+ with patch.object(audio_player, 'playlist') as mocked_playlist:
+ audio_player.next()
+
+ # THEN: playlist.next should had been called once.
+ mocked_playlist.next.assert_called_once_with()
diff --git a/tests/functional/openlp_core_ui/test_thememanager.py b/tests/functional/openlp_core_ui/test_thememanager.py
index a30eda7fa..45209ebeb 100644
--- a/tests/functional/openlp_core_ui/test_thememanager.py
+++ b/tests/functional/openlp_core_ui/test_thememanager.py
@@ -176,7 +176,7 @@ class TestThemeManager(TestCase):
self.assertTrue(result)
mocked_qmessagebox_question.assert_called_once_with(
theme_manager, 'Theme Already Exists', 'Theme Theme Name already exists. Do you want to replace it?',
- ANY, ANY)
+ defaultButton=ANY)
def test_over_write_message_box_no(self):
"""
@@ -196,7 +196,7 @@ class TestThemeManager(TestCase):
self.assertFalse(result)
mocked_qmessagebox_question.assert_called_once_with(
theme_manager, 'Theme Already Exists', 'Theme Theme Name already exists. Do you want to replace it?',
- ANY, ANY)
+ defaultButton=ANY)
def test_unzip_theme(self):
"""
diff --git a/tests/functional/openlp_plugins/bibles/test_bibleserver.py b/tests/functional/openlp_plugins/bibles/test_bibleserver.py
index a66f8b28e..bc05a601f 100644
--- a/tests/functional/openlp_plugins/bibles/test_bibleserver.py
+++ b/tests/functional/openlp_plugins/bibles/test_bibleserver.py
@@ -29,45 +29,11 @@ from bs4 import BeautifulSoup
from openlp.plugins.bibles.lib.importers.http import BSExtract
-# TODO: Items left to test
-# BGExtract
-# __init__
-# _remove_elements
-# _extract_verse
-# _clean_soup
-# _extract_verses
-# _extract_verses_old
-# get_bible_chapter
-# get_books_from_http
-# _get_application
-# CWExtract
-# __init__
-# get_bible_chapter
-# get_books_from_http
-# _get_application
-# HTTPBible
-# __init__
-# do_import
-# get_verses
-# get_chapter
-# get_books
-# get_chapter_count
-# get_verse_count
-# _get_application
-# get_soup_for_bible_ref
-# send_error_message
-
class TestBSExtract(TestCase):
"""
Test the BSExtractClass
"""
- # TODO: Items left to test
- # BSExtract
- # __init__
- # get_bible_chapter
- # get_books_from_http
- # _get_application
def setUp(self):
self.get_soup_for_bible_ref_patcher = patch('openlp.plugins.bibles.lib.importers.http.get_soup_for_bible_ref')
self.log_patcher = patch('openlp.plugins.bibles.lib.importers.http.log')
diff --git a/tests/functional/openlp_plugins/bibles/test_lib.py b/tests/functional/openlp_plugins/bibles/test_lib.py
index 2c2615a7a..5ae8ae85d 100644
--- a/tests/functional/openlp_plugins/bibles/test_lib.py
+++ b/tests/functional/openlp_plugins/bibles/test_lib.py
@@ -68,7 +68,8 @@ class TestLib(TestCase, TestMixin):
"""
# GIVEN: Some test data which contains different references to parse, with the expected results.
with patch('openlp.plugins.bibles.lib.Settings', return_value=MagicMock(**{'value.return_value': ''})):
- # The following test data tests with 222 variants when using the default 'separators'
+ # The following test data tests with about 240 variants when using the default 'separators'
+ # The amount is exactly 222 without '1. John 23' and'1. John. 23'
test_data = [
# Input reference, book name, chapter + verse reference
('Psalm 23', 'Psalm', '23'),
@@ -84,6 +85,8 @@ class TestLib(TestCase, TestMixin):
('Psalm 23{_and}24', 'Psalm', '23,24'),
('1 John 23', '1 John', '23'),
('1 John. 23', '1 John', '23'),
+ ('1. John 23', '1. John', '23'),
+ ('1. John. 23', '1. John', '23'),
('1 John 23{to}24', '1 John', '23-24'),
('1 John 23{verse}1{to}2', '1 John', '23:1-2'),
('1 John 23{verse}1{to}{end}', '1 John', '23:1-end'),
diff --git a/tests/functional/openlp_plugins/bibles/test_mediaitem.py b/tests/functional/openlp_plugins/bibles/test_mediaitem.py
index f9c5f64d0..a26802be7 100755
--- a/tests/functional/openlp_plugins/bibles/test_mediaitem.py
+++ b/tests/functional/openlp_plugins/bibles/test_mediaitem.py
@@ -199,9 +199,6 @@ class TestMediaItem(TestCase, TestMixin):
self.assertTrue(self.media_item.has_delete_icon, 'Check that the icon is called as True.')
self.assertFalse(self.media_item.add_to_service_item, 'Check that the icon is called as False')
- # TODO: Test add_end_header_bar
- # TODO: Test setupUi
-
def test_on_focus_search_tab_visible(self):
"""
Test the correct widget gets focus when the BibleMediaItem receives focus
@@ -480,9 +477,9 @@ class TestMediaItem(TestCase, TestMixin):
# WHEN: Calling update_auto_completer
self.media_item.update_auto_completer()
- # THEN: set_case_insensitive_completer should have been called with the names of the books in order
+ # THEN: set_case_insensitive_completer should have been called with the names of the books + space in order
mocked_set_case_insensitive_completer.assert_called_once_with(
- ['Book 1', 'Book 2', 'Book 3'], mocked_search_edit)
+ ['Book 1 ', 'Book 2 ', 'Book 3 '], mocked_search_edit)
def test_update_auto_completer_search_combined_type(self):
"""
@@ -500,11 +497,11 @@ class TestMediaItem(TestCase, TestMixin):
# WHEN: Calling update_auto_completer
self.media_item.update_auto_completer()
- # THEN: set_case_insensitive_completer should have been called with the names of the books in order
+ # THEN: set_case_insensitive_completer should have been called with the names of the books + space in order
mocked_set_case_insensitive_completer.assert_called_once_with(
- ['Book 1', 'Book 2', 'Book 3'], mocked_search_edit)
+ ['Book 1 ', 'Book 2 ', 'Book 3 '], mocked_search_edit)
- def test_on_import_click_no_import_wizzard_attr(self):
+ def test_on_import_click_no_import_wizard_attr(self):
"""
Test on_import_click when media_item does not have the `import_wizard` attribute. And the wizard was canceled.
"""
@@ -521,9 +518,9 @@ class TestMediaItem(TestCase, TestMixin):
self.assertTrue(mocked_bible_import_form.called)
self.assertFalse(mocked_reload_bibles.called)
- def test_on_import_click_wizzard_not_canceled(self):
+ def test_on_import_click_wizard_not_canceled(self):
"""
- Test on_import_click when the media item has the import_wizzard attr set and wizard completes sucessfully.
+ Test on_import_click when the media item has the import_wizard attr set and wizard completes sucessfully.
"""
# GIVEN: An instance of :class:`MediaManagerItem` and a mocked import_wizard
mocked_import_wizard = MagicMock(**{'exec.return_value': True})
@@ -1381,8 +1378,6 @@ class TestMediaItem(TestCase, TestMixin):
self.assertTrue(self.mocked_main_window.information_message.called)
mocked_display_results.assert_called_once_with()
- # TODO: Test text_search
-
def test_on_search_edit_text_changed_search_while_typing_disabled(self):
"""
Test on_search_edit_text_changed when 'search while typing' is disabled
diff --git a/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py b/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py
index 88544f0e9..3c08d226a 100644
--- a/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py
+++ b/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py
@@ -42,11 +42,6 @@ class TestPptviewController(TestCase, TestMixin):
"""
Test the PptviewController Class
"""
-# TODO: Items left to test
-# PptviewController
-# start_process(self)
-# kill
-
def setUp(self):
"""
Set up the patches and mocks need for all tests.
@@ -103,24 +98,6 @@ class TestPptviewDocument(TestCase):
"""
Test the PptviewDocument Class
"""
- # TODO: Items left to test
- # PptviewDocument
- # __init__
- # create_thumbnails
- # close_presentation
- # is_loaded
- # is_active
- # blank_screen
- # unblank_screen
- # is_blank
- # stop_presentation
- # start_presentation
- # get_slide_number
- # get_slide_count
- # goto_slide
- # next_step
- # previous_step
-
def setUp(self):
"""
Set up the patches and mocks need for all tests.
diff --git a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py
index 0254f3ce5..9f02fb9c8 100644
--- a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py
+++ b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py
@@ -36,19 +36,6 @@ class TestPresentationController(TestCase):
"""
Test the PresentationController.
"""
- # TODO: Items left to test
- # PresentationController
- # __init__
- # enabled
- # is_available
- # check_available
- # start_process
- # kill
- # add_document
- # remove_doc
- # close_presentation
- # _get_plugin_manager
-
def setUp(self):
self.get_thumbnail_folder_patcher = \
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder')
@@ -183,32 +170,6 @@ class TestPresentationDocument(TestCase):
"""
Test the PresentationDocument Class
"""
- # TODO: Items left to test
- # PresentationDocument
- # __init__
- # presentation_deleted
- # get_thumbnail_folder
- # get_temp_folder
- # check_thumbnails
- # close_presentation
- # is_active
- # is_loaded
- # blank_screen
- # unblank_screen
- # is_blank
- # stop_presentation
- # start_presentation
- # get_slide_number
- # get_slide_count
- # goto_slide
- # next_step
- # previous_step
- # convert_thumbnail
- # get_thumbnail_path
- # poll_slidenumber
- # get_slide_text
- # get_slide_notes
-
def setUp(self):
"""
Set up the patches and mocks need for all tests.
diff --git a/tests/functional/openlp_plugins/songs/test_foilpresenterimport.py b/tests/functional/openlp_plugins/songs/test_foilpresenterimport.py
index 1a8b1e38b..d3d705722 100644
--- a/tests/functional/openlp_plugins/songs/test_foilpresenterimport.py
+++ b/tests/functional/openlp_plugins/songs/test_foilpresenterimport.py
@@ -36,18 +36,6 @@ class TestFoilPresenter(TestCase):
"""
Test the functions in the :mod:`foilpresenterimport` module.
"""
- # TODO: The following modules still need tests written for
- # xml_to_song
- # to_str
- # _process_authors
- # _process_cclinumber
- # _process_comments
- # _process_copyright
- # _process_lyrics
- # _process_songbooks
- # _process_titles
- # _process_topics
-
def setUp(self):
self.to_str_patcher = patch('openlp.plugins.songs.lib.importers.foilpresenter.to_str')
self.clean_song_patcher = patch('openlp.plugins.songs.lib.importers.foilpresenter.clean_song')
diff --git a/tests/functional/openlp_plugins/songs/test_mediaitem.py b/tests/functional/openlp_plugins/songs/test_mediaitem.py
index d5b06b7dc..15c8e5ef0 100644
--- a/tests/functional/openlp_plugins/songs/test_mediaitem.py
+++ b/tests/functional/openlp_plugins/songs/test_mediaitem.py
@@ -46,9 +46,10 @@ class TestMediaItem(TestCase, TestMixin):
Registry.create()
Registry().register('service_list', MagicMock())
Registry().register('main_window', MagicMock())
+ self.mocked_plugin = MagicMock()
with patch('openlp.core.lib.mediamanageritem.MediaManagerItem._setup'), \
patch('openlp.plugins.songs.forms.editsongform.EditSongForm.__init__'):
- self.media_item = SongMediaItem(None, MagicMock())
+ self.media_item = SongMediaItem(None, self.mocked_plugin)
self.media_item.save_auto_select_id = MagicMock()
self.media_item.list_view = MagicMock()
self.media_item.list_view.save_auto_select_id = MagicMock()
@@ -558,3 +559,35 @@ class TestMediaItem(TestCase, TestMixin):
# THEN: The correct formatted results are returned
self.assertEqual(search_results, [[123, 'My Song', 'My alternative']])
+
+ @patch('openlp.plugins.songs.lib.mediaitem.Book')
+ @patch('openlp.plugins.songs.lib.mediaitem.SongBookEntry')
+ @patch('openlp.plugins.songs.lib.mediaitem.Song')
+ @patch('openlp.plugins.songs.lib.mediaitem.or_')
+ def test_entire_song_search(self, mocked_or, MockedSong, MockedSongBookEntry, MockedBook):
+ """
+ Test that searching the entire song does the right queries
+ """
+ # GIVEN: A song media item, a keyword and some mocks
+ keyword = 'Jesus'
+ mocked_song = MagicMock()
+ mocked_or.side_effect = lambda a, b, c, d, e: ' '.join([a, b, c, d, e])
+ MockedSong.search_title.like.side_effect = lambda a: a
+ MockedSong.search_lyrics.like.side_effect = lambda a: a
+ MockedSong.comments.like.side_effect = lambda a: a
+ MockedSongBookEntry.entry.like.side_effect = lambda a: a
+ MockedBook.name.like.side_effect = lambda a: a
+
+ # WHEN: search_entire_song() is called with the keyword
+ self.media_item.search_entire(keyword)
+
+ # THEN: The correct calls were made
+ MockedSong.search_title.like.assert_called_once_with('%jesus%')
+ MockedSong.search_lyrics.like.assert_called_once_with('%jesus%')
+ MockedSong.comments.like.assert_called_once_with('%jesus%')
+ MockedSongBookEntry.entry.like.assert_called_once_with('%jesus%')
+ MockedBook.name.like.assert_called_once_with('%jesus%')
+ mocked_or.assert_called_once_with('%jesus%', '%jesus%', '%jesus%', '%jesus%', '%jesus%')
+ self.mocked_plugin.manager.session.query.assert_called_once_with(MockedSong)
+
+ self.assertEqual(self.mocked_plugin.manager.session.query.mock_calls[4][0], '().join().join().filter().all')
diff --git a/tests/functional/openlp_plugins/songs/test_songselect.py b/tests/functional/openlp_plugins/songs/test_songselect.py
index b367b7c41..8583e0a17 100644
--- a/tests/functional/openlp_plugins/songs/test_songselect.py
+++ b/tests/functional/openlp_plugins/songs/test_songselect.py
@@ -612,8 +612,7 @@ class TestSongSelectForm(TestCase, TestMixin):
mocked_song_select_importer.save_song.assert_called_with(None)
mocked_question.assert_called_with(ssform, 'Song Imported',
'Your song has been imported, would you like to import more songs?',
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
- QtWidgets.QMessageBox.Yes)
+ defaultButton=QtWidgets.QMessageBox.Yes)
mocked_on_back_button_clicked.assert_called_with()
self.assertIsNone(ssform.song)
@@ -639,8 +638,7 @@ class TestSongSelectForm(TestCase, TestMixin):
mocked_song_select_importer.save_song.assert_called_with(None)
mocked_question.assert_called_with(ssform, 'Song Imported',
'Your song has been imported, would you like to import more songs?',
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
- QtWidgets.QMessageBox.Yes)
+ defaultButton=QtWidgets.QMessageBox.Yes)
mocked_done.assert_called_with(QtWidgets.QDialog.Accepted)
self.assertIsNone(ssform.song)
diff --git a/tests/interfaces/openlp_core_lib/test_searchedit.py b/tests/interfaces/openlp_core_lib/test_searchedit.py
index e2a01a450..4f4c4d68c 100644
--- a/tests/interfaces/openlp_core_lib/test_searchedit.py
+++ b/tests/interfaces/openlp_core_lib/test_searchedit.py
@@ -88,7 +88,7 @@ class TestSearchEdit(TestCase, TestMixin):
# settings
self.assertEqual(self.search_edit.current_search_type(), SearchTypes.First,
"The first search type should be selected.")
- self.mocked_settings().setValue.assert_called_once_with('settings_section/last search type', 0)
+ self.mocked_settings().setValue.assert_called_once_with('settings_section/last used search type', 0)
def test_set_current_search_type(self):
"""
@@ -105,7 +105,7 @@ class TestSearchEdit(TestCase, TestMixin):
self.assertEqual(self.search_edit.placeholderText(), SECOND_PLACEHOLDER_TEXT,
"The correct placeholder text should be 'Second Placeholder Text'.")
self.mocked_settings().setValue.assert_has_calls(
- [call('settings_section/last search type', 0), call('settings_section/last search type', 1)])
+ [call('settings_section/last used search type', 0), call('settings_section/last used search type', 1)])
def test_clear_button_visibility(self):
"""
diff --git a/tests/resources/projector/data.py b/tests/resources/projector/data.py
index 358719015..d9baa80d0 100644
--- a/tests/resources/projector/data.py
+++ b/tests/resources/projector/data.py
@@ -29,7 +29,7 @@ from tempfile import gettempdir
# Test data
TEST_DB_PJLINK1 = 'projector_pjlink1.sqlite'
-TEST_DB = os.path.join(gettempdir(), 'openlp-test-projectordb.sql')
+TEST_DB = 'openlp-test-projectordb.sqlite'
TEST_SALT = '498e4a67'
@@ -39,8 +39,6 @@ TEST_HASH = '5d8409bc1c3fa39749434aa3a5c38682'
TEST_CONNECT_AUTHENTICATE = 'PJLink 1 {salt}'.format(salt=TEST_SALT)
-TEST_DB = os.path.join(gettempdir(), 'openlp-test-projectordb.sql')
-
TEST1_DATA = dict(ip='111.111.111.111',
port='1111',
pin='1111',