diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 50a1ab9b6..db135ef10 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -27,26 +27,26 @@ 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 os -import sys -import logging import argparse -from traceback import format_exception +import logging +import os import shutil +import sys import time +from traceback import format_exception + from PyQt5 import QtCore, QtGui, QtWidgets -from openlp.core.common import Registry, OpenLPMixin, AppLocation, Settings, UiStrings, check_directory_exists, \ - is_macosx, is_win, translate +from openlp.core.common import Registry, OpenLPMixin, AppLocation, LanguageManager, Settings, UiStrings, \ + check_directory_exists, is_macosx, is_win, translate +from openlp.core.common.versionchecker import VersionThread, get_application_version from openlp.core.lib import ScreenList from openlp.core.resources import qInitResources -from openlp.core.ui.mainwindow import MainWindow -from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm -from openlp.core.ui.firsttimeform import FirstTimeForm -from openlp.core.ui.exceptionform import ExceptionForm from openlp.core.ui import SplashScreen -from openlp.core.utils import LanguageManager, VersionThread, get_application_version - +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 __all__ = ['OpenLP', 'main'] diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py index b0926dccd..b8a1a4d2e 100644 --- a/openlp/core/common/__init__.py +++ b/openlp/core/common/__init__.py @@ -24,15 +24,15 @@ The :mod:`common` module contains most of the components and libraries that make OpenLP work. """ import hashlib -import re -import os import logging +import os +import re import sys import traceback from ipaddress import IPv4Address, IPv6Address, AddressValueError -from codecs import decode, encode +from shutil import which -from PyQt5 import QtCore +from PyQt5 import QtCore, QtGui from PyQt5.QtCore import QCryptographicHash as QHash log = logging.getLogger(__name__ + '.__init__') @@ -40,6 +40,9 @@ log = logging.getLogger(__name__ + '.__init__') FIRST_CAMEL_REGEX = re.compile('(.)([A-Z][a-z]+)') SECOND_CAMEL_REGEX = re.compile('([a-z0-9])([A-Z])') +CONTROL_CHARS = re.compile(r'[\x00-\x1F\x7F-\x9F]', re.UNICODE) +INVALID_FILE_CHARS = re.compile(r'[\\/:\*\?"<>\|\+\[\]%]', re.UNICODE) +IMAGES_FILTER = None def trace_error_handler(logger): @@ -241,4 +244,130 @@ from .registryproperties import RegistryProperties from .uistrings import UiStrings from .settings import Settings from .applocation import AppLocation -from .historycombobox import HistoryComboBox +from .actions import ActionList +from .languagemanager import LanguageManager + + +def add_actions(target, actions): + """ + Adds multiple actions to a menu or toolbar in one command. + + :param target: The menu or toolbar to add actions to + :param actions: The actions to be added. An action consisting of the keyword ``None`` + will result in a separator being inserted into the target. + """ + for action in actions: + if action is None: + target.addSeparator() + else: + target.addAction(action) + + +def get_uno_command(connection_type='pipe'): + """ + Returns the UNO command to launch an libreoffice.org instance. + """ + for command in ['libreoffice', 'soffice']: + if which(command): + break + else: + raise FileNotFoundError('Command not found') + + OPTIONS = '--nologo --norestore --minimized --nodefault --nofirststartwizard' + if connection_type == 'pipe': + CONNECTION = '"--accept=pipe,name=openlp_pipe;urp;"' + else: + CONNECTION = '"--accept=socket,host=localhost,port=2002;urp;"' + return '%s %s %s' % (command, OPTIONS, CONNECTION) + + +def get_uno_instance(resolver, connection_type='pipe'): + """ + Returns a running libreoffice.org instance. + + :param resolver: The UNO resolver to use to find a running instance. + """ + log.debug('get UNO Desktop Openoffice - resolve') + if connection_type == 'pipe': + return resolver.resolve('uno:pipe,name=openlp_pipe;urp;StarOffice.ComponentContext') + else: + return resolver.resolve('uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext') + + +def get_filesystem_encoding(): + """ + Returns the name of the encoding used to convert Unicode filenames into system file names. + """ + encoding = sys.getfilesystemencoding() + if encoding is None: + encoding = sys.getdefaultencoding() + return encoding + + +def split_filename(path): + """ + Return a list of the parts in a given path. + """ + path = os.path.abspath(path) + if not os.path.isfile(path): + return path, '' + else: + return os.path.split(path) + + +def delete_file(file_path_name): + """ + Deletes a file from the system. + + :param file_path_name: The file, including path, to delete. + """ + if not file_path_name: + return False + try: + if os.path.exists(file_path_name): + os.remove(file_path_name) + return True + except (IOError, OSError): + log.exception("Unable to delete file %s" % file_path_name) + return False + + +def get_images_filter(): + """ + Returns a filter string for a file dialog containing all the supported image formats. + """ + global IMAGES_FILTER + if not IMAGES_FILTER: + log.debug('Generating images filter.') + formats = list(map(bytes.decode, list(map(bytes, QtGui.QImageReader.supportedImageFormats())))) + visible_formats = '(*.%s)' % '; *.'.join(formats) + actual_formats = '(*.%s)' % ' *.'.join(formats) + IMAGES_FILTER = '%s %s %s' % (translate('OpenLP', 'Image Files'), visible_formats, actual_formats) + return IMAGES_FILTER + + +def is_not_image_file(file_name): + """ + Validate that the file is not an image file. + + :param file_name: File name to be checked. + """ + if not file_name: + return True + else: + formats = [bytes(fmt).decode().lower() for fmt in QtGui.QImageReader.supportedImageFormats()] + file_part, file_extension = os.path.splitext(str(file_name)) + if file_extension[1:].lower() in formats and os.path.exists(file_name): + return False + return True + + +def clean_filename(filename): + """ + Removes invalid characters from the given ``filename``. + + :param filename: The "dirty" file name to clean. + """ + if not isinstance(filename, str): + filename = str(filename, 'utf-8') + return INVALID_FILE_CHARS.sub('_', CONTROL_CHARS.sub('', filename)) diff --git a/openlp/core/utils/actions.py b/openlp/core/common/actions.py similarity index 100% rename from openlp/core/utils/actions.py rename to openlp/core/common/actions.py diff --git a/openlp/core/utils/db.py b/openlp/core/common/db.py similarity index 100% rename from openlp/core/utils/db.py rename to openlp/core/common/db.py diff --git a/openlp/core/utils/languagemanager.py b/openlp/core/common/languagemanager.py similarity index 75% rename from openlp/core/utils/languagemanager.py rename to openlp/core/common/languagemanager.py index 873b64c57..52e9e9f13 100644 --- a/openlp/core/utils/languagemanager.py +++ b/openlp/core/common/languagemanager.py @@ -22,9 +22,9 @@ """ The :mod:`languagemanager` module provides all the translation settings and language file loading for OpenLP. """ +import locale import logging import re -import sys from PyQt5 import QtCore, QtWidgets @@ -33,6 +33,9 @@ from openlp.core.common import AppLocation, Settings, translate, is_win, is_maco log = logging.getLogger(__name__) +ICU_COLLATOR = None +DIGITS_OR_NONDIGITS = re.compile(r'\d+|\D+', re.UNICODE) + class LanguageManager(object): """ @@ -144,3 +147,60 @@ class LanguageManager(object): 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('\%[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/settings.py b/openlp/core/common/settings.py index 8ef2b3c8b..efa251eec 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -121,6 +121,7 @@ class Settings(QtCore.QSettings): 'advanced/double click live': False, 'advanced/enable exit confirmation': True, 'advanced/expand service item': False, + 'advanced/slide max height': 0, 'advanced/hide mouse': True, 'advanced/is portable': False, 'advanced/max recent files': 20, @@ -131,6 +132,7 @@ class Settings(QtCore.QSettings): 'advanced/save current plugin': False, 'advanced/slide limits': SlideLimits.End, 'advanced/single click preview': False, + 'advanced/single click service preview': False, 'advanced/x11 bypass wm': X11_BYPASS_DEFAULT, 'advanced/search as type': True, 'crashreport/last directory': '', diff --git a/openlp/core/common/versionchecker.py b/openlp/core/common/versionchecker.py new file mode 100644 index 000000000..136405607 --- /dev/null +++ b/openlp/core/common/versionchecker.py @@ -0,0 +1,170 @@ +import logging +import os +import platform +import sys +import time +import urllib.error +import urllib.parse +import urllib.request +from datetime import datetime +from distutils.version import LooseVersion +from subprocess import Popen, PIPE + +from openlp.core.common import AppLocation, Settings + +from PyQt5 import QtCore + +log = logging.getLogger(__name__) + +APPLICATION_VERSION = {} +CONNECTION_TIMEOUT = 30 +CONNECTION_RETRIES = 2 + + +class VersionThread(QtCore.QThread): + """ + A special Qt thread class to fetch the version of OpenLP from the website. + This is threaded so that it doesn't affect the loading time of OpenLP. + """ + def __init__(self, main_window): + """ + Constructor for the thread class. + + :param main_window: The main window Object. + """ + log.debug("VersionThread - Initialise") + super(VersionThread, self).__init__(None) + self.main_window = main_window + + def run(self): + """ + Run the thread. + """ + self.sleep(1) + log.debug('Version thread - run') + app_version = get_application_version() + version = check_latest_version(app_version) + log.debug("Versions %s and %s " % (LooseVersion(str(version)), LooseVersion(str(app_version['full'])))) + if LooseVersion(str(version)) > LooseVersion(str(app_version['full'])): + self.main_window.openlp_version_check.emit('%s' % version) + + +def get_application_version(): + """ + Returns the application version of the running instance of OpenLP:: + + {'full': '1.9.4-bzr1249', 'version': '1.9.4', 'build': 'bzr1249'} + """ + global APPLICATION_VERSION + if APPLICATION_VERSION: + return APPLICATION_VERSION + if '--dev-version' in sys.argv or '-d' in sys.argv: + # NOTE: The following code is a duplicate of the code in setup.py. Any fix applied here should also be applied + # there. + + # Get the revision of this tree. + bzr = Popen(('bzr', 'revno'), stdout=PIPE) + tree_revision, error = bzr.communicate() + tree_revision = tree_revision.decode() + code = bzr.wait() + if code != 0: + raise Exception('Error running bzr log') + + # Get all tags. + bzr = Popen(('bzr', 'tags'), stdout=PIPE) + output, error = bzr.communicate() + code = bzr.wait() + if code != 0: + raise Exception('Error running bzr tags') + tags = list(map(bytes.decode, output.splitlines())) + if not tags: + tag_version = '0.0.0' + tag_revision = '0' + else: + # Remove any tag that has "?" as revision number. A "?" as revision number indicates, that this tag is from + # another series. + tags = [tag for tag in tags if tag.split()[-1].strip() != '?'] + # Get the last tag and split it in a revision and tag name. + tag_version, tag_revision = tags[-1].split() + # If they are equal, then this tree is tarball with the source for the release. We do not want the revision + # number in the full version. + if tree_revision == tag_revision: + full_version = tag_version.strip() + else: + full_version = '%s-bzr%s' % (tag_version.strip(), tree_revision.strip()) + else: + # We're not running the development version, let's use the file. + file_path = AppLocation.get_directory(AppLocation.VersionDir) + file_path = os.path.join(file_path, '.version') + version_file = None + try: + version_file = open(file_path, 'r') + full_version = str(version_file.read()).rstrip() + except IOError: + log.exception('Error in version file.') + full_version = '0.0.0-bzr000' + finally: + if version_file: + version_file.close() + bits = full_version.split('-') + APPLICATION_VERSION = { + 'full': full_version, + 'version': bits[0], + 'build': bits[1] if len(bits) > 1 else None + } + if APPLICATION_VERSION['build']: + log.info('Openlp version %s build %s', APPLICATION_VERSION['version'], APPLICATION_VERSION['build']) + else: + log.info('Openlp version %s' % APPLICATION_VERSION['version']) + return APPLICATION_VERSION + + +def check_latest_version(current_version): + """ + Check the latest version of OpenLP against the version file on the OpenLP + site. + + **Rules around versions and version files:** + + * If a version number has a build (i.e. -bzr1234), then it is a nightly. + * If a version number's minor version is an odd number, it is a development release. + * If a version number's minor version is an even number, it is a stable release. + + :param current_version: The current version of OpenLP. + """ + version_string = current_version['full'] + # set to prod in the distribution config file. + settings = Settings() + settings.beginGroup('core') + last_test = settings.value('last version test') + this_test = str(datetime.now().date()) + settings.setValue('last version test', this_test) + settings.endGroup() + if last_test != this_test: + if current_version['build']: + req = urllib.request.Request('http://www.openlp.org/files/nightly_version.txt') + else: + version_parts = current_version['version'].split('.') + if int(version_parts[1]) % 2 != 0: + req = urllib.request.Request('http://www.openlp.org/files/dev_version.txt') + else: + req = urllib.request.Request('http://www.openlp.org/files/version.txt') + req.add_header('User-Agent', 'OpenLP/%s %s/%s; ' % (current_version['full'], platform.system(), + platform.release())) + remote_version = None + retries = 0 + while True: + try: + remote_version = str(urllib.request.urlopen(req, None, + timeout=CONNECTION_TIMEOUT).read().decode()).strip() + except (urllib.error.URLError, ConnectionError): + if retries > CONNECTION_RETRIES: + log.exception('Failed to download the latest OpenLP version file') + else: + retries += 1 + time.sleep(0.1) + continue + break + if remote_version: + version_string = remote_version + return version_string diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index d63dee23c..7ae3cdc6f 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -34,9 +34,8 @@ from sqlalchemy.pool import NullPool from alembic.migration import MigrationContext from alembic.operations import Operations -from openlp.core.common import AppLocation, Settings, translate +from openlp.core.common import AppLocation, Settings, translate, delete_file from openlp.core.lib.ui import critical_error_message_box -from openlp.core.utils import delete_file log = logging.getLogger(__name__) diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index 6c19ac1dd..b9c8ca5f0 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -24,11 +24,10 @@ Provide the generic plugin functionality for OpenLP plugins. """ import logging - from PyQt5 import QtCore from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings -from openlp.core.utils import get_application_version +from openlp.core.common.versionchecker import get_application_version log = logging.getLogger(__name__) diff --git a/openlp/core/lib/projector/pjlink1.py b/openlp/core/lib/projector/pjlink1.py index 5feda33f4..4cdd31269 100644 --- a/openlp/core/lib/projector/pjlink1.py +++ b/openlp/core/lib/projector/pjlink1.py @@ -513,17 +513,13 @@ class PJLink1(QTcpSocket): log.debug('(%s) _send_string(): Sending "%s"' % (self.ip, out.strip())) log.debug('(%s) _send_string(): Queue = %s' % (self.ip, self.send_queue)) self.socket_timer.start() - try: - self.projectorNetwork.emit(S_NETWORK_SENDING) - sent = self.write(out) - self.waitForBytesWritten(2000) # 2 seconds should be enough - if sent == -1: - # Network error? - self.change_status(E_NETWORK, - translate('OpenLP.PJLink1', 'Error while sending data to projector')) - except SocketError as e: - self.disconnect_from_host(abort=True) - self.changeStatus(E_NETWORK, '%s : %s' % (e.error(), e.errorString())) + self.projectorNetwork.emit(S_NETWORK_SENDING) + sent = self.write(out.encode('ascii')) + self.waitForBytesWritten(2000) # 2 seconds should be enough + if sent == -1: + # Network error? + self.change_status(E_NETWORK, + translate('OpenLP.PJLink1', 'Error while sending data to projector')) def process_command(self, cmd, data): """ @@ -665,7 +661,15 @@ class PJLink1(QTcpSocket): :param data: Class that projector supports. """ - self.pjlink_class = data + # bug 1550891: Projector returns non-standard class response: + # : Expected: %1CLSS=1 + # : Received: %1CLSS=Class 1 + if len(data) > 1: + # Split non-standard information from response + clss = data.split()[-1] + else: + clss = data + self.pjlink_class = clss log.debug('(%s) Setting pjlink_class for this projector to "%s"' % (self.ip, self.pjlink_class)) return diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py index 402e4ad34..ab47a65e1 100644 --- a/openlp/core/lib/ui.py +++ b/openlp/core/lib/ui.py @@ -27,8 +27,8 @@ import logging from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common import Registry, UiStrings, translate, is_macosx +from openlp.core.common.actions import ActionList from openlp.core.lib import build_icon -from openlp.core.utils.actions import ActionList log = logging.getLogger(__name__) diff --git a/openlp/core/lib/webpagereader.py b/openlp/core/lib/webpagereader.py new file mode 100644 index 000000000..653717c93 --- /dev/null +++ b/openlp/core/lib/webpagereader.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2016 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:`openlp.core.utils` module provides the utility libraries for OpenLP. +""" +import logging +import socket +import sys +import time +import urllib.error +import urllib.parse +import urllib.request +from http.client import HTTPException +from random import randint + +from openlp.core.common import Registry + +log = logging.getLogger(__name__ + '.__init__') + +USER_AGENTS = { + 'win32': [ + 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36' + ], + 'darwin': [ + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) ' + 'Chrome/26.0.1410.43 Safari/537.31', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/536.11 (KHTML, like Gecko) ' + 'Chrome/20.0.1132.57 Safari/536.11', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/536.11 (KHTML, like Gecko) ' + 'Chrome/20.0.1132.47 Safari/536.11', + ], + 'linux2': [ + 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.22 (KHTML, like Gecko) Ubuntu Chromium/25.0.1364.160 ' + 'Chrome/25.0.1364.160 Safari/537.22', + 'Mozilla/5.0 (X11; CrOS armv7l 2913.260.0) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.99 ' + 'Safari/537.11', + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.27 (KHTML, like Gecko) Chrome/26.0.1389.0 Safari/537.27' + ], + 'default': [ + 'Mozilla/5.0 (X11; NetBSD amd64; rv:18.0) Gecko/20130120 Firefox/18.0' + ] +} +CONNECTION_TIMEOUT = 30 +CONNECTION_RETRIES = 2 + + +class HTTPRedirectHandlerFixed(urllib.request.HTTPRedirectHandler): + """ + Special HTTPRedirectHandler used to work around http://bugs.python.org/issue22248 + (Redirecting to urls with special chars) + """ + def redirect_request(self, req, fp, code, msg, headers, new_url): + # + """ + Test if the new_url can be decoded to ascii + + :param req: + :param fp: + :param code: + :param msg: + :param headers: + :param new_url: + :return: + """ + try: + new_url.encode('latin1').decode('ascii') + fixed_url = new_url + except Exception: + # The url could not be decoded to ascii, so we do some url encoding + fixed_url = urllib.parse.quote(new_url.encode('latin1').decode('utf-8', 'replace'), safe='/:') + return super(HTTPRedirectHandlerFixed, self).redirect_request(req, fp, code, msg, headers, fixed_url) + + +def _get_user_agent(): + """ + Return a user agent customised for the platform the user is on. + """ + browser_list = USER_AGENTS.get(sys.platform, None) + if not browser_list: + browser_list = USER_AGENTS['default'] + random_index = randint(0, len(browser_list) - 1) + return browser_list[random_index] + + +def get_web_page(url, header=None, update_openlp=False): + """ + Attempts to download the webpage at url and returns that page or None. + + :param url: The URL to be downloaded. + :param header: An optional HTTP header to pass in the request to the web server. + :param update_openlp: Tells OpenLP to update itself if the page is successfully downloaded. + Defaults to False. + """ + # TODO: Add proxy usage. Get proxy info from OpenLP settings, add to a + # proxy_handler, build into an opener and install the opener into urllib2. + # http://docs.python.org/library/urllib2.html + if not url: + return None + # This is needed to work around http://bugs.python.org/issue22248 and https://bugs.launchpad.net/openlp/+bug/1251437 + opener = urllib.request.build_opener(HTTPRedirectHandlerFixed()) + urllib.request.install_opener(opener) + req = urllib.request.Request(url) + if not header or header[0].lower() != 'user-agent': + user_agent = _get_user_agent() + req.add_header('User-Agent', user_agent) + if header: + req.add_header(header[0], header[1]) + log.debug('Downloading URL = %s' % url) + retries = 0 + while retries <= CONNECTION_RETRIES: + retries += 1 + time.sleep(0.1) + try: + page = urllib.request.urlopen(req, timeout=CONNECTION_TIMEOUT) + log.debug('Downloaded page {}'.format(page.geturl())) + break + except urllib.error.URLError as err: + log.exception('URLError on {}'.format(url)) + log.exception('URLError: {}'.format(err.reason)) + page = None + if retries > CONNECTION_RETRIES: + raise + except socket.timeout: + log.exception('Socket timeout: {}'.format(url)) + page = None + if retries > CONNECTION_RETRIES: + raise + except socket.gaierror: + log.exception('Socket gaierror: {}'.format(url)) + page = None + if retries > CONNECTION_RETRIES: + raise + except ConnectionRefusedError: + log.exception('ConnectionRefused: {}'.format(url)) + page = None + if retries > CONNECTION_RETRIES: + raise + break + except ConnectionError: + log.exception('Connection error: {}'.format(url)) + page = None + if retries > CONNECTION_RETRIES: + raise + except HTTPException: + log.exception('HTTPException error: {}'.format(url)) + page = None + if retries > CONNECTION_RETRIES: + raise + except: + # Don't know what's happening, so reraise the original + raise + if update_openlp: + Registry().get('application').process_events() + if not page: + log.exception('{} could not be downloaded'.format(url)) + return None + log.debug(page) + return page + + +__all__ = ['get_application_version', 'check_latest_version', + 'get_web_page'] diff --git a/openlp/core/ui/aboutform.py b/openlp/core/ui/aboutform.py index b376d4646..fc29f968c 100644 --- a/openlp/core/ui/aboutform.py +++ b/openlp/core/ui/aboutform.py @@ -26,8 +26,8 @@ import webbrowser from PyQt5 import QtCore, QtWidgets +from openlp.core.common.versionchecker import get_application_version from openlp.core.lib import translate -from openlp.core.utils import get_application_version from .aboutdialog import UiAboutDialog diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 4421b432f..f32672f58 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -29,9 +29,9 @@ import sys from PyQt5 import QtCore, QtGui, QtWidgets -from openlp.core.common import AppLocation, Settings, SlideLimits, UiStrings, translate +from openlp.core.common import AppLocation, Settings, SlideLimits, UiStrings, translate, get_images_filter from openlp.core.lib import ColorButton, SettingsTab, build_icon -from openlp.core.utils import format_time, get_images_filter +from openlp.core.common.languagemanager import format_time log = logging.getLogger(__name__) @@ -77,9 +77,19 @@ class AdvancedTab(SettingsTab): self.single_click_preview_check_box = QtWidgets.QCheckBox(self.ui_group_box) self.single_click_preview_check_box.setObjectName('single_click_preview_check_box') self.ui_layout.addRow(self.single_click_preview_check_box) + self.single_click_service_preview_check_box = QtWidgets.QCheckBox(self.ui_group_box) + self.single_click_service_preview_check_box.setObjectName('single_click_service_preview_check_box') + self.ui_layout.addRow(self.single_click_service_preview_check_box) self.expand_service_item_check_box = QtWidgets.QCheckBox(self.ui_group_box) self.expand_service_item_check_box.setObjectName('expand_service_item_check_box') self.ui_layout.addRow(self.expand_service_item_check_box) + self.slide_max_height_label = QtWidgets.QLabel(self.ui_group_box) + self.slide_max_height_label.setObjectName('slide_max_height_label') + self.slide_max_height_spin_box = QtWidgets.QSpinBox(self.ui_group_box) + self.slide_max_height_spin_box.setObjectName('slide_max_height_spin_box') + self.slide_max_height_spin_box.setRange(0, 1000) + self.slide_max_height_spin_box.setSingleStep(20) + self.ui_layout.addRow(self.slide_max_height_label, self.slide_max_height_spin_box) self.search_as_type_check_box = QtWidgets.QCheckBox(self.ui_group_box) self.search_as_type_check_box.setObjectName('SearchAsType_check_box') self.ui_layout.addRow(self.search_as_type_check_box) @@ -270,8 +280,13 @@ class AdvancedTab(SettingsTab): 'Double-click to send items straight to live')) self.single_click_preview_check_box.setText(translate('OpenLP.AdvancedTab', 'Preview items when clicked in Media Manager')) + self.single_click_service_preview_check_box.setText(translate('OpenLP.AdvancedTab', + 'Preview items when clicked in Service Manager')) self.expand_service_item_check_box.setText(translate('OpenLP.AdvancedTab', 'Expand new service items on creation')) + self.slide_max_height_label.setText(translate('OpenLP.AdvancedTab', + 'Max height for non-text slides\nin slide controller:')) + self.slide_max_height_spin_box.setSpecialValueText(translate('OpenLP.AdvancedTab', 'Disabled')) self.enable_auto_close_check_box.setText(translate('OpenLP.AdvancedTab', 'Enable application exit confirmation')) self.service_name_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Default Service Name')) @@ -339,7 +354,9 @@ class AdvancedTab(SettingsTab): self.media_plugin_check_box.setChecked(settings.value('save current plugin')) self.double_click_live_check_box.setChecked(settings.value('double click live')) self.single_click_preview_check_box.setChecked(settings.value('single click preview')) + self.single_click_service_preview_check_box.setChecked(settings.value('single click service preview')) self.expand_service_item_check_box.setChecked(settings.value('expand service item')) + self.slide_max_height_spin_box.setValue(settings.value('slide max height')) self.enable_auto_close_check_box.setChecked(settings.value('enable exit confirmation')) self.hide_mouse_check_box.setChecked(settings.value('hide mouse')) self.service_name_day.setCurrentIndex(settings.value('default service day')) @@ -420,7 +437,9 @@ class AdvancedTab(SettingsTab): settings.setValue('save current plugin', self.media_plugin_check_box.isChecked()) settings.setValue('double click live', self.double_click_live_check_box.isChecked()) settings.setValue('single click preview', self.single_click_preview_check_box.isChecked()) + settings.setValue('single click service preview', self.single_click_service_preview_check_box.isChecked()) settings.setValue('expand service item', self.expand_service_item_check_box.isChecked()) + settings.setValue('slide max height', self.slide_max_height_spin_box.value()) settings.setValue('enable exit confirmation', self.enable_auto_close_check_box.isChecked()) settings.setValue('hide mouse', self.hide_mouse_check_box.isChecked()) settings.setValue('alternate rows', self.alternate_rows_check_box.isChecked()) diff --git a/openlp/core/ui/exceptionform.py b/openlp/core/ui/exceptionform.py index e985829ba..68dd9705f 100644 --- a/openlp/core/ui/exceptionform.py +++ b/openlp/core/ui/exceptionform.py @@ -23,18 +23,17 @@ The actual exception dialog form. """ import logging -import re import os import platform +import re import bs4 import sqlalchemy +from PyQt5 import Qt, QtCore, QtGui, QtWebKit, QtWidgets from lxml import etree from openlp.core.common import RegistryProperties, is_linux -from PyQt5 import Qt, QtCore, QtGui, QtWebKit, QtWidgets - try: import migrate MIGRATE_VERSION = getattr(migrate, '__version__', '< 0.7') @@ -74,7 +73,7 @@ except ImportError: VLC_VERSION = '-' from openlp.core.common import Settings, UiStrings, translate -from openlp.core.utils import get_application_version +from openlp.core.common.versionchecker import get_application_version from .exceptiondialog import Ui_ExceptionDialog @@ -180,11 +179,13 @@ class ExceptionForm(QtWidgets.QDialog, Ui_ExceptionDialog, RegistryProperties): if ':' in line: exception = line.split('\n')[-1].split(':')[0] subject = 'Bug report: %s in %s' % (exception, source) - mail_to_url = QtCore.QUrlQuery('mailto:bugs@openlp.org') - mail_to_url.addQueryItem('subject', subject) - mail_to_url.addQueryItem('body', self.report_text % content) + mail_urlquery = QtCore.QUrlQuery() + mail_urlquery.addQueryItem('subject', subject) + mail_urlquery.addQueryItem('body', self.report_text % content) if self.file_attachment: - mail_to_url.addQueryItem('attach', self.file_attachment) + mail_urlquery.addQueryItem('attach', self.file_attachment) + mail_to_url = QtCore.QUrl('mailto:bugs@openlp.org') + mail_to_url.setQuery(mail_urlquery) QtGui.QDesktopServices.openUrl(mail_to_url) def on_description_updated(self): diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py index 0d7c129bf..f2be3b29c 100644 --- a/openlp/core/ui/firsttimeform.py +++ b/openlp/core/ui/firsttimeform.py @@ -39,7 +39,7 @@ from openlp.core.common import Registry, RegistryProperties, AppLocation, Settin translate, clean_button_text, trace_error_handler from openlp.core.lib import PluginStatus, build_icon from openlp.core.lib.ui import critical_error_message_box -from openlp.core.utils import get_web_page, CONNECTION_RETRIES, CONNECTION_TIMEOUT +from openlp.core.lib.webpagereader import get_web_page, CONNECTION_RETRIES, CONNECTION_TIMEOUT from .firsttimewizard import UiFirstTimeWizard, FirstTimePage log = logging.getLogger(__name__) diff --git a/openlp/core/ui/firsttimelanguageform.py b/openlp/core/ui/firsttimelanguageform.py index a55713bf0..4058612fb 100644 --- a/openlp/core/ui/firsttimelanguageform.py +++ b/openlp/core/ui/firsttimelanguageform.py @@ -25,7 +25,7 @@ The language selection dialog. from PyQt5 import QtCore, QtWidgets from openlp.core.lib.ui import create_action -from openlp.core.utils import LanguageManager +from openlp.core.common import LanguageManager from .firsttimelanguagedialog import Ui_FirstTimeLanguageDialog diff --git a/tests/functional/openlp_core_utils/__init__.py b/openlp/core/ui/lib/__init__.py similarity index 100% rename from tests/functional/openlp_core_utils/__init__.py rename to openlp/core/ui/lib/__init__.py diff --git a/openlp/core/common/historycombobox.py b/openlp/core/ui/lib/historycombobox.py similarity index 98% rename from openlp/core/common/historycombobox.py rename to openlp/core/ui/lib/historycombobox.py index f0ec7c2ad..23e05e76e 100644 --- a/openlp/core/common/historycombobox.py +++ b/openlp/core/ui/lib/historycombobox.py @@ -20,7 +20,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -The :mod:`~openlp.core.common.historycombobox` module contains the HistoryComboBox widget +The :mod:`~openlp.core.ui.lib.historycombobox` module contains the HistoryComboBox widget """ from PyQt5 import QtCore, QtWidgets diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index fb6481e56..68c983d42 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -26,7 +26,7 @@ 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 +from openlp.core.common import RegistryProperties, Settings from openlp.core.lib import ImageSource, ServiceItem @@ -63,6 +63,8 @@ class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties): # Initialize variables. self.service_item = ServiceItem() self.screen_ratio = screen_ratio + # Connect signals + self.verticalHeader().sectionResized.connect(self.row_resized) def resizeEvent(self, event): """ @@ -80,12 +82,30 @@ class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties): # Sort out songs, bibles, etc. if self.service_item.is_text(): self.resizeRowsToContents() + # Sort out image heights. else: - # Sort out image heights. + height = self.viewport().width() // self.screen_ratio + max_img_row_height = Settings().value('advanced/slide max height') + # Adjust for row height cap if in use. + if max_img_row_height > 0 and height > max_img_row_height: + height = max_img_row_height + # Apply new height to slides for frame_number in range(len(self.service_item.get_frames())): - height = self.viewport().width() // self.screen_ratio self.setRowHeight(frame_number, height) + def row_resized(self, row, old_height, new_height): + """ + Will scale non-image slides. + """ + # Only for non-text slides when row height cap in use + if self.service_item.is_text() or Settings().value('advanced/slide max height') <= 0: + return + # Get and validate label widget containing slide & adjust max width + try: + self.cellWidget(row, 0).children()[1].setMaximumWidth(new_height * self.screen_ratio) + except: + return + def screen_size_changed(self, screen_ratio): """ This method is called whenever the live screen size changes, which then makes a layout recalculation necessary @@ -139,8 +159,26 @@ class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties): pixmap = QtGui.QPixmap.fromImage(image) pixmap.setDevicePixelRatio(label.devicePixelRatio()) label.setPixmap(pixmap) - self.setCellWidget(frame_number, 0, label) slide_height = width // self.screen_ratio + # Setup row height cap if in use. + max_img_row_height = Settings().value('advanced/slide max height') + if max_img_row_height > 0: + if slide_height > max_img_row_height: + slide_height = max_img_row_height + label.setMaximumWidth(max_img_row_height * self.screen_ratio) + label.resize(max_img_row_height * self.screen_ratio, max_img_row_height) + # Build widget with stretch padding + container = QtWidgets.QWidget() + hbox = QtWidgets.QHBoxLayout() + hbox.setContentsMargins(0, 0, 0, 0) + hbox.addWidget(label, stretch=1) + hbox.addStretch(0) + container.setLayout(hbox) + # Add to table + self.setCellWidget(frame_number, 0, container) + else: + # Add to table + self.setCellWidget(frame_number, 0, label) row += 1 text.append(str(row)) self.setItem(frame_number, 0, item) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index a4bfa4bc5..d9a9a6468 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -408,10 +408,7 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties): self.application.process_events() # Workaround for bug #1531319, should not be needed with PyQt 5.6. if is_win(): - # Workaround for bug #1531319, should not be needed with PyQt 5.6. fade_shake_timer.stop() - elif is_win(): - self.shake_web_view() # Wait for the webview to update before getting the preview. # Important otherwise first preview will miss the background ! while not self.web_loaded: @@ -429,6 +426,9 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties): self.setVisible(True) else: self.setVisible(True) + # Workaround for bug #1531319, should not be needed with PyQt 5.6. + if is_win(): + self.shake_web_view() return self.grab() def build_html(self, service_item, image_path=''): diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 4427de655..228969ad1 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -24,30 +24,29 @@ This is the main window, where all the action happens. """ import logging import os -import sys import shutil +import sys +import time +from datetime import datetime from distutils import dir_util from distutils.errors import DistutilsFileError from tempfile import gettempdir -import time -from datetime import datetime from PyQt5 import QtCore, QtGui, QtWidgets -from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, check_directory_exists, translate, \ - is_win, is_macosx +from openlp.core.common import Registry, RegistryProperties, AppLocation, LanguageManager, Settings, \ + check_directory_exists, translate, is_win, is_macosx, add_actions +from openlp.core.common.actions import ActionList, CategoryOrder +from openlp.core.common.versionchecker import get_application_version from openlp.core.lib import Renderer, OpenLPDockWidget, PluginManager, ImageManager, PluginStatus, ScreenList, \ build_icon from openlp.core.lib.ui import UiStrings, create_action from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, LiveController, PluginForm, \ MediaDockManager, ShortcutListForm, FormattingTagForm, PreviewController - -from openlp.core.ui.media import MediaController -from openlp.core.utils import LanguageManager, add_actions, get_application_version -from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.ui.firsttimeform import FirstTimeForm -from openlp.core.ui.projector.manager import ProjectorManager +from openlp.core.ui.media import MediaController from openlp.core.ui.printserviceform import PrintServiceForm +from openlp.core.ui.projector.manager import ProjectorManager log = logging.getLogger(__name__) diff --git a/openlp/core/ui/projector/manager.py b/openlp/core/ui/projector/manager.py index 52b640956..fc40ee386 100644 --- a/openlp/core/ui/projector/manager.py +++ b/openlp/core/ui/projector/manager.py @@ -83,60 +83,60 @@ class Ui_ProjectorManager(object): self.one_toolbar.add_toolbar_action('new_projector', text=translate('OpenLP.ProjectorManager', 'Add Projector'), icon=':/projector/projector_new.png', - tooltip=translate('OpenLP.ProjectorManager', 'Add a new projector'), + tooltip=translate('OpenLP.ProjectorManager', 'Add a new projector.'), triggers=self.on_add_projector) # Show edit/delete when projector not connected self.one_toolbar.add_toolbar_action('edit_projector', text=translate('OpenLP.ProjectorManager', 'Edit Projector'), icon=':/general/general_edit.png', - tooltip=translate('OpenLP.ProjectorManager', 'Edit selected projector'), + tooltip=translate('OpenLP.ProjectorManager', 'Edit selected projector.'), triggers=self.on_edit_projector) self.one_toolbar.add_toolbar_action('delete_projector', text=translate('OpenLP.ProjectorManager', 'Delete Projector'), icon=':/general/general_delete.png', - tooltip=translate('OpenLP.ProjectorManager', 'Delete selected projector'), + tooltip=translate('OpenLP.ProjectorManager', 'Delete selected projector.'), triggers=self.on_delete_projector) # Show source/view when projector connected self.one_toolbar.add_toolbar_action('source_view_projector', text=translate('OpenLP.ProjectorManager', 'Select Input Source'), icon=':/projector/projector_hdmi.png', tooltip=translate('OpenLP.ProjectorManager', - 'Choose input source on selected projector'), + 'Choose input source on selected projector.'), triggers=self.on_select_input) self.one_toolbar.add_toolbar_action('view_projector', text=translate('OpenLP.ProjectorManager', 'View Projector'), icon=':/system/system_about.png', tooltip=translate('OpenLP.ProjectorManager', - 'View selected projector information'), + 'View selected projector information.'), triggers=self.on_status_projector) self.one_toolbar.addSeparator() self.one_toolbar.add_toolbar_action('connect_projector', text=translate('OpenLP.ProjectorManager', - 'Connect to selected projector'), + 'Connect to selected projector.'), icon=':/projector/projector_connect.png', tooltip=translate('OpenLP.ProjectorManager', - 'Connect to selected projector'), + 'Connect to selected projector.'), triggers=self.on_connect_projector) self.one_toolbar.add_toolbar_action('connect_projector_multiple', text=translate('OpenLP.ProjectorManager', 'Connect to selected projectors'), icon=':/projector/projector_connect_tiled.png', tooltip=translate('OpenLP.ProjectorManager', - 'Connect to selected projector'), + 'Connect to selected projectors.'), triggers=self.on_connect_projector) self.one_toolbar.add_toolbar_action('disconnect_projector', text=translate('OpenLP.ProjectorManager', 'Disconnect from selected projectors'), icon=':/projector/projector_disconnect.png', tooltip=translate('OpenLP.ProjectorManager', - 'Disconnect from selected projector'), + 'Disconnect from selected projector.'), triggers=self.on_disconnect_projector) self.one_toolbar.add_toolbar_action('disconnect_projector_multiple', text=translate('OpenLP.ProjectorManager', 'Disconnect from selected projector'), icon=':/projector/projector_disconnect_tiled.png', tooltip=translate('OpenLP.ProjectorManager', - 'Disconnect from selected projector'), + 'Disconnect from selected projectors.'), triggers=self.on_disconnect_projector) self.one_toolbar.addSeparator() self.one_toolbar.add_toolbar_action('poweron_projector', @@ -144,26 +144,26 @@ class Ui_ProjectorManager(object): 'Power on selected projector'), icon=':/projector/projector_power_on.png', tooltip=translate('OpenLP.ProjectorManager', - 'Power on selected projector'), + 'Power on selected projector.'), triggers=self.on_poweron_projector) self.one_toolbar.add_toolbar_action('poweron_projector_multiple', text=translate('OpenLP.ProjectorManager', 'Power on selected projector'), icon=':/projector/projector_power_on_tiled.png', tooltip=translate('OpenLP.ProjectorManager', - 'Power on selected projector'), + 'Power on selected projectors.'), triggers=self.on_poweron_projector) self.one_toolbar.add_toolbar_action('poweroff_projector', text=translate('OpenLP.ProjectorManager', 'Standby selected projector'), icon=':/projector/projector_power_off.png', tooltip=translate('OpenLP.ProjectorManager', - 'Put selected projector in standby'), + 'Put selected projector in standby.'), triggers=self.on_poweroff_projector) self.one_toolbar.add_toolbar_action('poweroff_projector_multiple', text=translate('OpenLP.ProjectorManager', 'Standby selected projector'), icon=':/projector/projector_power_off_tiled.png', tooltip=translate('OpenLP.ProjectorManager', - 'Put selected projector in standby'), + 'Put selected projectors in standby.'), triggers=self.on_poweroff_projector) self.one_toolbar.addSeparator() self.one_toolbar.add_toolbar_action('blank_projector', @@ -175,24 +175,24 @@ class Ui_ProjectorManager(object): triggers=self.on_blank_projector) self.one_toolbar.add_toolbar_action('blank_projector_multiple', text=translate('OpenLP.ProjectorManager', - 'Blank selected projector screen'), + 'Blank selected projectors screen'), icon=':/projector/projector_blank_tiled.png', tooltip=translate('OpenLP.ProjectorManager', - 'Blank selected projector screen'), + 'Blank selected projectors screen.'), triggers=self.on_blank_projector) self.one_toolbar.add_toolbar_action('show_projector', text=translate('OpenLP.ProjectorManager', 'Show selected projector screen'), icon=':/projector/projector_show.png', tooltip=translate('OpenLP.ProjectorManager', - 'Show selected projector screen'), + 'Show selected projector screen.'), triggers=self.on_show_projector) self.one_toolbar.add_toolbar_action('show_projector_multiple', text=translate('OpenLP.ProjectorManager', 'Show selected projector screen'), icon=':/projector/projector_show_tiled.png', tooltip=translate('OpenLP.ProjectorManager', - 'Show selected projector screen'), + 'Show selected projectors screen.'), triggers=self.on_show_projector) self.layout.addWidget(self.one_toolbar) self.projector_one_widget = QtWidgets.QWidgetAction(self.one_toolbar) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index e4a1b143a..66cbdf1b7 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -23,23 +23,22 @@ The service manager sets up, loads, saves and manages services. """ import html +import json import os import shutil import zipfile -import json -from tempfile import mkstemp from datetime import datetime, timedelta +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 + RegistryMixin, check_directory_exists, UiStrings, translate, split_filename, delete_file +from openlp.core.common.actions import ActionList, CategoryOrder from openlp.core.lib import OpenLPToolbar, 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 -from openlp.core.ui.printserviceform import PrintServiceForm -from openlp.core.utils import delete_file, split_filename, format_time -from openlp.core.utils.actions import ActionList, CategoryOrder +from openlp.core.common.languagemanager import format_time class ServiceManagerList(QtWidgets.QTreeWidget): @@ -211,7 +210,8 @@ class Ui_ServiceManager(object): self.layout.addWidget(self.order_toolbar) # Connect up our signals and slots self.theme_combo_box.activated.connect(self.on_theme_combo_box_selected) - self.service_manager_list.doubleClicked.connect(self.on_make_live) + self.service_manager_list.doubleClicked.connect(self.on_double_click_live) + self.service_manager_list.clicked.connect(self.on_single_click_preview) self.service_manager_list.itemCollapsed.connect(self.collapsed) self.service_manager_list.itemExpanded.connect(self.expanded) # Last little bits of setting up @@ -319,6 +319,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa self._modified = False self._file_name = '' self.service_has_all_original_files = True + self.list_double_clicked = False def bootstrap_initialise(self): """ @@ -1454,13 +1455,38 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa else: return self.service_items[item]['service_item'] - def on_make_live(self, field=None): + def on_double_click_live(self, field=None): """ Send the current item to the Live slide controller but triggered by a tablewidget click event. :param field: """ + self.list_double_clicked = True self.make_live() + def on_single_click_preview(self, field=None): + """ + If single click previewing is enabled, and triggered by a tablewidget click event, + start a timeout to verify a double-click hasn't triggered. + :param field: + """ + if Settings().value('advanced/single click service preview'): + if not self.list_double_clicked: + # If a double click has not registered start a timer, otherwise wait for the existing timer to finish. + QtCore.QTimer.singleShot(QtWidgets.QApplication.instance().doubleClickInterval(), + self.on_single_click_preview_timeout) + + def on_single_click_preview_timeout(self): + """ + If a single click ok, but double click not triggered, send the current item to the Preview slide controller. + :param field: + """ + if self.list_double_clicked: + # If a double click has registered, clear it. + self.list_double_clicked = False + else: + # Otherwise preview the item. + self.make_preview() + def make_live(self, row=-1): """ Send the current item to the Live slide controller diff --git a/openlp/core/ui/shortcutlistform.py b/openlp/core/ui/shortcutlistform.py index 574392a7a..e0d72d9e1 100644 --- a/openlp/core/ui/shortcutlistform.py +++ b/openlp/core/ui/shortcutlistform.py @@ -27,7 +27,7 @@ import re from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common import RegistryProperties, Settings, translate -from openlp.core.utils.actions import ActionList +from openlp.core.common.actions import ActionList from .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 9e2c86a3a..96ce82868 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -23,20 +23,20 @@ The :mod:`slidecontroller` module contains the most important part of OpenLP - the slide controller """ -import os import copy +import os from collections import deque from threading import Lock from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common import Registry, RegistryProperties, Settings, SlideLimits, UiStrings, translate, \ - RegistryMixin, OpenLPMixin, is_win + RegistryMixin, OpenLPMixin +from openlp.core.common.actions import ActionList, CategoryOrder from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, ImageSource, ServiceItemAction, \ ScreenList, build_icon, build_html -from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType from openlp.core.lib.ui import create_action -from openlp.core.utils.actions import ActionList, CategoryOrder +from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType from openlp.core.ui.listpreviewwidget import ListPreviewWidget # Threshold which has to be trespassed to toggle. @@ -601,13 +601,21 @@ class SlideController(DisplayController, RegistryProperties): def __add_actions_to_widget(self, widget): """ Add actions to the widget specified by `widget` + This defines the controls available when Live display has stolen focus. + Examples of this happening: Clicking anything in the live window or certain single screen mode scenarios. + Needles to say, blank to modes should not be removed from here. + For some reason this required a test. It may be found in test_slidecontroller.py as + "live_stolen_focus_shortcuts_test. If you want to modify things here, you must also modify them there. (Duh) :param widget: The UI widget for the actions """ widget.addActions([ self.previous_item, self.next_item, self.previous_service, self.next_service, - self.escape_item]) + self.escape_item, + self.desktop_screen, + self.theme_screen, + self.blank_screen]) def preview_size_changed(self): """ diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index 0b1316d66..20143ddaa 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -27,11 +27,10 @@ import os from PyQt5 import QtCore, QtGui, QtWidgets -from openlp.core.common import Registry, RegistryProperties, UiStrings, translate +from openlp.core.common import Registry, RegistryProperties, UiStrings, translate, get_images_filter, is_not_image_file 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, is_not_image_file from .themewizard import Ui_ThemeWizard log = logging.getLogger(__name__) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index fdf87e528..a80640150 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -30,13 +30,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, \ - check_directory_exists, UiStrings, translate, is_win + check_directory_exists, UiStrings, translate, is_win, get_filesystem_encoding, delete_file from openlp.core.lib import FileDialog, ImageSource, OpenLPToolbar, ValidationError, get_text_file_string, build_icon, \ check_item_selected, create_thumb, validate_thumb from openlp.core.lib.theme import ThemeXML, BackgroundType from openlp.core.lib.ui import critical_error_message_box, create_widget_action from openlp.core.ui import FileRenameForm, ThemeForm -from openlp.core.utils import delete_file, get_locale_key, get_filesystem_encoding +from openlp.core.common.languagemanager import get_locale_key class Ui_ThemeManager(object): diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py deleted file mode 100644 index 086c69c79..000000000 --- a/openlp/core/utils/__init__.py +++ /dev/null @@ -1,543 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2016 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:`openlp.core.utils` module provides the utility libraries for OpenLP. -""" -from datetime import datetime -from distutils.version import LooseVersion -from http.client import HTTPException -import logging -import locale -import os -import platform -import re -import socket -import time -from shutil import which -from subprocess import Popen, PIPE -import sys -import urllib.request -import urllib.error -import urllib.parse -from random import randint - -from PyQt5 import QtGui, QtCore - -from openlp.core.common import Registry, AppLocation, Settings, is_win, is_macosx - - -if not is_win() and not is_macosx(): - try: - from xdg import BaseDirectory - XDG_BASE_AVAILABLE = True - except ImportError: - BaseDirectory = None - XDG_BASE_AVAILABLE = False - -from openlp.core.common import translate - -log = logging.getLogger(__name__ + '.__init__') - -APPLICATION_VERSION = {} -IMAGES_FILTER = None -ICU_COLLATOR = None -CONTROL_CHARS = re.compile(r'[\x00-\x1F\x7F-\x9F]', re.UNICODE) -INVALID_FILE_CHARS = re.compile(r'[\\/:\*\?"<>\|\+\[\]%]', re.UNICODE) -DIGITS_OR_NONDIGITS = re.compile(r'\d+|\D+', re.UNICODE) -USER_AGENTS = { - 'win32': [ - 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36', - 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36', - 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36' - ], - 'darwin': [ - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) ' - 'Chrome/26.0.1410.43 Safari/537.31', - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/536.11 (KHTML, like Gecko) ' - 'Chrome/20.0.1132.57 Safari/536.11', - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/536.11 (KHTML, like Gecko) ' - 'Chrome/20.0.1132.47 Safari/536.11', - ], - 'linux2': [ - 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.22 (KHTML, like Gecko) Ubuntu Chromium/25.0.1364.160 ' - 'Chrome/25.0.1364.160 Safari/537.22', - 'Mozilla/5.0 (X11; CrOS armv7l 2913.260.0) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.99 ' - 'Safari/537.11', - 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.27 (KHTML, like Gecko) Chrome/26.0.1389.0 Safari/537.27' - ], - 'default': [ - 'Mozilla/5.0 (X11; NetBSD amd64; rv:18.0) Gecko/20130120 Firefox/18.0' - ] -} -CONNECTION_TIMEOUT = 30 -CONNECTION_RETRIES = 2 - - -class VersionThread(QtCore.QThread): - """ - A special Qt thread class to fetch the version of OpenLP from the website. - This is threaded so that it doesn't affect the loading time of OpenLP. - """ - def __init__(self, main_window): - """ - Constructor for the thread class. - - :param main_window: The main window Object. - """ - log.debug("VersionThread - Initialise") - super(VersionThread, self).__init__(None) - self.main_window = main_window - - def run(self): - """ - Run the thread. - """ - self.sleep(1) - log.debug('Version thread - run') - app_version = get_application_version() - version = check_latest_version(app_version) - log.debug("Versions %s and %s " % (LooseVersion(str(version)), LooseVersion(str(app_version['full'])))) - if LooseVersion(str(version)) > LooseVersion(str(app_version['full'])): - self.main_window.openlp_version_check.emit('%s' % version) - - -class HTTPRedirectHandlerFixed(urllib.request.HTTPRedirectHandler): - """ - Special HTTPRedirectHandler used to work around http://bugs.python.org/issue22248 - (Redirecting to urls with special chars) - """ - def redirect_request(self, req, fp, code, msg, headers, new_url): - # - """ - Test if the new_url can be decoded to ascii - - :param req: - :param fp: - :param code: - :param msg: - :param headers: - :param new_url: - :return: - """ - try: - new_url.encode('latin1').decode('ascii') - fixed_url = new_url - except Exception: - # The url could not be decoded to ascii, so we do some url encoding - fixed_url = urllib.parse.quote(new_url.encode('latin1').decode('utf-8', 'replace'), safe='/:') - return super(HTTPRedirectHandlerFixed, self).redirect_request(req, fp, code, msg, headers, fixed_url) - - -def get_application_version(): - """ - Returns the application version of the running instance of OpenLP:: - - {'full': '1.9.4-bzr1249', 'version': '1.9.4', 'build': 'bzr1249'} - """ - global APPLICATION_VERSION - if APPLICATION_VERSION: - return APPLICATION_VERSION - if '--dev-version' in sys.argv or '-d' in sys.argv: - # NOTE: The following code is a duplicate of the code in setup.py. Any fix applied here should also be applied - # there. - - # Get the revision of this tree. - bzr = Popen(('bzr', 'revno'), stdout=PIPE) - tree_revision, error = bzr.communicate() - tree_revision = tree_revision.decode() - code = bzr.wait() - if code != 0: - raise Exception('Error running bzr log') - - # Get all tags. - bzr = Popen(('bzr', 'tags'), stdout=PIPE) - output, error = bzr.communicate() - code = bzr.wait() - if code != 0: - raise Exception('Error running bzr tags') - tags = list(map(bytes.decode, output.splitlines())) - if not tags: - tag_version = '0.0.0' - tag_revision = '0' - else: - # Remove any tag that has "?" as revision number. A "?" as revision number indicates, that this tag is from - # another series. - tags = [tag for tag in tags if tag.split()[-1].strip() != '?'] - # Get the last tag and split it in a revision and tag name. - tag_version, tag_revision = tags[-1].split() - # If they are equal, then this tree is tarball with the source for the release. We do not want the revision - # number in the full version. - if tree_revision == tag_revision: - full_version = tag_version.decode('utf-8') - else: - full_version = '%s-bzr%s' % (tag_version.decode('utf-8'), tree_revision.decode('utf-8')) - else: - # We're not running the development version, let's use the file. - file_path = AppLocation.get_directory(AppLocation.VersionDir) - file_path = os.path.join(file_path, '.version') - version_file = None - try: - version_file = open(file_path, 'r') - full_version = str(version_file.read()).rstrip() - except IOError: - log.exception('Error in version file.') - full_version = '0.0.0-bzr000' - finally: - if version_file: - version_file.close() - bits = full_version.split('-') - APPLICATION_VERSION = { - 'full': full_version, - 'version': bits[0], - 'build': bits[1] if len(bits) > 1 else None - } - if APPLICATION_VERSION['build']: - log.info('Openlp version %s build %s', APPLICATION_VERSION['version'], APPLICATION_VERSION['build']) - else: - log.info('Openlp version %s' % APPLICATION_VERSION['version']) - return APPLICATION_VERSION - - -def check_latest_version(current_version): - """ - Check the latest version of OpenLP against the version file on the OpenLP - site. - - **Rules around versions and version files:** - - * If a version number has a build (i.e. -bzr1234), then it is a nightly. - * If a version number's minor version is an odd number, it is a development release. - * If a version number's minor version is an even number, it is a stable release. - - :param current_version: The current version of OpenLP. - """ - version_string = current_version['full'] - # set to prod in the distribution config file. - settings = Settings() - settings.beginGroup('core') - last_test = settings.value('last version test') - this_test = str(datetime.now().date()) - settings.setValue('last version test', this_test) - settings.endGroup() - if last_test != this_test: - if current_version['build']: - req = urllib.request.Request('http://www.openlp.org/files/nightly_version.txt') - else: - version_parts = current_version['version'].split('.') - if int(version_parts[1]) % 2 != 0: - req = urllib.request.Request('http://www.openlp.org/files/dev_version.txt') - else: - req = urllib.request.Request('http://www.openlp.org/files/version.txt') - req.add_header('User-Agent', 'OpenLP/%s %s/%s; ' % (current_version['full'], platform.system(), - platform.release())) - remote_version = None - retries = 0 - while True: - try: - remote_version = str(urllib.request.urlopen(req, None, - timeout=CONNECTION_TIMEOUT).read().decode()).strip() - except (urllib.error.URLError, ConnectionError): - if retries > CONNECTION_RETRIES: - log.exception('Failed to download the latest OpenLP version file') - else: - retries += 1 - time.sleep(0.1) - continue - break - if remote_version: - version_string = remote_version - return version_string - - -def add_actions(target, actions): - """ - Adds multiple actions to a menu or toolbar in one command. - - :param target: The menu or toolbar to add actions to - :param actions: The actions to be added. An action consisting of the keyword ``None`` - will result in a separator being inserted into the target. - """ - for action in actions: - if action is None: - target.addSeparator() - else: - target.addAction(action) - - -def get_filesystem_encoding(): - """ - Returns the name of the encoding used to convert Unicode filenames into system file names. - """ - encoding = sys.getfilesystemencoding() - if encoding is None: - encoding = sys.getdefaultencoding() - return encoding - - -def get_images_filter(): - """ - Returns a filter string for a file dialog containing all the supported image formats. - """ - global IMAGES_FILTER - if not IMAGES_FILTER: - log.debug('Generating images filter.') - formats = list(map(bytes.decode, list(map(bytes, QtGui.QImageReader.supportedImageFormats())))) - visible_formats = '(*.%s)' % '; *.'.join(formats) - actual_formats = '(*.%s)' % ' *.'.join(formats) - IMAGES_FILTER = '%s %s %s' % (translate('OpenLP', 'Image Files'), visible_formats, actual_formats) - return IMAGES_FILTER - - -def is_not_image_file(file_name): - """ - Validate that the file is not an image file. - - :param file_name: File name to be checked. - """ - if not file_name: - return True - else: - formats = [bytes(fmt).decode().lower() for fmt in QtGui.QImageReader.supportedImageFormats()] - file_part, file_extension = os.path.splitext(str(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. - """ - path = os.path.abspath(path) - if not os.path.isfile(path): - return path, '' - else: - return os.path.split(path) - - -def clean_filename(filename): - """ - Removes invalid characters from the given ``filename``. - - :param filename: The "dirty" file name to clean. - """ - if not isinstance(filename, str): - filename = str(filename, 'utf-8') - return INVALID_FILE_CHARS.sub('_', CONTROL_CHARS.sub('', filename)) - - -def delete_file(file_path_name): - """ - Deletes a file from the system. - - :param file_path_name: The file, including path, to delete. - """ - if not file_path_name: - return False - try: - if os.path.exists(file_path_name): - os.remove(file_path_name) - return True - except (IOError, OSError): - log.exception("Unable to delete file %s" % file_path_name) - return False - - -def _get_user_agent(): - """ - Return a user agent customised for the platform the user is on. - """ - browser_list = USER_AGENTS.get(sys.platform, None) - if not browser_list: - browser_list = USER_AGENTS['default'] - random_index = randint(0, len(browser_list) - 1) - return browser_list[random_index] - - -def get_web_page(url, header=None, update_openlp=False): - """ - Attempts to download the webpage at url and returns that page or None. - - :param url: The URL to be downloaded. - :param header: An optional HTTP header to pass in the request to the web server. - :param update_openlp: Tells OpenLP to update itself if the page is successfully downloaded. - Defaults to False. - """ - # TODO: Add proxy usage. Get proxy info from OpenLP settings, add to a - # proxy_handler, build into an opener and install the opener into urllib2. - # http://docs.python.org/library/urllib2.html - if not url: - return None - # This is needed to work around http://bugs.python.org/issue22248 and https://bugs.launchpad.net/openlp/+bug/1251437 - opener = urllib.request.build_opener(HTTPRedirectHandlerFixed()) - urllib.request.install_opener(opener) - req = urllib.request.Request(url) - if not header or header[0].lower() != 'user-agent': - user_agent = _get_user_agent() - req.add_header('User-Agent', user_agent) - if header: - req.add_header(header[0], header[1]) - log.debug('Downloading URL = %s' % url) - retries = 0 - while retries <= CONNECTION_RETRIES: - retries += 1 - time.sleep(0.1) - try: - page = urllib.request.urlopen(req, timeout=CONNECTION_TIMEOUT) - log.debug('Downloaded page {}'.format(page.geturl())) - break - except urllib.error.URLError as err: - log.exception('URLError on {}'.format(url)) - log.exception('URLError: {}'.format(err.reason)) - page = None - if retries > CONNECTION_RETRIES: - raise - except socket.timeout: - log.exception('Socket timeout: {}'.format(url)) - page = None - if retries > CONNECTION_RETRIES: - raise - except socket.gaierror: - log.exception('Socket gaierror: {}'.format(url)) - page = None - if retries > CONNECTION_RETRIES: - raise - except ConnectionRefusedError: - log.exception('ConnectionRefused: {}'.format(url)) - page = None - if retries > CONNECTION_RETRIES: - raise - break - except ConnectionError: - log.exception('Connection error: {}'.format(url)) - page = None - if retries > CONNECTION_RETRIES: - raise - except HTTPException: - log.exception('HTTPException error: {}'.format(url)) - page = None - if retries > CONNECTION_RETRIES: - raise - except: - # Don't know what's happening, so reraise the original - raise - if update_openlp: - Registry().get('application').process_events() - if not page: - log.exception('{} could not be downloaded'.format(url)) - return None - log.debug(page) - return page - - -def get_uno_command(connection_type='pipe'): - """ - Returns the UNO command to launch an openoffice.org instance. - """ - for command in ['libreoffice', 'soffice']: - if which(command): - break - else: - raise FileNotFoundError('Command not found') - - OPTIONS = '--nologo --norestore --minimized --nodefault --nofirststartwizard' - if connection_type == 'pipe': - CONNECTION = '"--accept=pipe,name=openlp_pipe;urp;"' - else: - CONNECTION = '"--accept=socket,host=localhost,port=2002;urp;"' - return '%s %s %s' % (command, OPTIONS, CONNECTION) - - -def get_uno_instance(resolver, connection_type='pipe'): - """ - Returns a running openoffice.org instance. - - :param resolver: The UNO resolver to use to find a running instance. - """ - log.debug('get UNO Desktop Openoffice - resolve') - if connection_type == 'pipe': - return resolver.resolve('uno:pipe,name=openlp_pipe;urp;StarOffice.ComponentContext') - else: - return resolver.resolve('uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext') - - -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('\%[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 - from .languagemanager import LanguageManager - 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. - 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[0].isdigit(): - return [b''] + key - return key - - -from .languagemanager import LanguageManager -from .actions import ActionList - - -__all__ = ['ActionList', 'LanguageManager', 'get_application_version', 'check_latest_version', - 'add_actions', 'get_filesystem_encoding', 'get_web_page', 'get_uno_command', 'get_uno_instance', - 'delete_file', 'clean_filename', 'format_time', 'get_locale_key', 'get_natural_key'] diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 14b1f7805..61640262b 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -24,17 +24,16 @@ import logging from PyQt5 import QtGui - from openlp.core.common import Settings, translate +from openlp.core.common.actions import ActionList from openlp.core.lib import Plugin, StringContent, build_icon from openlp.core.lib.db import Manager -from openlp.core.lib.ui import create_action, UiStrings from openlp.core.lib.theme import VerticalType +from openlp.core.lib.ui import create_action, UiStrings from openlp.core.ui import AlertLocation -from openlp.core.utils.actions import ActionList +from openlp.plugins.alerts.forms import AlertForm from openlp.plugins.alerts.lib import AlertsManager, AlertsTab from openlp.plugins.alerts.lib.db import init_schema -from openlp.plugins.alerts.forms import AlertForm log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index 289f8cc32..ccc61ba56 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -24,13 +24,13 @@ import logging from PyQt5 import QtWidgets +from openlp.core.common.actions import ActionList from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib.ui import UiStrings, create_action -from openlp.core.utils.actions import ActionList +from openlp.plugins.bibles.forms import BibleUpgradeForm from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem, LayoutStyle, DisplayStyle, \ LanguageSelection from openlp.plugins.bibles.lib.mediaitem import BibleSearch -from openlp.plugins.bibles.forms import BibleUpgradeForm log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index 52417f2ef..27dbea963 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -28,11 +28,11 @@ import urllib.error from PyQt5 import QtWidgets -from openlp.core.common import AppLocation, Settings, UiStrings, translate +from openlp.core.common import AppLocation, Settings, UiStrings, translate, clean_filename from openlp.core.lib.db import delete_database from openlp.core.lib.ui import critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings -from openlp.core.utils import get_locale_key +from openlp.core.common.languagemanager import get_locale_key from openlp.plugins.bibles.lib.manager import BibleFormat from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename from openlp.plugins.bibles.lib.http import CWExtract, BGExtract, BSExtract diff --git a/openlp/plugins/bibles/forms/bibleupgradeform.py b/openlp/plugins/bibles/forms/bibleupgradeform.py index 4adfeaf3b..611e6ead3 100644 --- a/openlp/plugins/bibles/forms/bibleupgradeform.py +++ b/openlp/plugins/bibles/forms/bibleupgradeform.py @@ -29,10 +29,10 @@ from tempfile import gettempdir from PyQt5 import QtCore, QtWidgets -from openlp.core.common import Registry, AppLocation, UiStrings, Settings, check_directory_exists, translate +from openlp.core.common import Registry, AppLocation, UiStrings, Settings, check_directory_exists, translate, \ + delete_file from openlp.core.lib.ui import critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings -from openlp.core.utils import delete_file from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, BiblesResourcesDB from openlp.plugins.bibles.lib.http import BSExtract, BGExtract, CWExtract diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index b77117e21..8dcf8c042 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -33,10 +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 Registry, RegistryProperties, AppLocation, translate +from openlp.core.common import Registry, RegistryProperties, AppLocation, translate, clean_filename from openlp.core.lib.db import BaseModel, init_db, Manager from openlp.core.lib.ui import critical_error_message_box -from openlp.core.utils import clean_filename from openlp.plugins.bibles.lib import upgrade log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 35b1f4bcb..c81e65575 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -32,7 +32,7 @@ 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.utils import get_web_page +from openlp.core.lib.webpagereader import get_web_page from openlp.plugins.bibles.lib import SearchResults from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, Book diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 8cecbe0af..b8b7ee56f 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -23,8 +23,7 @@ import logging import os -from openlp.core.common import RegistryProperties, AppLocation, Settings, translate -from openlp.core.utils import delete_file +from openlp.core.common import RegistryProperties, AppLocation, Settings, translate, delete_file from openlp.plugins.bibles.lib import parse_reference, get_reference_separator, LanguageSelection from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta from .csvbible import CSVBible diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 94937e61b..cd728a68b 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -29,7 +29,7 @@ from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemConte 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.utils import get_locale_key +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 LayoutStyle, DisplayStyle, VerseReferenceList, get_reference_separator, \ diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 3aaee5290..b639c2692 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -198,6 +198,7 @@ class EditCustomForm(QtWidgets.QDialog, Ui_CustomEditDialog): # Insert all slides to make the old_slides list complete. for slide in slides: old_slides.insert(old_row, slide) + old_row += 1 self.slide_list_view.addItems(old_slides) self.slide_list_view.repaint() diff --git a/openlp/plugins/custom/lib/db.py b/openlp/plugins/custom/lib/db.py index 743822072..62ec1f408 100644 --- a/openlp/plugins/custom/lib/db.py +++ b/openlp/plugins/custom/lib/db.py @@ -28,7 +28,7 @@ from sqlalchemy import Column, Table, types from sqlalchemy.orm import mapper from openlp.core.lib.db import BaseModel, init_db -from openlp.core.utils import get_locale_key +from openlp.core.common.languagemanager import get_locale_key class CustomSlide(BaseModel): diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 248da94ea..f35fd48c7 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -25,11 +25,12 @@ import os from PyQt5 import QtCore, QtGui, QtWidgets -from openlp.core.common import Registry, AppLocation, Settings, UiStrings, check_directory_exists, translate +from openlp.core.common import Registry, AppLocation, Settings, UiStrings, check_directory_exists, translate, \ + delete_file, get_images_filter from openlp.core.lib import ItemCapabilities, MediaManagerItem, ServiceItemContext, StringContent, TreeWidgetWithDnD,\ 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.utils import delete_file, get_locale_key, get_images_filter +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 diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 3bd24fb8e..a8c6db35b 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -32,7 +32,7 @@ from openlp.core.lib import ItemCapabilities, MediaManagerItem, MediaType, Servi 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.utils import get_locale_key +from openlp.core.common.languagemanager import get_locale_key from openlp.core.ui.media.vlcplayer import get_vlc if get_vlc() is not None: diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index 183a05ac5..29af3a375 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -35,7 +35,7 @@ import logging import os import time -from openlp.core.common import is_win, Registry +from openlp.core.common import is_win, Registry, get_uno_command, get_uno_instance, delete_file if is_win(): from win32com.client import Dispatch @@ -57,7 +57,7 @@ else: from PyQt5 import QtCore from openlp.core.lib import ScreenList -from openlp.core.utils import delete_file, get_uno_command, get_uno_instance +from openlp.core.common import get_uno_command, get_uno_instance from .presentationcontroller import PresentationController, PresentationDocument, TextType diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index b2ece3e67..b64c552b8 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -29,7 +29,7 @@ from openlp.core.common import Registry, Settings, UiStrings, translate 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 -from openlp.core.utils import get_locale_key +from openlp.core.common.languagemanager import get_locale_key from openlp.plugins.presentations.lib import MessageListener from openlp.plugins.presentations.lib.pdfcontroller import PDF_CONTROLLER_FILETYPES diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py index 64e197eba..dbea84327 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -27,7 +27,7 @@ import re from shutil import which from subprocess import check_output, CalledProcessError, STDOUT -from openlp.core.utils import AppLocation +from openlp.core.common import AppLocation from openlp.core.common import Settings, is_win, trace_error_handler from openlp.core.lib import ScreenList from .presentationcontroller import PresentationController, PresentationDocument diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index aba0aa88e..c5e1b351f 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -20,7 +20,6 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import logging import os import logging import zipfile @@ -34,7 +33,7 @@ if is_win(): from ctypes import cdll from ctypes.wintypes import RECT -from openlp.core.utils import AppLocation +from openlp.core.common import AppLocation from openlp.core.lib import ScreenList from .presentationcontroller import PresentationController, PresentationDocument diff --git a/openlp/plugins/remotes/html/jquery.js b/openlp/plugins/remotes/html/assets/jquery.js similarity index 100% rename from openlp/plugins/remotes/html/jquery.js rename to openlp/plugins/remotes/html/assets/jquery.js diff --git a/openlp/plugins/remotes/html/jquery.min.js b/openlp/plugins/remotes/html/assets/jquery.min.js similarity index 100% rename from openlp/plugins/remotes/html/jquery.min.js rename to openlp/plugins/remotes/html/assets/jquery.min.js diff --git a/openlp/plugins/remotes/html/jquery.mobile.js b/openlp/plugins/remotes/html/assets/jquery.mobile.js similarity index 99% rename from openlp/plugins/remotes/html/jquery.mobile.js rename to openlp/plugins/remotes/html/assets/jquery.mobile.js index c5b71fa15..5cc32659b 100644 --- a/openlp/plugins/remotes/html/jquery.mobile.js +++ b/openlp/plugins/remotes/html/assets/jquery.mobile.js @@ -12,7 +12,7 @@ (function ( root, doc, factory ) { if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. - define( [ "jquery" ], function ( $ ) { + define( [ "jquery" ], function ($ ) { factory( $, root, doc ); return $.mobile; }); diff --git a/openlp/plugins/remotes/html/assets/jquery.mobile.min.css b/openlp/plugins/remotes/html/assets/jquery.mobile.min.css new file mode 100644 index 000000000..33b269a65 --- /dev/null +++ b/openlp/plugins/remotes/html/assets/jquery.mobile.min.css @@ -0,0 +1,2 @@ +/*! jQuery Mobile vGit Build: SHA1: 27e3c18acfebab2d47ee7ed37bd50fc4942c8838 <> Date: Fri Mar 22 08:50:04 2013 -0600 jquerymobile.com | jquery.org/license !*/ +.ui-bar-a{border:1px solid #333;background:#111;color:#fff;font-weight:bold;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from( #3c3c3c ),to( #111 ));background-image:-webkit-linear-gradient( #3c3c3c,#111 );background-image:-moz-linear-gradient( #3c3c3c,#111 );background-image:-ms-linear-gradient( #3c3c3c,#111 );background-image:-o-linear-gradient( #3c3c3c,#111 );background-image:linear-gradient( #3c3c3c,#111 )}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{font-family:Helvetica,Arial,sans-serif}.ui-bar-a .ui-link-inherit{color:#fff}.ui-bar-a a.ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-a a.ui-link:visited{color:#2489ce}.ui-bar-a a.ui-link:hover{color:#2489ce}.ui-bar-a a.ui-link:active{color:#2489ce}.ui-body-a,.ui-overlay-a{border:1px solid #444;background:#222;color:#fff;text-shadow:0 1px 1px #111;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from( #444 ),to( #222 ));background-image:-webkit-linear-gradient( #444,#222 );background-image:-moz-linear-gradient( #444,#222 );background-image:-ms-linear-gradient( #444,#222 );background-image:-o-linear-gradient( #444,#222 );background-image:linear-gradient( #444,#222 )}.ui-overlay-a{background-image:none;border-width:0}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{font-family:Helvetica,Arial,sans-serif}.ui-body-a .ui-link-inherit{color:#fff}.ui-body-a .ui-link{color:#2489ce;font-weight:bold}.ui-body-a .ui-link:visited{color:#2489ce}.ui-body-a .ui-link:hover{color:#2489ce}.ui-body-a .ui-link:active{color:#2489ce}.ui-btn-up-a{border:1px solid #111;background:#333;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from( #444 ),to( #2d2d2d ));background-image:-webkit-linear-gradient( #444,#2d2d2d );background-image:-moz-linear-gradient( #444,#2d2d2d );background-image:-ms-linear-gradient( #444,#2d2d2d );background-image:-o-linear-gradient( #444,#2d2d2d );background-image:linear-gradient( #444,#2d2d2d )}.ui-btn-up-a:visited,.ui-btn-up-a a.ui-link-inherit{color:#fff}.ui-btn-hover-a{border:1px solid #000;background:#444;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from( #555 ),to( #383838 ));background-image:-webkit-linear-gradient( #555,#383838 );background-image:-moz-linear-gradient( #555,#383838 );background-image:-ms-linear-gradient( #555,#383838 );background-image:-o-linear-gradient( #555,#383838 );background-image:linear-gradient( #555,#383838 )}.ui-btn-hover-a:visited,.ui-btn-hover-a:hover,.ui-btn-hover-a a.ui-link-inherit{color:#fff}.ui-btn-down-a{border:1px solid #000;background:#222;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from( #202020 ),to( #2c2c2c ));background-image:-webkit-linear-gradient( #202020,#2c2c2c );background-image:-moz-linear-gradient( #202020,#2c2c2c );background-image:-ms-linear-gradient( #202020,#2c2c2c );background-image:-o-linear-gradient( #202020,#2c2c2c );background-image:linear-gradient( #202020,#2c2c2c )}.ui-btn-down-a:visited,.ui-btn-down-a:hover,.ui-btn-down-a a.ui-link-inherit{color:#fff}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-b{border:1px solid #456f9a;background:#5e87b0;color:#fff;font-weight:bold;text-shadow:0 1px 1px #3e6790;background-image:-webkit-gradient(linear,left top,left bottom,from( #6facd5 ),to( #497bae ));background-image:-webkit-linear-gradient( #6facd5,#497bae );background-image:-moz-linear-gradient( #6facd5,#497bae );background-image:-ms-linear-gradient( #6facd5,#497bae );background-image:-o-linear-gradient( #6facd5,#497bae );background-image:linear-gradient( #6facd5,#497bae )}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{font-family:Helvetica,Arial,sans-serif}.ui-bar-b .ui-link-inherit{color:#fff}.ui-bar-b a.ui-link{color:#ddf0f8;font-weight:bold}.ui-bar-b a.ui-link:visited{color:#ddf0f8}.ui-bar-b a.ui-link:hover{color:#ddf0f8}.ui-bar-b a.ui-link:active{color:#ddf0f8}.ui-body-b,.ui-overlay-b{border:1px solid #999;background:#f3f3f3;color:#222;text-shadow:0 1px 0 #fff;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from( #ddd ),to( #ccc ));background-image:-webkit-linear-gradient( #ddd,#ccc );background-image:-moz-linear-gradient( #ddd,#ccc );background-image:-ms-linear-gradient( #ddd,#ccc );background-image:-o-linear-gradient( #ddd,#ccc );background-image:linear-gradient( #ddd,#ccc )}.ui-overlay-b{background-image:none;border-width:0}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{font-family:Helvetica,Arial,sans-serif}.ui-body-b .ui-link-inherit{color:#333}.ui-body-b .ui-link{color:#2489ce;font-weight:bold}.ui-body-b .ui-link:visited{color:#2489ce}.ui-body-b .ui-link:hover{color:#2489ce}.ui-body-b .ui-link:active{color:#2489ce}.ui-btn-up-b{border:1px solid #044062;background:#396b9e;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from( #5f9cc5 ),to( #396b9e ));background-image:-webkit-linear-gradient( #5f9cc5,#396b9e );background-image:-moz-linear-gradient( #5f9cc5,#396b9e );background-image:-ms-linear-gradient( #5f9cc5,#396b9e );background-image:-o-linear-gradient( #5f9cc5,#396b9e );background-image:linear-gradient( #5f9cc5,#396b9e )}.ui-btn-up-b:visited,.ui-btn-up-b a.ui-link-inherit{color:#fff}.ui-btn-hover-b{border:1px solid #00415e;background:#4b88b6;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from( #6facd5 ),to( #4272a4 ));background-image:-webkit-linear-gradient( #6facd5,#4272a4 );background-image:-moz-linear-gradient( #6facd5,#4272a4 );background-image:-ms-linear-gradient( #6facd5,#4272a4 );background-image:-o-linear-gradient( #6facd5,#4272a4 );background-image:linear-gradient( #6facd5,#4272a4 )}.ui-btn-hover-b:visited,.ui-btn-hover-b:hover,.ui-btn-hover-b a.ui-link-inherit{color:#fff}.ui-btn-down-b{border:1px solid #225377;background:#4e89c5;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from( #295b8e ),to( #3e79b5 ));background-image:-webkit-linear-gradient( #295b8e,#3e79b5 );background-image:-moz-linear-gradient( #295b8e,#3e79b5 );background-image:-ms-linear-gradient( #295b8e,#3e79b5 );background-image:-o-linear-gradient( #295b8e,#3e79b5 );background-image:linear-gradient( #295b8e,#3e79b5 )}.ui-btn-down-b:visited,.ui-btn-down-b:hover,.ui-btn-down-b a.ui-link-inherit{color:#fff}.ui-btn-up-b,.ui-btn-hover-b,.ui-btn-down-b{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-c{border:1px solid #b3b3b3;background:#eee;color:#3e3e3e;font-weight:bold;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #f0f0f0 ),to( #ddd ));background-image:-webkit-linear-gradient( #f0f0f0,#ddd );background-image:-moz-linear-gradient( #f0f0f0,#ddd );background-image:-ms-linear-gradient( #f0f0f0,#ddd );background-image:-o-linear-gradient( #f0f0f0,#ddd );background-image:linear-gradient( #f0f0f0,#ddd )}.ui-bar-c .ui-link-inherit{color:#3e3e3e}.ui-bar-c a.ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-c a.ui-link:visited{color:#2489ce}.ui-bar-c a.ui-link:hover{color:#2489ce}.ui-bar-c a.ui-link:active{color:#2489ce}.ui-bar-c,.ui-bar-c input,.ui-bar-c select,.ui-bar-c textarea,.ui-bar-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c,.ui-overlay-c{border:1px solid #aaa;color:#333;text-shadow:0 1px 0 #fff;background:#f9f9f9;background-image:-webkit-gradient(linear,left top,left bottom,from( #f9f9f9 ),to( #eee ));background-image:-webkit-linear-gradient( #f9f9f9,#eee );background-image:-moz-linear-gradient( #f9f9f9,#eee );background-image:-ms-linear-gradient( #f9f9f9,#eee );background-image:-o-linear-gradient( #f9f9f9,#eee );background-image:linear-gradient( #f9f9f9,#eee )}.ui-overlay-c{background-image:none;border-width:0}.ui-body-c,.ui-body-c input,.ui-body-c select,.ui-body-c textarea,.ui-body-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c .ui-link-inherit{color:#333}.ui-body-c .ui-link{color:#2489ce;font-weight:bold}.ui-body-c .ui-link:visited{color:#2489ce}.ui-body-c .ui-link:hover{color:#2489ce}.ui-body-c .ui-link:active{color:#2489ce}.ui-btn-up-c{border:1px solid #ccc;background:#eee;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #fff ),to( #f1f1f1 ));background-image:-webkit-linear-gradient( #fff,#f1f1f1 );background-image:-moz-linear-gradient( #fff,#f1f1f1 );background-image:-ms-linear-gradient( #fff,#f1f1f1 );background-image:-o-linear-gradient( #fff,#f1f1f1 );background-image:linear-gradient( #fff,#f1f1f1 )}.ui-btn-up-c:visited,.ui-btn-up-c a.ui-link-inherit{color:#2f3e46}.ui-btn-hover-c{border:1px solid #bbb;background:#dfdfdf;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #f6f6f6 ),to( #e0e0e0 ));background-image:-webkit-linear-gradient( #f6f6f6,#e0e0e0 );background-image:-moz-linear-gradient( #f6f6f6,#e0e0e0 );background-image:-ms-linear-gradient( #f6f6f6,#e0e0e0 );background-image:-o-linear-gradient( #f6f6f6,#e0e0e0 );background-image:linear-gradient( #f6f6f6,#e0e0e0 )}.ui-btn-hover-c:visited,.ui-btn-hover-c:hover,.ui-btn-hover-c a.ui-link-inherit{color:#2f3e46}.ui-btn-down-c{border:1px solid #bbb;background:#d6d6d6;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #d0d0d0 ),to( #dfdfdf ));background-image:-webkit-linear-gradient( #d0d0d0,#dfdfdf );background-image:-moz-linear-gradient( #d0d0d0,#dfdfdf );background-image:-ms-linear-gradient( #d0d0d0,#dfdfdf );background-image:-o-linear-gradient( #d0d0d0,#dfdfdf );background-image:linear-gradient( #d0d0d0,#dfdfdf )}.ui-btn-down-c:visited,.ui-btn-down-c:hover,.ui-btn-down-c a.ui-link-inherit{color:#2f3e46}.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-d{border:1px solid #bbb;background:#bbb;color:#333;font-weight:bold;text-shadow:0 1px 0 #eee;background-image:-webkit-gradient(linear,left top,left bottom,from( #ddd ),to( #bbb ));background-image:-webkit-linear-gradient( #ddd,#bbb );background-image:-moz-linear-gradient( #ddd,#bbb );background-image:-ms-linear-gradient( #ddd,#bbb );background-image:-o-linear-gradient( #ddd,#bbb );background-image:linear-gradient( #ddd,#bbb )}.ui-bar-d,.ui-bar-d input,.ui-bar-d select,.ui-bar-d textarea,.ui-bar-d button{font-family:Helvetica,Arial,sans-serif}.ui-bar-d .ui-link-inherit{color:#333}.ui-bar-d a.ui-link{color:#2489ce;font-weight:bold}.ui-bar-d a.ui-link:visited{color:#2489ce}.ui-bar-d a.ui-link:hover{color:#2489ce}.ui-bar-d a.ui-link:active{color:#2489ce}.ui-body-d,.ui-overlay-d{border:1px solid #bbb;color:#333;text-shadow:0 1px 0 #fff;background:#fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #fff ),to( #fff ));background-image:-webkit-linear-gradient( #fff,#fff );background-image:-moz-linear-gradient( #fff,#fff );background-image:-ms-linear-gradient( #fff,#fff );background-image:-o-linear-gradient( #fff,#fff );background-image:linear-gradient( #fff,#fff )}.ui-overlay-d{background-image:none;border-width:0}.ui-body-d,.ui-body-d input,.ui-body-d select,.ui-body-d textarea,.ui-body-d button{font-family:Helvetica,Arial,sans-serif}.ui-body-d .ui-link-inherit{color:#333}.ui-body-d .ui-link{color:#2489ce;font-weight:bold}.ui-body-d .ui-link:visited{color:#2489ce}.ui-body-d .ui-link:hover{color:#2489ce}.ui-body-d .ui-link:active{color:#2489ce}.ui-btn-up-d{border:1px solid #bbb;background:#fff;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #fafafa ),to( #f6f6f6 ));background-image:-webkit-linear-gradient( #fafafa,#f6f6f6 );background-image:-moz-linear-gradient( #fafafa,#f6f6f6 );background-image:-ms-linear-gradient( #fafafa,#f6f6f6 );background-image:-o-linear-gradient( #fafafa,#f6f6f6 );background-image:linear-gradient( #fafafa,#f6f6f6 )}.ui-btn-up-d:visited,.ui-btn-up-d a.ui-link-inherit{color:#333}.ui-btn-hover-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;cursor:pointer;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #eee ),to( #fff ));background-image:-webkit-linear-gradient( #eee,#fff );background-image:-moz-linear-gradient( #eee,#fff );background-image:-ms-linear-gradient( #eee,#fff );background-image:-o-linear-gradient( #eee,#fff );background-image:linear-gradient( #eee,#fff )}.ui-btn-hover-d:visited,.ui-btn-hover-d:hover,.ui-btn-hover-d a.ui-link-inherit{color:#333}.ui-btn-down-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #e5e5e5 ),to( #f2f2f2 ));background-image:-webkit-linear-gradient( #e5e5e5,#f2f2f2 );background-image:-moz-linear-gradient( #e5e5e5,#f2f2f2 );background-image:-ms-linear-gradient( #e5e5e5,#f2f2f2 );background-image:-o-linear-gradient( #e5e5e5,#f2f2f2 );background-image:linear-gradient( #e5e5e5,#f2f2f2 )}.ui-btn-down-d:visited,.ui-btn-down-d:hover,.ui-btn-down-d a.ui-link-inherit{color:#333}.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-e{border:1px solid #f7c942;background:#fadb4e;color:#333;font-weight:bold;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #fceda7 ),to( #fbef7e ));background-image:-webkit-linear-gradient( #fceda7,#fbef7e );background-image:-moz-linear-gradient( #fceda7,#fbef7e );background-image:-ms-linear-gradient( #fceda7,#fbef7e );background-image:-o-linear-gradient( #fceda7,#fbef7e );background-image:linear-gradient( #fceda7,#fbef7e )}.ui-bar-e,.ui-bar-e input,.ui-bar-e select,.ui-bar-e textarea,.ui-bar-e button{font-family:Helvetica,Arial,sans-serif}.ui-bar-e .ui-link-inherit{color:#333}.ui-bar-e a.ui-link{color:#2489ce;font-weight:bold}.ui-bar-e a.ui-link:visited{color:#2489ce}.ui-bar-e a.ui-link:hover{color:#2489ce}.ui-bar-e a.ui-link:active{color:#2489ce}.ui-body-e,.ui-overlay-e{border:1px solid #f7c942;color:#222;text-shadow:0 1px 0 #fff;background:#fff9df;background-image:-webkit-gradient(linear,left top,left bottom,from( #fffadf ),to( #fff3a5 ));background-image:-webkit-linear-gradient( #fffadf,#fff3a5 );background-image:-moz-linear-gradient( #fffadf,#fff3a5 );background-image:-ms-linear-gradient( #fffadf,#fff3a5 );background-image:-o-linear-gradient( #fffadf,#fff3a5 );background-image:linear-gradient( #fffadf,#fff3a5 )}.ui-overlay-e{background-image:none;border-width:0}.ui-body-e,.ui-body-e input,.ui-body-e select,.ui-body-e textarea,.ui-body-e button{font-family:Helvetica,Arial,sans-serif}.ui-body-e .ui-link-inherit{color:#222}.ui-body-e .ui-link{color:#2489ce;font-weight:bold}.ui-body-e .ui-link:visited{color:#2489ce}.ui-body-e .ui-link:hover{color:#2489ce}.ui-body-e .ui-link:active{color:#2489ce}.ui-btn-up-e{border:1px solid #f4c63f;background:#fadb4e;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #ffefaa ),to( #ffe155 ));background-image:-webkit-linear-gradient( #ffefaa,#ffe155 );background-image:-moz-linear-gradient( #ffefaa,#ffe155 );background-image:-ms-linear-gradient( #ffefaa,#ffe155 );background-image:-o-linear-gradient( #ffefaa,#ffe155 );background-image:linear-gradient( #ffefaa,#ffe155 )}.ui-btn-up-e:visited,.ui-btn-up-e a.ui-link-inherit{color:#222}.ui-btn-hover-e{border:1px solid #f2c43d;background:#fbe26f;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #fff5ba ),to( #fbdd52 ));background-image:-webkit-linear-gradient( #fff5ba,#fbdd52 );background-image:-moz-linear-gradient( #fff5ba,#fbdd52 );background-image:-ms-linear-gradient( #fff5ba,#fbdd52 );background-image:-o-linear-gradient( #fff5ba,#fbdd52 );background-image:linear-gradient( #fff5ba,#fbdd52 )}.ui-btn-hover-e:visited,.ui-btn-hover-e:hover,.ui-btn-hover-e a.ui-link-inherit{color:#333}.ui-btn-down-e{border:1px solid #f2c43d;background:#fceda7;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from( #f8d94c ),to( #fadb4e ));background-image:-webkit-linear-gradient( #f8d94c,#fadb4e );background-image:-moz-linear-gradient( #f8d94c,#fadb4e );background-image:-ms-linear-gradient( #f8d94c,#fadb4e );background-image:-o-linear-gradient( #f8d94c,#fadb4e );background-image:linear-gradient( #f8d94c,#fadb4e )}.ui-btn-down-e:visited,.ui-btn-down-e:hover,.ui-btn-down-e a.ui-link-inherit{color:#333}.ui-btn-up-e,.ui-btn-hover-e,.ui-btn-down-e{font-family:Helvetica,Arial,sans-serif;text-decoration:none}a.ui-link-inherit{text-decoration:none!important}.ui-btn-active{border:1px solid #2373a5;background:#5393c5;font-weight:bold;color:#fff;cursor:pointer;text-shadow:0 1px 1px #3373a5;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from( #5393c5 ),to( #6facd5 ));background-image:-webkit-linear-gradient( #5393c5,#6facd5 );background-image:-moz-linear-gradient( #5393c5,#6facd5 );background-image:-ms-linear-gradient( #5393c5,#6facd5 );background-image:-o-linear-gradient( #5393c5,#6facd5 );background-image:linear-gradient( #5393c5,#6facd5 );font-family:Helvetica,Arial,sans-serif}.ui-btn-active:visited,.ui-btn-active:hover,.ui-btn-active a.ui-link-inherit{color:#fff}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3)}.ui-corner-tl{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em}.ui-corner-tr{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bl{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-br{-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-top{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bottom{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-right{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-left{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-all{-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.ui-corner-none{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.ui-br{border-bottom:rgb(130,130,130);border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid}.ui-disabled{filter:Alpha(Opacity=30);opacity:.3;zoom:1}.ui-disabled,.ui-disabled a{cursor:default!important;pointer-events:none}.ui-icon,.ui-icon-searchfield:after{background:#666;background:rgba(0,0,0,.4);background-image:url(../images/icons-18-white.png);background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px} .ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(../images/icons-18-black.png);background-repeat:no-repeat}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(../images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px} .ui-icon-alt{background-image:url(../images/icons-36-black.png)}} .ui-icon-plus{background-position:-0 50%} .ui-icon-minus{background-position:-36px 50%} .ui-icon-delete{background-position:-72px 50%} .ui-icon-arrow-r{background-position:-108px 50%} .ui-icon-arrow-l{background-position:-144px 50%} .ui-icon-arrow-u{background-position:-180px 50%} .ui-icon-arrow-d{background-position:-216px 50%} .ui-icon-check{background-position:-252px 50%} .ui-icon-gear{background-position:-288px 50%} .ui-icon-refresh{background-position:-324px 50%} .ui-icon-forward{background-position:-360px 50%} .ui-icon-back{background-position:-396px 50%} .ui-icon-grid{background-position:-432px 50%} .ui-icon-star{background-position:-468px 50%} .ui-icon-alert{background-position:-504px 50%} .ui-icon-info{background-position:-540px 50%} .ui-icon-home{background-position:-576px 50%} .ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%} .ui-icon-checkbox-off{background-position:-684px 50%} .ui-icon-checkbox-on{background-position:-648px 50%} .ui-icon-radio-off{background-position:-756px 50%} .ui-icon-radio-on{background-position:-720px 50%} .ui-checkbox .ui-icon,.ui-selectmenu-list .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px} .ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent} .ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#4596ce} .ui-icon-loading{background:url(../images/ajax-loader.gif);background-size:46px 46px} .ui-btn-corner-tl{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em} .ui-btn-corner-tr{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em} .ui-btn-corner-bl{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em} .ui-btn-corner-br{-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em} .ui-btn-corner-top{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em} .ui-btn-corner-bottom{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em} .ui-btn-corner-right{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em} .ui-btn-corner-left{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em} .ui-btn-corner-all{-moz-border-radius:1em;-webkit-border-radius:1em;border-radius:1em} .ui-corner-tl,.ui-corner-tr,.ui-corner-bl,.ui-corner-br,.ui-corner-top,.ui-corner-bottom,.ui-corner-right,.ui-corner-left,.ui-corner-all,.ui-btn-corner-tl,.ui-btn-corner-tr,.ui-btn-corner-bl,.ui-btn-corner-br,.ui-btn-corner-top,.ui-btn-corner-bottom,.ui-btn-corner-right,.ui-btn-corner-left,.ui-btn-corner-all{-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box} .ui-overlay{background:#666;filter:Alpha(Opacity=50);opacity:.5;position:absolute;width:100%;height:100%} .ui-overlay-shadow{-moz-box-shadow:0 0 12px rgba(0,0,0,.6);-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)} .ui-shadow{-moz-box-shadow:0 1px 4px rgba(0,0,0,.3);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3);box-shadow:0 1px 4px rgba(0,0,0,.3)} .ui-bar-a .ui-shadow,.ui-bar-b .ui-shadow,.ui-bar-c .ui-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)} .ui-shadow-inset{-moz-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);box-shadow:inset 0 1px 4px rgba(0,0,0,.2)} .ui-icon-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.4);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.4);box-shadow:0 1px 0 rgba(255,255,255,.4)} .ui-btn:focus,.ui-link-inherit:focus{outline:0} .ui-btn.ui-focus{z-index:1} .ui-focus,.ui-btn:focus{-moz-box-shadow:inset 0 0 3px #387bbe,0px 0 9px #387bbe;-webkit-box-shadow:inset 0 0 3px #387bbe,0px 0 9px #387bbe;box-shadow:inset 0 0 3px #387bbe,0px 0 9px #387bbe} .ui-input-text.ui-focus,.ui-input-search.ui-focus{-moz-box-shadow:0 0 12px #387bbe;-webkit-box-shadow:0 0 12px #387bbe;box-shadow:0 0 12px #387bbe} .ui-mobile-nosupport-boxshadow *{-moz-box-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important} .ui-mobile-nosupport-boxshadow .ui-focus,.ui-mobile-nosupport-boxshadow .ui-btn:focus,.ui-mobile-nosupport-boxshadow .ui-link-inherit:focus{outline-width:1px;outline-style:auto} .ui-mobile,.ui-mobile body{height:99.9%} .ui-mobile fieldset,.ui-page{padding:0;margin:0} .ui-mobile a img,.ui-mobile fieldset{border-width:0} .ui-mobile-viewport{margin:0;overflow-x:visible;-webkit-text-size-adjust:100%;-ms-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)} body.ui-mobile-viewport,div.ui-mobile-viewport{overflow-x:hidden} .ui-mobile [data-role=page],.ui-mobile [data-role=dialog],.ui-page{top:0;left:0;width:100%;min-height:100%;position:absolute;display:none;border:0} .ui-mobile .ui-page-active{display:block;overflow:visible} .ui-page{outline:none}@media screen and (orientation:portrait){.ui-mobile,.ui-mobile .ui-page{min-height:420px}}@media screen and (orientation:landscape){.ui-mobile,.ui-mobile .ui-page{min-height:300px}} .ui-loading .ui-loader{display:block} .ui-loader{display:none;z-index:9999999;position:fixed;top:50%;left:50%;border:0} .ui-loader-default{background:none;filter:Alpha(Opacity=18);opacity:.18;width:46px;height:46px;margin-left:-23px;margin-top:-23px} .ui-loader-verbose{width:200px;filter:Alpha(Opacity=88);opacity:.88;box-shadow:0 1px 1px -1px #fff;height:auto;margin-left:-110px;margin-top:-43px;padding:10px} .ui-loader-default h1{font-size:0;width:0;height:0;overflow:hidden} .ui-loader-verbose h1{font-size:16px;margin:0;text-align:center} .ui-loader .ui-icon{background-color:#000;display:block;margin:0;width:44px;height:44px;padding:1px;-webkit-border-radius:36px;-moz-border-radius:36px;border-radius:36px} .ui-loader-verbose .ui-icon{margin:0 auto 10px;filter:Alpha(Opacity=75);opacity:.75} .ui-loader-textonly{padding:15px;margin-left:-115px} .ui-loader-textonly .ui-icon{display:none} .ui-loader-fakefix{position:absolute} .ui-mobile-rendering > *{visibility:hidden} .ui-bar,.ui-body{position:relative;padding:.4em 15px;overflow:hidden;display:block;clear:both} .ui-bar{font-size:16px;margin:0} .ui-bar h1,.ui-bar h2,.ui-bar h3,.ui-bar h4,.ui-bar h5,.ui-bar h6{margin:0;padding:0;font-size:16px;display:inline-block} .ui-header,.ui-footer{position:relative;zoom:1} .ui-mobile .ui-header,.ui-mobile .ui-footer{border-left-width:0;border-right-width:0} .ui-header .ui-btn-left,.ui-header .ui-btn-right,.ui-footer .ui-btn-left,.ui-footer .ui-btn-right{position:absolute;top:3px} .ui-header .ui-btn-left,.ui-footer .ui-btn-left{left:5px} .ui-header .ui-btn-right,.ui-footer .ui-btn-right{right:5px} .ui-footer .ui-btn-icon-notext,.ui-header .ui-btn-icon-notext{top:6px} .ui-header .ui-title,.ui-footer .ui-title{min-height:1.1em;text-align:center;font-size:16px;display:block;margin:.6em 30% .8em;padding:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;outline:0!important} .ui-footer .ui-title{margin:.6em 15px .8em} .ui-content{border-width:0;overflow:visible;overflow-x:hidden;padding:15px} .ui-icon{width:18px;height:18px} .ui-nojs{position:absolute;left:-9999px} .ui-hide-label label.ui-input-text,.ui-hide-label label.ui-select,.ui-hide-label label.ui-slider,.ui-hide-label label.ui-submit,.ui-hide-label .ui-controlgroup-label,.ui-hidden-accessible{position:absolute!important;left:-9999px;clip:rect(1px);clip:rect(1px,1px,1px,1px)} .ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} .ui-page-pre-in{opacity:0} .in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms} .out{-webkit-animation-timing-function:ease-in;-webkit-animation-duration:225ms;-moz-animation-timing-function:ease-in;-moz-animation-duration:225ms} @-webkit-keyframes fadein{from{opacity:0}to{opacity:1}} @-moz-keyframes fadein{from{opacity:0}to{opacity:1}} @-webkit-keyframes fadeout{from{opacity:1}to{opacity:0}} @-moz-keyframes fadeout{from{opacity:1}to{opacity:0}} .fade.out{opacity:0;-webkit-animation-duration:125ms;-webkit-animation-name:fadeout;-moz-animation-duration:125ms;-moz-animation-name:fadeout} .fade.in{opacity:1;-webkit-animation-duration:225ms;-webkit-animation-name:fadein;-moz-animation-duration:225ms;-moz-animation-name:fadein} .pop{-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%} .pop.in{-webkit-transform:scale(1);-moz-transform:scale(1);opacity:1;-webkit-animation-name:popin;-moz-animation-name:popin;-webkit-animation-duration:350ms;-moz-animation-duration:350ms} .pop.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;opacity:0;-webkit-animation-duration:100ms;-moz-animation-duration:100ms} .pop.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein} .pop.out.reverse{-webkit-transform:scale(.8);-moz-transform:scale(.8);-webkit-animation-name:popout;-moz-animation-name:popout} @-webkit-keyframes popin{from{-webkit-transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);opacity:1}} @-moz-keyframes popin{from{-moz-transform:scale(.8);opacity:0}to{-moz-transform:scale(1);opacity:1}} @-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}} @-moz-keyframes popout{from{-moz-transform:scale(1);opacity:1}to{-moz-transform:scale(.8);opacity:0}} @-webkit-keyframes slideinfromright{from{-webkit-transform:translateX(100%)}to{-webkit-transform:translateX(0)}} @-moz-keyframes slideinfromright{from{-moz-transform:translateX(100%)}to{-moz-transform:translateX(0)}} @-webkit-keyframes slideinfromleft{from{-webkit-transform:translateX(-100%)}to{-webkit-transform:translateX(0)}} @-moz-keyframes slideinfromleft{from{-moz-transform:translateX(-100%)}to{-moz-transform:translateX(0)}} @-webkit-keyframes slideouttoleft{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(-100%)}} @-moz-keyframes slideouttoleft{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(-100%)}} @-webkit-keyframes slideouttoright{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(100%)}} @-moz-keyframes slideouttoright{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(100%)}} .slide.out,.slide.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms} .slide.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft} .slide.in{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromright;-moz-transform:translateX(0);-moz-animation-name:slideinfromright} .slide.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright} .slide.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromleft;-moz-transform:translateX(0);-moz-animation-name:slideinfromleft} .slidefade.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;-webkit-animation-duration:225ms;-moz-animation-duration:225ms} .slidefade.in{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms} .slidefade.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;-webkit-animation-duration:200ms;-moz-animation-duration:200ms} .slidefade.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms} .slidedown.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms} .slidedown.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfromtop;-moz-transform:translateY(0);-moz-animation-name:slideinfromtop;-webkit-animation-duration:250ms;-moz-animation-duration:250ms} .slidedown.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms} .slidedown.out.reverse{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-webkit-animation-name:slideouttotop;-moz-animation-name:slideouttotop;-webkit-animation-duration:200ms;-moz-animation-duration:200ms} @-webkit-keyframes slideinfromtop{from{-webkit-transform:translateY(-100%)}to{-webkit-transform:translateY(0)}} @-moz-keyframes slideinfromtop{from{-moz-transform:translateY(-100%)}to{-moz-transform:translateY(0)}} @-webkit-keyframes slideouttotop{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(-100%)}} @-moz-keyframes slideouttotop{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(-100%)}} .slideup.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms} .slideup.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfrombottom;-moz-transform:translateY(0);-moz-animation-name:slideinfrombottom;-webkit-animation-duration:250ms;-moz-animation-duration:250ms} .slideup.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms} .slideup.out.reverse{-webkit-transform:translateY(100%);-moz-transform:translateY(100%);-webkit-animation-name:slideouttobottom;-moz-animation-name:slideouttobottom;-webkit-animation-duration:200ms;-moz-animation-duration:200ms} @-webkit-keyframes slideinfrombottom{from{-webkit-transform:translateY(100%)}to{-webkit-transform:translateY(0)}} @-moz-keyframes slideinfrombottom{from{-moz-transform:translateY(100%)}to{-moz-transform:translateY(0)}} @-webkit-keyframes slideouttobottom{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(100%)}} @-moz-keyframes slideouttobottom{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(100%)}} .viewport-flip{-webkit-perspective:1000;-moz-perspective:1000;position:absolute} .flip{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-moz-backface-visibility:hidden;-moz-transform:translateX(0)} .flip.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:175ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:175ms} .flip.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:225ms;-moz-animation-name:flipintoright;-moz-animation-duration:225ms} .flip.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright} .flip.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft} @-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}} @-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}} @-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}} @-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}} @-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}} @-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}} @-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}} @-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}} .viewport-turn{-webkit-perspective:1000;-moz-perspective:1000;position:absolute} .turn{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-webkit-transform-origin:0;-moz-backface-visibility:hidden;-moz-transform:translateX(0);-moz-transform-origin:0} .turn.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-webkit-animation-duration:125ms;-moz-animation-duration:125ms} .turn.in{-webkit-animation-name:flipintoright;-moz-animation-name:flipintoright;-webkit-animation-duration:250ms;-moz-animation-duration:250ms} .turn.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright} .turn.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft} @-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}} @-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}} @-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}} @-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}} @-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}} @-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}} @-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}} @-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}} .flow{-webkit-transform-origin:50% 30%;-moz-transform-origin:50% 30%;-webkit-box-shadow:0 0 20px rgba(0,0,0,.4);-moz-box-shadow:0 0 20px rgba(0,0,0,.4)} .ui-dialog.flow{-webkit-transform-origin:none;-moz-transform-origin:none;-webkit-box-shadow:none;-moz-box-shadow:none} .flow.out{-webkit-transform:translateX(-100%) scale(.7);-webkit-animation-name:flowouttoleft;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(-100%) scale(.7);-moz-animation-name:flowouttoleft;-moz-animation-timing-function:ease;-moz-animation-duration:350ms} .flow.in{-webkit-transform:translateX(0) scale(1);-webkit-animation-name:flowinfromright;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(0) scale(1);-moz-animation-name:flowinfromright;-moz-animation-timing-function:ease;-moz-animation-duration:350ms} .flow.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:flowouttoright;-moz-transform:translateX(100%);-moz-animation-name:flowouttoright} .flow.in.reverse{-webkit-animation-name:flowinfromleft;-moz-animation-name:flowinfromleft} @-webkit-keyframes flowouttoleft{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(-100%) scale(.7)}} @-moz-keyframes flowouttoleft{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(-100%) scale(.7)}} @-webkit-keyframes flowouttoright{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(100%) scale(.7)}} @-moz-keyframes flowouttoright{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(100%) scale(.7)}} @-webkit-keyframes flowinfromleft{0%{-webkit-transform:translateX(-100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}} @-moz-keyframes flowinfromleft{0%{-moz-transform:translateX(-100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}} @-webkit-keyframes flowinfromright{0%{-webkit-transform:translateX(100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}} @-moz-keyframes flowinfromright{0%{-moz-transform:translateX(100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}} .ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d{overflow:hidden} .ui-block-a,.ui-block-b,.ui-block-c,.ui-block-d,.ui-block-e{margin:0;padding:0;border:0;float:left;min-height:1px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box} .ui-grid-solo .ui-block-a{display:block;float:none} .ui-grid-a .ui-block-a,.ui-grid-a .ui-block-b{width:49.95%} .ui-grid-a >:nth-child(n){width:50%;margin-right:-.5px} .ui-grid-a .ui-block-a{clear:left} .ui-grid-b .ui-block-a,.ui-grid-b .ui-block-b,.ui-grid-b .ui-block-c{width:33.25%} .ui-grid-b >:nth-child(n){width:33.333%;margin-right:-.5px} .ui-grid-b .ui-block-a{clear:left} .ui-grid-c .ui-block-a,.ui-grid-c .ui-block-b,.ui-grid-c .ui-block-c,.ui-grid-c .ui-block-d{width:24.925%} .ui-grid-c >:nth-child(n){width:25%;margin-right:-.5px} .ui-grid-c .ui-block-a{clear:left} .ui-grid-d .ui-block-a,.ui-grid-d .ui-block-b,.ui-grid-d .ui-block-c,.ui-grid-d .ui-block-d,.ui-grid-d .ui-block-e{width:19.925%} .ui-grid-d >:nth-child(n){width:20%} .ui-grid-d .ui-block-a{clear:left} .ui-header-fixed,.ui-footer-fixed{left:0;right:0;width:100%;position:fixed;z-index:1000} .ui-header-fixed{top:0} .ui-footer-fixed{bottom:0} .ui-header-fullscreen,.ui-footer-fullscreen{filter:Alpha(Opacity=90);opacity:.9} .ui-page-header-fixed{padding-top:2.6875em} .ui-page-footer-fixed{padding-bottom:2.6875em} .ui-page-header-fullscreen .ui-content,.ui-page-footer-fullscreen .ui-content{padding:0} .ui-fixed-hidden{position:absolute} .ui-page-header-fullscreen .ui-fixed-hidden,.ui-page-footer-fullscreen .ui-fixed-hidden{left:-9999px} .ui-header-fixed .ui-btn,.ui-footer-fixed .ui-btn{z-index:10} .ui-navbar{max-width:100%} .ui-navbar.ui-mini{margin:0} .ui-navbar ul:before,.ui-navbar ul:after{content:" ";display:table} .ui-navbar ul:after{clear:both} .ui-navbar ul{list-style:none;margin:0;padding:0;position:relative;display:block;border:0;max-width:100%;overflow:visible;zoom:1} .ui-navbar li .ui-btn{display:block;text-align:center;margin:0 -1px 0 0;border-right-width:0} .ui-navbar li .ui-btn-icon-right .ui-icon{right:6px} .ui-navbar li:last-child .ui-btn,.ui-navbar .ui-grid-duo .ui-block-b .ui-btn{margin-right:0;border-right-width:1px} .ui-header .ui-navbar li:last-child .ui-btn,.ui-footer .ui-navbar li:last-child .ui-btn,.ui-header .ui-navbar .ui-grid-duo .ui-block-b .ui-btn,.ui-footer .ui-navbar .ui-grid-duo .ui-block-b .ui-btn{margin-right:-1px;border-right-width:0} .ui-navbar .ui-grid-duo li.ui-block-a:last-child .ui-btn{margin-right:-1px;border-right-width:1px} .ui-header .ui-navbar li .ui-btn,.ui-footer .ui-navbar li .ui-btn{border-top-width:0;border-bottom-width:0} .ui-header .ui-navbar .ui-grid-b li.ui-block-c .ui-btn,.ui-footer .ui-navbar .ui-grid-b li.ui-block-c .ui-btn{margin-right:-5px} .ui-header .ui-navbar .ui-grid-c li.ui-block-d .ui-btn,.ui-footer .ui-navbar .ui-grid-c li.ui-block-d .ui-btn,.ui-header .ui-navbar .ui-grid-d li.ui-block-e .ui-btn,.ui-footer .ui-navbar .ui-grid-d li.ui-block-e .ui-btn{margin-right:-4px} .ui-header .ui-navbar .ui-grid-b li.ui-block-c .ui-btn-icon-right .ui-icon,.ui-footer .ui-navbar .ui-grid-b li.ui-block-c .ui-btn-icon-right .ui-icon,.ui-header .ui-navbar .ui-grid-c li.ui-block-d .ui-btn-icon-right .ui-icon,.ui-footer .ui-navbar .ui-grid-c li.ui-block-d .ui-btn-icon-right .ui-icon,.ui-header .ui-navbar .ui-grid-d li.ui-block-e .ui-btn-icon-right .ui-icon,.ui-footer .ui-navbar .ui-grid-d li.ui-block-e .ui-btn-icon-right .ui-icon{right:8px} .ui-navbar li .ui-btn .ui-btn-inner{padding-top:.7em;padding-bottom:.8em} .ui-navbar li .ui-btn-icon-top .ui-btn-inner{padding-top:30px} .ui-navbar li .ui-btn-icon-bottom .ui-btn-inner{padding-bottom:30px} .ui-btn{display:block;text-align:center;cursor:pointer;position:relative;margin:.5em 0;padding:0} .ui-mini{margin-top:.25em;margin-bottom:.25em} .ui-btn-left,.ui-btn-right,.ui-input-clear,.ui-btn-inline,.ui-grid-a .ui-btn,.ui-grid-b .ui-btn,.ui-grid-c .ui-btn,.ui-grid-d .ui-btn,.ui-grid-e .ui-btn,.ui-grid-solo .ui-btn{margin-right:5px;margin-left:5px} .ui-btn-inner{font-size:16px;padding:.6em 20px;min-width:.75em;display:block;position:relative;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;zoom:1} .ui-btn input,.ui-btn button{z-index:2} .ui-btn-left,.ui-btn-right,.ui-btn-inline{display:inline-block;vertical-align:middle} .ui-mobile .ui-btn-left,.ui-mobile .ui-btn-right{margin:0} .ui-btn-block{display:block} .ui-header > .ui-btn,.ui-footer > .ui-btn{display:inline-block;margin:0} .ui-header .ui-btn-block,.ui-footer .ui-btn-block{display:block} .ui-header .ui-btn-inner,.ui-footer .ui-btn-inner,.ui-mini .ui-btn-inner{font-size:12.5px;padding:.55em 11px .5em} .ui-fullsize .ui-btn-inner,.ui-fullsize .ui-btn-inner{font-size:16px;padding:.6em 20px} .ui-btn-icon-notext{width:24px;height:24px} .ui-btn-icon-notext .ui-btn-inner{padding:0;height:100%} .ui-btn-icon-notext .ui-btn-inner .ui-icon{margin:2px 1px 2px 3px;float:left} .ui-btn-text{position:relative;z-index:1;width:100%;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none} div.ui-btn-text{width:auto} .ui-btn-icon-notext .ui-btn-text{position:absolute;left:-9999px} .ui-btn-icon-left .ui-btn-inner{padding-left:40px} .ui-btn-icon-right .ui-btn-inner{padding-right:40px} .ui-btn-icon-top .ui-btn-inner{padding-top:40px} .ui-btn-icon-bottom .ui-btn-inner{padding-bottom:40px} .ui-header .ui-btn-icon-left .ui-btn-inner,.ui-footer .ui-btn-icon-left .ui-btn-inner,.ui-mini.ui-btn-icon-left .ui-btn-inner,.ui-mini .ui-btn-icon-left .ui-btn-inner{padding-left:30px} .ui-header .ui-btn-icon-right .ui-btn-inner,.ui-footer .ui-btn-icon-right .ui-btn-inner,.ui-mini.ui-btn-icon-right .ui-btn-inner,.ui-mini .ui-btn-icon-right .ui-btn-inner{padding-right:30px} .ui-header .ui-btn-icon-top .ui-btn-inner,.ui-footer .ui-btn-icon-top .ui-btn-inner{padding:30px 3px .5em 3px} .ui-mini.ui-btn-icon-top .ui-btn-inner,.ui-mini .ui-btn-icon-top .ui-btn-inner{padding-top:30px} .ui-header .ui-btn-icon-bottom .ui-btn-inner,.ui-footer .ui-btn-icon-bottom .ui-btn-inner{padding:.55em 3px 30px 3px} .ui-mini.ui-btn-icon-bottom .ui-btn-inner,.ui-mini .ui-btn-icon-bottom .ui-btn-inner{padding-bottom:30px} .ui-btn-icon-notext .ui-icon{display:block;z-index:0} .ui-btn-icon-left > .ui-btn-inner > .ui-icon,.ui-btn-icon-right > .ui-btn-inner > .ui-icon{position:absolute;top:50%;margin-top:-9px} .ui-btn-icon-top .ui-btn-inner .ui-icon,.ui-btn-icon-bottom .ui-btn-inner .ui-icon{position:absolute;left:50%;margin-left:-9px} .ui-btn-icon-left .ui-icon{left:10px} .ui-btn-icon-right .ui-icon{right:10px} .ui-btn-icon-top .ui-icon{top:10px} .ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px} .ui-header .ui-btn-icon-left .ui-icon,.ui-footer .ui-btn-icon-left .ui-icon,.ui-mini.ui-btn-icon-left .ui-icon,.ui-mini .ui-btn-icon-left .ui-icon{left:5px} .ui-header .ui-btn-icon-right .ui-icon,.ui-footer .ui-btn-icon-right .ui-icon,.ui-mini.ui-btn-icon-right .ui-icon,.ui-mini .ui-btn-icon-right .ui-icon{right:5px} .ui-header .ui-btn-icon-top .ui-icon,.ui-footer .ui-btn-icon-top .ui-icon,.ui-mini.ui-btn-icon-top .ui-icon,.ui-mini .ui-btn-icon-top .ui-icon{top:5px} .ui-header .ui-btn-icon-bottom .ui-icon,.ui-footer .ui-btn-icon-bottom .ui-icon,.ui-mini.ui-btn-icon-bottom .ui-icon,.ui-mini .ui-btn-icon-bottom .ui-icon{bottom:5px} .ui-btn-hidden{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-appearance:none;cursor:pointer;background:#fff;background:rgba(255,255,255,0);filter:Alpha(Opacity=0);opacity:.1;font-size:1px;border:none;text-indent:-9999px} .ui-disabled .ui-btn-hidden{display:none} .ui-disabled{z-index:1} .ui-field-contain .ui-btn.ui-submit{margin:0} label.ui-submit{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}@media all and (min-width:450px){.ui-field-contain label.ui-submit{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-btn.ui-submit{width:78%;display:inline-block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.ui-hide-label .ui-btn.ui-submit{width:auto;display:block}} .ui-collapsible-inset{margin:.5em 0} .ui-collapsible-heading{font-size:16px;display:block;margin:0 -15px;padding:0;position:relative} .ui-collapsible-inset .ui-collapsible-heading{margin:0} .ui-collapsible-heading .ui-btn{text-align:left;margin:0;border-left-width:0;border-right-width:0} .ui-collapsible-inset .ui-collapsible-heading .ui-btn{border-right-width:1px;border-left-width:1px} .ui-collapsible-collapsed + .ui-collapsible:not(.ui-collapsible-inset) .ui-collapsible-heading .ui-btn{border-top-width:0} .ui-collapsible-set .ui-collapsible:not(.ui-collapsible-inset) .ui-collapsible-heading .ui-btn{border-top-width:1px} .ui-collapsible-heading .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-left .ui-btn-inner{padding-left:40px} .ui-collapsible-heading .ui-btn-icon-right .ui-btn-inner{padding-left:12px;padding-right:40px} .ui-collapsible-heading .ui-btn-icon-top .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-bottom .ui-btn-inner{padding-right:40px;text-align:center} .ui-collapsible-heading .ui-btn span.ui-btn{position:absolute;left:6px;top:50%;margin:-12px 0 0 0;width:20px;height:20px;padding:1px 0 1px 2px;text-indent:-9999px} .ui-collapsible-heading .ui-btn span.ui-btn .ui-btn-inner{padding:10px 0} .ui-collapsible-heading .ui-btn span.ui-btn .ui-icon{left:0;margin-top:-10px} .ui-collapsible-heading-status{position:absolute;top:-9999px;left:0} .ui-collapsible-content{display:block;margin:0 -15px;padding:10px 15px;border-left-width:0;border-right-width:0;border-top:none;background-image:none} .ui-collapsible-inset .ui-collapsible-content{margin:0;border-right-width:1px;border-left-width:1px} .ui-collapsible-content-collapsed{display:none} .ui-collapsible-set{margin:.5em 0} .ui-collapsible-set .ui-collapsible{margin:-1px 0 0} .ui-collapsible-set .ui-collapsible:first-child{margin-top:0} .ui-controlgroup,fieldset.ui-controlgroup{padding:0;margin:.5em 0;zoom:1} .ui-controlgroup.ui-mini,fieldset.ui-controlgroup.ui-mini{margin:.25em 0} .ui-field-contain .ui-controlgroup,.ui-field-contain fieldset.ui-controlgroup{margin:0} .ui-bar .ui-controlgroup{margin:0 5px} .ui-controlgroup-label{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .4em} .ui-controlgroup li{list-style:none} .ui-controlgroup-vertical .ui-btn,.ui-controlgroup-vertical .ui-checkbox,.ui-controlgroup-vertical .ui-radio{margin:0;border-bottom-width:0} .ui-controlgroup-vertical .ui-controlgroup-last{border-bottom-width:1px} .ui-controlgroup-controls label.ui-select{position:absolute;left:-9999px} .ui-controlgroup .ui-btn-icon-notext{width:auto;height:auto;top:auto} .ui-controlgroup .ui-btn-icon-notext .ui-btn-inner{height:20px;padding:.6em 20px .6em 20px} .ui-controlgroup-horizontal .ui-btn-icon-notext .ui-btn-inner{width:18px} .ui-controlgroup.ui-mini .ui-btn-icon-notext .ui-btn-inner,.ui-header .ui-controlgroup .ui-btn-icon-notext .ui-btn-inner,.ui-footer .ui-controlgroup .ui-btn-icon-notext .ui-btn-inner{height:16px;padding:.55em 11px .5em 11px} .ui-controlgroup .ui-btn-icon-notext .ui-btn-inner .ui-icon{position:absolute;top:50%;right:50%;margin:-9px -9px 0 0} .ui-controlgroup-horizontal .ui-controlgroup-controls:before,.ui-controlgroup-horizontal .ui-controlgroup-controls:after{content:"";display:table} .ui-controlgroup-horizontal .ui-controlgroup-controls:after{clear:both} .ui-controlgroup-horizontal .ui-controlgroup-controls{display:inline-block;vertical-align:middle;zoom:1} .ui-controlgroup-horizontal .ui-btn-inner{text-align:center} .ui-controlgroup-horizontal.ui-mini .ui-btn-inner{height:16px;line-height:16px} .ui-controlgroup-horizontal .ui-btn,.ui-controlgroup-horizontal .ui-select,.ui-controlgroup-horizontal .ui-checkbox,.ui-controlgroup-horizontal .ui-radio{float:left;clear:none;margin:0 -1px 0 0} .ui-controlgroup-horizontal .ui-select .ui-btn,.ui-controlgroup-horizontal .ui-checkbox .ui-btn,.ui-controlgroup-horizontal .ui-radio .ui-btn{float:none;margin:0} .ui-controlgroup-horizontal .ui-controlgroup-last,.ui-controlgroup-horizontal .ui-select:last-child,.ui-controlgroup-horizontal .ui-checkbox:last-child,.ui-controlgroup-horizontal .ui-radio:last-child{margin-right:0} .ui-controlgroup .ui-checkbox label,.ui-controlgroup .ui-radio label{font-size:16px}@media all and (min-width:450px){.ui-field-contain .ui-controlgroup-label{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-controlgroup-controls{width:78%;display:inline-block}.ui-field-contain .ui-controlgroup .ui-select{width:100%;display:block}.ui-field-contain .ui-controlgroup-horizontal .ui-select{width:auto}.ui-hide-label .ui-controlgroup-controls{width:100%}} .ui-dialog{background:none!important} .ui-dialog-contain{width:92.5%;max-width:500px;margin:10% auto 15px auto;padding:0;position:relative;top:-15px} .ui-dialog-contain > .ui-header,.ui-dialog-contain > .ui-content,.ui-dialog-contain > .ui-footer{display:block;position:relative;width:auto;margin:0} .ui-dialog-contain > .ui-header{border:none;overflow:hidden;z-index:10;padding:0} .ui-dialog-contain > .ui-content{padding:15px} .ui-dialog-contain > .ui-footer{z-index:10;padding:0 15px} .ui-popup-open .ui-header-fixed,.ui-popup-open .ui-footer-fixed{position:absolute!important} .ui-popup-screen{background-image:url(data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==);top:0;left:0;right:0;bottom:1px;position:absolute;filter:Alpha(Opacity=0);opacity:0;z-index:1099} .ui-popup-screen.in{opacity:0.5;filter:Alpha(Opacity=50)} .ui-popup-screen.out{opacity:0;filter:Alpha(Opacity=0)} .ui-popup-container{z-index:1100;display:inline-block;position:absolute;padding:0;outline:0} .ui-popup{position:relative} .ui-popup.ui-content,.ui-popup .ui-content{overflow:visible} .ui-popup > p,.ui-popup > h1,.ui-popup > h2,.ui-popup > h3,.ui-popup > h4,.ui-popup > h5,.ui-popup > h6{margin:.5em 7px} .ui-popup > span{display:block;margin:.5em 7px} .ui-popup .ui-title{font-size:16px;font-weight:bold;margin-top:.5em;margin-bottom:.5em} .ui-popup-container .ui-content > p,.ui-popup-container .ui-content > h1,.ui-popup-container .ui-content > h2,.ui-popup-container .ui-content > h3,.ui-popup-container .ui-content > h4,.ui-popup-container .ui-content > h5,.ui-popup-container .ui-content > h6{margin:.5em 0} .ui-popup-container .ui-content > span{margin:0} .ui-popup-container .ui-content > p:first-child,.ui-popup-container .ui-content > h1:first-child,.ui-popup-container .ui-content > h2:first-child,.ui-popup-container .ui-content > h3:first-child,.ui-popup-container .ui-content > h4:first-child,.ui-popup-container .ui-content > h5:first-child,.ui-popup-container .ui-content > h6:first-child{margin-top:0} .ui-popup-container .ui-content > p:last-child,.ui-popup-container .ui-content > h1:last-child,.ui-popup-container .ui-content > h2:last-child,.ui-popup-container .ui-content > h3:last-child,.ui-popup-container .ui-content > h4:last-child,.ui-popup-container .ui-content > h5:last-child,.ui-popup-container .ui-content > h6:last-child{margin-bottom:0} .ui-popup > img{width:auto;height:auto;max-width:100%;max-height:100%;vertical-align:middle} .ui-popup iframe{vertical-align:middle}@media all and (min-width:450px){.ui-popup .ui-field-contain label.ui-submit,.ui-popup .ui-field-contain .ui-controlgroup-label,.ui-popup .ui-field-contain label.ui-select,.ui-popup .ui-field-contain label.ui-input-text{font-size:16px;line-height:1.4;display:block;font-weight:normal;margin:0 0 .3em}.ui-popup .ui-field-contain .ui-btn.ui-submit,.ui-popup .ui-field-contain .ui-controlgroup-controls,.ui-popup .ui-field-contain .ui-select,.ui-popup .ui-field-contain input.ui-input-text,.ui-popup .ui-field-contain textarea.ui-input-text,.ui-popup .ui-field-contain .ui-input-search{width:100%;display:block}} .ui-popup > .ui-btn-left,.ui-popup > .ui-btn-right{position:absolute;top:-9px;margin:0;z-index:1101} .ui-popup > .ui-btn-left{left:-9px} .ui-popup > .ui-btn-right{right:-9px} .ui-popup.ui-corner-all > .ui-header,.ui-popup.ui-corner-all ~ .ui-content,.ui-popup.ui-corner-all > .ui-content:first-child{-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit;-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit} .ui-popup.ui-corner-all > .ui-content,.ui-popup.ui-corner-all > .ui-footer,.ui-popup.ui-corner-all > .ui-header:nth-child(n):last-child{-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit;-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit} .ui-popup.ui-corner-all > .ui-content:nth-child(2),.ui-popup.ui-corner-all > .ui-header:nth-child(2){-webkit-border-top-left-radius:0;border-top-left-radius:0;-webkit-border-top-right-radius:0;border-top-right-radius:0} .ui-popup.ui-corner-all > .ui-content:nth-last-child(1n+2),.ui-popup.ui-corner-all > .ui-footer:nth-last-child(1n+2){-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0} .ui-popup.ui-corner-all > .ui-header:only-child,.ui-popup.ui-corner-all > .ui-footer:only-child{-webkit-border-radius:inherit;border-radius:inherit} .ui-popup-hidden{top:-99999px;left:-9999px} .ui-checkbox,.ui-radio{position:relative;clear:both;margin:0;z-index:1} .ui-checkbox .ui-btn,.ui-radio .ui-btn{margin-top:.5em;margin-bottom:.5em;text-align:left;z-index:2} .ui-checkbox .ui-btn.ui-mini,.ui-radio .ui-btn.ui-mini{margin:.25em 0} .ui-controlgroup .ui-checkbox .ui-btn,.ui-controlgroup .ui-radio .ui-btn{margin:0} .ui-checkbox .ui-btn-inner,.ui-radio .ui-btn-inner{white-space:normal} .ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner{padding-left:45px} .ui-checkbox .ui-mini.ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-left .ui-btn-inner{padding-left:36px} .ui-checkbox .ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-btn-icon-right .ui-btn-inner{padding-right:45px} .ui-checkbox .ui-mini.ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-right .ui-btn-inner{padding-right:36px} .ui-checkbox .ui-btn-icon-top .ui-btn-inner,.ui-radio .ui-btn-icon-top .ui-btn-inner{padding-right:0;padding-left:0;text-align:center} .ui-checkbox .ui-btn-icon-bottom .ui-btn-inner,.ui-radio .ui-btn-icon-bottom .ui-btn-inner{padding-right:0;padding-left:0;text-align:center} .ui-checkbox .ui-icon,.ui-radio .ui-icon{top:1.1em} .ui-checkbox .ui-btn-icon-left .ui-icon,.ui-radio .ui-btn-icon-left .ui-icon{left:15px} .ui-checkbox .ui-mini.ui-btn-icon-left .ui-icon,.ui-radio .ui-mini.ui-btn-icon-left .ui-icon{left:9px} .ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px} .ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px} .ui-checkbox .ui-btn-icon-top .ui-icon,.ui-radio .ui-btn-icon-top .ui-icon{top:10px} .ui-checkbox .ui-btn-icon-bottom .ui-icon,.ui-radio .ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px} .ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px} .ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px} .ui-checkbox input,.ui-radio input{position:absolute;left:20px;top:50%;width:10px;height:10px;margin:-5px 0 0 0;outline:0!important;z-index:1} .ui-field-contain,fieldset.ui-field-contain{padding:.8em 0;margin:0;border-width:0 0 1px 0;overflow:visible} .ui-field-contain:last-child{border-bottom-width:0} .ui-field-contain{max-width:100%}@media all and (min-width:450px){.ui-field-contain,.ui-mobile fieldset.ui-field-contain{border-width:0;padding:0;margin:1em 0}} .ui-select{display:block;position:relative} .ui-select select{position:absolute;left:-9999px;top:-9999px} .ui-select .ui-btn{overflow:hidden;opacity:1} .ui-field-contain .ui-select .ui-btn{margin:0} .ui-select .ui-btn select{cursor:pointer;-webkit-appearance:none;left:0;top:0;width:100%;min-height:1.5em;min-height:100%;height:3em;max-height:100%;filter:Alpha(Opacity=0);opacity:0;z-index:2} .ui-select .ui-disabled{opacity:.3} .ui-select .ui-disabled select{display:none} @-moz-document url-prefix(){.ui-select .ui-btn select{opacity:0.0001}} .ui-select .ui-btn.ui-select-nativeonly{border-radius:0;border:0} .ui-select .ui-btn.ui-select-nativeonly select{opacity:1;text-indent:0;display:block} .ui-select .ui-disabled.ui-select-nativeonly .ui-btn-inner{opacity:0} .ui-select .ui-btn-icon-right .ui-btn-inner,.ui-select .ui-li-has-count .ui-btn-inner{padding-right:45px} .ui-select .ui-mini.ui-btn-icon-right .ui-btn-inner{padding-right:32px} .ui-select .ui-btn-icon-right.ui-li-has-count .ui-btn-inner{padding-right:80px} .ui-select .ui-mini.ui-btn-icon-right.ui-li-has-count .ui-btn-inner{padding-right:67px} .ui-select .ui-btn-icon-right .ui-icon{right:15px} .ui-select .ui-mini.ui-btn-icon-right .ui-icon{right:7px} .ui-select .ui-btn-icon-right.ui-li-has-count .ui-li-count{right:45px} .ui-select .ui-mini.ui-btn-icon-right.ui-li-has-count .ui-li-count{right:32px} label.ui-select{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block} .ui-select .ui-btn-text,.ui-selectmenu .ui-btn-text{display:block;min-height:1em;overflow:hidden!important} .ui-select .ui-btn-text{text-overflow:ellipsis} .ui-selectmenu{padding:6px;min-width:160px} .ui-selectmenu .ui-listview{margin:0} .ui-selectmenu .ui-btn.ui-li-divider{cursor:default} .ui-screen-hidden,.ui-selectmenu-list .ui-li .ui-icon{display:none} .ui-selectmenu-list .ui-li .ui-icon{display:block} .ui-li.ui-selectmenu-placeholder{display:none} .ui-selectmenu .ui-header{margin:0;padding:0} .ui-selectmenu.ui-popup .ui-header{-webkit-border-top-left-radius:0;border-top-left-radius:0;-webkit-border-top-right-radius:0;border-top-right-radius:0} .ui-selectmenu .ui-header .ui-title{margin:0.6em 46px 0.8em}@media all and (min-width:450px){.ui-field-contain label.ui-select{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-select{width:78%;display:inline-block}.ui-hide-label .ui-select{width:100%}} .ui-selectmenu .ui-header h1:after{content:'.';visibility:hidden} label.ui-input-text{font-size:16px;line-height:1.4;display:block;font-weight:normal;margin:0 0 .3em} input.ui-input-text,textarea.ui-input-text{background-image:none;padding:.4em;margin:.5em 0;line-height:1.4;font-size:16px;display:block;width:100%;outline:0} input.ui-input-text.ui-mini,textarea.ui-input-text.ui-mini{margin:.25em 0} .ui-field-contain input.ui-input-text,.ui-field-contain textarea.ui-input-text{margin:0} input.ui-input-text,textarea.ui-input-text,.ui-input-search{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box} input.ui-input-text{-webkit-appearance:none} textarea.ui-input-text{height:50px;-webkit-transition:height 200ms linear;-moz-transition:height 200ms linear;-o-transition:height 200ms linear;transition:height 200ms linear} .ui-input-search{padding:0 30px;margin:.5em 0;background-image:none;position:relative} .ui-input-search.ui-mini{margin:.25em 0} .ui-field-contain .ui-input-search{margin:0} .ui-icon-searchfield:after{position:absolute;left:7px;top:50%;margin-top:-9px;content:"";width:18px;height:18px;opacity:.5} .ui-input-search input.ui-input-text{border:none;width:98%;padding:.4em 0;margin:0;display:block;background:transparent none;outline:0!important} .ui-input-search .ui-input-clear{position:absolute;right:0;top:50%;margin-top:-13px} .ui-mini .ui-input-clear{right:-3px} .ui-input-search .ui-input-clear-hidden{display:none} input.ui-mini,.ui-mini input,textarea.ui-mini{font-size:14px} textarea.ui-mini{height:45px} input:-moz-placeholder{color:#aaa} input[type=number]::-webkit-outer-spin-button{margin:0}@media all and (min-width:450px){.ui-field-contain label.ui-input-text{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain input.ui-input-text,.ui-field-contain textarea.ui-input-text,.ui-field-contain .ui-input-search{width:78%;display:inline-block}.ui-hide-label input.ui-input-text,.ui-hide-label textarea.ui-input-text,.ui-hide-label .ui-input-search{width:100%}.ui-input-search input.ui-input-text{width:98%}} .ui-listview{margin:0} ol.ui-listview,ol.ui-listview .ui-li-divider{counter-reset:listnumbering} .ui-content .ui-listview{margin:-15px} .ui-collapsible-content > .ui-listview{margin:-10px -15px} .ui-content .ui-listview-inset{margin:1em 0} .ui-collapsible-content .ui-listview-inset{margin:.5em 0} .ui-listview,.ui-li{list-style:none;padding:0} .ui-li,.ui-li.ui-field-contain{display:block;margin:0;position:relative;overflow:visible;text-align:left;border-width:0;border-top-width:1px} .ui-li.ui-btn{margin:0} .ui-li .ui-btn-text a.ui-link-inherit{text-overflow:ellipsis;overflow:hidden;white-space:nowrap} .ui-li-static{background-image:none} .ui-li-divider{padding:.5em 15px;font-size:14px;font-weight:bold} ol.ui-listview .ui-link-inherit:before,ol.ui-listview .ui-li-static:before,.ui-li-dec{font-size:.8em;display:inline-block;padding-right:.3em;font-weight:normal;counter-increment:listnumbering;content:counter(listnumbering) ". "} ol.ui-listview .ui-li-jsnumbering:before{content:""!important} .ui-listview-inset .ui-li{border-right-width:1px;border-left-width:1px} .ui-li-last,.ui-li.ui-field-contain.ui-li-last{border-bottom-width:1px} .ui-collapsible [class*="ui-body"] > .ui-listview:not(.ui-listview-inset) .ui-li-last{border-bottom-width:0} .ui-collapsible-content > .ui-listview:not(.ui-listview-inset) .ui-li:first-child{border-top-width:0} .ui-collapsible-content > .ui-listview:not(.ui-listview-inset),.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) .ui-li-last{-webkit-border-bottom-left-radius:inherit;-webkit-border-bottom-right-radius:inherit;border-bottom-left-radius:inherit;border-bottom-right-radius:inherit} .ui-collapsible-content > .ui-listview:not(.ui-listview-inset) .ui-li-last .ui-li-link-alt{-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit} .ui-li>.ui-btn-inner{display:block;position:relative;padding:0} .ui-li .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li{padding:.7em 15px;display:block} .ui-li-has-thumb .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-thumb{min-height:60px;padding-left:100px} .ui-li-has-icon .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-icon{min-height:20px;padding-left:40px} .ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-count,.ui-li-divider.ui-li-has-count{padding-right:45px} .ui-li-has-arrow .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow{padding-right:40px} .ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow.ui-li-has-count{padding-right:75px} .ui-li-heading{font-size:16px;font-weight:bold;display:block;margin:.6em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap} .ui-li-desc{font-size:12px;font-weight:normal;display:block;margin:-.5em 0 .6em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap} .ui-li-thumb,.ui-listview .ui-li-icon{position:absolute;left:1px;top:0;max-height:80px;max-width:80px} .ui-listview .ui-li-icon{max-height:16px;max-width:16px;left:10px;top:.9em} .ui-li-thumb,.ui-listview .ui-li-icon,.ui-li-content{float:left;margin-right:10px} .ui-li-aside{float:right;width:50%;text-align:right;margin:.3em 0}@media all and (min-width:480px){.ui-li-aside{width:45%}} .ui-li-divider{cursor:default} .ui-li-has-alt .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-alt{padding-right:53px} .ui-li-has-alt.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-alt.ui-li-has-count{padding-right:88px} .ui-li-has-count .ui-li-count{position:absolute;font-size:11px;font-weight:bold;padding:.2em .5em;top:50%;margin-top:-.9em;right:10px} .ui-li-has-count.ui-li-divider .ui-li-count,.ui-li-has-count .ui-link-inherit .ui-li-count{margin-top:-.95em} .ui-li-has-arrow.ui-li-has-count .ui-li-count{right:40px} .ui-li-has-alt.ui-li-has-count .ui-li-count{right:53px} .ui-li-link-alt{position:absolute;width:40px;height:100%;border-width:0;border-left-width:1px;top:0;right:0;margin:0;padding:0;z-index:2} .ui-li-link-alt .ui-btn{overflow:hidden;position:absolute;right:8px;top:50%;margin:-13px 0 0 0;border-bottom-width:1px;z-index:-1} .ui-li-link-alt .ui-btn-inner{padding:0;height:100%;position:absolute;width:100%;top:0;left:0} .ui-li-link-alt .ui-btn .ui-icon{right:50%;margin-right:-9px} .ui-li-link-alt .ui-btn-icon-notext .ui-btn-inner .ui-icon{position:absolute;top:50%;margin-top:-9px} .ui-listview * .ui-btn-inner > .ui-btn > .ui-btn-inner{border-top:0} .ui-listview-filter{border-width:0;overflow:hidden;margin:-15px -15px 15px -15px} .ui-collapsible-content .ui-listview-filter{margin:-10px -15px 10px -15px;border-bottom:inherit} .ui-listview-filter-inset{margin:-15px -5px;background:transparent} .ui-collapsible-content .ui-listview-filter-inset{margin:-5px;border-bottom-width:0} .ui-listview-filter .ui-input-search{margin:5px;width:auto;display:block} .ui-li.ui-screen-hidden{display:none}@media only screen and (min-device-width:768px) and (max-device-width:1024px){.ui-li .ui-btn-text{overflow:visible}} label.ui-slider{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block} input.ui-slider-input,.ui-field-contain input.ui-slider-input{display:inline-block;width:50px;background-image:none;padding:.4em;margin:.5em 0;line-height:1.4;font-size:16px;outline:0} input.ui-slider-input.ui-mini,.ui-field-contain input.ui-slider-input.ui-mini{width:45px;margin:.25em 0;font-size:14px} .ui-field-contain input.ui-slider-input{margin:0} input.ui-slider-input,.ui-field-contain input.ui-slider-input{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;-ms-box-sizing:content-box;box-sizing:content-box} .ui-slider-input::-webkit-outer-spin-button{margin:0} select.ui-slider-switch{display:none} div.ui-slider{position:relative;display:inline-block;overflow:visible;height:15px;padding:0;margin:0 2% 0 20px;top:4px;width:65%} div.ui-slider-mini{height:12px;margin-left:10px;top:2px} div.ui-slider-bg{border:none;height:100%;padding-right:8px} .ui-controlgroup a.ui-slider-handle,a.ui-btn.ui-slider-handle{position:absolute;z-index:1;top:50%;width:28px;height:28px;margin:-15px 0 0 -15px;outline:0} a.ui-btn.ui-slider-handle .ui-btn-inner{padding:0;height:100%} div.ui-slider-mini a.ui-slider-handle{height:14px;width:14px;margin:-8px 0 0 -7px} div.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:-9px 0 0 -9px;border-top:none}@media all and (min-width:450px){.ui-field-contain label.ui-slider{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain div.ui-slider{width:43%}.ui-field-contain div.ui-slider-switch{width:5.5em}} div.ui-slider-switch{height:32px;margin-left:0;width:5.8em} a.ui-slider-handle-snapping{-webkit-transition:left 70ms linear;-moz-transition:left 70ms linear} div.ui-slider-switch a.ui-btn.ui-slider-handle{margin:1px 0 0 -15px;top:0} .ui-slider-inneroffset{margin:0 16px;position:relative;z-index:1} div.ui-slider-switch.ui-slider-mini{width:5em;height:29px} div.ui-slider-switch.ui-slider-mini .ui-slider-inneroffset{margin:0 15px 0 14px} div.ui-slider-switch.ui-slider-mini .ui-slider-handle{width:25px;height:25px;margin:1px 0 0 -13px} div.ui-slider-switch.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:0} span.ui-slider-label{position:absolute;text-align:center;width:100%;overflow:hidden;font-size:16px;top:0;line-height:2;min-height:100%;border-width:0;white-space:nowrap;cursor:pointer} .ui-slider-mini span.ui-slider-label{font-size:14px} span.ui-slider-label-a{z-index:1;left:0;text-indent:-1.5em} span.ui-slider-label-b{z-index:0;right:0;text-indent:1.5em} .ui-slider-inline{width:120px;display:inline-block} \ No newline at end of file diff --git a/openlp/plugins/remotes/html/assets/jquery.mobile.min.js b/openlp/plugins/remotes/html/assets/jquery.mobile.min.js new file mode 100644 index 000000000..41c25fefa --- /dev/null +++ b/openlp/plugins/remotes/html/assets/jquery.mobile.min.js @@ -0,0 +1,2 @@ +/*! jQuery Mobile vGit Build: SHA1: 27e3c18acfebab2d47ee7ed37bd50fc4942c8838 <> Date: Fri Mar 22 08:50:04 2013 -0600 jquerymobile.com | jquery.org/license !*/ +(function(e,t,n){typeof define=="function"&&define.amd?define(["jquery"],function(r){return n(r,e,t),r.mobile}):n(e.jQuery,e,t)})(this,document,function(e, t, n, r){(function(e, t, r){var i={};e.mobile=e.extend({},{version:"1.2.1",ns:"",subPageUrlKey:"ui-page",activePageClass:"ui-page-active",activeBtnClass:"ui-btn-active",focusClass:"ui-focus",ajaxEnabled:!0,hashListeningEnabled:!0,linkBindingEnabled:!0,defaultPageTransition:"fade",maxTransitionWidth:!1,minScrollBack:250,touchOverflowEnabled:!1,defaultDialogTransition:"pop",pageLoadErrorMessage:"Error Loading Page",pageLoadErrorMessageTheme:"e",phonegapNavigationEnabled:!1,autoInitializePage:!0,pushStateEnabled:!0,ignoreContentEnabled:!1,orientationChangeEnabled:!0,buttonMarkup:{hoverDelay:200},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91},behaviors:{},silentScroll:function(r){e.type(r)!=="number"&&(r=e.mobile.defaultHomeScroll),e.event.special.scrollstart.enabled=!1,setTimeout(function(){t.scrollTo(0,r),e(n).trigger("silentscroll",{x:0,y:r})},20),setTimeout(function(){e.event.special.scrollstart.enabled=!0},150)},nsNormalizeDict:i,nsNormalize:function(t){if(!t)return;return i[t]||(i[t]=e.camelCase(e.mobile.ns+t))},getInheritedTheme:function(e,t){var n=e[0],r="",i=/ui-(bar|body|overlay)-([a-z])\b/,s,o;while(n){s=n.className||"";if(s&&(o=i.exec(s))&&(r=o[2]))break;n=n.parentNode}return r||t||"a"},closestPageData:function(e){return e.closest(':jqmData(role="page"), :jqmData(role="dialog")').data("page")},enhanceable:function(e){return this.haveParents(e,"enhance")},hijackable:function(e){return this.haveParents(e,"ajax")},haveParents:function(t,n){if(!e.mobile.ignoreContentEnabled)return t;var r=t.length,i=e(),s,o,u;for(var a=0;a").text(e(this).text()).html()},e.fn.jqmEnhanceable=function(){return e.mobile.enhanceable(this)},e.fn.jqmHijackable=function(){return e.mobile.hijackable(this)};var s=e.find,o=/:jqmData\(([^)]*)\)/g;e.find=function(t,n,r,i){return t=t.replace(o,"[data-"+(e.mobile.ns||"")+"$1]"),s.call(this,t,n,r,i)},e.extend(e.find,s),e.find.matches=function(t,n){return e.find(t,null,null,n)},e.find.matchesSelector=function(t,n){return e.find(n,null,null,[t]).length>0}})(e,this),function(e,t){var n=0,r=Array.prototype.slice,i=e.cleanData;e.cleanData=function(t){for(var n=0,r;(r=t[n])!=null;n++)try{e(r).triggerHandler("remove")}catch(s){}i(t)},e.widget=function(t,n,r){var i,s,o,u,a=t.split(".")[0];t=t.split(".")[1],i=a+"-"+t,r||(r=n,n=e.Widget),e.expr[":"][i]=function(t){return!!e.data(t,i)},e[a]=e[a]||{},s=e[a][t],o=e[a][t]=function(e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)},e.extend(o,s,{version:r.version,_proto:e.extend({},r),_childConstructors:[]}),u=new n,u.options=e.widget.extend({},u.options),e.each(r,function(t,i){e.isFunction(i)&&(r[t]=function(){var e=function(){return n.prototype[t].apply(this,arguments)},r=function(e){return n.prototype[t].apply(this,e)};return function(){var t=this._super,n=this._superApply,s;return this._super=e,this._superApply=r,s=i.apply(this,arguments),this._super=t,this._superApply=n,s}}())}),o.prototype=e.widget.extend(u,{widgetEventPrefix:t},r,{constructor:o,namespace:a,widgetName:t,widgetBaseClass:i,widgetFullName:i}),s?(e.each(s._childConstructors,function(t,n){var r=n.prototype;e.widget(r.namespace+"."+r.widgetName,o,n._proto)}),delete s._childConstructors):n._childConstructors.push(o),e.widget.bridge(t,o)},e.widget.extend=function(n){var i=r.call(arguments,1),s=0,o=i.length,u,a;for(;s",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetName,this),e.data(r,this.widgetFullName,this),this._on({remove:"destroy"}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u"+""+"

"+"",fakeFixLoader:function(){var t=e("."+e.mobile.activeBtnClass).first();this.element.css({top:e.support.scrollTop&&s.scrollTop()+s.height()/2||t.length&&t.offset().top||100})},checkLoaderPosition:function(){var t=this.element.offset(),n=s.scrollTop(),r=e.mobile.getScreenHeight();if(t.topr)this.element.addClass("ui-loader-fakefix"),this.fakeFixLoader(),s.unbind("scroll",this.checkLoaderPosition).bind("scroll",e.proxy(this.fakeFixLoader,this))},resetHtml:function(){this.element.html(e(this.defaultHtml).html())},show:function(t,o,u){var a,f,l,c;this.resetHtml(),e.type(t)==="object"?(c=e.extend({},this.options,t),t=c.theme||e.mobile.loadingMessageTheme):(c=this.options,t=t||e.mobile.loadingMessageTheme||c.theme),f=o||e.mobile.loadingMessage||c.text,i.addClass("ui-loading");if(e.mobile.loadingMessage!==!1||c.html)e.mobile.loadingMessageTextVisible!==r?a=e.mobile.loadingMessageTextVisible:a=c.textVisible,this.element.attr("class",n+" ui-corner-all ui-body-"+t+" ui-loader-"+(a||o||t.text?"verbose":"default")+(c.textonly||u?" ui-loader-textonly":"")),c.html?this.element.html(c.html):this.element.find("h1").text(f),this.element.appendTo(e.mobile.pageContainer),this.checkLoaderPosition(),s.bind("scroll",e.proxy(this.checkLoaderPosition,this))},hide:function(){i.removeClass("ui-loading"),e.mobile.loadingMessage&&this.element.removeClass("ui-loader-fakefix"),e(t).unbind("scroll",this.fakeFixLoader),e(t).unbind("scroll",this.checkLoaderPosition)}}),s.bind("pagecontainercreate",function(){e.mobile.loaderWidget=e.mobile.loaderWidget||e(e.mobile.loader.prototype.defaultHtml).loader()})}(e,this),function(e,t,n,r){function x(e){while(e&&typeof e.originalEvent!="undefined")e=e.originalEvent;return e}function T(t,n){var i=t.type,s,o,a,l,c,h,p,d,v;t=e.Event(t),t.type=n,s=t.originalEvent,o=e.event.props,i.search(/^(mouse|click)/)>-1&&(o=f);if(s)for(p=o.length,l;p;)l=o[--p],t[l]=s[l];i.search(/mouse(down|up)|click/)>-1&&!t.which&&(t.which=1);if(i.search(/^touch/)!==-1){a=x(s),i=a.touches,c=a.changedTouches,h=i&&i.length?i[0]:c&&c.length?c[0]:r;if(h)for(d=0,v=u.length;di||Math.abs(n.pageY-p)>i,d&&!r&&D("vmousecancel",t,s),D("vmousemove",t,s),M()}function F(e){if(g)return;L();var t=N(e.target),n;D("vmouseup",e,t);if(!d){var r=D("vclick",e,t);r&&r.isDefaultPrevented()&&(n=x(e).changedTouches[0],v.push({touchID:E,x:n.clientX,y:n.clientY}),m=!0)}D("vmouseout",e,t),d=!1,M()}function I(t){var n=e.data(t,i),r;if(n)for(r in n)if(n[r])return!0;return!1}function q(){}function R(t){var n=t.substr(1);return{setup:function(r,s){I(this)||e.data(this,i,{});var o=e.data(this,i);o[t]=!0,l[t]=(l[t]||0)+1,l[t]===1&&b.bind(n,P),e(this).bind(n,q),y&&(l.touchstart=(l.touchstart||0)+1,l.touchstart===1&&b.bind("touchstart",H).bind("touchend",F).bind("touchmove",j).bind("scroll",B))},teardown:function(r,s){--l[t],l[t]||b.unbind(n,P),y&&(--l.touchstart,l.touchstart||b.unbind("touchstart",H).unbind("touchmove",j).unbind("touchend",F).unbind("scroll",B));var o=e(this),u=e.data(this,i);u&&(u[t]=!1),o.unbind(n,q),I(this)||o.removeData(i)}}}var i="virtualMouseBindings",s="virtualTouchID",o="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),u="clientX clientY pageX pageY screenX screenY".split(" "),a=e.event.mouseHooks?e.event.mouseHooks.props:[],f=e.event.props.concat(a),l={},c=0,h=0,p=0,d=!1,v=[],m=!1,g=!1,y="addEventListener"in n,b=e(n),w=1,E=0,S;e.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10,resetTimerDuration:1500};for(var U=0;Ue.event.special.swipe.scrollSupressionThreshold&&t.preventDefault()}var i=t.originalEvent.touches?t.originalEvent.touches[0]:t,s={time:(new Date).getTime(),coords:[i.pageX,i.pageY],origin:e(t.target)},o;n.bind(a,f).one(u,function(t){n.unbind(a,f),s&&o&&o.time-s.timee.event.special.swipe.horizontalDistanceThreshold&&Math.abs(s.coords[1]-o.coords[1])o.coords[0]?"swipeleft":"swiperight"),s=o=r})})}},e.each({scrollstop:"scrollstart",taphold:"tap",swipeleft:"swipe",swiperight:"swipe"},function(t,n){e.event.special[t]={setup:function(){e(this).bind(n,e.noop)}}})}(e,this),function(e,n){e.extend(e.support,{orientation:"orientation"in t&&"onorientationchange"in t})}(e),function(e){e.event.special.throttledresize={setup:function(){e(this).bind("resize",n)},teardown:function(){e(this).unbind("resize",n)}};var t=250,n=function(){s=(new Date).getTime(),o=s-r,o>=t?(r=s,e(this).trigger("throttledresize")):(i&&clearTimeout(i),i=setTimeout(n,t-o))},r=0,i,s,o}(e),function(e,t){function d(){var e=o();e!==u&&(u=e,r.trigger(i))}var r=e(t),i="orientationchange",s,o,u,a,f,l={0:!0,180:!0};if(e.support.orientation){var c=t.innerWidth||e(t).width(),h=t.innerHeight||e(t).height(),p=50;a=c>h&&c-h>p,f=l[t.orientation];if(a&&f||!a&&!f)l={"-90":!0,90:!0}}e.event.special.orientationchange=e.extend({},e.event.special.orientationchange,{setup:function(){if(e.support.orientation&&!e.event.special.orientationchange.disabled)return!1;u=o(),r.bind("throttledresize",d)},teardown:function(){if(e.support.orientation&&!e.event.special.orientationchange.disabled)return!1;r.unbind("throttledresize",d)},add:function(e){var t=e.handler;e.handler=function(e){return e.orientation=o(),t.apply(this,arguments)}}}),e.event.special.orientationchange.orientation=o=function(){var r=!0,i=n.documentElement;return e.support.orientation?r=l[t.orientation]:r=i&&i.clientWidth/i.clientHeight<1.1,r?"portrait":"landscape"},e.fn[i]=function(e){return e?this.bind(i,e):this.trigger(i)},e.attrFn&&(e.attrFn[i]=!0)}(e,this),function(e,r){var i=e(t),s=e("html");e.mobile.media=function(){var t={},r=e("
"),i=e("").append(r);return function(e){if(!(e in t)){var o=n.createElement("style"),u="@media "+e+" { #jquery-mediatest { position:absolute; } }";o.type="text/css",o.styleSheet?o.styleSheet.cssText=u:o.appendChild(n.createTextNode(u)),s.prepend(i).prepend(o),t[e]=r.css("position")==="absolute",i.add(o).remove()}return t[e]}}()}(e),function(e,r){function i(e){var t=e.charAt(0).toUpperCase()+e.substr(1),n=(e+" "+u.join(t+" ")+t).split(" ");for(var i in n)if(o[n[i]]!==r)return!0}function h(e,t,r){var i=n.createElement("div"),s=function(e){return e.charAt(0).toUpperCase()+e.substr(1)},o=function(e){return"-"+e.charAt(0).toLowerCase()+e.substr(1)+"-"},a=function(n){var r=o(n)+e+": "+t+";",u=s(n),a=u+s(e);i.setAttribute("style",r),!i.style[a]||(l=!0)},f=r?[r]:u,l;for(var c=0;c",{href:t}).appendTo("head"),o=e("").prependTo(s),u=o[0].href,n[0].href=i||location.pathname,r&&r.remove(),u.indexOf(t)===0}function v(){var e=n.createElement("x"),r=n.documentElement,i=t.getComputedStyle,s;return"pointerEvents"in e.style?(e.style.pointerEvents="auto",e.style.pointerEvents="x",r.appendChild(e),s=i&&i(e,"").pointerEvents==="auto",r.removeChild(e),!!s):!1}function m(){var e=n.createElement("div");return typeof e.getBoundingClientRect!="undefined"}var s=e("").prependTo("html"),o=s[0].style,u=["Webkit","Moz","O"],a="palmGetResource"in t,f=t.opera,l=t.operamini&&{}.toString.call(t.operamini)==="[object OperaMini]",c=t.blackberry&&!i("-webkit-transform");e.extend(e.mobile,{browser:{}}),e.mobile.browser.ie=function(){var e=3,t=n.createElement("div"),r=t.all||[];do t.innerHTML="";while(r[0]);return e>4?e:!e}(),e.extend(e.support,{cssTransitions:"WebKitTransitionEvent"in t||h("transition","height 100ms linear")&&!f,pushState:"pushState"in history&&"replaceState"in history,mediaquery:e.mobile.media("only all"),cssPseudoElement:!!i("content"),touchOverflow:!!i("overflowScrolling"),cssTransform3d:p(),boxShadow:!!i("boxShadow")&&!c,scrollTop:("pageXOffset"in t||"scrollTop"in n.documentElement||"scrollTop"in s[0])&&!a&&!l,dynamicBaseTag:d(),cssPointerEvents:v(),boundingRect:m()}),s.remove();var g=function(){var e=t.navigator.userAgent;return e.indexOf("Nokia")>-1&&(e.indexOf("Symbian/3")>-1||e.indexOf("Series60/5")>-1)&&e.indexOf("AppleWebKit")>-1&&e.match(/(BrowserNG|NokiaBrowser)\/7\.[0-3]/)}();e.mobile.gradeA=function(){return(e.support.mediaquery||e.mobile.browser.ie&&e.mobile.browser.ie>=7)&&(e.support.boundingRect||e.fn.jquery.match(/1\.[0-7+]\.[0-9+]?/)!==null)},e.mobile.ajaxBlacklist=t.blackberry&&!t.WebKitPoint||l||g,g&&e(function(){e("head link[rel='stylesheet']").attr("rel","alternate stylesheet").attr("rel","stylesheet")}),e.support.boxShadow||e("html").addClass("ui-mobile-nosupport-boxshadow")}(e),function(e,t){e.widget("mobile.page",e.mobile.widget,{options:{theme:"c",domCache:!1,keepNativeDefault:":jqmData(role='none'), :jqmData(role='nojs')"},_create:function(){var e=this;if(e._trigger("beforecreate")===!1)return!1;e.element.attr("tabindex","0").addClass("ui-page ui-body-"+e.options.theme).bind("pagebeforehide",function(){e.removeContainerBackground()}).bind("pagebeforeshow",function(){e.setContainerBackground()})},removeContainerBackground:function(){e.mobile.pageContainer.removeClass("ui-overlay-"+e.mobile.getInheritedTheme(this.element.parent()))},setContainerBackground:function(t){this.options.theme&&e.mobile.pageContainer.addClass("ui-overlay-"+(t||this.options.theme))},keepNativeSelector:function(){var t=this.options,n=t.keepNative&&e.trim(t.keepNative);return n&&t.keepNative!==t.keepNativeDefault?[t.keepNative,t.keepNativeDefault].join(", "):t.keepNativeDefault}})}(e),function(e,t,r){function l(e){return e=e||location.href,"#"+e.replace(/^[^#]*#?(.*)$/,"$1")}var i="hashchange",s=n,o,u=e.event.special,a=s.documentMode,f="on"+i in t&&(a===r||a>7);e.fn[i]=function(e){return e?this.bind(i,e):this.trigger(i)},e.fn[i].delay=50,u[i]=e.extend(u[i],{setup:function(){if(f)return!1;e(o.start)},teardown:function(){if(f)return!1;e(o.stop)}}),o=function(){function p(){var n=l(),r=h(u);n!==u?(c(u=n,r),e(t).trigger(i)):r!==u&&(location.href=location.href.replace(/#.*/,"")+r),o=setTimeout(p,e.fn[i].delay)}var n={},o,u=l(),a=function(e){return e},c=a,h=a;return n.start=function(){o||p()},n.stop=function(){o&&clearTimeout(o),o=r},e.browser.msie&&!f&&function(){var t,r;n.start=function(){t||(r=e.fn[i].src,r=r&&r+l(),t=e('