diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 49497a10e..7fe7beaca 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -93,14 +93,14 @@ class GeneralTab(SettingsTab): self.monitor_layout.addWidget(self.custom_width_label, 3, 3) self.custom_width_value_edit = QtGui.QSpinBox(self.monitor_group_box) self.custom_width_value_edit.setObjectName(u'custom_width_value_edit') - self.custom_width_value_edit.setMaximum(9999) + self.custom_width_value_edit.setRange(1, 9999) self.monitor_layout.addWidget(self.custom_width_value_edit, 4, 3) self.custom_height_label = QtGui.QLabel(self.monitor_group_box) self.custom_height_label.setObjectName(u'custom_height_label') self.monitor_layout.addWidget(self.custom_height_label, 3, 4) self.custom_height_value_edit = QtGui.QSpinBox(self.monitor_group_box) self.custom_height_value_edit.setObjectName(u'custom_height_value_edit') - self.custom_height_value_edit.setMaximum(9999) + self.custom_height_value_edit.setRange(1, 9999) self.monitor_layout.addWidget(self.custom_height_value_edit, 4, 4) self.display_on_monitor_check = QtGui.QCheckBox(self.monitor_group_box) self.display_on_monitor_check.setObjectName(u'monitor_combo_box') diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index 68d8cc216..007932f6e 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -38,7 +38,7 @@ from openlp.core.lib import UiStrings, Registry, translate from openlp.core.lib.theme import BackgroundType, BackgroundGradientType from openlp.core.lib.ui import critical_error_message_box from openlp.core.ui import ThemeLayoutForm -from openlp.core.utils import get_images_filter +from openlp.core.utils import get_images_filter, is_not_image_file from themewizard import Ui_ThemeWizard log = logging.getLogger(__name__) @@ -178,7 +178,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ background_image = BackgroundType.to_string(BackgroundType.Image) if self.page(self.currentId()) == self.backgroundPage and \ - self.theme.background_type == background_image and not self.imageFileEdit.text(): + self.theme.background_type == background_image and is_not_image_file(self.imageFileEdit.text()): QtGui.QMessageBox.critical(self, translate('OpenLP.ThemeWizard', 'Background Image Empty'), translate('OpenLP.ThemeWizard', 'You have not selected a ' 'background image. Please select one before continuing.')) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 59dd08b27..0a4df48f8 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -246,6 +246,23 @@ def get_images_filter(): return IMAGES_FILTER +def is_not_image_file(file_name): + """ + Validate that the file is not an image file. + + ``file_name`` + File name to be checked. + """ + if not file_name: + return True + else: + formats = [unicode(fmt).lower() for fmt in QtGui.QImageReader.supportedImageFormats()] + file_part, file_extension = os.path.splitext(unicode(file_name)) + if file_extension[1:].lower() in formats and os.path.exists(file_name): + return False + return True + + def split_filename(path): """ Return a list of the parts in a given path. diff --git a/openlp/plugins/remotes/html/live.css b/openlp/plugins/remotes/html/main.css similarity index 100% rename from openlp/plugins/remotes/html/live.css rename to openlp/plugins/remotes/html/main.css diff --git a/openlp/plugins/remotes/html/live.html b/openlp/plugins/remotes/html/main.html similarity index 95% rename from openlp/plugins/remotes/html/live.html rename to openlp/plugins/remotes/html/main.html index f9a2c874c..3fbd42447 100644 --- a/openlp/plugins/remotes/html/live.html +++ b/openlp/plugins/remotes/html/main.html @@ -30,10 +30,10 @@ ${live_title} - + - + diff --git a/openlp/plugins/remotes/html/live.js b/openlp/plugins/remotes/html/main.js similarity index 98% rename from openlp/plugins/remotes/html/live.js rename to openlp/plugins/remotes/html/main.js index d55072c16..4f4f36351 100644 --- a/openlp/plugins/remotes/html/live.js +++ b/openlp/plugins/remotes/html/main.js @@ -26,7 +26,7 @@ window.OpenLP = { loadSlide: function (event) { $.getJSON( - "/live/image", + "/main/image", function (data, status) { var img = document.getElementById('image'); img.src = data.results.slide_image; @@ -36,7 +36,7 @@ window.OpenLP = { }, pollServer: function () { $.getJSON( - "/live/poll", + "/main/poll", function (data, status) { if (OpenLP.slideCount != data.results.slide_count) { OpenLP.slideCount = data.results.slide_count; diff --git a/openlp/plugins/remotes/lib/httpserver.py b/openlp/plugins/remotes/lib/httpserver.py index 671a85517..48a6a4d79 100644 --- a/openlp/plugins/remotes/lib/httpserver.py +++ b/openlp/plugins/remotes/lib/httpserver.py @@ -177,11 +177,11 @@ class HttpServer(object): self.root = self.Public() self.root.files = self.Files() self.root.stage = self.Stage() - self.root.live = self.Live() + self.root.main = self.Main() self.root.router = self.router self.root.files.router = self.router self.root.stage.router = self.router - self.root.live.router = self.router + self.root.main.router = self.router cherrypy.tree.mount(self.root, '/', config=self.define_config()) # Turn off the flood of access messages cause by poll cherrypy.log.access_log.propagate = False @@ -218,7 +218,7 @@ class HttpServer(object): u'/stage': {u'tools.staticdir.on': True, u'tools.staticdir.dir': self.router.html_dir, u'tools.basic_auth.on': False}, - u'/live': {u'tools.staticdir.on': True, + u'/main': {u'tools.staticdir.on': True, u'tools.staticdir.dir': self.router.html_dir, u'tools.basic_auth.on': False}} return directory_config @@ -253,9 +253,9 @@ class HttpServer(object): url = urlparse.urlparse(cherrypy.url()) return self.router.process_http_request(url.path, *args) - class Live(object): + class Main(object): """ - Live view is read only so security is not relevant and would reduce it's usability + Main view is read only so security is not relevant and would reduce it's usability """ @cherrypy.expose def default(self, *args, **kwargs): @@ -281,12 +281,12 @@ class HttpRouter(object): self.routes = [ (u'^/$', self.serve_file), (u'^/(stage)$', self.serve_file), - (u'^/(live)$', self.serve_file), + (u'^/(main)$', self.serve_file), (r'^/files/(.*)$', self.serve_file), (r'^/api/poll$', self.poll), (r'^/stage/poll$', self.poll), - (r'^/live/poll$', self.live_poll), - (r'^/live/image$', self.live_image), + (r'^/main/poll$', self.main_poll), + (r'^/main/image$', self.main_image), (r'^/api/controller/(live|preview)/(.*)$', self.controller), (r'^/stage/controller/(live|preview)/(.*)$', self.controller), (r'^/api/service/(.*)$', self.service), @@ -378,7 +378,7 @@ class HttpRouter(object): 'slides': translate('RemotePlugin.Mobile', 'Slides') } - def serve_file(self, filename=None): + def serve_file(self, file_name=None): """ Send a file to the socket. For now, just a subset of file types and must be top level inside the html folder. If subfolders requested return 404, easier for security for the present. @@ -386,17 +386,17 @@ class HttpRouter(object): Ultimately for i18n, this could first look for xx/file.html before falling back to file.html. where xx is the language, e.g. 'en' """ - log.debug(u'serve file request %s' % filename) - if not filename: - filename = u'index.html' - elif filename == u'stage': - filename = u'stage.html' - elif filename == u'live': - filename = u'live.html' - path = os.path.normpath(os.path.join(self.html_dir, filename)) + log.debug(u'serve file request %s' % file_name) + if not file_name: + file_name = u'index.html' + elif file_name == u'stage': + file_name = u'stage.html' + elif file_name == u'main': + file_name = u'main.html' + path = os.path.normpath(os.path.join(self.html_dir, file_name)) if not path.startswith(self.html_dir): return self._http_not_found() - ext = os.path.splitext(filename)[1] + ext = os.path.splitext(file_name)[1] html = None if ext == u'.html': mimetype = u'text/html' @@ -447,7 +447,7 @@ class HttpRouter(object): cherrypy.response.headers['Content-Type'] = u'application/json' return json.dumps({u'results': result}).encode() - def live_poll(self): + def main_poll(self): """ Poll OpenLP to determine the current slide count. """ @@ -457,7 +457,7 @@ class HttpRouter(object): cherrypy.response.headers['Content-Type'] = u'application/json' return json.dumps({u'results': result}).encode() - def live_image(self): + def main_image(self): """ Return the latest display image as a byte stream. """ diff --git a/scripts/check_dependencies.py b/scripts/check_dependencies.py index bd7786b01..40377bb5b 100755 --- a/scripts/check_dependencies.py +++ b/scripts/check_dependencies.py @@ -83,7 +83,6 @@ MODULES = [ 'bs4', 'mako', 'cherrypy', - 'migrate', 'uno', 'icu', 'bs4', diff --git a/tests/interfaces/openlp_core_utils/__init__.py b/tests/interfaces/openlp_core_utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/interfaces/openlp_core_utils/test_utils.py b/tests/interfaces/openlp_core_utils/test_utils.py new file mode 100644 index 000000000..fe5d33560 --- /dev/null +++ b/tests/interfaces/openlp_core_utils/test_utils.py @@ -0,0 +1,52 @@ +""" +Functional tests to test the AppLocation class and related methods. +""" +import os +from unittest import TestCase + +from openlp.core.utils import is_not_image_file +from tests.utils.constants import TEST_RESOURCES_PATH + + +class TestUtils(TestCase): + """ + A test suite to test out various methods around the Utils functions. + """ + def is_not_image_empty_test(self): + """ + Test the method handles an empty string + """ + # Given and empty string + file_name = "" + + # WHEN testing for it + result = is_not_image_file(file_name) + + # THEN the result is false + assert result is True, u'The missing file test should return True' + + def is_not_image_with_image_file_test(self): + """ + Test the method handles an image file + """ + # Given and empty string + file_name = os.path.join(TEST_RESOURCES_PATH, u'church.jpg') + + # WHEN testing for it + result = is_not_image_file(file_name) + + # THEN the result is false + assert result is False, u'The file is present so the test should return False' + + def is_not_image_with_none_image_file_test(self): + """ + Test the method handles a non image file + """ + # Given and empty string + file_name = os.path.join(TEST_RESOURCES_PATH, u'serviceitem_custom_1.osj') + + # WHEN testing for it + result = is_not_image_file(file_name) + + # THEN the result is false + assert result is True, u'The file is not an image file so the test should return True' \ No newline at end of file