This commit is contained in:
Andreas Preikschat 2012-06-17 14:55:25 +02:00
commit 1b7b1a9802
86 changed files with 2237 additions and 1346 deletions

View File

@ -41,6 +41,7 @@ from traceback import format_exception
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, check_directory_exists from openlp.core.lib import Receiver, check_directory_exists
from openlp.core.lib.settings import Settings
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.core.resources import qInitResources from openlp.core.resources import qInitResources
from openlp.core.ui.mainwindow import MainWindow from openlp.core.ui.mainwindow import MainWindow
@ -113,15 +114,15 @@ class OpenLP(QtGui.QApplication):
# Decide how many screens we have and their size # Decide how many screens we have and their size
screens = ScreenList.create(self.desktop()) screens = ScreenList.create(self.desktop())
# First time checks in settings # First time checks in settings
has_run_wizard = QtCore.QSettings().value( has_run_wizard = Settings().value(
u'general/has run wizard', QtCore.QVariant(False)).toBool() u'general/has run wizard', QtCore.QVariant(False)).toBool()
if not has_run_wizard: if not has_run_wizard:
if FirstTimeForm(screens).exec_() == QtGui.QDialog.Accepted: if FirstTimeForm(screens).exec_() == QtGui.QDialog.Accepted:
QtCore.QSettings().setValue(u'general/has run wizard', Settings().setValue(u'general/has run wizard',
QtCore.QVariant(True)) QtCore.QVariant(True))
if os.name == u'nt': if os.name == u'nt':
self.setStyleSheet(application_stylesheet) self.setStyleSheet(application_stylesheet)
show_splash = QtCore.QSettings().value( show_splash = Settings().value(
u'general/show splash', QtCore.QVariant(True)).toBool() u'general/show splash', QtCore.QVariant(True)).toBool()
if show_splash: if show_splash:
self.splash = SplashScreen() self.splash = SplashScreen()
@ -141,7 +142,7 @@ class OpenLP(QtGui.QApplication):
self.processEvents() self.processEvents()
if not has_run_wizard: if not has_run_wizard:
self.mainWindow.firstTime() self.mainWindow.firstTime()
update_check = QtCore.QSettings().value( update_check = Settings().value(
u'general/update check', QtCore.QVariant(True)).toBool() u'general/update check', QtCore.QVariant(True)).toBool()
if update_check: if update_check:
VersionThread(self.mainWindow).start() VersionThread(self.mainWindow).start()
@ -258,6 +259,27 @@ def main(args=None):
app = OpenLP(qt_args) app = OpenLP(qt_args)
app.setOrganizationName(u'OpenLP') app.setOrganizationName(u'OpenLP')
app.setOrganizationDomain(u'openlp.org') app.setOrganizationDomain(u'openlp.org')
if options.portable:
log.info(u'Running portable')
app.setApplicationName(u'OpenLPPortable')
Settings.setDefaultFormat(Settings.IniFormat)
# Get location OpenLPPortable.ini
app_path = AppLocation.get_directory(AppLocation.AppDir)
portable_settings_file = os.path.abspath(os.path.join(app_path, u'..',
u'..', u'Data', u'OpenLP.ini'))
# Make this our settings file
log.info(u'INI file: %s', portable_settings_file)
Settings.setFilename(portable_settings_file)
portable_settings = Settings()
# Set our data path
data_path = os.path.abspath(os.path.join(app_path,
u'..', u'..', u'Data',))
log.info(u'Data path: %s', data_path)
# Point to our data path
portable_settings.setValue(u'advanced/data path', data_path)
portable_settings.setValue(u'advanced/is portable', True)
portable_settings.sync()
else:
app.setApplicationName(u'OpenLP') app.setApplicationName(u'OpenLP')
app.setApplicationVersion(get_application_version()[u'version']) app.setApplicationVersion(get_application_version()[u'version'])
# Instance check # Instance check
@ -266,7 +288,7 @@ def main(args=None):
if app.isAlreadyRunning(): if app.isAlreadyRunning():
sys.exit() sys.exit()
# First time checks in settings # First time checks in settings
if not QtCore.QSettings().value(u'general/has run wizard', if not Settings().value(u'general/has run wizard',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
if not FirstTimeLanguageForm().exec_(): if not FirstTimeLanguageForm().exec_():
# if cancel then stop processing # if cancel then stop processing

View File

@ -41,6 +41,7 @@ from sqlalchemy.pool import NullPool
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation, delete_file from openlp.core.utils import AppLocation, delete_file
from openlp.core.lib.settings import Settings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -179,7 +180,7 @@ class Manager(object):
The file name to use for this database. Defaults to None resulting The file name to use for this database. Defaults to None resulting
in the plugin_name being used. in the plugin_name being used.
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(plugin_name) settings.beginGroup(plugin_name)
self.db_url = u'' self.db_url = u''
self.is_dirty = False self.is_dirty = False
@ -238,6 +239,7 @@ class Manager(object):
``commit`` ``commit``
Commit the session with this object Commit the session with this object
""" """
for try_count in range(3):
try: try:
self.session.add(object_instance) self.session.add(object_instance)
if commit: if commit:
@ -248,17 +250,19 @@ class Manager(object):
# This exception clause is for users running MySQL which likes # This exception clause is for users running MySQL which likes
# to terminate connections on its own without telling anyone. # to terminate connections on its own without telling anyone.
# See bug #927473 # See bug #927473
# However, other dbms can raise it, usually in a non-recoverable
# way. So we only retry 3 times.
log.exception(u'Probably a MySQL issue - "MySQL has gone away"') log.exception(u'Probably a MySQL issue - "MySQL has gone away"')
self.session.rollback() self.session.rollback()
self.session.add(object_instance) if try_count >= 2:
if commit: raise
self.session.commit()
self.is_dirty = True
return True
except InvalidRequestError: except InvalidRequestError:
self.session.rollback() self.session.rollback()
log.exception(u'Object save failed') log.exception(u'Object list save failed')
return False return False
except:
self.session.rollback()
raise
def save_objects(self, object_list, commit=True): def save_objects(self, object_list, commit=True):
""" """
@ -270,6 +274,7 @@ class Manager(object):
``commit`` ``commit``
Commit the session with this object Commit the session with this object
""" """
for try_count in range(3):
try: try:
self.session.add_all(object_list) self.session.add_all(object_list)
if commit: if commit:
@ -280,17 +285,19 @@ class Manager(object):
# This exception clause is for users running MySQL which likes # This exception clause is for users running MySQL which likes
# to terminate connections on its own without telling anyone. # to terminate connections on its own without telling anyone.
# See bug #927473 # See bug #927473
# However, other dbms can raise it, usually in a non-recoverable
# way. So we only retry 3 times.
log.exception(u'Probably a MySQL issue, "MySQL has gone away"') log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
self.session.rollback() self.session.rollback()
self.session.add_all(object_list) if try_count >= 2:
if commit: raise
self.session.commit()
self.is_dirty = True
return True
except InvalidRequestError: except InvalidRequestError:
self.session.rollback() self.session.rollback()
log.exception(u'Object list save failed') log.exception(u'Object list save failed')
return False return False
except:
self.session.rollback()
raise
def get_object(self, object_class, key=None): def get_object(self, object_class, key=None):
""" """
@ -305,15 +312,18 @@ class Manager(object):
if not key: if not key:
return object_class() return object_class()
else: else:
for try_count in range(3):
try: try:
return self.session.query(object_class).get(key) return self.session.query(object_class).get(key)
except OperationalError: except OperationalError:
# This exception clause is for users running MySQL which likes # This exception clause is for users running MySQL which likes
# to terminate connections on its own without telling anyone. # to terminate connections on its own without telling anyone.
# See bug #927473 # See bug #927473
# However, other dbms can raise it, usually in a non-recoverable
# way. So we only retry 3 times.
log.exception(u'Probably a MySQL issue, "MySQL has gone away"') log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
self.session.rollback() if try_count >= 2:
return self.session.query(object_class).get(key) raise
def get_object_filtered(self, object_class, filter_clause): def get_object_filtered(self, object_class, filter_clause):
""" """
@ -325,15 +335,18 @@ class Manager(object):
``filter_clause`` ``filter_clause``
The criteria to select the object by The criteria to select the object by
""" """
for try_count in range(3):
try: try:
return self.session.query(object_class).filter(filter_clause).first() return self.session.query(object_class).filter(filter_clause).first()
except OperationalError: except OperationalError:
# This exception clause is for users running MySQL which likes # This exception clause is for users running MySQL which likes
# to terminate connections on its own without telling anyone. # to terminate connections on its own without telling anyone.
# See bug #927473 # See bug #927473
# However, other dbms can raise it, usually in a non-recoverable
# way. So we only retry 3 times.
log.exception(u'Probably a MySQL issue, "MySQL has gone away"') log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
self.session.rollback() if try_count >= 2:
return self.session.query(object_class).filter(filter_clause).first() raise
def get_all_objects(self, object_class, filter_clause=None, def get_all_objects(self, object_class, filter_clause=None,
order_by_ref=None): order_by_ref=None):
@ -357,15 +370,18 @@ class Manager(object):
query = query.order_by(*order_by_ref) query = query.order_by(*order_by_ref)
elif order_by_ref is not None: elif order_by_ref is not None:
query = query.order_by(order_by_ref) query = query.order_by(order_by_ref)
for try_count in range(3):
try: try:
return query.all() return query.all()
except OperationalError: except OperationalError:
# This exception clause is for users running MySQL which likes # This exception clause is for users running MySQL which likes
# to terminate connections on its own without telling anyone. # to terminate connections on its own without telling anyone.
# See bug #927473 # See bug #927473
# However, other dbms can raise it, usually in a non-recoverable
# way. So we only retry 3 times.
log.exception(u'Probably a MySQL issue, "MySQL has gone away"') log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
self.session.rollback() if try_count >= 2:
return query.all() raise
def get_object_count(self, object_class, filter_clause=None): def get_object_count(self, object_class, filter_clause=None):
""" """
@ -381,15 +397,18 @@ class Manager(object):
query = self.session.query(object_class) query = self.session.query(object_class)
if filter_clause is not None: if filter_clause is not None:
query = query.filter(filter_clause) query = query.filter(filter_clause)
for try_count in range(3):
try: try:
return query.count() return query.count()
except OperationalError: except OperationalError:
# This exception clause is for users running MySQL which likes # This exception clause is for users running MySQL which likes
# to terminate connections on its own without telling anyone. # to terminate connections on its own without telling anyone.
# See bug #927473 # See bug #927473
# However, other dbms can raise it, usually in a non-recoverable
# way. So we only retry 3 times.
log.exception(u'Probably a MySQL issue, "MySQL has gone away"') log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
self.session.rollback() if try_count >= 2:
return query.count() raise
def delete_object(self, object_class, key): def delete_object(self, object_class, key):
""" """
@ -403,6 +422,7 @@ class Manager(object):
""" """
if key != 0: if key != 0:
object_instance = self.get_object(object_class, key) object_instance = self.get_object(object_class, key)
for try_count in range(3):
try: try:
self.session.delete(object_instance) self.session.delete(object_instance)
self.session.commit() self.session.commit()
@ -412,16 +432,19 @@ class Manager(object):
# This exception clause is for users running MySQL which likes # This exception clause is for users running MySQL which likes
# to terminate connections on its own without telling anyone. # to terminate connections on its own without telling anyone.
# See bug #927473 # See bug #927473
# However, other dbms can raise it, usually in a non-recoverable
# way. So we only retry 3 times.
log.exception(u'Probably a MySQL issue, "MySQL has gone away"') log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
self.session.rollback() self.session.rollback()
self.session.delete(object_instance) if try_count >= 2:
self.session.commit() raise
self.is_dirty = True
return True
except InvalidRequestError: except InvalidRequestError:
self.session.rollback() self.session.rollback()
log.exception(u'Failed to delete object') log.exception(u'Failed to delete object')
return False return False
except:
self.session.rollback()
raise
else: else:
return True return True
@ -439,6 +462,7 @@ class Manager(object):
The filter governing selection of objects to return. Defaults to The filter governing selection of objects to return. Defaults to
None. None.
""" """
for try_count in range(3):
try: try:
query = self.session.query(object_class) query = self.session.query(object_class)
if filter_clause is not None: if filter_clause is not None:
@ -451,19 +475,19 @@ class Manager(object):
# This exception clause is for users running MySQL which likes # This exception clause is for users running MySQL which likes
# to terminate connections on its own without telling anyone. # to terminate connections on its own without telling anyone.
# See bug #927473 # See bug #927473
# However, other dbms can raise it, usually in a non-recoverable
# way. So we only retry 3 times.
log.exception(u'Probably a MySQL issue, "MySQL has gone away"') log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
self.session.rollback() self.session.rollback()
query = self.session.query(object_class) if try_count >= 2:
if filter_clause is not None: raise
query = query.filter(filter_clause)
query.delete(synchronize_session=False)
self.session.commit()
self.is_dirty = True
return True
except InvalidRequestError: except InvalidRequestError:
self.session.rollback() self.session.rollback()
log.exception(u'Failed to delete %s records', object_class.__name__) log.exception(u'Failed to delete %s records', object_class.__name__)
return False return False
except:
self.session.rollback()
raise
def finalise(self): def finalise(self):
""" """

View File

@ -268,7 +268,7 @@ class Receiver(object):
<<ACTION>> <<ACTION>>
)`` )``
""" """
eventreceiver = EventReceiver() __eventreceiver__ = EventReceiver()
@staticmethod @staticmethod
def send_message(event, msg=None): def send_message(event, msg=None):
@ -281,11 +281,11 @@ class Receiver(object):
``msg`` ``msg``
Defaults to *None*. The message to send with the event. Defaults to *None*. The message to send with the event.
""" """
Receiver.eventreceiver.send_message(event, msg) Receiver.__eventreceiver__.send_message(event, msg)
@staticmethod @staticmethod
def get_receiver(): def get_receiver():
""" """
Get the global ``eventreceiver`` instance. Get the global ``__eventreceiver__`` instance.
""" """
return Receiver.eventreceiver return Receiver.__eventreceiver__

View File

@ -32,6 +32,7 @@ import cPickle
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.settings import Settings
class FormattingTags(object): class FormattingTags(object):
@ -68,7 +69,7 @@ class FormattingTags(object):
if isinstance(tag[element], unicode): if isinstance(tag[element], unicode):
tag[element] = tag[element].encode('utf8') tag[element] = tag[element].encode('utf8')
# Formatting Tags were also known as display tags. # Formatting Tags were also known as display tags.
QtCore.QSettings().setValue(u'displayTags/html_tags', Settings().setValue(u'displayTags/html_tags',
QtCore.QVariant(cPickle.dumps(tags) if tags else u'')) QtCore.QVariant(cPickle.dumps(tags) if tags else u''))
@staticmethod @staticmethod
@ -164,7 +165,7 @@ class FormattingTags(object):
FormattingTags.add_html_tags(temporary_tags) FormattingTags.add_html_tags(temporary_tags)
# Formatting Tags were also known as display tags. # Formatting Tags were also known as display tags.
user_expands = QtCore.QSettings().value(u'displayTags/html_tags', user_expands = Settings().value(u'displayTags/html_tags',
QtCore.QVariant(u'')).toString() QtCore.QVariant(u'')).toString()
# cPickle only accepts str not unicode strings # cPickle only accepts str not unicode strings
user_expands_string = str(user_expands) user_expands_string = str(user_expands)

View File

@ -38,6 +38,7 @@ from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, \
from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import UiStrings, create_widget_action, \ from openlp.core.lib.ui import UiStrings, create_widget_action, \
critical_error_message_box critical_error_message_box
from openlp.core.lib.settings import Settings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -462,7 +463,7 @@ class MediaManagerItem(QtGui.QWidget):
""" """
Allows the list click action to be determined dynamically Allows the list click action to be determined dynamically
""" """
if QtCore.QSettings().value(u'advanced/double click live', if Settings().value(u'advanced/double click live',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
self.onLiveClick() self.onLiveClick()
else: else:
@ -472,7 +473,7 @@ class MediaManagerItem(QtGui.QWidget):
""" """
Allows the change of current item in the list to be actioned Allows the change of current item in the list to be actioned
""" """
if QtCore.QSettings().value(u'advanced/single click preview', if Settings().value(u'advanced/single click preview',
QtCore.QVariant(False)).toBool() and self.quickPreviewAllowed \ QtCore.QVariant(False)).toBool() and self.quickPreviewAllowed \
and self.listView.selectedIndexes() \ and self.listView.selectedIndexes() \
and self.autoSelectId == -1: and self.autoSelectId == -1:

View File

@ -32,6 +32,7 @@ import logging
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Receiver from openlp.core.lib import Receiver
from openlp.core.lib.settings import Settings
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.core.utils import get_application_version from openlp.core.utils import get_application_version
@ -190,7 +191,7 @@ class Plugin(QtCore.QObject):
""" """
Sets the status of the plugin Sets the status of the plugin
""" """
self.status = QtCore.QSettings().value( self.status = Settings().value(
self.settingsSection + u'/status', self.settingsSection + u'/status',
QtCore.QVariant(PluginStatus.Inactive)).toInt()[0] QtCore.QVariant(PluginStatus.Inactive)).toInt()[0]
@ -199,7 +200,7 @@ class Plugin(QtCore.QObject):
Changes the status of the plugin and remembers it Changes the status of the plugin and remembers it
""" """
self.status = new_status self.status = new_status
QtCore.QSettings().setValue( Settings().setValue(
self.settingsSection + u'/status', QtCore.QVariant(self.status)) self.settingsSection + u'/status', QtCore.QVariant(self.status))
if new_status == PluginStatus.Active: if new_status == PluginStatus.Active:
self.initialise() self.initialise()

View File

@ -41,13 +41,13 @@ class PluginManager(object):
and executes all the hooks, as and when necessary. and executes all the hooks, as and when necessary.
""" """
log.info(u'Plugin manager loaded') log.info(u'Plugin manager loaded')
__instance__ = None
@staticmethod @staticmethod
def get_instance(): def get_instance():
""" """
Obtain a single instance of class. Obtain a single instance of class.
""" """
return PluginManager.instance return PluginManager.__instance__
def __init__(self, plugin_dir): def __init__(self, plugin_dir):
""" """
@ -58,7 +58,7 @@ class PluginManager(object):
The directory to search for plugins. The directory to search for plugins.
""" """
log.info(u'Plugin manager Initialising') log.info(u'Plugin manager Initialising')
PluginManager.instance = self PluginManager.__instance__ = self
if not plugin_dir in sys.path: if not plugin_dir in sys.path:
log.debug(u'Inserting %s into sys.path', plugin_dir) log.debug(u'Inserting %s into sys.path', plugin_dir)
sys.path.insert(0, plugin_dir) sys.path.insert(0, plugin_dir)

View File

@ -234,10 +234,10 @@ class Renderer(object):
serviceItem = ServiceItem() serviceItem = ServiceItem()
if self.force_page: if self.force_page:
# make big page for theme edit dialog to get line count # make big page for theme edit dialog to get line count
serviceItem.add_from_text(u'', VERSE_FOR_LINE_COUNT) serviceItem.add_from_text(VERSE_FOR_LINE_COUNT)
else: else:
self.image_manager.deleteImage(theme_data.theme_name) self.image_manager.deleteImage(theme_data.theme_name)
serviceItem.add_from_text(u'', VERSE) serviceItem.add_from_text(VERSE)
serviceItem.renderer = self serviceItem.renderer = self
serviceItem.raw_footer = FOOTER serviceItem.raw_footer = FOOTER
# if No file do not update cache # if No file do not update cache
@ -303,7 +303,7 @@ class Renderer(object):
try: try:
text_to_render, text = \ text_to_render, text = \
text.split(u'\n[---]\n', 1) text.split(u'\n[---]\n', 1)
except: except ValueError:
text_to_render = text.split(u'\n[---]\n')[0] text_to_render = text.split(u'\n[---]\n')[0]
text = u'' text = u''
text_to_render, raw_tags, html_tags = \ text_to_render, raw_tags, html_tags = \

View File

@ -220,20 +220,17 @@ class ServiceItem(object):
self.image_border) self.image_border)
self._new_item() self._new_item()
def add_from_text(self, title, raw_slide, verse_tag=None): def add_from_text(self, raw_slide, verse_tag=None):
""" """
Add a text slide to the service item. Add a text slide to the service item.
``frame_title``
The title of the slide in the service item.
``raw_slide`` ``raw_slide``
The raw text of the slide. The raw text of the slide.
""" """
if verse_tag: if verse_tag:
verse_tag = verse_tag.upper() verse_tag = verse_tag.upper()
self.service_item_type = ServiceItemType.Text self.service_item_type = ServiceItemType.Text
title = title.split(u'\n')[0] title = raw_slide[:30].split(u'\n')[0]
self._raw_frames.append( self._raw_frames.append(
{u'title': title, u'raw_slide': raw_slide, u'verseTag': verse_tag}) {u'title': title, u'raw_slide': raw_slide, u'verseTag': verse_tag})
self._new_item() self._new_item()

View File

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
# 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:``settings`` module provides a thin wrapper for QSettings, which OpenLP
uses to manage settings persistence.
"""
import logging
from PyQt4 import QtCore
log = logging.getLogger()
class Settings(QtCore.QSettings):
"""
Class to wrap QSettings.
* Exposes all the methods of QSettings.
* Adds functionality for OpenLP Portable. If the ``defaultFormat`` is set to
``IniFormat``, and the path to the Ini file is set using ``setFilename``,
then the Settings constructor (without any arguments) will create a Settings
object for accessing settings stored in that Ini file.
"""
__filePath = u''
@staticmethod
def setFilename(iniFile):
"""
Sets the complete path to an Ini file to be used by Settings objects.
Does not affect existing Settings objects.
"""
Settings.__filePath = iniFile
def __init__(self, *args):
if not args and Settings.__filePath and (Settings.defaultFormat() ==
Settings.IniFormat):
QtCore.QSettings.__init__(self, Settings.__filePath,
Settings.IniFormat)
else:
QtCore.QSettings.__init__(self, *args)

View File

@ -34,6 +34,7 @@ import os
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib.settings import Settings
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
class SettingsManager(object): class SettingsManager(object):
@ -58,7 +59,7 @@ class SettingsManager(object):
name = u'last directory %d' % num name = u'last directory %d' % num
else: else:
name = u'last directory' name = u'last directory'
last_dir = unicode(QtCore.QSettings().value( last_dir = unicode(Settings().value(
section + u'/' + name, QtCore.QVariant(u'')).toString()) section + u'/' + name, QtCore.QVariant(u'')).toString())
return last_dir return last_dir
@ -81,7 +82,7 @@ class SettingsManager(object):
name = u'last directory %d' % num name = u'last directory %d' % num
else: else:
name = u'last directory' name = u'last directory'
QtCore.QSettings().setValue( Settings().setValue(
section + u'/' + name, QtCore.QVariant(directory)) section + u'/' + name, QtCore.QVariant(directory))
@staticmethod @staticmethod
@ -98,7 +99,7 @@ class SettingsManager(object):
``list`` ``list``
The list of values to save. The list of values to save.
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(section) settings.beginGroup(section)
old_count = settings.value( old_count = settings.value(
u'%s count' % name, QtCore.QVariant(0)).toInt()[0] u'%s count' % name, QtCore.QVariant(0)).toInt()[0]
@ -124,7 +125,7 @@ class SettingsManager(object):
``name`` ``name``
The name of the list. The name of the list.
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(section) settings.beginGroup(section)
list_count = settings.value( list_count = settings.value(
u'%s count' % name, QtCore.QVariant(0)).toInt()[0] u'%s count' % name, QtCore.QVariant(0)).toInt()[0]

View File

@ -80,6 +80,10 @@ class UiStrings(object):
self.Help = translate('OpenLP.Ui', 'Help') self.Help = translate('OpenLP.Ui', 'Help')
self.Hours = translate('OpenLP.Ui', 'h', self.Hours = translate('OpenLP.Ui', 'h',
'The abbreviated unit for hours') 'The abbreviated unit for hours')
self.IFdSs = translate('OpenLP.Ui', 'Invalid Folder Selected',
'Singular')
self.IFSs = translate('OpenLP.Ui', 'Invalid File Selected', 'Singular')
self.IFSp = translate('OpenLP.Ui', 'Invalid Files Selected', 'Plural')
self.Image = translate('OpenLP.Ui', 'Image') self.Image = translate('OpenLP.Ui', 'Image')
self.Import = translate('OpenLP.Ui', 'Import') self.Import = translate('OpenLP.Ui', 'Import')
self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:') self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import build_icon, translate from openlp.core.lib import build_icon, translate
from openlp.core.lib.ui import UiStrings, create_button, create_button_box from openlp.core.lib.ui import UiStrings, create_button, create_button_box

View File

@ -31,10 +31,16 @@ from datetime import datetime, timedelta
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
import logging
import os
import sys
from openlp.core.lib import SettingsTab, translate, build_icon, Receiver from openlp.core.lib import SettingsTab, translate, build_icon, Receiver
from openlp.core.lib.settings import Settings
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.core.utils import get_images_filter, AppLocation
from openlp.core.lib import SlideLimits from openlp.core.lib import SlideLimits
from openlp.core.utils import get_images_filter
log = logging.getLogger(__name__)
class AdvancedTab(SettingsTab): class AdvancedTab(SettingsTab):
""" """
@ -59,6 +65,7 @@ class AdvancedTab(SettingsTab):
'#strftime-strptime-behavior for more information.')) '#strftime-strptime-behavior for more information.'))
self.defaultImage = u':/graphics/openlp-splash-screen.png' self.defaultImage = u':/graphics/openlp-splash-screen.png'
self.defaultColor = u'#ffffff' self.defaultColor = u'#ffffff'
self.dataExists = False
self.iconPath = u':/system/system_settings.png' self.iconPath = u':/system/system_settings.png'
advanced_translated = translate('OpenLP.AdvancedTab', 'Advanced') advanced_translated = translate('OpenLP.AdvancedTab', 'Advanced')
SettingsTab.__init__(self, parent, u'Advanced', advanced_translated) SettingsTab.__init__(self, parent, u'Advanced', advanced_translated)
@ -151,6 +158,71 @@ class AdvancedTab(SettingsTab):
self.serviceNameLayout.addRow(self.serviceNameExampleLabel, self.serviceNameLayout.addRow(self.serviceNameExampleLabel,
self.serviceNameExample) self.serviceNameExample)
self.leftLayout.addWidget(self.serviceNameGroupBox) self.leftLayout.addWidget(self.serviceNameGroupBox)
# Data Directory
self.dataDirectoryGroupBox = QtGui.QGroupBox(self.leftColumn)
self.dataDirectoryGroupBox.setObjectName(u'dataDirectoryGroupBox')
self.dataDirectoryLayout = QtGui.QFormLayout(self.dataDirectoryGroupBox)
self.dataDirectoryLayout.setObjectName(u'dataDirectoryLayout')
self.dataDirectoryCurrentLabel = QtGui.QLabel(self.dataDirectoryGroupBox)
self.dataDirectoryCurrentLabel.setObjectName(
u'dataDirectoryCurrentLabel')
self.dataDirectoryLabel = QtGui.QLabel(self.dataDirectoryGroupBox)
self.dataDirectoryLabel.setObjectName(u'dataDirectoryLabel')
self.dataDirectoryNewLabel = QtGui.QLabel(self.dataDirectoryGroupBox)
self.dataDirectoryNewLabel.setObjectName(u'dataDirectoryCurrentLabel')
self.newDataDirectoryEdit = QtGui.QLineEdit(self.dataDirectoryGroupBox)
self.newDataDirectoryEdit.setObjectName(u'newDataDirectoryEdit')
self.newDataDirectoryEdit.setReadOnly(True)
self.newDataDirectoryHasFilesLabel = QtGui.QLabel(
self.dataDirectoryGroupBox)
self.newDataDirectoryHasFilesLabel.setObjectName(
u'newDataDirectoryHasFilesLabel')
self.newDataDirectoryHasFilesLabel.setWordWrap(True)
self.dataDirectoryBrowseButton = QtGui.QToolButton(
self.dataDirectoryGroupBox)
self.dataDirectoryBrowseButton.setObjectName(
u'dataDirectoryBrowseButton')
self.dataDirectoryBrowseButton.setIcon(
build_icon(u':/general/general_open.png'))
self.dataDirectoryDefaultButton = QtGui.QToolButton(
self.dataDirectoryGroupBox)
self.dataDirectoryDefaultButton.setObjectName(
u'dataDirectoryDefaultButton')
self.dataDirectoryDefaultButton.setIcon(
build_icon(u':/general/general_revert.png'))
self.dataDirectoryCancelButton = QtGui.QToolButton(
self.dataDirectoryGroupBox)
self.dataDirectoryCancelButton.setObjectName(
u'dataDirectoryCancelButton')
self.dataDirectoryCancelButton.setIcon(
build_icon(u':/general/general_delete.png'))
self.newDataDirectoryLabelHBox = QtGui.QHBoxLayout()
self.newDataDirectoryLabelHBox.setObjectName(
u'newDataDirectoryLabelHBox')
self.newDataDirectoryLabelHBox.addWidget(self.newDataDirectoryEdit)
self.newDataDirectoryLabelHBox.addWidget(
self.dataDirectoryBrowseButton)
self.newDataDirectoryLabelHBox.addWidget(
self.dataDirectoryDefaultButton)
self.dataDirectoryCopyCheckHBox = QtGui.QHBoxLayout()
self.dataDirectoryCopyCheckHBox.setObjectName(
u'dataDirectoryCopyCheckHBox')
self.dataDirectoryCopyCheckBox = QtGui.QCheckBox(
self.dataDirectoryGroupBox)
self.dataDirectoryCopyCheckBox.setObjectName(
u'dataDirectoryCopyCheckBox')
self.dataDirectoryCopyCheckHBox.addWidget(
self.dataDirectoryCopyCheckBox)
self.dataDirectoryCopyCheckHBox.addStretch()
self.dataDirectoryCopyCheckHBox.addWidget(
self.dataDirectoryCancelButton)
self.dataDirectoryLayout.addRow(self.dataDirectoryCurrentLabel,
self.dataDirectoryLabel)
self.dataDirectoryLayout.addRow(self.dataDirectoryNewLabel,
self.newDataDirectoryLabelHBox)
self.dataDirectoryLayout.addRow(self.dataDirectoryCopyCheckHBox)
self.dataDirectoryLayout.addRow(self.newDataDirectoryHasFilesLabel)
self.leftLayout.addWidget(self.dataDirectoryGroupBox)
self.leftLayout.addStretch() self.leftLayout.addStretch()
# Default Image # Default Image
self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn) self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn)
@ -219,7 +291,6 @@ class AdvancedTab(SettingsTab):
self.x11Layout.addWidget(self.x11BypassCheckBox) self.x11Layout.addWidget(self.x11BypassCheckBox)
self.rightLayout.addWidget(self.x11GroupBox) self.rightLayout.addWidget(self.x11GroupBox)
self.rightLayout.addStretch() self.rightLayout.addStretch()
self.shouldUpdateServiceNameExample = False self.shouldUpdateServiceNameExample = False
QtCore.QObject.connect(self.serviceNameCheckBox, QtCore.QObject.connect(self.serviceNameCheckBox,
QtCore.SIGNAL(u'toggled(bool)'), self.serviceNameCheckBoxToggled) QtCore.SIGNAL(u'toggled(bool)'), self.serviceNameCheckBoxToggled)
@ -243,6 +314,18 @@ class AdvancedTab(SettingsTab):
QtCore.SIGNAL(u'clicked()'), self.onDefaultRevertButtonClicked) QtCore.SIGNAL(u'clicked()'), self.onDefaultRevertButtonClicked)
QtCore.QObject.connect(self.x11BypassCheckBox, QtCore.QObject.connect(self.x11BypassCheckBox,
QtCore.SIGNAL(u'toggled(bool)'), self.onX11BypassCheckBoxToggled) QtCore.SIGNAL(u'toggled(bool)'), self.onX11BypassCheckBoxToggled)
QtCore.QObject.connect(self.dataDirectoryBrowseButton,
QtCore.SIGNAL(u'clicked()'),
self.onDataDirectoryBrowseButtonClicked)
QtCore.QObject.connect(self.dataDirectoryDefaultButton,
QtCore.SIGNAL(u'clicked()'),
self.onDataDirectoryDefaultButtonClicked)
QtCore.QObject.connect(self.dataDirectoryCancelButton,
QtCore.SIGNAL(u'clicked()'),
self.onDataDirectoryCancelButtonClicked)
QtCore.QObject.connect(self.dataDirectoryCopyCheckBox,
QtCore.SIGNAL(u'toggled(bool)'),
self.onDataDirectoryCopyCheckBoxToggled)
QtCore.QObject.connect(self.endSlideRadioButton, QtCore.QObject.connect(self.endSlideRadioButton,
QtCore.SIGNAL(u'clicked()'), self.onEndSlideButtonClicked) QtCore.SIGNAL(u'clicked()'), self.onEndSlideButtonClicked)
QtCore.QObject.connect(self.wrapSlideRadioButton, QtCore.QObject.connect(self.wrapSlideRadioButton,
@ -257,6 +340,8 @@ class AdvancedTab(SettingsTab):
self.tabTitleVisible = UiStrings().Advanced self.tabTitleVisible = UiStrings().Advanced
self.uiGroupBox.setTitle( self.uiGroupBox.setTitle(
translate('OpenLP.AdvancedTab', 'UI Settings')) translate('OpenLP.AdvancedTab', 'UI Settings'))
self.dataDirectoryGroupBox.setTitle(
translate('OpenLP.AdvancedTab', 'Data Location'))
self.recentLabel.setText( self.recentLabel.setText(
translate('OpenLP.AdvancedTab', translate('OpenLP.AdvancedTab',
'Number of recent files to display:')) 'Number of recent files to display:'))
@ -320,6 +405,32 @@ class AdvancedTab(SettingsTab):
'Browse for an image file to display.')) 'Browse for an image file to display.'))
self.defaultRevertButton.setToolTip(translate('OpenLP.AdvancedTab', self.defaultRevertButton.setToolTip(translate('OpenLP.AdvancedTab',
'Revert to the default OpenLP logo.')) 'Revert to the default OpenLP logo.'))
self.dataDirectoryCurrentLabel.setText(translate('OpenLP.AdvancedTab',
'Current path:'))
self.dataDirectoryNewLabel.setText(translate('OpenLP.AdvancedTab',
'Custom path:'))
self.dataDirectoryBrowseButton.setToolTip(
translate('OpenLP.AdvancedTab',
'Browse for new data file location.'))
self.dataDirectoryDefaultButton.setToolTip(
translate('OpenLP.AdvancedTab',
'Set the data location to the default.'))
self.dataDirectoryCancelButton.setText(
translate('OpenLP.AdvancedTab',
'Cancel'))
self.dataDirectoryCancelButton.setToolTip(
translate('OpenLP.AdvancedTab',
'Cancel OpenLP data directory location change.'))
self.dataDirectoryCopyCheckBox.setText(
translate('OpenLP.AdvancedTab',
'Copy data to new location.'))
self.dataDirectoryCopyCheckBox.setToolTip(
translate('OpenLP.AdvancedTab',
'Copy the OpenLP data files to the new location.'))
self.newDataDirectoryHasFilesLabel.setText(
translate('OpenLP.AdvancedTab',
'<strong>WARNING:</strong> New data directory location contains '
'OpenLP data files. These files WILL be replaced during a copy.'))
self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab', self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab',
'X11')) 'X11'))
self.x11BypassCheckBox.setText(translate('OpenLP.AdvancedTab', self.x11BypassCheckBox.setText(translate('OpenLP.AdvancedTab',
@ -340,12 +451,12 @@ class AdvancedTab(SettingsTab):
""" """
Load settings from disk. Load settings from disk.
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
# The max recent files value does not have an interface and so never # The max recent files value does not have an interface and so never
# gets actually stored in the settings therefore the default value of # gets actually stored in the settings therefore the default value of
# 20 will always be used. # 20 will always be used.
self.recentSpinBox.setMaximum(QtCore.QSettings().value( self.recentSpinBox.setMaximum(Settings().value(
u'max recent files', QtCore.QVariant(20)).toInt()[0]) u'max recent files', QtCore.QVariant(20)).toInt()[0])
self.recentSpinBox.setValue(settings.value(u'recent file count', self.recentSpinBox.setValue(settings.value(u'recent file count',
QtCore.QVariant(4)).toInt()[0]) QtCore.QVariant(4)).toInt()[0])
@ -397,6 +508,40 @@ class AdvancedTab(SettingsTab):
else: else:
self.nextItemRadioButton.setChecked(True) self.nextItemRadioButton.setChecked(True)
settings.endGroup() settings.endGroup()
self.dataDirectoryCopyCheckBox.hide()
self.newDataDirectoryHasFilesLabel.hide()
self.dataDirectoryCancelButton.hide()
# Since data location can be changed, make sure the path is present.
self.currentDataPath = AppLocation.get_data_path()
if not os.path.exists(self.currentDataPath):
log.error(u'Data path not found %s' % self.currentDataPath)
answer = QtGui.QMessageBox.critical(self,
translate('OpenLP.AdvancedTab',
'Data Directory Error'),
translate('OpenLP.AdvancedTab',
'OpenLP data directory was not found\n\n%s\n\n'
'This data directory was previously changed from the OpenLP '
'default location. If the new location was on removable '
'media, that media needs to be made available.\n\n'
'Click "No" to stop loading OpenLP. allowing you to fix '
'the the problem.\n\n'
'Click "Yes" to reset the data directory to the default '
'location.' % self.currentDataPath),
QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No),
QtGui.QMessageBox.No)
if answer == QtGui.QMessageBox.No:
log.info(u'User requested termination')
Receiver.send_message(u'cleanup')
sys.exit()
# Set data location to default.
settings.remove(u'advanced/data path')
self.currentDataPath = AppLocation.get_data_path()
log.warning(u'User requested data path set to default %s'
% self.currentDataPath)
self.dataDirectoryLabel.setText(os.path.abspath(
self.currentDataPath))
self.defaultColorButton.setStyleSheet( self.defaultColorButton.setStyleSheet(
u'background-color: %s' % self.defaultColor) u'background-color: %s' % self.defaultColor)
@ -404,7 +549,7 @@ class AdvancedTab(SettingsTab):
""" """
Save settings to disk. Save settings to disk.
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
settings.setValue(u'default service enabled', settings.setValue(u'default service enabled',
self.serviceNameCheckBox.isChecked()) self.serviceNameCheckBox.isChecked())
@ -446,6 +591,11 @@ class AdvancedTab(SettingsTab):
self.displayChanged = False self.displayChanged = False
Receiver.send_message(u'slidecontroller_update_slide_limits') Receiver.send_message(u'slidecontroller_update_slide_limits')
def cancel(self):
# Dialogue was cancelled, remove any pending data path change.
self.onDataDirectoryCancelButtonClicked()
SettingsTab.cancel(self)
def serviceNameCheckBoxToggled(self, default_service_enabled): def serviceNameCheckBoxToggled(self, default_service_enabled):
self.serviceNameDay.setEnabled(default_service_enabled) self.serviceNameDay.setEnabled(default_service_enabled)
time_enabled = default_service_enabled and \ time_enabled = default_service_enabled and \
@ -507,6 +657,122 @@ class AdvancedTab(SettingsTab):
self.defaultFileEdit.setText(filename) self.defaultFileEdit.setText(filename)
self.defaultFileEdit.setFocus() self.defaultFileEdit.setFocus()
def onDataDirectoryBrowseButtonClicked(self):
"""
Browse for a new data directory location.
"""
old_root_path = unicode(self.dataDirectoryLabel.text())
# Get the new directory location.
new_data_path = unicode(QtGui.QFileDialog.getExistingDirectory(self,
translate('OpenLP.AdvancedTab',
'Select Data Directory Location'), old_root_path,
options = QtGui.QFileDialog.ShowDirsOnly))
# Set the new data path.
if new_data_path:
if self.currentDataPath.lower() == new_data_path.lower():
self.onDataDirectoryCancelButtonClicked()
return
else:
return
# Make sure they want to change the data.
answer = QtGui.QMessageBox.question(self,
translate('OpenLP.AdvancedTab', 'Confirm Data Directory Change'),
translate('OpenLP.AdvancedTab',
'Are you sure you want to change the location of the OpenLP '
'data directory to:\n\n%s\n\n'
'The data directory will be changed when OpenLP is closed.'
% new_data_path),
QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No),
QtGui.QMessageBox.No)
if answer != QtGui.QMessageBox.Yes:
return
# Check if data already exists here.
self.checkDataOverwrite(new_data_path)
# Save the new location.
Receiver.send_message(u'set_new_data_path', new_data_path)
self.newDataDirectoryEdit.setText(new_data_path)
self.dataDirectoryCancelButton.show()
def onDataDirectoryDefaultButtonClicked(self):
"""
Re-set the data directory location to the 'default' location.
"""
new_data_path = AppLocation.get_directory(AppLocation.DataDir)
if self.currentDataPath.lower() != new_data_path.lower():
# Make sure they want to change the data location back to the default.
answer = QtGui.QMessageBox.question(self,
translate('OpenLP.AdvancedTab', 'Reset Data Directory'),
translate('OpenLP.AdvancedTab',
'Are you sure you want to change the location of the OpenLP '
'data directory to the default location?\n\n'
'This location will be used after OpenLP is closed.'),
QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No),
QtGui.QMessageBox.No)
if answer != QtGui.QMessageBox.Yes:
return
self.checkDataOverwrite(new_data_path)
# Save the new location.
Receiver.send_message(u'set_new_data_path', new_data_path)
self.newDataDirectoryEdit.setText(os.path.abspath(new_data_path))
self.dataDirectoryCancelButton.show()
else:
# We cancel the change in case user changed their mind.
self.onDataDirectoryCancelButtonClicked()
def onDataDirectoryCopyCheckBoxToggled(self):
Receiver.send_message(u'set_copy_data',
self.dataDirectoryCopyCheckBox.isChecked())
if self.dataExists:
if self.dataDirectoryCopyCheckBox.isChecked():
self.newDataDirectoryHasFilesLabel.show()
else:
self.newDataDirectoryHasFilesLabel.hide()
def checkDataOverwrite(self, data_path ):
test_path = os.path.join(data_path, u'songs')
self.dataDirectoryCopyCheckBox.show()
if os.path.exists(test_path):
self.dataExists = True
# Check is they want to replace existing data.
answer = QtGui.QMessageBox.warning(self,
translate('OpenLP.AdvancedTab', 'Overwrite Existing Data'),
translate('OpenLP.AdvancedTab',
'WARNING: \n\n'
'The location you have selected \n\n%s\n\n'
'appears to contain OpenLP data files. Do you wish to replace '
'these files with the current data files?'
% os.path.abspath(data_path,)),
QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No),
QtGui.QMessageBox.No)
if answer == QtGui.QMessageBox.Yes:
self.dataDirectoryCopyCheckBox.setChecked(True)
self.newDataDirectoryHasFilesLabel.show()
else:
self.dataDirectoryCopyCheckBox.setChecked(False)
self.newDataDirectoryHasFilesLabel.hide()
else:
self.dataExists = False
self.dataDirectoryCopyCheckBox.setChecked(True)
self.newDataDirectoryHasFilesLabel.hide()
def onDataDirectoryCancelButtonClicked(self):
"""
Cancel the data directory location change
"""
self.newDataDirectoryEdit.clear()
self.dataDirectoryCopyCheckBox.setChecked(False)
Receiver.send_message(u'set_new_data_path', u'')
Receiver.send_message(u'set_copy_data', False)
self.dataDirectoryCopyCheckBox.hide()
self.dataDirectoryCancelButton.hide()
self.newDataDirectoryHasFilesLabel.hide()
def onDefaultRevertButtonClicked(self): def onDefaultRevertButtonClicked(self):
self.defaultFileEdit.setText(u':/graphics/openlp-splash-screen.png') self.defaultFileEdit.setText(u':/graphics/openlp-splash-screen.png')
self.defaultFileEdit.setFocus() self.defaultFileEdit.setFocus()

View File

@ -39,6 +39,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, PluginStatus, Receiver, build_icon, \ from openlp.core.lib import translate, PluginStatus, Receiver, build_icon, \
check_directory_exists check_directory_exists
from openlp.core.lib.settings import Settings
from openlp.core.utils import get_web_page, AppLocation from openlp.core.utils import get_web_page, AppLocation
from firsttimewizard import Ui_FirstTimeWizard, FirstTimePage from firsttimewizard import Ui_FirstTimeWizard, FirstTimePage
@ -116,7 +117,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
check_directory_exists(os.path.join(gettempdir(), u'openlp')) check_directory_exists(os.path.join(gettempdir(), u'openlp'))
self.noInternetFinishButton.setVisible(False) self.noInternetFinishButton.setVisible(False)
# Check if this is a re-run of the wizard. # Check if this is a re-run of the wizard.
self.hasRunWizard = QtCore.QSettings().value( self.hasRunWizard = Settings().value(
u'general/has run wizard', QtCore.QVariant(False)).toBool() u'general/has run wizard', QtCore.QVariant(False)).toBool()
# Sort out internet access for downloads # Sort out internet access for downloads
if self.webAccess: if self.webAccess:
@ -209,7 +210,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
index = self.themeComboBox.findText(theme) index = self.themeComboBox.findText(theme)
if index == -1: if index == -1:
self.themeComboBox.addItem(theme) self.themeComboBox.addItem(theme)
default_theme = unicode(QtCore.QSettings().value( default_theme = unicode(Settings().value(
u'themes/global theme', u'themes/global theme',
QtCore.QVariant(u'')).toString()) QtCore.QVariant(u'')).toString())
# Pre-select the current default theme. # Pre-select the current default theme.
@ -261,7 +262,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
self._performWizard() self._performWizard()
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
QtCore.QSettings().setValue(u'general/has run wizard', Settings().setValue(u'general/has run wizard',
QtCore.QVariant(True)) QtCore.QVariant(True))
self.close() self.close()
@ -460,16 +461,16 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
os.path.join(themes_destination, theme)) os.path.join(themes_destination, theme))
# Set Default Display # Set Default Display
if self.displayComboBox.currentIndex() != -1: if self.displayComboBox.currentIndex() != -1:
QtCore.QSettings().setValue(u'General/monitor', Settings().setValue(u'General/monitor',
QtCore.QVariant(self.displayComboBox.currentIndex())) QtCore.QVariant(self.displayComboBox.currentIndex()))
self.screens.set_current_display( self.screens.set_current_display(
self.displayComboBox.currentIndex()) self.displayComboBox.currentIndex())
# Set Global Theme # Set Global Theme
if self.themeComboBox.currentIndex() != -1: if self.themeComboBox.currentIndex() != -1:
QtCore.QSettings().setValue(u'themes/global theme', Settings().setValue(u'themes/global theme',
QtCore.QVariant(self.themeComboBox.currentText())) QtCore.QVariant(self.themeComboBox.currentText()))
def _setPluginStatus(self, field, tag): def _setPluginStatus(self, field, tag):
status = PluginStatus.Active if field.checkState() \ status = PluginStatus.Active if field.checkState() \
== QtCore.Qt.Checked else PluginStatus.Inactive == QtCore.Qt.Checked else PluginStatus.Inactive
QtCore.QSettings().setValue(tag, QtCore.QVariant(status)) Settings().setValue(tag, QtCore.QVariant(status))

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, Receiver, translate from openlp.core.lib import SettingsTab, Receiver, translate
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.core.lib.settings import Settings
from openlp.core.ui import ScreenList from openlp.core.ui import ScreenList
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -265,7 +266,7 @@ class GeneralTab(SettingsTab):
""" """
Load the settings to populate the form Load the settings to populate the form
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
self.monitorComboBox.clear() self.monitorComboBox.clear()
self.monitorComboBox.addItems(self.screens.get_screen_list()) self.monitorComboBox.addItems(self.screens.get_screen_list())
@ -327,7 +328,7 @@ class GeneralTab(SettingsTab):
""" """
Save the settings from the form Save the settings from the form
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
settings.setValue(u'monitor', settings.setValue(u'monitor',
QtCore.QVariant(self.monitorComboBox.currentIndex())) QtCore.QVariant(self.monitorComboBox.currentIndex()))

View File

@ -38,6 +38,7 @@ from PyQt4.phonon import Phonon
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \ from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \
translate, PluginManager, expand_tags translate, PluginManager, expand_tags
from openlp.core.lib.theme import BackgroundType from openlp.core.lib.theme import BackgroundType
from openlp.core.lib.settings import Settings
from openlp.core.ui import HideMode, ScreenList, AlertLocation from openlp.core.ui import HideMode, ScreenList, AlertLocation
@ -100,9 +101,8 @@ class Display(QtGui.QGraphicsView):
self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal, self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal,
QtCore.Qt.ScrollBarAlwaysOff) QtCore.Qt.ScrollBarAlwaysOff)
def resizeEvent(self, ev): def resizeEvent(self, event):
self.webView.setGeometry(0, 0, self.webView.setGeometry(0, 0, self.width(), self.height())
self.width(), self.height())
def isWebLoaded(self): def isWebLoaded(self):
""" """
@ -120,7 +120,6 @@ class MainDisplay(Display):
Display.__init__(self, parent, live, controller) Display.__init__(self, parent, live, controller)
self.imageManager = imageManager self.imageManager = imageManager
self.screens = ScreenList() self.screens = ScreenList()
self.plugins = PluginManager.get_instance().plugins
self.rebuildCSS = False self.rebuildCSS = False
self.hideMode = None self.hideMode = None
self.override = {} self.override = {}
@ -131,10 +130,11 @@ class MainDisplay(Display):
else: else:
self.audioPlayer = None self.audioPlayer = None
self.firstTime = True self.firstTime = True
self.webLoaded = True
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
windowFlags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | \ windowFlags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | \
QtCore.Qt.WindowStaysOnTopHint QtCore.Qt.WindowStaysOnTopHint
if QtCore.QSettings().value(u'advanced/x11 bypass wm', if Settings().value(u'advanced/x11 bypass wm',
QtCore.QVariant(True)).toBool(): QtCore.QVariant(True)).toBool():
windowFlags |= QtCore.Qt.X11BypassWindowManagerHint windowFlags |= QtCore.Qt.X11BypassWindowManagerHint
# FIXME: QtCore.Qt.SplashScreen is workaround to make display screen # FIXME: QtCore.Qt.SplashScreen is workaround to make display screen
@ -195,15 +195,15 @@ class MainDisplay(Display):
Display.setup(self) Display.setup(self)
if self.isLive: if self.isLive:
# Build the initial frame. # Build the initial frame.
image_file = QtCore.QSettings().value(u'advanced/default image',
QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\
.toString()
background_color = QtGui.QColor() background_color = QtGui.QColor()
background_color.setNamedColor(QtCore.QSettings().value( background_color.setNamedColor(Settings().value(
u'advanced/default color', u'advanced/default color',
QtCore.QVariant(u'#ffffff')).toString()) QtCore.QVariant(u'#ffffff')).toString())
if not background_color.isValid(): if not background_color.isValid():
background_color = QtCore.Qt.white background_color = QtCore.Qt.white
image_file = Settings().value(u'advanced/default image',
QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\
.toString()
splash_image = QtGui.QImage(image_file) splash_image = QtGui.QImage(image_file)
self.initialFrame = QtGui.QImage( self.initialFrame = QtGui.QImage(
self.screen[u'size'].width(), self.screen[u'size'].width(),
@ -290,10 +290,10 @@ class MainDisplay(Display):
def image(self, name): def image(self, name):
""" """
Add an image as the background. The image has already been added Add an image as the background. The image has already been added to the
to the cache. cache.
``Image`` ``name``
The name of the image to be displayed. The name of the image to be displayed.
""" """
log.debug(u'image to display') log.debug(u'image to display')
@ -352,7 +352,7 @@ class MainDisplay(Display):
# Single screen active # Single screen active
if self.screens.display_count == 1: if self.screens.display_count == 1:
# Only make visible if setting enabled. # Only make visible if setting enabled.
if QtCore.QSettings().value(u'general/display on monitor', if Settings().value(u'general/display on monitor',
QtCore.QVariant(True)).toBool(): QtCore.QVariant(True)).toBool():
self.setVisible(True) self.setVisible(True)
else: else:
@ -401,7 +401,7 @@ class MainDisplay(Display):
self.footer(serviceItem.foot_text) self.footer(serviceItem.foot_text)
# if was hidden keep it hidden # if was hidden keep it hidden
if self.hideMode and self.isLive and not serviceItem.is_media(): if self.hideMode and self.isLive and not serviceItem.is_media():
if QtCore.QSettings().value(u'general/auto unblank', if Settings().value(u'general/auto unblank',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
Receiver.send_message(u'slidecontroller_live_unblank') Receiver.send_message(u'slidecontroller_live_unblank')
else: else:
@ -425,7 +425,7 @@ class MainDisplay(Display):
log.debug(u'hideDisplay mode = %d', mode) log.debug(u'hideDisplay mode = %d', mode)
if self.screens.display_count == 1: if self.screens.display_count == 1:
# Only make visible if setting enabled. # Only make visible if setting enabled.
if not QtCore.QSettings().value(u'general/display on monitor', if not Settings().value(u'general/display on monitor',
QtCore.QVariant(True)).toBool(): QtCore.QVariant(True)).toBool():
return return
if mode == HideMode.Screen: if mode == HideMode.Screen:
@ -450,7 +450,7 @@ class MainDisplay(Display):
log.debug(u'showDisplay') log.debug(u'showDisplay')
if self.screens.display_count == 1: if self.screens.display_count == 1:
# Only make visible if setting enabled. # Only make visible if setting enabled.
if not QtCore.QSettings().value(u'general/display on monitor', if not Settings().value(u'general/display on monitor',
QtCore.QVariant(True)).toBool(): QtCore.QVariant(True)).toBool():
return return
self.frame.evaluateJavaScript('show_blank("show");') self.frame.evaluateJavaScript('show_blank("show");')
@ -465,7 +465,7 @@ class MainDisplay(Display):
""" """
Hide mouse cursor when moved over display. Hide mouse cursor when moved over display.
""" """
if QtCore.QSettings().value(u'advanced/hide mouse', if Settings().value(u'advanced/hide mouse',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
self.setCursor(QtCore.Qt.BlankCursor) self.setCursor(QtCore.Qt.BlankCursor)
self.frame.evaluateJavaScript('document.body.style.cursor = "none"') self.frame.evaluateJavaScript('document.body.style.cursor = "none"')

View File

@ -29,6 +29,8 @@ import logging
import os import os
import sys import sys
import shutil import shutil
from distutils import dir_util
from distutils.errors import DistutilsFileError
from tempfile import gettempdir from tempfile import gettempdir
import time import time
from datetime import datetime from datetime import datetime
@ -38,6 +40,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \ from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \
PluginManager, Receiver, translate, ImageManager, PluginStatus PluginManager, Receiver, translate, ImageManager, PluginStatus
from openlp.core.lib.ui import UiStrings, create_action from openlp.core.lib.ui import UiStrings, create_action
from openlp.core.lib.settings import Settings
from openlp.core.lib import SlideLimits from openlp.core.lib import SlideLimits
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \ from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \
ThemeManager, SlideController, PluginForm, MediaDockManager, \ ThemeManager, SlideController, PluginForm, MediaDockManager, \
@ -100,12 +103,12 @@ class Ui_MainWindow(object):
# Create slide controllers # Create slide controllers
self.previewController = SlideController(self) self.previewController = SlideController(self)
self.liveController = SlideController(self, True) self.liveController = SlideController(self, True)
previewVisible = QtCore.QSettings().value( previewVisible = Settings().value(
u'user interface/preview panel', QtCore.QVariant(True)).toBool() u'user interface/preview panel', QtCore.QVariant(True)).toBool()
self.previewController.panel.setVisible(previewVisible) self.previewController.panel.setVisible(previewVisible)
liveVisible = QtCore.QSettings().value(u'user interface/live panel', liveVisible = Settings().value(u'user interface/live panel',
QtCore.QVariant(True)).toBool() QtCore.QVariant(True)).toBool()
panelLocked = QtCore.QSettings().value(u'user interface/lock panel', panelLocked = Settings().value(u'user interface/lock panel',
QtCore.QVariant(False)).toBool() QtCore.QVariant(False)).toBool()
self.liveController.panel.setVisible(liveVisible) self.liveController.panel.setVisible(liveVisible)
# Create menu # Create menu
@ -582,6 +585,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
# Once settings are loaded update the menu with the recent files. # Once settings are loaded update the menu with the recent files.
self.updateRecentFilesMenu() self.updateRecentFilesMenu()
self.pluginForm = PluginForm(self) self.pluginForm = PluginForm(self)
self.newDataPath = u''
self.copyData = False
# Set up signals and slots # Set up signals and slots
QtCore.QObject.connect(self.importThemeItem, QtCore.QObject.connect(self.importThemeItem,
QtCore.SIGNAL(u'triggered()'), QtCore.SIGNAL(u'triggered()'),
@ -634,6 +639,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged) QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'mainwindow_status_text'), self.showStatusMessage) QtCore.SIGNAL(u'mainwindow_status_text'), self.showStatusMessage)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'cleanup'), self.cleanUp)
# Media Manager # Media Manager
QtCore.QObject.connect(self.mediaToolBox, QtCore.QObject.connect(self.mediaToolBox,
QtCore.SIGNAL(u'currentChanged(int)'), self.onMediaToolBoxChanged) QtCore.SIGNAL(u'currentChanged(int)'), self.onMediaToolBoxChanged)
@ -646,6 +653,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_information_message'), QtCore.SIGNAL(u'openlp_information_message'),
self.onInformationMessage) self.onInformationMessage)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'set_new_data_path'), self.setNewDataPath)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'set_copy_data'), self.setCopyData)
# warning cyclic dependency # warning cyclic dependency
# renderer needs to call ThemeManager and # renderer needs to call ThemeManager and
# ThemeManager needs to call Renderer # ThemeManager needs to call Renderer
@ -686,9 +697,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.previewController.screenSizeChanged() self.previewController.screenSizeChanged()
self.liveController.screenSizeChanged() self.liveController.screenSizeChanged()
log.info(u'Load data from Settings') log.info(u'Load data from Settings')
if QtCore.QSettings().value(u'advanced/save current plugin', if Settings().value(u'advanced/save current plugin',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
savedPlugin = QtCore.QSettings().value( savedPlugin = Settings().value(
u'advanced/current media plugin', QtCore.QVariant()).toInt()[0] u'advanced/current media plugin', QtCore.QVariant()).toInt()[0]
if savedPlugin != -1: if savedPlugin != -1:
self.mediaToolBox.setCurrentIndex(savedPlugin) self.mediaToolBox.setCurrentIndex(savedPlugin)
@ -740,11 +751,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
if not isinstance(filename, unicode): if not isinstance(filename, unicode):
filename = unicode(filename, sys.getfilesystemencoding()) filename = unicode(filename, sys.getfilesystemencoding())
self.serviceManagerContents.loadFile(filename) self.serviceManagerContents.loadFile(filename)
elif QtCore.QSettings().value( elif Settings().value(
self.generalSettingsSection + u'/auto open', self.generalSettingsSection + u'/auto open',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
self.serviceManagerContents.loadLastFile() self.serviceManagerContents.loadLastFile()
view_mode = QtCore.QSettings().value(u'%s/view mode' % \ view_mode = Settings().value(u'%s/view mode' % \
self.generalSettingsSection, u'default').toString() self.generalSettingsSection, u'default').toString()
if view_mode == u'default': if view_mode == u'default':
self.modeDefaultItem.setChecked(True) self.modeDefaultItem.setChecked(True)
@ -822,7 +833,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
""" """
Check and display message if screen blank on setup. Check and display message if screen blank on setup.
""" """
settings = QtCore.QSettings() settings = Settings()
self.liveController.mainDisplaySetBackground() self.liveController.mainDisplaySetBackground()
if settings.value(u'%s/screen blank' % self.generalSettingsSection, if settings.value(u'%s/screen blank' % self.generalSettingsSection,
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
@ -956,9 +967,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
# Add plugin sections. # Add plugin sections.
for plugin in self.pluginManager.plugins: for plugin in self.pluginManager.plugins:
setting_sections.extend([plugin.name]) setting_sections.extend([plugin.name])
settings = QtCore.QSettings() settings = Settings()
import_settings = QtCore.QSettings(import_file_name, import_settings = Settings(import_file_name,
QtCore.QSettings.IniFormat) Settings.IniFormat)
import_keys = import_settings.allKeys() import_keys = import_settings.allKeys()
for section_key in import_keys: for section_key in import_keys:
# We need to handle the really bad files. # We need to handle the really bad files.
@ -1043,12 +1054,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
os.remove(temp_file) os.remove(temp_file)
if os.path.exists(export_file_name): if os.path.exists(export_file_name):
os.remove(export_file_name) os.remove(export_file_name)
settings = QtCore.QSettings() settings = Settings()
settings.remove(self.headerSection) settings.remove(self.headerSection)
# Get the settings. # Get the settings.
keys = settings.allKeys() keys = settings.allKeys()
export_settings = QtCore.QSettings(temp_file, export_settings = Settings(temp_file,
QtCore.QSettings.IniFormat) Settings.IniFormat)
# Add a header section. # Add a header section.
# This is to insure it's our conf file for import. # This is to insure it's our conf file for import.
now = datetime.now() now = datetime.now()
@ -1106,7 +1117,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
Set OpenLP to a different view mode. Set OpenLP to a different view mode.
""" """
if mode: if mode:
settings = QtCore.QSettings() settings = Settings()
settings.setValue(u'%s/view mode' % self.generalSettingsSection, settings.setValue(u'%s/view mode' % self.generalSettingsSection,
mode) mode)
self.mediaManagerDock.setVisible(media) self.mediaManagerDock.setVisible(media)
@ -1157,7 +1168,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
else: else:
event.ignore() event.ignore()
else: else:
if QtCore.QSettings().value(u'advanced/enable exit confirmation', if Settings().value(u'advanced/enable exit confirmation',
QtCore.QVariant(True)).toBool(): QtCore.QVariant(True)).toBool():
ret = QtGui.QMessageBox.question(self, ret = QtGui.QMessageBox.question(self,
translate('OpenLP.MainWindow', 'Close OpenLP'), translate('OpenLP.MainWindow', 'Close OpenLP'),
@ -1188,9 +1199,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
# Clean temporary files used by services # Clean temporary files used by services
self.serviceManagerContents.cleanUp() self.serviceManagerContents.cleanUp()
if save_settings: if save_settings:
if QtCore.QSettings().value(u'advanced/save current plugin', if Settings().value(u'advanced/save current plugin',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
QtCore.QSettings().setValue(u'advanced/current media plugin', Settings().setValue(u'advanced/current media plugin',
QtCore.QVariant(self.mediaToolBox.currentIndex())) QtCore.QVariant(self.mediaToolBox.currentIndex()))
# Call the cleanup method to shutdown plugins. # Call the cleanup method to shutdown plugins.
log.info(u'cleanup plugins') log.info(u'cleanup plugins')
@ -1198,6 +1209,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
if save_settings: if save_settings:
# Save settings # Save settings
self.saveSettings() self.saveSettings()
# Check if we need to change the data directory
if self.newDataPath:
self.changeDataDirectory()
# Close down the display # Close down the display
if self.liveController.display: if self.liveController.display:
self.liveController.display.close() self.liveController.display.close()
@ -1271,7 +1285,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
False - Hidden False - Hidden
""" """
self.previewController.panel.setVisible(visible) self.previewController.panel.setVisible(visible)
QtCore.QSettings().setValue(u'user interface/preview panel', Settings().setValue(u'user interface/preview panel',
QtCore.QVariant(visible)) QtCore.QVariant(visible))
self.viewPreviewPanel.setChecked(visible) self.viewPreviewPanel.setChecked(visible)
@ -1303,7 +1317,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.viewThemeManagerItem.setEnabled(True) self.viewThemeManagerItem.setEnabled(True)
self.viewPreviewPanel.setEnabled(True) self.viewPreviewPanel.setEnabled(True)
self.viewLivePanel.setEnabled(True) self.viewLivePanel.setEnabled(True)
QtCore.QSettings().setValue(u'user interface/lock panel', Settings().setValue(u'user interface/lock panel',
QtCore.QVariant(lock)) QtCore.QVariant(lock))
def setLivePanelVisibility(self, visible): def setLivePanelVisibility(self, visible):
@ -1317,7 +1331,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
False - Hidden False - Hidden
""" """
self.liveController.panel.setVisible(visible) self.liveController.panel.setVisible(visible)
QtCore.QSettings().setValue(u'user interface/live panel', Settings().setValue(u'user interface/live panel',
QtCore.QVariant(visible)) QtCore.QVariant(visible))
self.viewLivePanel.setChecked(visible) self.viewLivePanel.setChecked(visible)
@ -1327,19 +1341,19 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
""" """
log.debug(u'Loading QSettings') log.debug(u'Loading QSettings')
# Migrate Wrap Settings to Slide Limits Settings # Migrate Wrap Settings to Slide Limits Settings
if QtCore.QSettings().contains(self.generalSettingsSection + if Settings().contains(self.generalSettingsSection +
u'/enable slide loop'): u'/enable slide loop'):
if QtCore.QSettings().value(self.generalSettingsSection + if Settings().value(self.generalSettingsSection +
u'/enable slide loop', QtCore.QVariant(True)).toBool(): u'/enable slide loop', QtCore.QVariant(True)).toBool():
QtCore.QSettings().setValue(self.advancedSettingsSection + Settings().setValue(self.advancedSettingsSection +
u'/slide limits', QtCore.QVariant(SlideLimits.Wrap)) u'/slide limits', QtCore.QVariant(SlideLimits.Wrap))
else: else:
QtCore.QSettings().setValue(self.advancedSettingsSection + Settings().setValue(self.advancedSettingsSection +
u'/slide limits', QtCore.QVariant(SlideLimits.End)) u'/slide limits', QtCore.QVariant(SlideLimits.End))
QtCore.QSettings().remove(self.generalSettingsSection + Settings().remove(self.generalSettingsSection +
u'/enable slide loop') u'/enable slide loop')
Receiver.send_message(u'slidecontroller_update_slide_limits') Receiver.send_message(u'slidecontroller_update_slide_limits')
settings = QtCore.QSettings() settings = Settings()
# Remove obsolete entries. # Remove obsolete entries.
settings.remove(u'custom slide') settings.remove(u'custom slide')
settings.remove(u'service') settings.remove(u'service')
@ -1368,7 +1382,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
if self.settingsImported: if self.settingsImported:
return return
log.debug(u'Saving QSettings') log.debug(u'Saving QSettings')
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.generalSettingsSection) settings.beginGroup(self.generalSettingsSection)
recentFiles = QtCore.QVariant(self.recentFiles) \ recentFiles = QtCore.QVariant(self.recentFiles) \
if self.recentFiles else QtCore.QVariant() if self.recentFiles else QtCore.QVariant()
@ -1394,7 +1408,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
Updates the recent file menu with the latest list of service files Updates the recent file menu with the latest list of service files
accessed. accessed.
""" """
recentFileCount = QtCore.QSettings().value( recentFileCount = Settings().value(
u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0] u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0]
existingRecentFiles = [recentFile for recentFile in self.recentFiles existingRecentFiles = [recentFile for recentFile in self.recentFiles
if os.path.isfile(unicode(recentFile))] if os.path.isfile(unicode(recentFile))]
@ -1427,7 +1441,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
# The maxRecentFiles value does not have an interface and so never gets # The maxRecentFiles value does not have an interface and so never gets
# actually stored in the settings therefore the default value of 20 will # actually stored in the settings therefore the default value of 20 will
# always be used. # always be used.
maxRecentFiles = QtCore.QSettings().value(u'advanced/max recent files', maxRecentFiles = Settings().value(u'advanced/max recent files',
QtCore.QVariant(20)).toInt()[0] QtCore.QVariant(20)).toInt()[0]
if filename: if filename:
# Add some cleanup to reduce duplication in the recent file list # Add some cleanup to reduce duplication in the recent file list
@ -1474,3 +1488,45 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.timer_id = 0 self.timer_id = 0
self.loadProgressBar.hide() self.loadProgressBar.hide()
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
def setNewDataPath(self, new_data_path):
self.newDataPath = new_data_path
def setCopyData(self, copy_data):
self.copyData = copy_data
def changeDataDirectory(self):
log.info(u'Changing data path to %s' % self.newDataPath )
old_data_path = unicode(AppLocation.get_data_path())
# Copy OpenLP data to new location if requested.
if self.copyData:
log.info(u'Copying data to new path')
try:
Receiver.send_message(u'openlp_process_events')
Receiver.send_message(u'cursor_busy')
self.showStatusMessage(
translate('OpenLP.MainWindow',
'Copying OpenLP data to new data directory location - %s '
'- Please wait for copy to finish'
% self.newDataPath))
dir_util.copy_tree(old_data_path, self.newDataPath)
log.info(u'Copy sucessful')
except (IOError, os.error, DistutilsFileError), why:
Receiver.send_message(u'cursor_normal')
log.exception(u'Data copy failed %s' % unicode(why))
QtGui.QMessageBox.critical(self,
translate('OpenLP.MainWindow', 'New Data Directory Error'),
translate('OpenLP.MainWindow',
'OpenLP Data directory copy failed\n\n%s'
% unicode(why)),
QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Ok))
return False
else:
log.info(u'No data copy requested')
# Change the location of data directory in config file.
settings = QtCore.QSettings()
settings.setValue(u'advanced/data path', self.newDataPath)
# Check if the new data path is our default.
if self.newDataPath == AppLocation.get_directory(AppLocation.DataDir):
settings.remove(u'advanced/data path')

View File

@ -26,6 +26,8 @@
############################################################################### ###############################################################################
import logging import logging
from openlp.core.lib.settings import Settings
from PyQt4 import QtCore from PyQt4 import QtCore
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -78,11 +80,11 @@ def get_media_players():
Here an special media player is chosen for all media actions. Here an special media player is chosen for all media actions.
""" """
log.debug(u'get_media_players') log.debug(u'get_media_players')
players = unicode(QtCore.QSettings().value(u'media/players').toString()) players = unicode(Settings().value(u'media/players').toString())
if not players: if not players:
players = u'webkit' players = u'webkit'
reg_ex = QtCore.QRegExp(".*\[(.*)\].*") reg_ex = QtCore.QRegExp(".*\[(.*)\].*")
if QtCore.QSettings().value(u'media/override player', if Settings().value(u'media/override player',
QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0] == QtCore.Qt.Checked: QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0] == QtCore.Qt.Checked:
if reg_ex.exactMatch(players): if reg_ex.exactMatch(players):
overridden_player = u'%s' % reg_ex.cap(1) overridden_player = u'%s' % reg_ex.cap(1)
@ -107,10 +109,10 @@ def set_media_players(players_list, overridden_player=u'auto'):
""" """
log.debug(u'set_media_players') log.debug(u'set_media_players')
players = u','.join(players_list) players = u','.join(players_list)
if QtCore.QSettings().value(u'media/override player', if Settings().value(u'media/override player',
QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0] == \ QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0] == \
QtCore.Qt.Checked and overridden_player != u'auto': QtCore.Qt.Checked and overridden_player != u'auto':
players = players.replace(overridden_player, u'[%s]' % overridden_player) players = players.replace(overridden_player, u'[%s]' % overridden_player)
QtCore.QSettings().setValue(u'media/players', QtCore.QVariant(players)) Settings().setValue(u'media/players', QtCore.QVariant(players))
from mediacontroller import MediaController from mediacontroller import MediaController

View File

@ -30,6 +30,7 @@ import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, Receiver, translate from openlp.core.lib import OpenLPToolbar, Receiver, translate
from openlp.core.lib.settings import Settings
from openlp.core.lib.mediaplayer import MediaPlayer from openlp.core.lib.mediaplayer import MediaPlayer
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.media import MediaState, MediaInfo, MediaType, \ from openlp.core.ui.media import MediaState, MediaInfo, MediaType, \
@ -333,10 +334,9 @@ class MediaController(object):
"setBackBoard", null, null, null,"visible");') "setBackBoard", null, null, null,"visible");')
# now start playing # now start playing
if controller.isLive and \ if controller.isLive and \
(QtCore.QSettings().value(u'general/auto unblank', (Settings().value(u'general/auto unblank',
QtCore.QVariant(False)).toBool() or \ QtCore.QVariant(False)).toBool() or \
controller.media_info.is_background == True) or \ controller.media_info.is_background) or not controller.isLive:
controller.isLive == False:
if not self.video_play([controller]): if not self.video_play([controller]):
critical_error_message_box( critical_error_message_box(
translate('MediaPlugin.MediaItem', 'Unsupported File'), translate('MediaPlugin.MediaItem', 'Unsupported File'),

View File

@ -101,7 +101,7 @@ class PhononPlayer(MediaPlayer):
display.mediaObject = Phonon.MediaObject(display) display.mediaObject = Phonon.MediaObject(display)
Phonon.createPath(display.mediaObject, display.phononWidget) Phonon.createPath(display.mediaObject, display.phononWidget)
if display.hasAudio: if display.hasAudio:
display.audio = Phonon.AudioOutput( \ display.audio = Phonon.AudioOutput(
Phonon.VideoCategory, display.mediaObject) Phonon.VideoCategory, display.mediaObject)
Phonon.createPath(display.mediaObject, display.audio) Phonon.createPath(display.mediaObject, display.audio)
display.phononWidget.raise_() display.phononWidget.raise_()
@ -148,18 +148,17 @@ class PhononPlayer(MediaPlayer):
controller.media_info.start_time > 0: controller.media_info.start_time > 0:
start_time = controller.media_info.start_time start_time = controller.media_info.start_time
display.mediaObject.play() display.mediaObject.play()
if self.media_state_wait(display, Phonon.PlayingState): if not self.media_state_wait(display, Phonon.PlayingState):
return False
if start_time > 0: if start_time > 0:
self.seek(display, controller.media_info.start_time*1000) self.seek(display, controller.media_info.start_time * 1000)
self.volume(display, controller.media_info.volume) self.volume(display, controller.media_info.volume)
controller.media_info.length = \ controller.media_info.length = \
int(display.mediaObject.totalTime()/1000) int(display.mediaObject.totalTime() / 1000)
controller.seekSlider.setMaximum(controller.media_info.length*1000) controller.seekSlider.setMaximum(controller.media_info.length * 1000)
self.state = MediaState.Playing self.state = MediaState.Playing
display.phononWidget.raise_() display.phononWidget.raise_()
return True return True
else:
return False
def pause(self, display): def pause(self, display):
display.mediaObject.pause() display.mediaObject.pause()
@ -198,9 +197,9 @@ class PhononPlayer(MediaPlayer):
controller = display.controller controller = display.controller
if controller.media_info.end_time > 0: if controller.media_info.end_time > 0:
if display.mediaObject.currentTime() > \ if display.mediaObject.currentTime() > \
controller.media_info.end_time*1000: controller.media_info.end_time * 1000:
self.stop(display) self.stop(display)
self.set_visible(display, False) self.set_visible(display, False)
if not controller.seekSlider.isSliderDown(): if not controller.seekSlider.isSliderDown():
controller.seekSlider.setSliderPosition( \ controller.seekSlider.setSliderPosition(
display.mediaObject.currentTime()) display.mediaObject.currentTime())

View File

@ -48,7 +48,7 @@ import sys
from inspect import getargspec from inspect import getargspec
__version__ = "N/A" __version__ = "N/A"
build_date = "Fri Apr 27 16:47:21 2012" build_date = "Thu Jun 14 15:22:46 2012"
# Internal guard to prevent internal classes to be directly # Internal guard to prevent internal classes to be directly
# instanciated. # instanciated.
@ -235,6 +235,23 @@ def class_result(classname):
return classname(result) return classname(result)
return wrap_errcheck return wrap_errcheck
# FILE* ctypes wrapper, copied from
# http://svn.python.org/projects/ctypes/trunk/ctypeslib/ctypeslib/contrib/pythonhdr.py
class FILE(ctypes.Structure):
pass
FILE_ptr = ctypes.POINTER(FILE)
PyFile_FromFile = ctypes.pythonapi.PyFile_FromFile
PyFile_FromFile.restype = ctypes.py_object
PyFile_FromFile.argtypes = [FILE_ptr,
ctypes.c_char_p,
ctypes.c_char_p,
ctypes.CFUNCTYPE(ctypes.c_int, FILE_ptr)]
PyFile_AsFile = ctypes.pythonapi.PyFile_AsFile
PyFile_AsFile.restype = FILE_ptr
PyFile_AsFile.argtypes = [ctypes.py_object]
# Generated enum types # # Generated enum types #
class _Enum(ctypes.c_uint): class _Enum(ctypes.c_uint):
@ -256,6 +273,21 @@ class _Enum(ctypes.c_uint):
def __ne__(self, other): def __ne__(self, other):
return not self.__eq__(other) return not self.__eq__(other)
class LogLevel(_Enum):
'''Logging messages level.
\note future libvlc versions may define new levels.
'''
_enum_names_ = {
0: 'DEBUG',
2: 'NOTICE',
3: 'WARNING',
4: 'ERROR',
}
LogLevel.DEBUG = LogLevel(0)
LogLevel.ERROR = LogLevel(4)
LogLevel.NOTICE = LogLevel(2)
LogLevel.WARNING = LogLevel(3)
class EventType(_Enum): class EventType(_Enum):
'''Event types. '''Event types.
''' '''
@ -577,6 +609,247 @@ AudioOutputChannel.RStereo = AudioOutputChannel(2)
AudioOutputChannel.Right = AudioOutputChannel(4) AudioOutputChannel.Right = AudioOutputChannel(4)
AudioOutputChannel.Stereo = AudioOutputChannel(1) AudioOutputChannel.Stereo = AudioOutputChannel(1)
class Callback(ctypes.c_void_p):
"""Callback function notification
\param p_event the event triggering the callback
"""
pass
class LogCb(ctypes.c_void_p):
"""Callback prototype for LibVLC log message handler.
\param data data pointer as given to L{libvlc_log_subscribe}()
\param level message level (@ref enum libvlc_log_level)
\param fmt printf() format string (as defined by ISO C11)
\param args variable argument list for the format
\note Log message handlers <b>must</b> be thread-safe.
"""
pass
class VideoUnlockCb(ctypes.c_void_p):
"""Callback prototype to unlock a picture buffer.
When the video frame decoding is complete, the unlock callback is invoked.
This callback might not be needed at all. It is only an indication that the
application can now read the pixel values if it needs to.
\warning A picture buffer is unlocked after the picture is decoded,
but before the picture is displayed.
\param opaque private pointer as passed to libvlc_video_set_callbacks() [IN]
\param picture private pointer returned from the @ref libvlc_video_lock_cb
callback [IN]
\param planes pixel planes as defined by the @ref libvlc_video_lock_cb
callback (this parameter is only for convenience) [IN]
"""
pass
class VideoDisplayCb(ctypes.c_void_p):
"""Callback prototype to display a picture.
When the video frame needs to be shown, as determined by the media playback
clock, the display callback is invoked.
\param opaque private pointer as passed to libvlc_video_set_callbacks() [IN]
\param picture private pointer returned from the @ref libvlc_video_lock_cb
callback [IN]
"""
pass
class VideoFormatCb(ctypes.c_void_p):
"""Callback prototype to configure picture buffers format.
This callback gets the format of the video as output by the video decoder
and the chain of video filters (if any). It can opt to change any parameter
as it needs. In that case, LibVLC will attempt to convert the video format
(rescaling and chroma conversion) but these operations can be CPU intensive.
\param opaque pointer to the private pointer passed to
libvlc_video_set_callbacks() [IN/OUT]
\param chroma pointer to the 4 bytes video format identifier [IN/OUT]
\param width pointer to the pixel width [IN/OUT]
\param height pointer to the pixel height [IN/OUT]
\param pitches table of scanline pitches in bytes for each pixel plane
(the table is allocated by LibVLC) [OUT]
\param lines table of scanlines count for each plane [OUT]
\return the number of picture buffers allocated, 0 indicates failure
\note
For each pixels plane, the scanline pitch must be bigger than or equal to
the number of bytes per pixel multiplied by the pixel width.
Similarly, the number of scanlines must be bigger than of equal to
the pixel height.
Furthermore, we recommend that pitches and lines be multiple of 32
to not break assumption that might be made by various optimizations
in the video decoders, video filters and/or video converters.
"""
pass
class VideoCleanupCb(ctypes.c_void_p):
"""Callback prototype to configure picture buffers format.
\param opaque private pointer as passed to libvlc_video_set_callbacks()
(and possibly modified by @ref libvlc_video_format_cb) [IN]
"""
pass
class AudioPlayCb(ctypes.c_void_p):
"""Callback prototype for audio playback.
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
\param samples pointer to the first audio sample to play back [IN]
\param count number of audio samples to play back
\param pts expected play time stamp (see libvlc_delay())
"""
pass
class AudioPauseCb(ctypes.c_void_p):
"""Callback prototype for audio pause.
\note The pause callback is never called if the audio is already paused.
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
\param pts time stamp of the pause request (should be elapsed already)
"""
pass
class AudioResumeCb(ctypes.c_void_p):
"""Callback prototype for audio resumption (i.e. restart from pause).
\note The resume callback is never called if the audio is not paused.
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
\param pts time stamp of the resumption request (should be elapsed already)
"""
pass
class AudioFlushCb(ctypes.c_void_p):
"""Callback prototype for audio buffer flush
(i.e. discard all pending buffers and stop playback as soon as possible).
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
"""
pass
class AudioDrainCb(ctypes.c_void_p):
"""Callback prototype for audio buffer drain
(i.e. wait for pending buffers to be played).
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
"""
pass
class AudioSetVolumeCb(ctypes.c_void_p):
"""Callback prototype for audio volume change.
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
\param volume software volume (1. = nominal, 0. = mute)
\param mute muted flag
"""
pass
class AudioSetupCb(ctypes.c_void_p):
"""Callback prototype to setup the audio playback.
This is called when the media player needs to create a new audio output.
\param opaque pointer to the data pointer passed to
L{libvlc_audio_set_callbacks}() [IN/OUT]
\param format 4 bytes sample format [IN/OUT]
\param rate sample rate [IN/OUT]
\param channels channels count [IN/OUT]
\return 0 on success, anything else to skip audio playback
"""
pass
class AudioCleanupCb(ctypes.c_void_p):
"""Callback prototype for audio playback cleanup.
This is called when the media player no longer needs an audio output.
\param opaque data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
"""
pass
class CallbackDecorators(object):
"Class holding various method decorators for callback functions."
Callback = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
Callback.__doc__ = '''Callback function notification
\param p_event the event triggering the callback
'''
LogCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_void_p)
LogCb.__doc__ = '''Callback prototype for LibVLC log message handler.
\param data data pointer as given to L{libvlc_log_subscribe}()
\param level message level (@ref enum libvlc_log_level)
\param fmt printf() format string (as defined by ISO C11)
\param args variable argument list for the format
\note Log message handlers <b>must</b> be thread-safe.
'''
VideoUnlockCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ListPOINTER(ctypes.c_void_p))
VideoUnlockCb.__doc__ = '''Callback prototype to unlock a picture buffer.
When the video frame decoding is complete, the unlock callback is invoked.
This callback might not be needed at all. It is only an indication that the
application can now read the pixel values if it needs to.
\warning A picture buffer is unlocked after the picture is decoded,
but before the picture is displayed.
\param opaque private pointer as passed to libvlc_video_set_callbacks() [IN]
\param picture private pointer returned from the @ref libvlc_video_lock_cb
callback [IN]
\param planes pixel planes as defined by the @ref libvlc_video_lock_cb
callback (this parameter is only for convenience) [IN]
'''
VideoDisplayCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
VideoDisplayCb.__doc__ = '''Callback prototype to display a picture.
When the video frame needs to be shown, as determined by the media playback
clock, the display callback is invoked.
\param opaque private pointer as passed to libvlc_video_set_callbacks() [IN]
\param picture private pointer returned from the @ref libvlc_video_lock_cb
callback [IN]
'''
VideoFormatCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_uint), ListPOINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint))
VideoFormatCb.__doc__ = '''Callback prototype to configure picture buffers format.
This callback gets the format of the video as output by the video decoder
and the chain of video filters (if any). It can opt to change any parameter
as it needs. In that case, LibVLC will attempt to convert the video format
(rescaling and chroma conversion) but these operations can be CPU intensive.
\param opaque pointer to the private pointer passed to
libvlc_video_set_callbacks() [IN/OUT]
\param chroma pointer to the 4 bytes video format identifier [IN/OUT]
\param width pointer to the pixel width [IN/OUT]
\param height pointer to the pixel height [IN/OUT]
\param pitches table of scanline pitches in bytes for each pixel plane
(the table is allocated by LibVLC) [OUT]
\param lines table of scanlines count for each plane [OUT]
\return the number of picture buffers allocated, 0 indicates failure
\note
For each pixels plane, the scanline pitch must be bigger than or equal to
the number of bytes per pixel multiplied by the pixel width.
Similarly, the number of scanlines must be bigger than of equal to
the pixel height.
Furthermore, we recommend that pitches and lines be multiple of 32
to not break assumption that might be made by various optimizations
in the video decoders, video filters and/or video converters.
'''
VideoCleanupCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)
VideoCleanupCb.__doc__ = '''Callback prototype to configure picture buffers format.
\param opaque private pointer as passed to libvlc_video_set_callbacks()
(and possibly modified by @ref libvlc_video_format_cb) [IN]
'''
AudioPlayCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint, ctypes.c_int64)
AudioPlayCb.__doc__ = '''Callback prototype for audio playback.
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
\param samples pointer to the first audio sample to play back [IN]
\param count number of audio samples to play back
\param pts expected play time stamp (see libvlc_delay())
'''
AudioPauseCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64)
AudioPauseCb.__doc__ = '''Callback prototype for audio pause.
\note The pause callback is never called if the audio is already paused.
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
\param pts time stamp of the pause request (should be elapsed already)
'''
AudioResumeCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64)
AudioResumeCb.__doc__ = '''Callback prototype for audio resumption (i.e. restart from pause).
\note The resume callback is never called if the audio is not paused.
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
\param pts time stamp of the resumption request (should be elapsed already)
'''
AudioFlushCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64)
AudioFlushCb.__doc__ = '''Callback prototype for audio buffer flush
(i.e. discard all pending buffers and stop playback as soon as possible).
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
'''
AudioDrainCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)
AudioDrainCb.__doc__ = '''Callback prototype for audio buffer drain
(i.e. wait for pending buffers to be played).
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
'''
AudioSetVolumeCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_float, ctypes.c_bool)
AudioSetVolumeCb.__doc__ = '''Callback prototype for audio volume change.
\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
\param volume software volume (1. = nominal, 0. = mute)
\param mute muted flag
'''
AudioSetupCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_int), ListPOINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint))
AudioSetupCb.__doc__ = '''Callback prototype to setup the audio playback.
This is called when the media player needs to create a new audio output.
\param opaque pointer to the data pointer passed to
L{libvlc_audio_set_callbacks}() [IN/OUT]
\param format 4 bytes sample format [IN/OUT]
\param rate sample rate [IN/OUT]
\param channels channels count [IN/OUT]
\return 0 on success, anything else to skip audio playback
'''
AudioCleanupCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)
AudioCleanupCb.__doc__ = '''Callback prototype for audio playback cleanup.
This is called when the media player no longer needs an audio output.
\param opaque data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
'''
cb = CallbackDecorators
# End of generated enum types # # End of generated enum types #
# From libvlc_structures.h # From libvlc_structures.h
@ -905,10 +1178,10 @@ class Instance(_Ctype):
def media_new(self, mrl, *options): def media_new(self, mrl, *options):
"""Create a new Media instance. """Create a new Media instance.
If mrl contains a colon (:), it will be treated as a If mrl contains a colon (:) preceded by more than 1 letter, it
URL. Else, it will be considered as a local path. If you need will be treated as a URL. Else, it will be considered as a
more control, directly use media_new_location/media_new_path local path. If you need more control, directly use
methods. media_new_location/media_new_path methods.
Options can be specified as supplementary string parameters, e.g. Options can be specified as supplementary string parameters, e.g.
@ -920,7 +1193,7 @@ class Instance(_Ctype):
@param options: optional media option=value strings @param options: optional media option=value strings
""" """
if ':' in mrl: if ':' in mrl and mrl.index(':') > 1:
# Assume it is a URL # Assume it is a URL
m = libvlc_media_new_location(self, mrl) m = libvlc_media_new_location(self, mrl)
else: else:
@ -995,12 +1268,6 @@ class Instance(_Ctype):
''' '''
return libvlc_add_intf(self, name) return libvlc_add_intf(self, name)
def wait(self):
'''Waits until an interface causes the instance to exit.
You should start at least one interface first, using L{add_intf}().
'''
return libvlc_wait(self)
def set_user_agent(self, name, http): def set_user_agent(self, name, http):
'''Sets the application name. LibVLC passes this as the user agent string '''Sets the application name. LibVLC passes this as the user agent string
when a protocol requires it. when a protocol requires it.
@ -1455,7 +1722,11 @@ class Media(_Ctype):
This option will be used to determine how the media_player will This option will be used to determine how the media_player will
read the media. This allows to use VLC's advanced read the media. This allows to use VLC's advanced
reading/streaming options on a per-media basis. reading/streaming options on a per-media basis.
The options are detailed in vlc --long-help, for instance "--sout-all". The options are detailed in vlc --long-help, for instance
"--sout-all". Note that all options are not usable on medias:
specifically, due to architectural issues, video-related options
such as text renderer options cannot be set on a single media. They
must be set on the whole libvlc instance instead.
@param ppsz_options: the options (as a string). @param ppsz_options: the options (as a string).
''' '''
return libvlc_media_add_option(self, ppsz_options) return libvlc_media_add_option(self, ppsz_options)
@ -1465,7 +1736,11 @@ class Media(_Ctype):
This option will be used to determine how the media_player will This option will be used to determine how the media_player will
read the media. This allows to use VLC's advanced read the media. This allows to use VLC's advanced
reading/streaming options on a per-media basis. reading/streaming options on a per-media basis.
The options are detailed in vlc --long-help, for instance "--sout-all". The options are detailed in vlc --long-help, for instance
"--sout-all". Note that all options are not usable on medias:
specifically, due to architectural issues, video-related options
such as text renderer options cannot be set on a single media. They
must be set on the whole libvlc instance instead.
@param ppsz_options: the options (as a string). @param ppsz_options: the options (as a string).
@param i_flags: the flags for this option. @param i_flags: the flags for this option.
''' '''
@ -1608,7 +1883,7 @@ class Media(_Ctype):
Note, you need to call L{parse}() or play the media at least once Note, you need to call L{parse}() or play the media at least once
before calling this function. before calling this function.
Not doing this will result in an empty array. Not doing this will result in an empty array.
@param tracks: address to store an allocated array of Elementary Streams descriptions (must be freed by the caller). @param tracks: address to store an allocated array of Elementary Streams descriptions (must be freed by the caller) [OUT].
@return: the number of Elementary Streams. @return: the number of Elementary Streams.
''' '''
return libvlc_media_get_tracks_info(self) return libvlc_media_get_tracks_info(self)
@ -1718,7 +1993,7 @@ class MediaList(_Ctype):
"""Add media instance to media list. """Add media instance to media list.
The L{lock} should be held upon entering this function. The L{lock} should be held upon entering this function.
@param p_md: a media instance or a MRL. @param mrl: a media instance or a MRL.
@return: 0 on success, -1 if the media list is read-only. @return: 0 on success, -1 if the media list is read-only.
""" """
if isinstance(mrl, basestring): if isinstance(mrl, basestring):
@ -2149,16 +2424,25 @@ class MediaPlayer(_Ctype):
def video_set_format(self, chroma, width, height, pitch): def video_set_format(self, chroma, width, height, pitch):
'''Set decoded video chroma and dimensions. '''Set decoded video chroma and dimensions.
This only works in combination with libvlc_video_set_callbacks(), This only works in combination with libvlc_video_set_callbacks(),
and is mutually exclusive with libvlc_video_set_format_callbacks(). and is mutually exclusive with L{video_set_format_callbacks}().
@param chroma: a four-characters string identifying the chroma (e.g. "RV32" or "YUYV"). @param chroma: a four-characters string identifying the chroma (e.g. "RV32" or "YUYV").
@param width: pixel width. @param width: pixel width.
@param height: pixel height. @param height: pixel height.
@param pitch: line pitch (in bytes). @param pitch: line pitch (in bytes).
@version: LibVLC 1.1.1 or later. @version: LibVLC 1.1.1 or later.
@bug: All pixel planes are expected to have the same pitch. To use the YCbCr color space with chrominance subsampling, consider using libvlc_video_set_format_callbacks() instead. @bug: All pixel planes are expected to have the same pitch. To use the YCbCr color space with chrominance subsampling, consider using L{video_set_format_callbacks}() instead.
''' '''
return libvlc_video_set_format(self, chroma, width, height, pitch) return libvlc_video_set_format(self, chroma, width, height, pitch)
def video_set_format_callbacks(self, setup, cleanup):
'''Set decoded video chroma and dimensions. This only works in combination with
libvlc_video_set_callbacks().
@param setup: callback to select the video format (cannot be NULL).
@param cleanup: callback to release any allocated resources (or NULL).
@version: LibVLC 2.0.0 or later.
'''
return libvlc_video_set_format_callbacks(self, setup, cleanup)
def set_nsobject(self, drawable): def set_nsobject(self, drawable):
'''Set the NSView handler where the media player should render its video output. '''Set the NSView handler where the media player should render its video output.
Use the vout called "macosx". Use the vout called "macosx".
@ -2234,10 +2518,42 @@ class MediaPlayer(_Ctype):
''' '''
return libvlc_media_player_get_hwnd(self) return libvlc_media_player_get_hwnd(self)
def audio_set_callbacks(self, play, pause, resume, flush, drain, opaque):
'''Set callbacks and private data for decoded audio.
Use L{audio_set_format}() or L{audio_set_format_callbacks}()
to configure the decoded audio format.
@param play: callback to play audio samples (must not be NULL).
@param pause: callback to pause playback (or NULL to ignore).
@param resume: callback to resume playback (or NULL to ignore).
@param flush: callback to flush audio buffers (or NULL to ignore).
@param drain: callback to drain audio buffers (or NULL to ignore).
@param opaque: private pointer for the audio callbacks (as first parameter).
@version: LibVLC 2.0.0 or later.
'''
return libvlc_audio_set_callbacks(self, play, pause, resume, flush, drain, opaque)
def audio_set_volume_callback(self, set_volume):
'''Set callbacks and private data for decoded audio.
Use L{audio_set_format}() or L{audio_set_format_callbacks}()
to configure the decoded audio format.
@param set_volume: callback to apply audio volume, or NULL to apply volume in software.
@version: LibVLC 2.0.0 or later.
'''
return libvlc_audio_set_volume_callback(self, set_volume)
def audio_set_format_callbacks(self, setup, cleanup):
'''Set decoded audio format. This only works in combination with
L{audio_set_callbacks}().
@param setup: callback to select the audio format (cannot be NULL).
@param cleanup: callback to release any allocated resources (or NULL).
@version: LibVLC 2.0.0 or later.
'''
return libvlc_audio_set_format_callbacks(self, setup, cleanup)
def audio_set_format(self, format, rate, channels): def audio_set_format(self, format, rate, channels):
'''Set decoded audio format. '''Set decoded audio format.
This only works in combination with libvlc_audio_set_callbacks(), This only works in combination with L{audio_set_callbacks}(),
and is mutually exclusive with libvlc_audio_set_format_callbacks(). and is mutually exclusive with L{audio_set_format_callbacks}().
@param format: a four-characters string identifying the sample format (e.g. "S16N" or "FL32"). @param format: a four-characters string identifying the sample format (e.g. "S16N" or "FL32").
@param rate: sample rate (expressed in Hz). @param rate: sample rate (expressed in Hz).
@param channels: channels count. @param channels: channels count.
@ -2797,6 +3113,30 @@ def libvlc_clearerr():
None) None)
return f() return f()
def libvlc_vprinterr(fmt, ap):
'''Sets the LibVLC error status and message for the current thread.
Any previous error is overridden.
@param fmt: the format string.
@param ap: the arguments.
@return: a nul terminated string in any case.
'''
f = _Cfunctions.get('libvlc_vprinterr', None) or \
_Cfunction('libvlc_vprinterr', ((1,), (1,),), None,
ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p)
return f(fmt, ap)
def libvlc_printerr(fmt, args):
'''Sets the LibVLC error status and message for the current thread.
Any previous error is overridden.
@param fmt: the format string.
@param args: the arguments.
@return: a nul terminated string in any case.
'''
f = _Cfunctions.get('libvlc_printerr', None) or \
_Cfunction('libvlc_printerr', ((1,), (1,),), None,
ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p)
return f(fmt, args)
def libvlc_new(argc, argv): def libvlc_new(argc, argv):
'''Create and initialize a libvlc instance. '''Create and initialize a libvlc instance.
This functions accept a list of "command line" arguments similar to the This functions accept a list of "command line" arguments similar to the
@ -2842,16 +3182,6 @@ def libvlc_add_intf(p_instance, name):
ctypes.c_int, Instance, ctypes.c_char_p) ctypes.c_int, Instance, ctypes.c_char_p)
return f(p_instance, name) return f(p_instance, name)
def libvlc_wait(p_instance):
'''Waits until an interface causes the instance to exit.
You should start at least one interface first, using L{libvlc_add_intf}().
@param p_instance: the instance.
'''
f = _Cfunctions.get('libvlc_wait', None) or \
_Cfunction('libvlc_wait', ((1,),), None,
None, Instance)
return f(p_instance)
def libvlc_set_user_agent(p_instance, name, http): def libvlc_set_user_agent(p_instance, name, http):
'''Sets the application name. LibVLC passes this as the user agent string '''Sets the application name. LibVLC passes this as the user agent string
when a protocol requires it. when a protocol requires it.
@ -2916,7 +3246,7 @@ def libvlc_event_attach(p_event_manager, i_event_type, f_callback, user_data):
''' '''
f = _Cfunctions.get('libvlc_event_attach', None) or \ f = _Cfunctions.get('libvlc_event_attach', None) or \
_Cfunction('libvlc_event_attach', ((1,), (1,), (1,), (1,),), None, _Cfunction('libvlc_event_attach', ((1,), (1,), (1,), (1,),), None,
ctypes.c_int, EventManager, ctypes.c_uint, ctypes.c_void_p, ctypes.c_void_p) ctypes.c_int, EventManager, ctypes.c_uint, Callback, ctypes.c_void_p)
return f(p_event_manager, i_event_type, f_callback, user_data) return f(p_event_manager, i_event_type, f_callback, user_data)
def libvlc_event_detach(p_event_manager, i_event_type, f_callback, p_user_data): def libvlc_event_detach(p_event_manager, i_event_type, f_callback, p_user_data):
@ -2928,7 +3258,7 @@ def libvlc_event_detach(p_event_manager, i_event_type, f_callback, p_user_data):
''' '''
f = _Cfunctions.get('libvlc_event_detach', None) or \ f = _Cfunctions.get('libvlc_event_detach', None) or \
_Cfunction('libvlc_event_detach', ((1,), (1,), (1,), (1,),), None, _Cfunction('libvlc_event_detach', ((1,), (1,), (1,), (1,),), None,
None, EventManager, ctypes.c_uint, ctypes.c_void_p, ctypes.c_void_p) None, EventManager, ctypes.c_uint, Callback, ctypes.c_void_p)
return f(p_event_manager, i_event_type, f_callback, p_user_data) return f(p_event_manager, i_event_type, f_callback, p_user_data)
def libvlc_event_type_name(event_type): def libvlc_event_type_name(event_type):
@ -2940,6 +3270,45 @@ def libvlc_event_type_name(event_type):
ctypes.c_char_p, ctypes.c_uint) ctypes.c_char_p, ctypes.c_uint)
return f(event_type) return f(event_type)
def libvlc_log_subscribe(sub, cb, data):
'''Registers a logging callback to LibVLC.
This function is thread-safe.
@param sub: uninitialized subscriber structure.
@param cb: callback function pointer.
@param data: opaque data pointer for the callback function @note Some log messages (especially debug) are emitted by LibVLC while initializing, before any LibVLC instance even exists. Thus this function does not require a LibVLC instance parameter. @warning As a consequence of not depending on a LibVLC instance, all logging callbacks are shared by all LibVLC instances within the process / address space. This also enables log messages to be emitted by LibVLC components that are not specific to any given LibVLC instance. @warning Do not call this function from within a logging callback. It would trigger a dead lock.
@version: LibVLC 2.1.0 or later.
'''
f = _Cfunctions.get('libvlc_log_subscribe', None) or \
_Cfunction('libvlc_log_subscribe', ((1,), (1,), (1,),), None,
None, ctypes.c_void_p, LogCb, ctypes.c_void_p)
return f(sub, cb, data)
def libvlc_log_subscribe_file(sub, stream):
'''Registers a logging callback to a file.
@param stream: FILE pointer opened for writing (the FILE pointer must remain valid until L{libvlc_log_unsubscribe}()).
@version: LibVLC 2.1.0 or later.
'''
f = _Cfunctions.get('libvlc_log_subscribe_file', None) or \
_Cfunction('libvlc_log_subscribe_file', ((1,), (1,),), None,
None, ctypes.c_void_p, FILE_ptr)
return f(sub, stream)
def libvlc_log_unsubscribe(sub):
'''Deregisters a logging callback from LibVLC.
This function is thread-safe.
@note: After (and only after) L{libvlc_log_unsubscribe}() has returned,
LibVLC warrants that there are no more pending calls of the subscription
callback function.
@warning: Do not call this function from within a logging callback.
It would trigger a dead lock.
@param sub: initialized subscriber structure.
@version: LibVLC 2.1.0 or later.
'''
f = _Cfunctions.get('libvlc_log_unsubscribe', None) or \
_Cfunction('libvlc_log_unsubscribe', ((1,),), None,
None, ctypes.c_void_p)
return f(sub)
def libvlc_get_log_verbosity(p_instance): def libvlc_get_log_verbosity(p_instance):
'''Always returns minus one. '''Always returns minus one.
This function is only provided for backward compatibility. This function is only provided for backward compatibility.
@ -3158,7 +3527,11 @@ def libvlc_media_add_option(p_md, ppsz_options):
This option will be used to determine how the media_player will This option will be used to determine how the media_player will
read the media. This allows to use VLC's advanced read the media. This allows to use VLC's advanced
reading/streaming options on a per-media basis. reading/streaming options on a per-media basis.
The options are detailed in vlc --long-help, for instance "--sout-all". The options are detailed in vlc --long-help, for instance
"--sout-all". Note that all options are not usable on medias:
specifically, due to architectural issues, video-related options
such as text renderer options cannot be set on a single media. They
must be set on the whole libvlc instance instead.
@param p_md: the media descriptor. @param p_md: the media descriptor.
@param ppsz_options: the options (as a string). @param ppsz_options: the options (as a string).
''' '''
@ -3172,7 +3545,11 @@ def libvlc_media_add_option_flag(p_md, ppsz_options, i_flags):
This option will be used to determine how the media_player will This option will be used to determine how the media_player will
read the media. This allows to use VLC's advanced read the media. This allows to use VLC's advanced
reading/streaming options on a per-media basis. reading/streaming options on a per-media basis.
The options are detailed in vlc --long-help, for instance "--sout-all". The options are detailed in vlc --long-help, for instance
"--sout-all". Note that all options are not usable on medias:
specifically, due to architectural issues, video-related options
such as text renderer options cannot be set on a single media. They
must be set on the whole libvlc instance instead.
@param p_md: the media descriptor. @param p_md: the media descriptor.
@param ppsz_options: the options (as a string). @param ppsz_options: the options (as a string).
@param i_flags: the flags for this option. @param i_flags: the flags for this option.
@ -3384,7 +3761,7 @@ def libvlc_media_get_tracks_info(p_md):
before calling this function. before calling this function.
Not doing this will result in an empty array. Not doing this will result in an empty array.
@param p_md: media descriptor object. @param p_md: media descriptor object.
@param tracks: address to store an allocated array of Elementary Streams descriptions (must be freed by the caller). @param tracks: address to store an allocated array of Elementary Streams descriptions (must be freed by the caller) [OUT].
@return: the number of Elementary Streams. @return: the number of Elementary Streams.
''' '''
f = _Cfunctions.get('libvlc_media_get_tracks_info', None) or \ f = _Cfunctions.get('libvlc_media_get_tracks_info', None) or \
@ -3958,20 +4335,33 @@ def libvlc_media_player_stop(p_mi):
def libvlc_video_set_format(mp, chroma, width, height, pitch): def libvlc_video_set_format(mp, chroma, width, height, pitch):
'''Set decoded video chroma and dimensions. '''Set decoded video chroma and dimensions.
This only works in combination with libvlc_video_set_callbacks(), This only works in combination with libvlc_video_set_callbacks(),
and is mutually exclusive with libvlc_video_set_format_callbacks(). and is mutually exclusive with L{libvlc_video_set_format_callbacks}().
@param mp: the media player. @param mp: the media player.
@param chroma: a four-characters string identifying the chroma (e.g. "RV32" or "YUYV"). @param chroma: a four-characters string identifying the chroma (e.g. "RV32" or "YUYV").
@param width: pixel width. @param width: pixel width.
@param height: pixel height. @param height: pixel height.
@param pitch: line pitch (in bytes). @param pitch: line pitch (in bytes).
@version: LibVLC 1.1.1 or later. @version: LibVLC 1.1.1 or later.
@bug: All pixel planes are expected to have the same pitch. To use the YCbCr color space with chrominance subsampling, consider using libvlc_video_set_format_callbacks() instead. @bug: All pixel planes are expected to have the same pitch. To use the YCbCr color space with chrominance subsampling, consider using L{libvlc_video_set_format_callbacks}() instead.
''' '''
f = _Cfunctions.get('libvlc_video_set_format', None) or \ f = _Cfunctions.get('libvlc_video_set_format', None) or \
_Cfunction('libvlc_video_set_format', ((1,), (1,), (1,), (1,), (1,),), None, _Cfunction('libvlc_video_set_format', ((1,), (1,), (1,), (1,), (1,),), None,
None, MediaPlayer, ctypes.c_char_p, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint) None, MediaPlayer, ctypes.c_char_p, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint)
return f(mp, chroma, width, height, pitch) return f(mp, chroma, width, height, pitch)
def libvlc_video_set_format_callbacks(mp, setup, cleanup):
'''Set decoded video chroma and dimensions. This only works in combination with
libvlc_video_set_callbacks().
@param mp: the media player.
@param setup: callback to select the video format (cannot be NULL).
@param cleanup: callback to release any allocated resources (or NULL).
@version: LibVLC 2.0.0 or later.
'''
f = _Cfunctions.get('libvlc_video_set_format_callbacks', None) or \
_Cfunction('libvlc_video_set_format_callbacks', ((1,), (1,), (1,),), None,
None, MediaPlayer, VideoFormatCb, VideoCleanupCb)
return f(mp, setup, cleanup)
def libvlc_media_player_set_nsobject(p_mi, drawable): def libvlc_media_player_set_nsobject(p_mi, drawable):
'''Set the NSView handler where the media player should render its video output. '''Set the NSView handler where the media player should render its video output.
Use the vout called "macosx". Use the vout called "macosx".
@ -4087,10 +4477,54 @@ def libvlc_media_player_get_hwnd(p_mi):
ctypes.c_void_p, MediaPlayer) ctypes.c_void_p, MediaPlayer)
return f(p_mi) return f(p_mi)
def libvlc_audio_set_callbacks(mp, play, pause, resume, flush, drain, opaque):
'''Set callbacks and private data for decoded audio.
Use L{libvlc_audio_set_format}() or L{libvlc_audio_set_format_callbacks}()
to configure the decoded audio format.
@param mp: the media player.
@param play: callback to play audio samples (must not be NULL).
@param pause: callback to pause playback (or NULL to ignore).
@param resume: callback to resume playback (or NULL to ignore).
@param flush: callback to flush audio buffers (or NULL to ignore).
@param drain: callback to drain audio buffers (or NULL to ignore).
@param opaque: private pointer for the audio callbacks (as first parameter).
@version: LibVLC 2.0.0 or later.
'''
f = _Cfunctions.get('libvlc_audio_set_callbacks', None) or \
_Cfunction('libvlc_audio_set_callbacks', ((1,), (1,), (1,), (1,), (1,), (1,), (1,),), None,
None, MediaPlayer, AudioPlayCb, AudioPauseCb, AudioResumeCb, AudioFlushCb, AudioDrainCb, ctypes.c_void_p)
return f(mp, play, pause, resume, flush, drain, opaque)
def libvlc_audio_set_volume_callback(mp, set_volume):
'''Set callbacks and private data for decoded audio.
Use L{libvlc_audio_set_format}() or L{libvlc_audio_set_format_callbacks}()
to configure the decoded audio format.
@param mp: the media player.
@param set_volume: callback to apply audio volume, or NULL to apply volume in software.
@version: LibVLC 2.0.0 or later.
'''
f = _Cfunctions.get('libvlc_audio_set_volume_callback', None) or \
_Cfunction('libvlc_audio_set_volume_callback', ((1,), (1,),), None,
None, MediaPlayer, AudioSetVolumeCb)
return f(mp, set_volume)
def libvlc_audio_set_format_callbacks(mp, setup, cleanup):
'''Set decoded audio format. This only works in combination with
L{libvlc_audio_set_callbacks}().
@param mp: the media player.
@param setup: callback to select the audio format (cannot be NULL).
@param cleanup: callback to release any allocated resources (or NULL).
@version: LibVLC 2.0.0 or later.
'''
f = _Cfunctions.get('libvlc_audio_set_format_callbacks', None) or \
_Cfunction('libvlc_audio_set_format_callbacks', ((1,), (1,), (1,),), None,
None, MediaPlayer, AudioSetupCb, AudioCleanupCb)
return f(mp, setup, cleanup)
def libvlc_audio_set_format(mp, format, rate, channels): def libvlc_audio_set_format(mp, format, rate, channels):
'''Set decoded audio format. '''Set decoded audio format.
This only works in combination with libvlc_audio_set_callbacks(), This only works in combination with L{libvlc_audio_set_callbacks}(),
and is mutually exclusive with libvlc_audio_set_format_callbacks(). and is mutually exclusive with L{libvlc_audio_set_format_callbacks}().
@param mp: the media player. @param mp: the media player.
@param format: a four-characters string identifying the sample format (e.g. "S16N" or "FL32"). @param format: a four-characters string identifying the sample format (e.g. "S16N" or "FL32").
@param rate: sample rate (expressed in Hz). @param rate: sample rate (expressed in Hz).
@ -5394,17 +5828,11 @@ def libvlc_vlm_get_event_manager(p_instance):
return f(p_instance) return f(p_instance)
# 8 function(s) blacklisted: # 2 function(s) blacklisted:
# libvlc_audio_set_callbacks
# libvlc_audio_set_format_callbacks
# libvlc_audio_set_volume_callback
# libvlc_printerr
# libvlc_set_exit_handler # libvlc_set_exit_handler
# libvlc_video_set_callbacks # libvlc_video_set_callbacks
# libvlc_video_set_format_callbacks
# libvlc_vprinterr
# 13 function(s) not wrapped as methods: # 18 function(s) not wrapped as methods:
# libvlc_audio_output_list_release # libvlc_audio_output_list_release
# libvlc_clearerr # libvlc_clearerr
# libvlc_clock # libvlc_clock
@ -5414,10 +5842,15 @@ def libvlc_vlm_get_event_manager(p_instance):
# libvlc_get_changeset # libvlc_get_changeset
# libvlc_get_compiler # libvlc_get_compiler
# libvlc_get_version # libvlc_get_version
# libvlc_log_subscribe
# libvlc_log_subscribe_file
# libvlc_log_unsubscribe
# libvlc_module_description_list_release # libvlc_module_description_list_release
# libvlc_new # libvlc_new
# libvlc_printerr
# libvlc_track_description_list_release # libvlc_track_description_list_release
# libvlc_track_description_release # libvlc_track_description_release
# libvlc_vprinterr
# Start of footer.py # # Start of footer.py #
@ -5595,7 +6028,7 @@ if __name__ == '__main__':
print('Aspect ratio: %s' % player.video_get_aspect_ratio()) print('Aspect ratio: %s' % player.video_get_aspect_ratio())
#print('Window:' % player.get_hwnd() #print('Window:' % player.get_hwnd()
except Exception: except Exception:
print('Error: %s', sys.exc_info()[1]) print('Error: %s' % sys.exc_info()[1])
def sec_forward(): def sec_forward():
"""Go forward one sec""" """Go forward one sec"""

View File

@ -34,6 +34,7 @@ import sys
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver from openlp.core.lib import Receiver
from openlp.core.lib.settings import Settings
from openlp.core.lib.mediaplayer import MediaPlayer from openlp.core.lib.mediaplayer import MediaPlayer
from openlp.core.ui.media import MediaState from openlp.core.ui.media import MediaState
@ -114,7 +115,7 @@ class VlcPlayer(MediaPlayer):
command_line_options = u'--no-video-title-show' command_line_options = u'--no-video-title-show'
if not display.hasAudio: if not display.hasAudio:
command_line_options += u' --no-audio --no-video-title-show' command_line_options += u' --no-audio --no-video-title-show'
if QtCore.QSettings().value(u'advanced/hide mouse', if Settings().value(u'advanced/hide mouse',
QtCore.QVariant(False)).toBool() and \ QtCore.QVariant(False)).toBool() and \
display.controller.isLive: display.controller.isLive:
command_line_options += u' --mouse-hide-timeout=0' command_line_options += u' --mouse-hide-timeout=0'
@ -130,9 +131,9 @@ class VlcPlayer(MediaPlayer):
# this is platform specific! # this is platform specific!
# you have to give the id of the QFrame (or similar object) to # you have to give the id of the QFrame (or similar object) to
# vlc, different platforms have different functions for this # vlc, different platforms have different functions for this
if sys.platform == "win32": # for Windows if sys.platform == "win32":
display.vlcMediaPlayer.set_hwnd(int(display.vlcWidget.winId())) display.vlcMediaPlayer.set_hwnd(int(display.vlcWidget.winId()))
elif sys.platform == "darwin": # for MacOS elif sys.platform == "darwin":
display.vlcMediaPlayer.set_agl(int(display.vlcWidget.winId())) display.vlcMediaPlayer.set_agl(int(display.vlcWidget.winId()))
else: else:
# for Linux using the X Server # for Linux using the X Server
@ -181,7 +182,8 @@ class VlcPlayer(MediaPlayer):
if controller.media_info.start_time > 0: if controller.media_info.start_time > 0:
start_time = controller.media_info.start_time start_time = controller.media_info.start_time
display.vlcMediaPlayer.play() display.vlcMediaPlayer.play()
if self.media_state_wait(display, vlc.State.Playing): if not self.media_state_wait(display, vlc.State.Playing):
return False
if start_time > 0: if start_time > 0:
self.seek(display, controller.media_info.start_time * 1000) self.seek(display, controller.media_info.start_time * 1000)
controller.media_info.length = \ controller.media_info.length = \
@ -190,8 +192,6 @@ class VlcPlayer(MediaPlayer):
self.state = MediaState.Playing self.state = MediaState.Playing
display.vlcWidget.raise_() display.vlcWidget.raise_()
return True return True
else:
return False
def pause(self, display): def pause(self, display):
if display.vlcMedia.get_state() != vlc.State.Playing: if display.vlcMedia.get_state() != vlc.State.Playing:

View File

@ -339,7 +339,7 @@ class WebkitPlayer(MediaPlayer):
else: else:
display.frame.evaluateJavaScript(u'show_video("play");') display.frame.evaluateJavaScript(u'show_video("play");')
if start_time > 0: if start_time > 0:
self.seek(display, controller.media_info.start_time*1000) self.seek(display, controller.media_info.start_time * 1000)
# TODO add playing check and get the correct media length # TODO add playing check and get the correct media length
controller.media_info.length = length controller.media_info.length = length
self.state = MediaState.Playing self.state = MediaState.Playing
@ -375,11 +375,11 @@ class WebkitPlayer(MediaPlayer):
controller = display.controller controller = display.controller
if controller.media_info.is_flash: if controller.media_info.is_flash:
seek = seekVal seek = seekVal
display.frame.evaluateJavaScript( \ display.frame.evaluateJavaScript(
u'show_flash("seek", null, null, "%s");' % (seek)) u'show_flash("seek", null, null, "%s");' % (seek))
else: else:
seek = float(seekVal)/1000 seek = float(seekVal) / 1000
display.frame.evaluateJavaScript( \ display.frame.evaluateJavaScript(
u'show_video("seek", null, null, null, "%f");' % (seek)) u'show_video("seek", null, null, null, "%f");' % (seek))
def reset(self, display): def reset(self, display):
@ -406,24 +406,24 @@ class WebkitPlayer(MediaPlayer):
def update_ui(self, display): def update_ui(self, display):
controller = display.controller controller = display.controller
if controller.media_info.is_flash: if controller.media_info.is_flash:
currentTime = display.frame.evaluateJavaScript( \ currentTime = display.frame.evaluateJavaScript(
u'show_flash("currentTime");').toInt()[0] u'show_flash("currentTime");').toInt()[0]
length = display.frame.evaluateJavaScript( \ length = display.frame.evaluateJavaScript(
u'show_flash("length");').toInt()[0] u'show_flash("length");').toInt()[0]
else: else:
if display.frame.evaluateJavaScript( \ if display.frame.evaluateJavaScript(
u'show_video("isEnded");').toString() == 'true': u'show_video("isEnded");').toString() == 'true':
self.stop(display) self.stop(display)
(currentTime, ok) = display.frame.evaluateJavaScript( \ (currentTime, ok) = display.frame.evaluateJavaScript(
u'show_video("currentTime");').toFloat() u'show_video("currentTime");').toFloat()
# check if conversion was ok and value is not 'NaN' # check if conversion was ok and value is not 'NaN'
if ok and currentTime != float('inf'): if ok and currentTime != float('inf'):
currentTime = int(currentTime*1000) currentTime = int(currentTime * 1000)
(length, ok) = display.frame.evaluateJavaScript( \ (length, ok) = display.frame.evaluateJavaScript(
u'show_video("length");').toFloat() u'show_video("length");').toFloat()
# check if conversion was ok and value is not 'NaN' # check if conversion was ok and value is not 'NaN'
if ok and length != float('inf'): if ok and length != float('inf'):
length = int(length*1000) length = int(length * 1000)
if currentTime > 0: if currentTime > 0:
controller.media_info.length = length controller.media_info.length = length
controller.seekSlider.setMaximum(length) controller.seekSlider.setMaximum(length)

View File

@ -102,9 +102,9 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
self.versionNumberLabel.setText(self.activePlugin.version) self.versionNumberLabel.setText(self.activePlugin.version)
self.aboutTextBrowser.setHtml(self.activePlugin.about()) self.aboutTextBrowser.setHtml(self.activePlugin.about())
self.programaticChange = True self.programaticChange = True
status = 1 status = PluginStatus.Active
if self.activePlugin.status == PluginStatus.Active: if self.activePlugin.status == PluginStatus.Active:
status = 0 status = PluginStatus.Inactive
self.statusComboBox.setCurrentIndex(status) self.statusComboBox.setCurrentIndex(status)
self.statusComboBox.setEnabled(True) self.statusComboBox.setEnabled(True)
self.programaticChange = False self.programaticChange = False
@ -129,7 +129,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
def onStatusComboBoxChanged(self, status): def onStatusComboBoxChanged(self, status):
if self.programaticChange or status == PluginStatus.Disabled: if self.programaticChange or status == PluginStatus.Disabled:
return return
if status == 0: if status == PluginStatus.Inactive:
Receiver.send_message(u'cursor_busy') Receiver.send_message(u'cursor_busy')
self.activePlugin.toggleStatus(PluginStatus.Active) self.activePlugin.toggleStatus(PluginStatus.Active)
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')

View File

@ -33,6 +33,7 @@ from lxml import html
from openlp.core.lib import translate, get_text_file_string, Receiver from openlp.core.lib import translate, get_text_file_string, Receiver
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.core.lib.settings import Settings
from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
@ -120,7 +121,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
self.zoom = 0 self.zoom = 0
self.setupUi(self) self.setupUi(self)
# Load the settings for the dialog. # Load the settings for the dialog.
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(u'advanced') settings.beginGroup(u'advanced')
self.slideTextCheckBox.setChecked(settings.value( self.slideTextCheckBox.setChecked(settings.value(
u'print slide text', QtCore.QVariant(False)).toBool()) u'print slide text', QtCore.QVariant(False)).toBool())
@ -318,7 +319,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
elif display == ZoomSize.TwentyFive: elif display == ZoomSize.TwentyFive:
self.previewWidget.fitToWidth() self.previewWidget.fitToWidth()
self.previewWidget.zoomIn(0.25) self.previewWidget.zoomIn(0.25)
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(u'advanced') settings.beginGroup(u'advanced')
settings.setValue(u'display size', QtCore.QVariant(display)) settings.setValue(u'display size', QtCore.QVariant(display))
settings.endGroup() settings.endGroup()
@ -389,7 +390,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
Save the settings and close the dialog. Save the settings and close the dialog.
""" """
# Save the settings for this dialog. # Save the settings for this dialog.
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(u'advanced') settings.beginGroup(u'advanced')
settings.setValue(u'print slide text', settings.setValue(u'print slide text',
QtCore.QVariant(self.slideTextCheckBox.isChecked())) QtCore.QVariant(self.slideTextCheckBox.isChecked()))

View File

@ -34,6 +34,7 @@ import copy
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Receiver, translate from openlp.core.lib import Receiver, translate
from openlp.core.lib.settings import Settings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -245,7 +246,7 @@ class ScreenList(object):
""" """
Loads the screen size and the monitor number from the settings. Loads the screen size and the monitor number from the settings.
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(u'general') settings.beginGroup(u'general')
self.set_current_display(settings.value(u'monitor', self.set_current_display(settings.value(u'monitor',
QtCore.QVariant(self.display_count - 1)).toInt()[0]) QtCore.QVariant(self.display_count - 1)).toInt()[0])

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.ui import create_button_box, create_button from openlp.core.lib.ui import create_button_box, create_button

View File

@ -40,6 +40,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \ from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \
ItemCapabilities, SettingsManager, translate, str_to_bool ItemCapabilities, SettingsManager, translate, str_to_bool
from openlp.core.lib.theme import ThemeLevel from openlp.core.lib.theme import ThemeLevel
from openlp.core.lib.settings import Settings
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
create_widget_action, find_and_set_in_combo_box create_widget_action, find_and_set_in_combo_box
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
@ -274,7 +275,7 @@ class ServiceManager(QtGui.QWidget):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'service_item_update'), self.serviceItemUpdate) QtCore.SIGNAL(u'service_item_update'), self.serviceItemUpdate)
# Last little bits of setting up # Last little bits of setting up
self.service_theme = unicode(QtCore.QSettings().value( self.service_theme = unicode(Settings().value(
self.mainwindow.serviceManagerSettingsSection + u'/service theme', self.mainwindow.serviceManagerSettingsSection + u'/service theme',
QtCore.QVariant(u'')).toString()) QtCore.QVariant(u'')).toString())
self.servicePath = AppLocation.get_section_data_path(u'servicemanager') self.servicePath = AppLocation.get_section_data_path(u'servicemanager')
@ -352,7 +353,7 @@ class ServiceManager(QtGui.QWidget):
self._fileName = unicode(fileName) self._fileName = unicode(fileName)
self.mainwindow.setServiceModified(self.isModified(), self.mainwindow.setServiceModified(self.isModified(),
self.shortFileName()) self.shortFileName())
QtCore.QSettings(). \ Settings(). \
setValue(u'servicemanager/last file',QtCore.QVariant(fileName)) setValue(u'servicemanager/last file',QtCore.QVariant(fileName))
def fileName(self): def fileName(self):
@ -371,7 +372,7 @@ class ServiceManager(QtGui.QWidget):
""" """
Triggered when Config dialog is updated. Triggered when Config dialog is updated.
""" """
self.expandTabs = QtCore.QSettings().value( self.expandTabs = Settings().value(
u'advanced/expand service item', u'advanced/expand service item',
QtCore.QVariant(u'False')).toBool() QtCore.QVariant(u'False')).toBool()
@ -444,7 +445,7 @@ class ServiceManager(QtGui.QWidget):
self.setFileName(u'') self.setFileName(u'')
self.serviceId += 1 self.serviceId += 1
self.setModified(False) self.setModified(False)
QtCore.QSettings(). \ Settings(). \
setValue(u'servicemanager/last file',QtCore.QVariant(u'')) setValue(u'servicemanager/last file',QtCore.QVariant(u''))
Receiver.send_message(u'servicemanager_new_service') Receiver.send_message(u'servicemanager_new_service')
@ -580,10 +581,7 @@ class ServiceManager(QtGui.QWidget):
return self.saveFileAs() return self.saveFileAs()
self.mainwindow.addRecentFile(path_file_name) self.mainwindow.addRecentFile(path_file_name)
self.setModified(False) self.setModified(False)
try:
delete_file(temp_file_name) delete_file(temp_file_name)
except:
pass
return success return success
def saveFileAs(self): def saveFileAs(self):
@ -591,17 +589,17 @@ class ServiceManager(QtGui.QWidget):
Get a file name and then call :func:`ServiceManager.saveFile` to Get a file name and then call :func:`ServiceManager.saveFile` to
save the file. save the file.
""" """
default_service_enabled = QtCore.QSettings().value( default_service_enabled = Settings().value(
u'advanced/default service enabled', QtCore.QVariant(True)).toBool() u'advanced/default service enabled', QtCore.QVariant(True)).toBool()
if default_service_enabled: if default_service_enabled:
service_day = QtCore.QSettings().value( service_day = Settings().value(
u'advanced/default service day', 7).toInt()[0] u'advanced/default service day', 7).toInt()[0]
if service_day == 7: if service_day == 7:
time = datetime.now() time = datetime.now()
else: else:
service_hour = QtCore.QSettings().value( service_hour = Settings().value(
u'advanced/default service hour', 11).toInt()[0] u'advanced/default service hour', 11).toInt()[0]
service_minute = QtCore.QSettings().value( service_minute = Settings().value(
u'advanced/default service minute', 0).toInt()[0] u'advanced/default service minute', 0).toInt()[0]
now = datetime.now() now = datetime.now()
day_delta = service_day - now.weekday() day_delta = service_day - now.weekday()
@ -609,7 +607,7 @@ class ServiceManager(QtGui.QWidget):
day_delta += 7 day_delta += 7
time = now + timedelta(days=day_delta) time = now + timedelta(days=day_delta)
time = time.replace(hour=service_hour, minute=service_minute) time = time.replace(hour=service_hour, minute=service_minute)
default_pattern = unicode(QtCore.QSettings().value( default_pattern = unicode(Settings().value(
u'advanced/default service name', u'advanced/default service name',
translate('OpenLP.AdvancedTab', 'Service %Y-%m-%d %H-%M', translate('OpenLP.AdvancedTab', 'Service %Y-%m-%d %H-%M',
'This may not contain any of the following characters: ' 'This may not contain any of the following characters: '
@ -690,7 +688,7 @@ class ServiceManager(QtGui.QWidget):
self.setFileName(fileName) self.setFileName(fileName)
self.mainwindow.addRecentFile(fileName) self.mainwindow.addRecentFile(fileName)
self.setModified(False) self.setModified(False)
QtCore.QSettings().setValue( Settings().setValue(
'servicemanager/last file', QtCore.QVariant(fileName)) 'servicemanager/last file', QtCore.QVariant(fileName))
else: else:
critical_error_message_box( critical_error_message_box(
@ -732,7 +730,7 @@ class ServiceManager(QtGui.QWidget):
service was last closed. Can be blank if there was no service service was last closed. Can be blank if there was no service
present. present.
""" """
fileName = QtCore.QSettings(). \ fileName = Settings(). \
value(u'servicemanager/last file',QtCore.QVariant(u'')).toString() value(u'servicemanager/last file',QtCore.QVariant(u'')).toString()
if fileName: if fileName:
self.loadFile(fileName) self.loadFile(fileName)
@ -1104,7 +1102,7 @@ class ServiceManager(QtGui.QWidget):
log.debug(u'onThemeComboBoxSelected') log.debug(u'onThemeComboBoxSelected')
self.service_theme = unicode(self.themeComboBox.currentText()) self.service_theme = unicode(self.themeComboBox.currentText())
self.mainwindow.renderer.set_service_theme(self.service_theme) self.mainwindow.renderer.set_service_theme(self.service_theme)
QtCore.QSettings().setValue( Settings().setValue(
self.mainwindow.serviceManagerSettingsSection + self.mainwindow.serviceManagerSettingsSection +
u'/service theme', u'/service theme',
QtCore.QVariant(self.service_theme)) QtCore.QVariant(self.service_theme))
@ -1285,7 +1283,7 @@ class ServiceManager(QtGui.QWidget):
if self.serviceItems[item][u'service_item'].is_valid: if self.serviceItems[item][u'service_item'].is_valid:
self.mainwindow.liveController.addServiceManagerItem( self.mainwindow.liveController.addServiceManagerItem(
self.serviceItems[item][u'service_item'], child) self.serviceItems[item][u'service_item'], child)
if QtCore.QSettings().value( if Settings().value(
self.mainwindow.generalSettingsSection + u'/auto preview', self.mainwindow.generalSettingsSection + u'/auto preview',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
item += 1 item += 1

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import translate, SpellTextEdit from openlp.core.lib import translate, SpellTextEdit
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -29,7 +29,7 @@ The :mod:`settingsform` provides a user interface for the OpenLP settings
""" """
import logging import logging
from PyQt4 import QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, build_icon, PluginStatus from openlp.core.lib import Receiver, build_icon, PluginStatus
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab

View File

@ -31,6 +31,7 @@ import re
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver from openlp.core.lib import Receiver
from openlp.core.lib.settings import Settings
from openlp.core.utils import translate from openlp.core.utils import translate
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList
from shortcutlistdialog import Ui_ShortcutListDialog from shortcutlistdialog import Ui_ShortcutListDialog
@ -337,7 +338,7 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
Save the shortcuts. **Note**, that we do not have to load the shortcuts, Save the shortcuts. **Note**, that we do not have to load the shortcuts,
as they are loaded in :class:`~openlp.core.utils.ActionList`. as they are loaded in :class:`~openlp.core.utils.ActionList`.
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(u'shortcuts') settings.beginGroup(u'shortcuts')
for category in self.action_list.categories: for category in self.action_list.categories:
# Check if the category is for internal use only. # Check if the category is for internal use only.

View File

@ -35,6 +35,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \ from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \
translate, build_icon, build_html, PluginManager, ServiceItem translate, build_icon, build_html, PluginManager, ServiceItem
from openlp.core.lib.ui import UiStrings, create_action from openlp.core.lib.ui import UiStrings, create_action
from openlp.core.lib.settings import Settings
from openlp.core.lib import SlideLimits, ServiceItemAction from openlp.core.lib import SlideLimits, ServiceItemAction
from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList
from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.utils.actions import ActionList, CategoryOrder
@ -237,7 +238,7 @@ class SlideController(Controller):
text=UiStrings().PlaySlidesToEnd, text=UiStrings().PlaySlidesToEnd,
icon=u':/media/media_time.png', checked=False, shortcuts=[], icon=u':/media/media_time.png', checked=False, shortcuts=[],
category=self.category, triggers=self.onPlaySlidesOnce) category=self.category, triggers=self.onPlaySlidesOnce)
if QtCore.QSettings().value(self.parent().generalSettingsSection + if Settings().value(self.parent().generalSettingsSection +
u'/enable slide loop', QtCore.QVariant(True)).toBool(): u'/enable slide loop', QtCore.QVariant(True)).toBool():
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop) self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
else: else:
@ -662,7 +663,7 @@ class SlideController(Controller):
""" """
Updates the Slide Limits variable from the settings. Updates the Slide Limits variable from the settings.
""" """
self.slide_limits = QtCore.QSettings().value( self.slide_limits = Settings().value(
self.parent().advancedSettingsSection + u'/slide limits', self.parent().advancedSettingsSection + u'/slide limits',
QtCore.QVariant(SlideLimits.End)).toInt()[0] QtCore.QVariant(SlideLimits.End)).toInt()[0]
@ -692,7 +693,7 @@ class SlideController(Controller):
self.playSlidesLoop.setChecked(False) self.playSlidesLoop.setChecked(False)
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png')) self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
if item.is_text(): if item.is_text():
if QtCore.QSettings().value( if Settings().value(
self.parent().songsSettingsSection + u'/display songbar', self.parent().songsSettingsSection + u'/display songbar',
QtCore.QVariant(True)).toBool() and self.slideList: QtCore.QVariant(True)).toBool() and self.slideList:
self.songMenu.show() self.songMenu.show()
@ -813,11 +814,11 @@ class SlideController(Controller):
QtCore.QObject.connect(action, QtCore.QObject.connect(action,
QtCore.SIGNAL(u'triggered(bool)'), QtCore.SIGNAL(u'triggered(bool)'),
self.onTrackTriggered) self.onTrackTriggered)
self.display.audioPlayer.repeat = QtCore.QSettings().value( self.display.audioPlayer.repeat = Settings().value(
self.parent().generalSettingsSection + \ self.parent().generalSettingsSection + \
u'/audio repeat list', u'/audio repeat list',
QtCore.QVariant(False)).toBool() QtCore.QVariant(False)).toBool()
if QtCore.QSettings().value( if Settings().value(
self.parent().generalSettingsSection + \ self.parent().generalSettingsSection + \
u'/audio start paused', u'/audio start paused',
QtCore.QVariant(True)).toBool(): QtCore.QVariant(True)).toBool():
@ -930,7 +931,7 @@ class SlideController(Controller):
Allow the main display to blank the main display at startup time Allow the main display to blank the main display at startup time
""" """
log.debug(u'mainDisplaySetBackground live = %s' % self.isLive) log.debug(u'mainDisplaySetBackground live = %s' % self.isLive)
display_type = QtCore.QSettings().value( display_type = Settings().value(
self.parent().generalSettingsSection + u'/screen blank', self.parent().generalSettingsSection + u'/screen blank',
QtCore.QVariant(u'')).toString() QtCore.QVariant(u'')).toString()
if self.screens.which_screen(self.window()) != \ if self.screens.which_screen(self.window()) != \
@ -971,11 +972,11 @@ class SlideController(Controller):
self.themeScreen.setChecked(False) self.themeScreen.setChecked(False)
self.desktopScreen.setChecked(False) self.desktopScreen.setChecked(False)
if checked: if checked:
QtCore.QSettings().setValue( Settings().setValue(
self.parent().generalSettingsSection + u'/screen blank', self.parent().generalSettingsSection + u'/screen blank',
QtCore.QVariant(u'blanked')) QtCore.QVariant(u'blanked'))
else: else:
QtCore.QSettings().remove( Settings().remove(
self.parent().generalSettingsSection + u'/screen blank') self.parent().generalSettingsSection + u'/screen blank')
self.blankPlugin() self.blankPlugin()
self.updatePreview() self.updatePreview()
@ -992,11 +993,11 @@ class SlideController(Controller):
self.themeScreen.setChecked(checked) self.themeScreen.setChecked(checked)
self.desktopScreen.setChecked(False) self.desktopScreen.setChecked(False)
if checked: if checked:
QtCore.QSettings().setValue( Settings().setValue(
self.parent().generalSettingsSection + u'/screen blank', self.parent().generalSettingsSection + u'/screen blank',
QtCore.QVariant(u'themed')) QtCore.QVariant(u'themed'))
else: else:
QtCore.QSettings().remove( Settings().remove(
self.parent().generalSettingsSection + u'/screen blank') self.parent().generalSettingsSection + u'/screen blank')
self.blankPlugin() self.blankPlugin()
self.updatePreview() self.updatePreview()
@ -1013,11 +1014,11 @@ class SlideController(Controller):
self.themeScreen.setChecked(False) self.themeScreen.setChecked(False)
self.desktopScreen.setChecked(checked) self.desktopScreen.setChecked(checked)
if checked: if checked:
QtCore.QSettings().setValue( Settings().setValue(
self.parent().generalSettingsSection + u'/screen blank', self.parent().generalSettingsSection + u'/screen blank',
QtCore.QVariant(u'hidden')) QtCore.QVariant(u'hidden'))
else: else:
QtCore.QSettings().remove( Settings().remove(
self.parent().generalSettingsSection + u'/screen blank') self.parent().generalSettingsSection + u'/screen blank')
self.hidePlugin(checked) self.hidePlugin(checked)
self.updatePreview() self.updatePreview()
@ -1311,7 +1312,7 @@ class SlideController(Controller):
""" """
triggered by clicking the Preview slide items triggered by clicking the Preview slide items
""" """
if QtCore.QSettings().value(u'advanced/double click live', if Settings().value(u'advanced/double click live',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
# Live and Preview have issues if we have video or presentations # Live and Preview have issues if we have video or presentations
# playing in both at the same time. # playing in both at the same time.

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -40,6 +40,7 @@ from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, \
check_directory_exists, create_thumb, validate_thumb check_directory_exists, create_thumb, validate_thumb
from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \ from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \
BackgroundGradientType BackgroundGradientType
from openlp.core.lib.settings import Settings
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
create_widget_action create_widget_action
from openlp.core.theme import Theme from openlp.core.theme import Theme
@ -164,7 +165,7 @@ class ThemeManager(QtGui.QWidget):
""" """
Triggered when Config dialog is updated. Triggered when Config dialog is updated.
""" """
self.global_theme = unicode(QtCore.QSettings().value( self.global_theme = unicode(Settings().value(
self.settingsSection + u'/global theme', self.settingsSection + u'/global theme',
QtCore.QVariant(u'')).toString()) QtCore.QVariant(u'')).toString())
@ -244,7 +245,7 @@ class ThemeManager(QtGui.QWidget):
name = unicode(translate('OpenLP.ThemeManager', name = unicode(translate('OpenLP.ThemeManager',
'%s (default)')) % self.global_theme '%s (default)')) % self.global_theme
self.themeListWidget.item(count).setText(name) self.themeListWidget.item(count).setText(name)
QtCore.QSettings().setValue( Settings().setValue(
self.settingsSection + u'/global theme', self.settingsSection + u'/global theme',
QtCore.QVariant(self.global_theme)) QtCore.QVariant(self.global_theme))
Receiver.send_message(u'theme_update_global', self.global_theme) Receiver.send_message(u'theme_update_global', self.global_theme)
@ -451,7 +452,7 @@ class ThemeManager(QtGui.QWidget):
theme = ThemeXML() theme = ThemeXML()
theme.theme_name = UiStrings().Default theme.theme_name = UiStrings().Default
self._writeTheme(theme, None, None) self._writeTheme(theme, None, None)
QtCore.QSettings().setValue( Settings().setValue(
self.settingsSection + u'/global theme', self.settingsSection + u'/global theme',
QtCore.QVariant(theme.theme_name)) QtCore.QVariant(theme.theme_name))
self.configUpdated() self.configUpdated()
@ -534,6 +535,7 @@ class ThemeManager(QtGui.QWidget):
zip = None zip = None
out_file = None out_file = None
file_xml = None file_xml = None
abort_import = True
try: try:
zip = zipfile.ZipFile(file_name) zip = zipfile.ZipFile(file_name)
xml_file = filter(lambda name: xml_file = filter(lambda name:
@ -770,7 +772,7 @@ class ThemeManager(QtGui.QWidget):
Check to see if theme has been selected and the destructive action Check to see if theme has been selected and the destructive action
is allowed. is allowed.
""" """
self.global_theme = unicode(QtCore.QSettings().value( self.global_theme = unicode(Settings().value(
self.settingsSection + u'/global theme', self.settingsSection + u'/global theme',
QtCore.QVariant(u'')).toString()) QtCore.QVariant(u'')).toString())
if check_item_selected(self.themeListWidget, select_text): if check_item_selected(self.themeListWidget, select_text):

View File

@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, Receiver, translate from openlp.core.lib import SettingsTab, Receiver, translate
from openlp.core.lib.theme import ThemeLevel from openlp.core.lib.theme import ThemeLevel
from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box
from openlp.core.lib.settings import Settings
class ThemesTab(SettingsTab): class ThemesTab(SettingsTab):
""" """
@ -132,7 +133,7 @@ class ThemesTab(SettingsTab):
'any themes associated with either the service or the songs.')) 'any themes associated with either the service or the songs.'))
def load(self): def load(self):
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
self.theme_level = settings.value( self.theme_level = settings.value(
u'theme level', ThemeLevel.Song).toInt()[0] u'theme level', ThemeLevel.Song).toInt()[0]
@ -146,7 +147,7 @@ class ThemesTab(SettingsTab):
self.SongLevelRadioButton.setChecked(True) self.SongLevelRadioButton.setChecked(True)
def save(self): def save(self):
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
settings.setValue(u'theme level', QtCore.QVariant(self.theme_level)) settings.setValue(u'theme level', QtCore.QVariant(self.theme_level))
settings.setValue(u'global theme', QtCore.QVariant(self.global_theme)) settings.setValue(u'global theme', QtCore.QVariant(self.global_theme))
@ -183,7 +184,7 @@ class ThemesTab(SettingsTab):
[u'Bible Theme', u'Song Theme'] [u'Bible Theme', u'Song Theme']
""" """
# Reload as may have been triggered by the ThemeManager. # Reload as may have been triggered by the ThemeManager.
self.global_theme = unicode(QtCore.QSettings().value( self.global_theme = unicode(Settings().value(
self.settingsSection + u'/global theme', self.settingsSection + u'/global theme',
QtCore.QVariant(u'')).toString()) QtCore.QVariant(u'')).toString())
self.DefaultComboBox.clear() self.DefaultComboBox.clear()

View File

@ -44,20 +44,9 @@ class WizardStrings(object):
# Applications/Formats we import from or export to. These get used in # Applications/Formats we import from or export to. These get used in
# multiple places but do not need translating unless you find evidence of # multiple places but do not need translating unless you find evidence of
# the writers translating their own product name. # the writers translating their own product name.
CCLI = u'CCLI/SongSelect'
CSV = u'CSV' CSV = u'CSV'
DB = u'DreamBeam'
EW = u'EasyWorship'
ES = u'EasySlides'
FP = u'Foilpresenter'
OL = u'OpenLyrics'
OS = u'OpenSong' OS = u'OpenSong'
OSIS = u'OSIS' OSIS = u'OSIS'
PS = u'PowerSong 1.0'
SB = u'SongBeamer'
SoF = u'Songs of Fellowship'
SSP = u'SongShow Plus'
WoW = u'Words of Worship'
# These strings should need a good reason to be retranslated elsewhere. # These strings should need a good reason to be retranslated elsewhere.
FinishedImport = translate('OpenLP.Ui', 'Finished import.') FinishedImport = translate('OpenLP.Ui', 'Finished import.')
FormatLabel = translate('OpenLP.Ui', 'Format:') FormatLabel = translate('OpenLP.Ui', 'Format:')
@ -76,10 +65,12 @@ class WizardStrings(object):
PercentSymbolFormat = unicode(translate('OpenLP.Ui', '%p%')) PercentSymbolFormat = unicode(translate('OpenLP.Ui', '%p%'))
Ready = translate('OpenLP.Ui', 'Ready.') Ready = translate('OpenLP.Ui', 'Ready.')
StartingImport = translate('OpenLP.Ui', 'Starting import...') StartingImport = translate('OpenLP.Ui', 'Starting import...')
YouSpecifyFile = unicode(translate('OpenLP.Ui', 'You need to specify at ' YouSpecifyFile = unicode(translate('OpenLP.Ui', 'You need to specify one '
'%s file to import from.', 'A file type e.g. OpenSong'))
YouSpecifyFiles = unicode(translate('OpenLP.Ui', 'You need to specify at '
'least one %s file to import from.', 'A file type e.g. OpenSong')) 'least one %s file to import from.', 'A file type e.g. OpenSong'))
YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify a ' YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify one '
'%s folder to import from.', 'A file type e.g. OpenSong')) '%s folder to import from.', 'A song format e.g. PowerSong'))
class OpenLPWizard(QtGui.QWizard): class OpenLPWizard(QtGui.QWizard):
@ -108,7 +99,7 @@ class OpenLPWizard(QtGui.QWizard):
def setupUi(self, image): def setupUi(self, image):
""" """
Set up the wizard UI Set up the wizard UI.
""" """
self.setModal(True) self.setModal(True)
self.setWizardStyle(QtGui.QWizard.ModernStyle) self.setWizardStyle(QtGui.QWizard.ModernStyle)

View File

@ -36,6 +36,8 @@ from subprocess import Popen, PIPE
import sys import sys
import urllib2 import urllib2
from openlp.core.lib.settings import Settings
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
if sys.platform != u'win32' and sys.platform != u'darwin': if sys.platform != u'win32' and sys.platform != u'darwin':
@ -126,6 +128,11 @@ class AppLocation(object):
""" """
Return the path OpenLP stores all its data under. Return the path OpenLP stores all its data under.
""" """
# Check if we have a different data location.
if Settings().contains(u'advanced/data path'):
path = unicode(Settings().value(
u'advanced/data path').toString())
else:
path = AppLocation.get_directory(AppLocation.DataDir) path = AppLocation.get_directory(AppLocation.DataDir)
check_directory_exists(path) check_directory_exists(path)
return path return path
@ -280,7 +287,7 @@ def check_latest_version(current_version):
""" """
version_string = current_version[u'full'] version_string = current_version[u'full']
# set to prod in the distribution config file. # set to prod in the distribution config file.
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(u'general') settings.beginGroup(u'general')
last_test = unicode(settings.value(u'last version test', last_test = unicode(settings.value(u'last version test',
QtCore.QVariant(datetime.now().date())).toString()) QtCore.QVariant(datetime.now().date())).toString())

View File

@ -30,6 +30,8 @@ by the shortcuts system.
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib.settings import Settings
class ActionCategory(object): class ActionCategory(object):
""" """
The :class:`~openlp.core.utils.ActionCategory` class encapsulates a The :class:`~openlp.core.utils.ActionCategory` class encapsulates a
@ -226,7 +228,7 @@ class ActionList(object):
else: else:
self.categories[category].actions.add(action, weight) self.categories[category].actions.add(action, weight)
# Load the shortcut from the config. # Load the shortcut from the config.
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(u'shortcuts') settings.beginGroup(u'shortcuts')
shortcuts = settings.value(action.objectName(), shortcuts = settings.value(action.objectName(),
QtCore.QVariant(action.shortcuts())).toStringList() QtCore.QVariant(action.shortcuts())).toStringList()

View File

@ -35,6 +35,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.settings import Settings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -101,7 +102,7 @@ class LanguageManager(object):
""" """
Retrieve a saved language to use from settings Retrieve a saved language to use from settings
""" """
settings = QtCore.QSettings() settings = Settings()
language = unicode(settings.value( language = unicode(settings.value(
u'general/language', QtCore.QVariant(u'[en]')).toString()) u'general/language', QtCore.QVariant(u'[en]')).toString())
log.info(u'Language file: \'%s\' Loaded from conf file' % language) log.info(u'Language file: \'%s\' Loaded from conf file' % language)
@ -133,7 +134,7 @@ class LanguageManager(object):
language = unicode(qm_list[action_name]) language = unicode(qm_list[action_name])
if LanguageManager.auto_language: if LanguageManager.auto_language:
language = u'[%s]' % language language = u'[%s]' % language
QtCore.QSettings().setValue( Settings().setValue(
u'general/language', QtCore.QVariant(language)) u'general/language', QtCore.QVariant(language))
log.info(u'Language file: \'%s\' written to conf file' % language) log.info(u'Language file: \'%s\' written to conf file' % language)
if message: if message:

View File

@ -32,6 +32,7 @@ from PyQt4 import QtCore
from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.db import Manager from openlp.core.lib.db import Manager
from openlp.core.lib.ui import create_action, UiStrings from openlp.core.lib.ui import create_action, UiStrings
from openlp.core.lib.settings import Settings
from openlp.core.lib.theme import VerticalType from openlp.core.lib.theme import VerticalType
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList
from openlp.plugins.alerts.lib import AlertsManager, AlertsTab from openlp.plugins.alerts.lib import AlertsManager, AlertsTab
@ -160,7 +161,7 @@ class AlertsPlugin(Plugin):
def toggleAlertsState(self): def toggleAlertsState(self):
self.alertsActive = not self.alertsActive self.alertsActive = not self.alertsActive
QtCore.QSettings().setValue(self.settingsSection + u'/active', Settings().setValue(self.settingsSection + u'/active',
QtCore.QVariant(self.alertsActive)) QtCore.QVariant(self.alertsActive))
def onAlertsTrigger(self): def onAlertsTrigger(self):

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import build_icon, translate from openlp.core.lib import build_icon, translate
from openlp.core.lib.ui import create_button, create_button_box from openlp.core.lib.ui import create_button, create_button_box

View File

@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate, Receiver from openlp.core.lib import SettingsTab, translate, Receiver
from openlp.core.ui import AlertLocation from openlp.core.ui import AlertLocation
from openlp.core.lib.ui import UiStrings, create_valign_selection_widgets from openlp.core.lib.ui import UiStrings, create_valign_selection_widgets
from openlp.core.lib.settings import Settings
class AlertsTab(SettingsTab): class AlertsTab(SettingsTab):
""" """
@ -152,7 +153,7 @@ class AlertsTab(SettingsTab):
self.updateDisplay() self.updateDisplay()
def load(self): def load(self):
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
self.timeout = settings.value(u'timeout', QtCore.QVariant(5)).toInt()[0] self.timeout = settings.value(u'timeout', QtCore.QVariant(5)).toInt()[0]
self.font_color = unicode(settings.value( self.font_color = unicode(settings.value(
@ -180,7 +181,7 @@ class AlertsTab(SettingsTab):
self.changed = False self.changed = False
def save(self): def save(self):
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
# Check value has changed as no event handles this field # Check value has changed as no event handles this field
if settings.value(u'location', QtCore.QVariant(1)).toInt()[0] != \ if settings.value(u'location', QtCore.QVariant(1)).toInt()[0] != \

View File

@ -31,6 +31,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.ui import create_action, UiStrings from openlp.core.lib.ui import create_action, UiStrings
from openlp.core.lib.settings import Settings
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList
from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem
from openlp.plugins.bibles.forms import BibleUpgradeForm from openlp.plugins.bibles.forms import BibleUpgradeForm
@ -62,8 +63,7 @@ class BiblePlugin(Plugin):
# unicode(UiStrings().Export)) # unicode(UiStrings().Export))
# Set to invisible until we can export bibles # Set to invisible until we can export bibles
self.exportBibleItem.setVisible(False) self.exportBibleItem.setVisible(False)
if self.manager.old_bible_databases: self.toolsUpgradeItem.setVisible(bool(self.manager.old_bible_databases))
self.toolsUpgradeItem.setVisible(True)
def finalise(self): def finalise(self):
""" """
@ -91,7 +91,7 @@ class BiblePlugin(Plugin):
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No)) == QtGui.QMessageBox.Yes: QtGui.QMessageBox.No)) == QtGui.QMessageBox.Yes:
self.onToolsUpgradeItemTriggered() self.onToolsUpgradeItemTriggered()
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
if settings.contains(u'bookname language'): if settings.contains(u'bookname language'):
settings.setValue(u'book name language', settings.value( settings.setValue(u'book name language', settings.value(

View File

@ -36,6 +36,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, translate from openlp.core.lib import Receiver, translate
from openlp.core.lib.db import delete_database from openlp.core.lib.db import delete_database
from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.lib.settings import Settings
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
from openlp.plugins.bibles.lib.manager import BibleFormat from openlp.plugins.bibles.lib.manager import BibleFormat
@ -590,7 +591,7 @@ class BibleImportForm(OpenLPWizard):
""" """
Set default values for the wizard pages. Set default values for the wizard pages.
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.plugin.settingsSection) settings.beginGroup(self.plugin.settingsSection)
self.restart() self.restart()
self.finishButton.setVisible(False) self.finishButton.setVisible(False)

View File

@ -36,6 +36,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, SettingsManager, translate, \ from openlp.core.lib import Receiver, SettingsManager, translate, \
check_directory_exists check_directory_exists
from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.lib.settings import Settings
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
from openlp.core.utils import AppLocation, delete_file from openlp.core.utils import AppLocation, delete_file
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, \ from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, \
@ -341,7 +342,7 @@ class BibleUpgradeForm(OpenLPWizard):
Set default values for the wizard pages. Set default values for the wizard pages.
""" """
log.debug(u'BibleUpgrade setDefaults') log.debug(u'BibleUpgrade setDefaults')
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.plugin.settingsSection) settings.beginGroup(self.plugin.settingsSection)
self.stop_import_flag = False self.stop_import_flag = False
self.success.clear() self.success.clear()

View File

@ -24,7 +24,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -31,9 +31,8 @@ plugin.
import logging import logging
import re import re
from PyQt4 import QtCore
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.settings import Settings
from openlp.plugins.bibles.lib.db import BiblesResourcesDB from openlp.plugins.bibles.lib.db import BiblesResourcesDB
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -185,7 +184,7 @@ def update_reference_separators():
':|v|V|verse|verses;;-|to;;,|and;;end', ':|v|V|verse|verses;;-|to;;,|and;;end',
'Double-semicolon delimited separators for parsing references. ' 'Double-semicolon delimited separators for parsing references. '
'Consult the developers for further information.')).split(u';;') 'Consult the developers for further information.')).split(u';;')
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(u'bibles') settings.beginGroup(u'bibles')
custom_separators = [ custom_separators = [
unicode(settings.value(u'verse separator').toString()), unicode(settings.value(u'verse separator').toString()),

View File

@ -31,6 +31,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, SettingsTab, translate from openlp.core.lib import Receiver, SettingsTab, translate
from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box
from openlp.core.lib.settings import Settings
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \ from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \
update_reference_separators, get_reference_separator, LanguageSelection update_reference_separators, get_reference_separator, LanguageSelection
@ -414,7 +415,7 @@ class BiblesTab(SettingsTab):
self.getGreyTextPalette(True)) self.getGreyTextPalette(True))
def load(self): def load(self):
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
self.show_new_chapters = settings.value( self.show_new_chapters = settings.value(
u'display new chapter', QtCore.QVariant(False)).toBool() u'display new chapter', QtCore.QVariant(False)).toBool()
@ -488,7 +489,7 @@ class BiblesTab(SettingsTab):
settings.endGroup() settings.endGroup()
def save(self): def save(self):
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
settings.setValue(u'display new chapter', settings.setValue(u'display new chapter',
QtCore.QVariant(self.show_new_chapters)) QtCore.QVariant(self.show_new_chapters))

View File

@ -73,7 +73,7 @@ class CSVBible(BibleDB):
def __init__(self, parent, **kwargs): def __init__(self, parent, **kwargs):
""" """
Loads a Bible from a set of CVS files. Loads a Bible from a set of CSV files.
This class assumes the files contain all the information and This class assumes the files contain all the information and
a clean bible is being loaded. a clean bible is being loaded.
""" """

View File

@ -63,6 +63,7 @@ class Verse(BaseModel):
""" """
pass pass
def init_schema(url): def init_schema(url):
""" """
Setup a bible database connection and initialise the database schema. Setup a bible database connection and initialise the database schema.

View File

@ -43,6 +43,15 @@ from openlp.plugins.bibles.lib import SearchResults
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, \ from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, \
Book Book
UGLY_CHARS = {
u'\u2014': u' - ',
u'\u2018': u'\'',
u'\u2019': u'\'',
u'\u201c': u'"',
u'\u201d': u'"',
u'&nbsp;': u' '
}
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class BGExtract(object): class BGExtract(object):
@ -54,6 +63,103 @@ class BGExtract(object):
self.proxy_url = proxy_url self.proxy_url = proxy_url
socket.setdefaulttimeout(30) socket.setdefaulttimeout(30)
def _remove_elements(self, parent, tag, class_=None):
"""
Remove a particular element from the BeautifulSoup tree.
``parent``
The element from which items need to be removed.
``tag``
A string of the tab type, e.g. "div"
``class_``
An HTML class attribute for further qualification.
"""
if class_:
all_tags = parent.findAll(tag, class_)
else:
all_tags = parent.findAll(tag)
for element in all_tags:
element.extract()
def _extract_verse(self, tag):
"""
Extract a verse (or part of a verse) from a tag.
``tag``
The BeautifulSoup Tag element with the stuff we want.
"""
if isinstance(tag, NavigableString):
return None, unicode(tag)
elif tag.get('class') == 'versenum':
verse = unicode(tag.string)\
.replace('[', '').replace(']', '').strip()
return verse, None
elif tag.get('class') == 'chapternum':
verse = '1'
return verse, None
else:
verse, text = None, ''
for child in tag.contents:
c_verse, c_text = self._extract_verse(child)
if c_verse:
verse = c_verse
if text and c_text:
text += c_text
elif c_text is not None:
text = c_text
return verse, text
def _clean_soup(self, tag):
"""
Remove all the rubbish from the HTML page.
``tag``
The base tag within which we want to remove stuff.
"""
self._remove_elements(tag, 'sup', 'crossreference')
self._remove_elements(tag, 'sup', 'footnote')
self._remove_elements(tag, 'div', 'footnotes')
self._remove_elements(tag, 'div', 'crossrefs')
self._remove_elements(tag, 'h3')
def _extract_verses(self, tags):
"""
Extract all the verses from a pre-prepared list of HTML tags.
``tags``
A list of BeautifulSoup Tag elements.
"""
verses = []
tags = tags[::-1]
current_text = ''
for tag in tags:
verse, text = None, ''
for child in tag.contents:
c_verse, c_text = self._extract_verse(child)
if c_verse:
verse = c_verse
if text and c_text:
text += c_text
elif c_text is not None:
text = c_text
if not verse:
current_text = text + ' ' + current_text
else:
text += ' ' + current_text
current_text = ''
if text:
for old, new in UGLY_CHARS.iteritems():
text = text.replace(old, new)
text = u' '.join(text.split())
if verse and text:
verses.append((int(verse.strip()), text))
verse_list = {}
for verse, text in verses[::-1]:
verse_list[verse] = text
return verse_list
def get_bible_chapter(self, version, book_name, chapter): def get_bible_chapter(self, version, book_name, chapter):
""" """
Access and decode Bibles via the BibleGateway website. Access and decode Bibles via the BibleGateway website.
@ -80,60 +186,9 @@ class BGExtract(object):
if not soup: if not soup:
return None return None
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
footnotes = soup.findAll(u'sup', u'footnote') div = soup.find('div', 'result-text-style-normal')
if footnotes: self._clean_soup(div)
for footnote in footnotes: verse_list = self._extract_verses(div.findAll('span', 'text'))
footnote.extract()
crossrefs = soup.findAll(u'sup', u'xref')
if crossrefs:
for crossref in crossrefs:
crossref.extract()
headings = soup.findAll(u'h5')
if headings:
for heading in headings:
heading.extract()
chapter_notes = soup.findAll('div', 'footnotes')
if chapter_notes:
log.debug('Found chapter notes')
for note in chapter_notes:
note.extract()
note_comments = soup.findAll(text=u'end of footnotes')
if note_comments:
for comment in note_comments:
comment.extract()
cleanup = [(re.compile('\s+'), lambda match: ' ')]
verses = BeautifulSoup(str(soup), markupMassage=cleanup)
verse_list = {}
# Cater for inconsistent mark up in the first verse of a chapter.
first_verse = verses.find(u'versenum')
if first_verse and first_verse.contents:
verse_list[1] = unicode(first_verse.contents[0])
for verse in verses(u'sup', u'versenum'):
raw_verse_num = verse.next
clean_verse_num = 0
# Not all verses exist in all translations and may or may not be
# represented by a verse number. If they are not fine, if they are
# it will probably be in a format that breaks int(). We will then
# have no idea what garbage may be sucked in to the verse text so
# if we do not get a clean int() then ignore the verse completely.
try:
clean_verse_num = int(str(raw_verse_num))
except ValueError:
log.warn(u'Illegal verse number in %s %s %s:%s',
version, book_name, chapter, unicode(raw_verse_num))
if clean_verse_num:
verse_text = raw_verse_num.next
part = raw_verse_num.next.next
while not (isinstance(part, Tag) and part.attrMap and
part.attrMap[u'class'] == u'versenum'):
# While we are still in the same verse grab all the text.
if isinstance(part, NavigableString):
verse_text = verse_text + part
if isinstance(part.next, Tag) and part.next.name == u'div':
# Run out of verses so stop.
break
part = part.next
verse_list[clean_verse_num] = unicode(verse_text)
if not verse_list: if not verse_list:
log.debug(u'No content found in the BibleGateway response.') log.debug(u'No content found in the BibleGateway response.')
send_error_message(u'parse') send_error_message(u'parse')

View File

@ -32,6 +32,7 @@ from PyQt4 import QtCore
from openlp.core.lib import Receiver, SettingsManager, translate from openlp.core.lib import Receiver, SettingsManager, translate
from openlp.core.utils import AppLocation, delete_file from openlp.core.utils import AppLocation, delete_file
from openlp.core.lib.settings import Settings
from openlp.plugins.bibles.lib import parse_reference, \ from openlp.plugins.bibles.lib import parse_reference, \
get_reference_separator, LanguageSelection get_reference_separator, LanguageSelection
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
@ -126,7 +127,7 @@ class BibleManager(object):
self.db_cache = None self.db_cache = None
self.path = AppLocation.get_section_data_path(self.settingsSection) self.path = AppLocation.get_section_data_path(self.settingsSection)
self.proxy_name = unicode( self.proxy_name = unicode(
QtCore.QSettings().value(self.settingsSection + u'/proxy name', Settings().value(self.settingsSection + u'/proxy name',
QtCore.QVariant(u'')).toString()) QtCore.QVariant(u'')).toString())
self.suffix = u'.sqlite' self.suffix = u'.sqlite'
self.import_wizard = None self.import_wizard = None
@ -378,7 +379,7 @@ class BibleManager(object):
except (ValueError, TypeError): except (ValueError, TypeError):
language_selection = LanguageSelection.Application language_selection = LanguageSelection.Application
if language_selection is None or language_selection == -1: if language_selection is None or language_selection == -1:
language_selection = QtCore.QSettings().value( language_selection = Settings().value(
self.settingsSection + u'/bookname language', self.settingsSection + u'/bookname language',
QtCore.QVariant(0)).toInt()[0] QtCore.QVariant(0)).toInt()[0]
return language_selection return language_selection

View File

@ -33,6 +33,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
translate, create_separated_list translate, create_separated_list
from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.settings import Settings
from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \ from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \
create_horizontal_adjusting_combo_box, critical_error_message_box, \ create_horizontal_adjusting_combo_box, critical_error_message_box, \
find_and_set_in_combo_box, build_icon find_and_set_in_combo_box, build_icon
@ -294,7 +295,7 @@ class BibleMediaItem(MediaManagerItem):
def configUpdated(self): def configUpdated(self):
log.debug(u'configUpdated') log.debug(u'configUpdated')
if QtCore.QSettings().value(self.settingsSection + u'/second bibles', if Settings().value(self.settingsSection + u'/second bibles',
QtCore.QVariant(True)).toBool(): QtCore.QVariant(True)).toBool():
self.advancedSecondLabel.setVisible(True) self.advancedSecondLabel.setVisible(True)
self.advancedSecondComboBox.setVisible(True) self.advancedSecondComboBox.setVisible(True)
@ -362,7 +363,7 @@ class BibleMediaItem(MediaManagerItem):
translate('BiblesPlugin.MediaItem', 'Text Search'), translate('BiblesPlugin.MediaItem', 'Text Search'),
translate('BiblesPlugin.MediaItem', 'Search Text...')) translate('BiblesPlugin.MediaItem', 'Search Text...'))
]) ])
self.quickSearchEdit.setCurrentSearchType(QtCore.QSettings().value( self.quickSearchEdit.setCurrentSearchType(Settings().value(
u'%s/last search type' % self.settingsSection, u'%s/last search type' % self.settingsSection,
QtCore.QVariant(BibleSearch.Reference)).toInt()[0]) QtCore.QVariant(BibleSearch.Reference)).toInt()[0])
self.configUpdated() self.configUpdated()
@ -386,7 +387,7 @@ class BibleMediaItem(MediaManagerItem):
self.advancedVersionComboBox.addItems(bibles) self.advancedVersionComboBox.addItems(bibles)
self.advancedSecondComboBox.addItems(bibles) self.advancedSecondComboBox.addItems(bibles)
# set the default value # set the default value
bible = QtCore.QSettings().value( bible = Settings().value(
self.settingsSection + u'/advanced bible', self.settingsSection + u'/advanced bible',
QtCore.QVariant(u'')).toString() QtCore.QVariant(u'')).toString()
if bible in bibles: if bible in bibles:
@ -394,7 +395,7 @@ class BibleMediaItem(MediaManagerItem):
self.initialiseAdvancedBible(unicode(bible)) self.initialiseAdvancedBible(unicode(bible))
elif bibles: elif bibles:
self.initialiseAdvancedBible(bibles[0]) self.initialiseAdvancedBible(bibles[0])
bible = QtCore.QSettings().value( bible = Settings().value(
self.settingsSection + u'/quick bible', QtCore.QVariant( self.settingsSection + u'/quick bible', QtCore.QVariant(
self.quickVersionComboBox.currentText())).toString() self.quickVersionComboBox.currentText())).toString()
find_and_set_in_combo_box(self.quickVersionComboBox, bible) find_and_set_in_combo_box(self.quickVersionComboBox, bible)
@ -497,11 +498,11 @@ class BibleMediaItem(MediaManagerItem):
""" """
log.debug(u'updateAutoCompleter') log.debug(u'updateAutoCompleter')
# Save the current search type to the configuration. # Save the current search type to the configuration.
QtCore.QSettings().setValue(u'%s/last search type' % Settings().setValue(u'%s/last search type' %
self.settingsSection, self.settingsSection,
QtCore.QVariant(self.quickSearchEdit.currentSearchType())) QtCore.QVariant(self.quickSearchEdit.currentSearchType()))
# Save the current bible to the configuration. # Save the current bible to the configuration.
QtCore.QSettings().setValue(self.settingsSection + u'/quick bible', Settings().setValue(self.settingsSection + u'/quick bible',
QtCore.QVariant(self.quickVersionComboBox.currentText())) QtCore.QVariant(self.quickVersionComboBox.currentText()))
books = [] books = []
# We have to do a 'Reference Search'. # We have to do a 'Reference Search'.
@ -596,7 +597,7 @@ class BibleMediaItem(MediaManagerItem):
self.advancedStyleComboBox.setCurrentIndex(self.settings.layout_style) self.advancedStyleComboBox.setCurrentIndex(self.settings.layout_style)
self.settings.layoutStyleComboBox.setCurrentIndex( self.settings.layoutStyleComboBox.setCurrentIndex(
self.settings.layout_style) self.settings.layout_style)
QtCore.QSettings().setValue( Settings().setValue(
self.settingsSection + u'/verse layout style', self.settingsSection + u'/verse layout style',
QtCore.QVariant(self.settings.layout_style)) QtCore.QVariant(self.settings.layout_style))
@ -605,12 +606,12 @@ class BibleMediaItem(MediaManagerItem):
self.quickStyleComboBox.setCurrentIndex(self.settings.layout_style) self.quickStyleComboBox.setCurrentIndex(self.settings.layout_style)
self.settings.layoutStyleComboBox.setCurrentIndex( self.settings.layoutStyleComboBox.setCurrentIndex(
self.settings.layout_style) self.settings.layout_style)
QtCore.QSettings().setValue( Settings().setValue(
self.settingsSection + u'/verse layout style', self.settingsSection + u'/verse layout style',
QtCore.QVariant(self.settings.layout_style)) QtCore.QVariant(self.settings.layout_style))
def onAdvancedVersionComboBox(self): def onAdvancedVersionComboBox(self):
QtCore.QSettings().setValue(self.settingsSection + u'/advanced bible', Settings().setValue(self.settingsSection + u'/advanced bible',
QtCore.QVariant(self.advancedVersionComboBox.currentText())) QtCore.QVariant(self.advancedVersionComboBox.currentText()))
self.initialiseAdvancedBible( self.initialiseAdvancedBible(
unicode(self.advancedVersionComboBox.currentText()), unicode(self.advancedVersionComboBox.currentText()),
@ -975,7 +976,7 @@ class BibleMediaItem(MediaManagerItem):
else: else:
service_item.theme = self.settings.bible_theme service_item.theme = self.settings.bible_theme
for slide in raw_slides: for slide in raw_slides:
service_item.add_from_text(slide[:30], slide) service_item.add_from_text(slide)
return True return True
def formatTitle(self, start_bitem, old_bitem): def formatTitle(self, start_bitem, old_bitem):

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import build_icon, translate from openlp.core.lib import build_icon, translate
from openlp.core.lib.ui import UiStrings, create_button_box, create_button from openlp.core.lib.ui import UiStrings, create_button_box, create_button

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import translate, SpellTextEdit, build_icon from openlp.core.lib import translate, SpellTextEdit, build_icon
from openlp.core.lib.ui import UiStrings, create_button, create_button_box from openlp.core.lib.ui import UiStrings, create_button, create_button_box

View File

@ -28,6 +28,7 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate from openlp.core.lib import SettingsTab, translate
from openlp.core.lib.settings import Settings
class CustomTab(SettingsTab): class CustomTab(SettingsTab):
""" """
@ -66,11 +67,11 @@ class CustomTab(SettingsTab):
self.displayFooter = True self.displayFooter = True
def load(self): def load(self):
self.displayFooter = QtCore.QSettings().value( self.displayFooter = Settings().value(
self.settingsSection + u'/display footer', self.settingsSection + u'/display footer',
QtCore.QVariant(True)).toBool() QtCore.QVariant(True)).toBool()
self.displayFooterCheckBox.setChecked(self.displayFooter) self.displayFooterCheckBox.setChecked(self.displayFooter)
def save(self): def save(self):
QtCore.QSettings().setValue(self.settingsSection + u'/display footer', Settings().setValue(self.settingsSection + u'/display footer',
QtCore.QVariant(self.displayFooter)) QtCore.QVariant(self.displayFooter))

View File

@ -34,6 +34,7 @@ from sqlalchemy.sql import or_, func
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
check_item_selected, translate check_item_selected, translate
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.core.lib.settings import Settings
from openlp.plugins.custom.forms import EditCustomForm from openlp.plugins.custom.forms import EditCustomForm
from openlp.plugins.custom.lib import CustomXMLParser from openlp.plugins.custom.lib import CustomXMLParser
from openlp.plugins.custom.lib.db import CustomSlide from openlp.plugins.custom.lib.db import CustomSlide
@ -99,7 +100,7 @@ class CustomMediaItem(MediaManagerItem):
]) ])
self.loadList(self.manager.get_all_objects( self.loadList(self.manager.get_all_objects(
CustomSlide, order_by_ref=CustomSlide.title)) CustomSlide, order_by_ref=CustomSlide.title))
self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value( self.searchTextEdit.setCurrentSearchType(Settings().value(
u'%s/last search type' % self.settingsSection, u'%s/last search type' % self.settingsSection,
QtCore.QVariant(CustomSearch.Titles)).toInt()[0]) QtCore.QVariant(CustomSearch.Titles)).toInt()[0])
@ -209,13 +210,13 @@ class CustomMediaItem(MediaManagerItem):
theme = customSlide.theme_name theme = customSlide.theme_name
if theme: if theme:
service_item.theme = theme service_item.theme = theme
customXML = CustomXMLParser(customSlide.text) custom_xml = CustomXMLParser(customSlide.text)
verseList = customXML.get_verses() verse_list = custom_xml.get_verses()
raw_slides = [verse[1] for verse in verseList] raw_slides = [verse[1] for verse in verse_list]
service_item.title = title service_item.title = title
for slide in raw_slides: for slide in raw_slides:
service_item.add_from_text(slide[:30], slide) service_item.add_from_text(slide)
if QtCore.QSettings().value(self.settingsSection + u'/display footer', if Settings().value(self.settingsSection + u'/display footer',
QtCore.QVariant(True)).toBool() or credit: QtCore.QVariant(True)).toBool() or credit:
service_item.raw_footer.append(u' '.join([title, credit])) service_item.raw_footer.append(u' '.join([title, credit]))
else: else:
@ -224,7 +225,7 @@ class CustomMediaItem(MediaManagerItem):
def onSearchTextButtonClicked(self): def onSearchTextButtonClicked(self):
# Save the current search type to the configuration. # Save the current search type to the configuration.
QtCore.QSettings().setValue(u'%s/last search type' % Settings().setValue(u'%s/last search type' %
self.settingsSection, self.settingsSection,
QtCore.QVariant(self.searchTextEdit.currentSearchType())) QtCore.QVariant(self.searchTextEdit.currentSearchType()))
# Reload the list considering the new search type. # Reload the list considering the new search type.

View File

@ -31,6 +31,7 @@ import logging
from openlp.core.lib import Plugin, StringContent, build_icon, translate, \ from openlp.core.lib import Plugin, StringContent, build_icon, translate, \
Receiver Receiver
from openlp.core.lib.settings import Settings
from openlp.plugins.images.lib import ImageMediaItem, ImageTab from openlp.plugins.images.lib import ImageMediaItem, ImageTab
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -94,6 +95,6 @@ class ImagePlugin(Plugin):
image manager to require updates. Actual update is triggered by the image manager to require updates. Actual update is triggered by the
last part of saving the config. last part of saving the config.
""" """
background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection background = QtGui.QColor(Settings().value(self.settingsSection
+ u'/background color', QtCore.QVariant(u'#000000'))) + u'/background color', QtCore.QVariant(u'#000000')))
self.liveController.imageManager.updateImages(u'image', background) self.liveController.imageManager.updateImages(u'image', background)

View File

@ -28,6 +28,7 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate, Receiver from openlp.core.lib import SettingsTab, translate, Receiver
from openlp.core.lib.settings import Settings
class ImageTab(SettingsTab): class ImageTab(SettingsTab):
""" """
@ -82,7 +83,7 @@ class ImageTab(SettingsTab):
u'background-color: %s' % self.bg_color) u'background-color: %s' % self.bg_color)
def load(self): def load(self):
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
self.bg_color = unicode(settings.value( self.bg_color = unicode(settings.value(
u'background color', QtCore.QVariant(u'#000000')).toString()) u'background color', QtCore.QVariant(u'#000000')).toString())
@ -92,7 +93,7 @@ class ImageTab(SettingsTab):
u'background-color: %s' % self.bg_color) u'background-color: %s' % self.bg_color)
def save(self): def save(self):
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
settings.setValue(u'background color', QtCore.QVariant(self.bg_color)) settings.setValue(u'background color', QtCore.QVariant(self.bg_color))
settings.endGroup() settings.endGroup()

View File

@ -35,6 +35,7 @@ from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
SettingsManager, translate, check_item_selected, check_directory_exists, \ SettingsManager, translate, check_item_selected, check_directory_exists, \
Receiver, create_thumb, validate_thumb Receiver, create_thumb, validate_thumb
from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.lib.settings import Settings
from openlp.core.utils import AppLocation, delete_file, get_images_filter from openlp.core.utils import AppLocation, delete_file, get_images_filter
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -151,7 +152,7 @@ class ImageMediaItem(MediaManagerItem):
def generateSlideData(self, service_item, item=None, xmlVersion=False, def generateSlideData(self, service_item, item=None, xmlVersion=False,
remote=False): remote=False):
background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection background = QtGui.QColor(Settings().value(self.settingsSection
+ u'/background color', QtCore.QVariant(u'#000000'))) + u'/background color', QtCore.QVariant(u'#000000')))
if item: if item:
items = [item] items = [item]
@ -220,7 +221,7 @@ class ImageMediaItem(MediaManagerItem):
if check_item_selected(self.listView, if check_item_selected(self.listView,
translate('ImagePlugin.MediaItem', translate('ImagePlugin.MediaItem',
'You must select an image to replace the background with.')): 'You must select an image to replace the background with.')):
background = QtGui.QColor(QtCore.QSettings().value( background = QtGui.QColor(Settings().value(
self.settingsSection + u'/background color', self.settingsSection + u'/background color',
QtCore.QVariant(u'#000000'))) QtCore.QVariant(u'#000000')))
item = self.listView.selectedIndexes()[0] item = self.listView.selectedIndexes()[0]

View File

@ -29,6 +29,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate, Receiver from openlp.core.lib import SettingsTab, translate, Receiver
from openlp.core.lib.ui import UiStrings, create_button from openlp.core.lib.ui import UiStrings, create_button
from openlp.core.lib.settings import Settings
from openlp.core.ui.media import get_media_players, set_media_players from openlp.core.ui.media import get_media_players, set_media_players
class MediaQCheckBox(QtGui.QCheckBox): class MediaQCheckBox(QtGui.QCheckBox):
""" """
@ -186,7 +187,7 @@ class MediaTab(SettingsTab):
else: else:
checkbox.setChecked(False) checkbox.setChecked(False)
self.updatePlayerList() self.updatePlayerList()
self.overridePlayerCheckBox.setChecked(QtCore.QSettings().value( self.overridePlayerCheckBox.setChecked(Settings().value(
self.settingsSection + u'/override player', self.settingsSection + u'/override player',
QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0]) QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0])
@ -200,9 +201,9 @@ class MediaTab(SettingsTab):
player_string_changed = True player_string_changed = True
override_changed = True override_changed = True
setting_key = self.settingsSection + u'/override player' setting_key = self.settingsSection + u'/override player'
if QtCore.QSettings().value(setting_key).toInt()[0] != \ if Settings().value(setting_key).toInt()[0] != \
self.overridePlayerCheckBox.checkState(): self.overridePlayerCheckBox.checkState():
QtCore.QSettings().setValue(setting_key, Settings().setValue(setting_key,
QtCore.QVariant(self.overridePlayerCheckBox.checkState())) QtCore.QVariant(self.overridePlayerCheckBox.checkState()))
override_changed = True override_changed = True
if override_changed: if override_changed:

View File

@ -30,6 +30,7 @@ import logging
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.settings import Settings
from openlp.plugins.media.lib import MediaMediaItem, MediaTab from openlp.plugins.media.lib import MediaMediaItem, MediaTab
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -126,7 +127,7 @@ class MediaPlugin(Plugin):
we want to check if we have the old "Use Phonon" setting, and convert we want to check if we have the old "Use Phonon" setting, and convert
it to "enable Phonon" and "make it the first one in the list". it to "enable Phonon" and "make it the first one in the list".
""" """
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
if settings.contains(u'use phonon'): if settings.contains(u'use phonon'):
log.info(u'Found old Phonon setting') log.info(u'Found old Phonon setting')

View File

@ -36,6 +36,7 @@ from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \
validate_thumb validate_thumb
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
create_horizontal_adjusting_combo_box create_horizontal_adjusting_combo_box
from openlp.core.lib.settings import Settings
from openlp.plugins.presentations.lib import MessageListener from openlp.plugins.presentations.lib import MessageListener
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -149,7 +150,7 @@ class PresentationMediaItem(MediaManagerItem):
if self.displayTypeComboBox.count() > 1: if self.displayTypeComboBox.count() > 1:
self.displayTypeComboBox.insertItem(0, self.Automatic) self.displayTypeComboBox.insertItem(0, self.Automatic)
self.displayTypeComboBox.setCurrentIndex(0) self.displayTypeComboBox.setCurrentIndex(0)
if QtCore.QSettings().value(self.settingsSection + u'/override app', if Settings().value(self.settingsSection + u'/override app',
QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked: QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked:
self.presentationWidget.show() self.presentationWidget.show()
else: else:

View File

@ -33,6 +33,7 @@ from PyQt4 import QtCore
from openlp.core.lib import Receiver, check_directory_exists, create_thumb, \ from openlp.core.lib import Receiver, check_directory_exists, create_thumb, \
validate_thumb validate_thumb
from openlp.core.lib.settings import Settings
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -392,7 +393,7 @@ class PresentationController(object):
""" """
Return whether the controller is currently enabled Return whether the controller is currently enabled
""" """
if QtCore.QSettings().value( if Settings().value(
self.settings_section + u'/' + self.name, self.settings_section + u'/' + self.name,
QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0] == \ QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0] == \
QtCore.Qt.Checked: QtCore.Qt.Checked:

View File

@ -29,6 +29,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, SettingsTab, translate from openlp.core.lib import Receiver, SettingsTab, translate
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.core.lib.settings import Settings
class PresentationTab(SettingsTab): class PresentationTab(SettingsTab):
""" """
@ -102,10 +103,10 @@ class PresentationTab(SettingsTab):
for key in self.controllers: for key in self.controllers:
controller = self.controllers[key] controller = self.controllers[key]
checkbox = self.PresenterCheckboxes[controller.name] checkbox = self.PresenterCheckboxes[controller.name]
checkbox.setChecked(QtCore.QSettings().value( checkbox.setChecked(Settings().value(
self.settingsSection + u'/' + controller.name, self.settingsSection + u'/' + controller.name,
QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0]) QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0])
self.OverrideAppCheckBox.setChecked(QtCore.QSettings().value( self.OverrideAppCheckBox.setChecked(Settings().value(
self.settingsSection + u'/override app', self.settingsSection + u'/override app',
QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0]) QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0])
@ -123,19 +124,19 @@ class PresentationTab(SettingsTab):
if controller.is_available(): if controller.is_available():
checkbox = self.PresenterCheckboxes[controller.name] checkbox = self.PresenterCheckboxes[controller.name]
setting_key = self.settingsSection + u'/' + controller.name setting_key = self.settingsSection + u'/' + controller.name
if QtCore.QSettings().value(setting_key) != \ if Settings().value(setting_key) != \
checkbox.checkState(): checkbox.checkState():
changed = True changed = True
QtCore.QSettings().setValue(setting_key, Settings().setValue(setting_key,
QtCore.QVariant(checkbox.checkState())) QtCore.QVariant(checkbox.checkState()))
if checkbox.isChecked(): if checkbox.isChecked():
controller.start_process() controller.start_process()
else: else:
controller.kill() controller.kill()
setting_key = self.settingsSection + u'/override app' setting_key = self.settingsSection + u'/override app'
if QtCore.QSettings().value(setting_key) != \ if Settings().value(setting_key) != \
self.OverrideAppCheckBox.checkState(): self.OverrideAppCheckBox.checkState():
QtCore.QSettings().setValue(setting_key, Settings().setValue(setting_key,
QtCore.QVariant(self.OverrideAppCheckBox.checkState())) QtCore.QVariant(self.OverrideAppCheckBox.checkState()))
changed = True changed = True
if changed: if changed:

View File

@ -245,6 +245,9 @@ window.OpenLP = {
} }
else { else {
$.each(data.results.items, function (idx, value) { $.each(data.results.items, function (idx, value) {
if (typeof value[0] !== "number"){
value[0] = OpenLP.escapeString(value[0])
}
ul.append($("<li>").append($("<a>").attr("href", "#options") ul.append($("<li>").append($("<a>").attr("href", "#options")
.attr("data-rel", "dialog").attr("value", value[0]) .attr("data-rel", "dialog").attr("value", value[0])
.click(OpenLP.showOptions).text(value[1]))); .click(OpenLP.showOptions).text(value[1])));

View File

@ -122,6 +122,7 @@ from PyQt4 import QtCore, QtNetwork
from mako.template import Template from mako.template import Template
from openlp.core.lib import Receiver, PluginStatus, StringContent from openlp.core.lib import Receiver, PluginStatus, StringContent
from openlp.core.lib.settings import Settings
from openlp.core.utils import AppLocation, translate from openlp.core.utils import AppLocation, translate
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -169,10 +170,10 @@ class HttpServer(object):
clients. Listen out for socket connections. clients. Listen out for socket connections.
""" """
log.debug(u'Start TCP server') log.debug(u'Start TCP server')
port = QtCore.QSettings().value( port = Settings().value(
self.plugin.settingsSection + u'/port', self.plugin.settingsSection + u'/port',
QtCore.QVariant(4316)).toInt()[0] QtCore.QVariant(4316)).toInt()[0]
address = QtCore.QSettings().value( address = Settings().value(
self.plugin.settingsSection + u'/ip address', self.plugin.settingsSection + u'/ip address',
QtCore.QVariant(u'0.0.0.0')).toString() QtCore.QVariant(u'0.0.0.0')).toString()
self.server = QtNetwork.QTcpServer() self.server = QtNetwork.QTcpServer()
@ -404,7 +405,7 @@ class HttpConnection(object):
u'slide': self.parent.current_slide or 0, u'slide': self.parent.current_slide or 0,
u'item': self.parent.current_item._uuid \ u'item': self.parent.current_item._uuid \
if self.parent.current_item else u'', if self.parent.current_item else u'',
u'twelve':QtCore.QSettings().value( u'twelve':Settings().value(
u'remotes/twelve hour', QtCore.QVariant(True)).toBool(), u'remotes/twelve hour', QtCore.QVariant(True)).toBool(),
u'blank': self.parent.plugin.liveController.blankScreen.\ u'blank': self.parent.plugin.liveController.blankScreen.\
isChecked(), isChecked(),

View File

@ -28,6 +28,7 @@
from PyQt4 import QtCore, QtGui, QtNetwork from PyQt4 import QtCore, QtGui, QtNetwork
from openlp.core.lib import SettingsTab, translate, Receiver from openlp.core.lib import SettingsTab, translate, Receiver
from openlp.core.lib.settings import Settings
ZERO_URL = u'0.0.0.0' ZERO_URL = u'0.0.0.0'
@ -149,12 +150,12 @@ class RemoteTab(SettingsTab):
def load(self): def load(self):
self.portSpinBox.setValue( self.portSpinBox.setValue(
QtCore.QSettings().value(self.settingsSection + u'/port', Settings().value(self.settingsSection + u'/port',
QtCore.QVariant(4316)).toInt()[0]) QtCore.QVariant(4316)).toInt()[0])
self.addressEdit.setText( self.addressEdit.setText(
QtCore.QSettings().value(self.settingsSection + u'/ip address', Settings().value(self.settingsSection + u'/ip address',
QtCore.QVariant(ZERO_URL)).toString()) QtCore.QVariant(ZERO_URL)).toString())
self.twelveHour = QtCore.QSettings().value( self.twelveHour = Settings().value(
self.settingsSection + u'/twelve hour', self.settingsSection + u'/twelve hour',
QtCore.QVariant(True)).toBool() QtCore.QVariant(True)).toBool()
self.twelveHourCheckBox.setChecked(self.twelveHour) self.twelveHourCheckBox.setChecked(self.twelveHour)
@ -162,16 +163,16 @@ class RemoteTab(SettingsTab):
def save(self): def save(self):
changed = False changed = False
if QtCore.QSettings().value(self.settingsSection + u'/ip address', if Settings().value(self.settingsSection + u'/ip address',
QtCore.QVariant(ZERO_URL).toString() != self.addressEdit.text() or QtCore.QVariant(ZERO_URL).toString() != self.addressEdit.text() or
QtCore.QSettings().value(self.settingsSection + u'/port', Settings().value(self.settingsSection + u'/port',
QtCore.QVariant(4316).toInt()[0]) != self.portSpinBox.value()): QtCore.QVariant(4316).toInt()[0]) != self.portSpinBox.value()):
changed = True changed = True
QtCore.QSettings().setValue(self.settingsSection + u'/port', Settings().setValue(self.settingsSection + u'/port',
QtCore.QVariant(self.portSpinBox.value())) QtCore.QVariant(self.portSpinBox.value()))
QtCore.QSettings().setValue(self.settingsSection + u'/ip address', Settings().setValue(self.settingsSection + u'/ip address',
QtCore.QVariant(self.addressEdit.text())) QtCore.QVariant(self.addressEdit.text()))
QtCore.QSettings().setValue(self.settingsSection + u'/twelve hour', Settings().setValue(self.settingsSection + u'/twelve hour',
QtCore.QVariant(self.twelveHour)) QtCore.QVariant(self.twelveHour))
if changed: if changed:
Receiver.send_message(u'remotes_config_updated') Receiver.send_message(u'remotes_config_updated')

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -57,19 +57,17 @@ class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
self.firstNameEdit.setFocus() self.firstNameEdit.setFocus()
return QtGui.QDialog.exec_(self) return QtGui.QDialog.exec_(self)
def onFirstNameEditTextEdited(self, text): def onFirstNameEditTextEdited(self, display_name):
if not self._autoDisplayName: if not self._autoDisplayName:
return return
display_name = text if not self.lastNameEdit.text():
if self.lastNameEdit.text() != u'':
display_name = display_name + u' ' + self.lastNameEdit.text() display_name = display_name + u' ' + self.lastNameEdit.text()
self.displayEdit.setText(display_name) self.displayEdit.setText(display_name)
def onLastNameEditTextEdited(self, text): def onLastNameEditTextEdited(self, display_name):
if not self._autoDisplayName: if not self._autoDisplayName:
return return
display_name = text if not self.firstNameEdit.text():
if self.firstNameEdit.text() != u'':
display_name = self.firstNameEdit.text() + u' ' + display_name display_name = self.firstNameEdit.text() + u' ' + display_name
self.displayEdit.setText(display_name) self.displayEdit.setText(display_name)

View File

@ -172,17 +172,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def loadThemes(self, theme_list): def loadThemes(self, theme_list):
self.themeComboBox.clear() self.themeComboBox.clear()
self.themeComboBox.addItem(u'') self.themeComboBox.addItem(u'')
self.themes = [] self.themes = theme_list
for theme in theme_list: self.themeComboBox.addItems(theme_list)
self.themeComboBox.addItem(theme)
self.themes.append(theme)
set_case_insensitive_completer(self.themes, self.themeComboBox) set_case_insensitive_completer(self.themes, self.themeComboBox)
def loadMediaFiles(self): def loadMediaFiles(self):
self.audioAddFromMediaButton.setVisible(False) self.audioAddFromMediaButton.setVisible(False)
for plugin in self.parent().pluginManager.plugins: for plugin in self.parent().pluginManager.plugins:
if plugin.name == u'media' and \ if plugin.name == u'media' and plugin.status == PluginStatus.Active:
plugin.status == PluginStatus.Active:
self.audioAddFromMediaButton.setVisible(True) self.audioAddFromMediaButton.setVisible(True)
self.mediaForm.populateFiles( self.mediaForm.populateFiles(
plugin.mediaItem.getList(MediaType.Audio)) plugin.mediaItem.getList(MediaType.Audio))
@ -259,8 +256,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
verse_tags_translated = False verse_tags_translated = False
if self.song.lyrics.startswith(u'<?xml version='): if self.song.lyrics.startswith(u'<?xml version='):
songXML = SongXML() songXML = SongXML()
verseList = songXML.get_verses(self.song.lyrics) verse_list = songXML.get_verses(self.song.lyrics)
for count, verse in enumerate(verseList): for count, verse in enumerate(verse_list):
self.verseListWidget.setRowCount( self.verseListWidget.setRowCount(
self.verseListWidget.rowCount() + 1) self.verseListWidget.rowCount() + 1)
# This silently migrates from localized verse type markup. # This silently migrates from localized verse type markup.
@ -482,27 +479,26 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def onVerseEditButtonClicked(self): def onVerseEditButtonClicked(self):
item = self.verseListWidget.currentItem() item = self.verseListWidget.currentItem()
if item: if item:
tempText = item.text() temp_text = item.text()
verseId = unicode(item.data(QtCore.Qt.UserRole).toString()) verse_id = unicode(item.data(QtCore.Qt.UserRole).toString())
self.verseForm.setVerse(tempText, True, verseId) self.verseForm.setVerse(temp_text, True, verse_id)
if self.verseForm.exec_(): if self.verseForm.exec_():
after_text, verse_tag, verse_num = self.verseForm.getVerse() after_text, verse_tag, verse_num = self.verseForm.getVerse()
verse_def = u'%s%s' % (verse_tag, verse_num) verse_def = u'%s%s' % (verse_tag, verse_num)
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def)) item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def))
item.setText(after_text) item.setText(after_text)
# number of lines has changed, repaint the list moving the data # number of lines has changed, repaint the list moving the data
if len(tempText.split(u'\n')) != len(after_text.split(u'\n')): if len(temp_text.split(u'\n')) != len(after_text.split(u'\n')):
tempList = {} temp_list = []
tempId = {} temp_ids = []
for row in range(self.verseListWidget.rowCount()): for row in range(self.verseListWidget.rowCount()):
tempList[row] = self.verseListWidget.item(row, 0)\ item = self.verseListWidget.item(row, 0)
.text() temp_list.append(item.text())
tempId[row] = self.verseListWidget.item(row, 0)\ temp_ids.append(item.data(QtCore.Qt.UserRole))
.data(QtCore.Qt.UserRole)
self.verseListWidget.clear() self.verseListWidget.clear()
for row in range (0, len(tempList)): for row, entry in enumerate(temp_list):
item = QtGui.QTableWidgetItem(tempList[row], 0) item = QtGui.QTableWidgetItem(entry, 0)
item.setData(QtCore.Qt.UserRole, tempId[row]) item.setData(QtCore.Qt.UserRole, temp_ids[row])
self.verseListWidget.setItem(row, 0, item) self.verseListWidget.setItem(row, 0, item)
self.tagRows() self.tagRows()
# Check if all verse tags are used. # Check if all verse tags are used.
@ -926,9 +922,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
multiple = [] multiple = []
for i in range(self.verseListWidget.rowCount()): for i in range(self.verseListWidget.rowCount()):
item = self.verseListWidget.item(i, 0) item = self.verseListWidget.item(i, 0)
verseId = unicode(item.data(QtCore.Qt.UserRole).toString()) verse_id = unicode(item.data(QtCore.Qt.UserRole).toString())
verse_tag = verseId[0] verse_tag = verse_id[0]
verse_num = verseId[1:] verse_num = verse_id[1:]
sxml.add_verse_to_lyrics(verse_tag, verse_num, sxml.add_verse_to_lyrics(verse_tag, verse_num,
unicode(item.text())) unicode(item.text()))
if verse_num > u'1' and verse_tag not in multiple: if verse_num > u'1' and verse_tag not in multiple:

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -193,6 +193,7 @@ class VerseType(object):
return default return default
return verse_index return verse_index
def retrieve_windows_encoding(recommendation=None): def retrieve_windows_encoding(recommendation=None):
""" """
Determines which encoding to use on an information source. The process uses Determines which encoding to use on an information source. The process uses
@ -252,12 +253,14 @@ def retrieve_windows_encoding(recommendation=None):
return None return None
return filter(lambda item: item[1] == choice[0], encodings)[0][0] return filter(lambda item: item[1] == choice[0], encodings)[0][0]
def clean_string(string): def clean_string(string):
""" """
Strips punctuation from the passed string to assist searching Strips punctuation from the passed string to assist searching
""" """
return WHITESPACE.sub(u' ', APOSTROPHE.sub(u'', string)).lower() return WHITESPACE.sub(u' ', APOSTROPHE.sub(u'', string)).lower()
def clean_title(title): def clean_title(title):
""" """
Cleans the song title by removing Unicode control chars groups C0 & C1, Cleans the song title by removing Unicode control chars groups C0 & C1,
@ -265,6 +268,7 @@ def clean_title(title):
""" """
return CONTROL_CHARS.sub(u'', title).rstrip() return CONTROL_CHARS.sub(u'', title).rstrip()
def clean_song(manager, song): def clean_song(manager, song):
""" """
Cleans the search title, rebuilds the search lyrics, adds a default author Cleans the search title, rebuilds the search lyrics, adds a default author

View File

@ -29,6 +29,9 @@ The :mod:`importer` modules provides the general song import functionality.
""" """
import logging import logging
from openlp.core.lib import translate
from openlp.core.lib.ui import UiStrings
from openlp.core.ui.wizard import WizardStrings
from opensongimport import OpenSongImport from opensongimport import OpenSongImport
from easyslidesimport import EasySlidesImport from easyslidesimport import EasySlidesImport
from olpimport import OpenLPSongImport from olpimport import OpenLPSongImport
@ -41,6 +44,7 @@ from ewimport import EasyWorshipSongImport
from songbeamerimport import SongBeamerImport from songbeamerimport import SongBeamerImport
from songshowplusimport import SongShowPlusImport from songshowplusimport import SongShowPlusImport
from foilpresenterimport import FoilPresenterImport from foilpresenterimport import FoilPresenterImport
from zionworximport import ZionWorxImport
# Imports that might fail # Imports that might fail
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
try: try:
@ -62,13 +66,69 @@ except ImportError:
log.exception('Error importing %s', 'OooImport') log.exception('Error importing %s', 'OooImport')
HAS_OOO = False HAS_OOO = False
class SongFormatSelect(object):
"""
This is a special enumeration class listing available file selection modes.
"""
SingleFile = 0
MultipleFiles = 1
SingleFolder = 2
class SongFormat(object): class SongFormat(object):
""" """
This is a special enumeration class that holds the various types of songs, This is a special static class that holds an enumeration of the various
plus a few helper functions to facilitate generic handling of song types song formats handled by the importer, the attributes of each song format,
for importing. and a few helper functions.
Required attributes for each song format:
``u'class'``
Import class, e.g. ``OpenLyricsImport``
``u'name'``
Name of the format, e.g. ``u'OpenLyrics'``
``u'prefix'``
Prefix for Qt objects. Use mixedCase, e.g. ``u'openLyrics'``
See ``SongImportForm.addFileSelectItem()``
Optional attributes for each song format:
``u'canDisable'``
Whether song format importer is disablable.
``u'availability'``
Whether song format importer is available.
``u'selectMode'``
Whether format accepts single file, multiple files, or single folder
(as per ``SongFormatSelect`` options).
``u'filter'``
File extension filter for ``QFileDialog``.
Optional/custom text Strings for ``SongImportForm`` widgets:
``u'comboBoxText'``
Combo box selector (default value is the format's ``u'name'``).
``u'disabledLabelText'``
Required for disablable song formats.
``u'getFilesTitle'``
Title for ``QFileDialog`` (default includes the format's ``u'name'``).
``u'invalidSourceMsg'``
Message displayed if ``isValidSource()`` returns ``False``.
``u'descriptionText'``
Short description (1-2 lines) about the song format.
""" """
_format_availability = {} # Song formats (ordered alphabetically after Generic)
# * Numerical order of song formats is significant as it determines the
# order used by formatComboBox.
Unknown = -1 Unknown = -1
OpenLyrics = 0 OpenLyrics = 0
OpenLP2 = 1 OpenLP2 = 1
@ -85,50 +145,164 @@ class SongFormat(object):
SongShowPlus = 12 SongShowPlus = 12
SongsOfFellowship = 13 SongsOfFellowship = 13
WordsOfWorship = 14 WordsOfWorship = 14
#CSV = 15 ZionWorx = 15
#CSV = 16
# Set optional attribute defaults
__defaults__ = {
u'canDisable': False,
u'availability': True,
u'selectMode': SongFormatSelect.MultipleFiles,
u'filter': u'',
u'comboBoxText': None,
u'disabledLabelText': u'',
u'getFilesTitle': None,
u'invalidSourceMsg': None,
u'descriptionText': None
}
# Set attribute values for each Song Format
__attributes__ = {
OpenLyrics: {
u'class': OpenLyricsImport,
u'name': u'OpenLyrics',
u'prefix': u'openLyrics',
u'filter': u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm',
'OpenLyrics Files'),
u'comboBoxText': translate('SongsPlugin.ImportWizardForm',
'OpenLyrics or OpenLP 2.0 Exported Song')
},
OpenLP2: {
u'class': OpenLPSongImport,
u'name': UiStrings().OLPV2,
u'prefix': u'openLP2',
u'selectMode': SongFormatSelect.SingleFile,
u'filter': u'%s (*.sqlite)' % (translate(
'SongsPlugin.ImportWizardForm', 'OpenLP 2.0 Databases'))
},
OpenLP1: {
u'name': UiStrings().OLPV1,
u'prefix': u'openLP1',
u'canDisable': True,
u'selectMode': SongFormatSelect.SingleFile,
u'filter': u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm',
'openlp.org v1.x Databases'),
u'disabledLabelText': WizardStrings.NoSqlite
},
Generic: {
u'name': translate('SongsPlugin.ImportWizardForm',
'Generic Document/Presentation'),
u'prefix': u'generic',
u'canDisable': True,
u'disabledLabelText': translate('SongsPlugin.ImportWizardForm',
'The generic document/presentation importer has been disabled '
'because OpenLP cannot access OpenOffice or LibreOffice.'),
u'getFilesTitle': translate('SongsPlugin.ImportWizardForm',
'Select Document/Presentation Files')
},
CCLI: {
u'class': CCLIFileImport,
u'name': u'CCLI/SongSelect',
u'prefix': u'ccli',
u'filter': u'%s (*.usr *.txt)' % translate(
'SongsPlugin.ImportWizardForm', 'CCLI SongSelect Files')
},
DreamBeam: {
u'class': DreamBeamImport,
u'name': u'DreamBeam',
u'prefix': u'dreamBeam',
u'filter': u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm',
'DreamBeam Song Files')
},
EasySlides: {
u'class': EasySlidesImport,
u'name': u'EasySlides',
u'prefix': u'easySlides',
u'selectMode': SongFormatSelect.SingleFile,
u'filter': u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm',
'EasySlides XML File')
},
EasyWorship: {
u'class': EasyWorshipSongImport,
u'name': u'EasyWorship',
u'prefix': u'ew',
u'selectMode': SongFormatSelect.SingleFile,
u'filter': u'%s (*.db)' % translate('SongsPlugin.ImportWizardForm',
'EasyWorship Song Database')
},
FoilPresenter: {
u'class': FoilPresenterImport,
u'name': u'Foilpresenter',
u'prefix': u'foilPresenter',
u'filter': u'%s (*.foil)' % translate(
'SongsPlugin.ImportWizardForm', 'Foilpresenter Song Files')
},
OpenSong: {
u'class': OpenSongImport,
u'name': WizardStrings.OS,
u'prefix': u'openSong'
},
PowerSong: {
u'class': PowerSongImport,
u'name': u'PowerSong 1.0',
u'prefix': u'powerSong',
u'selectMode': SongFormatSelect.SingleFolder,
u'invalidSourceMsg': translate('SongsPlugin.ImportWizardForm',
'You need to specify a valid PowerSong 1.0 database folder.')
},
SongBeamer: {
u'class': SongBeamerImport,
u'name': u'SongBeamer',
u'prefix': u'songBeamer',
u'filter': u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm',
'SongBeamer Files')
},
SongShowPlus: {
u'class': SongShowPlusImport,
u'name': u'SongShow Plus',
u'prefix': u'songShowPlus',
u'filter': u'%s (*.sbsong)' % translate(
'SongsPlugin.ImportWizardForm', 'SongShow Plus Song Files')
},
SongsOfFellowship: {
u'name': u'Songs of Fellowship',
u'prefix': u'songsOfFellowship',
u'canDisable': True,
u'filter': u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm',
'Songs Of Fellowship Song Files'),
u'disabledLabelText': translate('SongsPlugin.ImportWizardForm',
'The Songs of Fellowship importer has been disabled because '
'OpenLP cannot access OpenOffice or LibreOffice.')
},
WordsOfWorship: {
u'class': WowImport,
u'name': u'Words of Worship',
u'prefix': u'wordsOfWorship',
u'filter': u'%s (*.wsg *.wow-song)' % translate(
'SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files')
},
ZionWorx: {
u'class': ZionWorxImport,
u'name': u'ZionWorx',
u'prefix': u'zionWorx',
u'selectMode': SongFormatSelect.SingleFile,
u'comboBoxText': translate('SongsPlugin.ImportWizardForm',
'ZionWorx (CSV)'),
u'descriptionText': translate('SongsPlugin.ImportWizardForm',
'First convert your ZionWorx database to a CSV text file, as '
'explained in the <a href="http://manual.openlp.org/songs.html'
'#importing-from-zionworx">User Manual</a>.')
# },
# CSV: {
# u'class': CSVImport,
# u'name': WizardStrings.CSV,
# u'prefix': u'csv',
# u'selectMode': SongFormatSelect.SingleFile
}
}
@staticmethod @staticmethod
def get_class(format): def get_format_list():
"""
Return the appropriate implementation class.
``format``
The song format.
"""
if format == SongFormat.OpenLP2:
return OpenLPSongImport
elif format == SongFormat.OpenLP1:
return OpenLP1SongImport
elif format == SongFormat.OpenLyrics:
return OpenLyricsImport
elif format == SongFormat.OpenSong:
return OpenSongImport
elif format == SongFormat.SongsOfFellowship:
return SofImport
elif format == SongFormat.WordsOfWorship:
return WowImport
elif format == SongFormat.Generic:
return OooImport
elif format == SongFormat.CCLI:
return CCLIFileImport
elif format == SongFormat.DreamBeam:
return DreamBeamImport
elif format == SongFormat.PowerSong:
return PowerSongImport
elif format == SongFormat.EasySlides:
return EasySlidesImport
elif format == SongFormat.EasyWorship:
return EasyWorshipSongImport
elif format == SongFormat.SongBeamer:
return SongBeamerImport
elif format == SongFormat.SongShowPlus:
return SongShowPlusImport
elif format == SongFormat.FoilPresenter:
return FoilPresenterImport
return None
@staticmethod
def get_formats_list():
""" """
Return a list of the supported song formats. Return a list of the supported song formats.
""" """
@ -147,26 +321,56 @@ class SongFormat(object):
SongFormat.SongBeamer, SongFormat.SongBeamer,
SongFormat.SongShowPlus, SongFormat.SongShowPlus,
SongFormat.SongsOfFellowship, SongFormat.SongsOfFellowship,
SongFormat.WordsOfWorship SongFormat.WordsOfWorship,
SongFormat.ZionWorx
] ]
@staticmethod @staticmethod
def set_availability(format, available): def get(format, *attributes):
""" """
Set the availability for a given song format. Return requested song format attribute(s).
``format``
A song format from SongFormat.
``*attributes``
Zero or more song format attributes from SongFormat.
Return type depends on number of supplied attributes:
:0: Return dict containing all defined attributes for the format.
:1: Return the attribute value.
:>1: Return tuple of requested attribute values.
""" """
SongFormat._format_availability[format] = available if not attributes:
return SongFormat.__attributes__.get(format)
elif len(attributes) == 1:
default = SongFormat.__defaults__.get(attributes[0])
return SongFormat.__attributes__[format].get(attributes[0],
default)
else:
values = []
for attr in attributes:
default = SongFormat.__defaults__.get(attr)
values.append(SongFormat.__attributes__[format].get(attr,
default))
return tuple(values)
@staticmethod @staticmethod
def get_availability(format): def set(format, attribute, value):
""" """
Return the availability of a given song format. Set specified song format attribute to the supplied value.
""" """
return SongFormat._format_availability.get(format, True) SongFormat.__attributes__[format][attribute] = value
SongFormat.set_availability(SongFormat.OpenLP1, HAS_OPENLP1) SongFormat.set(SongFormat.OpenLP1, u'availability', HAS_OPENLP1)
SongFormat.set_availability(SongFormat.SongsOfFellowship, HAS_SOF) if HAS_OPENLP1:
SongFormat.set_availability(SongFormat.Generic, HAS_OOO) SongFormat.set(SongFormat.OpenLP1, u'class', OpenLP1SongImport)
SongFormat.set(SongFormat.SongsOfFellowship, u'availability', HAS_SOF)
__all__ = [u'SongFormat'] if HAS_SOF:
SongFormat.set(SongFormat.SongsOfFellowship, u'class', SofImport)
SongFormat.set(SongFormat.Generic, u'availability', HAS_OOO)
if HAS_OOO:
SongFormat.set(SongFormat.Generic, u'class', OooImport)
__all__ = [u'SongFormat', u'SongFormatSelect']

View File

@ -37,6 +37,7 @@ from sqlalchemy.sql import or_
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
translate, check_item_selected, PluginStatus, create_separated_list translate, check_item_selected, PluginStatus, create_separated_list
from openlp.core.lib.ui import UiStrings, create_widget_action from openlp.core.lib.ui import UiStrings, create_widget_action
from openlp.core.lib.settings import Settings
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
SongImportForm, SongExportForm SongImportForm, SongExportForm
@ -131,13 +132,13 @@ class SongMediaItem(MediaManagerItem):
self.searchTextEdit.setFocus() self.searchTextEdit.setFocus()
def configUpdated(self): def configUpdated(self):
self.searchAsYouType = QtCore.QSettings().value( self.searchAsYouType = Settings().value(
self.settingsSection + u'/search as type', self.settingsSection + u'/search as type',
QtCore.QVariant(u'False')).toBool() QtCore.QVariant(u'False')).toBool()
self.updateServiceOnEdit = QtCore.QSettings().value( self.updateServiceOnEdit = Settings().value(
self.settingsSection + u'/update service on edit', self.settingsSection + u'/update service on edit',
QtCore.QVariant(u'False')).toBool() QtCore.QVariant(u'False')).toBool()
self.addSongFromService = QtCore.QSettings().value( self.addSongFromService = Settings().value(
self.settingsSection + u'/add song from service', self.settingsSection + u'/add song from service',
QtCore.QVariant(u'True')).toBool() QtCore.QVariant(u'True')).toBool()
@ -168,14 +169,14 @@ class SongMediaItem(MediaManagerItem):
(SongSearch.Themes, u':/slides/slide_theme.png', (SongSearch.Themes, u':/slides/slide_theme.png',
UiStrings().Themes, UiStrings().SearchThemes) UiStrings().Themes, UiStrings().SearchThemes)
]) ])
self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value( self.searchTextEdit.setCurrentSearchType(Settings().value(
u'%s/last search type' % self.settingsSection, u'%s/last search type' % self.settingsSection,
QtCore.QVariant(SongSearch.Entire)).toInt()[0]) QtCore.QVariant(SongSearch.Entire)).toInt()[0])
self.configUpdated() self.configUpdated()
def onSearchTextButtonClicked(self): def onSearchTextButtonClicked(self):
# Save the current search type to the configuration. # Save the current search type to the configuration.
QtCore.QSettings().setValue(u'%s/last search type' % Settings().setValue(u'%s/last search type' %
self.settingsSection, self.settingsSection,
QtCore.QVariant(self.searchTextEdit.currentSearchType())) QtCore.QVariant(self.searchTextEdit.currentSearchType()))
# Reload the list considering the new search type. # Reload the list considering the new search type.
@ -464,14 +465,14 @@ class SongMediaItem(MediaManagerItem):
service_item.theme = song.theme_name service_item.theme = song.theme_name
service_item.edit_id = item_id service_item.edit_id = item_id
if song.lyrics.startswith(u'<?xml version='): if song.lyrics.startswith(u'<?xml version='):
verseList = SongXML().get_verses(song.lyrics) verse_list = SongXML().get_verses(song.lyrics)
# no verse list or only 1 space (in error) # no verse list or only 1 space (in error)
verse_tags_translated = False verse_tags_translated = False
if VerseType.from_translated_string(unicode( if VerseType.from_translated_string(unicode(
verseList[0][0][u'type'])) is not None: verse_list[0][0][u'type'])) is not None:
verse_tags_translated = True verse_tags_translated = True
if not song.verse_order.strip(): if not song.verse_order.strip():
for verse in verseList: for verse in verse_list:
# We cannot use from_loose_input() here, because database # We cannot use from_loose_input() here, because database
# is supposed to contain English lowercase singlechar tags. # is supposed to contain English lowercase singlechar tags.
verse_tag = verse[0][u'type'] verse_tag = verse[0][u'type']
@ -485,14 +486,13 @@ class SongMediaItem(MediaManagerItem):
verse_index = VerseType.from_tag(verse_tag) verse_index = VerseType.from_tag(verse_tag)
verse_tag = VerseType.TranslatedTags[verse_index].upper() verse_tag = VerseType.TranslatedTags[verse_index].upper()
verse_def = u'%s%s' % (verse_tag, verse[0][u'label']) verse_def = u'%s%s' % (verse_tag, verse[0][u'label'])
service_item.add_from_text( service_item.add_from_text(unicode(verse[1]), verse_def)
verse[1][:30], unicode(verse[1]), verse_def)
else: else:
# Loop through the verse list and expand the song accordingly. # Loop through the verse list and expand the song accordingly.
for order in song.verse_order.lower().split(): for order in song.verse_order.lower().split():
if not order: if not order:
break break
for verse in verseList: for verse in verse_list:
if verse[0][u'type'][0].lower() == order[0] and \ if verse[0][u'type'][0].lower() == order[0] and \
(verse[0][u'label'].lower() == order[1:] or \ (verse[0][u'label'].lower() == order[1:] or \
not order[1:]): not order[1:]):
@ -505,22 +505,21 @@ class SongMediaItem(MediaManagerItem):
verse_tag = VerseType.TranslatedTags[verse_index] verse_tag = VerseType.TranslatedTags[verse_index]
verse_def = u'%s%s' % (verse_tag, verse_def = u'%s%s' % (verse_tag,
verse[0][u'label']) verse[0][u'label'])
service_item.add_from_text( service_item.add_from_text(verse[1], verse_def)
verse[1][:30], verse[1], verse_def)
else: else:
verses = song.lyrics.split(u'\n\n') verses = song.lyrics.split(u'\n\n')
for slide in verses: for slide in verses:
service_item.add_from_text(slide[:30], unicode(slide)) service_item.add_from_text(unicode(slide))
service_item.title = song.title service_item.title = song.title
author_list = [unicode(author.display_name) for author in song.authors] author_list = [unicode(author.display_name) for author in song.authors]
service_item.raw_footer.append(song.title) service_item.raw_footer.append(song.title)
service_item.raw_footer.append(create_separated_list(author_list)) service_item.raw_footer.append(create_separated_list(author_list))
service_item.raw_footer.append(song.copyright) service_item.raw_footer.append(song.copyright)
if QtCore.QSettings().value(u'general/ccli number', if Settings().value(u'general/ccli number',
QtCore.QVariant(u'')).toString(): QtCore.QVariant(u'')).toString():
service_item.raw_footer.append(unicode( service_item.raw_footer.append(unicode(
translate('SongsPlugin.MediaItem', 'CCLI License: ') + translate('SongsPlugin.MediaItem', 'CCLI License: ') +
QtCore.QSettings().value(u'general/ccli number', Settings().value(u'general/ccli number',
QtCore.QVariant(u'')).toString())) QtCore.QVariant(u'')).toString()))
service_item.audit = [ service_item.audit = [
song.title, author_list, song.copyright, unicode(song.ccli_number) song.title, author_list, song.copyright, unicode(song.ccli_number)

View File

@ -33,7 +33,6 @@ import fnmatch
import os import os
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -71,18 +70,15 @@ class PowerSongImport(SongImport):
* .song * .song
""" """
@staticmethod @staticmethod
def isValidSource(**kwargs): def isValidSource(import_source):
""" """
Checks if source is a PowerSong 1.0 folder: Checks if source is a PowerSong 1.0 folder:
* is a directory * is a directory
* contains at least one *.song file * contains at least one *.song file
""" """
if u'folder' in kwargs: if os.path.isdir(import_source):
dir = kwargs[u'folder'] for file in os.listdir(import_source):
if os.path.isdir(dir):
for file in os.listdir(dir):
if fnmatch.fnmatch(file, u'*.song'): if fnmatch.fnmatch(file, u'*.song'):
return True return True
return False return False
@ -91,6 +87,8 @@ class PowerSongImport(SongImport):
""" """
Receive either a list of files or a folder (unicode) to import. Receive either a list of files or a folder (unicode) to import.
""" """
from importer import SongFormat
PS_string = SongFormat.get(SongFormat.PowerSong, u'name')
if isinstance(self.importSource, unicode): if isinstance(self.importSource, unicode):
if os.path.isdir(self.importSource): if os.path.isdir(self.importSource):
dir = self.importSource dir = self.importSource
@ -104,7 +102,7 @@ class PowerSongImport(SongImport):
self.logError(unicode(translate('SongsPlugin.PowerSongImport', self.logError(unicode(translate('SongsPlugin.PowerSongImport',
'No songs to import.')), 'No songs to import.')),
unicode(translate('SongsPlugin.PowerSongImport', unicode(translate('SongsPlugin.PowerSongImport',
'No %s files found.' % WizardStrings.PS))) 'No %s files found.' % PS_string)))
return return
self.importWizard.progressBar.setMaximum(len(self.importSource)) self.importWizard.progressBar.setMaximum(len(self.importSource))
for file in self.importSource: for file in self.importSource:
@ -124,7 +122,7 @@ class PowerSongImport(SongImport):
self.logError(os.path.basename(file), unicode( self.logError(os.path.basename(file), unicode(
translate('SongsPlugin.PowerSongImport', translate('SongsPlugin.PowerSongImport',
'Invalid %s file. Unexpected byte value.' 'Invalid %s file. Unexpected byte value.'
% WizardStrings.PS))) % PS_string)))
break break
else: else:
if label == u'TITLE': if label == u'TITLE':
@ -142,15 +140,14 @@ class PowerSongImport(SongImport):
if not self.title: if not self.title:
self.logError(os.path.basename(file), unicode( self.logError(os.path.basename(file), unicode(
translate('SongsPlugin.PowerSongImport', translate('SongsPlugin.PowerSongImport',
'Invalid %s file. Missing "TITLE" header.' 'Invalid %s file. Missing "TITLE" header.' % PS_string)))
% WizardStrings.PS)))
continue continue
# Check that file had COPYRIGHTLINE label # Check that file had COPYRIGHTLINE label
if not found_copyright: if not found_copyright:
self.logError(self.title, unicode( self.logError(self.title, unicode(
translate('SongsPlugin.PowerSongImport', translate('SongsPlugin.PowerSongImport',
'Invalid %s file. Missing "COPYRIGHTLINE" ' 'Invalid %s file. Missing "COPYRIGHTLINE" '
'header.' % WizardStrings.PS))) 'header.' % PS_string)))
continue continue
# Check that file had at least one verse # Check that file had at least one verse
if not self.verses: if not self.verses:

View File

@ -51,11 +51,11 @@ class SongImport(QtCore.QObject):
as necessary as necessary
""" """
@staticmethod @staticmethod
def isValidSource(**kwargs): def isValidSource(import_source):
""" """
Override this method to validate the source prior to import. Override this method to validate the source prior to import.
""" """
pass return True
def __init__(self, manager, **kwargs): def __init__(self, manager, **kwargs):
""" """

View File

@ -28,6 +28,7 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate from openlp.core.lib import SettingsTab, translate
from openlp.core.lib.settings import Settings
class SongsTab(SettingsTab): class SongsTab(SettingsTab):
""" """
@ -110,7 +111,7 @@ class SongsTab(SettingsTab):
self.update_load = True self.update_load = True
def load(self): def load(self):
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
self.song_search = settings.value( self.song_search = settings.value(
u'search as type', QtCore.QVariant(False)).toBool() u'search as type', QtCore.QVariant(False)).toBool()
@ -127,7 +128,7 @@ class SongsTab(SettingsTab):
settings.endGroup() settings.endGroup()
def save(self): def save(self):
settings = QtCore.QSettings() settings = Settings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
settings.setValue(u'search as type', QtCore.QVariant(self.song_search)) settings.setValue(u'search as type', QtCore.QVariant(self.song_search))
settings.setValue(u'display songbar', QtCore.QVariant(self.tool_bar)) settings.setValue(u'display songbar', QtCore.QVariant(self.tool_bar))

View File

@ -0,0 +1,142 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
# 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:`zionworximport` module provides the functionality for importing
ZionWorx songs into the OpenLP database.
"""
import csv
import logging
from openlp.core.lib import translate
from openlp.plugins.songs.lib.songimport import SongImport
log = logging.getLogger(__name__)
class ZionWorxImport(SongImport):
"""
The :class:`ZionWorxImport` class provides the ability to import songs
from ZionWorx, via a dump of the ZionWorx database to a CSV file.
ZionWorx song database fields:
* ``SongNum`` Song ID. (Discarded by importer)
* ``Title1`` Main Title.
* ``Title2`` Alternate Title.
* ``Lyrics`` Song verses, separated by blank lines.
* ``Writer`` Song author(s).
* ``Copyright`` Copyright information
* ``Keywords`` (Discarded by importer)
* ``DefaultStyle`` (Discarded by importer)
ZionWorx has no native export function; it uses the proprietary TurboDB
database engine. The TurboDB vendor, dataWeb, provides tools which can
export TurboDB tables to other formats, such as freeware console tool
TurboDB Data Exchange which is available for Windows and Linux. This command
exports the ZionWorx songs table to a CSV file:
``tdbdatax MainTable.dat songstable.csv -fsdf -s, -qd``
* -f Table format: ``sdf`` denotes text file.
* -s Separator character between fields.
* -q Quote character surrounding fields. ``d`` denotes double-quote.
CSV format expected by importer:
* Field separator character is comma ``,``
* Fields surrounded by double-quotes ``"``. This enables fields (such as
Lyrics) to include new-lines and commas. Double-quotes within a field
are denoted by two double-quotes ``""``
* Note: This is the default format of the Python ``csv`` module.
"""
def doImport(self):
"""
Receive a CSV file (from a ZionWorx database dump) to import.
"""
# Used to strip control chars (10=LF, 13=CR, 127=DEL)
self.control_chars_map = dict.fromkeys(
range(10) + [11, 12] + range(14,32) + [127])
with open(self.importSource, 'rb') as songs_file:
fieldnames = [u'SongNum', u'Title1', u'Title2', u'Lyrics',
u'Writer', u'Copyright', u'Keywords', u'DefaultStyle']
songs_reader = csv.DictReader(songs_file, fieldnames)
try:
records = list(songs_reader)
except csv.Error, e:
self.logError(unicode(translate('SongsPlugin.ZionWorxImport',
'Error reading CSV file.')),
unicode(translate('SongsPlugin.ZionWorxImport',
'Line %d: %s' % (songs_reader.line_num, e))))
return
num_records = len(records)
log.info(u'%s records found in CSV file' % num_records)
self.importWizard.progressBar.setMaximum(num_records)
for index, record in enumerate(records, 1):
if self.stopImportFlag:
return
self.setDefaults()
try:
self.title = self._decode(record[u'Title1'])
if record[u'Title2']:
self.alternateTitle = self._decode(record[u'Title2'])
self.parseAuthor(self._decode(record[u'Writer']))
self.addCopyright(self._decode(record[u'Copyright']))
lyrics = self._decode(record[u'Lyrics'])
except UnicodeDecodeError, e:
self.logError(unicode(translate(
'SongsPlugin.ZionWorxImport', 'Record %d' % index)),
unicode(translate('SongsPlugin.ZionWorxImport',
'Decoding error: %s' % e)))
continue
except TypeError, e:
self.logError(unicode(translate(
'SongsPlugin.ZionWorxImport', 'File not valid ZionWorx '
'CSV format.')), u'TypeError: %s' % e)
return
verse = u''
for line in lyrics.splitlines():
if line and not line.isspace():
verse += line + u'\n'
elif verse:
self.addVerse(verse)
verse = u''
if verse:
self.addVerse(verse)
title = self.title
if not self.finish():
self.logError(unicode(translate(
'SongsPlugin.ZionWorxImport', 'Record %d' % index))
+ (u': "' + title + u'"' if title else u''))
def _decode(self, str):
"""
Decodes CSV input to unicode, stripping all control characters (except
new lines).
"""
# This encoding choice seems OK. ZionWorx has no option for setting the
# encoding for its songs, so we assume encoding is always the same.
return unicode(str, u'cp1252').translate(self.control_chars_map)

View File

@ -194,7 +194,8 @@ class SongsPlugin(Plugin):
self.manager.save_object(song) self.manager.save_object(song)
def importSongs(self, format, **kwargs): def importSongs(self, format, **kwargs):
class_ = SongFormat.get_class(format) class_ = SongFormat.get(format, u'class')
kwargs[u'plugin'] = self
importer = class_(self.manager, **kwargs) importer = class_(self.manager, **kwargs)
importer.register(self.mediaItem.importWizard) importer.register(self.mediaItem.importWizard)
return importer return importer

View File

@ -33,6 +33,7 @@ from sqlalchemy.sql import and_
from openlp.core.lib import SettingsManager, translate, Receiver, \ from openlp.core.lib import SettingsManager, translate, Receiver, \
check_directory_exists check_directory_exists
from openlp.core.lib.settings import Settings
from openlp.plugins.songusage.lib.db import SongUsageItem from openlp.plugins.songusage.lib.db import SongUsageItem
from songusagedetaildialog import Ui_SongUsageDetailDialog from songusagedetaildialog import Ui_SongUsageDetailDialog
@ -59,10 +60,10 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog):
year = QtCore.QDate().currentDate().year() year = QtCore.QDate().currentDate().year()
if QtCore.QDate().currentDate().month() < 9: if QtCore.QDate().currentDate().month() < 9:
year -= 1 year -= 1
toDate = QtCore.QSettings().value( toDate = Settings().value(
u'songusage/to date', u'songusage/to date',
QtCore.QVariant(QtCore.QDate(year, 8, 31))).toDate() QtCore.QVariant(QtCore.QDate(year, 8, 31))).toDate()
fromDate = QtCore.QSettings().value( fromDate = Settings().value(
u'songusage/from date', u'songusage/from date',
QtCore.QVariant(QtCore.QDate(year - 1, 9, 1))).toDate() QtCore.QVariant(QtCore.QDate(year - 1, 9, 1))).toDate()
self.fromDate.setSelectedDate(fromDate) self.fromDate.setSelectedDate(fromDate)
@ -103,9 +104,9 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog):
'usage_detail_%s_%s.txt')) % ( 'usage_detail_%s_%s.txt')) % (
self.fromDate.selectedDate().toString(u'ddMMyyyy'), self.fromDate.selectedDate().toString(u'ddMMyyyy'),
self.toDate.selectedDate().toString(u'ddMMyyyy')) self.toDate.selectedDate().toString(u'ddMMyyyy'))
QtCore.QSettings().setValue(u'songusage/from date', Settings().setValue(u'songusage/from date',
QtCore.QVariant(self.fromDate.selectedDate())) QtCore.QVariant(self.fromDate.selectedDate()))
QtCore.QSettings().setValue(u'songusage/to date', Settings().setValue(u'songusage/to date',
QtCore.QVariant(self.toDate.selectedDate())) QtCore.QVariant(self.toDate.selectedDate()))
usage = self.plugin.manager.get_all_objects( usage = self.plugin.manager.get_all_objects(
SongUsageItem, and_( SongUsageItem, and_(

View File

@ -34,6 +34,7 @@ from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, \
translate translate
from openlp.core.lib.db import Manager from openlp.core.lib.db import Manager
from openlp.core.lib.ui import create_action from openlp.core.lib.ui import create_action
from openlp.core.lib.settings import Settings
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList
from openlp.plugins.songusage.forms import SongUsageDetailForm, \ from openlp.plugins.songusage.forms import SongUsageDetailForm, \
SongUsageDeleteForm SongUsageDeleteForm
@ -125,7 +126,7 @@ class SongUsagePlugin(Plugin):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'print_service_started'), QtCore.SIGNAL(u'print_service_started'),
self.printSongUsage) self.printSongUsage)
self.songUsageActive = QtCore.QSettings().value( self.songUsageActive = Settings().value(
self.settingsSection + u'/active', self.settingsSection + u'/active',
QtCore.QVariant(False)).toBool() QtCore.QVariant(False)).toBool()
# Set the button and checkbox state # Set the button and checkbox state
@ -168,7 +169,7 @@ class SongUsagePlugin(Plugin):
the UI when necessary, the UI when necessary,
""" """
self.songUsageActive = not self.songUsageActive self.songUsageActive = not self.songUsageActive
QtCore.QSettings().setValue(self.settingsSection + u'/active', Settings().setValue(self.settingsSection + u'/active',
QtCore.QVariant(self.songUsageActive)) QtCore.QVariant(self.songUsageActive))
self.setButtonState() self.setButtonState()