forked from openlp/openlp
r1996
This commit is contained in:
commit
6e0ccae954
@ -41,6 +41,7 @@ from traceback import format_exception
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
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.resources import qInitResources
|
||||
from openlp.core.ui.mainwindow import MainWindow
|
||||
@ -113,15 +114,15 @@ class OpenLP(QtGui.QApplication):
|
||||
# Decide how many screens we have and their size
|
||||
screens = ScreenList.create(self.desktop())
|
||||
# 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()
|
||||
if not has_run_wizard:
|
||||
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))
|
||||
if os.name == u'nt':
|
||||
self.setStyleSheet(application_stylesheet)
|
||||
show_splash = QtCore.QSettings().value(
|
||||
show_splash = Settings().value(
|
||||
u'general/show splash', QtCore.QVariant(True)).toBool()
|
||||
if show_splash:
|
||||
self.splash = SplashScreen()
|
||||
@ -141,7 +142,7 @@ class OpenLP(QtGui.QApplication):
|
||||
self.processEvents()
|
||||
if not has_run_wizard:
|
||||
self.mainWindow.firstTime()
|
||||
update_check = QtCore.QSettings().value(
|
||||
update_check = Settings().value(
|
||||
u'general/update check', QtCore.QVariant(True)).toBool()
|
||||
if update_check:
|
||||
VersionThread(self.mainWindow).start()
|
||||
@ -258,7 +259,28 @@ def main(args=None):
|
||||
app = OpenLP(qt_args)
|
||||
app.setOrganizationName(u'OpenLP')
|
||||
app.setOrganizationDomain(u'openlp.org')
|
||||
app.setApplicationName(u'OpenLP')
|
||||
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.setApplicationVersion(get_application_version()[u'version'])
|
||||
# Instance check
|
||||
if not options.testing:
|
||||
@ -266,7 +288,7 @@ def main(args=None):
|
||||
if app.isAlreadyRunning():
|
||||
sys.exit()
|
||||
# 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():
|
||||
if not FirstTimeLanguageForm().exec_():
|
||||
# if cancel then stop processing
|
||||
|
@ -41,6 +41,7 @@ from sqlalchemy.pool import NullPool
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.utils import AppLocation, delete_file
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -179,7 +180,7 @@ class Manager(object):
|
||||
The file name to use for this database. Defaults to None resulting
|
||||
in the plugin_name being used.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(plugin_name)
|
||||
self.db_url = u''
|
||||
self.is_dirty = False
|
||||
@ -238,27 +239,30 @@ class Manager(object):
|
||||
``commit``
|
||||
Commit the session with this object
|
||||
"""
|
||||
try:
|
||||
self.session.add(object_instance)
|
||||
if commit:
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# See bug #927473
|
||||
log.exception(u'Probably a MySQL issue - "MySQL has gone away"')
|
||||
self.session.rollback()
|
||||
self.session.add(object_instance)
|
||||
if commit:
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
log.exception(u'Object save failed')
|
||||
return False
|
||||
for try_count in range(3):
|
||||
try:
|
||||
self.session.add(object_instance)
|
||||
if commit:
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# 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"')
|
||||
self.session.rollback()
|
||||
if try_count >= 2:
|
||||
raise
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
log.exception(u'Object list save failed')
|
||||
return False
|
||||
except:
|
||||
self.session.rollback()
|
||||
raise
|
||||
|
||||
def save_objects(self, object_list, commit=True):
|
||||
"""
|
||||
@ -270,27 +274,30 @@ class Manager(object):
|
||||
``commit``
|
||||
Commit the session with this object
|
||||
"""
|
||||
try:
|
||||
self.session.add_all(object_list)
|
||||
if commit:
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# See bug #927473
|
||||
log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
|
||||
self.session.rollback()
|
||||
self.session.add_all(object_list)
|
||||
if commit:
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
log.exception(u'Object list save failed')
|
||||
return False
|
||||
for try_count in range(3):
|
||||
try:
|
||||
self.session.add_all(object_list)
|
||||
if commit:
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# 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"')
|
||||
self.session.rollback()
|
||||
if try_count >= 2:
|
||||
raise
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
log.exception(u'Object list save failed')
|
||||
return False
|
||||
except:
|
||||
self.session.rollback()
|
||||
raise
|
||||
|
||||
def get_object(self, object_class, key=None):
|
||||
"""
|
||||
@ -305,15 +312,18 @@ class Manager(object):
|
||||
if not key:
|
||||
return object_class()
|
||||
else:
|
||||
try:
|
||||
return self.session.query(object_class).get(key)
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# See bug #927473
|
||||
log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
|
||||
self.session.rollback()
|
||||
return self.session.query(object_class).get(key)
|
||||
for try_count in range(3):
|
||||
try:
|
||||
return self.session.query(object_class).get(key)
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# 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"')
|
||||
if try_count >= 2:
|
||||
raise
|
||||
|
||||
def get_object_filtered(self, object_class, filter_clause):
|
||||
"""
|
||||
@ -325,15 +335,18 @@ class Manager(object):
|
||||
``filter_clause``
|
||||
The criteria to select the object by
|
||||
"""
|
||||
try:
|
||||
return self.session.query(object_class).filter(filter_clause).first()
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# See bug #927473
|
||||
log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
|
||||
self.session.rollback()
|
||||
return self.session.query(object_class).filter(filter_clause).first()
|
||||
for try_count in range(3):
|
||||
try:
|
||||
return self.session.query(object_class).filter(filter_clause).first()
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# 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"')
|
||||
if try_count >= 2:
|
||||
raise
|
||||
|
||||
def get_all_objects(self, object_class, filter_clause=None,
|
||||
order_by_ref=None):
|
||||
@ -357,15 +370,18 @@ class Manager(object):
|
||||
query = query.order_by(*order_by_ref)
|
||||
elif order_by_ref is not None:
|
||||
query = query.order_by(order_by_ref)
|
||||
try:
|
||||
return query.all()
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# See bug #927473
|
||||
log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
|
||||
self.session.rollback()
|
||||
return query.all()
|
||||
for try_count in range(3):
|
||||
try:
|
||||
return query.all()
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# 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"')
|
||||
if try_count >= 2:
|
||||
raise
|
||||
|
||||
def get_object_count(self, object_class, filter_clause=None):
|
||||
"""
|
||||
@ -381,15 +397,18 @@ class Manager(object):
|
||||
query = self.session.query(object_class)
|
||||
if filter_clause is not None:
|
||||
query = query.filter(filter_clause)
|
||||
try:
|
||||
return query.count()
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# See bug #927473
|
||||
log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
|
||||
self.session.rollback()
|
||||
return query.count()
|
||||
for try_count in range(3):
|
||||
try:
|
||||
return query.count()
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# 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"')
|
||||
if try_count >= 2:
|
||||
raise
|
||||
|
||||
def delete_object(self, object_class, key):
|
||||
"""
|
||||
@ -403,25 +422,29 @@ class Manager(object):
|
||||
"""
|
||||
if key != 0:
|
||||
object_instance = self.get_object(object_class, key)
|
||||
try:
|
||||
self.session.delete(object_instance)
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# See bug #927473
|
||||
log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
|
||||
self.session.rollback()
|
||||
self.session.delete(object_instance)
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
log.exception(u'Failed to delete object')
|
||||
return False
|
||||
for try_count in range(3):
|
||||
try:
|
||||
self.session.delete(object_instance)
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# 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"')
|
||||
self.session.rollback()
|
||||
if try_count >= 2:
|
||||
raise
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
log.exception(u'Failed to delete object')
|
||||
return False
|
||||
except:
|
||||
self.session.rollback()
|
||||
raise
|
||||
else:
|
||||
return True
|
||||
|
||||
@ -439,31 +462,32 @@ class Manager(object):
|
||||
The filter governing selection of objects to return. Defaults to
|
||||
None.
|
||||
"""
|
||||
try:
|
||||
query = self.session.query(object_class)
|
||||
if filter_clause is not None:
|
||||
query = query.filter(filter_clause)
|
||||
query.delete(synchronize_session=False)
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# See bug #927473
|
||||
log.exception(u'Probably a MySQL issue, "MySQL has gone away"')
|
||||
self.session.rollback()
|
||||
query = self.session.query(object_class)
|
||||
if filter_clause is not None:
|
||||
query = query.filter(filter_clause)
|
||||
query.delete(synchronize_session=False)
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
log.exception(u'Failed to delete %s records', object_class.__name__)
|
||||
return False
|
||||
for try_count in range(3):
|
||||
try:
|
||||
query = self.session.query(object_class)
|
||||
if filter_clause is not None:
|
||||
query = query.filter(filter_clause)
|
||||
query.delete(synchronize_session=False)
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except OperationalError:
|
||||
# This exception clause is for users running MySQL which likes
|
||||
# to terminate connections on its own without telling anyone.
|
||||
# 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"')
|
||||
self.session.rollback()
|
||||
if try_count >= 2:
|
||||
raise
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
log.exception(u'Failed to delete %s records', object_class.__name__)
|
||||
return False
|
||||
except:
|
||||
self.session.rollback()
|
||||
raise
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
|
@ -268,7 +268,7 @@ class Receiver(object):
|
||||
<<ACTION>>
|
||||
)``
|
||||
"""
|
||||
eventreceiver = EventReceiver()
|
||||
__eventreceiver__ = EventReceiver()
|
||||
|
||||
@staticmethod
|
||||
def send_message(event, msg=None):
|
||||
@ -281,11 +281,11 @@ class Receiver(object):
|
||||
``msg``
|
||||
Defaults to *None*. The message to send with the event.
|
||||
"""
|
||||
Receiver.eventreceiver.send_message(event, msg)
|
||||
Receiver.__eventreceiver__.send_message(event, msg)
|
||||
|
||||
@staticmethod
|
||||
def get_receiver():
|
||||
"""
|
||||
Get the global ``eventreceiver`` instance.
|
||||
Get the global ``__eventreceiver__`` instance.
|
||||
"""
|
||||
return Receiver.eventreceiver
|
||||
return Receiver.__eventreceiver__
|
||||
|
@ -32,6 +32,7 @@ import cPickle
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
|
||||
class FormattingTags(object):
|
||||
@ -68,7 +69,7 @@ class FormattingTags(object):
|
||||
if isinstance(tag[element], unicode):
|
||||
tag[element] = tag[element].encode('utf8')
|
||||
# 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''))
|
||||
|
||||
@staticmethod
|
||||
@ -164,7 +165,7 @@ class FormattingTags(object):
|
||||
FormattingTags.add_html_tags(temporary_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()
|
||||
# cPickle only accepts str not unicode strings
|
||||
user_expands_string = str(user_expands)
|
||||
|
@ -38,6 +38,7 @@ from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, \
|
||||
from openlp.core.lib.searchedit import SearchEdit
|
||||
from openlp.core.lib.ui import UiStrings, create_widget_action, \
|
||||
critical_error_message_box
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -462,7 +463,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
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():
|
||||
self.onLiveClick()
|
||||
else:
|
||||
@ -472,7 +473,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
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 \
|
||||
and self.listView.selectedIndexes() \
|
||||
and self.autoSelectId == -1:
|
||||
|
@ -32,6 +32,7 @@ import logging
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import Receiver
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.core.utils import get_application_version
|
||||
|
||||
@ -190,7 +191,7 @@ class Plugin(QtCore.QObject):
|
||||
"""
|
||||
Sets the status of the plugin
|
||||
"""
|
||||
self.status = QtCore.QSettings().value(
|
||||
self.status = Settings().value(
|
||||
self.settingsSection + u'/status',
|
||||
QtCore.QVariant(PluginStatus.Inactive)).toInt()[0]
|
||||
|
||||
@ -199,7 +200,7 @@ class Plugin(QtCore.QObject):
|
||||
Changes the status of the plugin and remembers it
|
||||
"""
|
||||
self.status = new_status
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
self.settingsSection + u'/status', QtCore.QVariant(self.status))
|
||||
if new_status == PluginStatus.Active:
|
||||
self.initialise()
|
||||
|
@ -41,13 +41,13 @@ class PluginManager(object):
|
||||
and executes all the hooks, as and when necessary.
|
||||
"""
|
||||
log.info(u'Plugin manager loaded')
|
||||
|
||||
__instance__ = None
|
||||
@staticmethod
|
||||
def get_instance():
|
||||
"""
|
||||
Obtain a single instance of class.
|
||||
"""
|
||||
return PluginManager.instance
|
||||
return PluginManager.__instance__
|
||||
|
||||
def __init__(self, plugin_dir):
|
||||
"""
|
||||
@ -58,7 +58,7 @@ class PluginManager(object):
|
||||
The directory to search for plugins.
|
||||
"""
|
||||
log.info(u'Plugin manager Initialising')
|
||||
PluginManager.instance = self
|
||||
PluginManager.__instance__ = self
|
||||
if not plugin_dir in sys.path:
|
||||
log.debug(u'Inserting %s into sys.path', plugin_dir)
|
||||
sys.path.insert(0, plugin_dir)
|
||||
|
@ -55,29 +55,32 @@ class Renderer(object):
|
||||
"""
|
||||
log.info(u'Renderer Loaded')
|
||||
|
||||
def __init__(self, imageManager, themeManager):
|
||||
def __init__(self, image_manager, theme_manager):
|
||||
"""
|
||||
Initialise the renderer.
|
||||
|
||||
``imageManager``
|
||||
A imageManager instance which takes care of e. g. caching and resizing
|
||||
images.
|
||||
``image_manager``
|
||||
A image_manager instance which takes care of e. g. caching and
|
||||
resizing images.
|
||||
|
||||
``themeManager``
|
||||
The themeManager instance, used to get the current theme details.
|
||||
``theme_manager``
|
||||
The theme_manager instance, used to get the current theme details.
|
||||
"""
|
||||
log.debug(u'Initialisation started')
|
||||
self.themeManager = themeManager
|
||||
self.imageManager = imageManager
|
||||
self.theme_manager = theme_manager
|
||||
self.image_manager = image_manager
|
||||
self.screens = ScreenList()
|
||||
self.service_theme = u''
|
||||
self.theme_level = u''
|
||||
self.override_background = None
|
||||
self.theme_data = None
|
||||
self.bg_frame = None
|
||||
self.theme_level = ThemeLevel.Global
|
||||
self.global_theme_name = u''
|
||||
self.service_theme_name = u''
|
||||
self.item_theme_name = u''
|
||||
self.force_page = False
|
||||
self.display = MainDisplay(None, self.imageManager, False, self)
|
||||
self.display = MainDisplay(None, self.image_manager, False, self)
|
||||
self.display.setup()
|
||||
self._theme_dimensions = {}
|
||||
self._calculate_default()
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'theme_update_global'), self.set_global_theme)
|
||||
|
||||
def update_display(self):
|
||||
"""
|
||||
@ -87,100 +90,132 @@ class Renderer(object):
|
||||
self._calculate_default()
|
||||
if self.display:
|
||||
self.display.close()
|
||||
self.display = MainDisplay(None, self.imageManager, False, self)
|
||||
self.display = MainDisplay(None, self.image_manager, False, self)
|
||||
self.display.setup()
|
||||
self.bg_frame = None
|
||||
self.theme_data = None
|
||||
self._theme_dimensions = {}
|
||||
|
||||
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
|
||||
def update_theme(self, theme_name, old_theme_name=None, only_delete=False):
|
||||
"""
|
||||
Set the global-level theme and the theme level.
|
||||
This method updates the theme in ``_theme_dimensions`` when a theme
|
||||
has been edited or renamed.
|
||||
|
||||
``global_theme``
|
||||
The global-level theme to be set.
|
||||
``theme_name``
|
||||
The current theme name.
|
||||
|
||||
``old_theme_name``
|
||||
The old theme name. Has only to be passed, when the theme has been
|
||||
renamed. Defaults to *None*.
|
||||
|
||||
``only_delete``
|
||||
Only remove the given ``theme_name`` from the ``_theme_dimensions``
|
||||
list. This can be used when a theme is permanently deleted.
|
||||
"""
|
||||
if old_theme_name is not None and \
|
||||
old_theme_name in self._theme_dimensions:
|
||||
del self._theme_dimensions[old_theme_name]
|
||||
if theme_name in self._theme_dimensions:
|
||||
del self._theme_dimensions[theme_name]
|
||||
if not only_delete:
|
||||
self._set_theme(theme_name)
|
||||
|
||||
def _set_theme(self, theme_name):
|
||||
"""
|
||||
Helper method to save theme names and theme data.
|
||||
|
||||
``theme_name``
|
||||
The theme name.
|
||||
"""
|
||||
if theme_name not in self._theme_dimensions:
|
||||
theme_data = self.theme_manager.getThemeData(theme_name)
|
||||
main_rect = self.get_main_rectangle(theme_data)
|
||||
footer_rect = self.get_footer_rectangle(theme_data)
|
||||
self._theme_dimensions[theme_name] = \
|
||||
[theme_data, main_rect, footer_rect]
|
||||
else:
|
||||
theme_data, main_rect, footer_rect = \
|
||||
self._theme_dimensions[theme_name]
|
||||
# if No file do not update cache
|
||||
if theme_data.background_filename:
|
||||
self.image_manager.addImage(theme_data.theme_name,
|
||||
theme_data.background_filename, u'theme',
|
||||
QtGui.QColor(theme_data.background_border_color))
|
||||
|
||||
def pre_render(self, override_theme_data=None):
|
||||
"""
|
||||
Set up the theme to be used before rendering an item.
|
||||
|
||||
``override_theme_data``
|
||||
The theme data should be passed, when we want to use our own theme
|
||||
data, regardless of the theme level. This should for example be used
|
||||
in the theme manager. **Note**, this is **not** to be mixed up with
|
||||
the ``set_item_theme`` method.
|
||||
"""
|
||||
# Just assume we use the global theme.
|
||||
theme_to_use = self.global_theme_name
|
||||
# The theme level is either set to Service or Item. Use the service
|
||||
# theme if one is set. We also have to use the service theme, even when
|
||||
# the theme level is set to Item, because the item does not necessarily
|
||||
# have to have a theme.
|
||||
if self.theme_level != ThemeLevel.Global:
|
||||
# When the theme level is at Service and we actually have a service
|
||||
# theme then use it.
|
||||
if self.service_theme_name:
|
||||
theme_to_use = self.service_theme_name
|
||||
# If we have Item level and have an item theme then use it.
|
||||
if self.theme_level == ThemeLevel.Song and self.item_theme_name:
|
||||
theme_to_use = self.item_theme_name
|
||||
if override_theme_data is None:
|
||||
if theme_to_use not in self._theme_dimensions:
|
||||
self._set_theme(theme_to_use)
|
||||
theme_data, main_rect, footer_rect = \
|
||||
self._theme_dimensions[theme_to_use]
|
||||
else:
|
||||
# Ignore everything and use own theme data.
|
||||
theme_data = override_theme_data
|
||||
main_rect = self.get_main_rectangle(override_theme_data)
|
||||
footer_rect = self.get_footer_rectangle(override_theme_data)
|
||||
self._set_text_rectangle(theme_data, main_rect, footer_rect)
|
||||
return theme_data, self._rect, self._rect_footer
|
||||
|
||||
def set_theme_level(self, theme_level):
|
||||
"""
|
||||
Sets the theme level.
|
||||
|
||||
``theme_level``
|
||||
Defaults to ``ThemeLevel.Global``. The theme level, can be
|
||||
``ThemeLevel.Global``, ``ThemeLevel.Service`` or
|
||||
``ThemeLevel.Song``.
|
||||
The theme level to be used.
|
||||
"""
|
||||
self.global_theme = global_theme
|
||||
self.theme_level = theme_level
|
||||
self.global_theme_data = \
|
||||
self.themeManager.getThemeData(self.global_theme)
|
||||
self.theme_data = None
|
||||
self._cache_background_image(self.global_theme_data)
|
||||
|
||||
def set_service_theme(self, service_theme):
|
||||
def set_global_theme(self, global_theme_name):
|
||||
"""
|
||||
Set the global-level theme name.
|
||||
|
||||
``global_theme_name``
|
||||
The global-level theme's name.
|
||||
"""
|
||||
self._set_theme(global_theme_name)
|
||||
self.global_theme_name = global_theme_name
|
||||
|
||||
def set_service_theme(self, service_theme_name):
|
||||
"""
|
||||
Set the service-level theme.
|
||||
|
||||
``service_theme``
|
||||
The service-level theme to be set.
|
||||
``service_theme_name``
|
||||
The service level theme's name.
|
||||
"""
|
||||
self.service_theme = service_theme
|
||||
self.theme_data = None
|
||||
self._cache_background_image(self.themeManager.getThemeData
|
||||
(service_theme))
|
||||
self._set_theme(service_theme_name)
|
||||
self.service_theme_name = service_theme_name
|
||||
|
||||
def _cache_background_image(self, temp_theme):
|
||||
def set_item_theme(self, item_theme_name):
|
||||
"""
|
||||
Adds a background image to the image cache if necessary.
|
||||
Set the item-level theme. **Note**, this has to be done for each item we
|
||||
are rendering.
|
||||
|
||||
``temp_theme``
|
||||
The theme object containing the theme data.
|
||||
``item_theme_name``
|
||||
The item theme's name.
|
||||
"""
|
||||
# if No file do not update cache
|
||||
if temp_theme.background_filename:
|
||||
self.imageManager.addImage(temp_theme.theme_name,
|
||||
temp_theme.background_filename, u'theme',
|
||||
QtGui.QColor(temp_theme.background_border_color))
|
||||
|
||||
def set_override_theme(self, override_theme, override_levels=False):
|
||||
"""
|
||||
Set the appropriate theme depending on the theme level.
|
||||
Called by the service item when building a display frame
|
||||
|
||||
``override_theme``
|
||||
The name of the song-level theme. None means the service
|
||||
item wants to use the given value.
|
||||
|
||||
``override_levels``
|
||||
Used to force the theme data passed in to be used.
|
||||
"""
|
||||
log.debug(u'set override theme to %s', override_theme)
|
||||
theme_level = self.theme_level
|
||||
if override_levels:
|
||||
theme_level = ThemeLevel.Song
|
||||
if theme_level == ThemeLevel.Global:
|
||||
theme = self.global_theme
|
||||
elif theme_level == ThemeLevel.Service:
|
||||
if self.service_theme == u'':
|
||||
theme = self.global_theme
|
||||
else:
|
||||
theme = self.service_theme
|
||||
else:
|
||||
# Images have a theme of -1
|
||||
if override_theme and override_theme != -1:
|
||||
theme = override_theme
|
||||
elif theme_level == ThemeLevel.Song or \
|
||||
theme_level == ThemeLevel.Service:
|
||||
if self.service_theme == u'':
|
||||
theme = self.global_theme
|
||||
else:
|
||||
theme = self.service_theme
|
||||
else:
|
||||
theme = self.global_theme
|
||||
log.debug(u'theme is now %s', theme)
|
||||
# Force the theme to be the one passed in.
|
||||
if override_levels:
|
||||
self.theme_data = override_theme
|
||||
else:
|
||||
self.theme_data = self.themeManager.getThemeData(theme)
|
||||
self._calculate_default()
|
||||
self._build_text_rectangle(self.theme_data)
|
||||
self._cache_background_image(self.theme_data)
|
||||
return self._rect, self._rect_footer
|
||||
self._set_theme(item_theme_name)
|
||||
self.item_theme_name = item_theme_name
|
||||
|
||||
def generate_preview(self, theme_data, force_page=False):
|
||||
"""
|
||||
@ -195,27 +230,31 @@ class Renderer(object):
|
||||
log.debug(u'generate preview')
|
||||
# save value for use in format_slide
|
||||
self.force_page = force_page
|
||||
# set the default image size for previews
|
||||
self._calculate_default()
|
||||
# build a service item to generate preview
|
||||
serviceItem = ServiceItem()
|
||||
serviceItem.theme = theme_data
|
||||
if self.force_page:
|
||||
# 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:
|
||||
self.imageManager.deleteImage(theme_data.theme_name)
|
||||
serviceItem.add_from_text(u'', VERSE)
|
||||
self.image_manager.deleteImage(theme_data.theme_name)
|
||||
serviceItem.add_from_text(VERSE)
|
||||
serviceItem.renderer = self
|
||||
serviceItem.raw_footer = FOOTER
|
||||
# if No file do not update cache
|
||||
if theme_data.background_filename:
|
||||
self.image_manager.addImage(theme_data.theme_name,
|
||||
theme_data.background_filename, u'theme',
|
||||
QtGui.QColor(theme_data.background_border_color))
|
||||
theme_data, main, footer = self.pre_render(theme_data)
|
||||
serviceItem.themedata = theme_data
|
||||
serviceItem.main = main
|
||||
serviceItem.footer = footer
|
||||
serviceItem.render(True)
|
||||
if not self.force_page:
|
||||
self.display.buildHtml(serviceItem)
|
||||
raw_html = serviceItem.get_rendered_frame(0)
|
||||
self.display.text(raw_html)
|
||||
preview = self.display.preview()
|
||||
# Reset the real screen size for subsequent render requests
|
||||
self._calculate_default()
|
||||
return preview
|
||||
self.force_page = False
|
||||
|
||||
@ -264,7 +303,7 @@ class Renderer(object):
|
||||
try:
|
||||
text_to_render, text = \
|
||||
text.split(u'\n[---]\n', 1)
|
||||
except:
|
||||
except ValueError:
|
||||
text_to_render = text.split(u'\n[---]\n')[0]
|
||||
text = u''
|
||||
text_to_render, raw_tags, html_tags = \
|
||||
@ -315,52 +354,41 @@ class Renderer(object):
|
||||
# 90% is start of footer
|
||||
self.footer_start = int(self.height * 0.90)
|
||||
|
||||
def _build_text_rectangle(self, theme):
|
||||
"""
|
||||
Builds a text block using the settings in ``theme``
|
||||
and the size of the display screen.height.
|
||||
Note the system has a 10 pixel border round the screen
|
||||
|
||||
``theme``
|
||||
The theme to build a text block for.
|
||||
"""
|
||||
log.debug(u'_build_text_rectangle')
|
||||
main_rect = self.get_main_rectangle(theme)
|
||||
footer_rect = self.get_footer_rectangle(theme)
|
||||
self._set_text_rectangle(main_rect, footer_rect)
|
||||
|
||||
def get_main_rectangle(self, theme):
|
||||
def get_main_rectangle(self, theme_data):
|
||||
"""
|
||||
Calculates the placement and size of the main rectangle.
|
||||
|
||||
``theme``
|
||||
``theme_data``
|
||||
The theme information
|
||||
"""
|
||||
if not theme.font_main_override:
|
||||
return QtCore.QRect(10, 0, self.width - 20, self.footer_start)
|
||||
if not theme_data.font_main_override:
|
||||
return QtCore.QRect(10, 0, self.width, self.footer_start)
|
||||
else:
|
||||
return QtCore.QRect(theme.font_main_x, theme.font_main_y,
|
||||
theme.font_main_width - 1, theme.font_main_height - 1)
|
||||
return QtCore.QRect(theme_data.font_main_x, theme_data.font_main_y,
|
||||
theme_data.font_main_width - 1, theme_data.font_main_height - 1)
|
||||
|
||||
def get_footer_rectangle(self, theme):
|
||||
def get_footer_rectangle(self, theme_data):
|
||||
"""
|
||||
Calculates the placement and size of the footer rectangle.
|
||||
|
||||
``theme``
|
||||
The theme information
|
||||
``theme_data``
|
||||
The theme data.
|
||||
"""
|
||||
if not theme.font_footer_override:
|
||||
if not theme_data.font_footer_override:
|
||||
return QtCore.QRect(10, self.footer_start, self.width - 20,
|
||||
self.height - self.footer_start)
|
||||
else:
|
||||
return QtCore.QRect(theme.font_footer_x,
|
||||
theme.font_footer_y, theme.font_footer_width - 1,
|
||||
theme.font_footer_height - 1)
|
||||
return QtCore.QRect(theme_data.font_footer_x,
|
||||
theme_data.font_footer_y, theme_data.font_footer_width - 1,
|
||||
theme_data.font_footer_height - 1)
|
||||
|
||||
def _set_text_rectangle(self, rect_main, rect_footer):
|
||||
def _set_text_rectangle(self, theme_data, rect_main, rect_footer):
|
||||
"""
|
||||
Sets the rectangle within which text should be rendered.
|
||||
|
||||
``theme_data``
|
||||
The theme data.
|
||||
|
||||
``rect_main``
|
||||
The main text block.
|
||||
|
||||
@ -372,9 +400,9 @@ class Renderer(object):
|
||||
self._rect_footer = rect_footer
|
||||
self.page_width = self._rect.width()
|
||||
self.page_height = self._rect.height()
|
||||
if self.theme_data.font_main_shadow:
|
||||
self.page_width -= int(self.theme_data.font_main_shadow_size)
|
||||
self.page_height -= int(self.theme_data.font_main_shadow_size)
|
||||
if theme_data.font_main_shadow:
|
||||
self.page_width -= int(theme_data.font_main_shadow_size)
|
||||
self.page_height -= int(theme_data.font_main_shadow_size)
|
||||
self.web = QtWebKit.QWebView()
|
||||
self.web.setVisible(False)
|
||||
self.web.resize(self.page_width, self.page_height)
|
||||
@ -392,8 +420,8 @@ class Renderer(object):
|
||||
</script><style>*{margin: 0; padding: 0; border: 0;}
|
||||
#main {position: absolute; top: 0px; %s %s}</style></head><body>
|
||||
<div id="main"></div></body></html>""" % \
|
||||
(build_lyrics_format_css(self.theme_data, self.page_width,
|
||||
self.page_height), build_lyrics_outline_css(self.theme_data))
|
||||
(build_lyrics_format_css(theme_data, self.page_width,
|
||||
self.page_height), build_lyrics_outline_css(theme_data))
|
||||
self.web.setHtml(html)
|
||||
self.empty_height = self.web_frame.contentsSize().height()
|
||||
|
||||
|
@ -158,19 +158,24 @@ class ServiceItem(object):
|
||||
self.icon = icon
|
||||
self.iconic_representation = build_icon(icon)
|
||||
|
||||
def render(self, use_override=False):
|
||||
def render(self, provides_own_theme_data=False):
|
||||
"""
|
||||
The render method is what generates the frames for the screen and
|
||||
obtains the display information from the renderer. At this point all
|
||||
slides are built for the given display size.
|
||||
|
||||
``provides_own_theme_data``
|
||||
This switch disables the usage of the item's theme. However, this is
|
||||
disabled by default. If this is used, it has to be taken care, that
|
||||
the renderer knows the correct theme data. However, this is needed
|
||||
for the theme manager.
|
||||
"""
|
||||
log.debug(u'Render called')
|
||||
self._display_frames = []
|
||||
self.bg_image_bytes = None
|
||||
theme = self.theme if self.theme else None
|
||||
self.main, self.footer = \
|
||||
self.renderer.set_override_theme(theme, use_override)
|
||||
self.themedata = self.renderer.theme_data
|
||||
if not provides_own_theme_data:
|
||||
self.renderer.set_item_theme(self.theme)
|
||||
self.themedata, self.main, self.footer = self.renderer.pre_render()
|
||||
if self.service_item_type == ServiceItemType.Text:
|
||||
log.debug(u'Formatting slides')
|
||||
for slide in self._raw_frames:
|
||||
@ -211,24 +216,21 @@ class ServiceItem(object):
|
||||
self.image_border = background
|
||||
self.service_item_type = ServiceItemType.Image
|
||||
self._raw_frames.append({u'title': title, u'path': path})
|
||||
self.renderer.imageManager.addImage(title, path, u'image',
|
||||
self.renderer.image_manager.addImage(title, path, u'image',
|
||||
self.image_border)
|
||||
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.
|
||||
|
||||
``frame_title``
|
||||
The title of the slide in the service item.
|
||||
|
||||
``raw_slide``
|
||||
The raw text of the slide.
|
||||
"""
|
||||
if verse_tag:
|
||||
verse_tag = verse_tag.upper()
|
||||
self.service_item_type = ServiceItemType.Text
|
||||
title = title.split(u'\n')[0]
|
||||
title = raw_slide[:30].split(u'\n')[0]
|
||||
self._raw_frames.append(
|
||||
{u'title': title, u'raw_slide': raw_slide, u'verseTag': verse_tag})
|
||||
self._new_item()
|
||||
|
66
openlp/core/lib/settings.py
Normal file
66
openlp/core/lib/settings.py
Normal 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)
|
@ -34,6 +34,7 @@ import os
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.utils import AppLocation
|
||||
|
||||
class SettingsManager(object):
|
||||
@ -58,7 +59,7 @@ class SettingsManager(object):
|
||||
name = u'last directory %d' % num
|
||||
else:
|
||||
name = u'last directory'
|
||||
last_dir = unicode(QtCore.QSettings().value(
|
||||
last_dir = unicode(Settings().value(
|
||||
section + u'/' + name, QtCore.QVariant(u'')).toString())
|
||||
return last_dir
|
||||
|
||||
@ -81,7 +82,7 @@ class SettingsManager(object):
|
||||
name = u'last directory %d' % num
|
||||
else:
|
||||
name = u'last directory'
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
section + u'/' + name, QtCore.QVariant(directory))
|
||||
|
||||
@staticmethod
|
||||
@ -98,7 +99,7 @@ class SettingsManager(object):
|
||||
``list``
|
||||
The list of values to save.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(section)
|
||||
old_count = settings.value(
|
||||
u'%s count' % name, QtCore.QVariant(0)).toInt()[0]
|
||||
@ -124,7 +125,7 @@ class SettingsManager(object):
|
||||
``name``
|
||||
The name of the list.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(section)
|
||||
list_count = settings.value(
|
||||
u'%s count' % name, QtCore.QVariant(0)).toInt()[0]
|
||||
|
@ -80,6 +80,10 @@ class UiStrings(object):
|
||||
self.Help = translate('OpenLP.Ui', 'Help')
|
||||
self.Hours = translate('OpenLP.Ui', 'h',
|
||||
'The abbreviated unit for hours')
|
||||
self.IFdSs = translate('OpenLP.Ui', 'Invalid Folder Selected',
|
||||
'Singular')
|
||||
self.IFSs = translate('OpenLP.Ui', 'Invalid File Selected', 'Singular')
|
||||
self.IFSp = translate('OpenLP.Ui', 'Invalid Files Selected', 'Plural')
|
||||
self.Image = translate('OpenLP.Ui', 'Image')
|
||||
self.Import = translate('OpenLP.Ui', 'Import')
|
||||
self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import UiStrings, create_button, create_button_box
|
||||
|
@ -31,10 +31,16 @@ from datetime import datetime, timedelta
|
||||
|
||||
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.settings import Settings
|
||||
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.utils import get_images_filter
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class AdvancedTab(SettingsTab):
|
||||
"""
|
||||
@ -59,6 +65,7 @@ class AdvancedTab(SettingsTab):
|
||||
'#strftime-strptime-behavior for more information.'))
|
||||
self.defaultImage = u':/graphics/openlp-splash-screen.png'
|
||||
self.defaultColor = u'#ffffff'
|
||||
self.dataExists = False
|
||||
self.iconPath = u':/system/system_settings.png'
|
||||
advanced_translated = translate('OpenLP.AdvancedTab', 'Advanced')
|
||||
SettingsTab.__init__(self, parent, u'Advanced', advanced_translated)
|
||||
@ -151,6 +158,71 @@ class AdvancedTab(SettingsTab):
|
||||
self.serviceNameLayout.addRow(self.serviceNameExampleLabel,
|
||||
self.serviceNameExample)
|
||||
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()
|
||||
# Default Image
|
||||
self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn)
|
||||
@ -219,7 +291,6 @@ class AdvancedTab(SettingsTab):
|
||||
self.x11Layout.addWidget(self.x11BypassCheckBox)
|
||||
self.rightLayout.addWidget(self.x11GroupBox)
|
||||
self.rightLayout.addStretch()
|
||||
|
||||
self.shouldUpdateServiceNameExample = False
|
||||
QtCore.QObject.connect(self.serviceNameCheckBox,
|
||||
QtCore.SIGNAL(u'toggled(bool)'), self.serviceNameCheckBoxToggled)
|
||||
@ -243,6 +314,18 @@ class AdvancedTab(SettingsTab):
|
||||
QtCore.SIGNAL(u'clicked()'), self.onDefaultRevertButtonClicked)
|
||||
QtCore.QObject.connect(self.x11BypassCheckBox,
|
||||
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.SIGNAL(u'clicked()'), self.onEndSlideButtonClicked)
|
||||
QtCore.QObject.connect(self.wrapSlideRadioButton,
|
||||
@ -257,6 +340,8 @@ class AdvancedTab(SettingsTab):
|
||||
self.tabTitleVisible = UiStrings().Advanced
|
||||
self.uiGroupBox.setTitle(
|
||||
translate('OpenLP.AdvancedTab', 'UI Settings'))
|
||||
self.dataDirectoryGroupBox.setTitle(
|
||||
translate('OpenLP.AdvancedTab', 'Data Location'))
|
||||
self.recentLabel.setText(
|
||||
translate('OpenLP.AdvancedTab',
|
||||
'Number of recent files to display:'))
|
||||
@ -320,6 +405,32 @@ class AdvancedTab(SettingsTab):
|
||||
'Browse for an image file to display.'))
|
||||
self.defaultRevertButton.setToolTip(translate('OpenLP.AdvancedTab',
|
||||
'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',
|
||||
'X11'))
|
||||
self.x11BypassCheckBox.setText(translate('OpenLP.AdvancedTab',
|
||||
@ -340,12 +451,12 @@ class AdvancedTab(SettingsTab):
|
||||
"""
|
||||
Load settings from disk.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
# The max recent files value does not have an interface and so never
|
||||
# gets actually stored in the settings therefore the default value of
|
||||
# 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])
|
||||
self.recentSpinBox.setValue(settings.value(u'recent file count',
|
||||
QtCore.QVariant(4)).toInt()[0])
|
||||
@ -397,6 +508,40 @@ class AdvancedTab(SettingsTab):
|
||||
else:
|
||||
self.nextItemRadioButton.setChecked(True)
|
||||
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(
|
||||
u'background-color: %s' % self.defaultColor)
|
||||
|
||||
@ -404,7 +549,7 @@ class AdvancedTab(SettingsTab):
|
||||
"""
|
||||
Save settings to disk.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'default service enabled',
|
||||
self.serviceNameCheckBox.isChecked())
|
||||
@ -446,6 +591,11 @@ class AdvancedTab(SettingsTab):
|
||||
self.displayChanged = False
|
||||
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):
|
||||
self.serviceNameDay.setEnabled(default_service_enabled)
|
||||
time_enabled = default_service_enabled and \
|
||||
@ -507,6 +657,122 @@ class AdvancedTab(SettingsTab):
|
||||
self.defaultFileEdit.setText(filename)
|
||||
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):
|
||||
self.defaultFileEdit.setText(u':/graphics/openlp-splash-screen.png')
|
||||
self.defaultFileEdit.setFocus()
|
||||
|
@ -39,6 +39,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate, PluginStatus, Receiver, build_icon, \
|
||||
check_directory_exists
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.utils import get_web_page, AppLocation
|
||||
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'))
|
||||
self.noInternetFinishButton.setVisible(False)
|
||||
# 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()
|
||||
# Sort out internet access for downloads
|
||||
if self.webAccess:
|
||||
@ -209,7 +210,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
index = self.themeComboBox.findText(theme)
|
||||
if index == -1:
|
||||
self.themeComboBox.addItem(theme)
|
||||
default_theme = unicode(QtCore.QSettings().value(
|
||||
default_theme = unicode(Settings().value(
|
||||
u'themes/global theme',
|
||||
QtCore.QVariant(u'')).toString())
|
||||
# Pre-select the current default theme.
|
||||
@ -261,7 +262,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self._performWizard()
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
QtCore.QSettings().setValue(u'general/has run wizard',
|
||||
Settings().setValue(u'general/has run wizard',
|
||||
QtCore.QVariant(True))
|
||||
self.close()
|
||||
|
||||
@ -460,16 +461,16 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
os.path.join(themes_destination, theme))
|
||||
# Set Default Display
|
||||
if self.displayComboBox.currentIndex() != -1:
|
||||
QtCore.QSettings().setValue(u'General/monitor',
|
||||
Settings().setValue(u'General/monitor',
|
||||
QtCore.QVariant(self.displayComboBox.currentIndex()))
|
||||
self.screens.set_current_display(
|
||||
self.displayComboBox.currentIndex())
|
||||
# Set Global Theme
|
||||
if self.themeComboBox.currentIndex() != -1:
|
||||
QtCore.QSettings().setValue(u'themes/global theme',
|
||||
Settings().setValue(u'themes/global theme',
|
||||
QtCore.QVariant(self.themeComboBox.currentText()))
|
||||
|
||||
def _setPluginStatus(self, field, tag):
|
||||
status = PluginStatus.Active if field.checkState() \
|
||||
== QtCore.Qt.Checked else PluginStatus.Inactive
|
||||
QtCore.QSettings().setValue(tag, QtCore.QVariant(status))
|
||||
Settings().setValue(tag, QtCore.QVariant(status))
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import create_button_box
|
||||
|
@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, Receiver, translate
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.ui import ScreenList
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -265,7 +266,7 @@ class GeneralTab(SettingsTab):
|
||||
"""
|
||||
Load the settings to populate the form
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.monitorComboBox.clear()
|
||||
self.monitorComboBox.addItems(self.screens.get_screen_list())
|
||||
@ -327,7 +328,7 @@ class GeneralTab(SettingsTab):
|
||||
"""
|
||||
Save the settings from the form
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'monitor',
|
||||
QtCore.QVariant(self.monitorComboBox.currentIndex()))
|
||||
|
@ -38,6 +38,7 @@ from PyQt4.phonon import Phonon
|
||||
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \
|
||||
translate, PluginManager, expand_tags
|
||||
from openlp.core.lib.theme import BackgroundType
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
from openlp.core.ui import HideMode, ScreenList, AlertLocation
|
||||
|
||||
@ -100,9 +101,8 @@ class Display(QtGui.QGraphicsView):
|
||||
self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal,
|
||||
QtCore.Qt.ScrollBarAlwaysOff)
|
||||
|
||||
def resizeEvent(self, ev):
|
||||
self.webView.setGeometry(0, 0,
|
||||
self.width(), self.height())
|
||||
def resizeEvent(self, event):
|
||||
self.webView.setGeometry(0, 0, self.width(), self.height())
|
||||
|
||||
def isWebLoaded(self):
|
||||
"""
|
||||
@ -120,7 +120,6 @@ class MainDisplay(Display):
|
||||
Display.__init__(self, parent, live, controller)
|
||||
self.imageManager = imageManager
|
||||
self.screens = ScreenList()
|
||||
self.plugins = PluginManager.get_instance().plugins
|
||||
self.rebuildCSS = False
|
||||
self.hideMode = None
|
||||
self.override = {}
|
||||
@ -131,10 +130,11 @@ class MainDisplay(Display):
|
||||
else:
|
||||
self.audioPlayer = None
|
||||
self.firstTime = True
|
||||
self.webLoaded = True
|
||||
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
|
||||
windowFlags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | \
|
||||
QtCore.Qt.WindowStaysOnTopHint
|
||||
if QtCore.QSettings().value(u'advanced/x11 bypass wm',
|
||||
QtCore.Qt.WindowStaysOnTopHint
|
||||
if Settings().value(u'advanced/x11 bypass wm',
|
||||
QtCore.QVariant(True)).toBool():
|
||||
windowFlags |= QtCore.Qt.X11BypassWindowManagerHint
|
||||
# FIXME: QtCore.Qt.SplashScreen is workaround to make display screen
|
||||
@ -195,15 +195,15 @@ class MainDisplay(Display):
|
||||
Display.setup(self)
|
||||
if self.isLive:
|
||||
# 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.setNamedColor(QtCore.QSettings().value(
|
||||
background_color.setNamedColor(Settings().value(
|
||||
u'advanced/default color',
|
||||
QtCore.QVariant(u'#ffffff')).toString())
|
||||
if not background_color.isValid():
|
||||
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)
|
||||
self.initialFrame = QtGui.QImage(
|
||||
self.screen[u'size'].width(),
|
||||
@ -290,10 +290,10 @@ class MainDisplay(Display):
|
||||
|
||||
def image(self, name):
|
||||
"""
|
||||
Add an image as the background. The image has already been added
|
||||
to the cache.
|
||||
Add an image as the background. The image has already been added to the
|
||||
cache.
|
||||
|
||||
``Image``
|
||||
``name``
|
||||
The name of the image to be displayed.
|
||||
"""
|
||||
log.debug(u'image to display')
|
||||
@ -352,7 +352,7 @@ class MainDisplay(Display):
|
||||
# Single screen active
|
||||
if self.screens.display_count == 1:
|
||||
# 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():
|
||||
self.setVisible(True)
|
||||
else:
|
||||
@ -401,7 +401,7 @@ class MainDisplay(Display):
|
||||
self.footer(serviceItem.foot_text)
|
||||
# if was hidden keep it hidden
|
||||
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():
|
||||
Receiver.send_message(u'slidecontroller_live_unblank')
|
||||
else:
|
||||
@ -425,7 +425,7 @@ class MainDisplay(Display):
|
||||
log.debug(u'hideDisplay mode = %d', mode)
|
||||
if self.screens.display_count == 1:
|
||||
# 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():
|
||||
return
|
||||
if mode == HideMode.Screen:
|
||||
@ -450,7 +450,7 @@ class MainDisplay(Display):
|
||||
log.debug(u'showDisplay')
|
||||
if self.screens.display_count == 1:
|
||||
# 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():
|
||||
return
|
||||
self.frame.evaluateJavaScript('show_blank("show");')
|
||||
@ -465,7 +465,7 @@ class MainDisplay(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():
|
||||
self.setCursor(QtCore.Qt.BlankCursor)
|
||||
self.frame.evaluateJavaScript('document.body.style.cursor = "none"')
|
||||
|
@ -29,6 +29,8 @@ import logging
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
from distutils import dir_util
|
||||
from distutils.errors import DistutilsFileError
|
||||
from tempfile import gettempdir
|
||||
import time
|
||||
from datetime import datetime
|
||||
@ -38,6 +40,7 @@ from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \
|
||||
PluginManager, Receiver, translate, ImageManager, PluginStatus
|
||||
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.ui import AboutForm, SettingsForm, ServiceManager, \
|
||||
ThemeManager, SlideController, PluginForm, MediaDockManager, \
|
||||
@ -100,12 +103,12 @@ class Ui_MainWindow(object):
|
||||
# Create slide controllers
|
||||
self.previewController = SlideController(self)
|
||||
self.liveController = SlideController(self, True)
|
||||
previewVisible = QtCore.QSettings().value(
|
||||
previewVisible = Settings().value(
|
||||
u'user interface/preview panel', QtCore.QVariant(True)).toBool()
|
||||
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()
|
||||
panelLocked = QtCore.QSettings().value(u'user interface/lock panel',
|
||||
panelLocked = Settings().value(u'user interface/lock panel',
|
||||
QtCore.QVariant(False)).toBool()
|
||||
self.liveController.panel.setVisible(liveVisible)
|
||||
# Create menu
|
||||
@ -582,6 +585,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
# Once settings are loaded update the menu with the recent files.
|
||||
self.updateRecentFilesMenu()
|
||||
self.pluginForm = PluginForm(self)
|
||||
self.newDataPath = u''
|
||||
self.copyData = False
|
||||
# Set up signals and slots
|
||||
QtCore.QObject.connect(self.importThemeItem,
|
||||
QtCore.SIGNAL(u'triggered()'),
|
||||
@ -634,6 +639,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'mainwindow_status_text'), self.showStatusMessage)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'cleanup'), self.cleanUp)
|
||||
# Media Manager
|
||||
QtCore.QObject.connect(self.mediaToolBox,
|
||||
QtCore.SIGNAL(u'currentChanged(int)'), self.onMediaToolBoxChanged)
|
||||
@ -646,6 +653,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'openlp_information_message'),
|
||||
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
|
||||
# renderer needs to call ThemeManager and
|
||||
# ThemeManager needs to call Renderer
|
||||
@ -686,9 +697,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.previewController.screenSizeChanged()
|
||||
self.liveController.screenSizeChanged()
|
||||
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():
|
||||
savedPlugin = QtCore.QSettings().value(
|
||||
savedPlugin = Settings().value(
|
||||
u'advanced/current media plugin', QtCore.QVariant()).toInt()[0]
|
||||
if savedPlugin != -1:
|
||||
self.mediaToolBox.setCurrentIndex(savedPlugin)
|
||||
@ -740,11 +751,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
if not isinstance(filename, unicode):
|
||||
filename = unicode(filename, sys.getfilesystemencoding())
|
||||
self.serviceManagerContents.loadFile(filename)
|
||||
elif QtCore.QSettings().value(
|
||||
elif Settings().value(
|
||||
self.generalSettingsSection + u'/auto open',
|
||||
QtCore.QVariant(False)).toBool():
|
||||
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()
|
||||
if view_mode == u'default':
|
||||
self.modeDefaultItem.setChecked(True)
|
||||
@ -822,7 +833,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
Check and display message if screen blank on setup.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
self.liveController.mainDisplaySetBackground()
|
||||
if settings.value(u'%s/screen blank' % self.generalSettingsSection,
|
||||
QtCore.QVariant(False)).toBool():
|
||||
@ -956,9 +967,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
# Add plugin sections.
|
||||
for plugin in self.pluginManager.plugins:
|
||||
setting_sections.extend([plugin.name])
|
||||
settings = QtCore.QSettings()
|
||||
import_settings = QtCore.QSettings(import_file_name,
|
||||
QtCore.QSettings.IniFormat)
|
||||
settings = Settings()
|
||||
import_settings = Settings(import_file_name,
|
||||
Settings.IniFormat)
|
||||
import_keys = import_settings.allKeys()
|
||||
for section_key in import_keys:
|
||||
# We need to handle the really bad files.
|
||||
@ -1020,7 +1031,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
'OpenLP Export Settings File (*.conf)')))
|
||||
if not export_file_name:
|
||||
return
|
||||
# Make sure it's a .conf file.
|
||||
# Make sure it's a .conf file.
|
||||
if not export_file_name.endswith(u'conf'):
|
||||
export_file_name = export_file_name + u'.conf'
|
||||
temp_file = os.path.join(unicode(gettempdir()),
|
||||
@ -1043,12 +1054,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
os.remove(temp_file)
|
||||
if os.path.exists(export_file_name):
|
||||
os.remove(export_file_name)
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.remove(self.headerSection)
|
||||
# Get the settings.
|
||||
keys = settings.allKeys()
|
||||
export_settings = QtCore.QSettings(temp_file,
|
||||
QtCore.QSettings.IniFormat)
|
||||
export_settings = Settings(temp_file,
|
||||
Settings.IniFormat)
|
||||
# Add a header section.
|
||||
# This is to insure it's our conf file for import.
|
||||
now = datetime.now()
|
||||
@ -1106,7 +1117,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
Set OpenLP to a different view mode.
|
||||
"""
|
||||
if mode:
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.setValue(u'%s/view mode' % self.generalSettingsSection,
|
||||
mode)
|
||||
self.mediaManagerDock.setVisible(media)
|
||||
@ -1157,7 +1168,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
else:
|
||||
event.ignore()
|
||||
else:
|
||||
if QtCore.QSettings().value(u'advanced/enable exit confirmation',
|
||||
if Settings().value(u'advanced/enable exit confirmation',
|
||||
QtCore.QVariant(True)).toBool():
|
||||
ret = QtGui.QMessageBox.question(self,
|
||||
translate('OpenLP.MainWindow', 'Close OpenLP'),
|
||||
@ -1188,9 +1199,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
# Clean temporary files used by services
|
||||
self.serviceManagerContents.cleanUp()
|
||||
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.QSettings().setValue(u'advanced/current media plugin',
|
||||
Settings().setValue(u'advanced/current media plugin',
|
||||
QtCore.QVariant(self.mediaToolBox.currentIndex()))
|
||||
# Call the cleanup method to shutdown plugins.
|
||||
log.info(u'cleanup plugins')
|
||||
@ -1198,6 +1209,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
if save_settings:
|
||||
# Save settings
|
||||
self.saveSettings()
|
||||
# Check if we need to change the data directory
|
||||
if self.newDataPath:
|
||||
self.changeDataDirectory()
|
||||
# Close down the display
|
||||
if self.liveController.display:
|
||||
self.liveController.display.close()
|
||||
@ -1271,7 +1285,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
False - Hidden
|
||||
"""
|
||||
self.previewController.panel.setVisible(visible)
|
||||
QtCore.QSettings().setValue(u'user interface/preview panel',
|
||||
Settings().setValue(u'user interface/preview panel',
|
||||
QtCore.QVariant(visible))
|
||||
self.viewPreviewPanel.setChecked(visible)
|
||||
|
||||
@ -1303,7 +1317,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.viewThemeManagerItem.setEnabled(True)
|
||||
self.viewPreviewPanel.setEnabled(True)
|
||||
self.viewLivePanel.setEnabled(True)
|
||||
QtCore.QSettings().setValue(u'user interface/lock panel',
|
||||
Settings().setValue(u'user interface/lock panel',
|
||||
QtCore.QVariant(lock))
|
||||
|
||||
def setLivePanelVisibility(self, visible):
|
||||
@ -1317,7 +1331,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
False - Hidden
|
||||
"""
|
||||
self.liveController.panel.setVisible(visible)
|
||||
QtCore.QSettings().setValue(u'user interface/live panel',
|
||||
Settings().setValue(u'user interface/live panel',
|
||||
QtCore.QVariant(visible))
|
||||
self.viewLivePanel.setChecked(visible)
|
||||
|
||||
@ -1327,19 +1341,19 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
log.debug(u'Loading QSettings')
|
||||
# Migrate Wrap Settings to Slide Limits Settings
|
||||
if QtCore.QSettings().contains(self.generalSettingsSection +
|
||||
if Settings().contains(self.generalSettingsSection +
|
||||
u'/enable slide loop'):
|
||||
if QtCore.QSettings().value(self.generalSettingsSection +
|
||||
if Settings().value(self.generalSettingsSection +
|
||||
u'/enable slide loop', QtCore.QVariant(True)).toBool():
|
||||
QtCore.QSettings().setValue(self.advancedSettingsSection +
|
||||
Settings().setValue(self.advancedSettingsSection +
|
||||
u'/slide limits', QtCore.QVariant(SlideLimits.Wrap))
|
||||
else:
|
||||
QtCore.QSettings().setValue(self.advancedSettingsSection +
|
||||
Settings().setValue(self.advancedSettingsSection +
|
||||
u'/slide limits', QtCore.QVariant(SlideLimits.End))
|
||||
QtCore.QSettings().remove(self.generalSettingsSection +
|
||||
Settings().remove(self.generalSettingsSection +
|
||||
u'/enable slide loop')
|
||||
Receiver.send_message(u'slidecontroller_update_slide_limits')
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
# Remove obsolete entries.
|
||||
settings.remove(u'custom slide')
|
||||
settings.remove(u'service')
|
||||
@ -1368,7 +1382,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
if self.settingsImported:
|
||||
return
|
||||
log.debug(u'Saving QSettings')
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.generalSettingsSection)
|
||||
recentFiles = QtCore.QVariant(self.recentFiles) \
|
||||
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
|
||||
accessed.
|
||||
"""
|
||||
recentFileCount = QtCore.QSettings().value(
|
||||
recentFileCount = Settings().value(
|
||||
u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0]
|
||||
existingRecentFiles = [recentFile for recentFile in self.recentFiles
|
||||
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
|
||||
# actually stored in the settings therefore the default value of 20 will
|
||||
# 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]
|
||||
if filename:
|
||||
# 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.loadProgressBar.hide()
|
||||
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')
|
||||
|
@ -26,6 +26,8 @@
|
||||
###############################################################################
|
||||
import logging
|
||||
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -78,11 +80,11 @@ def get_media_players():
|
||||
Here an special media player is chosen for all media actions.
|
||||
"""
|
||||
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:
|
||||
players = u'webkit'
|
||||
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:
|
||||
if reg_ex.exactMatch(players):
|
||||
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')
|
||||
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.Qt.Checked and overridden_player != u'auto':
|
||||
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
|
||||
|
@ -30,6 +30,7 @@ import os
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
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.ui import critical_error_message_box
|
||||
from openlp.core.ui.media import MediaState, MediaInfo, MediaType, \
|
||||
@ -333,10 +334,9 @@ class MediaController(object):
|
||||
"setBackBoard", null, null, null,"visible");')
|
||||
# now start playing
|
||||
if controller.isLive and \
|
||||
(QtCore.QSettings().value(u'general/auto unblank',
|
||||
(Settings().value(u'general/auto unblank',
|
||||
QtCore.QVariant(False)).toBool() or \
|
||||
controller.media_info.is_background == True) or \
|
||||
controller.isLive == False:
|
||||
controller.media_info.is_background) or not controller.isLive:
|
||||
if not self.video_play([controller]):
|
||||
critical_error_message_box(
|
||||
translate('MediaPlugin.MediaItem', 'Unsupported File'),
|
||||
@ -495,7 +495,7 @@ class MediaController(object):
|
||||
return
|
||||
controller = self.parent.liveController
|
||||
for display in self.curDisplayMediaPlayer.keys():
|
||||
if display.controller != controller or \
|
||||
if display.controller != controller or \
|
||||
self.curDisplayMediaPlayer[display].state != MediaState.Playing:
|
||||
continue
|
||||
self.curDisplayMediaPlayer[display].pause(display)
|
||||
|
@ -38,21 +38,21 @@ from openlp.core.ui.media import MediaState
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
ADDITIONAL_EXT = {
|
||||
u'audio/ac3': [u'.ac3'],
|
||||
u'audio/flac': [u'.flac'],
|
||||
u'audio/x-m4a': [u'.m4a'],
|
||||
u'audio/midi': [u'.mid', u'.midi'],
|
||||
u'audio/x-mp3': [u'.mp3'],
|
||||
u'audio/mpeg': [u'.mp3', u'.mp2', u'.mpga', u'.mpega', u'.m4a'],
|
||||
u'audio/qcelp': [u'.qcp'],
|
||||
u'audio/x-wma': [u'.wma'],
|
||||
u'audio/x-ms-wma': [u'.wma'],
|
||||
u'video/x-flv': [u'.flv'],
|
||||
u'video/x-matroska': [u'.mpv', u'.mkv'],
|
||||
u'video/x-wmv': [u'.wmv'],
|
||||
u'video/x-mpg': [u'.mpg'],
|
||||
u'video/mpeg' : [u'.mp4', u'.mts'],
|
||||
u'video/x-ms-wmv': [u'.wmv']}
|
||||
u'audio/ac3': [u'.ac3'],
|
||||
u'audio/flac': [u'.flac'],
|
||||
u'audio/x-m4a': [u'.m4a'],
|
||||
u'audio/midi': [u'.mid', u'.midi'],
|
||||
u'audio/x-mp3': [u'.mp3'],
|
||||
u'audio/mpeg': [u'.mp3', u'.mp2', u'.mpga', u'.mpega', u'.m4a'],
|
||||
u'audio/qcelp': [u'.qcp'],
|
||||
u'audio/x-wma': [u'.wma'],
|
||||
u'audio/x-ms-wma': [u'.wma'],
|
||||
u'video/x-flv': [u'.flv'],
|
||||
u'video/x-matroska': [u'.mpv', u'.mkv'],
|
||||
u'video/x-wmv': [u'.wmv'],
|
||||
u'video/x-mpg': [u'.mpg'],
|
||||
u'video/mpeg' : [u'.mp4', u'.mts'],
|
||||
u'video/x-ms-wmv': [u'.wmv']}
|
||||
|
||||
|
||||
class PhononPlayer(MediaPlayer):
|
||||
@ -101,7 +101,7 @@ class PhononPlayer(MediaPlayer):
|
||||
display.mediaObject = Phonon.MediaObject(display)
|
||||
Phonon.createPath(display.mediaObject, display.phononWidget)
|
||||
if display.hasAudio:
|
||||
display.audio = Phonon.AudioOutput( \
|
||||
display.audio = Phonon.AudioOutput(
|
||||
Phonon.VideoCategory, display.mediaObject)
|
||||
Phonon.createPath(display.mediaObject, display.audio)
|
||||
display.phononWidget.raise_()
|
||||
@ -148,18 +148,17 @@ class PhononPlayer(MediaPlayer):
|
||||
controller.media_info.start_time > 0:
|
||||
start_time = controller.media_info.start_time
|
||||
display.mediaObject.play()
|
||||
if self.media_state_wait(display, Phonon.PlayingState):
|
||||
if start_time > 0:
|
||||
self.seek(display, controller.media_info.start_time*1000)
|
||||
self.volume(display, controller.media_info.volume)
|
||||
controller.media_info.length = \
|
||||
int(display.mediaObject.totalTime()/1000)
|
||||
controller.seekSlider.setMaximum(controller.media_info.length*1000)
|
||||
self.state = MediaState.Playing
|
||||
display.phononWidget.raise_()
|
||||
return True
|
||||
else:
|
||||
if not self.media_state_wait(display, Phonon.PlayingState):
|
||||
return False
|
||||
if start_time > 0:
|
||||
self.seek(display, controller.media_info.start_time * 1000)
|
||||
self.volume(display, controller.media_info.volume)
|
||||
controller.media_info.length = \
|
||||
int(display.mediaObject.totalTime() / 1000)
|
||||
controller.seekSlider.setMaximum(controller.media_info.length * 1000)
|
||||
self.state = MediaState.Playing
|
||||
display.phononWidget.raise_()
|
||||
return True
|
||||
|
||||
def pause(self, display):
|
||||
display.mediaObject.pause()
|
||||
@ -198,9 +197,9 @@ class PhononPlayer(MediaPlayer):
|
||||
controller = display.controller
|
||||
if controller.media_info.end_time > 0:
|
||||
if display.mediaObject.currentTime() > \
|
||||
controller.media_info.end_time*1000:
|
||||
controller.media_info.end_time * 1000:
|
||||
self.stop(display)
|
||||
self.set_visible(display, False)
|
||||
if not controller.seekSlider.isSliderDown():
|
||||
controller.seekSlider.setSliderPosition( \
|
||||
controller.seekSlider.setSliderPosition(
|
||||
display.mediaObject.currentTime())
|
||||
|
@ -48,7 +48,7 @@ import sys
|
||||
from inspect import getargspec
|
||||
|
||||
__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
|
||||
# instanciated.
|
||||
@ -235,6 +235,23 @@ def class_result(classname):
|
||||
return classname(result)
|
||||
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 #
|
||||
|
||||
class _Enum(ctypes.c_uint):
|
||||
@ -256,6 +273,21 @@ class _Enum(ctypes.c_uint):
|
||||
def __ne__(self, 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):
|
||||
'''Event types.
|
||||
'''
|
||||
@ -577,6 +609,247 @@ AudioOutputChannel.RStereo = AudioOutputChannel(2)
|
||||
AudioOutputChannel.Right = AudioOutputChannel(4)
|
||||
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 #
|
||||
|
||||
# From libvlc_structures.h
|
||||
@ -905,10 +1178,10 @@ class Instance(_Ctype):
|
||||
def media_new(self, mrl, *options):
|
||||
"""Create a new Media instance.
|
||||
|
||||
If mrl contains a colon (:), it will be treated as a
|
||||
URL. Else, it will be considered as a local path. If you need
|
||||
more control, directly use media_new_location/media_new_path
|
||||
methods.
|
||||
If mrl contains a colon (:) preceded by more than 1 letter, it
|
||||
will be treated as a URL. Else, it will be considered as a
|
||||
local path. If you need more control, directly use
|
||||
media_new_location/media_new_path methods.
|
||||
|
||||
Options can be specified as supplementary string parameters, e.g.
|
||||
|
||||
@ -920,7 +1193,7 @@ class Instance(_Ctype):
|
||||
|
||||
@param options: optional media option=value strings
|
||||
"""
|
||||
if ':' in mrl:
|
||||
if ':' in mrl and mrl.index(':') > 1:
|
||||
# Assume it is a URL
|
||||
m = libvlc_media_new_location(self, mrl)
|
||||
else:
|
||||
@ -995,12 +1268,6 @@ class Instance(_Ctype):
|
||||
'''
|
||||
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):
|
||||
'''Sets the application name. LibVLC passes this as the user agent string
|
||||
when a protocol requires it.
|
||||
@ -1455,7 +1722,11 @@ class Media(_Ctype):
|
||||
This option will be used to determine how the media_player will
|
||||
read the media. This allows to use VLC's advanced
|
||||
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).
|
||||
'''
|
||||
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
|
||||
read the media. This allows to use VLC's advanced
|
||||
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 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
|
||||
before calling this function.
|
||||
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 libvlc_media_get_tracks_info(self)
|
||||
@ -1718,7 +1993,7 @@ class MediaList(_Ctype):
|
||||
"""Add media instance to media list.
|
||||
|
||||
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.
|
||||
"""
|
||||
if isinstance(mrl, basestring):
|
||||
@ -2149,16 +2424,25 @@ class MediaPlayer(_Ctype):
|
||||
def video_set_format(self, chroma, width, height, pitch):
|
||||
'''Set decoded video chroma and dimensions.
|
||||
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 width: pixel width.
|
||||
@param height: pixel height.
|
||||
@param pitch: line pitch (in bytes).
|
||||
@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)
|
||||
|
||||
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):
|
||||
'''Set the NSView handler where the media player should render its video output.
|
||||
Use the vout called "macosx".
|
||||
@ -2234,10 +2518,42 @@ class MediaPlayer(_Ctype):
|
||||
'''
|
||||
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):
|
||||
'''Set decoded audio format.
|
||||
This only works in combination with libvlc_audio_set_callbacks(),
|
||||
and is mutually exclusive with libvlc_audio_set_format_callbacks().
|
||||
This only works in combination with L{audio_set_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 rate: sample rate (expressed in Hz).
|
||||
@param channels: channels count.
|
||||
@ -2797,6 +3113,30 @@ def libvlc_clearerr():
|
||||
None)
|
||||
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):
|
||||
'''Create and initialize a libvlc instance.
|
||||
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)
|
||||
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):
|
||||
'''Sets the application name. LibVLC passes this as the user agent string
|
||||
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 \
|
||||
_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)
|
||||
|
||||
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 \
|
||||
_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)
|
||||
|
||||
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)
|
||||
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):
|
||||
'''Always returns minus one.
|
||||
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
|
||||
read the media. This allows to use VLC's advanced
|
||||
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 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
|
||||
read the media. This allows to use VLC's advanced
|
||||
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 ppsz_options: the options (as a string).
|
||||
@param i_flags: the flags for this option.
|
||||
@ -3384,7 +3761,7 @@ def libvlc_media_get_tracks_info(p_md):
|
||||
before calling this function.
|
||||
Not doing this will result in an empty array.
|
||||
@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.
|
||||
'''
|
||||
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):
|
||||
'''Set decoded video chroma and dimensions.
|
||||
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 chroma: a four-characters string identifying the chroma (e.g. "RV32" or "YUYV").
|
||||
@param width: pixel width.
|
||||
@param height: pixel height.
|
||||
@param pitch: line pitch (in bytes).
|
||||
@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 \
|
||||
_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)
|
||||
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):
|
||||
'''Set the NSView handler where the media player should render its video output.
|
||||
Use the vout called "macosx".
|
||||
@ -4087,10 +4477,54 @@ def libvlc_media_player_get_hwnd(p_mi):
|
||||
ctypes.c_void_p, MediaPlayer)
|
||||
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):
|
||||
'''Set decoded audio format.
|
||||
This only works in combination with libvlc_audio_set_callbacks(),
|
||||
and is mutually exclusive with libvlc_audio_set_format_callbacks().
|
||||
This only works in combination with L{libvlc_audio_set_callbacks}(),
|
||||
and is mutually exclusive with L{libvlc_audio_set_format_callbacks}().
|
||||
@param mp: the media player.
|
||||
@param format: a four-characters string identifying the sample format (e.g. "S16N" or "FL32").
|
||||
@param rate: sample rate (expressed in Hz).
|
||||
@ -5394,17 +5828,11 @@ def libvlc_vlm_get_event_manager(p_instance):
|
||||
return f(p_instance)
|
||||
|
||||
|
||||
# 8 function(s) blacklisted:
|
||||
# libvlc_audio_set_callbacks
|
||||
# libvlc_audio_set_format_callbacks
|
||||
# libvlc_audio_set_volume_callback
|
||||
# libvlc_printerr
|
||||
# 2 function(s) blacklisted:
|
||||
# libvlc_set_exit_handler
|
||||
# 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_clearerr
|
||||
# libvlc_clock
|
||||
@ -5414,10 +5842,15 @@ def libvlc_vlm_get_event_manager(p_instance):
|
||||
# libvlc_get_changeset
|
||||
# libvlc_get_compiler
|
||||
# libvlc_get_version
|
||||
# libvlc_log_subscribe
|
||||
# libvlc_log_subscribe_file
|
||||
# libvlc_log_unsubscribe
|
||||
# libvlc_module_description_list_release
|
||||
# libvlc_new
|
||||
# libvlc_printerr
|
||||
# libvlc_track_description_list_release
|
||||
# libvlc_track_description_release
|
||||
# libvlc_vprinterr
|
||||
|
||||
# Start of footer.py #
|
||||
|
||||
@ -5595,7 +6028,7 @@ if __name__ == '__main__':
|
||||
print('Aspect ratio: %s' % player.video_get_aspect_ratio())
|
||||
#print('Window:' % player.get_hwnd()
|
||||
except Exception:
|
||||
print('Error: %s', sys.exc_info()[1])
|
||||
print('Error: %s' % sys.exc_info()[1])
|
||||
|
||||
def sec_forward():
|
||||
"""Go forward one sec"""
|
||||
|
@ -34,6 +34,7 @@ import sys
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.lib.mediaplayer import MediaPlayer
|
||||
from openlp.core.ui.media import MediaState
|
||||
|
||||
@ -62,7 +63,7 @@ if VLC_AVAILABLE:
|
||||
log.debug(u'VLC could not be loaded: %s' % version)
|
||||
|
||||
AUDIO_EXT = [
|
||||
u'*.mp3'
|
||||
u'*.mp3'
|
||||
, u'*.wav'
|
||||
, u'*.ogg'
|
||||
]
|
||||
@ -114,7 +115,7 @@ class VlcPlayer(MediaPlayer):
|
||||
command_line_options = u'--no-video-title-show'
|
||||
if not display.hasAudio:
|
||||
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 \
|
||||
display.controller.isLive:
|
||||
command_line_options += u' --mouse-hide-timeout=0'
|
||||
@ -130,9 +131,9 @@ class VlcPlayer(MediaPlayer):
|
||||
# this is platform specific!
|
||||
# you have to give the id of the QFrame (or similar object) to
|
||||
# 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()))
|
||||
elif sys.platform == "darwin": # for MacOS
|
||||
elif sys.platform == "darwin":
|
||||
display.vlcMediaPlayer.set_agl(int(display.vlcWidget.winId()))
|
||||
else:
|
||||
# for Linux using the X Server
|
||||
@ -181,17 +182,16 @@ class VlcPlayer(MediaPlayer):
|
||||
if controller.media_info.start_time > 0:
|
||||
start_time = controller.media_info.start_time
|
||||
display.vlcMediaPlayer.play()
|
||||
if self.media_state_wait(display, vlc.State.Playing):
|
||||
if start_time > 0:
|
||||
self.seek(display, controller.media_info.start_time * 1000)
|
||||
controller.media_info.length = \
|
||||
int(display.vlcMediaPlayer.get_media().get_duration() / 1000)
|
||||
controller.seekSlider.setMaximum(controller.media_info.length * 1000)
|
||||
self.state = MediaState.Playing
|
||||
display.vlcWidget.raise_()
|
||||
return True
|
||||
else:
|
||||
if not self.media_state_wait(display, vlc.State.Playing):
|
||||
return False
|
||||
if start_time > 0:
|
||||
self.seek(display, controller.media_info.start_time * 1000)
|
||||
controller.media_info.length = \
|
||||
int(display.vlcMediaPlayer.get_media().get_duration() / 1000)
|
||||
controller.seekSlider.setMaximum(controller.media_info.length * 1000)
|
||||
self.state = MediaState.Playing
|
||||
display.vlcWidget.raise_()
|
||||
return True
|
||||
|
||||
def pause(self, display):
|
||||
if display.vlcMedia.get_state() != vlc.State.Playing:
|
||||
|
@ -227,33 +227,33 @@ FLASH_HTML = u"""
|
||||
"""
|
||||
|
||||
VIDEO_EXT = [
|
||||
u'*.3gp'
|
||||
, u'*.3gpp'
|
||||
, u'*.3g2'
|
||||
, u'*.3gpp2'
|
||||
, u'*.aac'
|
||||
, u'*.flv'
|
||||
, u'*.f4a'
|
||||
, u'*.f4b'
|
||||
, u'*.f4p'
|
||||
, u'*.f4v'
|
||||
, u'*.mov'
|
||||
, u'*.m4a'
|
||||
, u'*.m4b'
|
||||
, u'*.m4p'
|
||||
, u'*.m4v'
|
||||
, u'*.mkv'
|
||||
, u'*.mp4'
|
||||
, u'*.ogv'
|
||||
, u'*.webm'
|
||||
, u'*.mpg', u'*.wmv', u'*.mpeg', u'*.avi'
|
||||
, u'*.swf'
|
||||
]
|
||||
u'*.3gp'
|
||||
, u'*.3gpp'
|
||||
, u'*.3g2'
|
||||
, u'*.3gpp2'
|
||||
, u'*.aac'
|
||||
, u'*.flv'
|
||||
, u'*.f4a'
|
||||
, u'*.f4b'
|
||||
, u'*.f4p'
|
||||
, u'*.f4v'
|
||||
, u'*.mov'
|
||||
, u'*.m4a'
|
||||
, u'*.m4b'
|
||||
, u'*.m4p'
|
||||
, u'*.m4v'
|
||||
, u'*.mkv'
|
||||
, u'*.mp4'
|
||||
, u'*.ogv'
|
||||
, u'*.webm'
|
||||
, u'*.mpg', u'*.wmv', u'*.mpeg', u'*.avi'
|
||||
, u'*.swf'
|
||||
]
|
||||
|
||||
AUDIO_EXT = [
|
||||
u'*.mp3'
|
||||
, u'*.ogg'
|
||||
]
|
||||
u'*.mp3'
|
||||
, u'*.ogg'
|
||||
]
|
||||
|
||||
|
||||
class WebkitPlayer(MediaPlayer):
|
||||
@ -339,7 +339,7 @@ class WebkitPlayer(MediaPlayer):
|
||||
else:
|
||||
display.frame.evaluateJavaScript(u'show_video("play");')
|
||||
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
|
||||
controller.media_info.length = length
|
||||
self.state = MediaState.Playing
|
||||
@ -375,11 +375,11 @@ class WebkitPlayer(MediaPlayer):
|
||||
controller = display.controller
|
||||
if controller.media_info.is_flash:
|
||||
seek = seekVal
|
||||
display.frame.evaluateJavaScript( \
|
||||
display.frame.evaluateJavaScript(
|
||||
u'show_flash("seek", null, null, "%s");' % (seek))
|
||||
else:
|
||||
seek = float(seekVal)/1000
|
||||
display.frame.evaluateJavaScript( \
|
||||
seek = float(seekVal) / 1000
|
||||
display.frame.evaluateJavaScript(
|
||||
u'show_video("seek", null, null, null, "%f");' % (seek))
|
||||
|
||||
def reset(self, display):
|
||||
@ -406,24 +406,24 @@ class WebkitPlayer(MediaPlayer):
|
||||
def update_ui(self, display):
|
||||
controller = display.controller
|
||||
if controller.media_info.is_flash:
|
||||
currentTime = display.frame.evaluateJavaScript( \
|
||||
currentTime = display.frame.evaluateJavaScript(
|
||||
u'show_flash("currentTime");').toInt()[0]
|
||||
length = display.frame.evaluateJavaScript( \
|
||||
length = display.frame.evaluateJavaScript(
|
||||
u'show_flash("length");').toInt()[0]
|
||||
else:
|
||||
if display.frame.evaluateJavaScript( \
|
||||
if display.frame.evaluateJavaScript(
|
||||
u'show_video("isEnded");').toString() == 'true':
|
||||
self.stop(display)
|
||||
(currentTime, ok) = display.frame.evaluateJavaScript( \
|
||||
(currentTime, ok) = display.frame.evaluateJavaScript(
|
||||
u'show_video("currentTime");').toFloat()
|
||||
# check if conversion was ok and value is not 'NaN'
|
||||
if ok and currentTime != float('inf'):
|
||||
currentTime = int(currentTime*1000)
|
||||
(length, ok) = display.frame.evaluateJavaScript( \
|
||||
currentTime = int(currentTime * 1000)
|
||||
(length, ok) = display.frame.evaluateJavaScript(
|
||||
u'show_video("length");').toFloat()
|
||||
# check if conversion was ok and value is not 'NaN'
|
||||
if ok and length != float('inf'):
|
||||
length = int(length*1000)
|
||||
length = int(length * 1000)
|
||||
if currentTime > 0:
|
||||
controller.media_info.length = length
|
||||
controller.seekSlider.setMaximum(length)
|
||||
|
@ -102,9 +102,9 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
self.versionNumberLabel.setText(self.activePlugin.version)
|
||||
self.aboutTextBrowser.setHtml(self.activePlugin.about())
|
||||
self.programaticChange = True
|
||||
status = 1
|
||||
status = PluginStatus.Active
|
||||
if self.activePlugin.status == PluginStatus.Active:
|
||||
status = 0
|
||||
status = PluginStatus.Inactive
|
||||
self.statusComboBox.setCurrentIndex(status)
|
||||
self.statusComboBox.setEnabled(True)
|
||||
self.programaticChange = False
|
||||
@ -129,7 +129,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
def onStatusComboBoxChanged(self, status):
|
||||
if self.programaticChange or status == PluginStatus.Disabled:
|
||||
return
|
||||
if status == 0:
|
||||
if status == PluginStatus.Inactive:
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.activePlugin.toggleStatus(PluginStatus.Active)
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
|
@ -33,6 +33,7 @@ from lxml import html
|
||||
|
||||
from openlp.core.lib import translate, get_text_file_string, Receiver
|
||||
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.utils import AppLocation
|
||||
|
||||
@ -120,7 +121,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
self.zoom = 0
|
||||
self.setupUi(self)
|
||||
# Load the settings for the dialog.
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'advanced')
|
||||
self.slideTextCheckBox.setChecked(settings.value(
|
||||
u'print slide text', QtCore.QVariant(False)).toBool())
|
||||
@ -318,7 +319,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
elif display == ZoomSize.TwentyFive:
|
||||
self.previewWidget.fitToWidth()
|
||||
self.previewWidget.zoomIn(0.25)
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'advanced')
|
||||
settings.setValue(u'display size', QtCore.QVariant(display))
|
||||
settings.endGroup()
|
||||
@ -389,7 +390,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
Save the settings and close the dialog.
|
||||
"""
|
||||
# Save the settings for this dialog.
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'advanced')
|
||||
settings.setValue(u'print slide text',
|
||||
QtCore.QVariant(self.slideTextCheckBox.isChecked()))
|
||||
|
@ -34,6 +34,7 @@ import copy
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import Receiver, translate
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -245,7 +246,7 @@ class ScreenList(object):
|
||||
"""
|
||||
Loads the screen size and the monitor number from the settings.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'general')
|
||||
self.set_current_display(settings.value(u'monitor',
|
||||
QtCore.QVariant(self.display_count - 1)).toInt()[0])
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import create_button_box, create_button
|
||||
|
@ -40,6 +40,7 @@ from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \
|
||||
ItemCapabilities, SettingsManager, translate, str_to_bool
|
||||
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, \
|
||||
create_widget_action, find_and_set_in_combo_box
|
||||
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
|
||||
@ -274,7 +275,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'service_item_update'), self.serviceItemUpdate)
|
||||
# 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',
|
||||
QtCore.QVariant(u'')).toString())
|
||||
self.servicePath = AppLocation.get_section_data_path(u'servicemanager')
|
||||
@ -352,7 +353,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
self._fileName = unicode(fileName)
|
||||
self.mainwindow.setServiceModified(self.isModified(),
|
||||
self.shortFileName())
|
||||
QtCore.QSettings(). \
|
||||
Settings(). \
|
||||
setValue(u'servicemanager/last file',QtCore.QVariant(fileName))
|
||||
|
||||
def fileName(self):
|
||||
@ -371,7 +372,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
"""
|
||||
Triggered when Config dialog is updated.
|
||||
"""
|
||||
self.expandTabs = QtCore.QSettings().value(
|
||||
self.expandTabs = Settings().value(
|
||||
u'advanced/expand service item',
|
||||
QtCore.QVariant(u'False')).toBool()
|
||||
|
||||
@ -444,7 +445,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.setFileName(u'')
|
||||
self.serviceId += 1
|
||||
self.setModified(False)
|
||||
QtCore.QSettings(). \
|
||||
Settings(). \
|
||||
setValue(u'servicemanager/last file',QtCore.QVariant(u''))
|
||||
Receiver.send_message(u'servicemanager_new_service')
|
||||
|
||||
@ -580,10 +581,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
return self.saveFileAs()
|
||||
self.mainwindow.addRecentFile(path_file_name)
|
||||
self.setModified(False)
|
||||
try:
|
||||
delete_file(temp_file_name)
|
||||
except:
|
||||
pass
|
||||
delete_file(temp_file_name)
|
||||
return success
|
||||
|
||||
def saveFileAs(self):
|
||||
@ -591,17 +589,17 @@ class ServiceManager(QtGui.QWidget):
|
||||
Get a file name and then call :func:`ServiceManager.saveFile` to
|
||||
save the file.
|
||||
"""
|
||||
default_service_enabled = QtCore.QSettings().value(
|
||||
default_service_enabled = Settings().value(
|
||||
u'advanced/default service enabled', QtCore.QVariant(True)).toBool()
|
||||
if default_service_enabled:
|
||||
service_day = QtCore.QSettings().value(
|
||||
service_day = Settings().value(
|
||||
u'advanced/default service day', 7).toInt()[0]
|
||||
if service_day == 7:
|
||||
time = datetime.now()
|
||||
else:
|
||||
service_hour = QtCore.QSettings().value(
|
||||
service_hour = Settings().value(
|
||||
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]
|
||||
now = datetime.now()
|
||||
day_delta = service_day - now.weekday()
|
||||
@ -609,7 +607,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
day_delta += 7
|
||||
time = now + timedelta(days=day_delta)
|
||||
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',
|
||||
translate('OpenLP.AdvancedTab', 'Service %Y-%m-%d %H-%M',
|
||||
'This may not contain any of the following characters: '
|
||||
@ -690,7 +688,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.setFileName(fileName)
|
||||
self.mainwindow.addRecentFile(fileName)
|
||||
self.setModified(False)
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
'servicemanager/last file', QtCore.QVariant(fileName))
|
||||
else:
|
||||
critical_error_message_box(
|
||||
@ -732,7 +730,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
service was last closed. Can be blank if there was no service
|
||||
present.
|
||||
"""
|
||||
fileName = QtCore.QSettings(). \
|
||||
fileName = Settings(). \
|
||||
value(u'servicemanager/last file',QtCore.QVariant(u'')).toString()
|
||||
if fileName:
|
||||
self.loadFile(fileName)
|
||||
@ -1104,7 +1102,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
log.debug(u'onThemeComboBoxSelected')
|
||||
self.service_theme = unicode(self.themeComboBox.currentText())
|
||||
self.mainwindow.renderer.set_service_theme(self.service_theme)
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
self.mainwindow.serviceManagerSettingsSection +
|
||||
u'/service theme',
|
||||
QtCore.QVariant(self.service_theme))
|
||||
@ -1285,7 +1283,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
if self.serviceItems[item][u'service_item'].is_valid:
|
||||
self.mainwindow.liveController.addServiceManagerItem(
|
||||
self.serviceItems[item][u'service_item'], child)
|
||||
if QtCore.QSettings().value(
|
||||
if Settings().value(
|
||||
self.mainwindow.generalSettingsSection + u'/auto preview',
|
||||
QtCore.QVariant(False)).toBool():
|
||||
item += 1
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import create_button_box
|
||||
|
@ -29,7 +29,7 @@ The :mod:`settingsform` provides a user interface for the OpenLP settings
|
||||
"""
|
||||
import logging
|
||||
|
||||
from PyQt4 import QtGui
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, build_icon, PluginStatus
|
||||
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
|
||||
|
@ -31,6 +31,7 @@ import re
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.utils import translate
|
||||
from openlp.core.utils.actions import ActionList
|
||||
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,
|
||||
as they are loaded in :class:`~openlp.core.utils.ActionList`.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'shortcuts')
|
||||
for category in self.action_list.categories:
|
||||
# Check if the category is for internal use only.
|
||||
|
@ -35,6 +35,7 @@ from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \
|
||||
translate, build_icon, build_html, PluginManager, ServiceItem
|
||||
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.ui import HideMode, MainDisplay, Display, ScreenList
|
||||
from openlp.core.utils.actions import ActionList, CategoryOrder
|
||||
@ -237,7 +238,7 @@ class SlideController(Controller):
|
||||
text=UiStrings().PlaySlidesToEnd,
|
||||
icon=u':/media/media_time.png', checked=False, shortcuts=[],
|
||||
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():
|
||||
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
|
||||
else:
|
||||
@ -662,7 +663,7 @@ class SlideController(Controller):
|
||||
"""
|
||||
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',
|
||||
QtCore.QVariant(SlideLimits.End)).toInt()[0]
|
||||
|
||||
@ -692,7 +693,7 @@ class SlideController(Controller):
|
||||
self.playSlidesLoop.setChecked(False)
|
||||
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
|
||||
if item.is_text():
|
||||
if QtCore.QSettings().value(
|
||||
if Settings().value(
|
||||
self.parent().songsSettingsSection + u'/display songbar',
|
||||
QtCore.QVariant(True)).toBool() and self.slideList:
|
||||
self.songMenu.show()
|
||||
@ -813,11 +814,11 @@ class SlideController(Controller):
|
||||
QtCore.QObject.connect(action,
|
||||
QtCore.SIGNAL(u'triggered(bool)'),
|
||||
self.onTrackTriggered)
|
||||
self.display.audioPlayer.repeat = QtCore.QSettings().value(
|
||||
self.display.audioPlayer.repeat = Settings().value(
|
||||
self.parent().generalSettingsSection + \
|
||||
u'/audio repeat list',
|
||||
QtCore.QVariant(False)).toBool()
|
||||
if QtCore.QSettings().value(
|
||||
if Settings().value(
|
||||
self.parent().generalSettingsSection + \
|
||||
u'/audio start paused',
|
||||
QtCore.QVariant(True)).toBool():
|
||||
@ -863,7 +864,7 @@ class SlideController(Controller):
|
||||
image = self.imageManager.getImage(frame[u'title'])
|
||||
label.setPixmap(QtGui.QPixmap.fromImage(image))
|
||||
self.previewListWidget.setCellWidget(framenumber, 0, label)
|
||||
slideHeight = width * self.parent().renderer.screen_ratio
|
||||
slideHeight = width * (1 / self.ratio)
|
||||
row += 1
|
||||
self.slideList[unicode(row)] = row - 1
|
||||
text.append(unicode(row))
|
||||
@ -930,7 +931,7 @@ class SlideController(Controller):
|
||||
Allow the main display to blank the main display at startup time
|
||||
"""
|
||||
log.debug(u'mainDisplaySetBackground live = %s' % self.isLive)
|
||||
display_type = QtCore.QSettings().value(
|
||||
display_type = Settings().value(
|
||||
self.parent().generalSettingsSection + u'/screen blank',
|
||||
QtCore.QVariant(u'')).toString()
|
||||
if self.screens.which_screen(self.window()) != \
|
||||
@ -971,11 +972,11 @@ class SlideController(Controller):
|
||||
self.themeScreen.setChecked(False)
|
||||
self.desktopScreen.setChecked(False)
|
||||
if checked:
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
self.parent().generalSettingsSection + u'/screen blank',
|
||||
QtCore.QVariant(u'blanked'))
|
||||
else:
|
||||
QtCore.QSettings().remove(
|
||||
Settings().remove(
|
||||
self.parent().generalSettingsSection + u'/screen blank')
|
||||
self.blankPlugin()
|
||||
self.updatePreview()
|
||||
@ -992,11 +993,11 @@ class SlideController(Controller):
|
||||
self.themeScreen.setChecked(checked)
|
||||
self.desktopScreen.setChecked(False)
|
||||
if checked:
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
self.parent().generalSettingsSection + u'/screen blank',
|
||||
QtCore.QVariant(u'themed'))
|
||||
else:
|
||||
QtCore.QSettings().remove(
|
||||
Settings().remove(
|
||||
self.parent().generalSettingsSection + u'/screen blank')
|
||||
self.blankPlugin()
|
||||
self.updatePreview()
|
||||
@ -1013,11 +1014,11 @@ class SlideController(Controller):
|
||||
self.themeScreen.setChecked(False)
|
||||
self.desktopScreen.setChecked(checked)
|
||||
if checked:
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
self.parent().generalSettingsSection + u'/screen blank',
|
||||
QtCore.QVariant(u'hidden'))
|
||||
else:
|
||||
QtCore.QSettings().remove(
|
||||
Settings().remove(
|
||||
self.parent().generalSettingsSection + u'/screen blank')
|
||||
self.hidePlugin(checked)
|
||||
self.updatePreview()
|
||||
@ -1311,7 +1312,7 @@ class SlideController(Controller):
|
||||
"""
|
||||
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():
|
||||
# Live and Preview have issues if we have video or presentations
|
||||
# playing in both at the same time.
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import create_button_box
|
||||
|
@ -40,6 +40,7 @@ from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, \
|
||||
check_directory_exists, create_thumb, validate_thumb
|
||||
from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \
|
||||
BackgroundGradientType
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
|
||||
create_widget_action
|
||||
from openlp.core.theme import Theme
|
||||
@ -164,7 +165,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
"""
|
||||
Triggered when Config dialog is updated.
|
||||
"""
|
||||
self.global_theme = unicode(QtCore.QSettings().value(
|
||||
self.global_theme = unicode(Settings().value(
|
||||
self.settingsSection + u'/global theme',
|
||||
QtCore.QVariant(u'')).toString())
|
||||
|
||||
@ -244,11 +245,10 @@ class ThemeManager(QtGui.QWidget):
|
||||
name = unicode(translate('OpenLP.ThemeManager',
|
||||
'%s (default)')) % self.global_theme
|
||||
self.themeListWidget.item(count).setText(name)
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
self.settingsSection + u'/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)
|
||||
self._pushThemes()
|
||||
|
||||
def onAddTheme(self):
|
||||
@ -285,6 +285,8 @@ class ThemeManager(QtGui.QWidget):
|
||||
if plugin.usesTheme(old_theme_name):
|
||||
plugin.renameTheme(old_theme_name, new_theme_name)
|
||||
self.loadThemes()
|
||||
self.mainwindow.renderer.update_theme(
|
||||
new_theme_name, old_theme_name)
|
||||
|
||||
def onCopyTheme(self):
|
||||
"""
|
||||
@ -321,9 +323,8 @@ class ThemeManager(QtGui.QWidget):
|
||||
Loads the settings for the theme that is to be edited and launches the
|
||||
theme editing form so the user can make their changes.
|
||||
"""
|
||||
if check_item_selected(self.themeListWidget,
|
||||
translate('OpenLP.ThemeManager',
|
||||
'You must select a theme to edit.')):
|
||||
if check_item_selected(self.themeListWidget, translate(
|
||||
'OpenLP.ThemeManager', 'You must select a theme to edit.')):
|
||||
item = self.themeListWidget.currentItem()
|
||||
theme = self.getThemeData(
|
||||
unicode(item.data(QtCore.Qt.UserRole).toString()))
|
||||
@ -332,6 +333,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
self.themeForm.theme = theme
|
||||
self.themeForm.exec_(True)
|
||||
self.old_background_image = None
|
||||
self.mainwindow.renderer.update_theme(theme.theme_name)
|
||||
|
||||
def onDeleteTheme(self):
|
||||
"""
|
||||
@ -349,6 +351,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
# As we do not reload the themes, push out the change. Reload the
|
||||
# list as the internal lists and events need to be triggered.
|
||||
self._pushThemes()
|
||||
self.mainwindow.renderer.update_theme(theme, only_delete=True)
|
||||
|
||||
def deleteTheme(self, theme):
|
||||
"""
|
||||
@ -449,7 +452,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
theme = ThemeXML()
|
||||
theme.theme_name = UiStrings().Default
|
||||
self._writeTheme(theme, None, None)
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
self.settingsSection + u'/global theme',
|
||||
QtCore.QVariant(theme.theme_name))
|
||||
self.configUpdated()
|
||||
@ -532,6 +535,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
zip = None
|
||||
out_file = None
|
||||
file_xml = None
|
||||
abort_import = True
|
||||
try:
|
||||
zip = zipfile.ZipFile(file_name)
|
||||
xml_file = filter(lambda name:
|
||||
@ -768,7 +772,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
Check to see if theme has been selected and the destructive action
|
||||
is allowed.
|
||||
"""
|
||||
self.global_theme = unicode(QtCore.QSettings().value(
|
||||
self.global_theme = unicode(Settings().value(
|
||||
self.settingsSection + u'/global theme',
|
||||
QtCore.QVariant(u'')).toString())
|
||||
if check_item_selected(self.themeListWidget, select_text):
|
||||
|
@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import SettingsTab, Receiver, translate
|
||||
from openlp.core.lib.theme import ThemeLevel
|
||||
from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
class ThemesTab(SettingsTab):
|
||||
"""
|
||||
@ -132,7 +133,7 @@ class ThemesTab(SettingsTab):
|
||||
'any themes associated with either the service or the songs.'))
|
||||
|
||||
def load(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.theme_level = settings.value(
|
||||
u'theme level', ThemeLevel.Song).toInt()[0]
|
||||
@ -146,13 +147,13 @@ class ThemesTab(SettingsTab):
|
||||
self.SongLevelRadioButton.setChecked(True)
|
||||
|
||||
def save(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'theme level', QtCore.QVariant(self.theme_level))
|
||||
settings.setValue(u'global theme', QtCore.QVariant(self.global_theme))
|
||||
settings.endGroup()
|
||||
self.mainwindow.renderer.set_global_theme(
|
||||
self.global_theme, self.theme_level)
|
||||
self.mainwindow.renderer.set_global_theme(self.global_theme)
|
||||
self.mainwindow.renderer.set_theme_level(self.theme_level)
|
||||
Receiver.send_message(u'theme_update_global', self.global_theme)
|
||||
|
||||
def postSetUp(self):
|
||||
@ -169,8 +170,8 @@ class ThemesTab(SettingsTab):
|
||||
|
||||
def onDefaultComboBoxChanged(self, value):
|
||||
self.global_theme = unicode(self.DefaultComboBox.currentText())
|
||||
self.mainwindow.renderer.set_global_theme(
|
||||
self.global_theme, self.theme_level)
|
||||
self.mainwindow.renderer.set_global_theme(self.global_theme)
|
||||
self.mainwindow.renderer.set_theme_level(self.theme_level)
|
||||
self.__previewGlobalTheme()
|
||||
|
||||
def updateThemeList(self, theme_list):
|
||||
@ -183,14 +184,14 @@ class ThemesTab(SettingsTab):
|
||||
[u'Bible Theme', u'Song Theme']
|
||||
"""
|
||||
# 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',
|
||||
QtCore.QVariant(u'')).toString())
|
||||
self.DefaultComboBox.clear()
|
||||
self.DefaultComboBox.addItems(theme_list)
|
||||
find_and_set_in_combo_box(self.DefaultComboBox, self.global_theme)
|
||||
self.mainwindow.renderer.set_global_theme(
|
||||
self.global_theme, self.theme_level)
|
||||
self.mainwindow.renderer.set_global_theme(self.global_theme)
|
||||
self.mainwindow.renderer.set_theme_level(self.theme_level)
|
||||
if self.global_theme is not u'':
|
||||
self.__previewGlobalTheme()
|
||||
|
||||
|
@ -44,20 +44,9 @@ class WizardStrings(object):
|
||||
# Applications/Formats we import from or export to. These get used in
|
||||
# multiple places but do not need translating unless you find evidence of
|
||||
# the writers translating their own product name.
|
||||
CCLI = u'CCLI/SongSelect'
|
||||
CSV = u'CSV'
|
||||
DB = u'DreamBeam'
|
||||
EW = u'EasyWorship'
|
||||
ES = u'EasySlides'
|
||||
FP = u'Foilpresenter'
|
||||
OL = u'OpenLyrics'
|
||||
OS = u'OpenSong'
|
||||
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.
|
||||
FinishedImport = translate('OpenLP.Ui', 'Finished import.')
|
||||
FormatLabel = translate('OpenLP.Ui', 'Format:')
|
||||
@ -76,10 +65,12 @@ class WizardStrings(object):
|
||||
PercentSymbolFormat = unicode(translate('OpenLP.Ui', '%p%'))
|
||||
Ready = translate('OpenLP.Ui', 'Ready.')
|
||||
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'))
|
||||
YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify a '
|
||||
'%s folder to import from.', 'A file type e.g. OpenSong'))
|
||||
YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify one '
|
||||
'%s folder to import from.', 'A song format e.g. PowerSong'))
|
||||
|
||||
|
||||
class OpenLPWizard(QtGui.QWizard):
|
||||
@ -108,7 +99,7 @@ class OpenLPWizard(QtGui.QWizard):
|
||||
|
||||
def setupUi(self, image):
|
||||
"""
|
||||
Set up the wizard UI
|
||||
Set up the wizard UI.
|
||||
"""
|
||||
self.setModal(True)
|
||||
self.setWizardStyle(QtGui.QWizard.ModernStyle)
|
||||
|
@ -36,6 +36,8 @@ from subprocess import Popen, PIPE
|
||||
import sys
|
||||
import urllib2
|
||||
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
from PyQt4 import QtGui, QtCore
|
||||
|
||||
if sys.platform != u'win32' and sys.platform != u'darwin':
|
||||
@ -87,7 +89,7 @@ class AppLocation(object):
|
||||
VersionDir = 5
|
||||
CacheDir = 6
|
||||
LanguageDir = 7
|
||||
|
||||
|
||||
# Base path where data/config/cache dir is located
|
||||
BaseDir = None
|
||||
|
||||
@ -126,8 +128,13 @@ class AppLocation(object):
|
||||
"""
|
||||
Return the path OpenLP stores all its data under.
|
||||
"""
|
||||
path = AppLocation.get_directory(AppLocation.DataDir)
|
||||
check_directory_exists(path)
|
||||
# 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)
|
||||
check_directory_exists(path)
|
||||
return path
|
||||
|
||||
@staticmethod
|
||||
@ -280,7 +287,7 @@ def check_latest_version(current_version):
|
||||
"""
|
||||
version_string = current_version[u'full']
|
||||
# set to prod in the distribution config file.
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'general')
|
||||
last_test = unicode(settings.value(u'last version test',
|
||||
QtCore.QVariant(datetime.now().date())).toString())
|
||||
|
@ -30,6 +30,8 @@ by the shortcuts system.
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
class ActionCategory(object):
|
||||
"""
|
||||
The :class:`~openlp.core.utils.ActionCategory` class encapsulates a
|
||||
@ -226,7 +228,7 @@ class ActionList(object):
|
||||
else:
|
||||
self.categories[category].actions.add(action, weight)
|
||||
# Load the shortcut from the config.
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'shortcuts')
|
||||
shortcuts = settings.value(action.objectName(),
|
||||
QtCore.QVariant(action.shortcuts())).toStringList()
|
||||
|
@ -35,6 +35,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.utils import AppLocation
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -101,7 +102,7 @@ class LanguageManager(object):
|
||||
"""
|
||||
Retrieve a saved language to use from settings
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
language = unicode(settings.value(
|
||||
u'general/language', QtCore.QVariant(u'[en]')).toString())
|
||||
log.info(u'Language file: \'%s\' Loaded from conf file' % language)
|
||||
@ -133,7 +134,7 @@ class LanguageManager(object):
|
||||
language = unicode(qm_list[action_name])
|
||||
if LanguageManager.auto_language:
|
||||
language = u'[%s]' % language
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
u'general/language', QtCore.QVariant(language))
|
||||
log.info(u'Language file: \'%s\' written to conf file' % language)
|
||||
if message:
|
||||
|
@ -32,6 +32,7 @@ from PyQt4 import QtCore
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.core.lib.db import Manager
|
||||
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.utils.actions import ActionList
|
||||
from openlp.plugins.alerts.lib import AlertsManager, AlertsTab
|
||||
@ -160,7 +161,7 @@ class AlertsPlugin(Plugin):
|
||||
|
||||
def toggleAlertsState(self):
|
||||
self.alertsActive = not self.alertsActive
|
||||
QtCore.QSettings().setValue(self.settingsSection + u'/active',
|
||||
Settings().setValue(self.settingsSection + u'/active',
|
||||
QtCore.QVariant(self.alertsActive))
|
||||
|
||||
def onAlertsTrigger(self):
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import create_button, create_button_box
|
||||
|
@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import SettingsTab, translate, Receiver
|
||||
from openlp.core.ui import AlertLocation
|
||||
from openlp.core.lib.ui import UiStrings, create_valign_selection_widgets
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
class AlertsTab(SettingsTab):
|
||||
"""
|
||||
@ -152,7 +153,7 @@ class AlertsTab(SettingsTab):
|
||||
self.updateDisplay()
|
||||
|
||||
def load(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.timeout = settings.value(u'timeout', QtCore.QVariant(5)).toInt()[0]
|
||||
self.font_color = unicode(settings.value(
|
||||
@ -180,7 +181,7 @@ class AlertsTab(SettingsTab):
|
||||
self.changed = False
|
||||
|
||||
def save(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
# Check value has changed as no event handles this field
|
||||
if settings.value(u'location', QtCore.QVariant(1)).toInt()[0] != \
|
||||
|
@ -31,6 +31,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
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.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem
|
||||
from openlp.plugins.bibles.forms import BibleUpgradeForm
|
||||
@ -62,8 +63,7 @@ class BiblePlugin(Plugin):
|
||||
# unicode(UiStrings().Export))
|
||||
# Set to invisible until we can export bibles
|
||||
self.exportBibleItem.setVisible(False)
|
||||
if self.manager.old_bible_databases:
|
||||
self.toolsUpgradeItem.setVisible(True)
|
||||
self.toolsUpgradeItem.setVisible(bool(self.manager.old_bible_databases))
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
@ -91,7 +91,7 @@ class BiblePlugin(Plugin):
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
|
||||
QtGui.QMessageBox.No)) == QtGui.QMessageBox.Yes:
|
||||
self.onToolsUpgradeItemTriggered()
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
if settings.contains(u'bookname language'):
|
||||
settings.setValue(u'book name language', settings.value(
|
||||
|
@ -36,6 +36,7 @@ from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import Receiver, translate
|
||||
from openlp.core.lib.db import delete_database
|
||||
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.utils import AppLocation
|
||||
from openlp.plugins.bibles.lib.manager import BibleFormat
|
||||
@ -590,7 +591,7 @@ class BibleImportForm(OpenLPWizard):
|
||||
"""
|
||||
Set default values for the wizard pages.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.plugin.settingsSection)
|
||||
self.restart()
|
||||
self.finishButton.setVisible(False)
|
||||
|
@ -36,6 +36,7 @@ from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import Receiver, SettingsManager, translate, \
|
||||
check_directory_exists
|
||||
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.utils import AppLocation, delete_file
|
||||
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, \
|
||||
@ -341,7 +342,7 @@ class BibleUpgradeForm(OpenLPWizard):
|
||||
Set default values for the wizard pages.
|
||||
"""
|
||||
log.debug(u'BibleUpgrade setDefaults')
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.plugin.settingsSection)
|
||||
self.stop_import_flag = False
|
||||
self.success.clear()
|
||||
|
@ -24,7 +24,7 @@
|
||||
# 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.ui import create_button_box
|
||||
|
@ -31,9 +31,8 @@ plugin.
|
||||
import logging
|
||||
import re
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.plugins.bibles.lib.db import BiblesResourcesDB
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -185,7 +184,7 @@ def update_reference_separators():
|
||||
':|v|V|verse|verses;;-|to;;,|and;;end',
|
||||
'Double-semicolon delimited separators for parsing references. '
|
||||
'Consult the developers for further information.')).split(u';;')
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'bibles')
|
||||
custom_separators = [
|
||||
unicode(settings.value(u'verse separator').toString()),
|
||||
|
@ -31,6 +31,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
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.settings import Settings
|
||||
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \
|
||||
update_reference_separators, get_reference_separator, LanguageSelection
|
||||
|
||||
@ -414,7 +415,7 @@ class BiblesTab(SettingsTab):
|
||||
self.getGreyTextPalette(True))
|
||||
|
||||
def load(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.show_new_chapters = settings.value(
|
||||
u'display new chapter', QtCore.QVariant(False)).toBool()
|
||||
@ -488,7 +489,7 @@ class BiblesTab(SettingsTab):
|
||||
settings.endGroup()
|
||||
|
||||
def save(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'display new chapter',
|
||||
QtCore.QVariant(self.show_new_chapters))
|
||||
|
@ -73,7 +73,7 @@ class CSVBible(BibleDB):
|
||||
|
||||
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
|
||||
a clean bible is being loaded.
|
||||
"""
|
||||
|
@ -63,6 +63,7 @@ class Verse(BaseModel):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def init_schema(url):
|
||||
"""
|
||||
Setup a bible database connection and initialise the database schema.
|
||||
|
@ -43,6 +43,15 @@ from openlp.plugins.bibles.lib import SearchResults
|
||||
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, \
|
||||
Book
|
||||
|
||||
UGLY_CHARS = {
|
||||
u'\u2014': u' - ',
|
||||
u'\u2018': u'\'',
|
||||
u'\u2019': u'\'',
|
||||
u'\u201c': u'"',
|
||||
u'\u201d': u'"',
|
||||
u' ': u' '
|
||||
}
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class BGExtract(object):
|
||||
@ -54,6 +63,103 @@ class BGExtract(object):
|
||||
self.proxy_url = proxy_url
|
||||
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):
|
||||
"""
|
||||
Access and decode Bibles via the BibleGateway website.
|
||||
@ -80,60 +186,9 @@ class BGExtract(object):
|
||||
if not soup:
|
||||
return None
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
footnotes = soup.findAll(u'sup', u'footnote')
|
||||
if footnotes:
|
||||
for footnote in footnotes:
|
||||
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)
|
||||
div = soup.find('div', 'result-text-style-normal')
|
||||
self._clean_soup(div)
|
||||
verse_list = self._extract_verses(div.findAll('span', 'text'))
|
||||
if not verse_list:
|
||||
log.debug(u'No content found in the BibleGateway response.')
|
||||
send_error_message(u'parse')
|
||||
|
@ -32,6 +32,7 @@ from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import Receiver, SettingsManager, translate
|
||||
from openlp.core.utils import AppLocation, delete_file
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.plugins.bibles.lib import parse_reference, \
|
||||
get_reference_separator, LanguageSelection
|
||||
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
|
||||
@ -126,7 +127,7 @@ class BibleManager(object):
|
||||
self.db_cache = None
|
||||
self.path = AppLocation.get_section_data_path(self.settingsSection)
|
||||
self.proxy_name = unicode(
|
||||
QtCore.QSettings().value(self.settingsSection + u'/proxy name',
|
||||
Settings().value(self.settingsSection + u'/proxy name',
|
||||
QtCore.QVariant(u'')).toString())
|
||||
self.suffix = u'.sqlite'
|
||||
self.import_wizard = None
|
||||
@ -378,7 +379,7 @@ class BibleManager(object):
|
||||
except (ValueError, TypeError):
|
||||
language_selection = LanguageSelection.Application
|
||||
if language_selection is None or language_selection == -1:
|
||||
language_selection = QtCore.QSettings().value(
|
||||
language_selection = Settings().value(
|
||||
self.settingsSection + u'/bookname language',
|
||||
QtCore.QVariant(0)).toInt()[0]
|
||||
return language_selection
|
||||
|
@ -33,6 +33,7 @@ from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
|
||||
translate, create_separated_list
|
||||
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, \
|
||||
create_horizontal_adjusting_combo_box, critical_error_message_box, \
|
||||
find_and_set_in_combo_box, build_icon
|
||||
@ -294,7 +295,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
|
||||
def configUpdated(self):
|
||||
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():
|
||||
self.advancedSecondLabel.setVisible(True)
|
||||
self.advancedSecondComboBox.setVisible(True)
|
||||
@ -362,7 +363,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
translate('BiblesPlugin.MediaItem', 'Text Search'),
|
||||
translate('BiblesPlugin.MediaItem', 'Search Text...'))
|
||||
])
|
||||
self.quickSearchEdit.setCurrentSearchType(QtCore.QSettings().value(
|
||||
self.quickSearchEdit.setCurrentSearchType(Settings().value(
|
||||
u'%s/last search type' % self.settingsSection,
|
||||
QtCore.QVariant(BibleSearch.Reference)).toInt()[0])
|
||||
self.configUpdated()
|
||||
@ -386,7 +387,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.advancedVersionComboBox.addItems(bibles)
|
||||
self.advancedSecondComboBox.addItems(bibles)
|
||||
# set the default value
|
||||
bible = QtCore.QSettings().value(
|
||||
bible = Settings().value(
|
||||
self.settingsSection + u'/advanced bible',
|
||||
QtCore.QVariant(u'')).toString()
|
||||
if bible in bibles:
|
||||
@ -394,7 +395,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.initialiseAdvancedBible(unicode(bible))
|
||||
elif bibles:
|
||||
self.initialiseAdvancedBible(bibles[0])
|
||||
bible = QtCore.QSettings().value(
|
||||
bible = Settings().value(
|
||||
self.settingsSection + u'/quick bible', QtCore.QVariant(
|
||||
self.quickVersionComboBox.currentText())).toString()
|
||||
find_and_set_in_combo_box(self.quickVersionComboBox, bible)
|
||||
@ -417,7 +418,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
|
||||
``bible``
|
||||
The bible to initialise (unicode).
|
||||
|
||||
|
||||
``last_book_id``
|
||||
The "book reference id" of the book which is choosen at the moment.
|
||||
(int)
|
||||
@ -497,11 +498,11 @@ class BibleMediaItem(MediaManagerItem):
|
||||
"""
|
||||
log.debug(u'updateAutoCompleter')
|
||||
# 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,
|
||||
QtCore.QVariant(self.quickSearchEdit.currentSearchType()))
|
||||
# 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()))
|
||||
books = []
|
||||
# We have to do a 'Reference Search'.
|
||||
@ -596,7 +597,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.advancedStyleComboBox.setCurrentIndex(self.settings.layout_style)
|
||||
self.settings.layoutStyleComboBox.setCurrentIndex(
|
||||
self.settings.layout_style)
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
self.settingsSection + u'/verse layout style',
|
||||
QtCore.QVariant(self.settings.layout_style))
|
||||
|
||||
@ -605,12 +606,12 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.quickStyleComboBox.setCurrentIndex(self.settings.layout_style)
|
||||
self.settings.layoutStyleComboBox.setCurrentIndex(
|
||||
self.settings.layout_style)
|
||||
QtCore.QSettings().setValue(
|
||||
Settings().setValue(
|
||||
self.settingsSection + u'/verse layout style',
|
||||
QtCore.QVariant(self.settings.layout_style))
|
||||
|
||||
def onAdvancedVersionComboBox(self):
|
||||
QtCore.QSettings().setValue(self.settingsSection + u'/advanced bible',
|
||||
Settings().setValue(self.settingsSection + u'/advanced bible',
|
||||
QtCore.QVariant(self.advancedVersionComboBox.currentText()))
|
||||
self.initialiseAdvancedBible(
|
||||
unicode(self.advancedVersionComboBox.currentText()),
|
||||
@ -975,7 +976,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
else:
|
||||
service_item.theme = self.settings.bible_theme
|
||||
for slide in raw_slides:
|
||||
service_item.add_from_text(slide[:30], slide)
|
||||
service_item.add_from_text(slide)
|
||||
return True
|
||||
|
||||
def formatTitle(self, start_bitem, old_bitem):
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import UiStrings, create_button_box, create_button
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import UiStrings, create_button, create_button_box
|
||||
|
@ -28,6 +28,7 @@
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, translate
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
class CustomTab(SettingsTab):
|
||||
"""
|
||||
@ -66,11 +67,11 @@ class CustomTab(SettingsTab):
|
||||
self.displayFooter = True
|
||||
|
||||
def load(self):
|
||||
self.displayFooter = QtCore.QSettings().value(
|
||||
self.displayFooter = Settings().value(
|
||||
self.settingsSection + u'/display footer',
|
||||
QtCore.QVariant(True)).toBool()
|
||||
self.displayFooterCheckBox.setChecked(self.displayFooter)
|
||||
|
||||
def save(self):
|
||||
QtCore.QSettings().setValue(self.settingsSection + u'/display footer',
|
||||
Settings().setValue(self.settingsSection + u'/display footer',
|
||||
QtCore.QVariant(self.displayFooter))
|
||||
|
@ -34,6 +34,7 @@ from sqlalchemy.sql import or_, func
|
||||
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
|
||||
check_item_selected, translate
|
||||
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.lib import CustomXMLParser
|
||||
from openlp.plugins.custom.lib.db import CustomSlide
|
||||
@ -99,7 +100,7 @@ class CustomMediaItem(MediaManagerItem):
|
||||
])
|
||||
self.loadList(self.manager.get_all_objects(
|
||||
CustomSlide, order_by_ref=CustomSlide.title))
|
||||
self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value(
|
||||
self.searchTextEdit.setCurrentSearchType(Settings().value(
|
||||
u'%s/last search type' % self.settingsSection,
|
||||
QtCore.QVariant(CustomSearch.Titles)).toInt()[0])
|
||||
|
||||
@ -197,9 +198,6 @@ class CustomMediaItem(MediaManagerItem):
|
||||
|
||||
def generateSlideData(self, service_item, item=None, xmlVersion=False,
|
||||
remote=False):
|
||||
raw_footer = []
|
||||
slide = None
|
||||
theme = None
|
||||
item_id = self._getIdOfItemToGenerate(item, self.remoteCustom)
|
||||
service_item.add_capability(ItemCapabilities.CanEdit)
|
||||
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||
@ -212,23 +210,22 @@ class CustomMediaItem(MediaManagerItem):
|
||||
theme = customSlide.theme_name
|
||||
if theme:
|
||||
service_item.theme = theme
|
||||
customXML = CustomXMLParser(customSlide.text)
|
||||
verseList = customXML.get_verses()
|
||||
raw_slides = [verse[1] for verse in verseList]
|
||||
custom_xml = CustomXMLParser(customSlide.text)
|
||||
verse_list = custom_xml.get_verses()
|
||||
raw_slides = [verse[1] for verse in verse_list]
|
||||
service_item.title = title
|
||||
for slide in raw_slides:
|
||||
service_item.add_from_text(slide[:30], slide)
|
||||
if QtCore.QSettings().value(self.settingsSection + u'/display footer',
|
||||
service_item.add_from_text(slide)
|
||||
if Settings().value(self.settingsSection + u'/display footer',
|
||||
QtCore.QVariant(True)).toBool() or credit:
|
||||
raw_footer.append(title + u' ' + credit)
|
||||
service_item.raw_footer.append(u' '.join([title, credit]))
|
||||
else:
|
||||
raw_footer.append(u'')
|
||||
service_item.raw_footer = raw_footer
|
||||
service_item.raw_footer.append(u'')
|
||||
return True
|
||||
|
||||
def onSearchTextButtonClicked(self):
|
||||
# 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,
|
||||
QtCore.QVariant(self.searchTextEdit.currentSearchType()))
|
||||
# Reload the list considering the new search type.
|
||||
|
@ -31,6 +31,7 @@ import logging
|
||||
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate, \
|
||||
Receiver
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.plugins.images.lib import ImageMediaItem, ImageTab
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -94,6 +95,6 @@ class ImagePlugin(Plugin):
|
||||
image manager to require updates. Actual update is triggered by the
|
||||
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')))
|
||||
self.liveController.imageManager.updateImages(u'image', background)
|
||||
|
@ -28,6 +28,7 @@
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, translate, Receiver
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
class ImageTab(SettingsTab):
|
||||
"""
|
||||
@ -82,7 +83,7 @@ class ImageTab(SettingsTab):
|
||||
u'background-color: %s' % self.bg_color)
|
||||
|
||||
def load(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.bg_color = unicode(settings.value(
|
||||
u'background color', QtCore.QVariant(u'#000000')).toString())
|
||||
@ -92,7 +93,7 @@ class ImageTab(SettingsTab):
|
||||
u'background-color: %s' % self.bg_color)
|
||||
|
||||
def save(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'background color', QtCore.QVariant(self.bg_color))
|
||||
settings.endGroup()
|
||||
|
@ -35,6 +35,7 @@ from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
|
||||
SettingsManager, translate, check_item_selected, check_directory_exists, \
|
||||
Receiver, create_thumb, validate_thumb
|
||||
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
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -151,7 +152,7 @@ class ImageMediaItem(MediaManagerItem):
|
||||
|
||||
def generateSlideData(self, service_item, item=None, xmlVersion=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')))
|
||||
if item:
|
||||
items = [item]
|
||||
@ -220,7 +221,7 @@ class ImageMediaItem(MediaManagerItem):
|
||||
if check_item_selected(self.listView,
|
||||
translate('ImagePlugin.MediaItem',
|
||||
'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',
|
||||
QtCore.QVariant(u'#000000')))
|
||||
item = self.listView.selectedIndexes()[0]
|
||||
|
@ -29,6 +29,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, translate, Receiver
|
||||
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
|
||||
class MediaQCheckBox(QtGui.QCheckBox):
|
||||
"""
|
||||
@ -186,7 +187,7 @@ class MediaTab(SettingsTab):
|
||||
else:
|
||||
checkbox.setChecked(False)
|
||||
self.updatePlayerList()
|
||||
self.overridePlayerCheckBox.setChecked(QtCore.QSettings().value(
|
||||
self.overridePlayerCheckBox.setChecked(Settings().value(
|
||||
self.settingsSection + u'/override player',
|
||||
QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0])
|
||||
|
||||
@ -200,9 +201,9 @@ class MediaTab(SettingsTab):
|
||||
player_string_changed = True
|
||||
override_changed = True
|
||||
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():
|
||||
QtCore.QSettings().setValue(setting_key,
|
||||
Settings().setValue(setting_key,
|
||||
QtCore.QVariant(self.overridePlayerCheckBox.checkState()))
|
||||
override_changed = True
|
||||
if override_changed:
|
||||
|
@ -30,6 +30,7 @@ import logging
|
||||
from PyQt4 import QtCore
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
it to "enable Phonon" and "make it the first one in the list".
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
if settings.contains(u'use phonon'):
|
||||
log.info(u'Found old Phonon setting')
|
||||
|
@ -36,6 +36,7 @@ from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \
|
||||
validate_thumb
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
|
||||
create_horizontal_adjusting_combo_box
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.plugins.presentations.lib import MessageListener
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -149,7 +150,7 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
if self.displayTypeComboBox.count() > 1:
|
||||
self.displayTypeComboBox.insertItem(0, self.Automatic)
|
||||
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:
|
||||
self.presentationWidget.show()
|
||||
else:
|
||||
|
@ -33,6 +33,7 @@ from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import Receiver, check_directory_exists, create_thumb, \
|
||||
validate_thumb
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.utils import AppLocation
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -392,7 +393,7 @@ class PresentationController(object):
|
||||
"""
|
||||
Return whether the controller is currently enabled
|
||||
"""
|
||||
if QtCore.QSettings().value(
|
||||
if Settings().value(
|
||||
self.settings_section + u'/' + self.name,
|
||||
QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0] == \
|
||||
QtCore.Qt.Checked:
|
||||
|
@ -29,6 +29,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, SettingsTab, translate
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
class PresentationTab(SettingsTab):
|
||||
"""
|
||||
@ -102,10 +103,10 @@ class PresentationTab(SettingsTab):
|
||||
for key in self.controllers:
|
||||
controller = self.controllers[key]
|
||||
checkbox = self.PresenterCheckboxes[controller.name]
|
||||
checkbox.setChecked(QtCore.QSettings().value(
|
||||
checkbox.setChecked(Settings().value(
|
||||
self.settingsSection + u'/' + controller.name,
|
||||
QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0])
|
||||
self.OverrideAppCheckBox.setChecked(QtCore.QSettings().value(
|
||||
self.OverrideAppCheckBox.setChecked(Settings().value(
|
||||
self.settingsSection + u'/override app',
|
||||
QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0])
|
||||
|
||||
@ -123,19 +124,19 @@ class PresentationTab(SettingsTab):
|
||||
if controller.is_available():
|
||||
checkbox = self.PresenterCheckboxes[controller.name]
|
||||
setting_key = self.settingsSection + u'/' + controller.name
|
||||
if QtCore.QSettings().value(setting_key) != \
|
||||
if Settings().value(setting_key) != \
|
||||
checkbox.checkState():
|
||||
changed = True
|
||||
QtCore.QSettings().setValue(setting_key,
|
||||
Settings().setValue(setting_key,
|
||||
QtCore.QVariant(checkbox.checkState()))
|
||||
if checkbox.isChecked():
|
||||
controller.start_process()
|
||||
else:
|
||||
controller.kill()
|
||||
setting_key = self.settingsSection + u'/override app'
|
||||
if QtCore.QSettings().value(setting_key) != \
|
||||
if Settings().value(setting_key) != \
|
||||
self.OverrideAppCheckBox.checkState():
|
||||
QtCore.QSettings().setValue(setting_key,
|
||||
Settings().setValue(setting_key,
|
||||
QtCore.QVariant(self.OverrideAppCheckBox.checkState()))
|
||||
changed = True
|
||||
if changed:
|
||||
|
@ -245,6 +245,9 @@ window.OpenLP = {
|
||||
}
|
||||
else {
|
||||
$.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")
|
||||
.attr("data-rel", "dialog").attr("value", value[0])
|
||||
.click(OpenLP.showOptions).text(value[1])));
|
||||
|
@ -122,6 +122,7 @@ from PyQt4 import QtCore, QtNetwork
|
||||
from mako.template import Template
|
||||
|
||||
from openlp.core.lib import Receiver, PluginStatus, StringContent
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.utils import AppLocation, translate
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -169,10 +170,10 @@ class HttpServer(object):
|
||||
clients. Listen out for socket connections.
|
||||
"""
|
||||
log.debug(u'Start TCP server')
|
||||
port = QtCore.QSettings().value(
|
||||
port = Settings().value(
|
||||
self.plugin.settingsSection + u'/port',
|
||||
QtCore.QVariant(4316)).toInt()[0]
|
||||
address = QtCore.QSettings().value(
|
||||
address = Settings().value(
|
||||
self.plugin.settingsSection + u'/ip address',
|
||||
QtCore.QVariant(u'0.0.0.0')).toString()
|
||||
self.server = QtNetwork.QTcpServer()
|
||||
@ -404,7 +405,7 @@ class HttpConnection(object):
|
||||
u'slide': self.parent.current_slide or 0,
|
||||
u'item': self.parent.current_item._uuid \
|
||||
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'blank': self.parent.plugin.liveController.blankScreen.\
|
||||
isChecked(),
|
||||
|
@ -28,6 +28,7 @@
|
||||
from PyQt4 import QtCore, QtGui, QtNetwork
|
||||
|
||||
from openlp.core.lib import SettingsTab, translate, Receiver
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
ZERO_URL = u'0.0.0.0'
|
||||
|
||||
@ -149,12 +150,12 @@ class RemoteTab(SettingsTab):
|
||||
|
||||
def load(self):
|
||||
self.portSpinBox.setValue(
|
||||
QtCore.QSettings().value(self.settingsSection + u'/port',
|
||||
Settings().value(self.settingsSection + u'/port',
|
||||
QtCore.QVariant(4316)).toInt()[0])
|
||||
self.addressEdit.setText(
|
||||
QtCore.QSettings().value(self.settingsSection + u'/ip address',
|
||||
Settings().value(self.settingsSection + u'/ip address',
|
||||
QtCore.QVariant(ZERO_URL)).toString())
|
||||
self.twelveHour = QtCore.QSettings().value(
|
||||
self.twelveHour = Settings().value(
|
||||
self.settingsSection + u'/twelve hour',
|
||||
QtCore.QVariant(True)).toBool()
|
||||
self.twelveHourCheckBox.setChecked(self.twelveHour)
|
||||
@ -162,16 +163,16 @@ class RemoteTab(SettingsTab):
|
||||
|
||||
def save(self):
|
||||
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.QSettings().value(self.settingsSection + u'/port',
|
||||
Settings().value(self.settingsSection + u'/port',
|
||||
QtCore.QVariant(4316).toInt()[0]) != self.portSpinBox.value()):
|
||||
changed = True
|
||||
QtCore.QSettings().setValue(self.settingsSection + u'/port',
|
||||
Settings().setValue(self.settingsSection + u'/port',
|
||||
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.QSettings().setValue(self.settingsSection + u'/twelve hour',
|
||||
Settings().setValue(self.settingsSection + u'/twelve hour',
|
||||
QtCore.QVariant(self.twelveHour))
|
||||
if changed:
|
||||
Receiver.send_message(u'remotes_config_updated')
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import create_button_box
|
||||
|
@ -57,19 +57,17 @@ class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
|
||||
self.firstNameEdit.setFocus()
|
||||
return QtGui.QDialog.exec_(self)
|
||||
|
||||
def onFirstNameEditTextEdited(self, text):
|
||||
def onFirstNameEditTextEdited(self, display_name):
|
||||
if not self._autoDisplayName:
|
||||
return
|
||||
display_name = text
|
||||
if self.lastNameEdit.text() != u'':
|
||||
if not self.lastNameEdit.text():
|
||||
display_name = display_name + u' ' + self.lastNameEdit.text()
|
||||
self.displayEdit.setText(display_name)
|
||||
|
||||
def onLastNameEditTextEdited(self, text):
|
||||
def onLastNameEditTextEdited(self, display_name):
|
||||
if not self._autoDisplayName:
|
||||
return
|
||||
display_name = text
|
||||
if self.firstNameEdit.text() != u'':
|
||||
if not self.firstNameEdit.text():
|
||||
display_name = self.firstNameEdit.text() + u' ' + display_name
|
||||
self.displayEdit.setText(display_name)
|
||||
|
||||
|
@ -97,7 +97,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
self.onVerseOrderTextChanged)
|
||||
QtCore.QObject.connect(self.themeAddButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.mediaitem.plugin.renderer.themeManager.onAddTheme)
|
||||
self.mediaitem.plugin.renderer.theme_manager.onAddTheme)
|
||||
QtCore.QObject.connect(self.maintenanceButton,
|
||||
QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked)
|
||||
QtCore.QObject.connect(self.audioAddFromFileButton,
|
||||
@ -172,17 +172,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
def loadThemes(self, theme_list):
|
||||
self.themeComboBox.clear()
|
||||
self.themeComboBox.addItem(u'')
|
||||
self.themes = []
|
||||
for theme in theme_list:
|
||||
self.themeComboBox.addItem(theme)
|
||||
self.themes.append(theme)
|
||||
self.themes = theme_list
|
||||
self.themeComboBox.addItems(theme_list)
|
||||
set_case_insensitive_completer(self.themes, self.themeComboBox)
|
||||
|
||||
def loadMediaFiles(self):
|
||||
self.audioAddFromMediaButton.setVisible(False)
|
||||
for plugin in self.parent().pluginManager.plugins:
|
||||
if plugin.name == u'media' and \
|
||||
plugin.status == PluginStatus.Active:
|
||||
if plugin.name == u'media' and plugin.status == PluginStatus.Active:
|
||||
self.audioAddFromMediaButton.setVisible(True)
|
||||
self.mediaForm.populateFiles(
|
||||
plugin.mediaItem.getList(MediaType.Audio))
|
||||
@ -259,8 +256,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
verse_tags_translated = False
|
||||
if self.song.lyrics.startswith(u'<?xml version='):
|
||||
songXML = SongXML()
|
||||
verseList = songXML.get_verses(self.song.lyrics)
|
||||
for count, verse in enumerate(verseList):
|
||||
verse_list = songXML.get_verses(self.song.lyrics)
|
||||
for count, verse in enumerate(verse_list):
|
||||
self.verseListWidget.setRowCount(
|
||||
self.verseListWidget.rowCount() + 1)
|
||||
# This silently migrates from localized verse type markup.
|
||||
@ -482,27 +479,26 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
def onVerseEditButtonClicked(self):
|
||||
item = self.verseListWidget.currentItem()
|
||||
if item:
|
||||
tempText = item.text()
|
||||
verseId = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||
self.verseForm.setVerse(tempText, True, verseId)
|
||||
temp_text = item.text()
|
||||
verse_id = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||
self.verseForm.setVerse(temp_text, True, verse_id)
|
||||
if self.verseForm.exec_():
|
||||
after_text, verse_tag, verse_num = self.verseForm.getVerse()
|
||||
verse_def = u'%s%s' % (verse_tag, verse_num)
|
||||
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def))
|
||||
item.setText(after_text)
|
||||
# number of lines has changed, repaint the list moving the data
|
||||
if len(tempText.split(u'\n')) != len(after_text.split(u'\n')):
|
||||
tempList = {}
|
||||
tempId = {}
|
||||
if len(temp_text.split(u'\n')) != len(after_text.split(u'\n')):
|
||||
temp_list = []
|
||||
temp_ids = []
|
||||
for row in range(self.verseListWidget.rowCount()):
|
||||
tempList[row] = self.verseListWidget.item(row, 0)\
|
||||
.text()
|
||||
tempId[row] = self.verseListWidget.item(row, 0)\
|
||||
.data(QtCore.Qt.UserRole)
|
||||
item = self.verseListWidget.item(row, 0)
|
||||
temp_list.append(item.text())
|
||||
temp_ids.append(item.data(QtCore.Qt.UserRole))
|
||||
self.verseListWidget.clear()
|
||||
for row in range (0, len(tempList)):
|
||||
item = QtGui.QTableWidgetItem(tempList[row], 0)
|
||||
item.setData(QtCore.Qt.UserRole, tempId[row])
|
||||
for row, entry in enumerate(temp_list):
|
||||
item = QtGui.QTableWidgetItem(entry, 0)
|
||||
item.setData(QtCore.Qt.UserRole, temp_ids[row])
|
||||
self.verseListWidget.setItem(row, 0, item)
|
||||
self.tagRows()
|
||||
# Check if all verse tags are used.
|
||||
@ -707,7 +703,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
text = unicode(self.songBookComboBox.currentText())
|
||||
if item == 0 and text:
|
||||
temp_song_book = text
|
||||
self.mediaitem.songMaintenanceForm.exec_()
|
||||
self.mediaitem.songMaintenanceForm.exec_(True)
|
||||
self.loadAuthors()
|
||||
self.loadBooks()
|
||||
self.loadTopics()
|
||||
@ -865,12 +861,16 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
for row in xrange(self.authorsListView.count()):
|
||||
item = self.authorsListView.item(row)
|
||||
authorId = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||
self.song.authors.append(self.manager.get_object(Author, authorId))
|
||||
author = self.manager.get_object(Author, authorId)
|
||||
if author is not None:
|
||||
self.song.authors.append(author)
|
||||
self.song.topics = []
|
||||
for row in xrange(self.topicsListView.count()):
|
||||
item = self.topicsListView.item(row)
|
||||
topicId = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||
self.song.topics.append(self.manager.get_object(Topic, topicId))
|
||||
topic = self.manager.get_object(Topic, topicId)
|
||||
if topic is not None:
|
||||
self.song.topics.append(topic)
|
||||
# Save the song here because we need a valid id for the audio files.
|
||||
clean_song(self.manager, self.song)
|
||||
self.manager.save_object(self.song)
|
||||
@ -922,9 +922,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
multiple = []
|
||||
for i in range(self.verseListWidget.rowCount()):
|
||||
item = self.verseListWidget.item(i, 0)
|
||||
verseId = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||
verse_tag = verseId[0]
|
||||
verse_num = verseId[1:]
|
||||
verse_id = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||
verse_tag = verse_id[0]
|
||||
verse_num = verse_id[1:]
|
||||
sxml.add_verse_to_lyrics(verse_tag, verse_num,
|
||||
unicode(item.text()))
|
||||
if verse_num > u'1' and verse_tag not in multiple:
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import create_button_box
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -87,7 +87,15 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
QtCore.SIGNAL(u'currentRowChanged(int)'),
|
||||
self.onBooksListRowChanged)
|
||||
|
||||
def exec_(self):
|
||||
def exec_(self, fromSongEdit=False):
|
||||
"""
|
||||
Show the dialog.
|
||||
|
||||
``fromSongEdit``
|
||||
Indicates if the maintenance dialog has been opened from song edit
|
||||
or from the media manager. Defaults to **False**.
|
||||
"""
|
||||
self.fromSongEdit = fromSongEdit
|
||||
self.typeListWidget.setCurrentRow(0)
|
||||
self.resetAuthors()
|
||||
self.resetTopics()
|
||||
@ -103,20 +111,20 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
else:
|
||||
return -1
|
||||
|
||||
def _deleteItem(self, item_class, list_widget, reset_func, dlg_title,
|
||||
def _deleteItem(self, itemClass, listWidget, resetFunc, dlgTitle,
|
||||
del_text, err_text):
|
||||
item_id = self._getCurrentItemId(list_widget)
|
||||
item_id = self._getCurrentItemId(listWidget)
|
||||
if item_id != -1:
|
||||
item = self.manager.get_object(item_class, item_id)
|
||||
item = self.manager.get_object(itemClass, item_id)
|
||||
if item and not item.songs:
|
||||
if critical_error_message_box(dlg_title, del_text, self,
|
||||
if critical_error_message_box(dlgTitle, del_text, self,
|
||||
True) == QtGui.QMessageBox.Yes:
|
||||
self.manager.delete_object(item_class, item.id)
|
||||
reset_func()
|
||||
self.manager.delete_object(itemClass, item.id)
|
||||
resetFunc()
|
||||
else:
|
||||
critical_error_message_box(dlg_title, err_text)
|
||||
critical_error_message_box(dlgTitle, err_text)
|
||||
else:
|
||||
critical_error_message_box(dlg_title, UiStrings().NISs)
|
||||
critical_error_message_box(dlgTitle, UiStrings().NISs)
|
||||
|
||||
def resetAuthors(self):
|
||||
"""
|
||||
@ -157,34 +165,34 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id))
|
||||
self.booksListWidget.addItem(book_name)
|
||||
|
||||
def checkAuthor(self, new_author, edit=False):
|
||||
def checkAuthor(self, newAuthor, edit=False):
|
||||
"""
|
||||
Returns *False* if the given Author already exists, otherwise *True*.
|
||||
"""
|
||||
authors = self.manager.get_all_objects(Author,
|
||||
and_(Author.first_name == new_author.first_name,
|
||||
Author.last_name == new_author.last_name,
|
||||
Author.display_name == new_author.display_name))
|
||||
return self.__checkObject(authors, new_author, edit)
|
||||
and_(Author.first_name == newAuthor.first_name,
|
||||
Author.last_name == newAuthor.last_name,
|
||||
Author.display_name == newAuthor.display_name))
|
||||
return self.__checkObject(authors, newAuthor, edit)
|
||||
|
||||
def checkTopic(self, new_topic, edit=False):
|
||||
def checkTopic(self, newTopic, edit=False):
|
||||
"""
|
||||
Returns *False* if the given Topic already exists, otherwise *True*.
|
||||
"""
|
||||
topics = self.manager.get_all_objects(Topic,
|
||||
Topic.name == new_topic.name)
|
||||
return self.__checkObject(topics, new_topic, edit)
|
||||
Topic.name == newTopic.name)
|
||||
return self.__checkObject(topics, newTopic, edit)
|
||||
|
||||
def checkBook(self, new_book, edit=False):
|
||||
def checkBook(self, newBook, edit=False):
|
||||
"""
|
||||
Returns *False* if the given Topic already exists, otherwise *True*.
|
||||
"""
|
||||
books = self.manager.get_all_objects(Book,
|
||||
and_(Book.name == new_book.name,
|
||||
Book.publisher == new_book.publisher))
|
||||
return self.__checkObject(books, new_book, edit)
|
||||
and_(Book.name == newBook.name,
|
||||
Book.publisher == newBook.publisher))
|
||||
return self.__checkObject(books, newBook, edit)
|
||||
|
||||
def __checkObject(self, objects, new_object, edit):
|
||||
def __checkObject(self, objects, newObject, edit):
|
||||
"""
|
||||
Utility method to check for an existing object.
|
||||
|
||||
@ -196,7 +204,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
# not return False when nothing has changed.
|
||||
if edit:
|
||||
for object in objects:
|
||||
if object.id != new_object.id:
|
||||
if object.id != newObject.id:
|
||||
return False
|
||||
return True
|
||||
else:
|
||||
@ -275,7 +283,8 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
if self.checkAuthor(author, True):
|
||||
if self.manager.save_object(author):
|
||||
self.resetAuthors()
|
||||
Receiver.send_message(u'songs_load_list')
|
||||
if not self.fromSongEdit:
|
||||
Receiver.send_message(u'songs_load_list')
|
||||
else:
|
||||
critical_error_message_box(
|
||||
message=translate('SongsPlugin.SongMaintenanceForm',
|
||||
@ -373,75 +382,76 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
merge(dbObject)
|
||||
reset()
|
||||
Receiver.send_message(u'songs_load_list')
|
||||
if not self.fromSongEdit:
|
||||
Receiver.send_message(u'songs_load_list')
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
|
||||
def mergeAuthors(self, old_author):
|
||||
def mergeAuthors(self, oldAuthor):
|
||||
"""
|
||||
Merges two authors into one author.
|
||||
|
||||
``old_author``
|
||||
``oldAuthor``
|
||||
The object, which was edited, that will be deleted
|
||||
"""
|
||||
# Find the duplicate.
|
||||
existing_author = self.manager.get_object_filtered(Author,
|
||||
and_(Author.first_name == old_author.first_name,
|
||||
Author.last_name == old_author.last_name,
|
||||
Author.display_name == old_author.display_name,
|
||||
Author.id != old_author.id))
|
||||
# Find the songs, which have the old_author as author.
|
||||
and_(Author.first_name == oldAuthor.first_name,
|
||||
Author.last_name == oldAuthor.last_name,
|
||||
Author.display_name == oldAuthor.display_name,
|
||||
Author.id != oldAuthor.id))
|
||||
# Find the songs, which have the oldAuthor as author.
|
||||
songs = self.manager.get_all_objects(Song,
|
||||
Song.authors.contains(old_author))
|
||||
Song.authors.contains(oldAuthor))
|
||||
for song in songs:
|
||||
# We check if the song has already existing_author as author. If
|
||||
# that is not the case we add it.
|
||||
if existing_author not in song.authors:
|
||||
song.authors.append(existing_author)
|
||||
song.authors.remove(old_author)
|
||||
song.authors.remove(oldAuthor)
|
||||
self.manager.save_object(song)
|
||||
self.manager.delete_object(Author, old_author.id)
|
||||
self.manager.delete_object(Author, oldAuthor.id)
|
||||
|
||||
def mergeTopics(self, old_topic):
|
||||
def mergeTopics(self, oldTopic):
|
||||
"""
|
||||
Merges two topics into one topic.
|
||||
|
||||
``old_topic``
|
||||
``oldTopic``
|
||||
The object, which was edited, that will be deleted
|
||||
"""
|
||||
# Find the duplicate.
|
||||
existing_topic = self.manager.get_object_filtered(Topic,
|
||||
and_(Topic.name == old_topic.name, Topic.id != old_topic.id))
|
||||
# Find the songs, which have the old_topic as topic.
|
||||
and_(Topic.name == oldTopic.name, Topic.id != oldTopic.id))
|
||||
# Find the songs, which have the oldTopic as topic.
|
||||
songs = self.manager.get_all_objects(Song,
|
||||
Song.topics.contains(old_topic))
|
||||
Song.topics.contains(oldTopic))
|
||||
for song in songs:
|
||||
# We check if the song has already existing_topic as topic. If that
|
||||
# is not the case we add it.
|
||||
if existing_topic not in song.topics:
|
||||
song.topics.append(existing_topic)
|
||||
song.topics.remove(old_topic)
|
||||
song.topics.remove(oldTopic)
|
||||
self.manager.save_object(song)
|
||||
self.manager.delete_object(Topic, old_topic.id)
|
||||
self.manager.delete_object(Topic, oldTopic.id)
|
||||
|
||||
def mergeBooks(self, old_book):
|
||||
def mergeBooks(self, oldBook):
|
||||
"""
|
||||
Merges two books into one book.
|
||||
|
||||
``old_book``
|
||||
``oldBook``
|
||||
The object, which was edited, that will be deleted
|
||||
"""
|
||||
# Find the duplicate.
|
||||
existing_book = self.manager.get_object_filtered(Book,
|
||||
and_(Book.name == old_book.name,
|
||||
Book.publisher == old_book.publisher,
|
||||
Book.id != old_book.id))
|
||||
# Find the songs, which have the old_book as book.
|
||||
and_(Book.name == oldBook.name,
|
||||
Book.publisher == oldBook.publisher,
|
||||
Book.id != oldBook.id))
|
||||
# Find the songs, which have the oldBook as book.
|
||||
songs = self.manager.get_all_objects(Song,
|
||||
Song.song_book_id == old_book.id)
|
||||
Song.song_book_id == oldBook.id)
|
||||
for song in songs:
|
||||
song.song_book_id = existing_book.id
|
||||
self.manager.save_object(song)
|
||||
self.manager.delete_object(Book, old_book.id)
|
||||
self.manager.delete_object(Book, oldBook.id)
|
||||
|
||||
def onAuthorDeleteButtonClicked(self):
|
||||
"""
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 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.ui import create_button_box
|
||||
|
@ -193,6 +193,7 @@ class VerseType(object):
|
||||
return default
|
||||
return verse_index
|
||||
|
||||
|
||||
def retrieve_windows_encoding(recommendation=None):
|
||||
"""
|
||||
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 filter(lambda item: item[1] == choice[0], encodings)[0][0]
|
||||
|
||||
|
||||
def clean_string(string):
|
||||
"""
|
||||
Strips punctuation from the passed string to assist searching
|
||||
"""
|
||||
return WHITESPACE.sub(u' ', APOSTROPHE.sub(u'', string)).lower()
|
||||
|
||||
|
||||
def clean_title(title):
|
||||
"""
|
||||
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()
|
||||
|
||||
|
||||
def clean_song(manager, song):
|
||||
"""
|
||||
Cleans the search title, rebuilds the search lyrics, adds a default author
|
||||
|
@ -29,6 +29,9 @@ The :mod:`importer` modules provides the general song import functionality.
|
||||
"""
|
||||
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 easyslidesimport import EasySlidesImport
|
||||
from olpimport import OpenLPSongImport
|
||||
@ -41,6 +44,7 @@ from ewimport import EasyWorshipSongImport
|
||||
from songbeamerimport import SongBeamerImport
|
||||
from songshowplusimport import SongShowPlusImport
|
||||
from foilpresenterimport import FoilPresenterImport
|
||||
from zionworximport import ZionWorxImport
|
||||
# Imports that might fail
|
||||
log = logging.getLogger(__name__)
|
||||
try:
|
||||
@ -62,13 +66,69 @@ except ImportError:
|
||||
log.exception('Error importing %s', 'OooImport')
|
||||
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):
|
||||
"""
|
||||
This is a special enumeration class that holds the various types of songs,
|
||||
plus a few helper functions to facilitate generic handling of song types
|
||||
for importing.
|
||||
This is a special static class that holds an enumeration of the various
|
||||
song formats handled by the importer, the attributes of each song format,
|
||||
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
|
||||
OpenLyrics = 0
|
||||
OpenLP2 = 1
|
||||
@ -85,50 +145,164 @@ class SongFormat(object):
|
||||
SongShowPlus = 12
|
||||
SongsOfFellowship = 13
|
||||
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
|
||||
def get_class(format):
|
||||
"""
|
||||
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():
|
||||
def get_format_list():
|
||||
"""
|
||||
Return a list of the supported song formats.
|
||||
"""
|
||||
@ -138,7 +312,7 @@ class SongFormat(object):
|
||||
SongFormat.OpenLP1,
|
||||
SongFormat.Generic,
|
||||
SongFormat.CCLI,
|
||||
SongFormat.DreamBeam,
|
||||
SongFormat.DreamBeam,
|
||||
SongFormat.EasySlides,
|
||||
SongFormat.EasyWorship,
|
||||
SongFormat.FoilPresenter,
|
||||
@ -147,26 +321,56 @@ class SongFormat(object):
|
||||
SongFormat.SongBeamer,
|
||||
SongFormat.SongShowPlus,
|
||||
SongFormat.SongsOfFellowship,
|
||||
SongFormat.WordsOfWorship
|
||||
SongFormat.WordsOfWorship,
|
||||
SongFormat.ZionWorx
|
||||
]
|
||||
|
||||
@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
|
||||
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_availability(SongFormat.SongsOfFellowship, HAS_SOF)
|
||||
SongFormat.set_availability(SongFormat.Generic, HAS_OOO)
|
||||
|
||||
__all__ = [u'SongFormat']
|
||||
SongFormat.set(SongFormat.OpenLP1, u'availability', HAS_OPENLP1)
|
||||
if HAS_OPENLP1:
|
||||
SongFormat.set(SongFormat.OpenLP1, u'class', OpenLP1SongImport)
|
||||
SongFormat.set(SongFormat.SongsOfFellowship, u'availability', HAS_SOF)
|
||||
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']
|
||||
|
@ -37,6 +37,7 @@ from sqlalchemy.sql import or_
|
||||
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
|
||||
translate, check_item_selected, PluginStatus, create_separated_list
|
||||
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.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
|
||||
SongImportForm, SongExportForm
|
||||
@ -131,13 +132,13 @@ class SongMediaItem(MediaManagerItem):
|
||||
self.searchTextEdit.setFocus()
|
||||
|
||||
def configUpdated(self):
|
||||
self.searchAsYouType = QtCore.QSettings().value(
|
||||
self.searchAsYouType = Settings().value(
|
||||
self.settingsSection + u'/search as type',
|
||||
QtCore.QVariant(u'False')).toBool()
|
||||
self.updateServiceOnEdit = QtCore.QSettings().value(
|
||||
self.updateServiceOnEdit = Settings().value(
|
||||
self.settingsSection + u'/update service on edit',
|
||||
QtCore.QVariant(u'False')).toBool()
|
||||
self.addSongFromService = QtCore.QSettings().value(
|
||||
self.addSongFromService = Settings().value(
|
||||
self.settingsSection + u'/add song from service',
|
||||
QtCore.QVariant(u'True')).toBool()
|
||||
|
||||
@ -168,14 +169,14 @@ class SongMediaItem(MediaManagerItem):
|
||||
(SongSearch.Themes, u':/slides/slide_theme.png',
|
||||
UiStrings().Themes, UiStrings().SearchThemes)
|
||||
])
|
||||
self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value(
|
||||
self.searchTextEdit.setCurrentSearchType(Settings().value(
|
||||
u'%s/last search type' % self.settingsSection,
|
||||
QtCore.QVariant(SongSearch.Entire)).toInt()[0])
|
||||
self.configUpdated()
|
||||
|
||||
def onSearchTextButtonClicked(self):
|
||||
# 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,
|
||||
QtCore.QVariant(self.searchTextEdit.currentSearchType()))
|
||||
# Reload the list considering the new search type.
|
||||
@ -464,14 +465,14 @@ class SongMediaItem(MediaManagerItem):
|
||||
service_item.theme = song.theme_name
|
||||
service_item.edit_id = item_id
|
||||
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)
|
||||
verse_tags_translated = False
|
||||
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
|
||||
if not song.verse_order.strip():
|
||||
for verse in verseList:
|
||||
for verse in verse_list:
|
||||
# We cannot use from_loose_input() here, because database
|
||||
# is supposed to contain English lowercase singlechar tags.
|
||||
verse_tag = verse[0][u'type']
|
||||
@ -485,14 +486,13 @@ class SongMediaItem(MediaManagerItem):
|
||||
verse_index = VerseType.from_tag(verse_tag)
|
||||
verse_tag = VerseType.TranslatedTags[verse_index].upper()
|
||||
verse_def = u'%s%s' % (verse_tag, verse[0][u'label'])
|
||||
service_item.add_from_text(
|
||||
verse[1][:30], unicode(verse[1]), verse_def)
|
||||
service_item.add_from_text(unicode(verse[1]), verse_def)
|
||||
else:
|
||||
# Loop through the verse list and expand the song accordingly.
|
||||
for order in song.verse_order.lower().split():
|
||||
if not order:
|
||||
break
|
||||
for verse in verseList:
|
||||
for verse in verse_list:
|
||||
if verse[0][u'type'][0].lower() == order[0] and \
|
||||
(verse[0][u'label'].lower() == order[1:] or \
|
||||
not order[1:]):
|
||||
@ -505,22 +505,21 @@ class SongMediaItem(MediaManagerItem):
|
||||
verse_tag = VerseType.TranslatedTags[verse_index]
|
||||
verse_def = u'%s%s' % (verse_tag,
|
||||
verse[0][u'label'])
|
||||
service_item.add_from_text(
|
||||
verse[1][:30], verse[1], verse_def)
|
||||
service_item.add_from_text(verse[1], verse_def)
|
||||
else:
|
||||
verses = song.lyrics.split(u'\n\n')
|
||||
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
|
||||
author_list = [unicode(author.display_name) for author in song.authors]
|
||||
service_item.raw_footer.append(song.title)
|
||||
service_item.raw_footer.append(create_separated_list(author_list))
|
||||
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():
|
||||
service_item.raw_footer.append(unicode(
|
||||
translate('SongsPlugin.MediaItem', 'CCLI License: ') +
|
||||
QtCore.QSettings().value(u'general/ccli number',
|
||||
Settings().value(u'general/ccli number',
|
||||
QtCore.QVariant(u'')).toString()))
|
||||
service_item.audit = [
|
||||
song.title, author_list, song.copyright, unicode(song.ccli_number)
|
||||
|
@ -33,7 +33,6 @@ import fnmatch
|
||||
import os
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.ui.wizard import WizardStrings
|
||||
from openlp.plugins.songs.lib.songimport import SongImport
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -71,26 +70,25 @@ class PowerSongImport(SongImport):
|
||||
|
||||
* .song
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def isValidSource(**kwargs):
|
||||
def isValidSource(import_source):
|
||||
"""
|
||||
Checks if source is a PowerSong 1.0 folder:
|
||||
* is a directory
|
||||
* contains at least one *.song file
|
||||
"""
|
||||
if u'folder' in kwargs:
|
||||
dir = kwargs[u'folder']
|
||||
if os.path.isdir(dir):
|
||||
for file in os.listdir(dir):
|
||||
if fnmatch.fnmatch(file, u'*.song'):
|
||||
return True
|
||||
if os.path.isdir(import_source):
|
||||
for file in os.listdir(import_source):
|
||||
if fnmatch.fnmatch(file, u'*.song'):
|
||||
return True
|
||||
return False
|
||||
|
||||
def doImport(self):
|
||||
"""
|
||||
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 os.path.isdir(self.importSource):
|
||||
dir = self.importSource
|
||||
@ -104,7 +102,7 @@ class PowerSongImport(SongImport):
|
||||
self.logError(unicode(translate('SongsPlugin.PowerSongImport',
|
||||
'No songs to import.')),
|
||||
unicode(translate('SongsPlugin.PowerSongImport',
|
||||
'No %s files found.' % WizardStrings.PS)))
|
||||
'No %s files found.' % PS_string)))
|
||||
return
|
||||
self.importWizard.progressBar.setMaximum(len(self.importSource))
|
||||
for file in self.importSource:
|
||||
@ -124,7 +122,7 @@ class PowerSongImport(SongImport):
|
||||
self.logError(os.path.basename(file), unicode(
|
||||
translate('SongsPlugin.PowerSongImport',
|
||||
'Invalid %s file. Unexpected byte value.'
|
||||
% WizardStrings.PS)))
|
||||
% PS_string)))
|
||||
break
|
||||
else:
|
||||
if label == u'TITLE':
|
||||
@ -142,15 +140,14 @@ class PowerSongImport(SongImport):
|
||||
if not self.title:
|
||||
self.logError(os.path.basename(file), unicode(
|
||||
translate('SongsPlugin.PowerSongImport',
|
||||
'Invalid %s file. Missing "TITLE" header.'
|
||||
% WizardStrings.PS)))
|
||||
'Invalid %s file. Missing "TITLE" header.' % PS_string)))
|
||||
continue
|
||||
# Check that file had COPYRIGHTLINE label
|
||||
if not found_copyright:
|
||||
self.logError(self.title, unicode(
|
||||
translate('SongsPlugin.PowerSongImport',
|
||||
'Invalid %s file. Missing "COPYRIGHTLINE" '
|
||||
'header.' % WizardStrings.PS)))
|
||||
'header.' % PS_string)))
|
||||
continue
|
||||
# Check that file had at least one verse
|
||||
if not self.verses:
|
||||
|
@ -51,11 +51,11 @@ class SongImport(QtCore.QObject):
|
||||
as necessary
|
||||
"""
|
||||
@staticmethod
|
||||
def isValidSource(**kwargs):
|
||||
def isValidSource(import_source):
|
||||
"""
|
||||
Override this method to validate the source prior to import.
|
||||
"""
|
||||
pass
|
||||
return True
|
||||
|
||||
def __init__(self, manager, **kwargs):
|
||||
"""
|
||||
|
@ -28,6 +28,7 @@
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, translate
|
||||
from openlp.core.lib.settings import Settings
|
||||
|
||||
class SongsTab(SettingsTab):
|
||||
"""
|
||||
@ -110,7 +111,7 @@ class SongsTab(SettingsTab):
|
||||
self.update_load = True
|
||||
|
||||
def load(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.song_search = settings.value(
|
||||
u'search as type', QtCore.QVariant(False)).toBool()
|
||||
@ -127,7 +128,7 @@ class SongsTab(SettingsTab):
|
||||
settings.endGroup()
|
||||
|
||||
def save(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'search as type', QtCore.QVariant(self.song_search))
|
||||
settings.setValue(u'display songbar', QtCore.QVariant(self.tool_bar))
|
||||
|
142
openlp/plugins/songs/lib/zionworximport.py
Normal file
142
openlp/plugins/songs/lib/zionworximport.py
Normal 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)
|
@ -194,7 +194,8 @@ class SongsPlugin(Plugin):
|
||||
self.manager.save_object(song)
|
||||
|
||||
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.register(self.mediaItem.importWizard)
|
||||
return importer
|
||||
|
@ -33,6 +33,7 @@ from sqlalchemy.sql import and_
|
||||
|
||||
from openlp.core.lib import SettingsManager, translate, Receiver, \
|
||||
check_directory_exists
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.plugins.songusage.lib.db import SongUsageItem
|
||||
from songusagedetaildialog import Ui_SongUsageDetailDialog
|
||||
|
||||
@ -59,10 +60,10 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog):
|
||||
year = QtCore.QDate().currentDate().year()
|
||||
if QtCore.QDate().currentDate().month() < 9:
|
||||
year -= 1
|
||||
toDate = QtCore.QSettings().value(
|
||||
toDate = Settings().value(
|
||||
u'songusage/to date',
|
||||
QtCore.QVariant(QtCore.QDate(year, 8, 31))).toDate()
|
||||
fromDate = QtCore.QSettings().value(
|
||||
fromDate = Settings().value(
|
||||
u'songusage/from date',
|
||||
QtCore.QVariant(QtCore.QDate(year - 1, 9, 1))).toDate()
|
||||
self.fromDate.setSelectedDate(fromDate)
|
||||
@ -103,9 +104,9 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog):
|
||||
'usage_detail_%s_%s.txt')) % (
|
||||
self.fromDate.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.QSettings().setValue(u'songusage/to date',
|
||||
Settings().setValue(u'songusage/to date',
|
||||
QtCore.QVariant(self.toDate.selectedDate()))
|
||||
usage = self.plugin.manager.get_all_objects(
|
||||
SongUsageItem, and_(
|
||||
|
@ -34,6 +34,7 @@ from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, \
|
||||
translate
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.core.lib.ui import create_action
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.utils.actions import ActionList
|
||||
from openlp.plugins.songusage.forms import SongUsageDetailForm, \
|
||||
SongUsageDeleteForm
|
||||
@ -125,7 +126,7 @@ class SongUsagePlugin(Plugin):
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'print_service_started'),
|
||||
self.printSongUsage)
|
||||
self.songUsageActive = QtCore.QSettings().value(
|
||||
self.songUsageActive = Settings().value(
|
||||
self.settingsSection + u'/active',
|
||||
QtCore.QVariant(False)).toBool()
|
||||
# Set the button and checkbox state
|
||||
@ -168,7 +169,7 @@ class SongUsagePlugin(Plugin):
|
||||
the UI when necessary,
|
||||
"""
|
||||
self.songUsageActive = not self.songUsageActive
|
||||
QtCore.QSettings().setValue(self.settingsSection + u'/active',
|
||||
Settings().setValue(self.settingsSection + u'/active',
|
||||
QtCore.QVariant(self.songUsageActive))
|
||||
self.setButtonState()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user