This commit is contained in:
Andreas Preikschat 2013-07-17 14:21:44 +02:00
commit 48d2956bdd
10 changed files with 97 additions and 29 deletions

View File

@ -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')

View File

@ -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.'))

View File

@ -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.

View File

@ -30,10 +30,10 @@
<head>
<meta charset="utf-8" />
<title>${live_title}</title>
<link rel="stylesheet" href="/files/live.css" />
<link rel="stylesheet" href="/files/main.css" />
<link rel="shortcut icon" type="image/x-icon" href="/files/images/favicon.ico">
<script type="text/javascript" src="/files/jquery.js"></script>
<script type="text/javascript" src="/files/live.js"></script>
<script type="text/javascript" src="/files/main.js"></script>
</head>
<body>
<img id="image" class="size"/>

View File

@ -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;

View File

@ -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.
"""

View File

@ -83,7 +83,6 @@ MODULES = [
'bs4',
'mako',
'cherrypy',
'migrate',
'uno',
'icu',
'bs4',

View File

@ -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'