diff --git a/.bzrignore b/.bzrignore
index c7abfd456..01c96078a 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -44,3 +44,4 @@ coverage
tags
output
htmlcov
+openlp-test-projectordb.sqlite
diff --git a/openlp.py b/openlp.py
index 73c0d9033..02287cd5e 100755
--- a/openlp.py
+++ b/openlp.py
@@ -27,16 +27,26 @@ import faulthandler
import multiprocessing
import sys
+from openlp.core.app import main
from openlp.core.common import is_win, is_macosx
from openlp.core.common.applocation import AppLocation
-from openlp.core import main
+from openlp.core.common.path import create_paths
+
+
+def set_up_fault_handling():
+ """
+ Set up the Python fault handler
+ """
+ # Create the cache directory if it doesn't exist, and enable the fault handler to log to an error log file
+ create_paths(AppLocation.get_directory(AppLocation.CacheDir))
+ faulthandler.enable(open(str(AppLocation.get_directory(AppLocation.CacheDir) / 'error.log'), 'wb'))
-faulthandler.enable(open(str(AppLocation.get_directory(AppLocation.CacheDir) / 'error.log'), 'wb'))
if __name__ == '__main__':
"""
Instantiate and run the application.
"""
+ set_up_fault_handling()
# Add support for using multiprocessing from frozen Windows executable (built using PyInstaller),
# see https://docs.python.org/3/library/multiprocessing.html#multiprocessing.freeze_support
if is_win():
diff --git a/openlp/__init__.py b/openlp/__init__.py
index 16d57e9af..2074ec39a 100644
--- a/openlp/__init__.py
+++ b/openlp/__init__.py
@@ -22,7 +22,3 @@
"""
The :mod:`openlp` module contains all the project produced OpenLP functionality
"""
-
-from openlp import core, plugins
-
-__all__ = ['core', 'plugins']
diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py
index c9e446143..b3fa9b6a6 100644
--- a/openlp/core/__init__.py
+++ b/openlp/core/__init__.py
@@ -26,396 +26,3 @@ The :mod:`core` module provides all core application functions
All the core functions of the OpenLP application including the GUI, settings,
logging and a plugin framework are contained within the openlp.core module.
"""
-import argparse
-import logging
-import sys
-import time
-from datetime import datetime
-from traceback import format_exception
-
-from PyQt5 import QtCore, QtGui, QtWidgets
-
-from openlp.core.common import Registry, OpenLPMixin, AppLocation, LanguageManager, Settings, UiStrings, \
- check_directory_exists, is_macosx, is_win, translate
-from openlp.core.common.path import Path, copytree
-from openlp.core.version import check_for_update, get_version
-from openlp.core.lib import ScreenList
-from openlp.core.resources import qInitResources
-from openlp.core.ui import SplashScreen
-from openlp.core.ui.exceptionform import ExceptionForm
-from openlp.core.ui.firsttimeform import FirstTimeForm
-from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
-from openlp.core.ui.mainwindow import MainWindow
-from openlp.core.ui.style import get_application_stylesheet
-
-
-__all__ = ['OpenLP', 'main']
-
-
-log = logging.getLogger()
-
-
-class OpenLP(OpenLPMixin, QtWidgets.QApplication):
- """
- The core application class. This class inherits from Qt's QApplication
- class in order to provide the core of the application.
- """
-
- args = []
-
- def exec(self):
- """
- Override exec method to allow the shared memory to be released on exit
- """
- self.is_event_loop_active = True
- result = QtWidgets.QApplication.exec()
- self.shared_memory.detach()
- return result
-
- def run(self, args):
- """
- Run the OpenLP application.
-
- :param args: Some Args
- """
- self.is_event_loop_active = False
- # On Windows, the args passed into the constructor are ignored. Not very handy, so set the ones we want to use.
- # On Linux and FreeBSD, in order to set the WM_CLASS property for X11, we pass "OpenLP" in as a command line
- # argument. This interferes with files being passed in as command line arguments, so we remove it from the list.
- if 'OpenLP' in args:
- args.remove('OpenLP')
- self.args.extend(args)
- # Decide how many screens we have and their size
- screens = ScreenList.create(self.desktop())
- # First time checks in settings
- has_run_wizard = Settings().value('core/has run wizard')
- if not has_run_wizard:
- ftw = FirstTimeForm()
- ftw.initialize(screens)
- if ftw.exec() == QtWidgets.QDialog.Accepted:
- Settings().setValue('core/has run wizard', True)
- elif ftw.was_cancelled:
- QtCore.QCoreApplication.exit()
- sys.exit()
- # Correct stylesheet bugs
- application_stylesheet = get_application_stylesheet()
- if application_stylesheet:
- self.setStyleSheet(application_stylesheet)
- can_show_splash = Settings().value('core/show splash')
- if can_show_splash:
- self.splash = SplashScreen()
- self.splash.show()
- # make sure Qt really display the splash screen
- self.processEvents()
- # Check if OpenLP has been upgrade and if a backup of data should be created
- self.backup_on_upgrade(has_run_wizard, can_show_splash)
- # start the main app window
- self.main_window = MainWindow()
- Registry().execute('bootstrap_initialise')
- Registry().execute('bootstrap_post_set_up')
- Registry().initialise = False
- self.main_window.show()
- if can_show_splash:
- # now kill the splashscreen
- self.splash.finish(self.main_window)
- log.debug('Splashscreen closed')
- # make sure Qt really display the splash screen
- self.processEvents()
- self.main_window.repaint()
- self.processEvents()
- if not has_run_wizard:
- self.main_window.first_time()
- if Settings().value('core/update check'):
- check_for_update(self.main_window)
- self.main_window.is_display_blank()
- self.main_window.app_startup()
- return self.exec()
-
- def is_already_running(self):
- """
- Look to see if OpenLP is already running and ask if a 2nd instance is to be started.
- """
- self.shared_memory = QtCore.QSharedMemory('OpenLP')
- if self.shared_memory.attach():
- status = QtWidgets.QMessageBox.critical(None, UiStrings().Error, UiStrings().OpenLPStart,
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
- QtWidgets.QMessageBox.No))
- if status == QtWidgets.QMessageBox.No:
- return True
- return False
- else:
- self.shared_memory.create(1)
- return False
-
- def is_data_path_missing(self):
- """
- Check if the data folder path exists.
- """
- data_folder_path = AppLocation.get_data_path()
- if not data_folder_path.exists():
- log.critical('Database was not found in: %s', data_folder_path)
- status = QtWidgets.QMessageBox.critical(
- None, translate('OpenLP', 'Data Directory Error'),
- translate('OpenLP', 'OpenLP data folder was not found in:\n\n{path}\n\nThe location of the data folder '
- 'was previously changed from the OpenLP\'s default location. If the data was '
- 'stored on removable device, that device needs to be made available.\n\nYou may '
- 'reset the data location back to the default location, or you can try to make the '
- 'current location available.\n\nDo you want to reset to the default data location? '
- 'If not, OpenLP will be closed so you can try to fix the the problem.')
- .format(path=data_folder_path),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
- QtWidgets.QMessageBox.No)
- if status == QtWidgets.QMessageBox.No:
- # If answer was "No", return "True", it will shutdown OpenLP in def main
- log.info('User requested termination')
- return True
- # If answer was "Yes", remove the custom data path thus resetting the default location.
- Settings().remove('advanced/data path')
- log.info('Database location has been reset to the default settings.')
- return False
-
- def hook_exception(self, exc_type, value, traceback):
- """
- Add an exception hook so that any uncaught exceptions are displayed in this window rather than somewhere where
- users cannot see it and cannot report when we encounter these problems.
-
- :param exc_type: The class of exception.
- :param value: The actual exception object.
- :param traceback: A traceback object with the details of where the exception occurred.
- """
- # We can't log.exception here because the last exception no longer exists, we're actually busy handling it.
- log.critical(''.join(format_exception(exc_type, value, traceback)))
- if not hasattr(self, 'exception_form'):
- self.exception_form = ExceptionForm()
- self.exception_form.exception_text_edit.setPlainText(''.join(format_exception(exc_type, value, traceback)))
- self.set_normal_cursor()
- is_splash_visible = False
- if hasattr(self, 'splash') and self.splash.isVisible():
- is_splash_visible = True
- self.splash.hide()
- self.exception_form.exec()
- if is_splash_visible:
- self.splash.show()
-
- def backup_on_upgrade(self, has_run_wizard, can_show_splash):
- """
- Check if OpenLP has been upgraded, and ask if a backup of data should be made
-
- :param has_run_wizard: OpenLP has been run before
- :param can_show_splash: Should OpenLP show the splash screen
- """
- data_version = Settings().value('core/application version')
- openlp_version = get_version()['version']
- # New installation, no need to create backup
- if not has_run_wizard:
- Settings().setValue('core/application version', openlp_version)
- # If data_version is different from the current version ask if we should backup the data folder
- elif data_version != openlp_version:
- if can_show_splash and self.splash.isVisible():
- self.splash.hide()
- 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?'),
- 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")
- data_folder_backup_path = data_folder_path.with_name(data_folder_path.name + '-' + timestamp)
- try:
- copytree(data_folder_path, data_folder_backup_path)
- except OSError:
- QtWidgets.QMessageBox.warning(None, translate('OpenLP', 'Backup'),
- translate('OpenLP', 'Backup of the data folder failed!'))
- return
- message = translate('OpenLP',
- 'A backup of the data folder has been created at:\n\n'
- '{text}').format(text=data_folder_backup_path)
- QtWidgets.QMessageBox.information(None, translate('OpenLP', 'Backup'), message)
-
- # Update the version in the settings
- Settings().setValue('core/application version', openlp_version)
- if can_show_splash:
- self.splash.show()
-
- def process_events(self):
- """
- Wrapper to make ProcessEvents visible and named correctly
- """
- self.processEvents()
-
- def set_busy_cursor(self):
- """
- Sets the Busy Cursor for the Application
- """
- self.setOverrideCursor(QtCore.Qt.BusyCursor)
- self.processEvents()
-
- def set_normal_cursor(self):
- """
- Sets the Normal Cursor for the Application
- """
- self.restoreOverrideCursor()
- self.processEvents()
-
- def event(self, event):
- """
- Enables platform specific event handling i.e. direct file opening on OS X
-
- :param event: The event
- """
- if event.type() == QtCore.QEvent.FileOpen:
- file_name = event.file()
- log.debug('Got open file event for {name}!'.format(name=file_name))
- self.args.insert(0, file_name)
- return True
- # Mac OS X should restore app window when user clicked on the OpenLP icon
- # in the Dock bar. However, OpenLP consists of multiple windows and this
- # does not work. This workaround fixes that.
- # The main OpenLP window is restored when it was previously minimized.
- elif event.type() == QtCore.QEvent.ApplicationActivate:
- if is_macosx() and hasattr(self, 'main_window'):
- if self.main_window.isMinimized():
- # Copied from QWidget.setWindowState() docs on how to restore and activate a minimized window
- # while preserving its maximized and/or full-screen state.
- self.main_window.setWindowState(self.main_window.windowState() & ~QtCore.Qt.WindowMinimized |
- QtCore.Qt.WindowActive)
- return True
- return QtWidgets.QApplication.event(self, event)
-
-
-def parse_options(args=None):
- """
- Parse the command line arguments
-
- :param args: list of command line arguments
- :return: a tuple of parsed options of type optparse.Value and a list of remaining argsZ
- """
- # Set up command line options.
- parser = argparse.ArgumentParser(prog='openlp.py')
- parser.add_argument('-e', '--no-error-form', dest='no_error_form', action='store_true',
- help='Disable the error notification form.')
- parser.add_argument('-l', '--log-level', dest='loglevel', default='warning', metavar='LEVEL',
- help='Set logging to LEVEL level. Valid values are "debug", "info", "warning".')
- parser.add_argument('-p', '--portable', dest='portable', action='store_true',
- help='Specify if this should be run as a portable app, '
- 'off a USB flash drive (not implemented).')
- parser.add_argument('-d', '--dev-version', dest='dev_version', action='store_true',
- help='Ignore the version file and pull the version directly from Bazaar')
- parser.add_argument('-s', '--style', dest='style', help='Set the Qt5 style (passed directly to Qt5).')
- parser.add_argument('-w', '--no-web-server', dest='no_web_server', action='store_false',
- help='Turn off the Web and Socket Server ')
- parser.add_argument('rargs', nargs='?', default=[])
- # Parse command line options and deal with them. Use args supplied pragmatically if possible.
- return parser.parse_args(args) if args else parser.parse_args()
-
-
-def set_up_logging(log_path):
- """
- Setup our logging using log_path
-
- :param openlp.core.common.path.Path log_path: The file to save the log to.
- :rtype: None
- """
- check_directory_exists(log_path, True)
- file_path = log_path / 'openlp.log'
- # TODO: FileHandler accepts a Path object in Py3.6
- logfile = logging.FileHandler(str(file_path), 'w', encoding='UTF-8')
- logfile.setFormatter(logging.Formatter('%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
- log.addHandler(logfile)
- if log.isEnabledFor(logging.DEBUG):
- print('Logging to: {name}'.format(name=file_path))
-
-
-def main(args=None):
- """
- The main function which parses command line options and then runs
-
- :param args: Some args
- """
- args = parse_options(args)
- qt_args = []
- if args and args.loglevel.lower() in ['d', 'debug']:
- log.setLevel(logging.DEBUG)
- elif args and args.loglevel.lower() in ['w', 'warning']:
- log.setLevel(logging.WARNING)
- else:
- log.setLevel(logging.INFO)
- if args and args.style:
- qt_args.extend(['-style', args.style])
- # Throw the rest of the arguments at Qt, just in case.
- qt_args.extend(args.rargs)
- # Bug #1018855: Set the WM_CLASS property in X11
- if not is_win() and not is_macosx():
- qt_args.append('OpenLP')
- # Initialise the resources
- qInitResources()
- # Now create and actually run the application.
- application = OpenLP(qt_args)
- application.setOrganizationName('OpenLP')
- application.setOrganizationDomain('openlp.org')
- application.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
- application.setAttribute(QtCore.Qt.AA_DontCreateNativeWidgetSiblings, True)
- if args and args.portable:
- application.setApplicationName('OpenLPPortable')
- Settings.setDefaultFormat(Settings.IniFormat)
- # Get location OpenLPPortable.ini
- portable_path = (AppLocation.get_directory(AppLocation.AppDir) / '..' / '..').resolve()
- data_path = portable_path / 'Data'
- set_up_logging(portable_path / 'Other')
- log.info('Running portable')
- portable_settings_path = data_path / 'OpenLP.ini'
- # Make this our settings file
- log.info('INI file: {name}'.format(name=portable_settings_path))
- Settings.set_filename(str(portable_settings_path))
- portable_settings = Settings()
- # Set our data path
- log.info('Data path: {name}'.format(name=data_path))
- # Point to our data path
- portable_settings.setValue('advanced/data path', data_path)
- portable_settings.setValue('advanced/is portable', True)
- portable_settings.sync()
- else:
- application.setApplicationName('OpenLP')
- set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
- Registry.create()
- Registry().register('application', application)
- Registry().set_flag('no_web_server', args.no_web_server)
- application.setApplicationVersion(get_version()['version'])
- # Check if an instance of OpenLP is already running. Quit if there is a running instance and the user only wants one
- if application.is_already_running():
- sys.exit()
- # If the custom data path is missing and the user wants to restore the data path, quit OpenLP.
- if application.is_data_path_missing():
- application.shared_memory.detach()
- sys.exit()
- # Upgrade settings.
- settings = Settings()
- if settings.can_upgrade():
- now = datetime.now()
- # Only back up if OpenLP has previously run.
- if settings.value('core/has run wizard'):
- back_up_path = AppLocation.get_data_path() / (now.strftime('%Y-%m-%d %H-%M') + '.conf')
- log.info('Settings about to be upgraded. Existing settings are being backed up to {back_up_path}'
- .format(back_up_path=back_up_path))
- QtWidgets.QMessageBox.information(
- None, translate('OpenLP', 'Settings Upgrade'),
- translate('OpenLP', 'Your settings are about to upgraded. A backup will be created at {back_up_path}')
- .format(back_up_path=back_up_path))
- settings.export(back_up_path)
- settings.upgrade_settings()
- # First time checks in settings
- if not Settings().value('core/has run wizard'):
- if not FirstTimeLanguageForm().exec():
- # if cancel then stop processing
- sys.exit()
- # i18n Set Language
- language = LanguageManager.get_language()
- translators = LanguageManager.get_translators(language)
- for translator in translators:
- if not translator.isEmpty():
- application.installTranslator(translator)
- if not translators:
- log.debug('Could not find translators.')
- if args and not args.no_error_form:
- sys.excepthook = application.hook_exception
- sys.exit(application.run(qt_args))
diff --git a/openlp/core/api/deploy.py b/openlp/core/api/deploy.py
index 9b1e6e793..0419b45db 100644
--- a/openlp/core/api/deploy.py
+++ b/openlp/core/api/deploy.py
@@ -25,7 +25,8 @@ Download and "install" the remote web client
import os
from zipfile import ZipFile
-from openlp.core.common import AppLocation, Registry
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.registry import Registry
from openlp.core.common.httputils import url_get_file, get_web_page, get_url_file_size
diff --git a/openlp/core/api/endpoint/controller.py b/openlp/core/api/endpoint/controller.py
index c3f5fd89f..8ecfdb732 100644
--- a/openlp/core/api/endpoint/controller.py
+++ b/openlp/core/api/endpoint/controller.py
@@ -27,7 +27,9 @@ import json
from openlp.core.api.http.endpoint import Endpoint
from openlp.core.api.http import requires_auth
-from openlp.core.common import Registry, AppLocation, Settings
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import ItemCapabilities, create_thumb
log = logging.getLogger(__name__)
diff --git a/openlp/core/api/endpoint/core.py b/openlp/core/api/endpoint/core.py
index 5814651b1..2988e03aa 100644
--- a/openlp/core/api/endpoint/core.py
+++ b/openlp/core/api/endpoint/core.py
@@ -19,13 +19,17 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
+"""
+The :mod:`~openlp.core.api.endpoint.core` module contains the core API endpoints
+"""
import logging
import os
-from openlp.core.api.http.endpoint import Endpoint
from openlp.core.api.http import requires_auth
-from openlp.core.common import Registry, UiStrings, translate
-from openlp.core.lib import image_to_byte, PluginStatus, StringContent
+from openlp.core.api.http.endpoint import Endpoint
+from openlp.core.common.registry import Registry
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.lib import PluginStatus, StringContent, image_to_byte
template_dir = 'templates'
diff --git a/openlp/core/api/endpoint/pluginhelpers.py b/openlp/core/api/endpoint/pluginhelpers.py
index d2955ef61..9377bde6a 100644
--- a/openlp/core/api/endpoint/pluginhelpers.py
+++ b/openlp/core/api/endpoint/pluginhelpers.py
@@ -24,11 +24,11 @@ import json
import re
import urllib
-from urllib.parse import urlparse
from webob import Response
from openlp.core.api.http.errors import NotFound
-from openlp.core.common import Registry, AppLocation
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.registry import Registry
from openlp.core.lib import PluginStatus, image_to_byte
diff --git a/openlp/core/api/endpoint/service.py b/openlp/core/api/endpoint/service.py
index 4e3b53fbb..ab9ae6740 100644
--- a/openlp/core/api/endpoint/service.py
+++ b/openlp/core/api/endpoint/service.py
@@ -22,9 +22,9 @@
import logging
import json
-from openlp.core.api.http.endpoint import Endpoint
from openlp.core.api.http import requires_auth
-from openlp.core.common import Registry
+from openlp.core.api.http.endpoint import Endpoint
+from openlp.core.common.registry import Registry
log = logging.getLogger(__name__)
diff --git a/openlp/core/api/http/endpoint.py b/openlp/core/api/http/endpoint.py
index d6a923a50..fe2b11d9a 100644
--- a/openlp/core/api/http/endpoint.py
+++ b/openlp/core/api/http/endpoint.py
@@ -22,12 +22,12 @@
"""
The Endpoint class, which provides plugins with a way to serve their own portion of the API
"""
-
import os
-from openlp.core.common import AppLocation
from mako.template import Template
+from openlp.core.common.applocation import AppLocation
+
class Endpoint(object):
"""
diff --git a/openlp/core/api/http/server.py b/openlp/core/api/http/server.py
index 2a2ec7292..fad135f2b 100644
--- a/openlp/core/api/http/server.py
+++ b/openlp/core/api/http/server.py
@@ -19,31 +19,31 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-
"""
The :mod:`http` module contains the API web server. This is a lightweight web server used by remotes to interact
with OpenLP. It uses JSON to communicate with the remotes.
"""
-
import logging
import time
from PyQt5 import QtCore, QtWidgets
from waitress import serve
-from openlp.core.api.http import register_endpoint
-from openlp.core.api.http import application
-from openlp.core.common import AppLocation, RegistryMixin, RegistryProperties, OpenLPMixin, \
- Settings, Registry, UiStrings, check_directory_exists
-from openlp.core.lib import translate
-
from openlp.core.api.deploy import download_and_check, download_sha256
-from openlp.core.api.poll import Poller
from openlp.core.api.endpoint.controller import controller_endpoint, api_controller_endpoint
from openlp.core.api.endpoint.core import chords_endpoint, stage_endpoint, blank_endpoint, main_endpoint
from openlp.core.api.endpoint.service import service_endpoint, api_service_endpoint
from openlp.core.api.endpoint.remote import remote_endpoint
-
+from openlp.core.api.http import register_endpoint
+from openlp.core.api.http import application
+from openlp.core.api.poll import Poller
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings
+from openlp.core.common.mixins import OpenLPMixin, RegistryMixin
+from openlp.core.common.path import create_paths
+from openlp.core.common.registry import RegistryProperties, Registry
+from openlp.core.common.settings import Settings
+from openlp.core.common.i18n import translate
log = logging.getLogger(__name__)
@@ -115,11 +115,11 @@ class HttpServer(RegistryMixin, RegistryProperties, OpenLPMixin):
Create the internal file structure if it does not exist
:return:
"""
- check_directory_exists(AppLocation.get_section_data_path('remotes') / 'assets')
- check_directory_exists(AppLocation.get_section_data_path('remotes') / 'images')
- check_directory_exists(AppLocation.get_section_data_path('remotes') / 'static')
- check_directory_exists(AppLocation.get_section_data_path('remotes') / 'static' / 'index')
- check_directory_exists(AppLocation.get_section_data_path('remotes') / 'templates')
+ create_paths(AppLocation.get_section_data_path('remotes') / 'assets',
+ AppLocation.get_section_data_path('remotes') / 'images',
+ AppLocation.get_section_data_path('remotes') / 'static',
+ AppLocation.get_section_data_path('remotes') / 'static' / 'index',
+ AppLocation.get_section_data_path('remotes') / 'templates')
def first_time(self):
"""
diff --git a/openlp/core/api/http/wsgiapp.py b/openlp/core/api/http/wsgiapp.py
index 153344ab5..f948d4096 100644
--- a/openlp/core/api/http/wsgiapp.py
+++ b/openlp/core/api/http/wsgiapp.py
@@ -31,7 +31,7 @@ import re
from webob import Request, Response
from webob.static import DirectoryApp
-from openlp.core.common import AppLocation
+from openlp.core.common.applocation import AppLocation
from openlp.core.api.http.errors import HttpError, NotFound, ServerError
diff --git a/openlp/core/api/poll.py b/openlp/core/api/poll.py
index c4b25848a..5b3fb33c4 100644
--- a/openlp/core/api/poll.py
+++ b/openlp/core/api/poll.py
@@ -22,8 +22,9 @@
import json
-from openlp.core.common import RegistryProperties, Settings
from openlp.core.common.httputils import get_web_page
+from openlp.core.common.registry import RegistryProperties
+from openlp.core.common.settings import Settings
class Poller(RegistryProperties):
diff --git a/openlp/core/api/tab.py b/openlp/core/api/tab.py
index 7f645d6c6..ddca61176 100644
--- a/openlp/core/api/tab.py
+++ b/openlp/core/api/tab.py
@@ -19,10 +19,14 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-
+"""
+The :mod:`~openlp.core.api.tab` module contains the settings tab for the API
+"""
from PyQt5 import QtCore, QtGui, QtNetwork, QtWidgets
-from openlp.core.common import UiStrings, Registry, Settings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab
ZERO_URL = '0.0.0.0'
diff --git a/openlp/core/api/websockets.py b/openlp/core/api/websockets.py
index cf4d83425..d64fdf3cc 100644
--- a/openlp/core/api/websockets.py
+++ b/openlp/core/api/websockets.py
@@ -19,12 +19,10 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-
"""
The :mod:`http` module contains the API web server. This is a lightweight web server used by remotes to interact
with OpenLP. It uses JSON to communicate with the remotes.
"""
-
import asyncio
import websockets
import json
@@ -33,7 +31,9 @@ import time
from PyQt5 import QtCore
-from openlp.core.common import Settings, RegistryProperties, OpenLPMixin, Registry
+from openlp.core.common.mixins import OpenLPMixin
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
log = logging.getLogger(__name__)
diff --git a/openlp/core/app.py b/openlp/core/app.py
new file mode 100644
index 000000000..7c3938cfe
--- /dev/null
+++ b/openlp/core/app.py
@@ -0,0 +1,425 @@
+# -*- 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:`core` module provides all core application functions
+
+All the core functions of the OpenLP application including the GUI, settings,
+logging and a plugin framework are contained within the openlp.core module.
+"""
+import argparse
+import logging
+import sys
+import time
+from datetime import datetime
+from traceback import format_exception
+
+from PyQt5 import QtCore, QtWidgets
+
+from openlp.core.common import is_macosx, is_win
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import LanguageManager, UiStrings, translate
+from openlp.core.common.mixins import OpenLPMixin
+from openlp.core.common.path import create_paths, copytree
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
+from openlp.core.version import check_for_update, get_version
+from openlp.core.display.screens import ScreenList
+from openlp.core.resources import qInitResources
+from openlp.core.ui import SplashScreen
+from openlp.core.ui.exceptionform import ExceptionForm
+from openlp.core.ui.firsttimeform import FirstTimeForm
+from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
+from openlp.core.ui.mainwindow import MainWindow
+from openlp.core.ui.style import get_application_stylesheet
+
+
+__all__ = ['OpenLP', 'main']
+
+
+log = logging.getLogger()
+
+
+class OpenLP(OpenLPMixin, QtWidgets.QApplication):
+ """
+ The core application class. This class inherits from Qt's QApplication
+ class in order to provide the core of the application.
+ """
+
+ args = []
+
+ def exec(self):
+ """
+ Override exec method to allow the shared memory to be released on exit
+ """
+ self.is_event_loop_active = True
+ result = QtWidgets.QApplication.exec()
+ self.shared_memory.detach()
+ return result
+
+ def run(self, args):
+ """
+ Run the OpenLP application.
+
+ :param args: Some Args
+ """
+ self.is_event_loop_active = False
+ # On Windows, the args passed into the constructor are ignored. Not very handy, so set the ones we want to use.
+ # On Linux and FreeBSD, in order to set the WM_CLASS property for X11, we pass "OpenLP" in as a command line
+ # argument. This interferes with files being passed in as command line arguments, so we remove it from the list.
+ if 'OpenLP' in args:
+ args.remove('OpenLP')
+ self.args.extend(args)
+ # Decide how many screens we have and their size
+ screens = ScreenList.create(self.desktop())
+ # First time checks in settings
+ has_run_wizard = Settings().value('core/has run wizard')
+ if not has_run_wizard:
+ ftw = FirstTimeForm()
+ ftw.initialize(screens)
+ if ftw.exec() == QtWidgets.QDialog.Accepted:
+ Settings().setValue('core/has run wizard', True)
+ elif ftw.was_cancelled:
+ QtCore.QCoreApplication.exit()
+ sys.exit()
+ # Correct stylesheet bugs
+ application_stylesheet = get_application_stylesheet()
+ if application_stylesheet:
+ self.setStyleSheet(application_stylesheet)
+ can_show_splash = Settings().value('core/show splash')
+ if can_show_splash:
+ self.splash = SplashScreen()
+ self.splash.show()
+ # make sure Qt really display the splash screen
+ self.processEvents()
+ # Check if OpenLP has been upgrade and if a backup of data should be created
+ self.backup_on_upgrade(has_run_wizard, can_show_splash)
+ # start the main app window
+ self.main_window = MainWindow()
+ Registry().execute('bootstrap_initialise')
+ Registry().execute('bootstrap_post_set_up')
+ Registry().initialise = False
+ self.main_window.show()
+ if can_show_splash:
+ # now kill the splashscreen
+ self.splash.finish(self.main_window)
+ log.debug('Splashscreen closed')
+ # make sure Qt really display the splash screen
+ self.processEvents()
+ self.main_window.repaint()
+ self.processEvents()
+ if not has_run_wizard:
+ self.main_window.first_time()
+ if Settings().value('core/update check'):
+ check_for_update(self.main_window)
+ self.main_window.is_display_blank()
+ self.main_window.app_startup()
+ return self.exec()
+
+ def is_already_running(self):
+ """
+ Look to see if OpenLP is already running and ask if a 2nd instance is to be started.
+ """
+ self.shared_memory = QtCore.QSharedMemory('OpenLP')
+ if self.shared_memory.attach():
+ status = QtWidgets.QMessageBox.critical(None, UiStrings().Error, UiStrings().OpenLPStart,
+ QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
+ QtWidgets.QMessageBox.No))
+ if status == QtWidgets.QMessageBox.No:
+ return True
+ return False
+ else:
+ self.shared_memory.create(1)
+ return False
+
+ def is_data_path_missing(self):
+ """
+ Check if the data folder path exists.
+ """
+ data_folder_path = AppLocation.get_data_path()
+ if not data_folder_path.exists():
+ log.critical('Database was not found in: %s', data_folder_path)
+ status = QtWidgets.QMessageBox.critical(
+ None, translate('OpenLP', 'Data Directory Error'),
+ translate('OpenLP', 'OpenLP data folder was not found in:\n\n{path}\n\nThe location of the data folder '
+ 'was previously changed from the OpenLP\'s default location. If the data was '
+ 'stored on removable device, that device needs to be made available.\n\nYou may '
+ 'reset the data location back to the default location, or you can try to make the '
+ 'current location available.\n\nDo you want to reset to the default data location? '
+ 'If not, OpenLP will be closed so you can try to fix the the problem.')
+ .format(path=data_folder_path),
+ QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
+ QtWidgets.QMessageBox.No)
+ if status == QtWidgets.QMessageBox.No:
+ # If answer was "No", return "True", it will shutdown OpenLP in def main
+ log.info('User requested termination')
+ return True
+ # If answer was "Yes", remove the custom data path thus resetting the default location.
+ Settings().remove('advanced/data path')
+ log.info('Database location has been reset to the default settings.')
+ return False
+
+ def hook_exception(self, exc_type, value, traceback):
+ """
+ Add an exception hook so that any uncaught exceptions are displayed in this window rather than somewhere where
+ users cannot see it and cannot report when we encounter these problems.
+
+ :param exc_type: The class of exception.
+ :param value: The actual exception object.
+ :param traceback: A traceback object with the details of where the exception occurred.
+ """
+ # We can't log.exception here because the last exception no longer exists, we're actually busy handling it.
+ log.critical(''.join(format_exception(exc_type, value, traceback)))
+ if not hasattr(self, 'exception_form'):
+ self.exception_form = ExceptionForm()
+ self.exception_form.exception_text_edit.setPlainText(''.join(format_exception(exc_type, value, traceback)))
+ self.set_normal_cursor()
+ is_splash_visible = False
+ if hasattr(self, 'splash') and self.splash.isVisible():
+ is_splash_visible = True
+ self.splash.hide()
+ self.exception_form.exec()
+ if is_splash_visible:
+ self.splash.show()
+
+ def backup_on_upgrade(self, has_run_wizard, can_show_splash):
+ """
+ Check if OpenLP has been upgraded, and ask if a backup of data should be made
+
+ :param has_run_wizard: OpenLP has been run before
+ :param can_show_splash: Should OpenLP show the splash screen
+ """
+ data_version = Settings().value('core/application version')
+ openlp_version = get_version()['version']
+ # New installation, no need to create backup
+ if not has_run_wizard:
+ Settings().setValue('core/application version', openlp_version)
+ # If data_version is different from the current version ask if we should backup the data folder
+ elif data_version != openlp_version:
+ if can_show_splash and self.splash.isVisible():
+ self.splash.hide()
+ 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?'),
+ 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")
+ data_folder_backup_path = data_folder_path.with_name(data_folder_path.name + '-' + timestamp)
+ try:
+ copytree(data_folder_path, data_folder_backup_path)
+ except OSError:
+ QtWidgets.QMessageBox.warning(None, translate('OpenLP', 'Backup'),
+ translate('OpenLP', 'Backup of the data folder failed!'))
+ return
+ message = translate('OpenLP',
+ 'A backup of the data folder has been created at:\n\n'
+ '{text}').format(text=data_folder_backup_path)
+ QtWidgets.QMessageBox.information(None, translate('OpenLP', 'Backup'), message)
+
+ # Update the version in the settings
+ Settings().setValue('core/application version', openlp_version)
+ if can_show_splash:
+ self.splash.show()
+
+ def process_events(self):
+ """
+ Wrapper to make ProcessEvents visible and named correctly
+ """
+ self.processEvents()
+
+ def set_busy_cursor(self):
+ """
+ Sets the Busy Cursor for the Application
+ """
+ self.setOverrideCursor(QtCore.Qt.BusyCursor)
+ self.processEvents()
+
+ def set_normal_cursor(self):
+ """
+ Sets the Normal Cursor for the Application
+ """
+ self.restoreOverrideCursor()
+ self.processEvents()
+
+ def event(self, event):
+ """
+ Enables platform specific event handling i.e. direct file opening on OS X
+
+ :param event: The event
+ """
+ if event.type() == QtCore.QEvent.FileOpen:
+ file_name = event.file()
+ log.debug('Got open file event for {name}!'.format(name=file_name))
+ self.args.insert(0, file_name)
+ return True
+ # Mac OS X should restore app window when user clicked on the OpenLP icon
+ # in the Dock bar. However, OpenLP consists of multiple windows and this
+ # does not work. This workaround fixes that.
+ # The main OpenLP window is restored when it was previously minimized.
+ elif event.type() == QtCore.QEvent.ApplicationActivate:
+ if is_macosx() and hasattr(self, 'main_window'):
+ if self.main_window.isMinimized():
+ # Copied from QWidget.setWindowState() docs on how to restore and activate a minimized window
+ # while preserving its maximized and/or full-screen state.
+ self.main_window.setWindowState(self.main_window.windowState() & ~QtCore.Qt.WindowMinimized |
+ QtCore.Qt.WindowActive)
+ return True
+ return QtWidgets.QApplication.event(self, event)
+
+
+def parse_options(args=None):
+ """
+ Parse the command line arguments
+
+ :param args: list of command line arguments
+ :return: a tuple of parsed options of type optparse.Value and a list of remaining argsZ
+ """
+ # Set up command line options.
+ parser = argparse.ArgumentParser(prog='openlp.py')
+ parser.add_argument('-e', '--no-error-form', dest='no_error_form', action='store_true',
+ help='Disable the error notification form.')
+ parser.add_argument('-l', '--log-level', dest='loglevel', default='warning', metavar='LEVEL',
+ help='Set logging to LEVEL level. Valid values are "debug", "info", "warning".')
+ parser.add_argument('-p', '--portable', dest='portable', action='store_true',
+ help='Specify if this should be run as a portable app, '
+ 'off a USB flash drive (not implemented).')
+ parser.add_argument('-d', '--dev-version', dest='dev_version', action='store_true',
+ help='Ignore the version file and pull the version directly from Bazaar')
+ parser.add_argument('-s', '--style', dest='style', help='Set the Qt5 style (passed directly to Qt5).')
+ parser.add_argument('-w', '--no-web-server', dest='no_web_server', action='store_false',
+ help='Turn off the Web and Socket Server ')
+ parser.add_argument('rargs', nargs='?', default=[])
+ # Parse command line options and deal with them. Use args supplied pragmatically if possible.
+ return parser.parse_args(args) if args else parser.parse_args()
+
+
+def set_up_logging(log_path):
+ """
+ Setup our logging using log_path
+
+ :param openlp.core.common.path.Path log_path: The file to save the log to.
+ :rtype: None
+ """
+ create_paths(log_path, do_not_log=True)
+ file_path = log_path / 'openlp.log'
+ # TODO: FileHandler accepts a Path object in Py3.6
+ logfile = logging.FileHandler(str(file_path), 'w', encoding='UTF-8')
+ logfile.setFormatter(logging.Formatter('%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
+ log.addHandler(logfile)
+ if log.isEnabledFor(logging.DEBUG):
+ print('Logging to: {name}'.format(name=file_path))
+
+
+def main(args=None):
+ """
+ The main function which parses command line options and then runs
+
+ :param args: Some args
+ """
+ args = parse_options(args)
+ qt_args = []
+ if args and args.loglevel.lower() in ['d', 'debug']:
+ log.setLevel(logging.DEBUG)
+ elif args and args.loglevel.lower() in ['w', 'warning']:
+ log.setLevel(logging.WARNING)
+ else:
+ log.setLevel(logging.INFO)
+ if args and args.style:
+ qt_args.extend(['-style', args.style])
+ # Throw the rest of the arguments at Qt, just in case.
+ qt_args.extend(args.rargs)
+ # Bug #1018855: Set the WM_CLASS property in X11
+ if not is_win() and not is_macosx():
+ qt_args.append('OpenLP')
+ # Initialise the resources
+ qInitResources()
+ # Now create and actually run the application.
+ application = OpenLP(qt_args)
+ application.setOrganizationName('OpenLP')
+ application.setOrganizationDomain('openlp.org')
+ application.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
+ application.setAttribute(QtCore.Qt.AA_DontCreateNativeWidgetSiblings, True)
+ if args and args.portable:
+ application.setApplicationName('OpenLPPortable')
+ Settings.setDefaultFormat(Settings.IniFormat)
+ # Get location OpenLPPortable.ini
+ portable_path = (AppLocation.get_directory(AppLocation.AppDir) / '..' / '..').resolve()
+ data_path = portable_path / 'Data'
+ set_up_logging(portable_path / 'Other')
+ log.info('Running portable')
+ portable_settings_path = data_path / 'OpenLP.ini'
+ # Make this our settings file
+ log.info('INI file: {name}'.format(name=portable_settings_path))
+ Settings.set_filename(str(portable_settings_path))
+ portable_settings = Settings()
+ # Set our data path
+ log.info('Data path: {name}'.format(name=data_path))
+ # Point to our data path
+ portable_settings.setValue('advanced/data path', data_path)
+ portable_settings.setValue('advanced/is portable', True)
+ portable_settings.sync()
+ else:
+ application.setApplicationName('OpenLP')
+ set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
+ Registry.create()
+ Registry().register('application', application)
+ Registry().set_flag('no_web_server', args.no_web_server)
+ application.setApplicationVersion(get_version()['version'])
+ # Check if an instance of OpenLP is already running. Quit if there is a running instance and the user only wants one
+ if application.is_already_running():
+ sys.exit()
+ # If the custom data path is missing and the user wants to restore the data path, quit OpenLP.
+ if application.is_data_path_missing():
+ application.shared_memory.detach()
+ sys.exit()
+ # Upgrade settings.
+ settings = Settings()
+ if settings.can_upgrade():
+ now = datetime.now()
+ # Only back up if OpenLP has previously run.
+ if settings.value('core/has run wizard'):
+ back_up_path = AppLocation.get_data_path() / (now.strftime('%Y-%m-%d %H-%M') + '.conf')
+ log.info('Settings about to be upgraded. Existing settings are being backed up to {back_up_path}'
+ .format(back_up_path=back_up_path))
+ QtWidgets.QMessageBox.information(
+ None, translate('OpenLP', 'Settings Upgrade'),
+ translate('OpenLP', 'Your settings are about to upgraded. A backup will be created at {back_up_path}')
+ .format(back_up_path=back_up_path))
+ settings.export(back_up_path)
+ settings.upgrade_settings()
+ # First time checks in settings
+ if not Settings().value('core/has run wizard'):
+ if not FirstTimeLanguageForm().exec():
+ # if cancel then stop processing
+ sys.exit()
+ # i18n Set Language
+ language = LanguageManager.get_language()
+ translators = LanguageManager.get_translators(language)
+ for translator in translators:
+ if not translator.isEmpty():
+ application.installTranslator(translator)
+ if not translators:
+ log.debug('Could not find translators.')
+ if args and not args.no_error_form:
+ sys.excepthook = application.hook_exception
+ sys.exit(application.run(qt_args))
diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py
index 9a4a1935b..f8017fdbd 100644
--- a/openlp/core/common/__init__.py
+++ b/openlp/core/common/__init__.py
@@ -35,7 +35,7 @@ from ipaddress import IPv4Address, IPv6Address, AddressValueError
from shutil import which
from subprocess import check_output, CalledProcessError, STDOUT
-from PyQt5 import QtCore, QtGui
+from PyQt5 import QtGui
from PyQt5.QtCore import QCryptographicHash as QHash
log = logging.getLogger(__name__ + '.__init__')
@@ -56,30 +56,10 @@ def trace_error_handler(logger):
"""
log_string = "OpenLP Error trace"
for tb in traceback.extract_stack():
- log_string += '\n File {file} at line {line} \n\t called {data}'.format(file=tb[0],
- line=tb[1],
- data=tb[3])
+ log_string += '\n File {file} at line {line} \n\t called {data}'.format(file=tb[0], line=tb[1], data=tb[3])
logger.error(log_string)
-def check_directory_exists(directory, do_not_log=False):
- """
- Check a directory exists and if not create it
-
- :param openlp.core.common.path.Path directory: The directory to make sure exists
- :param bool do_not_log: To not log anything. This is need for the start up, when the log isn't ready.
- :rtype: None
- """
- if not do_not_log:
- log.debug('check_directory_exists {text}'.format(text=directory))
- try:
- if not directory.exists():
- directory.mkdir(parents=True)
- except IOError:
- if not do_not_log:
- log.exception('failed to check if directory exists or create directory')
-
-
def extension_loader(glob_pattern, excluded_files=[]):
"""
A utility function to find and load OpenLP extensions, such as plugins, presentation and media controllers and
@@ -90,6 +70,7 @@ def extension_loader(glob_pattern, excluded_files=[]):
:param list[str] excluded_files: A list of file names to exclude that the glob pattern may find.
:rtype: None
"""
+ from openlp.core.common.applocation import AppLocation
app_dir = AppLocation.get_directory(AppLocation.AppDir)
for extension_path in app_dir.glob(glob_pattern):
extension_path = extension_path.relative_to(app_dir)
@@ -137,19 +118,6 @@ class ThemeLevel(object):
Song = 3
-def translate(context, text, comment=None, qt_translate=QtCore.QCoreApplication.translate):
- """
- A special shortcut method to wrap around the Qt5 translation functions. This abstracts the translation procedure so
- that we can change it if at a later date if necessary, without having to redo the whole of OpenLP.
-
- :param context: The translation context, used to give each string a context or a namespace.
- :param text: The text to put into the translation tables for translation.
- :param comment: An identifying string for when the same text is used in different roles within the same context.
- :param qt_translate:
- """
- return qt_translate(context, text, comment)
-
-
class SlideLimits(object):
"""
Provides an enumeration for behaviour of OpenLP at the end limits of each service item when pressing the up/down
@@ -203,7 +171,7 @@ def verify_ipv4(addr):
:returns: bool
"""
try:
- valid = IPv4Address(addr)
+ IPv4Address(addr)
return True
except AddressValueError:
return False
@@ -217,7 +185,7 @@ def verify_ipv6(addr):
:returns: bool
"""
try:
- valid = IPv6Address(addr)
+ IPv6Address(addr)
return True
except AddressValueError:
return False
@@ -290,20 +258,6 @@ def clean_button_text(button_text):
return button_text.replace('&', '').replace('< ', '').replace(' >', '')
-from .openlpmixin import OpenLPMixin
-from .registry import Registry
-from .registrymixin import RegistryMixin
-from .registryproperties import RegistryProperties
-from .uistrings import UiStrings
-from .settings import Settings
-from .applocation import AppLocation
-from .actions import ActionList
-from .languagemanager import LanguageManager
-
-if is_win():
- from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW
-
-
def add_actions(target, actions):
"""
Adds multiple actions to a menu or toolbar in one command.
@@ -394,6 +348,7 @@ def get_images_filter():
"""
Returns a filter string for a file dialog containing all the supported image formats.
"""
+ from openlp.core.common.i18n import translate
global IMAGES_FILTER
if not IMAGES_FILTER:
log.debug('Generating images filter.')
@@ -446,6 +401,7 @@ def check_binary_exists(program_path):
try:
# Setup startupinfo options for check_output to avoid console popping up on windows
if is_win():
+ from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW
startupinfo = STARTUPINFO()
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
else:
diff --git a/openlp/core/common/actions.py b/openlp/core/common/actions.py
index c39cbc824..a5b417017 100644
--- a/openlp/core/common/actions.py
+++ b/openlp/core/common/actions.py
@@ -27,7 +27,7 @@ import logging
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Settings
+from openlp.core.common.settings import Settings
log = logging.getLogger(__name__)
diff --git a/openlp/core/common/applocation.py b/openlp/core/common/applocation.py
index 02a872303..cf70edfc1 100644
--- a/openlp/core/common/applocation.py
+++ b/openlp/core/common/applocation.py
@@ -26,8 +26,10 @@ import logging
import os
import sys
-from openlp.core.common import Settings, is_win, is_macosx
-from openlp.core.common.path import Path
+import openlp
+from openlp.core.common import get_frozen_path, is_win, is_macosx
+from openlp.core.common.path import Path, create_paths
+from openlp.core.common.settings import Settings
if not is_win() and not is_macosx():
try:
@@ -36,10 +38,6 @@ if not is_win() and not is_macosx():
except ImportError:
XDG_BASE_AVAILABLE = False
-import openlp
-from openlp.core.common import check_directory_exists, get_frozen_path
-
-
log = logging.getLogger(__name__)
FROZEN_APP_PATH = Path(sys.argv[0]).parent
@@ -88,7 +86,7 @@ class AppLocation(object):
path = Settings().value('advanced/data path')
else:
path = AppLocation.get_directory(AppLocation.DataDir)
- check_directory_exists(path)
+ create_paths(path)
return path
@staticmethod
@@ -121,7 +119,7 @@ class AppLocation(object):
:rtype: openlp.core.common.path.Path
"""
path = AppLocation.get_data_path() / section
- check_directory_exists(path)
+ create_paths(path)
return path
diff --git a/openlp/core/common/httputils.py b/openlp/core/common/httputils.py
index a92cd92c9..11ae7b563 100644
--- a/openlp/core/common/httputils.py
+++ b/openlp/core/common/httputils.py
@@ -30,7 +30,8 @@ from random import randint
import requests
-from openlp.core.common import Registry, trace_error_handler
+from openlp.core.common import trace_error_handler
+from openlp.core.common.registry import Registry
log = logging.getLogger(__name__ + '.__init__')
diff --git a/openlp/core/common/i18n.py b/openlp/core/common/i18n.py
new file mode 100644
index 000000000..1f4357808
--- /dev/null
+++ b/openlp/core/common/i18n.py
@@ -0,0 +1,556 @@
+# -*- 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:`languages` module provides a list of language names with utility functions.
+"""
+import itertools
+import locale
+import logging
+import re
+from collections import namedtuple
+
+from PyQt5 import QtCore, QtWidgets
+
+from openlp.core.common import is_win, is_macosx
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.settings import Settings
+
+log = logging.getLogger(__name__)
+
+
+# Due to dependency issues, this HAS to be at the top of the file
+def translate(context, text, comment=None, qt_translate=QtCore.QCoreApplication.translate):
+ """
+ A special shortcut method to wrap around the Qt5 translation functions. This abstracts the translation procedure so
+ that we can change it if at a later date if necessary, without having to redo the whole of OpenLP.
+
+ :param context: The translation context, used to give each string a context or a namespace.
+ :param text: The text to put into the translation tables for translation.
+ :param comment: An identifying string for when the same text is used in different roles within the same context.
+ :param qt_translate:
+ """
+ return qt_translate(context, text, comment)
+
+
+Language = namedtuple('Language', ['id', 'name', 'code'])
+ICU_COLLATOR = None
+DIGITS_OR_NONDIGITS = re.compile(r'\d+|\D+', re.UNICODE)
+LANGUAGES = sorted([
+ Language(1, translate('common.languages', '(Afan) Oromo', 'Language code: om'), 'om'),
+ Language(2, translate('common.languages', 'Abkhazian', 'Language code: ab'), 'ab'),
+ Language(3, translate('common.languages', 'Afar', 'Language code: aa'), 'aa'),
+ Language(4, translate('common.languages', 'Afrikaans', 'Language code: af'), 'af'),
+ Language(5, translate('common.languages', 'Albanian', 'Language code: sq'), 'sq'),
+ Language(6, translate('common.languages', 'Amharic', 'Language code: am'), 'am'),
+ Language(140, translate('common.languages', 'Amuzgo', 'Language code: amu'), 'amu'),
+ Language(152, translate('common.languages', 'Ancient Greek', 'Language code: grc'), 'grc'),
+ Language(7, translate('common.languages', 'Arabic', 'Language code: ar'), 'ar'),
+ Language(8, translate('common.languages', 'Armenian', 'Language code: hy'), 'hy'),
+ Language(9, translate('common.languages', 'Assamese', 'Language code: as'), 'as'),
+ Language(10, translate('common.languages', 'Aymara', 'Language code: ay'), 'ay'),
+ Language(11, translate('common.languages', 'Azerbaijani', 'Language code: az'), 'az'),
+ Language(12, translate('common.languages', 'Bashkir', 'Language code: ba'), 'ba'),
+ Language(13, translate('common.languages', 'Basque', 'Language code: eu'), 'eu'),
+ Language(14, translate('common.languages', 'Bengali', 'Language code: bn'), 'bn'),
+ Language(15, translate('common.languages', 'Bhutani', 'Language code: dz'), 'dz'),
+ Language(16, translate('common.languages', 'Bihari', 'Language code: bh'), 'bh'),
+ Language(17, translate('common.languages', 'Bislama', 'Language code: bi'), 'bi'),
+ Language(18, translate('common.languages', 'Breton', 'Language code: br'), 'br'),
+ Language(19, translate('common.languages', 'Bulgarian', 'Language code: bg'), 'bg'),
+ Language(20, translate('common.languages', 'Burmese', 'Language code: my'), 'my'),
+ Language(21, translate('common.languages', 'Byelorussian', 'Language code: be'), 'be'),
+ Language(142, translate('common.languages', 'Cakchiquel', 'Language code: cak'), 'cak'),
+ Language(22, translate('common.languages', 'Cambodian', 'Language code: km'), 'km'),
+ Language(23, translate('common.languages', 'Catalan', 'Language code: ca'), 'ca'),
+ Language(24, translate('common.languages', 'Chinese', 'Language code: zh'), 'zh'),
+ Language(141, translate('common.languages', 'Comaltepec Chinantec', 'Language code: cco'), 'cco'),
+ Language(25, translate('common.languages', 'Corsican', 'Language code: co'), 'co'),
+ Language(26, translate('common.languages', 'Croatian', 'Language code: hr'), 'hr'),
+ Language(27, translate('common.languages', 'Czech', 'Language code: cs'), 'cs'),
+ Language(28, translate('common.languages', 'Danish', 'Language code: da'), 'da'),
+ Language(29, translate('common.languages', 'Dutch', 'Language code: nl'), 'nl'),
+ Language(30, translate('common.languages', 'English', 'Language code: en'), 'en'),
+ Language(31, translate('common.languages', 'Esperanto', 'Language code: eo'), 'eo'),
+ Language(32, translate('common.languages', 'Estonian', 'Language code: et'), 'et'),
+ Language(33, translate('common.languages', 'Faeroese', 'Language code: fo'), 'fo'),
+ Language(34, translate('common.languages', 'Fiji', 'Language code: fj'), 'fj'),
+ Language(35, translate('common.languages', 'Finnish', 'Language code: fi'), 'fi'),
+ Language(36, translate('common.languages', 'French', 'Language code: fr'), 'fr'),
+ Language(37, translate('common.languages', 'Frisian', 'Language code: fy'), 'fy'),
+ Language(38, translate('common.languages', 'Galician', 'Language code: gl'), 'gl'),
+ Language(39, translate('common.languages', 'Georgian', 'Language code: ka'), 'ka'),
+ Language(40, translate('common.languages', 'German', 'Language code: de'), 'de'),
+ Language(41, translate('common.languages', 'Greek', 'Language code: el'), 'el'),
+ Language(42, translate('common.languages', 'Greenlandic', 'Language code: kl'), 'kl'),
+ Language(43, translate('common.languages', 'Guarani', 'Language code: gn'), 'gn'),
+ Language(44, translate('common.languages', 'Gujarati', 'Language code: gu'), 'gu'),
+ Language(143, translate('common.languages', 'Haitian Creole', 'Language code: ht'), 'ht'),
+ Language(45, translate('common.languages', 'Hausa', 'Language code: ha'), 'ha'),
+ Language(46, translate('common.languages', 'Hebrew (former iw)', 'Language code: he'), 'he'),
+ Language(144, translate('common.languages', 'Hiligaynon', 'Language code: hil'), 'hil'),
+ Language(47, translate('common.languages', 'Hindi', 'Language code: hi'), 'hi'),
+ Language(48, translate('common.languages', 'Hungarian', 'Language code: hu'), 'hu'),
+ Language(49, translate('common.languages', 'Icelandic', 'Language code: is'), 'is'),
+ Language(50, translate('common.languages', 'Indonesian (former in)', 'Language code: id'), 'id'),
+ Language(51, translate('common.languages', 'Interlingua', 'Language code: ia'), 'ia'),
+ Language(52, translate('common.languages', 'Interlingue', 'Language code: ie'), 'ie'),
+ Language(54, translate('common.languages', 'Inuktitut (Eskimo)', 'Language code: iu'), 'iu'),
+ Language(53, translate('common.languages', 'Inupiak', 'Language code: ik'), 'ik'),
+ Language(55, translate('common.languages', 'Irish', 'Language code: ga'), 'ga'),
+ Language(56, translate('common.languages', 'Italian', 'Language code: it'), 'it'),
+ Language(145, translate('common.languages', 'Jakalteko', 'Language code: jac'), 'jac'),
+ Language(57, translate('common.languages', 'Japanese', 'Language code: ja'), 'ja'),
+ Language(58, translate('common.languages', 'Javanese', 'Language code: jw'), 'jw'),
+ Language(150, translate('common.languages', 'K\'iche\'', 'Language code: quc'), 'quc'),
+ Language(59, translate('common.languages', 'Kannada', 'Language code: kn'), 'kn'),
+ Language(60, translate('common.languages', 'Kashmiri', 'Language code: ks'), 'ks'),
+ Language(61, translate('common.languages', 'Kazakh', 'Language code: kk'), 'kk'),
+ Language(146, translate('common.languages', 'Kekchà ', 'Language code: kek'), 'kek'),
+ Language(62, translate('common.languages', 'Kinyarwanda', 'Language code: rw'), 'rw'),
+ Language(63, translate('common.languages', 'Kirghiz', 'Language code: ky'), 'ky'),
+ Language(64, translate('common.languages', 'Kirundi', 'Language code: rn'), 'rn'),
+ Language(65, translate('common.languages', 'Korean', 'Language code: ko'), 'ko'),
+ Language(66, translate('common.languages', 'Kurdish', 'Language code: ku'), 'ku'),
+ Language(67, translate('common.languages', 'Laothian', 'Language code: lo'), 'lo'),
+ Language(68, translate('common.languages', 'Latin', 'Language code: la'), 'la'),
+ Language(69, translate('common.languages', 'Latvian, Lettish', 'Language code: lv'), 'lv'),
+ Language(70, translate('common.languages', 'Lingala', 'Language code: ln'), 'ln'),
+ Language(71, translate('common.languages', 'Lithuanian', 'Language code: lt'), 'lt'),
+ Language(72, translate('common.languages', 'Macedonian', 'Language code: mk'), 'mk'),
+ Language(73, translate('common.languages', 'Malagasy', 'Language code: mg'), 'mg'),
+ Language(74, translate('common.languages', 'Malay', 'Language code: ms'), 'ms'),
+ Language(75, translate('common.languages', 'Malayalam', 'Language code: ml'), 'ml'),
+ Language(76, translate('common.languages', 'Maltese', 'Language code: mt'), 'mt'),
+ Language(148, translate('common.languages', 'Mam', 'Language code: mam'), 'mam'),
+ Language(77, translate('common.languages', 'Maori', 'Language code: mi'), 'mi'),
+ Language(147, translate('common.languages', 'Maori', 'Language code: mri'), 'mri'),
+ Language(78, translate('common.languages', 'Marathi', 'Language code: mr'), 'mr'),
+ Language(79, translate('common.languages', 'Moldavian', 'Language code: mo'), 'mo'),
+ Language(80, translate('common.languages', 'Mongolian', 'Language code: mn'), 'mn'),
+ Language(149, translate('common.languages', 'Nahuatl', 'Language code: nah'), 'nah'),
+ Language(81, translate('common.languages', 'Nauru', 'Language code: na'), 'na'),
+ Language(82, translate('common.languages', 'Nepali', 'Language code: ne'), 'ne'),
+ Language(83, translate('common.languages', 'Norwegian', 'Language code: no'), 'no'),
+ Language(84, translate('common.languages', 'Occitan', 'Language code: oc'), 'oc'),
+ Language(85, translate('common.languages', 'Oriya', 'Language code: or'), 'or'),
+ Language(86, translate('common.languages', 'Pashto, Pushto', 'Language code: ps'), 'ps'),
+ Language(87, translate('common.languages', 'Persian', 'Language code: fa'), 'fa'),
+ Language(151, translate('common.languages', 'Plautdietsch', 'Language code: pdt'), 'pdt'),
+ Language(88, translate('common.languages', 'Polish', 'Language code: pl'), 'pl'),
+ Language(89, translate('common.languages', 'Portuguese', 'Language code: pt'), 'pt'),
+ Language(90, translate('common.languages', 'Punjabi', 'Language code: pa'), 'pa'),
+ Language(91, translate('common.languages', 'Quechua', 'Language code: qu'), 'qu'),
+ Language(92, translate('common.languages', 'Rhaeto-Romance', 'Language code: rm'), 'rm'),
+ Language(93, translate('common.languages', 'Romanian', 'Language code: ro'), 'ro'),
+ Language(94, translate('common.languages', 'Russian', 'Language code: ru'), 'ru'),
+ Language(95, translate('common.languages', 'Samoan', 'Language code: sm'), 'sm'),
+ Language(96, translate('common.languages', 'Sangro', 'Language code: sg'), 'sg'),
+ Language(97, translate('common.languages', 'Sanskrit', 'Language code: sa'), 'sa'),
+ Language(98, translate('common.languages', 'Scots Gaelic', 'Language code: gd'), 'gd'),
+ Language(99, translate('common.languages', 'Serbian', 'Language code: sr'), 'sr'),
+ Language(100, translate('common.languages', 'Serbo-Croatian', 'Language code: sh'), 'sh'),
+ Language(101, translate('common.languages', 'Sesotho', 'Language code: st'), 'st'),
+ Language(102, translate('common.languages', 'Setswana', 'Language code: tn'), 'tn'),
+ Language(103, translate('common.languages', 'Shona', 'Language code: sn'), 'sn'),
+ Language(104, translate('common.languages', 'Sindhi', 'Language code: sd'), 'sd'),
+ Language(105, translate('common.languages', 'Singhalese', 'Language code: si'), 'si'),
+ Language(106, translate('common.languages', 'Siswati', 'Language code: ss'), 'ss'),
+ Language(107, translate('common.languages', 'Slovak', 'Language code: sk'), 'sk'),
+ Language(108, translate('common.languages', 'Slovenian', 'Language code: sl'), 'sl'),
+ Language(109, translate('common.languages', 'Somali', 'Language code: so'), 'so'),
+ Language(110, translate('common.languages', 'Spanish', 'Language code: es'), 'es'),
+ Language(111, translate('common.languages', 'Sudanese', 'Language code: su'), 'su'),
+ Language(112, translate('common.languages', 'Swahili', 'Language code: sw'), 'sw'),
+ Language(113, translate('common.languages', 'Swedish', 'Language code: sv'), 'sv'),
+ Language(114, translate('common.languages', 'Tagalog', 'Language code: tl'), 'tl'),
+ Language(115, translate('common.languages', 'Tajik', 'Language code: tg'), 'tg'),
+ Language(116, translate('common.languages', 'Tamil', 'Language code: ta'), 'ta'),
+ Language(117, translate('common.languages', 'Tatar', 'Language code: tt'), 'tt'),
+ Language(118, translate('common.languages', 'Tegulu', 'Language code: te'), 'te'),
+ Language(119, translate('common.languages', 'Thai', 'Language code: th'), 'th'),
+ Language(120, translate('common.languages', 'Tibetan', 'Language code: bo'), 'bo'),
+ Language(121, translate('common.languages', 'Tigrinya', 'Language code: ti'), 'ti'),
+ Language(122, translate('common.languages', 'Tonga', 'Language code: to'), 'to'),
+ Language(123, translate('common.languages', 'Tsonga', 'Language code: ts'), 'ts'),
+ Language(124, translate('common.languages', 'Turkish', 'Language code: tr'), 'tr'),
+ Language(125, translate('common.languages', 'Turkmen', 'Language code: tk'), 'tk'),
+ Language(126, translate('common.languages', 'Twi', 'Language code: tw'), 'tw'),
+ Language(127, translate('common.languages', 'Uigur', 'Language code: ug'), 'ug'),
+ Language(128, translate('common.languages', 'Ukrainian', 'Language code: uk'), 'uk'),
+ Language(129, translate('common.languages', 'Urdu', 'Language code: ur'), 'ur'),
+ Language(153, translate('common.languages', 'Uspanteco', 'Language code: usp'), 'usp'),
+ Language(130, translate('common.languages', 'Uzbek', 'Language code: uz'), 'uz'),
+ Language(131, translate('common.languages', 'Vietnamese', 'Language code: vi'), 'vi'),
+ Language(132, translate('common.languages', 'Volapuk', 'Language code: vo'), 'vo'),
+ Language(133, translate('common.languages', 'Welch', 'Language code: cy'), 'cy'),
+ Language(134, translate('common.languages', 'Wolof', 'Language code: wo'), 'wo'),
+ Language(135, translate('common.languages', 'Xhosa', 'Language code: xh'), 'xh'),
+ Language(136, translate('common.languages', 'Yiddish (former ji)', 'Language code: yi'), 'yi'),
+ Language(137, translate('common.languages', 'Yoruba', 'Language code: yo'), 'yo'),
+ Language(138, translate('common.languages', 'Zhuang', 'Language code: za'), 'za'),
+ Language(139, translate('common.languages', 'Zulu', 'Language code: zu'), 'zu')
+], key=lambda language: language.name)
+
+
+class LanguageManager(object):
+ """
+ Helper for Language selection
+ """
+ __qm_list__ = {}
+ auto_language = False
+
+ @staticmethod
+ def get_translators(language):
+ """
+ Set up a translator to use in this instance of OpenLP
+
+ :param language: The language to load into the translator
+ """
+ if LanguageManager.auto_language:
+ language = QtCore.QLocale.system().name()
+ lang_path = str(AppLocation.get_directory(AppLocation.LanguageDir))
+ app_translator = QtCore.QTranslator()
+ app_translator.load(language, lang_path)
+ # A translator for buttons and other default strings provided by Qt.
+ if not is_win() and not is_macosx():
+ lang_path = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)
+ # As of Qt5, the core translations come in 2 files per language
+ default_translator = QtCore.QTranslator()
+ default_translator.load('qt_%s' % language, lang_path)
+ base_translator = QtCore.QTranslator()
+ base_translator.load('qtbase_%s' % language, lang_path)
+ return app_translator, default_translator, base_translator
+
+ @staticmethod
+ def find_qm_files():
+ """
+ Find all available language files in this OpenLP install
+ """
+ log.debug('Translation files: {files}'.format(files=AppLocation.get_directory(AppLocation.LanguageDir)))
+ trans_dir = QtCore.QDir(str(AppLocation.get_directory(AppLocation.LanguageDir)))
+ file_names = trans_dir.entryList(['*.qm'], QtCore.QDir.Files, QtCore.QDir.Name)
+ # Remove qm files from the list which start with "qt".
+ file_names = [file_ for file_ in file_names if not file_.startswith('qt')]
+ return list(map(trans_dir.filePath, file_names))
+
+ @staticmethod
+ def language_name(qm_file):
+ """
+ Load the language name from a language file
+
+ :param qm_file: The file to obtain the name from
+ """
+ translator = QtCore.QTranslator()
+ translator.load(qm_file)
+ return translator.translate('OpenLP.MainWindow', 'English', 'Please add the name of your language here')
+
+ @staticmethod
+ def get_language():
+ """
+ Retrieve a saved language to use from settings
+ """
+ language = Settings().value('core/language')
+ language = str(language)
+ log.info("Language file: '{language}' Loaded from conf file".format(language=language))
+ if re.match(r'[[].*[]]', language):
+ LanguageManager.auto_language = True
+ language = re.sub(r'[\[\]]', '', language)
+ return language
+
+ @staticmethod
+ def set_language(action, message=True):
+ """
+ Set the language to translate OpenLP into
+
+ :param action: The language menu option
+ :param message: Display the message option
+ """
+ language = 'en'
+ if action:
+ action_name = str(action.objectName())
+ if action_name == 'autoLanguageItem':
+ LanguageManager.auto_language = True
+ else:
+ LanguageManager.auto_language = False
+ qm_list = LanguageManager.get_qm_list()
+ language = str(qm_list[action_name])
+ if LanguageManager.auto_language:
+ language = '[{language}]'.format(language=language)
+ Settings().setValue('core/language', language)
+ log.info("Language file: '{language}' written to conf file".format(language=language))
+ if message:
+ QtWidgets.QMessageBox.information(None,
+ translate('OpenLP.LanguageManager', 'Language'),
+ translate('OpenLP.LanguageManager',
+ 'Please restart OpenLP to use your new language setting.'))
+
+ @staticmethod
+ def init_qm_list():
+ """
+ Initialise the list of available translations
+ """
+ LanguageManager.__qm_list__ = {}
+ qm_files = LanguageManager.find_qm_files()
+ for counter, qmf in enumerate(qm_files):
+ reg_ex = QtCore.QRegExp("^.*i18n/(.*).qm")
+ if reg_ex.exactMatch(qmf):
+ name = '{regex}'.format(regex=reg_ex.cap(1))
+ LanguageManager.__qm_list__[
+ '{count:>2d} {name}'.format(count=counter + 1, name=LanguageManager.language_name(qmf))] = name
+
+ @staticmethod
+ def get_qm_list():
+ """
+ Return the list of available translations
+ """
+ if not LanguageManager.__qm_list__:
+ LanguageManager.init_qm_list()
+ return LanguageManager.__qm_list__
+
+
+class UiStrings(object):
+ """
+ Provide standard strings for objects to use.
+ """
+ __instance__ = None
+
+ def __new__(cls):
+ """
+ Override the default object creation method to return a single instance.
+ """
+ if not cls.__instance__:
+ cls.__instance__ = object.__new__(cls)
+ return cls.__instance__
+
+ def __init__(self):
+ """
+ These strings should need a good reason to be retranslated elsewhere.
+ Should some/more/less of these have an & attached?
+ """
+ self.About = translate('OpenLP.Ui', 'About')
+ self.Add = translate('OpenLP.Ui', '&Add')
+ self.AddGroup = translate('OpenLP.Ui', 'Add group')
+ self.AddGroupDot = translate('OpenLP.Ui', 'Add group.')
+ self.Advanced = translate('OpenLP.Ui', 'Advanced')
+ self.AllFiles = translate('OpenLP.Ui', 'All Files')
+ self.Automatic = translate('OpenLP.Ui', 'Automatic')
+ self.BackgroundColor = translate('OpenLP.Ui', 'Background Color')
+ self.BackgroundColorColon = translate('OpenLP.Ui', 'Background color:')
+ self.BibleShortSearchTitle = translate('OpenLP.Ui', 'Search is Empty or too Short')
+ self.BibleShortSearch = translate('OpenLP.Ui', 'The search you have entered is empty or shorter '
+ 'than 3 characters long.
Please try again with '
+ 'a longer search.')
+ self.BibleNoBiblesTitle = translate('OpenLP.Ui', 'No Bibles Available')
+ self.BibleNoBibles = translate('OpenLP.Ui', 'There are no Bibles currently installed.
'
+ 'Please use the Import Wizard to install one or more Bibles.')
+ self.Bottom = translate('OpenLP.Ui', 'Bottom')
+ self.Browse = translate('OpenLP.Ui', 'Browse...')
+ self.Cancel = translate('OpenLP.Ui', 'Cancel')
+ self.CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:')
+ self.CCLISongNumberLabel = translate('OpenLP.Ui', 'CCLI song number:')
+ self.CreateService = translate('OpenLP.Ui', 'Create a new service.')
+ self.ConfirmDelete = translate('OpenLP.Ui', 'Confirm Delete')
+ self.Continuous = translate('OpenLP.Ui', 'Continuous')
+ self.Default = translate('OpenLP.Ui', 'Default')
+ self.DefaultColor = translate('OpenLP.Ui', 'Default Color:')
+ self.DefaultServiceName = translate('OpenLP.Ui', 'Service %Y-%m-%d %H-%M',
+ 'This may not contain any of the following characters: /\\?*|<>[]":+\n'
+ 'See http://docs.python.org/library/datetime'
+ '.html#strftime-strptime-behavior for more information.')
+ self.Delete = translate('OpenLP.Ui', '&Delete')
+ self.DisplayStyle = translate('OpenLP.Ui', 'Display style:')
+ self.Duplicate = translate('OpenLP.Ui', 'Duplicate Error')
+ self.Edit = translate('OpenLP.Ui', '&Edit')
+ self.EmptyField = translate('OpenLP.Ui', 'Empty Field')
+ self.Error = translate('OpenLP.Ui', 'Error')
+ self.Export = translate('OpenLP.Ui', 'Export')
+ self.File = translate('OpenLP.Ui', 'File')
+ self.FontSizePtUnit = translate('OpenLP.Ui', 'pt', 'Abbreviated font pointsize unit')
+ self.Help = translate('OpenLP.Ui', 'Help')
+ self.Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours')
+ self.IFdSs = translate('OpenLP.Ui', 'Invalid Folder Selected', 'Singular')
+ self.IFSs = translate('OpenLP.Ui', 'Invalid File Selected', 'Singular')
+ self.IFSp = translate('OpenLP.Ui', 'Invalid Files Selected', 'Plural')
+ self.Image = translate('OpenLP.Ui', 'Image')
+ self.Import = translate('OpenLP.Ui', 'Import')
+ self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
+ self.Live = translate('OpenLP.Ui', 'Live')
+ self.LiveBGError = translate('OpenLP.Ui', 'Live Background Error')
+ self.LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar')
+ self.Load = translate('OpenLP.Ui', 'Load')
+ self.Manufacturer = translate('OpenLP.Ui', 'Manufacturer', 'Singular')
+ self.Manufacturers = translate('OpenLP.Ui', 'Manufacturers', 'Plural')
+ self.Model = translate('OpenLP.Ui', 'Model', 'Singular')
+ self.Models = translate('OpenLP.Ui', 'Models', 'Plural')
+ self.Minutes = translate('OpenLP.Ui', 'm', 'The abbreviated unit for minutes')
+ self.Middle = translate('OpenLP.Ui', 'Middle')
+ self.New = translate('OpenLP.Ui', 'New')
+ self.NewService = translate('OpenLP.Ui', 'New Service')
+ self.NewTheme = translate('OpenLP.Ui', 'New Theme')
+ self.NextTrack = translate('OpenLP.Ui', 'Next Track')
+ self.NFdSs = translate('OpenLP.Ui', 'No Folder Selected', 'Singular')
+ self.NFSs = translate('OpenLP.Ui', 'No File Selected', 'Singular')
+ self.NFSp = translate('OpenLP.Ui', 'No Files Selected', 'Plural')
+ self.NISs = translate('OpenLP.Ui', 'No Item Selected', 'Singular')
+ self.NISp = translate('OpenLP.Ui', 'No Items Selected', 'Plural')
+ self.NoResults = translate('OpenLP.Ui', 'No Search Results')
+ self.OpenLP = translate('OpenLP.Ui', 'OpenLP')
+ self.OpenLPv2AndUp = translate('OpenLP.Ui', 'OpenLP 2.0 and up')
+ self.OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. Do you wish to continue?')
+ self.OpenService = translate('OpenLP.Ui', 'Open service.')
+ self.OptionalShowInFooter = translate('OpenLP.Ui', 'Optional, this will be displayed in footer.')
+ self.OptionalHideInFooter = translate('OpenLP.Ui', 'Optional, this won\'t be displayed in footer.')
+ self.PlaySlidesInLoop = translate('OpenLP.Ui', 'Play Slides in Loop')
+ self.PlaySlidesToEnd = translate('OpenLP.Ui', 'Play Slides to End')
+ self.Preview = translate('OpenLP.Ui', 'Preview')
+ self.PreviewToolbar = translate('OpenLP.Ui', 'Preview Toolbar')
+ self.PrintService = translate('OpenLP.Ui', 'Print Service')
+ self.Projector = translate('OpenLP.Ui', 'Projector', 'Singular')
+ self.Projectors = translate('OpenLP.Ui', 'Projectors', 'Plural')
+ self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
+ self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace live background.')
+ self.ReplaceLiveBGDisabled = translate('OpenLP.Ui', 'Replace live background is not available when the WebKit '
+ 'player is disabled.')
+ self.ResetBG = translate('OpenLP.Ui', 'Reset Background')
+ self.ResetLiveBG = translate('OpenLP.Ui', 'Reset live background.')
+ self.RequiredShowInFooter = translate('OpenLP.Ui', 'Required, this will be displayed in footer.')
+ self.Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds')
+ self.SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview')
+ self.Search = translate('OpenLP.Ui', 'Search')
+ self.SearchThemes = translate('OpenLP.Ui', 'Search Themes...', 'Search bar place holder text ')
+ self.SelectDelete = translate('OpenLP.Ui', 'You must select an item to delete.')
+ self.SelectEdit = translate('OpenLP.Ui', 'You must select an item to edit.')
+ self.Settings = translate('OpenLP.Ui', 'Settings')
+ self.SaveService = translate('OpenLP.Ui', 'Save Service')
+ self.Service = translate('OpenLP.Ui', 'Service')
+ self.ShortResults = translate('OpenLP.Ui', 'Please type more text to use \'Search As You Type\'')
+ 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.')
+ self.StartingImport = translate('OpenLP.Ui', 'Starting import...')
+ 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')
+ self.Themes = translate('OpenLP.Ui', 'Themes', 'Plural')
+ self.Tools = translate('OpenLP.Ui', 'Tools')
+ self.Top = translate('OpenLP.Ui', 'Top')
+ self.UnsupportedFile = translate('OpenLP.Ui', 'Unsupported File')
+ self.VersePerSlide = translate('OpenLP.Ui', 'Verse Per Slide')
+ self.VersePerLine = translate('OpenLP.Ui', 'Verse Per Line')
+ self.Version = translate('OpenLP.Ui', 'Version')
+ self.View = translate('OpenLP.Ui', 'View')
+ self.ViewMode = translate('OpenLP.Ui', 'View Mode')
+ self.Video = translate('OpenLP.Ui', 'Video')
+ self.WebDownloadText = translate('OpenLP.Ui', 'Web Interface, Download and Install latest Version')
+ book_chapter = translate('OpenLP.Ui', 'Book Chapter')
+ chapter = translate('OpenLP.Ui', 'Chapter')
+ verse = translate('OpenLP.Ui', 'Verse')
+ gap = ' | '
+ psalm = translate('OpenLP.Ui', 'Psalm')
+ may_shorten = translate('OpenLP.Ui', 'Book names may be shortened from full names, for an example Ps 23 = '
+ 'Psalm 23')
+ bible_scripture_items = \
+ [book_chapter, gap, psalm, ' 23
',
+ book_chapter, '%(range)s', chapter, gap, psalm, ' 23%(range)s24
',
+ book_chapter, '%(verse)s', verse, '%(range)s', verse, gap, psalm, ' 23%(verse)s1%(range)s2
',
+ book_chapter, '%(verse)s', verse, '%(range)s', verse, '%(list)s', verse, '%(range)s', verse, gap, psalm,
+ ' 23%(verse)s1%(range)s2%(list)s5%(range)s6
',
+ book_chapter, '%(verse)s', verse, '%(range)s', verse, '%(list)s', chapter, '%(verse)s', verse, '%(range)s',
+ verse, gap, psalm, ' 23%(verse)s1%(range)s2%(list)s24%(verse)s1%(range)s3
',
+ book_chapter, '%(verse)s', verse, '%(range)s', chapter, '%(verse)s', verse, gap, psalm,
+ ' 23%(verse)s1%(range)s24%(verse)s1
', may_shorten]
+ itertools.chain.from_iterable(itertools.repeat(strings, 1) if isinstance(strings, str)
+ else strings for strings in bible_scripture_items)
+ self.BibleScriptureError = ''.join(str(joined) for joined in bible_scripture_items)
+
+
+def format_time(text, local_time):
+ """
+ Workaround for Python built-in time formatting function time.strftime().
+
+ time.strftime() accepts only ascii characters. This function accepts
+ unicode string and passes individual % placeholders to time.strftime().
+ This ensures only ascii characters are passed to time.strftime().
+
+ :param text: The text to be processed.
+ :param local_time: The time to be used to add to the string. This is a time object
+ """
+
+ def match_formatting(match):
+ """
+ Format the match
+ """
+ return local_time.strftime(match.group())
+
+ return re.sub(r'\%[a-zA-Z]', match_formatting, text)
+
+
+def get_locale_key(string):
+ """
+ Creates a key for case insensitive, locale aware string sorting.
+
+ :param string: The corresponding string.
+ """
+ string = string.lower()
+ # ICU is the prefered way to handle locale sort key, we fallback to locale.strxfrm which will work in most cases.
+ global ICU_COLLATOR
+ try:
+ if ICU_COLLATOR is None:
+ import icu
+ language = LanguageManager.get_language()
+ icu_locale = icu.Locale(language)
+ ICU_COLLATOR = icu.Collator.createInstance(icu_locale)
+ return ICU_COLLATOR.getSortKey(string)
+ except:
+ return locale.strxfrm(string).encode()
+
+
+def get_natural_key(string):
+ """
+ Generate a key for locale aware natural string sorting.
+
+ :param string: string to be sorted by
+ Returns a list of string compare keys and integers.
+ """
+ key = DIGITS_OR_NONDIGITS.findall(string)
+ key = [int(part) if part.isdigit() else get_locale_key(part) for part in key]
+ # Python 3 does not support comparison of different types anymore. So make sure, that we do not compare str
+ # and int.
+ if string and string[0].isdigit():
+ return [b''] + key
+ return key
+
+
+def get_language(name):
+ """
+ Find the language by its name or code.
+
+ :param name: The name or abbreviation of the language.
+ :return: The first match as a Language namedtuple or None
+ """
+ if name:
+ name_lower = name.lower()
+ name_title = name_lower[:1].upper() + name_lower[1:]
+ for language in LANGUAGES:
+ if language.name == name_title or language.code == name_lower:
+ return language
+ return None
diff --git a/openlp/core/common/languagemanager.py b/openlp/core/common/languagemanager.py
deleted file mode 100644
index 40e4930fb..000000000
--- a/openlp/core/common/languagemanager.py
+++ /dev/null
@@ -1,210 +0,0 @@
-# -*- 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:`languagemanager` module provides all the translation settings and language file loading for OpenLP.
-"""
-import locale
-import logging
-import re
-
-from PyQt5 import QtCore, QtWidgets
-
-
-from openlp.core.common import AppLocation, Settings, translate, is_win, is_macosx
-
-log = logging.getLogger(__name__)
-
-ICU_COLLATOR = None
-DIGITS_OR_NONDIGITS = re.compile(r'\d+|\D+', re.UNICODE)
-
-
-class LanguageManager(object):
- """
- Helper for Language selection
- """
- __qm_list__ = {}
- auto_language = False
-
- @staticmethod
- def get_translators(language):
- """
- Set up a translator to use in this instance of OpenLP
-
- :param language: The language to load into the translator
- """
- if LanguageManager.auto_language:
- language = QtCore.QLocale.system().name()
- lang_path = str(AppLocation.get_directory(AppLocation.LanguageDir))
- app_translator = QtCore.QTranslator()
- app_translator.load(language, lang_path)
- # A translator for buttons and other default strings provided by Qt.
- if not is_win() and not is_macosx():
- lang_path = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)
- # As of Qt5, the core translations come in 2 files per language
- default_translator = QtCore.QTranslator()
- default_translator.load('qt_%s' % language, lang_path)
- base_translator = QtCore.QTranslator()
- base_translator.load('qtbase_%s' % language, lang_path)
- return app_translator, default_translator, base_translator
-
- @staticmethod
- def find_qm_files():
- """
- Find all available language files in this OpenLP install
- """
- log.debug('Translation files: {files}'.format(files=AppLocation.get_directory(AppLocation.LanguageDir)))
- trans_dir = QtCore.QDir(str(AppLocation.get_directory(AppLocation.LanguageDir)))
- file_names = trans_dir.entryList(['*.qm'], QtCore.QDir.Files, QtCore.QDir.Name)
- # Remove qm files from the list which start with "qt".
- file_names = [file_ for file_ in file_names if not file_.startswith('qt')]
- return list(map(trans_dir.filePath, file_names))
-
- @staticmethod
- def language_name(qm_file):
- """
- Load the language name from a language file
-
- :param qm_file: The file to obtain the name from
- """
- translator = QtCore.QTranslator()
- translator.load(qm_file)
- return translator.translate('OpenLP.MainWindow', 'English', 'Please add the name of your language here')
-
- @staticmethod
- def get_language():
- """
- Retrieve a saved language to use from settings
- """
- language = Settings().value('core/language')
- language = str(language)
- log.info("Language file: '{language}' Loaded from conf file".format(language=language))
- if re.match(r'[[].*[]]', language):
- LanguageManager.auto_language = True
- language = re.sub(r'[\[\]]', '', language)
- return language
-
- @staticmethod
- def set_language(action, message=True):
- """
- Set the language to translate OpenLP into
-
- :param action: The language menu option
- :param message: Display the message option
- """
- language = 'en'
- if action:
- action_name = str(action.objectName())
- if action_name == 'autoLanguageItem':
- LanguageManager.auto_language = True
- else:
- LanguageManager.auto_language = False
- qm_list = LanguageManager.get_qm_list()
- language = str(qm_list[action_name])
- if LanguageManager.auto_language:
- language = '[{language}]'.format(language=language)
- Settings().setValue('core/language', language)
- log.info("Language file: '{language}' written to conf file".format(language=language))
- if message:
- QtWidgets.QMessageBox.information(None,
- translate('OpenLP.LanguageManager', 'Language'),
- translate('OpenLP.LanguageManager',
- 'Please restart OpenLP to use your new language setting.'))
-
- @staticmethod
- def init_qm_list():
- """
- Initialise the list of available translations
- """
- LanguageManager.__qm_list__ = {}
- qm_files = LanguageManager.find_qm_files()
- for counter, qmf in enumerate(qm_files):
- reg_ex = QtCore.QRegExp("^.*i18n/(.*).qm")
- if reg_ex.exactMatch(qmf):
- name = '{regex}'.format(regex=reg_ex.cap(1))
- LanguageManager.__qm_list__[
- '{count:>2d} {name}'.format(count=counter + 1, name=LanguageManager.language_name(qmf))] = name
-
- @staticmethod
- def get_qm_list():
- """
- Return the list of available translations
- """
- if not LanguageManager.__qm_list__:
- LanguageManager.init_qm_list()
- return LanguageManager.__qm_list__
-
-
-def format_time(text, local_time):
- """
- Workaround for Python built-in time formatting function time.strftime().
-
- time.strftime() accepts only ascii characters. This function accepts
- unicode string and passes individual % placeholders to time.strftime().
- This ensures only ascii characters are passed to time.strftime().
-
- :param text: The text to be processed.
- :param local_time: The time to be used to add to the string. This is a time object
- """
-
- def match_formatting(match):
- """
- Format the match
- """
- return local_time.strftime(match.group())
-
- return re.sub(r'\%[a-zA-Z]', match_formatting, text)
-
-
-def get_locale_key(string):
- """
- Creates a key for case insensitive, locale aware string sorting.
-
- :param string: The corresponding string.
- """
- string = string.lower()
- # ICU is the prefered way to handle locale sort key, we fallback to locale.strxfrm which will work in most cases.
- global ICU_COLLATOR
- try:
- if ICU_COLLATOR is None:
- import icu
- language = LanguageManager.get_language()
- icu_locale = icu.Locale(language)
- ICU_COLLATOR = icu.Collator.createInstance(icu_locale)
- return ICU_COLLATOR.getSortKey(string)
- except:
- return locale.strxfrm(string).encode()
-
-
-def get_natural_key(string):
- """
- Generate a key for locale aware natural string sorting.
-
- :param string: string to be sorted by
- Returns a list of string compare keys and integers.
- """
- key = DIGITS_OR_NONDIGITS.findall(string)
- key = [int(part) if part.isdigit() else get_locale_key(part) for part in key]
- # Python 3 does not support comparison of different types anymore. So make sure, that we do not compare str
- # and int.
- if string and string[0].isdigit():
- return [b''] + key
- return key
diff --git a/openlp/core/common/languages.py b/openlp/core/common/languages.py
deleted file mode 100644
index 77d0b1558..000000000
--- a/openlp/core/common/languages.py
+++ /dev/null
@@ -1,201 +0,0 @@
-# -*- 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:`languages` module provides a list of language names with utility functions.
-"""
-from collections import namedtuple
-
-from openlp.core.common import translate
-
-
-Language = namedtuple('Language', ['id', 'name', 'code'])
-languages = sorted([
- Language(1, translate('common.languages', '(Afan) Oromo', 'Language code: om'), 'om'),
- Language(2, translate('common.languages', 'Abkhazian', 'Language code: ab'), 'ab'),
- Language(3, translate('common.languages', 'Afar', 'Language code: aa'), 'aa'),
- Language(4, translate('common.languages', 'Afrikaans', 'Language code: af'), 'af'),
- Language(5, translate('common.languages', 'Albanian', 'Language code: sq'), 'sq'),
- Language(6, translate('common.languages', 'Amharic', 'Language code: am'), 'am'),
- Language(140, translate('common.languages', 'Amuzgo', 'Language code: amu'), 'amu'),
- Language(152, translate('common.languages', 'Ancient Greek', 'Language code: grc'), 'grc'),
- Language(7, translate('common.languages', 'Arabic', 'Language code: ar'), 'ar'),
- Language(8, translate('common.languages', 'Armenian', 'Language code: hy'), 'hy'),
- Language(9, translate('common.languages', 'Assamese', 'Language code: as'), 'as'),
- Language(10, translate('common.languages', 'Aymara', 'Language code: ay'), 'ay'),
- Language(11, translate('common.languages', 'Azerbaijani', 'Language code: az'), 'az'),
- Language(12, translate('common.languages', 'Bashkir', 'Language code: ba'), 'ba'),
- Language(13, translate('common.languages', 'Basque', 'Language code: eu'), 'eu'),
- Language(14, translate('common.languages', 'Bengali', 'Language code: bn'), 'bn'),
- Language(15, translate('common.languages', 'Bhutani', 'Language code: dz'), 'dz'),
- Language(16, translate('common.languages', 'Bihari', 'Language code: bh'), 'bh'),
- Language(17, translate('common.languages', 'Bislama', 'Language code: bi'), 'bi'),
- Language(18, translate('common.languages', 'Breton', 'Language code: br'), 'br'),
- Language(19, translate('common.languages', 'Bulgarian', 'Language code: bg'), 'bg'),
- Language(20, translate('common.languages', 'Burmese', 'Language code: my'), 'my'),
- Language(21, translate('common.languages', 'Byelorussian', 'Language code: be'), 'be'),
- Language(142, translate('common.languages', 'Cakchiquel', 'Language code: cak'), 'cak'),
- Language(22, translate('common.languages', 'Cambodian', 'Language code: km'), 'km'),
- Language(23, translate('common.languages', 'Catalan', 'Language code: ca'), 'ca'),
- Language(24, translate('common.languages', 'Chinese', 'Language code: zh'), 'zh'),
- Language(141, translate('common.languages', 'Comaltepec Chinantec', 'Language code: cco'), 'cco'),
- Language(25, translate('common.languages', 'Corsican', 'Language code: co'), 'co'),
- Language(26, translate('common.languages', 'Croatian', 'Language code: hr'), 'hr'),
- Language(27, translate('common.languages', 'Czech', 'Language code: cs'), 'cs'),
- Language(28, translate('common.languages', 'Danish', 'Language code: da'), 'da'),
- Language(29, translate('common.languages', 'Dutch', 'Language code: nl'), 'nl'),
- Language(30, translate('common.languages', 'English', 'Language code: en'), 'en'),
- Language(31, translate('common.languages', 'Esperanto', 'Language code: eo'), 'eo'),
- Language(32, translate('common.languages', 'Estonian', 'Language code: et'), 'et'),
- Language(33, translate('common.languages', 'Faeroese', 'Language code: fo'), 'fo'),
- Language(34, translate('common.languages', 'Fiji', 'Language code: fj'), 'fj'),
- Language(35, translate('common.languages', 'Finnish', 'Language code: fi'), 'fi'),
- Language(36, translate('common.languages', 'French', 'Language code: fr'), 'fr'),
- Language(37, translate('common.languages', 'Frisian', 'Language code: fy'), 'fy'),
- Language(38, translate('common.languages', 'Galician', 'Language code: gl'), 'gl'),
- Language(39, translate('common.languages', 'Georgian', 'Language code: ka'), 'ka'),
- Language(40, translate('common.languages', 'German', 'Language code: de'), 'de'),
- Language(41, translate('common.languages', 'Greek', 'Language code: el'), 'el'),
- Language(42, translate('common.languages', 'Greenlandic', 'Language code: kl'), 'kl'),
- Language(43, translate('common.languages', 'Guarani', 'Language code: gn'), 'gn'),
- Language(44, translate('common.languages', 'Gujarati', 'Language code: gu'), 'gu'),
- Language(143, translate('common.languages', 'Haitian Creole', 'Language code: ht'), 'ht'),
- Language(45, translate('common.languages', 'Hausa', 'Language code: ha'), 'ha'),
- Language(46, translate('common.languages', 'Hebrew (former iw)', 'Language code: he'), 'he'),
- Language(144, translate('common.languages', 'Hiligaynon', 'Language code: hil'), 'hil'),
- Language(47, translate('common.languages', 'Hindi', 'Language code: hi'), 'hi'),
- Language(48, translate('common.languages', 'Hungarian', 'Language code: hu'), 'hu'),
- Language(49, translate('common.languages', 'Icelandic', 'Language code: is'), 'is'),
- Language(50, translate('common.languages', 'Indonesian (former in)', 'Language code: id'), 'id'),
- Language(51, translate('common.languages', 'Interlingua', 'Language code: ia'), 'ia'),
- Language(52, translate('common.languages', 'Interlingue', 'Language code: ie'), 'ie'),
- Language(54, translate('common.languages', 'Inuktitut (Eskimo)', 'Language code: iu'), 'iu'),
- Language(53, translate('common.languages', 'Inupiak', 'Language code: ik'), 'ik'),
- Language(55, translate('common.languages', 'Irish', 'Language code: ga'), 'ga'),
- Language(56, translate('common.languages', 'Italian', 'Language code: it'), 'it'),
- Language(145, translate('common.languages', 'Jakalteko', 'Language code: jac'), 'jac'),
- Language(57, translate('common.languages', 'Japanese', 'Language code: ja'), 'ja'),
- Language(58, translate('common.languages', 'Javanese', 'Language code: jw'), 'jw'),
- Language(150, translate('common.languages', 'K\'iche\'', 'Language code: quc'), 'quc'),
- Language(59, translate('common.languages', 'Kannada', 'Language code: kn'), 'kn'),
- Language(60, translate('common.languages', 'Kashmiri', 'Language code: ks'), 'ks'),
- Language(61, translate('common.languages', 'Kazakh', 'Language code: kk'), 'kk'),
- Language(146, translate('common.languages', 'Kekchà ', 'Language code: kek'), 'kek'),
- Language(62, translate('common.languages', 'Kinyarwanda', 'Language code: rw'), 'rw'),
- Language(63, translate('common.languages', 'Kirghiz', 'Language code: ky'), 'ky'),
- Language(64, translate('common.languages', 'Kirundi', 'Language code: rn'), 'rn'),
- Language(65, translate('common.languages', 'Korean', 'Language code: ko'), 'ko'),
- Language(66, translate('common.languages', 'Kurdish', 'Language code: ku'), 'ku'),
- Language(67, translate('common.languages', 'Laothian', 'Language code: lo'), 'lo'),
- Language(68, translate('common.languages', 'Latin', 'Language code: la'), 'la'),
- Language(69, translate('common.languages', 'Latvian, Lettish', 'Language code: lv'), 'lv'),
- Language(70, translate('common.languages', 'Lingala', 'Language code: ln'), 'ln'),
- Language(71, translate('common.languages', 'Lithuanian', 'Language code: lt'), 'lt'),
- Language(72, translate('common.languages', 'Macedonian', 'Language code: mk'), 'mk'),
- Language(73, translate('common.languages', 'Malagasy', 'Language code: mg'), 'mg'),
- Language(74, translate('common.languages', 'Malay', 'Language code: ms'), 'ms'),
- Language(75, translate('common.languages', 'Malayalam', 'Language code: ml'), 'ml'),
- Language(76, translate('common.languages', 'Maltese', 'Language code: mt'), 'mt'),
- Language(148, translate('common.languages', 'Mam', 'Language code: mam'), 'mam'),
- Language(77, translate('common.languages', 'Maori', 'Language code: mi'), 'mi'),
- Language(147, translate('common.languages', 'Maori', 'Language code: mri'), 'mri'),
- Language(78, translate('common.languages', 'Marathi', 'Language code: mr'), 'mr'),
- Language(79, translate('common.languages', 'Moldavian', 'Language code: mo'), 'mo'),
- Language(80, translate('common.languages', 'Mongolian', 'Language code: mn'), 'mn'),
- Language(149, translate('common.languages', 'Nahuatl', 'Language code: nah'), 'nah'),
- Language(81, translate('common.languages', 'Nauru', 'Language code: na'), 'na'),
- Language(82, translate('common.languages', 'Nepali', 'Language code: ne'), 'ne'),
- Language(83, translate('common.languages', 'Norwegian', 'Language code: no'), 'no'),
- Language(84, translate('common.languages', 'Occitan', 'Language code: oc'), 'oc'),
- Language(85, translate('common.languages', 'Oriya', 'Language code: or'), 'or'),
- Language(86, translate('common.languages', 'Pashto, Pushto', 'Language code: ps'), 'ps'),
- Language(87, translate('common.languages', 'Persian', 'Language code: fa'), 'fa'),
- Language(151, translate('common.languages', 'Plautdietsch', 'Language code: pdt'), 'pdt'),
- Language(88, translate('common.languages', 'Polish', 'Language code: pl'), 'pl'),
- Language(89, translate('common.languages', 'Portuguese', 'Language code: pt'), 'pt'),
- Language(90, translate('common.languages', 'Punjabi', 'Language code: pa'), 'pa'),
- Language(91, translate('common.languages', 'Quechua', 'Language code: qu'), 'qu'),
- Language(92, translate('common.languages', 'Rhaeto-Romance', 'Language code: rm'), 'rm'),
- Language(93, translate('common.languages', 'Romanian', 'Language code: ro'), 'ro'),
- Language(94, translate('common.languages', 'Russian', 'Language code: ru'), 'ru'),
- Language(95, translate('common.languages', 'Samoan', 'Language code: sm'), 'sm'),
- Language(96, translate('common.languages', 'Sangro', 'Language code: sg'), 'sg'),
- Language(97, translate('common.languages', 'Sanskrit', 'Language code: sa'), 'sa'),
- Language(98, translate('common.languages', 'Scots Gaelic', 'Language code: gd'), 'gd'),
- Language(99, translate('common.languages', 'Serbian', 'Language code: sr'), 'sr'),
- Language(100, translate('common.languages', 'Serbo-Croatian', 'Language code: sh'), 'sh'),
- Language(101, translate('common.languages', 'Sesotho', 'Language code: st'), 'st'),
- Language(102, translate('common.languages', 'Setswana', 'Language code: tn'), 'tn'),
- Language(103, translate('common.languages', 'Shona', 'Language code: sn'), 'sn'),
- Language(104, translate('common.languages', 'Sindhi', 'Language code: sd'), 'sd'),
- Language(105, translate('common.languages', 'Singhalese', 'Language code: si'), 'si'),
- Language(106, translate('common.languages', 'Siswati', 'Language code: ss'), 'ss'),
- Language(107, translate('common.languages', 'Slovak', 'Language code: sk'), 'sk'),
- Language(108, translate('common.languages', 'Slovenian', 'Language code: sl'), 'sl'),
- Language(109, translate('common.languages', 'Somali', 'Language code: so'), 'so'),
- Language(110, translate('common.languages', 'Spanish', 'Language code: es'), 'es'),
- Language(111, translate('common.languages', 'Sudanese', 'Language code: su'), 'su'),
- Language(112, translate('common.languages', 'Swahili', 'Language code: sw'), 'sw'),
- Language(113, translate('common.languages', 'Swedish', 'Language code: sv'), 'sv'),
- Language(114, translate('common.languages', 'Tagalog', 'Language code: tl'), 'tl'),
- Language(115, translate('common.languages', 'Tajik', 'Language code: tg'), 'tg'),
- Language(116, translate('common.languages', 'Tamil', 'Language code: ta'), 'ta'),
- Language(117, translate('common.languages', 'Tatar', 'Language code: tt'), 'tt'),
- Language(118, translate('common.languages', 'Tegulu', 'Language code: te'), 'te'),
- Language(119, translate('common.languages', 'Thai', 'Language code: th'), 'th'),
- Language(120, translate('common.languages', 'Tibetan', 'Language code: bo'), 'bo'),
- Language(121, translate('common.languages', 'Tigrinya', 'Language code: ti'), 'ti'),
- Language(122, translate('common.languages', 'Tonga', 'Language code: to'), 'to'),
- Language(123, translate('common.languages', 'Tsonga', 'Language code: ts'), 'ts'),
- Language(124, translate('common.languages', 'Turkish', 'Language code: tr'), 'tr'),
- Language(125, translate('common.languages', 'Turkmen', 'Language code: tk'), 'tk'),
- Language(126, translate('common.languages', 'Twi', 'Language code: tw'), 'tw'),
- Language(127, translate('common.languages', 'Uigur', 'Language code: ug'), 'ug'),
- Language(128, translate('common.languages', 'Ukrainian', 'Language code: uk'), 'uk'),
- Language(129, translate('common.languages', 'Urdu', 'Language code: ur'), 'ur'),
- Language(153, translate('common.languages', 'Uspanteco', 'Language code: usp'), 'usp'),
- Language(130, translate('common.languages', 'Uzbek', 'Language code: uz'), 'uz'),
- Language(131, translate('common.languages', 'Vietnamese', 'Language code: vi'), 'vi'),
- Language(132, translate('common.languages', 'Volapuk', 'Language code: vo'), 'vo'),
- Language(133, translate('common.languages', 'Welch', 'Language code: cy'), 'cy'),
- Language(134, translate('common.languages', 'Wolof', 'Language code: wo'), 'wo'),
- Language(135, translate('common.languages', 'Xhosa', 'Language code: xh'), 'xh'),
- Language(136, translate('common.languages', 'Yiddish (former ji)', 'Language code: yi'), 'yi'),
- Language(137, translate('common.languages', 'Yoruba', 'Language code: yo'), 'yo'),
- Language(138, translate('common.languages', 'Zhuang', 'Language code: za'), 'za'),
- Language(139, translate('common.languages', 'Zulu', 'Language code: zu'), 'zu')
-], key=lambda language: language.name)
-
-
-def get_language(name):
- """
- Find the language by its name or code.
-
- :param name: The name or abbreviation of the language.
- :return: The first match as a Language namedtuple or None
- """
- if name:
- name_lower = name.lower()
- name_title = name_lower[:1].upper() + name_lower[1:]
- for language in languages:
- if language.name == name_title or language.code == name_lower:
- return language
- return None
diff --git a/openlp/core/common/openlpmixin.py b/openlp/core/common/mixins.py
similarity index 80%
rename from openlp/core/common/openlpmixin.py
rename to openlp/core/common/mixins.py
index 0e63a339c..6a39b8f2c 100644
--- a/openlp/core/common/openlpmixin.py
+++ b/openlp/core/common/mixins.py
@@ -25,7 +25,8 @@ Provide Error Handling and login Services
import logging
import inspect
-from openlp.core.common import trace_error_handler
+from openlp.core.common import trace_error_handler, de_hump
+from openlp.core.common.registry import Registry
DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent', 'drag_enter_event', 'drop_event', 'on_controller_size_changed',
'preview_size_changed', 'resizeEvent']
@@ -90,3 +91,32 @@ class OpenLPMixin(object):
"""
trace_error_handler(self.logger)
self.logger.exception(message)
+
+
+class RegistryMixin(object):
+ """
+ This adds registry components to classes to use at run time.
+ """
+ def __init__(self, parent):
+ """
+ Register the class and bootstrap hooks.
+ """
+ try:
+ super(RegistryMixin, self).__init__(parent)
+ except TypeError:
+ super(RegistryMixin, self).__init__()
+ Registry().register(de_hump(self.__class__.__name__), self)
+ Registry().register_function('bootstrap_initialise', self.bootstrap_initialise)
+ Registry().register_function('bootstrap_post_set_up', self.bootstrap_post_set_up)
+
+ def bootstrap_initialise(self):
+ """
+ Dummy method to be overridden
+ """
+ pass
+
+ def bootstrap_post_set_up(self):
+ """
+ Dummy method to be overridden
+ """
+ pass
diff --git a/openlp/core/common/path.py b/openlp/core/common/path.py
index cdb115940..19e17470b 100644
--- a/openlp/core/common/path.py
+++ b/openlp/core/common/path.py
@@ -19,6 +19,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
+import logging
import shutil
from contextlib import suppress
@@ -29,6 +30,45 @@ if is_win():
else:
from pathlib import PosixPath as PathVariant
+log = logging.getLogger(__name__)
+
+
+class Path(PathVariant):
+ """
+ Subclass pathlib.Path, so we can add json conversion methods
+ """
+ @staticmethod
+ def encode_json(obj, base_path=None, **kwargs):
+ """
+ Create a Path object from a dictionary representation. The dictionary has been constructed by JSON encoding of
+ a JSON reprensation of a Path object.
+
+ :param dict[str] obj: The dictionary representation
+ :param openlp.core.common.path.Path base_path: If specified, an absolute path to base the relative path off of.
+ :param kwargs: Contains any extra parameters. Not used!
+ :return: The reconstructed Path object
+ :rtype: openlp.core.common.path.Path
+ """
+ path = Path(*obj['__Path__'])
+ if base_path and not path.is_absolute():
+ return base_path / path
+ return path
+
+ def json_object(self, base_path=None, **kwargs):
+ """
+ Create a dictionary that can be JSON decoded.
+
+ :param openlp.core.common.path.Path base_path: If specified, an absolute path to make a relative path from.
+ :param kwargs: Contains any extra parameters. Not used!
+ :return: The dictionary representation of this Path object.
+ :rtype: dict[tuple]
+ """
+ path = self
+ if base_path:
+ with suppress(ValueError):
+ path = path.relative_to(base_path)
+ return {'__Path__': path.parts}
+
def replace_params(args, kwargs, params):
"""
@@ -179,38 +219,32 @@ def str_to_path(string):
return Path(string)
-class Path(PathVariant):
+def create_paths(*paths, **kwargs):
"""
- Subclass pathlib.Path, so we can add json conversion methods
+ Create one or more paths
+
+ :param openlp.core.common.path.Path paths: The paths to create
+ :param bool do_not_log: To not log anything. This is need for the start up, when the log isn't ready.
+ :rtype: None
"""
- @staticmethod
- def encode_json(obj, base_path=None, **kwargs):
- """
- Create a Path object from a dictionary representation. The dictionary has been constructed by JSON encoding of
- a JSON reprensation of a Path object.
+ for path in paths:
+ if not kwargs.get('do_not_log', False):
+ log.debug('create_path {path}'.format(path=path))
+ try:
+ if not path.exists():
+ path.mkdir(parents=True)
+ except IOError:
+ if not kwargs.get('do_not_log', False):
+ log.exception('failed to check if directory exists or create directory')
- :param dict[str] obj: The dictionary representation
- :param openlp.core.common.path.Path base_path: If specified, an absolute path to base the relative path off of.
- :param kwargs: Contains any extra parameters. Not used!
- :return: The reconstructed Path object
- :rtype: openlp.core.common.path.Path
- """
- path = Path(*obj['__Path__'])
- if base_path and not path.is_absolute():
- return base_path / path
- return path
- def json_object(self, base_path=None, **kwargs):
- """
- Create a dictionary that can be JSON decoded.
+def files_to_paths(file_names):
+ """
+ Convert a list of file names in to a list of file paths.
- :param openlp.core.common.path.Path base_path: If specified, an absolute path to make a relative path from.
- :param kwargs: Contains any extra parameters. Not used!
- :return: The dictionary representation of this Path object.
- :rtype: dict[tuple]
- """
- path = self
- if base_path:
- with suppress(ValueError):
- path = path.relative_to(base_path)
- return {'__Path__': path.parts}
+ :param list[str] file_names: The list of file names to convert.
+ :return: The list converted to file paths
+ :rtype: openlp.core.common.path.Path
+ """
+ if file_names:
+ return [str_to_path(file_name) for file_name in file_names]
diff --git a/openlp/core/common/registry.py b/openlp/core/common/registry.py
index be9183a2f..f01c41b0b 100644
--- a/openlp/core/common/registry.py
+++ b/openlp/core/common/registry.py
@@ -25,7 +25,7 @@ Provide Registry Services
import logging
import sys
-from openlp.core.common import trace_error_handler
+from openlp.core.common import is_win, trace_error_handler
log = logging.getLogger(__name__)
@@ -176,3 +176,130 @@ class Registry(object):
"""
if key in self.working_flags:
del self.working_flags[key]
+
+
+class RegistryProperties(object):
+ """
+ This adds registry components to classes to use at run time.
+ """
+
+ @property
+ def application(self):
+ """
+ Adds the openlp to the class dynamically.
+ Windows needs to access the application in a dynamic manner.
+ """
+ if is_win():
+ return Registry().get('application')
+ else:
+ if not hasattr(self, '_application') or not self._application:
+ self._application = Registry().get('application')
+ return self._application
+
+ @property
+ def plugin_manager(self):
+ """
+ Adds the plugin manager to the class dynamically
+ """
+ if not hasattr(self, '_plugin_manager') or not self._plugin_manager:
+ self._plugin_manager = Registry().get('plugin_manager')
+ return self._plugin_manager
+
+ @property
+ def image_manager(self):
+ """
+ Adds the image manager to the class dynamically
+ """
+ if not hasattr(self, '_image_manager') or not self._image_manager:
+ self._image_manager = Registry().get('image_manager')
+ return self._image_manager
+
+ @property
+ def media_controller(self):
+ """
+ Adds the media controller to the class dynamically
+ """
+ if not hasattr(self, '_media_controller') or not self._media_controller:
+ self._media_controller = Registry().get('media_controller')
+ return self._media_controller
+
+ @property
+ def service_manager(self):
+ """
+ Adds the service manager to the class dynamically
+ """
+ if not hasattr(self, '_service_manager') or not self._service_manager:
+ self._service_manager = Registry().get('service_manager')
+ return self._service_manager
+
+ @property
+ def preview_controller(self):
+ """
+ Adds the preview controller to the class dynamically
+ """
+ if not hasattr(self, '_preview_controller') or not self._preview_controller:
+ self._preview_controller = Registry().get('preview_controller')
+ return self._preview_controller
+
+ @property
+ def live_controller(self):
+ """
+ Adds the live controller to the class dynamically
+ """
+ if not hasattr(self, '_live_controller') or not self._live_controller:
+ self._live_controller = Registry().get('live_controller')
+ return self._live_controller
+
+ @property
+ def main_window(self):
+ """
+ Adds the main window to the class dynamically
+ """
+ if not hasattr(self, '_main_window') or not self._main_window:
+ self._main_window = Registry().get('main_window')
+ return self._main_window
+
+ @property
+ def renderer(self):
+ """
+ Adds the Renderer to the class dynamically
+ """
+ if not hasattr(self, '_renderer') or not self._renderer:
+ self._renderer = Registry().get('renderer')
+ return self._renderer
+
+ @property
+ def theme_manager(self):
+ """
+ Adds the theme manager to the class dynamically
+ """
+ if not hasattr(self, '_theme_manager') or not self._theme_manager:
+ self._theme_manager = Registry().get('theme_manager')
+ return self._theme_manager
+
+ @property
+ def settings_form(self):
+ """
+ Adds the settings form to the class dynamically
+ """
+ if not hasattr(self, '_settings_form') or not self._settings_form:
+ self._settings_form = Registry().get('settings_form')
+ return self._settings_form
+
+ @property
+ def alerts_manager(self):
+ """
+ Adds the alerts manager to the class dynamically
+ """
+ if not hasattr(self, '_alerts_manager') or not self._alerts_manager:
+ self._alerts_manager = Registry().get('alerts_manager')
+ return self._alerts_manager
+
+ @property
+ def projector_manager(self):
+ """
+ Adds the projector manager to the class dynamically
+ """
+ if not hasattr(self, '_projector_manager') or not self._projector_manager:
+ self._projector_manager = Registry().get('projector_manager')
+ return self._projector_manager
diff --git a/openlp/core/common/registryproperties.py b/openlp/core/common/registryproperties.py
deleted file mode 100644
index 29bd3b2ce..000000000
--- a/openlp/core/common/registryproperties.py
+++ /dev/null
@@ -1,152 +0,0 @@
-# -*- 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 #
-###############################################################################
-"""
-Provide Registry values for adding to classes
-"""
-from openlp.core.common import Registry, is_win
-
-
-class RegistryProperties(object):
- """
- This adds registry components to classes to use at run time.
- """
-
- @property
- def application(self):
- """
- Adds the openlp to the class dynamically.
- Windows needs to access the application in a dynamic manner.
- """
- if is_win():
- return Registry().get('application')
- else:
- if not hasattr(self, '_application') or not self._application:
- self._application = Registry().get('application')
- return self._application
-
- @property
- def plugin_manager(self):
- """
- Adds the plugin manager to the class dynamically
- """
- if not hasattr(self, '_plugin_manager') or not self._plugin_manager:
- self._plugin_manager = Registry().get('plugin_manager')
- return self._plugin_manager
-
- @property
- def image_manager(self):
- """
- Adds the image manager to the class dynamically
- """
- if not hasattr(self, '_image_manager') or not self._image_manager:
- self._image_manager = Registry().get('image_manager')
- return self._image_manager
-
- @property
- def media_controller(self):
- """
- Adds the media controller to the class dynamically
- """
- if not hasattr(self, '_media_controller') or not self._media_controller:
- self._media_controller = Registry().get('media_controller')
- return self._media_controller
-
- @property
- def service_manager(self):
- """
- Adds the service manager to the class dynamically
- """
- if not hasattr(self, '_service_manager') or not self._service_manager:
- self._service_manager = Registry().get('service_manager')
- return self._service_manager
-
- @property
- def preview_controller(self):
- """
- Adds the preview controller to the class dynamically
- """
- if not hasattr(self, '_preview_controller') or not self._preview_controller:
- self._preview_controller = Registry().get('preview_controller')
- return self._preview_controller
-
- @property
- def live_controller(self):
- """
- Adds the live controller to the class dynamically
- """
- if not hasattr(self, '_live_controller') or not self._live_controller:
- self._live_controller = Registry().get('live_controller')
- return self._live_controller
-
- @property
- def main_window(self):
- """
- Adds the main window to the class dynamically
- """
- if not hasattr(self, '_main_window') or not self._main_window:
- self._main_window = Registry().get('main_window')
- return self._main_window
-
- @property
- def renderer(self):
- """
- Adds the Renderer to the class dynamically
- """
- if not hasattr(self, '_renderer') or not self._renderer:
- self._renderer = Registry().get('renderer')
- return self._renderer
-
- @property
- def theme_manager(self):
- """
- Adds the theme manager to the class dynamically
- """
- if not hasattr(self, '_theme_manager') or not self._theme_manager:
- self._theme_manager = Registry().get('theme_manager')
- return self._theme_manager
-
- @property
- def settings_form(self):
- """
- Adds the settings form to the class dynamically
- """
- if not hasattr(self, '_settings_form') or not self._settings_form:
- self._settings_form = Registry().get('settings_form')
- return self._settings_form
-
- @property
- def alerts_manager(self):
- """
- Adds the alerts manager to the class dynamically
- """
- if not hasattr(self, '_alerts_manager') or not self._alerts_manager:
- self._alerts_manager = Registry().get('alerts_manager')
- return self._alerts_manager
-
- @property
- def projector_manager(self):
- """
- Adds the projector manager to the class dynamically
- """
- if not hasattr(self, '_projector_manager') or not self._projector_manager:
- self._projector_manager = Registry().get('projector_manager')
- return self._projector_manager
diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py
index ca59d4e6f..a6bc549f1 100644
--- a/openlp/core/common/settings.py
+++ b/openlp/core/common/settings.py
@@ -28,11 +28,11 @@ import json
import os
from tempfile import gettempdir
-from PyQt5 import QtCore, QtGui, QtWidgets
+from PyQt5 import QtCore, QtGui
-from openlp.core.common import SlideLimits, ThemeLevel, UiStrings, is_linux, is_win, translate
+from openlp.core.common import SlideLimits, ThemeLevel, is_linux, is_win
from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder
-from openlp.core.common.path import Path, str_to_path
+from openlp.core.common.path import Path, str_to_path, files_to_paths
log = logging.getLogger(__name__)
@@ -62,18 +62,6 @@ def media_players_conv(string):
return string
-def file_names_conv(file_names):
- """
- Convert a list of file names in to a list of file paths.
-
- :param list[str] file_names: The list of file names to convert.
- :return: The list converted to file paths
- :rtype: openlp.core.common.path.Path
- """
- if file_names:
- return [str_to_path(file_name) for file_name in file_names]
-
-
class Settings(QtCore.QSettings):
"""
Class to wrap QSettings.
@@ -116,7 +104,7 @@ class Settings(QtCore.QSettings):
'advanced/default service enabled': True,
'advanced/default service hour': 11,
'advanced/default service minute': 0,
- 'advanced/default service name': UiStrings().DefaultServiceName,
+ 'advanced/default service name': 'Service %Y-%m-%d %H-%M',
'advanced/display size': 0,
'advanced/double click live': False,
'advanced/enable exit confirmation': True,
@@ -261,9 +249,9 @@ class Settings(QtCore.QSettings):
('songs/last directory import', 'songs/last directory import', [(str_to_path, None)]),
('songs/last directory export', 'songs/last directory export', [(str_to_path, None)]),
('songusage/last directory export', 'songusage/last directory export', [(str_to_path, None)]),
- ('core/recent files', 'core/recent files', [(file_names_conv, None)]),
- ('media/media files', 'media/media files', [(file_names_conv, None)]),
- ('presentations/presentations files', 'presentations/presentations files', [(file_names_conv, None)]),
+ ('core/recent files', 'core/recent files', [(files_to_paths, None)]),
+ ('media/media files', 'media/media files', [(files_to_paths, None)]),
+ ('presentations/presentations files', 'presentations/presentations files', [(files_to_paths, None)]),
('core/logo file', 'core/logo file', [(str_to_path, None)]),
('presentations/last directory', 'presentations/last directory', [(str_to_path, None)]),
('images/last directory', 'images/last directory', [(str_to_path, None)]),
@@ -298,6 +286,7 @@ class Settings(QtCore.QSettings):
"""
# Make sure the string is translated (when building the dict the string is not translated because the translate
# function was not set up as this stage).
+ from openlp.core.common.i18n import UiStrings
Settings.__default_settings__['advanced/default service name'] = UiStrings().DefaultServiceName
def __init__(self, *args):
@@ -609,11 +598,5 @@ class Settings(QtCore.QSettings):
if file_record.find('@Invalid()') == -1:
file_record = file_record.replace('%20', ' ')
export_conf_file.write(file_record)
- except OSError as ose:
- QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Export setting error'),
- translate('OpenLP.MainWindow',
- 'An error occurred while exporting the settings: {err}'
- ).format(err=ose.strerror),
- QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
finally:
temp_path.unlink()
diff --git a/openlp/core/common/uistrings.py b/openlp/core/common/uistrings.py
deleted file mode 100644
index 9dd24a866..000000000
--- a/openlp/core/common/uistrings.py
+++ /dev/null
@@ -1,187 +0,0 @@
-# -*- 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:`uistrings` module provides standard strings for OpenLP.
-"""
-import logging
-import itertools
-
-from openlp.core.common import translate
-
-
-log = logging.getLogger(__name__)
-
-
-class UiStrings(object):
- """
- Provide standard strings for objects to use.
- """
- __instance__ = None
-
- def __new__(cls):
- """
- Override the default object creation method to return a single instance.
- """
- if not cls.__instance__:
- cls.__instance__ = object.__new__(cls)
- return cls.__instance__
-
- def __init__(self):
- """
- These strings should need a good reason to be retranslated elsewhere.
- Should some/more/less of these have an & attached?
- """
- self.About = translate('OpenLP.Ui', 'About')
- self.Add = translate('OpenLP.Ui', '&Add')
- self.AddGroup = translate('OpenLP.Ui', 'Add group')
- self.AddGroupDot = translate('OpenLP.Ui', 'Add group.')
- self.Advanced = translate('OpenLP.Ui', 'Advanced')
- self.AllFiles = translate('OpenLP.Ui', 'All Files')
- self.Automatic = translate('OpenLP.Ui', 'Automatic')
- self.BackgroundColor = translate('OpenLP.Ui', 'Background Color')
- self.BackgroundColorColon = translate('OpenLP.Ui', 'Background color:')
- self.BibleShortSearchTitle = translate('OpenLP.Ui', 'Search is Empty or too Short')
- self.BibleShortSearch = translate('OpenLP.Ui', 'The search you have entered is empty or shorter '
- 'than 3 characters long.
Please try again with '
- 'a longer search.')
- self.BibleNoBiblesTitle = translate('OpenLP.Ui', 'No Bibles Available')
- self.BibleNoBibles = translate('OpenLP.Ui', 'There are no Bibles currently installed.
'
- 'Please use the Import Wizard to install one or more Bibles.')
- self.Bottom = translate('OpenLP.Ui', 'Bottom')
- self.Browse = translate('OpenLP.Ui', 'Browse...')
- self.Cancel = translate('OpenLP.Ui', 'Cancel')
- self.CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:')
- self.CCLISongNumberLabel = translate('OpenLP.Ui', 'CCLI song number:')
- self.CreateService = translate('OpenLP.Ui', 'Create a new service.')
- self.ConfirmDelete = translate('OpenLP.Ui', 'Confirm Delete')
- self.Continuous = translate('OpenLP.Ui', 'Continuous')
- self.Default = translate('OpenLP.Ui', 'Default')
- self.DefaultColor = translate('OpenLP.Ui', 'Default Color:')
- self.DefaultServiceName = translate('OpenLP.Ui', 'Service %Y-%m-%d %H-%M',
- 'This may not contain any of the following characters: /\\?*|<>[]":+\n'
- 'See http://docs.python.org/library/datetime'
- '.html#strftime-strptime-behavior for more information.')
- self.Delete = translate('OpenLP.Ui', '&Delete')
- self.DisplayStyle = translate('OpenLP.Ui', 'Display style:')
- self.Duplicate = translate('OpenLP.Ui', 'Duplicate Error')
- self.Edit = translate('OpenLP.Ui', '&Edit')
- self.EmptyField = translate('OpenLP.Ui', 'Empty Field')
- self.Error = translate('OpenLP.Ui', 'Error')
- self.Export = translate('OpenLP.Ui', 'Export')
- self.File = translate('OpenLP.Ui', 'File')
- self.FontSizePtUnit = translate('OpenLP.Ui', 'pt', 'Abbreviated font pointsize unit')
- self.Help = translate('OpenLP.Ui', 'Help')
- self.Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours')
- self.IFdSs = translate('OpenLP.Ui', 'Invalid Folder Selected', 'Singular')
- self.IFSs = translate('OpenLP.Ui', 'Invalid File Selected', 'Singular')
- self.IFSp = translate('OpenLP.Ui', 'Invalid Files Selected', 'Plural')
- self.Image = translate('OpenLP.Ui', 'Image')
- self.Import = translate('OpenLP.Ui', 'Import')
- self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
- self.Live = translate('OpenLP.Ui', 'Live')
- self.LiveBGError = translate('OpenLP.Ui', 'Live Background Error')
- self.LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar')
- self.Load = translate('OpenLP.Ui', 'Load')
- self.Manufacturer = translate('OpenLP.Ui', 'Manufacturer', 'Singular')
- self.Manufacturers = translate('OpenLP.Ui', 'Manufacturers', 'Plural')
- self.Model = translate('OpenLP.Ui', 'Model', 'Singular')
- self.Models = translate('OpenLP.Ui', 'Models', 'Plural')
- self.Minutes = translate('OpenLP.Ui', 'm', 'The abbreviated unit for minutes')
- self.Middle = translate('OpenLP.Ui', 'Middle')
- self.New = translate('OpenLP.Ui', 'New')
- self.NewService = translate('OpenLP.Ui', 'New Service')
- self.NewTheme = translate('OpenLP.Ui', 'New Theme')
- self.NextTrack = translate('OpenLP.Ui', 'Next Track')
- self.NFdSs = translate('OpenLP.Ui', 'No Folder Selected', 'Singular')
- self.NFSs = translate('OpenLP.Ui', 'No File Selected', 'Singular')
- self.NFSp = translate('OpenLP.Ui', 'No Files Selected', 'Plural')
- self.NISs = translate('OpenLP.Ui', 'No Item Selected', 'Singular')
- self.NISp = translate('OpenLP.Ui', 'No Items Selected', 'Plural')
- self.NoResults = translate('OpenLP.Ui', 'No Search Results')
- self.OpenLP = translate('OpenLP.Ui', 'OpenLP')
- self.OpenLPv2AndUp = translate('OpenLP.Ui', 'OpenLP 2.0 and up')
- self.OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. Do you wish to continue?')
- self.OpenService = translate('OpenLP.Ui', 'Open service.')
- self.OptionalShowInFooter = translate('OpenLP.Ui', 'Optional, this will be displayed in footer.')
- self.OptionalHideInFooter = translate('OpenLP.Ui', 'Optional, this won\'t be displayed in footer.')
- self.PlaySlidesInLoop = translate('OpenLP.Ui', 'Play Slides in Loop')
- self.PlaySlidesToEnd = translate('OpenLP.Ui', 'Play Slides to End')
- self.Preview = translate('OpenLP.Ui', 'Preview')
- self.PreviewToolbar = translate('OpenLP.Ui', 'Preview Toolbar')
- self.PrintService = translate('OpenLP.Ui', 'Print Service')
- self.Projector = translate('OpenLP.Ui', 'Projector', 'Singular')
- self.Projectors = translate('OpenLP.Ui', 'Projectors', 'Plural')
- self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
- self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace live background.')
- self.ReplaceLiveBGDisabled = translate('OpenLP.Ui', 'Replace live background is not available when the WebKit '
- 'player is disabled.')
- self.ResetBG = translate('OpenLP.Ui', 'Reset Background')
- self.ResetLiveBG = translate('OpenLP.Ui', 'Reset live background.')
- self.RequiredShowInFooter = translate('OpenLP.Ui', 'Required, this will be displayed in footer.')
- self.Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds')
- self.SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview')
- self.Search = translate('OpenLP.Ui', 'Search')
- self.SearchThemes = translate('OpenLP.Ui', 'Search Themes...', 'Search bar place holder text ')
- self.SelectDelete = translate('OpenLP.Ui', 'You must select an item to delete.')
- self.SelectEdit = translate('OpenLP.Ui', 'You must select an item to edit.')
- self.Settings = translate('OpenLP.Ui', 'Settings')
- self.SaveService = translate('OpenLP.Ui', 'Save Service')
- self.Service = translate('OpenLP.Ui', 'Service')
- self.ShortResults = translate('OpenLP.Ui', 'Please type more text to use \'Search As You Type\'')
- 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.')
- self.StartingImport = translate('OpenLP.Ui', 'Starting import...')
- 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')
- self.Themes = translate('OpenLP.Ui', 'Themes', 'Plural')
- self.Tools = translate('OpenLP.Ui', 'Tools')
- self.Top = translate('OpenLP.Ui', 'Top')
- self.UnsupportedFile = translate('OpenLP.Ui', 'Unsupported File')
- self.VersePerSlide = translate('OpenLP.Ui', 'Verse Per Slide')
- self.VersePerLine = translate('OpenLP.Ui', 'Verse Per Line')
- self.Version = translate('OpenLP.Ui', 'Version')
- self.View = translate('OpenLP.Ui', 'View')
- self.ViewMode = translate('OpenLP.Ui', 'View Mode')
- self.Video = translate('OpenLP.Ui', 'Video')
- self.WebDownloadText = translate('OpenLP.Ui', 'Web Interface, Download and Install latest Version')
- book_chapter = translate('OpenLP.Ui', 'Book Chapter')
- chapter = translate('OpenLP.Ui', 'Chapter')
- verse = translate('OpenLP.Ui', 'Verse')
- gap = ' | '
- psalm = translate('OpenLP.Ui', 'Psalm')
- may_shorten = translate('OpenLP.Ui', 'Book names may be shortened from full names, for an example Ps 23 = '
- 'Psalm 23')
- bible_scripture_items = \
- [book_chapter, gap, psalm, ' 23
',
- book_chapter, '%(range)s', chapter, gap, psalm, ' 23%(range)s24
',
- book_chapter, '%(verse)s', verse, '%(range)s', verse, gap, psalm, ' 23%(verse)s1%(range)s2
',
- book_chapter, '%(verse)s', verse, '%(range)s', verse, '%(list)s', verse, '%(range)s', verse, gap, psalm,
- ' 23%(verse)s1%(range)s2%(list)s5%(range)s6
',
- book_chapter, '%(verse)s', verse, '%(range)s', verse, '%(list)s', chapter, '%(verse)s', verse, '%(range)s',
- verse, gap, psalm, ' 23%(verse)s1%(range)s2%(list)s24%(verse)s1%(range)s3
',
- book_chapter, '%(verse)s', verse, '%(range)s', chapter, '%(verse)s', verse, gap, psalm,
- ' 23%(verse)s1%(range)s24%(verse)s1
', may_shorten]
- itertools.chain.from_iterable(itertools.repeat(strings, 1) if isinstance(strings, str)
- else strings for strings in bible_scripture_items)
- self.BibleScriptureError = ''.join(str(joined) for joined in bible_scripture_items)
diff --git a/openlp/core/common/registrymixin.py b/openlp/core/display/__init__.py
similarity index 63%
rename from openlp/core/common/registrymixin.py
rename to openlp/core/display/__init__.py
index ffc1f9264..dea4ef4db 100644
--- a/openlp/core/common/registrymixin.py
+++ b/openlp/core/display/__init__.py
@@ -20,35 +20,5 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
-Provide Registry Services
+The :mod:`~openlp.core.display` module contains all the code related to rendering and output
"""
-from openlp.core.common import Registry, de_hump
-
-
-class RegistryMixin(object):
- """
- This adds registry components to classes to use at run time.
- """
- def __init__(self, parent):
- """
- Register the class and bootstrap hooks.
- """
- try:
- super(RegistryMixin, self).__init__(parent)
- except TypeError:
- super(RegistryMixin, self).__init__()
- Registry().register(de_hump(self.__class__.__name__), self)
- Registry().register_function('bootstrap_initialise', self.bootstrap_initialise)
- Registry().register_function('bootstrap_post_set_up', self.bootstrap_post_set_up)
-
- def bootstrap_initialise(self):
- """
- Dummy method to be overridden
- """
- pass
-
- def bootstrap_post_set_up(self):
- """
- Dummy method to be overridden
- """
- pass
diff --git a/openlp/core/lib/renderer.py b/openlp/core/display/renderer.py
similarity index 98%
rename from openlp/core/lib/renderer.py
rename to openlp/core/display/renderer.py
index 8b8d5669c..fd040d9c6 100644
--- a/openlp/core/lib/renderer.py
+++ b/openlp/core/display/renderer.py
@@ -25,12 +25,15 @@ import re
from string import Template
from PyQt5 import QtGui, QtCore, QtWebKitWidgets
-from openlp.core.common import Registry, RegistryProperties, OpenLPMixin, RegistryMixin, Settings
+from openlp.core.common.mixins import OpenLPMixin, RegistryMixin
from openlp.core.common.path import path_to_str
-from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, ScreenList, ServiceItem, expand_tags, \
- build_lyrics_format_css, build_lyrics_outline_css, build_chords_css
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
+from openlp.core.display.screens import ScreenList
+from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, ServiceItem, expand_tags, build_chords_css, \
+ build_lyrics_format_css, build_lyrics_outline_css
from openlp.core.common import ThemeLevel
-from openlp.core.ui import MainDisplay
+from openlp.core.ui.maindisplay import MainDisplay
VERSE = 'The Lord said to {r}Noah{/r}: \n' \
'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n' \
@@ -243,6 +246,9 @@ class Renderer(OpenLPMixin, RegistryMixin, RegistryProperties):
elif item.is_capable(ItemCapabilities.CanSoftBreak):
pages = []
if '[---]' in text:
+ # Remove Overflow split if at start of the text
+ if text.startswith('[---]'):
+ text = text[5:]
# Remove two or more option slide breaks next to each other (causing infinite loop).
while '\n[---]\n[---]\n' in text:
text = text.replace('\n[---]\n[---]\n', '\n[---]\n')
diff --git a/openlp/core/lib/screen.py b/openlp/core/display/screens.py
similarity index 98%
rename from openlp/core/lib/screen.py
rename to openlp/core/display/screens.py
index 2e642f497..0a1a4cd28 100644
--- a/openlp/core/lib/screen.py
+++ b/openlp/core/display/screens.py
@@ -23,13 +23,14 @@
The :mod:`screen` module provides management functionality for a machines'
displays.
"""
-
import logging
import copy
from PyQt5 import QtCore
-from openlp.core.common import Registry, Settings, translate
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
+from openlp.core.common.i18n import translate
log = logging.getLogger(__name__)
diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py
index 4602fee2c..0f4078420 100644
--- a/openlp/core/lib/__init__.py
+++ b/openlp/core/lib/__init__.py
@@ -29,9 +29,9 @@ import os
import re
import math
-from PyQt5 import QtCore, QtGui, Qt, QtWidgets
+from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.common.path import Path
log = logging.getLogger(__name__ + '.__init__')
@@ -612,7 +612,6 @@ def create_separated_list(string_list):
from .exceptions import ValidationError
-from .screen import ScreenList
from .formattingtags import FormattingTags
from .plugin import PluginStatus, StringContent, Plugin
from .pluginmanager import PluginManager
@@ -620,7 +619,6 @@ from .settingstab import SettingsTab
from .serviceitem import ServiceItem, ServiceItemType, ItemCapabilities
from .htmlbuilder import build_html, build_lyrics_format_css, build_lyrics_outline_css, build_chords_css
from .imagemanager import ImageManager
-from .renderer import Renderer
from .mediamanageritem import MediaManagerItem
from .projector.db import ProjectorDB, Projector
from .projector.pjlink import PJLink
diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py
index 9d6330dc6..698b1d73e 100644
--- a/openlp/core/lib/db.py
+++ b/openlp/core/lib/db.py
@@ -29,17 +29,19 @@ import os
from copy import copy
from urllib.parse import quote_plus as urlquote
-from sqlalchemy import Table, MetaData, Column, types, create_engine, UnicodeText
+from alembic.migration import MigrationContext
+from alembic.operations import Operations
+from sqlalchemy import Table, MetaData, Column, UnicodeText, types, create_engine
from sqlalchemy.engine.url import make_url
from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError, OperationalError, ProgrammingError
from sqlalchemy.orm import scoped_session, sessionmaker, mapper
from sqlalchemy.pool import NullPool
-from alembic.migration import MigrationContext
-from alembic.operations import Operations
-
-from openlp.core.common import AppLocation, Settings, delete_file, translate
+from openlp.core.common import delete_file
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import translate
from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder
+from openlp.core.common.settings import Settings
from openlp.core.lib.ui import critical_error_message_box
log = logging.getLogger(__name__)
diff --git a/openlp/core/lib/formattingtags.py b/openlp/core/lib/formattingtags.py
index de16bbc7b..c364d388e 100644
--- a/openlp/core/lib/formattingtags.py
+++ b/openlp/core/lib/formattingtags.py
@@ -24,8 +24,8 @@ Provide HTML Tag management and Formatting Tag access class
"""
import json
-from openlp.core.common import Settings
-from openlp.core.lib import translate
+from openlp.core.common.settings import Settings
+from openlp.core.common.i18n import translate
class FormattingTags(object):
diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py
index df88f5f91..0330f10c8 100644
--- a/openlp/core/lib/htmlbuilder.py
+++ b/openlp/core/lib/htmlbuilder.py
@@ -411,7 +411,7 @@ import logging
from string import Template
from PyQt5 import QtWebKit
-from openlp.core.common import Settings
+from openlp.core.common.settings import Settings
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, VerticalType, HorizontalType
log = logging.getLogger(__name__)
diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py
index 79c3a2c90..81a1b659d 100644
--- a/openlp/core/lib/imagemanager.py
+++ b/openlp/core/lib/imagemanager.py
@@ -31,8 +31,10 @@ import queue
from PyQt5 import QtCore
-from openlp.core.common import Registry, Settings
-from openlp.core.lib import ScreenList, resize_image, image_to_byte
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
+from openlp.core.display.screens import ScreenList
+from openlp.core.lib import resize_image, image_to_byte
log = logging.getLogger(__name__)
diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py
index 1c7a5b4ef..dda12e10e 100644
--- a/openlp/core/lib/mediamanageritem.py
+++ b/openlp/core/lib/mediamanageritem.py
@@ -28,8 +28,10 @@ import re
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.common.path import Path, path_to_str, str_to_path
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib import ServiceItem, StringContent, ServiceItemContext
from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import create_widget_action, critical_error_message_box
diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py
index 6a05638ac..059b7a314 100644
--- a/openlp/core/lib/plugin.py
+++ b/openlp/core/lib/plugin.py
@@ -26,7 +26,9 @@ import logging
from PyQt5 import QtCore
-from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
+from openlp.core.common.i18n import UiStrings
from openlp.core.version import get_version
log = logging.getLogger(__name__)
diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py
index 20af89e6c..1bdb020aa 100644
--- a/openlp/core/lib/pluginmanager.py
+++ b/openlp/core/lib/pluginmanager.py
@@ -24,8 +24,11 @@ Provide plugin management
"""
import os
+from openlp.core.common import extension_loader
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.registry import RegistryProperties
+from openlp.core.common.mixins import OpenLPMixin, RegistryMixin
from openlp.core.lib import Plugin, PluginStatus
-from openlp.core.common import AppLocation, RegistryProperties, OpenLPMixin, RegistryMixin, extension_loader
class PluginManager(RegistryMixin, OpenLPMixin, RegistryProperties):
diff --git a/openlp/core/lib/projector/constants.py b/openlp/core/lib/projector/constants.py
index f2d78e31c..715896133 100644
--- a/openlp/core/lib/projector/constants.py
+++ b/openlp/core/lib/projector/constants.py
@@ -20,37 +20,15 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
- :mod:`openlp.core.lib.projector.constants` module
-
- Provides the constants used for projector errors/status/defaults
+The :mod:`openlp.core.lib.projector.constants` module provides the constants used for projector errors/status/defaults
"""
-
import logging
+
+from openlp.core.common.i18n import translate
+
log = logging.getLogger(__name__)
log.debug('projector_constants loaded')
-from openlp.core.common import translate
-
-
-__all__ = ['S_OK', 'E_GENERAL', 'E_NOT_CONNECTED', 'E_FAN', 'E_LAMP', 'E_TEMP',
- 'E_COVER', 'E_FILTER', 'E_AUTHENTICATION', 'E_NO_AUTHENTICATION',
- 'E_UNDEFINED', 'E_PARAMETER', 'E_UNAVAILABLE', 'E_PROJECTOR',
- 'E_INVALID_DATA', 'E_WARN', 'E_ERROR', 'E_CLASS', 'E_PREFIX',
- 'E_CONNECTION_REFUSED', 'E_REMOTE_HOST_CLOSED_CONNECTION', 'E_HOST_NOT_FOUND',
- 'E_SOCKET_ACCESS', 'E_SOCKET_RESOURCE', 'E_SOCKET_TIMEOUT', 'E_DATAGRAM_TOO_LARGE',
- 'E_NETWORK', 'E_ADDRESS_IN_USE', 'E_SOCKET_ADDRESS_NOT_AVAILABLE',
- 'E_UNSUPPORTED_SOCKET_OPERATION', 'E_PROXY_AUTHENTICATION_REQUIRED',
- 'E_SLS_HANDSHAKE_FAILED', 'E_UNFINISHED_SOCKET_OPERATION', 'E_PROXY_CONNECTION_REFUSED',
- 'E_PROXY_CONNECTION_CLOSED', 'E_PROXY_CONNECTION_TIMEOUT', 'E_PROXY_NOT_FOUND',
- 'E_PROXY_PROTOCOL', 'E_UNKNOWN_SOCKET_ERROR',
- 'S_NOT_CONNECTED', 'S_CONNECTING', 'S_CONNECTED',
- 'S_STATUS', 'S_OFF', 'S_INITIALIZE', 'S_STANDBY', 'S_WARMUP', 'S_ON', 'S_COOLDOWN',
- 'S_INFO', 'S_NETWORK_SENDING', 'S_NETWORK_RECEIVED',
- 'ERROR_STRING', 'CR', 'LF', 'PJLINK_ERST_DATA', 'PJLINK_ERST_STATUS', 'PJLINK_POWR_STATUS',
- 'PJLINK_PORT', 'PJLINK_MAX_PACKET', 'TIMEOUT', 'ERROR_MSG', 'PJLINK_ERRORS',
- 'STATUS_STRING', 'PJLINK_VALID_CMD', 'CONNECTION_ERRORS',
- 'PJLINK_DEFAULT_SOURCES', 'PJLINK_DEFAULT_CODES', 'PJLINK_DEFAULT_ITEMS']
-
# Set common constants.
CR = chr(0x0D) # \r
LF = chr(0x0A) # \n
diff --git a/openlp/core/lib/projector/pjlink.py b/openlp/core/lib/projector/pjlink.py
index 1a5e9e832..2eb4da32c 100644
--- a/openlp/core/lib/projector/pjlink.py
+++ b/openlp/core/lib/projector/pjlink.py
@@ -20,39 +20,40 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
- :mod:`openlp.core.lib.projector.pjlink` module
- Provides the necessary functions for connecting to a PJLink-capable projector.
+The :mod:`openlp.core.lib.projector.pjlink` module provides the necessary functions for connecting to a PJLink-capable
+projector.
- PJLink Class 1 Specifications.
- http://pjlink.jbmia.or.jp/english/dl_class1.html
- Section 5-1 PJLink Specifications
- Section 5-5 Guidelines for Input Terminals
+PJLink Class 1 Specifications
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- PJLink Class 2 Specifications.
- http://pjlink.jbmia.or.jp/english/dl_class2.html
- Section 5-1 PJLink Specifications
- Section 5-5 Guidelines for Input Terminals
+Website: http://pjlink.jbmia.or.jp/english/dl_class1.html
- NOTE:
- Function names follow the following syntax:
- def process_CCCC(...):
- WHERE:
- CCCC = PJLink command being processed.
+- Section 5-1 PJLink Specifications
+- Section 5-5 Guidelines for Input Terminals
+
+PJLink Class 2 Specifications
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Website: http://pjlink.jbmia.or.jp/english/dl_class2.html
+
+- Section 5-1 PJLink Specifications
+- Section 5-5 Guidelines for Input Terminals
+
+.. note:
+ Function names follow the following syntax::
+
+ def process_CCCC(...):
+
+ where ``CCCC`` is the PJLink command being processed
"""
-
import logging
-log = logging.getLogger(__name__)
-
-log.debug('pjlink loaded')
-
-__all__ = ['PJLink']
-
import re
from codecs import decode
from PyQt5 import QtCore, QtNetwork
-from openlp.core.common import translate, qmd5_hash
+from openlp.core.common import qmd5_hash
+from openlp.core.common.i18n import translate
from openlp.core.lib.projector.constants import CONNECTION_ERRORS, CR, ERROR_MSG, ERROR_STRING, \
E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, E_OK, \
E_PARAMETER, E_PROJECTOR, E_SOCKET_TIMEOUT, E_UNAVAILABLE, E_UNDEFINED, PJLINK_ERRORS, PJLINK_ERST_DATA, \
@@ -60,6 +61,11 @@ from openlp.core.lib.projector.constants import CONNECTION_ERRORS, CR, ERROR_MSG
STATUS_STRING, S_CONNECTED, S_CONNECTING, S_INFO, S_NETWORK_RECEIVED, S_NETWORK_SENDING, \
S_NOT_CONNECTED, S_OFF, S_OK, S_ON, S_STATUS
+log = logging.getLogger(__name__)
+log.debug('pjlink loaded')
+
+__all__ = ['PJLink']
+
# Shortcuts
SocketError = QtNetwork.QAbstractSocket.SocketError
SocketSTate = QtNetwork.QAbstractSocket.SocketState
diff --git a/openlp/core/lib/searchedit.py b/openlp/core/lib/searchedit.py
index e2e70a934..db45486f9 100644
--- a/openlp/core/lib/searchedit.py
+++ b/openlp/core/lib/searchedit.py
@@ -24,9 +24,9 @@ import logging
from PyQt5 import QtCore, QtWidgets
+from openlp.core.common.settings import Settings
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_widget_action
-from openlp.core.common import Settings
log = logging.getLogger(__name__)
diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py
index 124b158e8..22b1f9b5f 100644
--- a/openlp/core/lib/serviceitem.py
+++ b/openlp/core/lib/serviceitem.py
@@ -23,7 +23,6 @@
The :mod:`serviceitem` provides the service item functionality including the
type and capability of an item.
"""
-
import datetime
import html
import logging
@@ -33,8 +32,12 @@ import ntpath
from PyQt5 import QtGui
-from openlp.core.common import RegistryProperties, Settings, translate, AppLocation, md5_hash
-from openlp.core.lib import ImageSource, build_icon, clean_tags, expand_tags, expand_chords, create_thumb
+from openlp.core.common import md5_hash
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import RegistryProperties
+from openlp.core.common.settings import Settings
+from openlp.core.lib import ImageSource, build_icon, clean_tags, expand_tags, expand_chords
log = logging.getLogger(__name__)
diff --git a/openlp/core/lib/settingstab.py b/openlp/core/lib/settingstab.py
index 7eb4a6877..4b259465f 100644
--- a/openlp/core/lib/settingstab.py
+++ b/openlp/core/lib/settingstab.py
@@ -23,12 +23,9 @@
The :mod:`~openlp.core.lib.settingstab` module contains the base SettingsTab class which plugins use for adding their
own tab to the settings dialog.
"""
-
-
from PyQt5 import QtWidgets
-
-from openlp.core.common import RegistryProperties
+from openlp.core.common.registry import RegistryProperties
class SettingsTab(QtWidgets.QWidget, RegistryProperties):
diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py
index 8522225d9..92d12ebfd 100644
--- a/openlp/core/lib/theme.py
+++ b/openlp/core/lib/theme.py
@@ -26,10 +26,12 @@ import json
import logging
from lxml import etree, objectify
-from openlp.core.common import AppLocation, de_hump
+
+from openlp.core.common import de_hump
+from openlp.core.common.applocation import AppLocation
from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder
-from openlp.core.common.path import Path, str_to_path
-from openlp.core.lib import str_to_bool, ScreenList, get_text_file_string
+from openlp.core.display.screens import ScreenList
+from openlp.core.lib import str_to_bool, get_text_file_string
log = logging.getLogger(__name__)
diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py
index fe67c53ba..0d5b3c0bd 100644
--- a/openlp/core/lib/ui.py
+++ b/openlp/core/lib/ui.py
@@ -26,8 +26,10 @@ import logging
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, UiStrings, translate, is_macosx
+from openlp.core.common import is_macosx
from openlp.core.common.actions import ActionList
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry
from openlp.core.lib import build_icon
diff --git a/openlp/core/ui/aboutdialog.py b/openlp/core/ui/aboutdialog.py
index 0c37c7624..8cd422ecf 100644
--- a/openlp/core/ui/aboutdialog.py
+++ b/openlp/core/ui/aboutdialog.py
@@ -23,7 +23,7 @@ import datetime
from PyQt5 import QtGui, QtWidgets
-from openlp.core.common import UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button, create_button_box
diff --git a/openlp/core/ui/aboutform.py b/openlp/core/ui/aboutform.py
index bed83785b..e2b4eca87 100644
--- a/openlp/core/ui/aboutform.py
+++ b/openlp/core/ui/aboutform.py
@@ -27,7 +27,7 @@ import webbrowser
from PyQt5 import QtCore, QtWidgets
from openlp.core.version import get_version
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
from .aboutdialog import UiAboutDialog
diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py
index 26303f1cb..9581dc6f9 100644
--- a/openlp/core/ui/advancedtab.py
+++ b/openlp/core/ui/advancedtab.py
@@ -27,9 +27,10 @@ from datetime import datetime, timedelta
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import AppLocation, Settings, SlideLimits, UiStrings, translate
-from openlp.core.common.languagemanager import format_time
-from openlp.core.common.path import path_to_str
+from openlp.core.common import SlideLimits
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings, format_time, translate
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab, build_icon
from openlp.core.ui.lib import PathEdit, PathType
from openlp.core.ui.style import HAS_DARK_STYLE
diff --git a/openlp/core/ui/exceptiondialog.py b/openlp/core/ui/exceptiondialog.py
index ab001f3e1..0cdd3d28d 100644
--- a/openlp/core/ui/exceptiondialog.py
+++ b/openlp/core/ui/exceptiondialog.py
@@ -25,7 +25,8 @@ The GUI widgets of the exception dialog.
from PyQt5 import QtGui, QtWidgets
-from openlp.core.lib import translate, build_icon
+from openlp.core.common.i18n import translate
+from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button, create_button_box
diff --git a/openlp/core/ui/exceptionform.py b/openlp/core/ui/exceptionform.py
index 2a5f6b2e7..1ceeed989 100644
--- a/openlp/core/ui/exceptionform.py
+++ b/openlp/core/ui/exceptionform.py
@@ -70,11 +70,14 @@ try:
except ImportError:
VLC_VERSION = '-'
-from openlp.core.common import RegistryProperties, Settings, UiStrings, is_linux, translate
-from openlp.core.version import get_version
+from openlp.core.common import is_linux
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import RegistryProperties
+from openlp.core.common.settings import Settings
+from openlp.core.ui.exceptiondialog import Ui_ExceptionDialog
from openlp.core.ui.lib.filedialog import FileDialog
+from openlp.core.version import get_version
-from .exceptiondialog import Ui_ExceptionDialog
log = logging.getLogger(__name__)
diff --git a/openlp/core/ui/filerenamedialog.py b/openlp/core/ui/filerenamedialog.py
index ea6a8593f..0c2e089af 100644
--- a/openlp/core/ui/filerenamedialog.py
+++ b/openlp/core/ui/filerenamedialog.py
@@ -24,7 +24,8 @@ The UI widgets for the rename dialog
"""
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.lib import translate, build_icon
+from openlp.core.common.i18n import translate
+from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/core/ui/filerenameform.py b/openlp/core/ui/filerenameform.py
index 2314fda43..d6a519240 100644
--- a/openlp/core/ui/filerenameform.py
+++ b/openlp/core/ui/filerenameform.py
@@ -22,12 +22,11 @@
"""
The file rename dialog.
"""
-
from PyQt5 import QtCore, QtWidgets
-from .filerenamedialog import Ui_FileRenameDialog
-
-from openlp.core.common import Registry, RegistryProperties, translate
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.ui.filerenamedialog import Ui_FileRenameDialog
class FileRenameForm(QtWidgets.QDialog, Ui_FileRenameDialog, RegistryProperties):
diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py
index f948f8145..ea98577c8 100644
--- a/openlp/core/ui/firsttimeform.py
+++ b/openlp/core/ui/firsttimeform.py
@@ -34,9 +34,12 @@ from tempfile import gettempdir
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, check_directory_exists, \
- translate, clean_button_text, trace_error_handler
-from openlp.core.common.path import Path
+from openlp.core.common import clean_button_text, trace_error_handler
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import translate
+from openlp.core.common.path import Path, create_paths
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib import PluginStatus, build_icon
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.common.httputils import get_web_page, get_url_file_size, url_get_file, CONNECTION_TIMEOUT
@@ -277,7 +280,7 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
self.no_internet_cancel_button.setVisible(False)
# Check if this is a re-run of the wizard.
self.has_run_wizard = Settings().value('core/has run wizard')
- check_directory_exists(Path(gettempdir(), 'openlp'))
+ create_paths(Path(gettempdir(), 'openlp'))
def update_screen_list_combo(self):
"""
@@ -597,7 +600,7 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
'The following files were not able to be '
'downloaded:
{text}'.format(text=file_list)))
msg.setStandardButtons(msg.Ok)
- ans = msg.exec()
+ msg.exec()
return True
def _set_plugin_status(self, field, tag):
diff --git a/openlp/core/ui/firsttimelanguagedialog.py b/openlp/core/ui/firsttimelanguagedialog.py
index 2a177f918..abe12aa63 100644
--- a/openlp/core/ui/firsttimelanguagedialog.py
+++ b/openlp/core/ui/firsttimelanguagedialog.py
@@ -24,7 +24,7 @@ The UI widgets of the language selection dialog.
"""
from PyQt5 import QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/core/ui/firsttimelanguageform.py b/openlp/core/ui/firsttimelanguageform.py
index bfe593b83..1131883bf 100644
--- a/openlp/core/ui/firsttimelanguageform.py
+++ b/openlp/core/ui/firsttimelanguageform.py
@@ -24,8 +24,8 @@ The language selection dialog.
"""
from PyQt5 import QtCore, QtWidgets
+from openlp.core.common.i18n import LanguageManager
from openlp.core.lib.ui import create_action
-from openlp.core.common import LanguageManager
from .firsttimelanguagedialog import Ui_FirstTimeLanguageDialog
diff --git a/openlp/core/ui/firsttimewizard.py b/openlp/core/ui/firsttimewizard.py
index d7f81372e..be893cd5e 100644
--- a/openlp/core/ui/firsttimewizard.py
+++ b/openlp/core/ui/firsttimewizard.py
@@ -24,8 +24,9 @@ The UI widgets for the first time wizard.
"""
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common.uistrings import UiStrings
-from openlp.core.common import translate, is_macosx, clean_button_text, Settings
+from openlp.core.common import is_macosx, clean_button_text
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.settings import Settings
from openlp.core.lib import build_icon
from openlp.core.lib.ui import add_welcome_page
diff --git a/openlp/core/ui/formattingtagcontroller.py b/openlp/core/ui/formattingtagcontroller.py
index 062eb21fc..e92173fed 100644
--- a/openlp/core/ui/formattingtagcontroller.py
+++ b/openlp/core/ui/formattingtagcontroller.py
@@ -24,9 +24,9 @@ The :mod:`formattingtagform` provides an Tag Edit facility. The Base set are pro
Custom tags can be defined and saved. The Custom Tag arrays are saved in a pickle so QSettings works on them. Base Tags
cannot be changed.
"""
-
import re
-from openlp.core.common import translate
+
+from openlp.core.common.i18n import translate
from openlp.core.lib import FormattingTags
diff --git a/openlp/core/ui/formattingtagdialog.py b/openlp/core/ui/formattingtagdialog.py
index c6e173128..fa36fa818 100644
--- a/openlp/core/ui/formattingtagdialog.py
+++ b/openlp/core/ui/formattingtagdialog.py
@@ -24,7 +24,7 @@ The UI widgets for the formatting tags window.
"""
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/core/ui/formattingtagform.py b/openlp/core/ui/formattingtagform.py
index a4c32440a..ab0bfc79f 100644
--- a/openlp/core/ui/formattingtagform.py
+++ b/openlp/core/ui/formattingtagform.py
@@ -24,10 +24,9 @@ The :mod:`formattingtagform` provides an Tag Edit facility. The Base set are pro
Custom tags can be defined and saved. The Custom Tag arrays are saved in a json string so QSettings works on them.
Base Tags cannot be changed.
"""
-
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import FormattingTags
from openlp.core.ui.formattingtagdialog import Ui_FormattingTagDialog
from openlp.core.ui.formattingtagcontroller import FormattingTagController
diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py
index cc382badf..8488f13a1 100644
--- a/openlp/core/ui/generaltab.py
+++ b/openlp/core/ui/generaltab.py
@@ -26,9 +26,13 @@ import logging
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, Settings, UiStrings, translate, get_images_filter
-from openlp.core.common.path import Path, path_to_str, str_to_path
-from openlp.core.lib import SettingsTab, ScreenList
+from openlp.core.common import get_images_filter
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.path import Path
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
+from openlp.core.display.screens import ScreenList
+from openlp.core.lib import SettingsTab
from openlp.core.ui.lib import ColorButton, PathEdit
log = logging.getLogger(__name__)
diff --git a/openlp/core/ui/lib/colorbutton.py b/openlp/core/ui/lib/colorbutton.py
index 662b83033..6eef707b2 100644
--- a/openlp/core/ui/lib/colorbutton.py
+++ b/openlp/core/ui/lib/colorbutton.py
@@ -25,7 +25,7 @@ Provide a custom widget based on QPushButton for the selection of colors
"""
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
class ColorButton(QtWidgets.QPushButton):
diff --git a/openlp/core/ui/lib/dockwidget.py b/openlp/core/ui/lib/dockwidget.py
index d8bcab0fa..398d1e674 100644
--- a/openlp/core/ui/lib/dockwidget.py
+++ b/openlp/core/ui/lib/dockwidget.py
@@ -28,7 +28,8 @@ import logging
from PyQt5 import QtWidgets
-from openlp.core.lib import ScreenList, build_icon
+from openlp.core.display.screens import ScreenList
+from openlp.core.lib import build_icon
log = logging.getLogger(__name__)
diff --git a/openlp/core/ui/lib/listpreviewwidget.py b/openlp/core/ui/lib/listpreviewwidget.py
index 142034785..d03261e8c 100644
--- a/openlp/core/ui/lib/listpreviewwidget.py
+++ b/openlp/core/ui/lib/listpreviewwidget.py
@@ -26,7 +26,8 @@ It is based on a QTableWidget but represents its contents in list form.
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import RegistryProperties, Settings
+from openlp.core.common.registry import RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib import ImageSource, ItemCapabilities, ServiceItem
@@ -209,21 +210,21 @@ class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties):
Switches to the given row.
"""
# Retrieve setting
- autoscrolling = Settings().value('advanced/autoscrolling')
+ auto_scrolling = Settings().value('advanced/autoscrolling')
# Check if auto-scroll disabled (None) and validate value as dict containing 'dist' and 'pos'
# 'dist' represents the slide to scroll to relative to the new slide (-1 = previous, 0 = current, 1 = next)
# 'pos' represents the vert position of of the slide (0 = in view, 1 = top, 2 = middle, 3 = bottom)
- if not (isinstance(autoscrolling, dict) and 'dist' in autoscrolling and 'pos' in autoscrolling and
- isinstance(autoscrolling['dist'], int) and isinstance(autoscrolling['pos'], int)):
+ if not (isinstance(auto_scrolling, dict) and 'dist' in auto_scrolling and 'pos' in auto_scrolling and
+ isinstance(auto_scrolling['dist'], int) and isinstance(auto_scrolling['pos'], int)):
return
# prevent scrolling past list bounds
- scroll_to_slide = slide + autoscrolling['dist']
+ scroll_to_slide = slide + auto_scrolling['dist']
if scroll_to_slide < 0:
scroll_to_slide = 0
if scroll_to_slide >= self.slide_count():
scroll_to_slide = self.slide_count() - 1
# Scroll to item if possible.
- self.scrollToItem(self.item(scroll_to_slide, 0), autoscrolling['pos'])
+ self.scrollToItem(self.item(scroll_to_slide, 0), auto_scrolling['pos'])
self.selectRow(slide)
def current_slide_number(self):
diff --git a/openlp/core/ui/lib/listwidgetwithdnd.py b/openlp/core/ui/lib/listwidgetwithdnd.py
index 1758d46fb..5648ff8f4 100755
--- a/openlp/core/ui/lib/listwidgetwithdnd.py
+++ b/openlp/core/ui/lib/listwidgetwithdnd.py
@@ -26,7 +26,8 @@ import os
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, UiStrings
+from openlp.core.common.i18n import UiStrings
+from openlp.core.common.registry import Registry
class ListWidgetWithDnD(QtWidgets.QListWidget):
diff --git a/openlp/core/ui/lib/pathedit.py b/openlp/core/ui/lib/pathedit.py
index d5b9272fa..7b28c47ba 100644
--- a/openlp/core/ui/lib/pathedit.py
+++ b/openlp/core/ui/lib/pathedit.py
@@ -23,7 +23,7 @@ from enum import Enum
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.common.path import Path, path_to_str, str_to_path
from openlp.core.lib import build_icon
from openlp.core.ui.lib.filedialog import FileDialog
diff --git a/openlp/core/ui/lib/spelltextedit.py b/openlp/core/ui/lib/spelltextedit.py
index 41e28a7e5..d0fc25af2 100644
--- a/openlp/core/ui/lib/spelltextedit.py
+++ b/openlp/core/ui/lib/spelltextedit.py
@@ -38,7 +38,8 @@ except ImportError:
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.lib import translate, FormattingTags
+from openlp.core.common.i18n import translate
+from openlp.core.lib import FormattingTags
from openlp.core.lib.ui import create_action
log = logging.getLogger(__name__)
diff --git a/openlp/core/ui/lib/treewidgetwithdnd.py b/openlp/core/ui/lib/treewidgetwithdnd.py
index fe45666f5..792fa8ab8 100644
--- a/openlp/core/ui/lib/treewidgetwithdnd.py
+++ b/openlp/core/ui/lib/treewidgetwithdnd.py
@@ -26,7 +26,8 @@ import os
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, is_win
+from openlp.core.common import is_win
+from openlp.core.common.registry import Registry
class TreeWidgetWithDnD(QtWidgets.QTreeWidget):
diff --git a/openlp/core/ui/lib/wizard.py b/openlp/core/ui/lib/wizard.py
index 677949b33..1da24eab3 100644
--- a/openlp/core/ui/lib/wizard.py
+++ b/openlp/core/ui/lib/wizard.py
@@ -23,11 +23,13 @@
The :mod:``wizard`` module provides generic wizard tools for OpenLP.
"""
import logging
-import os
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings, translate, is_macosx
+from openlp.core.common import is_macosx
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib import build_icon
from openlp.core.lib.ui import add_welcome_page
from openlp.core.ui.lib.filedialog import FileDialog
diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py
index 097d92699..d7f2264ee 100644
--- a/openlp/core/ui/maindisplay.py
+++ b/openlp/core/ui/maindisplay.py
@@ -26,19 +26,22 @@ Some of the code for this form is based on the examples at:
* `http://www.steveheffernan.com/html5-video-player/demo-video-player.html`_
* `http://html5demos.com/two-videos`_
-
"""
-
import html
import logging
import os
from PyQt5 import QtCore, QtWidgets, QtWebKit, QtWebKitWidgets, QtGui, QtMultimedia
-from openlp.core.common import AppLocation, Registry, RegistryProperties, OpenLPMixin, Settings, translate,\
- is_macosx, is_win
+from openlp.core.common import is_macosx, is_win
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import translate
+from openlp.core.common.mixins import OpenLPMixin
from openlp.core.common.path import path_to_str
-from openlp.core.lib import ServiceItem, ImageSource, ScreenList, build_html, expand_tags, image_to_byte
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
+from openlp.core.display.screens import ScreenList
+from openlp.core.lib import ServiceItem, ImageSource, build_html, expand_tags, image_to_byte
from openlp.core.lib.theme import BackgroundType
from openlp.core.ui import HideMode, AlertLocation, DisplayControllerType
diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py
index 25fe818ee..26a8b921a 100644
--- a/openlp/core/ui/mainwindow.py
+++ b/openlp/core/ui/mainwindow.py
@@ -36,21 +36,26 @@ from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.api import websockets
from openlp.core.api.http import server
-from openlp.core.common import Registry, RegistryProperties, AppLocation, LanguageManager, Settings, UiStrings, \
- check_directory_exists, translate, is_win, is_macosx, add_actions
+from openlp.core.common import is_win, is_macosx, add_actions
from openlp.core.common.actions import ActionList, CategoryOrder
-from openlp.core.common.path import Path, copyfile, path_to_str, str_to_path
-from openlp.core.lib import Renderer, PluginManager, ImageManager, PluginStatus, ScreenList, build_icon
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import LanguageManager, UiStrings, translate
+from openlp.core.common.path import Path, copyfile, create_paths, path_to_str, str_to_path
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
+from openlp.core.display.screens import ScreenList
+from openlp.core.display.renderer import Renderer
+from openlp.core.lib import PluginManager, ImageManager, PluginStatus, build_icon
from openlp.core.lib.ui import create_action
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, LiveController, PluginForm, \
ShortcutListForm, FormattingTagForm, PreviewController
from openlp.core.ui.firsttimeform import FirstTimeForm
-from openlp.core.ui.media import MediaController
-from openlp.core.ui.printserviceform import PrintServiceForm
-from openlp.core.ui.projector.manager import ProjectorManager
from openlp.core.ui.lib.dockwidget import OpenLPDockWidget
from openlp.core.ui.lib.filedialog import FileDialog
from openlp.core.ui.lib.mediadockmanager import MediaDockManager
+from openlp.core.ui.media import MediaController
+from openlp.core.ui.printserviceform import PrintServiceForm
+from openlp.core.ui.projector.manager import ProjectorManager
from openlp.core.ui.style import PROGRESSBAR_STYLE, get_library_stylesheet
from openlp.core.version import get_version
@@ -853,7 +858,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties):
setting_sections.extend([plugin.name for plugin in self.plugin_manager.plugins])
# Copy the settings file to the tmp dir, because we do not want to change the original one.
temp_dir_path = Path(gettempdir(), 'openlp')
- check_directory_exists(temp_dir_path)
+ create_paths(temp_dir_path)
temp_config_path = temp_dir_path / import_file_path.name
copyfile(import_file_path, temp_config_path)
settings = Settings()
@@ -896,6 +901,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties):
try:
value = import_settings.value(section_key)
except KeyError:
+ value = None
log.warning('The key "{key}" does not exist (anymore), so it will be skipped.'.format(key=section_key))
if value is not None:
settings.setValue('{key}'.format(key=section_key), value)
@@ -929,7 +935,14 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties):
# Make sure it's a .conf file.
export_file_path = export_file_path.with_suffix('.conf')
self.save_settings()
- Settings().export(export_file_path)
+ try:
+ Settings().export(export_file_path)
+ except OSError as ose:
+ QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Export setting error'),
+ translate('OpenLP.MainWindow',
+ 'An error occurred while exporting the settings: {err}'
+ ).format(err=ose.strerror),
+ QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
def on_mode_default_item_clicked(self):
"""
diff --git a/openlp/core/ui/media/__init__.py b/openlp/core/ui/media/__init__.py
index 9294ea16f..145f5e8bd 100644
--- a/openlp/core/ui/media/__init__.py
+++ b/openlp/core/ui/media/__init__.py
@@ -26,7 +26,7 @@ import logging
from PyQt5 import QtCore
-from openlp.core.common import Settings
+from openlp.core.common.settings import Settings
log = logging.getLogger(__name__ + '.__init__')
diff --git a/openlp/core/ui/media/endpoint.py b/openlp/core/ui/media/endpoint.py
index 83aca8871..af7623003 100644
--- a/openlp/core/ui/media/endpoint.py
+++ b/openlp/core/ui/media/endpoint.py
@@ -19,15 +19,16 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
+"""
+The :mod:`~openlp.core.api.endpoint` module contains various API endpoints
+"""
import logging
from openlp.core.api.http.endpoint import Endpoint
from openlp.core.api.http import requires_auth
-from openlp.core.common import Registry
-
+from openlp.core.common.registry import Registry
log = logging.getLogger(__name__)
-
media_endpoint = Endpoint('media')
diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py
index b778c68dd..bdc315556 100644
--- a/openlp/core/ui/media/mediacontroller.py
+++ b/openlp/core/ui/media/mediacontroller.py
@@ -29,8 +29,11 @@ import datetime
from PyQt5 import QtCore, QtWidgets
from openlp.core.api.http import register_endpoint
-from openlp.core.common import OpenLPMixin, Registry, RegistryMixin, RegistryProperties, Settings, UiStrings, \
- extension_loader, translate
+from openlp.core.common import extension_loader
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.mixins import OpenLPMixin, RegistryMixin
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib import ItemCapabilities
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui import DisplayControllerType
diff --git a/openlp/core/ui/media/mediaplayer.py b/openlp/core/ui/media/mediaplayer.py
index edf08608b..e4d210513 100644
--- a/openlp/core/ui/media/mediaplayer.py
+++ b/openlp/core/ui/media/mediaplayer.py
@@ -22,7 +22,7 @@
"""
The :mod:`~openlp.core.ui.media.mediaplayer` module contains the MediaPlayer class.
"""
-from openlp.core.common import RegistryProperties
+from openlp.core.common.registry import RegistryProperties
from openlp.core.ui.media import MediaState
diff --git a/openlp/core/ui/media/playertab.py b/openlp/core/ui/media/playertab.py
index da8386734..f719a167b 100644
--- a/openlp/core/ui/media/playertab.py
+++ b/openlp/core/ui/media/playertab.py
@@ -25,7 +25,9 @@ The :mod:`~openlp.core.ui.media.playertab` module holds the configuration tab fo
import platform
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab
from openlp.core.lib.ui import create_button
from openlp.core.ui.media import get_media_players, set_media_players
diff --git a/openlp/core/ui/media/systemplayer.py b/openlp/core/ui/media/systemplayer.py
index 52ad1e749..a6423db02 100644
--- a/openlp/core/ui/media/systemplayer.py
+++ b/openlp/core/ui/media/systemplayer.py
@@ -28,7 +28,7 @@ import mimetypes
from PyQt5 import QtCore, QtMultimedia, QtMultimediaWidgets
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
from openlp.core.ui.media import MediaState
from openlp.core.ui.media.mediaplayer import MediaPlayer
diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py
index 8d330f683..605f6a8a1 100644
--- a/openlp/core/ui/media/vlcplayer.py
+++ b/openlp/core/ui/media/vlcplayer.py
@@ -31,8 +31,9 @@ import sys
import ctypes
from PyQt5 import QtWidgets
-from openlp.core.common import Settings, is_win, is_macosx, is_linux
-from openlp.core.lib import translate
+from openlp.core.common import is_win, is_macosx, is_linux
+from openlp.core.common.i18n import translate
+from openlp.core.common.settings import Settings
from openlp.core.ui.media import MediaState, MediaType
from openlp.core.ui.media.mediaplayer import MediaPlayer
diff --git a/openlp/core/ui/media/webkitplayer.py b/openlp/core/ui/media/webkitplayer.py
index 571f21e48..e9142463e 100644
--- a/openlp/core/ui/media/webkitplayer.py
+++ b/openlp/core/ui/media/webkitplayer.py
@@ -26,8 +26,8 @@ import logging
from PyQt5 import QtGui, QtWebKitWidgets
-from openlp.core.common import Settings
-from openlp.core.lib import translate
+from openlp.core.common.settings import Settings
+from openlp.core.common.i18n import translate
from openlp.core.ui.media import MediaState
from openlp.core.ui.media.mediaplayer import MediaPlayer
diff --git a/openlp/core/ui/plugindialog.py b/openlp/core/ui/plugindialog.py
index a89b0ab6a..76087a33a 100644
--- a/openlp/core/ui/plugindialog.py
+++ b/openlp/core/ui/plugindialog.py
@@ -24,7 +24,7 @@ The UI widgets of the plugin view dialog
#"""
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py
index 0299683a5..b34d79714 100644
--- a/openlp/core/ui/pluginform.py
+++ b/openlp/core/ui/pluginform.py
@@ -26,9 +26,10 @@ import logging
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import RegistryProperties, translate
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import RegistryProperties
from openlp.core.lib import PluginStatus
-from .plugindialog import Ui_PluginViewDialog
+from openlp.core.ui.plugindialog import Ui_PluginViewDialog
log = logging.getLogger(__name__)
diff --git a/openlp/core/ui/printservicedialog.py b/openlp/core/ui/printservicedialog.py
index 925b88599..d71b42cdb 100644
--- a/openlp/core/ui/printservicedialog.py
+++ b/openlp/core/ui/printservicedialog.py
@@ -24,7 +24,7 @@ The UI widgets of the print service dialog.
"""
from PyQt5 import QtCore, QtWidgets, QtPrintSupport
-from openlp.core.common import UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.ui.lib import SpellTextEdit
diff --git a/openlp/core/ui/printserviceform.py b/openlp/core/ui/printserviceform.py
index 9394de9ce..482d0f084 100644
--- a/openlp/core/ui/printserviceform.py
+++ b/openlp/core/ui/printserviceform.py
@@ -23,16 +23,17 @@
The actual print service dialog
"""
import datetime
-import os
import html
import lxml.html
from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
-from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings, translate
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib import get_text_file_string
from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize
-from openlp.core.common import AppLocation
DEFAULT_CSS = """/*
Edit this file to customize the service order print. Note, that not all CSS
diff --git a/openlp/core/ui/projector/editform.py b/openlp/core/ui/projector/editform.py
index 6a6f0a362..bd3267665 100644
--- a/openlp/core/ui/projector/editform.py
+++ b/openlp/core/ui/projector/editform.py
@@ -20,22 +20,22 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
- :mod: `openlp.core.ui.projector.editform` module
-
- Provides the functions for adding/editing entries in the projector database.
+The :mod: `openlp.core.ui.projector.editform` module provides the functions for adding/editing entries in the projector
+database.
"""
-
import logging
-log = logging.getLogger(__name__)
-log.debug('editform loaded')
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import translate, verify_ip_address
+from openlp.core.common import verify_ip_address
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.projector.db import Projector
from openlp.core.lib.projector.constants import PJLINK_PORT
+log = logging.getLogger(__name__)
+log.debug('editform loaded')
+
class Ui_ProjectorEditForm(object):
"""
diff --git a/openlp/core/ui/projector/manager.py b/openlp/core/ui/projector/manager.py
index d3c1880d2..47bbb832e 100644
--- a/openlp/core/ui/projector/manager.py
+++ b/openlp/core/ui/projector/manager.py
@@ -29,9 +29,10 @@ import logging
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import RegistryProperties, Settings, OpenLPMixin, \
- RegistryMixin, translate
-from openlp.core.ui.lib import OpenLPToolbar
+from openlp.core.common.i18n import translate
+from openlp.core.common.mixins import OpenLPMixin, RegistryMixin
+from openlp.core.common.registry import RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib.ui import create_widget_action
from openlp.core.lib.projector import DialogSourceStyle
from openlp.core.lib.projector.constants import ERROR_MSG, ERROR_STRING, E_AUTHENTICATION, E_ERROR, \
@@ -39,6 +40,7 @@ from openlp.core.lib.projector.constants import ERROR_MSG, ERROR_STRING, E_AUTHE
S_INITIALIZE, S_NOT_CONNECTED, S_OFF, S_ON, S_STANDBY, S_WARMUP
from openlp.core.lib.projector.db import ProjectorDB
from openlp.core.lib.projector.pjlink import PJLink, PJLinkUDP
+from openlp.core.ui.lib import OpenLPToolbar
from openlp.core.ui.projector.editform import ProjectorEditForm
from openlp.core.ui.projector.sourceselectform import SourceSelectTabs, SourceSelectSingle
diff --git a/openlp/core/ui/projector/sourceselectform.py b/openlp/core/ui/projector/sourceselectform.py
index dc231d3e9..0c150d25b 100644
--- a/openlp/core/ui/projector/sourceselectform.py
+++ b/openlp/core/ui/projector/sourceselectform.py
@@ -28,7 +28,8 @@ import logging
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import translate, is_macosx
+from openlp.core.common import is_macosx
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.projector.db import ProjectorSource
from openlp.core.lib.projector.constants import PJLINK_DEFAULT_SOURCES, PJLINK_DEFAULT_CODES
diff --git a/openlp/core/ui/projector/tab.py b/openlp/core/ui/projector/tab.py
index 06d9e53a7..b7c2e5dda 100644
--- a/openlp/core/ui/projector/tab.py
+++ b/openlp/core/ui/projector/tab.py
@@ -20,21 +20,20 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
- :mod:`openlp.core.ui.projector.tab`
-
- Provides the settings tab in the settings dialog.
+The :mod:`openlp.core.ui.projector.tab` module provides the settings tab in the settings dialog.
"""
-
import logging
-log = logging.getLogger(__name__)
-log.debug('projectortab module loaded')
from PyQt5 import QtWidgets
-from openlp.core.common import Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab
from openlp.core.lib.projector import DialogSourceStyle
+log = logging.getLogger(__name__)
+log.debug('projectortab module loaded')
+
class ProjectorTab(SettingsTab):
"""
diff --git a/openlp/core/ui/serviceitemeditdialog.py b/openlp/core/ui/serviceitemeditdialog.py
index be5da152a..80be015f8 100644
--- a/openlp/core/ui/serviceitemeditdialog.py
+++ b/openlp/core/ui/serviceitemeditdialog.py
@@ -24,7 +24,7 @@ The UI widgets for the service item edit dialog
"""
from PyQt5 import QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box, create_button
diff --git a/openlp/core/ui/serviceitemeditform.py b/openlp/core/ui/serviceitemeditform.py
index f23956e70..17f648ecc 100644
--- a/openlp/core/ui/serviceitemeditform.py
+++ b/openlp/core/ui/serviceitemeditform.py
@@ -24,9 +24,8 @@ The service item edit dialog
"""
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, RegistryProperties
-
-from .serviceitemeditdialog import Ui_ServiceItemEditDialog
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.ui.serviceitemeditdialog import Ui_ServiceItemEditDialog
class ServiceItemEditForm(QtWidgets.QDialog, Ui_ServiceItemEditDialog, RegistryProperties):
diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py
index 153034e33..ff6ab9a47 100644
--- a/openlp/core/ui/servicemanager.py
+++ b/openlp/core/ui/servicemanager.py
@@ -32,11 +32,14 @@ from tempfile import mkstemp
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, ThemeLevel, OpenLPMixin, \
- RegistryMixin, check_directory_exists, UiStrings, translate, split_filename, delete_file
+from openlp.core.common import ThemeLevel, split_filename, delete_file
from openlp.core.common.actions import ActionList, CategoryOrder
-from openlp.core.common.languagemanager import format_time
-from openlp.core.common.path import Path, path_to_str, str_to_path
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings, format_time, translate
+from openlp.core.common.mixins import OpenLPMixin, RegistryMixin
+from openlp.core.common.path import Path, create_paths, path_to_str, str_to_path
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib import ServiceItem, ItemCapabilities, PluginStatus, build_icon
from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
@@ -594,7 +597,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa
audio_from = os.path.join(self.service_path, audio_from)
save_file = os.path.join(self.service_path, audio_to)
save_path = os.path.split(save_file)[0]
- check_directory_exists(Path(save_path))
+ create_paths(Path(save_path))
if not os.path.exists(save_file):
shutil.copy(audio_from, save_file)
zip_file.write(audio_from, audio_to)
diff --git a/openlp/core/ui/servicenoteform.py b/openlp/core/ui/servicenoteform.py
index fc4da438a..998431636 100644
--- a/openlp/core/ui/servicenoteform.py
+++ b/openlp/core/ui/servicenoteform.py
@@ -24,7 +24,8 @@ The :mod:`~openlp.core.ui.servicenoteform` module contains the `ServiceNoteForm`
"""
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, translate
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import Registry, RegistryProperties
from openlp.core.ui.lib import SpellTextEdit
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/core/ui/settingsdialog.py b/openlp/core/ui/settingsdialog.py
index 61626fa6e..0e591e6ad 100644
--- a/openlp/core/ui/settingsdialog.py
+++ b/openlp/core/ui/settingsdialog.py
@@ -24,7 +24,7 @@ The UI widgets of the settings dialog.
"""
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py
index f77c2be59..5524b89ad 100644
--- a/openlp/core/ui/settingsform.py
+++ b/openlp/core/ui/settingsform.py
@@ -27,12 +27,12 @@ import logging
from PyQt5 import QtCore, QtWidgets
from openlp.core.api import ApiTab
-from openlp.core.common import Registry, RegistryProperties
+from openlp.core.common.registry import Registry, RegistryProperties
from openlp.core.lib import build_icon
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
from openlp.core.ui.media import PlayerTab
-from .settingsdialog import Ui_SettingsDialog
from openlp.core.ui.projector.tab import ProjectorTab
+from openlp.core.ui.settingsdialog import Ui_SettingsDialog
log = logging.getLogger(__name__)
diff --git a/openlp/core/ui/shortcutlistdialog.py b/openlp/core/ui/shortcutlistdialog.py
index f47b79eb4..22da4109f 100644
--- a/openlp/core/ui/shortcutlistdialog.py
+++ b/openlp/core/ui/shortcutlistdialog.py
@@ -24,7 +24,7 @@ The list of shortcuts within a dialog.
"""
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/core/ui/shortcutlistform.py b/openlp/core/ui/shortcutlistform.py
index fc9a77ac8..3db127d75 100644
--- a/openlp/core/ui/shortcutlistform.py
+++ b/openlp/core/ui/shortcutlistform.py
@@ -20,15 +20,18 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
-The :mod:`~openlp.core.ui.shortcutlistform` module contains the form class"""
+The :mod:`~openlp.core.ui.shortcutlistform` module contains the form class
+"""
import logging
import re
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import RegistryProperties, Settings, translate
from openlp.core.common.actions import ActionList
-from .shortcutlistdialog import Ui_ShortcutListDialog
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import RegistryProperties
+from openlp.core.common.settings import Settings
+from openlp.core.ui.shortcutlistdialog import Ui_ShortcutListDialog
REMOVE_AMPERSAND = re.compile(r'&{1}')
diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py
index 26bbeb38d..062adbd71 100644
--- a/openlp/core/ui/slidecontroller.py
+++ b/openlp/core/ui/slidecontroller.py
@@ -30,11 +30,14 @@ from threading import Lock
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, Settings, SlideLimits, UiStrings, translate, \
- RegistryMixin, OpenLPMixin
+from openlp.core.common import SlideLimits
from openlp.core.common.actions import ActionList, CategoryOrder
-from openlp.core.lib import ItemCapabilities, ServiceItem, ImageSource, ServiceItemAction, ScreenList, build_icon, \
- build_html
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.mixins import OpenLPMixin, RegistryMixin
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
+from openlp.core.display.screens import ScreenList
+from openlp.core.lib import ItemCapabilities, ServiceItem, ImageSource, ServiceItemAction, build_icon, build_html
from openlp.core.lib.ui import create_action
from openlp.core.ui.lib.toolbar import OpenLPToolbar
from openlp.core.ui.lib.listpreviewwidget import ListPreviewWidget
diff --git a/openlp/core/ui/starttimedialog.py b/openlp/core/ui/starttimedialog.py
index 256bf8f55..fd5163593 100644
--- a/openlp/core/ui/starttimedialog.py
+++ b/openlp/core/ui/starttimedialog.py
@@ -24,7 +24,7 @@ The UI widgets for the time dialog
"""
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/core/ui/starttimeform.py b/openlp/core/ui/starttimeform.py
index ae82d4c9e..e1ad9d9a6 100644
--- a/openlp/core/ui/starttimeform.py
+++ b/openlp/core/ui/starttimeform.py
@@ -24,10 +24,10 @@ The actual start time form.
"""
from PyQt5 import QtCore, QtWidgets
-from .starttimedialog import Ui_StartTimeDialog
-
-from openlp.core.common import Registry, RegistryProperties, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry, RegistryProperties
from openlp.core.lib.ui import critical_error_message_box
+from openlp.core.ui.starttimedialog import Ui_StartTimeDialog
class StartTimeForm(QtWidgets.QDialog, Ui_StartTimeDialog, RegistryProperties):
diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py
index 37978d10a..c15110569 100644
--- a/openlp/core/ui/themeform.py
+++ b/openlp/core/ui/themeform.py
@@ -23,11 +23,12 @@
The Theme wizard
"""
import logging
-import os
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, UiStrings, translate, get_images_filter, is_not_image_file
+from openlp.core.common import get_images_filter, is_not_image_file
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry, RegistryProperties
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui import ThemeLayoutForm
diff --git a/openlp/core/ui/themelayoutdialog.py b/openlp/core/ui/themelayoutdialog.py
index dc48234da..d9ed9638d 100644
--- a/openlp/core/ui/themelayoutdialog.py
+++ b/openlp/core/ui/themelayoutdialog.py
@@ -24,7 +24,7 @@ The layout of the theme
"""
from PyQt5 import QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py
index dffa82d47..f27eb6abb 100644
--- a/openlp/core/ui/thememanager.py
+++ b/openlp/core/ui/thememanager.py
@@ -28,10 +28,13 @@ from xml.etree.ElementTree import ElementTree, XML
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, OpenLPMixin, RegistryMixin, \
- UiStrings, check_directory_exists, translate, delete_file
-from openlp.core.common.languagemanager import get_locale_key
-from openlp.core.common.path import Path, copyfile, path_to_str, rmtree
+from openlp.core.common import delete_file
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings, translate, get_locale_key
+from openlp.core.common.mixins import OpenLPMixin, RegistryMixin
+from openlp.core.common.path import Path, copyfile, create_paths, path_to_str, rmtree
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib import ImageSource, ValidationError, get_text_file_string, build_icon, \
check_item_selected, create_thumb, validate_thumb
from openlp.core.lib.theme import Theme, BackgroundType
@@ -176,9 +179,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
:rtype: None
"""
self.theme_path = AppLocation.get_section_data_path(self.settings_section)
- check_directory_exists(self.theme_path)
self.thumb_path = self.theme_path / 'thumbnails'
- check_directory_exists(self.thumb_path)
+ create_paths(self.theme_path, self.thumb_path)
def check_list_state(self, item, field=None):
"""
@@ -594,7 +596,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
# is directory or preview file
continue
full_name = directory_path / zipped_file_rel_path
- check_directory_exists(full_name.parent)
+ create_paths(full_name.parent)
if zipped_file_rel_path.suffix.lower() == '.xml' or zipped_file_rel_path.suffix.lower() == '.json':
file_xml = str(theme_zip.read(zipped_file), 'utf-8')
with full_name.open('w', encoding='utf-8') as out_file:
@@ -661,7 +663,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
name = theme.theme_name
theme_pretty = theme.export_theme(self.theme_path)
theme_dir = self.theme_path / name
- check_directory_exists(theme_dir)
+ create_paths(theme_dir)
theme_path = theme_dir / '{file_name}.json'.format(file_name=name)
try:
theme_path.write_text(theme_pretty)
diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py
index bf4be809c..d578e0082 100644
--- a/openlp/core/ui/themestab.py
+++ b/openlp/core/ui/themestab.py
@@ -22,11 +22,12 @@
"""
The Themes configuration tab
"""
-
-
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, Settings, ThemeLevel, UiStrings, translate
+from openlp.core.common import ThemeLevel
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab
from openlp.core.lib.ui import find_and_set_in_combo_box
diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py
index 80efa5fdf..c50cd1a85 100644
--- a/openlp/core/ui/themewizard.py
+++ b/openlp/core/ui/themewizard.py
@@ -24,8 +24,8 @@ The Create/Edit theme wizard
"""
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import UiStrings, translate, is_macosx
-from openlp.core.common.path import Path
+from openlp.core.common import is_macosx
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType
from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets
diff --git a/openlp/core/version.py b/openlp/core/version.py
index 14ddc40ff..6d038a3d9 100644
--- a/openlp/core/version.py
+++ b/openlp/core/version.py
@@ -34,7 +34,8 @@ from subprocess import Popen, PIPE
import requests
from PyQt5 import QtCore
-from openlp.core.common import AppLocation, Settings
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.settings import Settings
from openlp.core.threading import run_thread
log = logging.getLogger(__name__)
diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py
index ba63c61f4..992c5c360 100644
--- a/openlp/plugins/alerts/alertsplugin.py
+++ b/openlp/plugins/alerts/alertsplugin.py
@@ -25,8 +25,9 @@ import logging
from PyQt5 import QtGui
from openlp.core.api.http import register_endpoint
-from openlp.core.common import Settings, UiStrings, translate
from openlp.core.common.actions import ActionList
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.settings import Settings
from openlp.core.lib import Plugin, StringContent, build_icon
from openlp.core.lib.db import Manager
from openlp.core.lib.theme import VerticalType
diff --git a/openlp/plugins/alerts/endpoint.py b/openlp/plugins/alerts/endpoint.py
index 65800c5f6..19449b863 100644
--- a/openlp/plugins/alerts/endpoint.py
+++ b/openlp/plugins/alerts/endpoint.py
@@ -26,7 +26,7 @@ from urllib.parse import urlparse
from openlp.core.api.http.endpoint import Endpoint
from openlp.core.api.http import requires_auth
-from openlp.core.common import Registry
+from openlp.core.common.registry import Registry
from openlp.core.lib import PluginStatus
diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py
index e6e97d467..79dff94c0 100644
--- a/openlp/plugins/alerts/forms/alertdialog.py
+++ b/openlp/plugins/alerts/forms/alertdialog.py
@@ -22,7 +22,7 @@
from PyQt5 import QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button, create_button_box
diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py
index a27d93390..c7f9487c4 100644
--- a/openlp/plugins/alerts/forms/alertform.py
+++ b/openlp/plugins/alerts/forms/alertform.py
@@ -22,7 +22,8 @@
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, translate
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import Registry
from openlp.plugins.alerts.lib.db import AlertItem
from .alertdialog import Ui_AlertDialog
diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py
index 9b1abd226..6eb26ff57 100644
--- a/openlp/plugins/alerts/lib/alertsmanager.py
+++ b/openlp/plugins/alerts/lib/alertsmanager.py
@@ -23,10 +23,12 @@
The :mod:`~openlp.plugins.alerts.lib.alertsmanager` module contains the part of the plugin which manages storing and
displaying of alerts.
"""
-
from PyQt5 import QtCore
-from openlp.core.common import OpenLPMixin, RegistryMixin, Registry, RegistryProperties, Settings, translate
+from openlp.core.common.i18n import translate
+from openlp.core.common.mixins import OpenLPMixin, RegistryMixin
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
class AlertsManager(OpenLPMixin, RegistryMixin, QtCore.QObject, RegistryProperties):
diff --git a/openlp/plugins/alerts/lib/alertstab.py b/openlp/plugins/alerts/lib/alertstab.py
index f5934a30e..406e35607 100644
--- a/openlp/plugins/alerts/lib/alertstab.py
+++ b/openlp/plugins/alerts/lib/alertstab.py
@@ -22,7 +22,8 @@
from PyQt5 import QtGui, QtWidgets
-from openlp.core.common import Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab
from openlp.core.lib.ui import create_valign_selection_widgets
from openlp.core.ui.lib.colorbutton import ColorButton
diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py
index 4829ff234..7d5baf859 100644
--- a/openlp/plugins/bibles/bibleplugin.py
+++ b/openlp/plugins/bibles/bibleplugin.py
@@ -23,9 +23,9 @@
import logging
from openlp.core.api.http import register_endpoint
-from openlp.core.common import UiStrings
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.common.actions import ActionList
-from openlp.core.lib import Plugin, StringContent, build_icon, translate
+from openlp.core.lib import Plugin, StringContent, build_icon
from openlp.plugins.bibles.endpoint import api_bibles_endpoint, bibles_endpoint
from openlp.core.lib.ui import create_action
from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem, LayoutStyle, DisplayStyle, \
diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py
index fd270fced..4cb9ee453 100644
--- a/openlp/plugins/bibles/forms/bibleimportform.py
+++ b/openlp/plugins/bibles/forms/bibleimportform.py
@@ -34,8 +34,10 @@ try:
except:
PYSWORD_AVAILABLE = False
-from openlp.core.common import AppLocation, Settings, UiStrings, trace_error_handler, translate
-from openlp.core.common.languagemanager import get_locale_key
+from openlp.core.common import trace_error_handler
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings, translate, get_locale_key
+from openlp.core.common.settings import Settings
from openlp.core.lib.db import delete_database
from openlp.core.lib.exceptions import ValidationError
from openlp.core.lib.ui import critical_error_message_box
diff --git a/openlp/plugins/bibles/forms/booknamedialog.py b/openlp/plugins/bibles/forms/booknamedialog.py
index 6118ac293..07d749755 100644
--- a/openlp/plugins/bibles/forms/booknamedialog.py
+++ b/openlp/plugins/bibles/forms/booknamedialog.py
@@ -22,7 +22,7 @@
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/plugins/bibles/forms/booknameform.py b/openlp/plugins/bibles/forms/booknameform.py
index 588ba96d4..f78559ce5 100644
--- a/openlp/plugins/bibles/forms/booknameform.py
+++ b/openlp/plugins/bibles/forms/booknameform.py
@@ -29,7 +29,7 @@ import re
from PyQt5.QtWidgets import QDialog
from PyQt5 import QtCore
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.forms.booknamedialog import Ui_BookNameDialog
from openlp.plugins.bibles.lib import BibleStrings
diff --git a/openlp/plugins/bibles/forms/editbibledialog.py b/openlp/plugins/bibles/forms/editbibledialog.py
index ecd672503..799c2af7c 100644
--- a/openlp/plugins/bibles/forms/editbibledialog.py
+++ b/openlp/plugins/bibles/forms/editbibledialog.py
@@ -22,7 +22,7 @@
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
from openlp.plugins.bibles.lib import LanguageSelection, BibleStrings
diff --git a/openlp/plugins/bibles/forms/editbibleform.py b/openlp/plugins/bibles/forms/editbibleform.py
index 543531c2d..365d98a4e 100644
--- a/openlp/plugins/bibles/forms/editbibleform.py
+++ b/openlp/plugins/bibles/forms/editbibleform.py
@@ -21,12 +21,12 @@
###############################################################################
import logging
-import os
import re
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import RegistryProperties, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import RegistryProperties
from openlp.core.lib.ui import critical_error_message_box
from .editbibledialog import Ui_EditBibleDialog
from openlp.plugins.bibles.lib import BibleStrings
diff --git a/openlp/plugins/bibles/forms/languagedialog.py b/openlp/plugins/bibles/forms/languagedialog.py
index f51bc79fc..fad18bf05 100644
--- a/openlp/plugins/bibles/forms/languagedialog.py
+++ b/openlp/plugins/bibles/forms/languagedialog.py
@@ -22,7 +22,7 @@
from PyQt5 import QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/plugins/bibles/forms/languageform.py b/openlp/plugins/bibles/forms/languageform.py
index 6494950c8..80ce9e989 100644
--- a/openlp/plugins/bibles/forms/languageform.py
+++ b/openlp/plugins/bibles/forms/languageform.py
@@ -28,8 +28,7 @@ import logging
from PyQt5.QtWidgets import QDialog
from PyQt5 import QtCore
-from openlp.core.common import translate
-from openlp.core.common.languages import languages
+from openlp.core.common.i18n import LANGUAGES, translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.forms.languagedialog import Ui_LanguageDialog
@@ -55,7 +54,7 @@ class LanguageForm(QDialog, Ui_LanguageDialog):
if bible_name:
self.bible_label.setText(bible_name)
self.language_combo_box.addItem('')
- for language in languages:
+ for language in LANGUAGES:
self.language_combo_box.addItem(language.name, language.id)
return QDialog.exec(self)
diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py
index 9d90a94e2..9247485c1 100644
--- a/openlp/plugins/bibles/lib/__init__.py
+++ b/openlp/plugins/bibles/lib/__init__.py
@@ -26,8 +26,8 @@ plugin.
import logging
import re
-from openlp.core.common import Settings
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
+from openlp.core.common.settings import Settings
log = logging.getLogger(__name__)
diff --git a/openlp/plugins/bibles/lib/bibleimport.py b/openlp/plugins/bibles/lib/bibleimport.py
index 00c7262a0..61aa35a3e 100644
--- a/openlp/plugins/bibles/lib/bibleimport.py
+++ b/openlp/plugins/bibles/lib/bibleimport.py
@@ -23,7 +23,9 @@
from lxml import etree, objectify
from zipfile import is_zipfile
-from openlp.core.common import OpenLPMixin, Registry, RegistryProperties, languages, translate
+from openlp.core.common.mixins import OpenLPMixin
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.i18n import get_language, translate
from openlp.core.lib import ValidationError
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.lib.db import AlternativeBookNamesDB, BibleDB, BiblesResourcesDB
@@ -109,7 +111,7 @@ class BibleImport(OpenLPMixin, RegistryProperties, BibleDB):
"""
language_id = None
if file_language:
- language = languages.get_language(file_language)
+ language = get_language(file_language)
if language and language.id:
language_id = language.id
if not language_id:
diff --git a/openlp/plugins/bibles/lib/biblestab.py b/openlp/plugins/bibles/lib/biblestab.py
index 1420dcc33..21970c106 100644
--- a/openlp/plugins/bibles/lib/biblestab.py
+++ b/openlp/plugins/bibles/lib/biblestab.py
@@ -24,7 +24,9 @@ import logging
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab
from openlp.core.lib.ui import find_and_set_in_combo_box
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, update_reference_separators, \
diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py
index 64744113b..5d82fe613 100644
--- a/openlp/plugins/bibles/lib/db.py
+++ b/openlp/plugins/bibles/lib/db.py
@@ -33,7 +33,9 @@ from sqlalchemy.exc import OperationalError
from sqlalchemy.orm import class_mapper, mapper, relation
from sqlalchemy.orm.exc import UnmappedClassError
-from openlp.core.common import AppLocation, translate, clean_filename
+from openlp.core.common import clean_filename
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import translate
from openlp.core.lib.db import BaseModel, init_db, Manager
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.lib import BibleStrings, LanguageSelection, upgrade
@@ -546,7 +548,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
"""
log.debug('BiblesResourcesDB.get_book_like("{text}")'.format(text=string))
if not isinstance(string, str):
- name = str(string)
+ string = str(string)
books = BiblesResourcesDB.run_sql(
'SELECT id, testament_id, name, abbreviation, chapters FROM book_reference WHERE '
'LOWER(name) LIKE ? OR LOWER(abbreviation) LIKE ?',
diff --git a/openlp/plugins/bibles/lib/importers/csvbible.py b/openlp/plugins/bibles/lib/importers/csvbible.py
index e319bdf36..e897c4803 100644
--- a/openlp/plugins/bibles/lib/importers/csvbible.py
+++ b/openlp/plugins/bibles/lib/importers/csvbible.py
@@ -52,12 +52,12 @@ All CSV files are expected to use a comma (',') as the delimiter and double quot
import csv
from collections import namedtuple
-from openlp.core.common import get_file_encoding, translate
+from openlp.core.common import get_file_encoding
+from openlp.core.common.i18n import translate
from openlp.core.common.path import Path
from openlp.core.lib.exceptions import ValidationError
from openlp.plugins.bibles.lib.bibleimport import BibleImport
-
Book = namedtuple('Book', 'id, testament_id, name, abbreviation')
Verse = namedtuple('Verse', 'book_id_name, chapter_number, number, text')
diff --git a/openlp/plugins/bibles/lib/importers/http.py b/openlp/plugins/bibles/lib/importers/http.py
index ffc2ddfbf..5d3098b4d 100644
--- a/openlp/plugins/bibles/lib/importers/http.py
+++ b/openlp/plugins/bibles/lib/importers/http.py
@@ -30,9 +30,10 @@ import urllib.error
from bs4 import BeautifulSoup, NavigableString, Tag
-from openlp.core.common import Registry, RegistryProperties, translate
-from openlp.core.lib.ui import critical_error_message_box
from openlp.core.common.httputils import get_web_page
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.lib import SearchResults
from openlp.plugins.bibles.lib.bibleimport import BibleImport
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, Book
diff --git a/openlp/plugins/bibles/lib/importers/sword.py b/openlp/plugins/bibles/lib/importers/sword.py
index e01783087..fd7b91a44 100644
--- a/openlp/plugins/bibles/lib/importers/sword.py
+++ b/openlp/plugins/bibles/lib/importers/sword.py
@@ -23,7 +23,7 @@
import logging
from pysword import modules
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.lib.bibleimport import BibleImport
from openlp.plugins.bibles.lib.db import BiblesResourcesDB
diff --git a/openlp/plugins/bibles/lib/importers/zefania.py b/openlp/plugins/bibles/lib/importers/zefania.py
index 221d57cb3..a3849a7a0 100644
--- a/openlp/plugins/bibles/lib/importers/zefania.py
+++ b/openlp/plugins/bibles/lib/importers/zefania.py
@@ -22,7 +22,7 @@
import logging
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.lib.bibleimport import BibleImport
from openlp.plugins.bibles.lib.db import BiblesResourcesDB
diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py
index 5c8728e58..55444f080 100644
--- a/openlp/plugins/bibles/lib/manager.py
+++ b/openlp/plugins/bibles/lib/manager.py
@@ -22,8 +22,13 @@
import logging
-from openlp.core.common import AppLocation, OpenLPMixin, RegistryProperties, Settings, translate, delete_file, UiStrings
+from openlp.core.common import delete_file
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.mixins import OpenLPMixin
from openlp.core.common.path import Path
+from openlp.core.common.registry import RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.plugins.bibles.lib import LanguageSelection, parse_reference
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
from .importers.csvbible import CSVBible
diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py
index a05747705..10bb8d6ec 100755
--- a/openlp/plugins/bibles/lib/mediaitem.py
+++ b/openlp/plugins/bibles/lib/mediaitem.py
@@ -26,12 +26,13 @@ from enum import IntEnum, unique
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate, get_locale_key
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemContext
from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import set_case_insensitive_completer, create_horizontal_adjusting_combo_box, \
critical_error_message_box, find_and_set_in_combo_box, build_icon
-from openlp.core.common.languagemanager import get_locale_key
from openlp.plugins.bibles.forms.bibleimportform import BibleImportForm
from openlp.plugins.bibles.forms.editbibleform import EditBibleForm
from openlp.plugins.bibles.lib import DisplayStyle, LayoutStyle, VerseReferenceList, \
diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py
index 99eda1d52..8cb02ab17 100644
--- a/openlp/plugins/custom/customplugin.py
+++ b/openlp/plugins/custom/customplugin.py
@@ -27,7 +27,8 @@ for the Custom Slides plugin.
import logging
from openlp.core.api.http import register_endpoint
-from openlp.core.lib import Plugin, StringContent, build_icon, translate
+from openlp.core.common.i18n import translate
+from openlp.core.lib import Plugin, StringContent, build_icon
from openlp.core.lib.db import Manager
from openlp.plugins.custom.endpoint import api_custom_endpoint, custom_endpoint
from openlp.plugins.custom.lib import CustomMediaItem, CustomTab
diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py
index c71ac3d70..e0f5646d3 100644
--- a/openlp/plugins/custom/forms/editcustomdialog.py
+++ b/openlp/plugins/custom/forms/editcustomdialog.py
@@ -19,10 +19,9 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-
from PyQt5 import QtWidgets
-from openlp.core.common import UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box, create_button
diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py
index 1bd2187f2..ee2d7b415 100644
--- a/openlp/plugins/custom/forms/editcustomform.py
+++ b/openlp/plugins/custom/forms/editcustomform.py
@@ -24,7 +24,8 @@ import logging
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, translate
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import Registry
from openlp.core.lib.ui import critical_error_message_box, find_and_set_in_combo_box
from openlp.plugins.custom.lib import CustomXMLBuilder, CustomXMLParser
from openlp.plugins.custom.lib.db import CustomSlide
diff --git a/openlp/plugins/custom/forms/editcustomslidedialog.py b/openlp/plugins/custom/forms/editcustomslidedialog.py
index ede46a6ee..452146feb 100644
--- a/openlp/plugins/custom/forms/editcustomslidedialog.py
+++ b/openlp/plugins/custom/forms/editcustomslidedialog.py
@@ -22,7 +22,7 @@
from PyQt5 import QtWidgets
-from openlp.core.common import UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button, create_button_box
from openlp.core.ui.lib import SpellTextEdit
diff --git a/openlp/plugins/custom/lib/customtab.py b/openlp/plugins/custom/lib/customtab.py
index 167aa6d0d..2239ac2ce 100644
--- a/openlp/plugins/custom/lib/customtab.py
+++ b/openlp/plugins/custom/lib/customtab.py
@@ -23,10 +23,10 @@
The :mod:`~openlp.plugins.custom.lib.customtab` module contains the settings tab
for the Custom Slides plugin, which is inserted into the configuration dialog.
"""
-
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Settings, translate
+from openlp.core.common.i18n import translate
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab
diff --git a/openlp/plugins/custom/lib/db.py b/openlp/plugins/custom/lib/db.py
index b1e42e3d9..dc1f74567 100644
--- a/openlp/plugins/custom/lib/db.py
+++ b/openlp/plugins/custom/lib/db.py
@@ -23,12 +23,11 @@
The :mod:`db` module provides the database and schema that is the backend for
the Custom plugin
"""
-
from sqlalchemy import Column, Table, types
from sqlalchemy.orm import mapper
+from openlp.core.common.i18n import get_locale_key
from openlp.core.lib.db import BaseModel, init_db
-from openlp.core.common.languagemanager import get_locale_key
class CustomSlide(BaseModel):
diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py
index c90d14e10..35eddc117 100644
--- a/openlp/plugins/custom/lib/mediaitem.py
+++ b/openlp/plugins/custom/lib/mediaitem.py
@@ -25,7 +25,9 @@ import logging
from PyQt5 import QtCore, QtWidgets
from sqlalchemy.sql import or_, func, and_
-from openlp.core.common import Registry, Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemContext, PluginStatus, \
check_item_selected
from openlp.plugins.custom.forms.editcustomform import EditCustomForm
diff --git a/openlp/plugins/images/forms/addgroupdialog.py b/openlp/plugins/images/forms/addgroupdialog.py
index 233bfef31..665fcd824 100644
--- a/openlp/plugins/images/forms/addgroupdialog.py
+++ b/openlp/plugins/images/forms/addgroupdialog.py
@@ -22,7 +22,7 @@
from PyQt5 import QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/plugins/images/forms/addgroupform.py b/openlp/plugins/images/forms/addgroupform.py
index 953d02339..88f9377f3 100644
--- a/openlp/plugins/images/forms/addgroupform.py
+++ b/openlp/plugins/images/forms/addgroupform.py
@@ -22,7 +22,7 @@
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.images.forms.addgroupdialog import Ui_AddGroupDialog
diff --git a/openlp/plugins/images/forms/choosegroupdialog.py b/openlp/plugins/images/forms/choosegroupdialog.py
index f71a74e70..35e959fb5 100644
--- a/openlp/plugins/images/forms/choosegroupdialog.py
+++ b/openlp/plugins/images/forms/choosegroupdialog.py
@@ -22,7 +22,7 @@
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py
index 36051a505..cfa5448f5 100644
--- a/openlp/plugins/images/imageplugin.py
+++ b/openlp/plugins/images/imageplugin.py
@@ -25,7 +25,8 @@ from PyQt5 import QtGui
import logging
from openlp.core.api.http import register_endpoint
-from openlp.core.common import Settings, translate
+from openlp.core.common.i18n import translate
+from openlp.core.common.settings import Settings
from openlp.core.lib import Plugin, StringContent, ImageSource, build_icon
from openlp.core.lib.db import Manager
from openlp.plugins.images.endpoint import api_images_endpoint, images_endpoint
diff --git a/openlp/plugins/images/lib/imagetab.py b/openlp/plugins/images/lib/imagetab.py
index 565ef6543..23b742bfb 100644
--- a/openlp/plugins/images/lib/imagetab.py
+++ b/openlp/plugins/images/lib/imagetab.py
@@ -22,7 +22,8 @@
from PyQt5 import QtWidgets
-from openlp.core.common import Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab
from openlp.core.ui.lib.colorbutton import ColorButton
diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py
index b436d2708..134dbe2eb 100644
--- a/openlp/plugins/images/lib/mediaitem.py
+++ b/openlp/plugins/images/lib/mediaitem.py
@@ -24,14 +24,16 @@ import logging
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, AppLocation, Settings, UiStrings, check_directory_exists, translate, \
- delete_file, get_images_filter
-from openlp.core.common.path import Path
+from openlp.core.common import delete_file, get_images_filter
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings, translate, get_locale_key
+from openlp.core.common.path import Path, create_paths
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import ItemCapabilities, MediaManagerItem, ServiceItemContext, StringContent, build_icon, \
check_item_selected, create_thumb, validate_thumb
from openlp.core.lib.ui import create_widget_action, critical_error_message_box
from openlp.core.ui.lib.treewidgetwithdnd import TreeWidgetWithDnD
-from openlp.core.common.languagemanager import get_locale_key
from openlp.plugins.images.forms import AddGroupForm, ChooseGroupForm
from openlp.plugins.images.lib.db import ImageFilenames, ImageGroups
@@ -99,7 +101,7 @@ class ImageMediaItem(MediaManagerItem):
self.list_view.setIndentation(self.list_view.default_indentation)
self.list_view.allow_internal_dnd = True
self.service_path = AppLocation.get_section_data_path(self.settings_section) / 'thumbnails'
- check_directory_exists(self.service_path)
+ create_paths(self.service_path)
# Load images from the database
self.load_full_list(
self.manager.get_all_objects(ImageFilenames, order_by_ref=ImageFilenames.file_path), initial_load=True)
diff --git a/openlp/plugins/images/lib/upgrade.py b/openlp/plugins/images/lib/upgrade.py
index d467e9d3c..bc1310d79 100644
--- a/openlp/plugins/images/lib/upgrade.py
+++ b/openlp/plugins/images/lib/upgrade.py
@@ -27,7 +27,7 @@ import logging
from sqlalchemy import Column, Table
-from openlp.core.common import AppLocation
+from openlp.core.common.applocation import AppLocation
from openlp.core.common.db import drop_columns
from openlp.core.common.json import OpenLPJsonEncoder
from openlp.core.common.path import Path
diff --git a/openlp/plugins/media/forms/mediaclipselectordialog.py b/openlp/plugins/media/forms/mediaclipselectordialog.py
index 82e9a77b5..38ecda99c 100644
--- a/openlp/plugins/media/forms/mediaclipselectordialog.py
+++ b/openlp/plugins/media/forms/mediaclipselectordialog.py
@@ -23,7 +23,7 @@
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib import build_icon
diff --git a/openlp/plugins/media/forms/mediaclipselectorform.py b/openlp/plugins/media/forms/mediaclipselectorform.py
index d6e6fd352..f48e9b09e 100644
--- a/openlp/plugins/media/forms/mediaclipselectorform.py
+++ b/openlp/plugins/media/forms/mediaclipselectorform.py
@@ -19,7 +19,6 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-
import os
import logging
import re
@@ -28,7 +27,9 @@ from datetime import datetime
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import translate, is_win, is_linux, is_macosx, RegistryProperties
+from openlp.core.common import is_win, is_linux, is_macosx
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import RegistryProperties
from openlp.plugins.media.forms.mediaclipselectordialog import Ui_MediaClipSelector
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.media.vlcplayer import get_vlc
@@ -683,7 +684,6 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro
elif is_macosx():
# Look for DVD folders in devices to find optical devices
volumes = os.listdir('/Volumes')
- candidates = list()
for volume in volumes:
if volume.startswith('.'):
continue
diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py
index 154d033c1..ab0cf4968 100644
--- a/openlp/plugins/media/lib/mediaitem.py
+++ b/openlp/plugins/media/lib/mediaitem.py
@@ -25,15 +25,16 @@ import os
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, check_directory_exists, UiStrings,\
- translate
-from openlp.core.common.path import Path, path_to_str, str_to_path
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings, translate, get_locale_key
+from openlp.core.common.path import Path, path_to_str, create_paths
+from openlp.core.common.registry import Registry, RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib import ItemCapabilities, MediaManagerItem, MediaType, ServiceItem, ServiceItemContext, \
build_icon, check_item_selected
from openlp.core.lib.ui import create_widget_action, critical_error_message_box, create_horizontal_adjusting_combo_box
from openlp.core.ui import DisplayControllerType
from openlp.core.ui.media import get_media_players, set_media_players, parse_optical_path, format_milliseconds
-from openlp.core.common.languagemanager import get_locale_key
from openlp.core.ui.media.vlcplayer import get_vlc
if get_vlc() is not None:
@@ -302,7 +303,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
"""
self.list_view.clear()
self.service_path = os.path.join(str(AppLocation.get_section_data_path(self.settings_section)), 'thumbnails')
- check_directory_exists(Path(self.service_path))
+ create_paths(Path(self.service_path))
self.load_list([path_to_str(file) for file in Settings().value(self.settings_section + '/media files')])
self.rebuild_players()
diff --git a/openlp/plugins/media/lib/mediatab.py b/openlp/plugins/media/lib/mediatab.py
index a4f2652f6..84c339a27 100644
--- a/openlp/plugins/media/lib/mediatab.py
+++ b/openlp/plugins/media/lib/mediatab.py
@@ -22,7 +22,8 @@
from PyQt5 import QtWidgets
-from openlp.core.common import Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab
diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py
index f73cae56d..5efe8c910 100644
--- a/openlp/plugins/media/mediaplugin.py
+++ b/openlp/plugins/media/mediaplugin.py
@@ -22,14 +22,16 @@
"""
The Media plugin
"""
-
import logging
import os
import re
+
from PyQt5 import QtCore
from openlp.core.api.http import register_endpoint
-from openlp.core.common import AppLocation, translate, check_binary_exists
+from openlp.core.common import check_binary_exists
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import translate
from openlp.core.common.path import Path
from openlp.core.lib import Plugin, StringContent, build_icon
from openlp.plugins.media.endpoint import api_media_endpoint, media_endpoint
diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py
index 0e57f9577..cb1d7ec0e 100644
--- a/openlp/plugins/presentations/lib/impresscontroller.py
+++ b/openlp/plugins/presentations/lib/impresscontroller.py
@@ -36,8 +36,9 @@ import time
from PyQt5 import QtCore
-from openlp.core.common import Registry, delete_file, get_uno_command, get_uno_instance, is_win
-from openlp.core.lib import ScreenList
+from openlp.core.common import delete_file, get_uno_command, get_uno_instance, is_win
+from openlp.core.common.registry import Registry
+from openlp.core.display.screens import ScreenList
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument, \
TextType
diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py
index 8061bb193..b801597b1 100644
--- a/openlp/plugins/presentations/lib/mediaitem.py
+++ b/openlp/plugins/presentations/lib/mediaitem.py
@@ -23,9 +23,10 @@ import logging
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, Settings, UiStrings, translate
-from openlp.core.common.languagemanager import get_locale_key
+from openlp.core.common.i18n import UiStrings, translate, get_locale_key
from openlp.core.common.path import Path, path_to_str, str_to_path
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemContext,\
build_icon, check_item_selected, create_thumb, validate_thumb
from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box
diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py
index ef4a0bdc0..53674f84b 100644
--- a/openlp/plugins/presentations/lib/messagelistener.py
+++ b/openlp/plugins/presentations/lib/messagelistener.py
@@ -24,7 +24,8 @@ import logging
from PyQt5 import QtCore
-from openlp.core.common import Registry, Settings
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.common.path import Path
from openlp.core.lib import ServiceItemContext
from openlp.core.ui import HideMode
diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py
index 81fa3994a..26eb87d85 100644
--- a/openlp/plugins/presentations/lib/pdfcontroller.py
+++ b/openlp/plugins/presentations/lib/pdfcontroller.py
@@ -25,10 +25,11 @@ import logging
import re
from subprocess import check_output, CalledProcessError
-from openlp.core.common import AppLocation, check_binary_exists
-from openlp.core.common import Settings, is_win
+from openlp.core.common import check_binary_exists, is_win
+from openlp.core.common.applocation import AppLocation
from openlp.core.common.path import which
-from openlp.core.lib import ScreenList
+from openlp.core.common.settings import Settings
+from openlp.core.display.screens import ScreenList
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
if is_win():
@@ -131,7 +132,6 @@ class PdfController(PresentationController):
elif (application_path / 'mutool.exe').is_file():
self.mutoolbin = application_path / 'mutool.exe'
else:
- DEVNULL = open(os.devnull, 'wb')
# First try to find mudraw
self.mudrawbin = which('mudraw')
# if mudraw isn't installed, try mutool
diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py
index 7cbce786c..b01c90700 100644
--- a/openlp/plugins/presentations/lib/powerpointcontroller.py
+++ b/openlp/plugins/presentations/lib/powerpointcontroller.py
@@ -25,11 +25,15 @@ This module is for controlling powerpoint. PPT API documentation:
2010: https://msdn.microsoft.com/en-us/library/office/ff743835%28v=office.14%29.aspx
2013: https://msdn.microsoft.com/en-us/library/office/ff743835.aspx
"""
-import os
import logging
-import time
-from openlp.core.common import is_win, Settings
+from openlp.core.common import is_win, trace_error_handler
+from openlp.core.common.i18n import UiStrings
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
+from openlp.core.display.screens import ScreenList
+from openlp.core.lib.ui import critical_error_message_box, translate
+from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
if is_win():
from win32com.client import Dispatch
@@ -39,12 +43,6 @@ if is_win():
import winreg
import pywintypes
-
-from openlp.core.common import Registry, UiStrings, trace_error_handler
-from openlp.core.lib import ScreenList
-from openlp.core.lib.ui import critical_error_message_box, translate
-from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
-
log = logging.getLogger(__name__)
diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py
index 1bd30ca97..daa73f48f 100644
--- a/openlp/plugins/presentations/lib/pptviewcontroller.py
+++ b/openlp/plugins/presentations/lib/pptviewcontroller.py
@@ -19,25 +19,20 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-
-import os
import logging
import zipfile
import re
from xml.etree import ElementTree
-
from openlp.core.common import is_win
+from openlp.core.common.applocation import AppLocation
+from openlp.core.display.screens import ScreenList
+from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
if is_win():
from ctypes import cdll
from ctypes.wintypes import RECT
-from openlp.core.common import AppLocation
-from openlp.core.lib import ScreenList
-from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
-
-
log = logging.getLogger(__name__)
diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py
index 0cdd29f19..b19d91837 100644
--- a/openlp/plugins/presentations/lib/presentationcontroller.py
+++ b/openlp/plugins/presentations/lib/presentationcontroller.py
@@ -23,8 +23,11 @@ import logging
from PyQt5 import QtCore
-from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists, md5_hash
-from openlp.core.common.path import Path, rmtree
+from openlp.core.common import md5_hash
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.path import Path, create_paths, rmtree
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import create_thumb, validate_thumb
log = logging.getLogger(__name__)
@@ -103,7 +106,7 @@ class PresentationDocument(object):
"""
self.slide_number = 0
self.file_path = document_path
- check_directory_exists(self.get_thumbnail_folder())
+ create_paths(self.get_thumbnail_folder())
def load_presentation(self):
"""
@@ -428,8 +431,7 @@ class PresentationController(object):
self.temp_folder = AppLocation.get_section_data_path(self.settings_section) / name
self.thumbnail_folder = AppLocation.get_section_data_path(self.settings_section) / 'thumbnails'
self.thumbnail_prefix = 'slide'
- check_directory_exists(self.thumbnail_folder)
- check_directory_exists(self.temp_folder)
+ create_paths(self.thumbnail_folder, self.temp_folder)
def enabled(self):
"""
diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py
index ca9ceacbc..96fcc573a 100644
--- a/openlp/plugins/presentations/lib/presentationtab.py
+++ b/openlp/plugins/presentations/lib/presentationtab.py
@@ -22,8 +22,8 @@
from PyQt5 import QtWidgets
-from openlp.core.common import Settings, UiStrings, translate
-from openlp.core.common.path import path_to_str, str_to_path
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.settings import Settings
from openlp.core.lib import SettingsTab
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.lib import PathEdit
diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py
index dc9065d81..7f3333049 100644
--- a/openlp/plugins/presentations/presentationplugin.py
+++ b/openlp/plugins/presentations/presentationplugin.py
@@ -29,7 +29,8 @@ import logging
from PyQt5 import QtCore
from openlp.core.api.http import register_endpoint
-from openlp.core.common import extension_loader, translate
+from openlp.core.common import extension_loader
+from openlp.core.common.i18n import translate
from openlp.core.lib import Plugin, StringContent, build_icon
from openlp.plugins.presentations.endpoint import api_presentations_endpoint, presentations_endpoint
from openlp.plugins.presentations.lib import PresentationController, PresentationMediaItem, PresentationTab
diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py
index 45b94daec..d4f560e9b 100644
--- a/openlp/plugins/songs/forms/authorsdialog.py
+++ b/openlp/plugins/songs/forms/authorsdialog.py
@@ -22,7 +22,8 @@
from PyQt5 import QtWidgets
-from openlp.core.lib import translate, build_icon
+from openlp.core.common.i18n import translate
+from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/plugins/songs/forms/authorsform.py b/openlp/plugins/songs/forms/authorsform.py
index 84e0343e9..75ae61035 100644
--- a/openlp/plugins/songs/forms/authorsform.py
+++ b/openlp/plugins/songs/forms/authorsform.py
@@ -22,7 +22,7 @@
from PyQt5 import QtCore, QtWidgets
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.songs.forms.authorsdialog import Ui_AuthorsDialog
diff --git a/openlp/plugins/songs/forms/duplicatesongremovalform.py b/openlp/plugins/songs/forms/duplicatesongremovalform.py
index b89748402..d2238d4b7 100644
--- a/openlp/plugins/songs/forms/duplicatesongremovalform.py
+++ b/openlp/plugins/songs/forms/duplicatesongremovalform.py
@@ -25,14 +25,14 @@ The duplicate song removal logic for OpenLP.
import logging
import multiprocessing
-import os
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, translate
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import Registry, RegistryProperties
from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings
from openlp.plugins.songs.lib import delete_song
-from openlp.plugins.songs.lib.db import Song, MediaFile
+from openlp.plugins.songs.lib.db import Song
from openlp.plugins.songs.forms.songreviewwidget import SongReviewWidget
from openlp.plugins.songs.lib.songcompare import songs_probably_equal
diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py
index 46f9b899c..9cf133f06 100644
--- a/openlp/plugins/songs/forms/editsongdialog.py
+++ b/openlp/plugins/songs/forms/editsongdialog.py
@@ -22,7 +22,7 @@
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box, create_button
from openlp.core.ui import SingleColumnTableWidget
diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py
index db7053b91..bdb1a9353 100644
--- a/openlp/plugins/songs/forms/editsongform.py
+++ b/openlp/plugins/songs/forms/editsongform.py
@@ -24,14 +24,14 @@ The :mod:`~openlp.plugins.songs.forms.editsongform` module contains the form
used to edit songs.
"""
import logging
-import os
import re
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, AppLocation, UiStrings, check_directory_exists, translate
-from openlp.core.common.languagemanager import get_natural_key
-from openlp.core.common.path import copyfile
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings, translate, get_natural_key
+from openlp.core.common.path import create_paths, copyfile
+from openlp.core.common.registry import Registry, RegistryProperties
from openlp.core.lib import PluginStatus, MediaType, create_separated_list
from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, find_and_set_in_combo_box
from openlp.core.ui.lib.filedialog import FileDialog
@@ -1066,7 +1066,7 @@ class EditSongForm(QtWidgets.QDialog, Ui_EditSongDialog, RegistryProperties):
audio_paths = [a.file_path for a in self.song.media_files]
log.debug(audio_paths)
save_path = AppLocation.get_section_data_path(self.media_item.plugin.name) / 'audio' / str(self.song.id)
- check_directory_exists(save_path)
+ create_paths(save_path)
self.song.media_files = []
file_paths = []
for row in range(self.audio_list_widget.count()):
diff --git a/openlp/plugins/songs/forms/editversedialog.py b/openlp/plugins/songs/forms/editversedialog.py
index 4826b1a5d..63ca0cf27 100644
--- a/openlp/plugins/songs/forms/editversedialog.py
+++ b/openlp/plugins/songs/forms/editversedialog.py
@@ -22,8 +22,9 @@
from PyQt5 import QtWidgets
-from openlp.core.common import Settings, UiStrings
-from openlp.core.lib import build_icon, translate
+from openlp.core.common.settings import Settings
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
from openlp.core.ui.lib import SpellTextEdit
from openlp.plugins.songs.lib import VerseType
@@ -42,10 +43,14 @@ class Ui_EditVerseDialog(object):
self.dialog_layout.addWidget(self.verse_text_edit)
self.verse_type_layout = QtWidgets.QHBoxLayout()
self.verse_type_layout.setObjectName('verse_type_layout')
- self.split_button = QtWidgets.QPushButton(edit_verse_dialog)
- self.split_button.setIcon(build_icon(':/general/general_add.png'))
- self.split_button.setObjectName('split_button')
- self.verse_type_layout.addWidget(self.split_button)
+ self.forced_split_button = QtWidgets.QPushButton(edit_verse_dialog)
+ self.forced_split_button.setIcon(build_icon(':/general/general_add.png'))
+ self.forced_split_button.setObjectName('forced_split_button')
+ self.verse_type_layout.addWidget(self.forced_split_button)
+ self.overflow_split_button = QtWidgets.QPushButton(edit_verse_dialog)
+ self.overflow_split_button.setIcon(build_icon(':/general/general_add.png'))
+ self.overflow_split_button.setObjectName('overflow_split_button')
+ self.verse_type_layout.addWidget(self.overflow_split_button)
self.verse_type_label = QtWidgets.QLabel(edit_verse_dialog)
self.verse_type_label.setObjectName('verse_type_label')
self.verse_type_layout.addWidget(self.verse_type_label)
@@ -93,8 +98,11 @@ class Ui_EditVerseDialog(object):
self.verse_type_combo_box.setItemText(VerseType.Intro, VerseType.translated_names[VerseType.Intro])
self.verse_type_combo_box.setItemText(VerseType.Ending, VerseType.translated_names[VerseType.Ending])
self.verse_type_combo_box.setItemText(VerseType.Other, VerseType.translated_names[VerseType.Other])
- self.split_button.setText(UiStrings().Split)
- self.split_button.setToolTip(UiStrings().SplitToolTip)
+ self.overflow_split_button.setText(UiStrings().Split)
+ self.overflow_split_button.setToolTip(UiStrings().SplitToolTip)
+ self.forced_split_button.setText(translate('SongsPlugin.EditVerseForm', '&Forced Split'))
+ self.forced_split_button.setToolTip(translate('SongsPlugin.EditVerseForm', 'Split the verse when displayed '
+ 'regardless of the screen size.'))
self.insert_button.setText(translate('SongsPlugin.EditVerseForm', '&Insert'))
self.insert_button.setToolTip(translate('SongsPlugin.EditVerseForm',
'Split a slide into two by inserting a verse splitter.'))
diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py
index 1e36df1e4..09ba1e300 100644
--- a/openlp/plugins/songs/forms/editverseform.py
+++ b/openlp/plugins/songs/forms/editverseform.py
@@ -25,10 +25,11 @@ import logging
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.plugins.songs.lib import VerseType, transpose_lyrics
from openlp.core.lib.ui import critical_error_message_box
-from openlp.core.common import translate, Settings
-from .editversedialog import Ui_EditVerseDialog
+from openlp.core.common.i18n import translate
+from openlp.core.common.settings import Settings
+from openlp.plugins.songs.forms.editversedialog import Ui_EditVerseDialog
+from openlp.plugins.songs.lib import VerseType, transpose_lyrics
log = logging.getLogger(__name__)
@@ -48,12 +49,13 @@ class EditVerseForm(QtWidgets.QDialog, Ui_EditVerseDialog):
self.setupUi(self)
self.has_single_verse = False
self.insert_button.clicked.connect(self.on_insert_button_clicked)
- self.split_button.clicked.connect(self.on_split_button_clicked)
+ self.overflow_split_button.clicked.connect(self.on_overflow_split_button_clicked)
self.verse_text_edit.cursorPositionChanged.connect(self.on_cursor_position_changed)
self.verse_type_combo_box.currentIndexChanged.connect(self.on_verse_type_combo_box_changed)
+ self.forced_split_button.clicked.connect(self.on_forced_split_button_clicked)
if Settings().value('songs/enable chords'):
- self.transpose_down_button.clicked.connect(self.on_transepose_down_button_clicked)
- self.transpose_up_button.clicked.connect(self.on_transepose_up_button_clicked)
+ self.transpose_down_button.clicked.connect(self.on_transpose_down_button_clicked)
+ self.transpose_up_button.clicked.connect(self.on_transpose_up_button_clicked)
def insert_verse(self, verse_tag, verse_num=1):
"""
@@ -68,13 +70,27 @@ class EditVerseForm(QtWidgets.QDialog, Ui_EditVerseDialog):
self.verse_text_edit.insertPlainText('---[{tag}:{number}]---\n'.format(tag=verse_tag, number=verse_num))
self.verse_text_edit.setFocus()
- def on_split_button_clicked(self):
+ def on_overflow_split_button_clicked(self):
"""
- The split button has been pressed
+ The optional split button has been pressed so we need add the split
+ """
+ self._add_splitter_to_text('[---]')
+
+ def on_forced_split_button_clicked(self):
+ """
+ The force split button has been pressed so we need add the split
+ """
+ self._add_splitter_to_text('[--}{--]')
+
+ def _add_splitter_to_text(self, insert_string):
+ """
+ Add a custom splitter to the song text
+
+ :param insert_string: The string to insert
+ :return:
"""
text = self.verse_text_edit.toPlainText()
position = self.verse_text_edit.textCursor().position()
- insert_string = '[---]'
if position and text[position - 1] != '\n':
insert_string = '\n' + insert_string
if position == len(text) or text[position] != '\n':
@@ -101,7 +117,7 @@ class EditVerseForm(QtWidgets.QDialog, Ui_EditVerseDialog):
"""
self.update_suggested_verse_number()
- def on_transepose_up_button_clicked(self):
+ def on_transpose_up_button_clicked(self):
"""
The transpose up button clicked
"""
@@ -118,7 +134,7 @@ class EditVerseForm(QtWidgets.QDialog, Ui_EditVerseDialog):
self.verse_text_edit.setFocus()
self.verse_text_edit.moveCursor(QtGui.QTextCursor.End)
- def on_transepose_down_button_clicked(self):
+ def on_transpose_down_button_clicked(self):
"""
The transpose down button clicked
"""
@@ -217,7 +233,7 @@ class EditVerseForm(QtWidgets.QDialog, Ui_EditVerseDialog):
"""
if Settings().value('songs/enable chords'):
try:
- transposed_lyrics = transpose_lyrics(self.verse_text_edit.toPlainText(), 1)
+ transpose_lyrics(self.verse_text_edit.toPlainText(), 1)
super(EditVerseForm, self).accept()
except ValueError as ve:
# Transposing failed
diff --git a/openlp/plugins/songs/forms/mediafilesdialog.py b/openlp/plugins/songs/forms/mediafilesdialog.py
index 4f9ec4f27..41a6862d3 100644
--- a/openlp/plugins/songs/forms/mediafilesdialog.py
+++ b/openlp/plugins/songs/forms/mediafilesdialog.py
@@ -22,7 +22,8 @@
from PyQt5 import QtCore, QtWidgets
-from openlp.core.lib import translate, build_icon
+from openlp.core.common.i18n import translate
+from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/plugins/songs/forms/songbookdialog.py b/openlp/plugins/songs/forms/songbookdialog.py
index 1242803b7..4a248cb48 100644
--- a/openlp/plugins/songs/forms/songbookdialog.py
+++ b/openlp/plugins/songs/forms/songbookdialog.py
@@ -22,7 +22,8 @@
from PyQt5 import QtWidgets
-from openlp.core.lib import translate, build_icon
+from openlp.core.common.i18n import translate
+from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/plugins/songs/forms/songbookform.py b/openlp/plugins/songs/forms/songbookform.py
index fc1b87c09..594768aaf 100644
--- a/openlp/plugins/songs/forms/songbookform.py
+++ b/openlp/plugins/songs/forms/songbookform.py
@@ -25,7 +25,7 @@ This module contains the song book form
from PyQt5 import QtCore, QtWidgets
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.songs.forms.songbookdialog import Ui_SongBookDialog
diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py
index 582d63a84..28ca8054c 100644
--- a/openlp/plugins/songs/forms/songexportform.py
+++ b/openlp/plugins/songs/forms/songexportform.py
@@ -27,7 +27,9 @@ import logging
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import create_separated_list
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.lib import PathEdit, PathType
diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py
index 5a88ad4cb..acfa4b5b8 100644
--- a/openlp/plugins/songs/forms/songimportform.py
+++ b/openlp/plugins/songs/forms/songimportform.py
@@ -26,7 +26,9 @@ import logging
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import RegistryProperties, Settings, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate
+from openlp.core.common.registry import RegistryProperties
+from openlp.core.common.settings import Settings
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.lib import PathEdit, PathType
from openlp.core.ui.lib.filedialog import FileDialog
@@ -191,7 +193,6 @@ class SongImportForm(OpenLPWizard, RegistryProperties):
Re-implement the validateCurrentPage() method. Validate the current page before moving on to the next page.
Provide each song format class with a chance to validate its input by overriding is_valid_source().
"""
- completeChanged = QtCore.pyqtSignal()
if self.currentPage() == self.welcome_page:
return True
elif self.currentPage() == self.source_page:
diff --git a/openlp/plugins/songs/forms/songmaintenancedialog.py b/openlp/plugins/songs/forms/songmaintenancedialog.py
index be226f55e..728861f26 100644
--- a/openlp/plugins/songs/forms/songmaintenancedialog.py
+++ b/openlp/plugins/songs/forms/songmaintenancedialog.py
@@ -22,7 +22,7 @@
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import UiStrings
+from openlp.core.common.i18n import UiStrings
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
from openlp.plugins.songs.lib.ui import SongStrings
diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py
index 766231712..4dc485e24 100644
--- a/openlp/plugins/songs/forms/songmaintenanceform.py
+++ b/openlp/plugins/songs/forms/songmaintenanceform.py
@@ -24,9 +24,9 @@ import logging
from PyQt5 import QtCore, QtWidgets
from sqlalchemy.sql import and_
-from openlp.core.common import Registry, RegistryProperties, UiStrings, translate
+from openlp.core.common.i18n import UiStrings, translate, get_natural_key
+from openlp.core.common.registry import Registry, RegistryProperties
from openlp.core.lib.ui import critical_error_message_box
-from openlp.core.common.languagemanager import get_natural_key
from openlp.plugins.songs.forms.authorsform import AuthorsForm
from openlp.plugins.songs.forms.topicsform import TopicsForm
from openlp.plugins.songs.forms.songbookform import SongBookForm
diff --git a/openlp/plugins/songs/forms/songselectdialog.py b/openlp/plugins/songs/forms/songselectdialog.py
index 512e7b26d..b784071bd 100644
--- a/openlp/plugins/songs/forms/songselectdialog.py
+++ b/openlp/plugins/songs/forms/songselectdialog.py
@@ -25,9 +25,10 @@ The :mod:`~openlp.plugins.songs.forms.songselectdialog` module contains the user
from PyQt5 import QtCore, QtWidgets
-from openlp.core.ui.lib.historycombobox import HistoryComboBox
-from openlp.core.lib import translate, build_icon
+from openlp.core.common.i18n import translate
+from openlp.core.lib import build_icon
from openlp.core.ui import SingleColumnTableWidget
+from openlp.core.ui.lib.historycombobox import HistoryComboBox
class Ui_SongSelectDialog(object):
diff --git a/openlp/plugins/songs/forms/songselectform.py b/openlp/plugins/songs/forms/songselectform.py
index 4863529a9..5d175bb5e 100644
--- a/openlp/plugins/songs/forms/songselectform.py
+++ b/openlp/plugins/songs/forms/songselectform.py
@@ -22,16 +22,15 @@
"""
The :mod:`~openlp.plugins.songs.forms.songselectform` module contains the GUI for the SongSelect importer
"""
-
import logging
-import os
from time import sleep
from PyQt5 import QtCore, QtWidgets
-from openlp.core import Settings
-from openlp.core.common import Registry, is_win
-from openlp.core.lib import translate
+from openlp.core.common import is_win
+from openlp.core.common.i18n import translate
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.plugins.songs.forms.songselectdialog import Ui_SongSelectDialog
from openlp.plugins.songs.lib.songselect import SongSelectImport
diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py
index 4cc32d245..fe5020941 100644
--- a/openlp/plugins/songs/forms/topicsdialog.py
+++ b/openlp/plugins/songs/forms/topicsdialog.py
@@ -22,7 +22,8 @@
from PyQt5 import QtWidgets
-from openlp.core.lib import translate, build_icon
+from openlp.core.common.i18n import translate
+from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box
diff --git a/openlp/plugins/songs/forms/topicsform.py b/openlp/plugins/songs/forms/topicsform.py
index f0c7f0ab1..2956c7e26 100644
--- a/openlp/plugins/songs/forms/topicsform.py
+++ b/openlp/plugins/songs/forms/topicsform.py
@@ -25,7 +25,7 @@ This module contains the topic edit form.
from PyQt5 import QtCore, QtWidgets
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.songs.forms.topicsdialog import Ui_TopicsDialog
diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py
index 68effbe9b..f88aa8678 100644
--- a/openlp/plugins/songs/lib/__init__.py
+++ b/openlp/plugins/songs/lib/__init__.py
@@ -29,8 +29,11 @@ import re
from PyQt5 import QtWidgets
-from openlp.core.common import AppLocation, CONTROL_CHARS, Settings
-from openlp.core.lib import translate, clean_tags
+from openlp.core.common import CONTROL_CHARS
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import translate
+from openlp.core.common.settings import Settings
+from openlp.core.lib import clean_tags
from openlp.plugins.songs.lib.db import Author, MediaFile, Song, Topic
from openlp.plugins.songs.lib.ui import SongStrings
@@ -546,12 +549,12 @@ def delete_song(song_id, song_plugin):
song_plugin.manager.delete_object(Song, song_id)
-def transpose_lyrics(lyrics, transepose_value):
+def transpose_lyrics(lyrics, transpose_value):
"""
- Transepose lyrics
+ Transpose lyrics
- :param lyrcs: The lyrics to be transposed
- :param transepose_value: The value to transpose the lyrics with
+ :param lyrics: The lyrics to be transposed
+ :param transpose_value: The value to transpose the lyrics with
:return: The transposed lyrics
"""
# Split text by verse delimiter - both normal and optional
@@ -562,16 +565,17 @@ def transpose_lyrics(lyrics, transepose_value):
if verse.startswith('---[') or verse == '[---]':
transposed_lyrics += verse
else:
- transposed_lyrics += transpose_verse(verse, transepose_value, notation)
+ transposed_lyrics += transpose_verse(verse, transpose_value, notation)
return transposed_lyrics
-def transpose_verse(verse_text, transepose_value, notation):
+def transpose_verse(verse_text, transpose_value, notation):
"""
- Transepose lyrics
+ Transpose Verse
- :param lyrcs: The lyrics to be transposed
- :param transepose_value: The value to transpose the lyrics with
+ :param verse_text: The lyrics to be transposed
+ :param transpose_value: The value to transpose the lyrics with
+ :param notation: which notation to use
:return: The transposed lyrics
"""
if '[' not in verse_text:
@@ -589,11 +593,11 @@ def transpose_verse(verse_text, transepose_value, notation):
if word == ']':
in_tag = False
transposed_lyrics += word
- elif word == '/':
+ elif word == '/' or word == '--}{--':
transposed_lyrics += word
else:
# This MUST be a chord
- transposed_lyrics += transpose_chord(word, transepose_value, notation)
+ transposed_lyrics += transpose_chord(word, transpose_value, notation)
# If still inside a chord tag something is wrong!
if in_tag:
return verse_text
@@ -629,36 +633,36 @@ def transpose_chord(chord, transpose_value, notation):
for i in range(0, len(chord_split)):
if i > 0:
transposed_chord += '/'
- currentchord = chord_split[i]
- if currentchord and currentchord[0] == '(':
+ current_chord = chord_split[i]
+ if current_chord and current_chord[0] == '(':
transposed_chord += '('
- if len(currentchord) > 1:
- currentchord = currentchord[1:]
+ if len(current_chord) > 1:
+ current_chord = current_chord[1:]
else:
- currentchord = ''
- if len(currentchord) > 0:
- if len(currentchord) > 1:
- if '#b'.find(currentchord[1]) == -1:
- note = currentchord[0:1]
- rest = currentchord[1:]
+ current_chord = ''
+ if len(current_chord) > 0:
+ if len(current_chord) > 1:
+ if '#b'.find(current_chord[1]) == -1:
+ note = current_chord[0:1]
+ rest = current_chord[1:]
else:
- note = currentchord[0:2]
- rest = currentchord[2:]
+ note = current_chord[0:2]
+ rest = current_chord[2:]
else:
- note = currentchord
+ note = current_chord
rest = ''
- notenumber = notes_flat.index(note) if note not in notes_sharp else notes_sharp.index(note)
- notenumber += transpose_value
- while notenumber > 11:
- notenumber -= 12
- while notenumber < 0:
- notenumber += 12
+ note_number = notes_flat.index(note) if note not in notes_sharp else notes_sharp.index(note)
+ note_number += transpose_value
+ while note_number > 11:
+ note_number -= 12
+ while note_number < 0:
+ note_number += 12
if i == 0:
- current_chord = notes_sharp[notenumber] if notes_preferred[notenumber] == '#' else notes_flat[
- notenumber]
+ current_chord = notes_sharp[note_number] if notes_preferred[note_number] == '#' else notes_flat[
+ note_number]
last_chord = current_chord
else:
- current_chord = notes_flat[notenumber] if last_chord not in notes_sharp else notes_sharp[notenumber]
+ current_chord = notes_flat[note_number] if last_chord not in notes_sharp else notes_sharp[note_number]
if not (note not in notes_flat and note not in notes_sharp):
transposed_chord += current_chord + rest
else:
diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py
index 5910bd1a8..0963fd084 100644
--- a/openlp/plugins/songs/lib/db.py
+++ b/openlp/plugins/songs/lib/db.py
@@ -23,14 +23,11 @@
The :mod:`db` module provides the database and schema that is the backend for
the Songs plugin
"""
-from contextlib import suppress
from sqlalchemy import Column, ForeignKey, Table, types
from sqlalchemy.orm import mapper, relation, reconstructor
from sqlalchemy.sql.expression import func, text
-from openlp.core.common.applocation import AppLocation
-from openlp.core.common.languagemanager import get_natural_key
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate, get_natural_key
from openlp.core.lib.db import BaseModel, PathType, init_db
diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py
index 9f925b35c..3b8081999 100644
--- a/openlp/plugins/songs/lib/importer.py
+++ b/openlp/plugins/songs/lib/importer.py
@@ -22,10 +22,10 @@
"""
The :mod:`importer` modules provides the general song import functionality.
"""
-import os
import logging
-from openlp.core.common import translate, UiStrings, is_win
+from openlp.core.common import is_win
+from openlp.core.common.i18n import UiStrings, translate
from openlp.core.ui.lib.wizard import WizardStrings
from .importers.opensong import OpenSongImport
from .importers.easyslides import EasySlidesImport
diff --git a/openlp/plugins/songs/lib/importers/cclifile.py b/openlp/plugins/songs/lib/importers/cclifile.py
index 223263183..10a8b09e1 100644
--- a/openlp/plugins/songs/lib/importers/cclifile.py
+++ b/openlp/plugins/songs/lib/importers/cclifile.py
@@ -23,7 +23,7 @@ import chardet
import codecs
import logging
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib import VerseType
from .songimport import SongImport
diff --git a/openlp/plugins/songs/lib/importers/chordpro.py b/openlp/plugins/songs/lib/importers/chordpro.py
index 2250e65f1..0d4c4d4f2 100644
--- a/openlp/plugins/songs/lib/importers/chordpro.py
+++ b/openlp/plugins/songs/lib/importers/chordpro.py
@@ -23,27 +23,25 @@
The :mod:`chordpro` module provides the functionality for importing
ChordPro files into the current database.
"""
-
import logging
import re
-from openlp.core.common import Settings
-
-from .songimport import SongImport
-
+from openlp.core.common.settings import Settings
+from openlp.plugins.songs.lib.importers.songimport import SongImport
log = logging.getLogger(__name__)
class ChordProImport(SongImport):
"""
- The :class:`ChordProImport` class provides OpenLP with the
- ability to import ChordPro files.
+ The :class:`ChordProImport` class provides OpenLP with the ability to import ChordPro files.
+
This importer is based on the information available on these webpages:
- http://webchord.sourceforge.net/tech.html
- http://www.vromans.org/johan/projects/Chordii/chordpro/
- http://www.tenbyten.com/software/songsgen/help/HtmlHelp/files_reference.htm
- http://linkesoft.com/songbook/chordproformat.html
+
+ - http://webchord.sourceforge.net/tech.html
+ - http://www.vromans.org/johan/projects/Chordii/chordpro/
+ - http://www.tenbyten.com/software/songsgen/help/HtmlHelp/files_reference.htm
+ - http://linkesoft.com/songbook/chordproformat.html
"""
def do_import(self):
self.import_wizard.progress_bar.setMaximum(len(self.import_source))
diff --git a/openlp/plugins/songs/lib/importers/dreambeam.py b/openlp/plugins/songs/lib/importers/dreambeam.py
index 094827792..eb2ec1ded 100644
--- a/openlp/plugins/songs/lib/importers/dreambeam.py
+++ b/openlp/plugins/songs/lib/importers/dreambeam.py
@@ -26,7 +26,7 @@ import logging
from lxml import etree, objectify
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib.importers.songimport import SongImport
from openlp.plugins.songs.lib.ui import SongStrings
diff --git a/openlp/plugins/songs/lib/importers/easyworship.py b/openlp/plugins/songs/lib/importers/easyworship.py
index ac22029a3..c82a7e6ad 100644
--- a/openlp/plugins/songs/lib/importers/easyworship.py
+++ b/openlp/plugins/songs/lib/importers/easyworship.py
@@ -30,8 +30,8 @@ import zlib
import sqlite3
+from openlp.core.common.i18n import translate
from openlp.core.common.path import Path
-from openlp.core.lib import translate
from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib import retrieve_windows_encoding, strip_rtf
from .songimport import SongImport
diff --git a/openlp/plugins/songs/lib/importers/foilpresenter.py b/openlp/plugins/songs/lib/importers/foilpresenter.py
index 98ec9d6ac..860177172 100644
--- a/openlp/plugins/songs/lib/importers/foilpresenter.py
+++ b/openlp/plugins/songs/lib/importers/foilpresenter.py
@@ -87,7 +87,7 @@ import re
from lxml import etree, objectify
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
from openlp.core.ui.lib.wizard import WizardStrings
from openlp.plugins.songs.lib import clean_song, VerseType
from openlp.plugins.songs.lib.importers.songimport import SongImport
diff --git a/openlp/plugins/songs/lib/importers/lyrix.py b/openlp/plugins/songs/lib/importers/lyrix.py
index 87df138a0..c8dbac24b 100644
--- a/openlp/plugins/songs/lib/importers/lyrix.py
+++ b/openlp/plugins/songs/lib/importers/lyrix.py
@@ -26,7 +26,7 @@ exproted from Lyrix."""
import logging
import re
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib.importers.songimport import SongImport
log = logging.getLogger(__name__)
diff --git a/openlp/plugins/songs/lib/importers/mediashout.py b/openlp/plugins/songs/lib/importers/mediashout.py
index c3d42681b..67cf0d0fb 100644
--- a/openlp/plugins/songs/lib/importers/mediashout.py
+++ b/openlp/plugins/songs/lib/importers/mediashout.py
@@ -30,7 +30,7 @@ a MediaShout database into the OpenLP database.
import pyodbc
import logging
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib.importers.songimport import SongImport
VERSE_TAGS = ['V', 'C', 'B', 'O', 'P', 'I', 'E']
diff --git a/openlp/plugins/songs/lib/importers/openlp.py b/openlp/plugins/songs/lib/importers/openlp.py
index 2e348a867..252b8fd8b 100644
--- a/openlp/plugins/songs/lib/importers/openlp.py
+++ b/openlp/plugins/songs/lib/importers/openlp.py
@@ -29,7 +29,7 @@ from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy.orm import class_mapper, mapper, relation, scoped_session, sessionmaker
from sqlalchemy.orm.exc import UnmappedClassError
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.core.lib.db import BaseModel
from openlp.core.ui.lib.wizard import WizardStrings
from openlp.plugins.songs.lib import clean_song
diff --git a/openlp/plugins/songs/lib/importers/openoffice.py b/openlp/plugins/songs/lib/importers/openoffice.py
index f03f7b4a4..a097d8b85 100644
--- a/openlp/plugins/songs/lib/importers/openoffice.py
+++ b/openlp/plugins/songs/lib/importers/openoffice.py
@@ -25,7 +25,7 @@ import time
from PyQt5 import QtCore
from openlp.core.common import is_win, get_uno_command, get_uno_instance
-from openlp.core.lib import translate
+from openlp.core.common.i18n import translate
from .songimport import SongImport
log = logging.getLogger(__name__)
diff --git a/openlp/plugins/songs/lib/importers/opensong.py b/openlp/plugins/songs/lib/importers/opensong.py
index 3f6e76685..e6924e7b2 100644
--- a/openlp/plugins/songs/lib/importers/opensong.py
+++ b/openlp/plugins/songs/lib/importers/opensong.py
@@ -25,7 +25,8 @@ import re
from lxml import objectify
from lxml.etree import Error, LxmlError
-from openlp.core.common import translate, Settings
+from openlp.core.common.i18n import translate
+from openlp.core.common.settings import Settings
from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.importers.songimport import SongImport
from openlp.plugins.songs.lib.ui import SongStrings
diff --git a/openlp/plugins/songs/lib/importers/opspro.py b/openlp/plugins/songs/lib/importers/opspro.py
index 3ede706f4..f7dba83b8 100644
--- a/openlp/plugins/songs/lib/importers/opspro.py
+++ b/openlp/plugins/songs/lib/importers/opspro.py
@@ -32,7 +32,7 @@ import re
import pyodbc
import struct
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib.importers.songimport import SongImport
log = logging.getLogger(__name__)
diff --git a/openlp/plugins/songs/lib/importers/powersong.py b/openlp/plugins/songs/lib/importers/powersong.py
index fd51ec7e6..7fac4ef75 100644
--- a/openlp/plugins/songs/lib/importers/powersong.py
+++ b/openlp/plugins/songs/lib/importers/powersong.py
@@ -27,7 +27,7 @@ import logging
import fnmatch
import os
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib.importers.songimport import SongImport
log = logging.getLogger(__name__)
diff --git a/openlp/plugins/songs/lib/importers/presentationmanager.py b/openlp/plugins/songs/lib/importers/presentationmanager.py
index 2ea23679b..e7fec2a6c 100644
--- a/openlp/plugins/songs/lib/importers/presentationmanager.py
+++ b/openlp/plugins/songs/lib/importers/presentationmanager.py
@@ -27,7 +27,8 @@ import re
from lxml import objectify, etree
-from openlp.core.common import get_file_encoding, translate
+from openlp.core.common.i18n import translate
+from openlp.core.common import get_file_encoding
from openlp.core.ui.lib.wizard import WizardStrings
from .songimport import SongImport
diff --git a/openlp/plugins/songs/lib/importers/songbeamer.py b/openlp/plugins/songs/lib/importers/songbeamer.py
index 346b1588d..adc364325 100644
--- a/openlp/plugins/songs/lib/importers/songbeamer.py
+++ b/openlp/plugins/songs/lib/importers/songbeamer.py
@@ -28,7 +28,8 @@ import re
import base64
import math
-from openlp.core.common import Settings, is_win, is_macosx, get_file_encoding
+from openlp.core.common import is_win, is_macosx, get_file_encoding
+from openlp.core.common.settings import Settings
from openlp.core.common.path import Path
from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.importers.songimport import SongImport
@@ -313,7 +314,8 @@ class SongBeamerImport(SongImport):
elif tag_val[0] == '#QuickFind':
pass
elif tag_val[0] == '#Rights':
- song_book_pub = tag_val[1]
+ # song_book_pub = tag_val[1]
+ pass
elif tag_val[0] == '#Songbook' or tag_val[0] == '#SongBook':
book_data = tag_val[1].split('/')
self.song_book_name = book_data[0].strip()
diff --git a/openlp/plugins/songs/lib/importers/songimport.py b/openlp/plugins/songs/lib/importers/songimport.py
index a74aaf9e7..e0cc5220e 100644
--- a/openlp/plugins/songs/lib/importers/songimport.py
+++ b/openlp/plugins/songs/lib/importers/songimport.py
@@ -25,8 +25,10 @@ import re
from PyQt5 import QtCore
-from openlp.core.common import Registry, AppLocation, check_directory_exists, translate
-from openlp.core.common.path import copyfile
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import translate
+from openlp.core.common.path import copyfile, create_paths
+from openlp.core.common.registry import Registry
from openlp.core.ui.lib.wizard import WizardStrings
from openlp.plugins.songs.lib import clean_song, VerseType
from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
@@ -423,7 +425,7 @@ class SongImport(QtCore.QObject):
"""
if not hasattr(self, 'save_path'):
self.save_path = AppLocation.get_section_data_path(self.import_wizard.plugin.name) / 'audio' / str(song_id)
- check_directory_exists(self.save_path)
+ create_paths(self.save_path)
if self.save_path not in file_path.parents:
old_path, file_path = file_path, self.save_path / file_path.name
copyfile(old_path, file_path)
diff --git a/openlp/plugins/songs/lib/importers/videopsalm.py b/openlp/plugins/songs/lib/importers/videopsalm.py
index ef020997a..180dbd333 100644
--- a/openlp/plugins/songs/lib/importers/videopsalm.py
+++ b/openlp/plugins/songs/lib/importers/videopsalm.py
@@ -21,12 +21,13 @@
###############################################################################
"""
The :mod:`lyrix` module provides the functionality for importing songs which are
-exproted from Lyrix."""
+exported from Lyrix."""
import json
import logging
import re
-from openlp.core.common import translate, Settings
+from openlp.core.common.i18n import translate
+from openlp.core.common.settings import Settings
from openlp.core.common.path import Path
from openlp.plugins.songs.lib.importers.songimport import SongImport
from openlp.plugins.songs.lib.db import AuthorType
diff --git a/openlp/plugins/songs/lib/importers/wordsofworship.py b/openlp/plugins/songs/lib/importers/wordsofworship.py
index 62ad367bf..e1c561361 100644
--- a/openlp/plugins/songs/lib/importers/wordsofworship.py
+++ b/openlp/plugins/songs/lib/importers/wordsofworship.py
@@ -27,7 +27,7 @@ import os
import logging
from openlp.core.common.path import Path
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib.importers.songimport import SongImport
BLOCK_TYPES = ('V', 'C', 'B')
diff --git a/openlp/plugins/songs/lib/importers/worshipassistant.py b/openlp/plugins/songs/lib/importers/worshipassistant.py
index b4cb87576..f9354427d 100644
--- a/openlp/plugins/songs/lib/importers/worshipassistant.py
+++ b/openlp/plugins/songs/lib/importers/worshipassistant.py
@@ -23,12 +23,12 @@
The :mod:`worshipassistant` module provides the functionality for importing
Worship Assistant songs into the OpenLP database.
"""
-import chardet
import csv
import logging
import re
-from openlp.core.common import get_file_encoding, translate
+from openlp.core.common import get_file_encoding
+from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.importers.songimport import SongImport
diff --git a/openlp/plugins/songs/lib/importers/worshipcenterpro.py b/openlp/plugins/songs/lib/importers/worshipcenterpro.py
index 426e8c153..6bba00682 100644
--- a/openlp/plugins/songs/lib/importers/worshipcenterpro.py
+++ b/openlp/plugins/songs/lib/importers/worshipcenterpro.py
@@ -27,7 +27,7 @@ import logging
import re
import pyodbc
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib.importers.songimport import SongImport
log = logging.getLogger(__name__)
diff --git a/openlp/plugins/songs/lib/importers/zionworx.py b/openlp/plugins/songs/lib/importers/zionworx.py
index b4aec2c16..5cfc0576d 100644
--- a/openlp/plugins/songs/lib/importers/zionworx.py
+++ b/openlp/plugins/songs/lib/importers/zionworx.py
@@ -25,7 +25,7 @@ The :mod:`zionworx` module provides the functionality for importing ZionWorx son
import csv
import logging
-from openlp.core.common import translate
+from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib.importers.songimport import SongImport
log = logging.getLogger(__name__)
diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py
index 6632387f5..c6ad9c927 100644
--- a/openlp/plugins/songs/lib/mediaitem.py
+++ b/openlp/plugins/songs/lib/mediaitem.py
@@ -19,16 +19,17 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-
import logging
import os
from PyQt5 import QtCore, QtWidgets
from sqlalchemy.sql import and_, or_
-from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists, UiStrings, translate
-from openlp.core.common.languagemanager import get_natural_key
-from openlp.core.common.path import copyfile
+from openlp.core.common.applocation import AppLocation
+from openlp.core.common.i18n import UiStrings, translate, get_natural_key
+from openlp.core.common.path import copyfile, create_paths
+from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import MediaManagerItem, ItemCapabilities, PluginStatus, ServiceItemContext, \
check_item_selected, create_separated_list
from openlp.core.lib.ui import create_widget_action
@@ -89,7 +90,7 @@ class SongMediaItem(MediaManagerItem):
for i, bga in enumerate(item.background_audio):
dest_path =\
AppLocation.get_section_data_path(self.plugin.name) / 'audio' / str(song.id) / os.path.split(bga)[1]
- check_directory_exists(dest_path.parent)
+ create_paths(dest_path.parent)
copyfile(AppLocation.get_section_data_path('servicemanager') / bga, dest_path)
song.media_files.append(MediaFile.populate(weight=i, file_path=dest_path))
self.plugin.manager.save_object(song, True)
@@ -534,7 +535,7 @@ class SongMediaItem(MediaManagerItem):
# Copy audio files from the old to the new song
if len(old_song.media_files) > 0:
save_path = AppLocation.get_section_data_path(self.plugin.name) / 'audio' / str(new_song.id)
- check_directory_exists(save_path)
+ create_paths(save_path)
for media_file in old_song.media_files:
new_media_file_path = save_path / media_file.file_path.name
copyfile(media_file.file_path, new_media_file_path)
@@ -577,7 +578,7 @@ class SongMediaItem(MediaManagerItem):
if not song.verse_order.strip():
for verse in verse_list:
# We cannot use from_loose_input() here, because database is supposed to contain English lowercase
- # singlechar tags.
+ # single char tags.
verse_tag = verse[0]['type']
verse_index = None
if len(verse_tag) > 1:
@@ -588,7 +589,9 @@ class SongMediaItem(MediaManagerItem):
verse_index = VerseType.from_tag(verse_tag)
verse_tag = VerseType.translated_tags[verse_index].upper()
verse_def = '{tag}{label}'.format(tag=verse_tag, label=verse[0]['label'])
- service_item.add_from_text(str(verse[1]), verse_def)
+ force_verse = verse[1].split('[--}{--]\n')
+ for split_verse in force_verse:
+ service_item.add_from_text(split_verse, verse_def)
else:
# Loop through the verse list and expand the song accordingly.
for order in song.verse_order.lower().split():
@@ -603,7 +606,9 @@ class SongMediaItem(MediaManagerItem):
verse_index = VerseType.from_tag(verse[0]['type'])
verse_tag = VerseType.translated_tags[verse_index]
verse_def = '{tag}{label}'.format(tag=verse_tag, label=verse[0]['label'])
- service_item.add_from_text(verse[1], verse_def)
+ force_verse = verse[1].split('[--}{--]\n')
+ for split_verse in force_verse:
+ service_item.add_from_text(split_verse, verse_def)
service_item.title = song.title
author_list = self.generate_footer(service_item, song)
service_item.data_string = {'title': song.search_title, 'authors': ', '.join(author_list)}
diff --git a/openlp/plugins/songs/lib/openlyricsexport.py b/openlp/plugins/songs/lib/openlyricsexport.py
index 430e37da5..ca7fe0bc7 100644
--- a/openlp/plugins/songs/lib/openlyricsexport.py
+++ b/openlp/plugins/songs/lib/openlyricsexport.py
@@ -27,7 +27,10 @@ import logging
from lxml import etree
-from openlp.core.common import RegistryProperties, check_directory_exists, translate, clean_filename
+from openlp.core.common import clean_filename
+from openlp.core.common.i18n import translate
+from openlp.core.common.path import create_paths
+from openlp.core.common.registry import RegistryProperties
from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics
log = logging.getLogger(__name__)
@@ -49,7 +52,7 @@ class OpenLyricsExport(RegistryProperties):
self.manager = parent.plugin.manager
self.songs = songs
self.save_path = save_path
- check_directory_exists(self.save_path)
+ create_paths(self.save_path)
def do_export(self):
"""
diff --git a/openlp/plugins/songs/lib/openlyricsxml.py b/openlp/plugins/songs/lib/openlyricsxml.py
index 4819e61de..74d91068c 100644
--- a/openlp/plugins/songs/lib/openlyricsxml.py
+++ b/openlp/plugins/songs/lib/openlyricsxml.py
@@ -61,7 +61,8 @@ import re
from lxml import etree, objectify
-from openlp.core.common import translate, Settings
+from openlp.core.common.i18n import translate
+from openlp.core.common.settings import Settings
from openlp.core.version import get_version
from openlp.core.lib import FormattingTags
from openlp.plugins.songs.lib import VerseType, clean_song
@@ -71,6 +72,7 @@ log = logging.getLogger(__name__)
NAMESPACE = 'http://openlyrics.info/namespace/2009/song'
NSMAP = '{{' + NAMESPACE + '}}{tag}'
+NEWPAGETAG = '